· 11 years ago · Jun 24, 2015, 09:22 PM
1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
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 <anthmct@yahoo.com>
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 <anthmct@yahoo.com>
27 * Michael Jerris <mike@jerris.com>
28 * Paul D. Tinsley <pdt at jackhammer.org>
29 *
30 *
31 * switch_core.c -- Main Core Library
32 *
33 */
34
35#include <switch.h>
36#include <stdio.h>
37#include <switch_version.h>
38
39#ifdef HAVE_MLOCKALL
40#include <sys/mman.h>
41#endif
42
43//#define DEBUG_ALLOC
44#define DO_EVENTS
45
46#ifdef CRASH_PROT
47#define __CP "ENABLED"
48#else
49#define __CP "DISABLED"
50#endif
51
52#define SWITCH_EVENT_QUEUE_LEN 256
53#define SWITCH_MESSAGE_QUEUE_LEN 256
54#define SWITCH_SQL_QUEUE_LEN 2000
55
56#define SWITCH_BUFFER_BLOCK_FRAMES 25
57#define SWITCH_BUFFER_START_FRAMES 50
58
59struct switch_media_bug {
60 switch_buffer_t *raw_write_buffer;
61 switch_buffer_t *raw_read_buffer;
62 switch_media_bug_callback_t callback;
63 switch_mutex_t *read_mutex;
64 switch_mutex_t *write_mutex;
65 switch_core_session_t *session;
66 void *user_data;
67 uint32_t flags;
68 struct switch_media_bug *next;
69};
70
71struct switch_core_session {
72 uint32_t id;
73 char name[80];
74 int thread_running;
75 switch_memory_pool_t *pool;
76 switch_channel_t *channel;
77 switch_thread_t *thread;
78 const switch_endpoint_interface_t *endpoint_interface;
79 switch_io_event_hooks_t event_hooks;
80 switch_codec_t *read_codec;
81 switch_codec_t *write_codec;
82
83 switch_buffer_t *raw_write_buffer;
84 switch_frame_t raw_write_frame;
85 switch_frame_t enc_write_frame;
86 uint8_t raw_write_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
87 uint8_t enc_write_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
88
89 switch_buffer_t *raw_read_buffer;
90 switch_frame_t raw_read_frame;
91 switch_frame_t enc_read_frame;
92 uint8_t raw_read_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
93 uint8_t enc_read_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
94
95
96 switch_audio_resampler_t *read_resampler;
97 switch_audio_resampler_t *write_resampler;
98
99 switch_mutex_t *mutex;
100 switch_thread_cond_t *cond;
101
102 switch_thread_rwlock_t *rwlock;
103
104 void *streams[SWITCH_MAX_STREAMS];
105 int stream_count;
106
107 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
108 void *private_info;
109 switch_queue_t *event_queue;
110 switch_queue_t *message_queue;
111 switch_queue_t *private_event_queue;
112 switch_thread_rwlock_t *bug_rwlock;
113 switch_media_bug_t *bugs;
114};
115
116SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs;
117
118struct switch_core_runtime {
119 switch_time_t initiated;
120 uint32_t session_id;
121 apr_pool_t *memory_pool;
122 switch_hash_t *session_table;
123 switch_hash_t *global_vars;
124 switch_mutex_t *session_table_mutex;
125#ifdef CRASH_PROT
126 switch_hash_t *stack_table;
127#endif
128 switch_core_db_t *db;
129 switch_core_db_t *event_db;
130 const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];
131 int state_handler_index;
132 FILE *console;
133 uint32_t session_count;
134 uint32_t session_limit;
135 switch_queue_t *sql_queue;
136 uint32_t no_new_sessions;
137 uint32_t shutting_down;
138 uint8_t running;
139};
140
141/* Prototypes */
142static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj);
143static void switch_core_standard_on_init(switch_core_session_t *session);
144static void switch_core_standard_on_hangup(switch_core_session_t *session);
145static void switch_core_standard_on_ring(switch_core_session_t *session);
146static void switch_core_standard_on_execute(switch_core_session_t *session);
147static void switch_core_standard_on_loopback(switch_core_session_t *session);
148static void switch_core_standard_on_transmit(switch_core_session_t *session);
149static void switch_core_standard_on_hold(switch_core_session_t *session);
150
151
152/* The main runtime obj we keep this hidden for ourselves */
153static struct switch_core_runtime runtime;
154
155
156static void db_pick_path(char *dbname, char *buf, switch_size_t size)
157{
158
159 memset(buf, 0, size);
160 if (strchr(dbname, '/')) {
161 strncpy(buf, dbname, size);
162 } else {
163 snprintf(buf, size, "%s%s%s.db", SWITCH_GLOBAL_dirs.db_dir, SWITCH_PATH_SEPARATOR, dbname);
164 }
165}
166
167static void switch_core_media_bug_destroy(switch_media_bug_t *bug)
168{
169 switch_buffer_destroy(&bug->raw_read_buffer);
170 switch_buffer_destroy(&bug->raw_write_buffer);
171}
172
173SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug)
174{
175 return bug->user_data;
176}
177
178SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame)
179{
180 uint32_t bytes = 0;
181 uint8_t data[SWITCH_RECCOMMENDED_BUFFER_SIZE] = {0};
182 uint32_t datalen = 0;
183 int16_t *dp, *fp;
184 uint32_t x;
185 size_t rlen = 0;
186 size_t wlen = 0;
187 uint32_t blen;
188 size_t rdlen = 0;
189 uint32_t maxlen;
190
191
192 if (bug->raw_read_buffer) {
193 rlen = switch_buffer_inuse(bug->raw_read_buffer);
194 }
195
196 if (bug->raw_write_buffer) {
197 wlen = switch_buffer_inuse(bug->raw_write_buffer);
198 }
199
200 if ((bug->raw_read_buffer && bug->raw_write_buffer) && (!rlen && !wlen)) {
201 return SWITCH_STATUS_FALSE;
202 }
203
204
205 maxlen = sizeof(data) > frame->buflen ? frame->buflen : sizeof(data);
206 if ((rdlen = rlen > wlen ? wlen : rlen) > maxlen) {
207 rdlen = maxlen;
208 }
209
210 if (!rdlen) {
211 rdlen = maxlen;
212 }
213
214 frame->datalen = 0;
215
216 if (rlen) {
217 switch_mutex_lock(bug->read_mutex);
218
219 frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer,
220 frame->data,
221 rdlen);
222 switch_mutex_unlock(bug->read_mutex);
223 }
224
225 if (wlen) {
226 switch_mutex_lock(bug->write_mutex);
227 datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer,
228 data,
229 rdlen);
230 switch_mutex_unlock(bug->write_mutex);
231 }
232
233
234 bytes = (datalen > frame->datalen) ? datalen : frame->datalen;
235
236 if (bytes) {
237 dp = (int16_t *) data;
238 fp = (int16_t *) frame->data;
239
240 rlen = frame->datalen / 2;
241 wlen = datalen / 2;
242 blen = bytes / 2;
243
244 for(x = 0; x < blen; x++) {
245 int32_t z = 0;
246
247 if (x < rlen) {
248 z += (int32_t) *(fp+x);
249 }
250 if (x < wlen) {
251 z += (int32_t)*(dp+x);
252 }
253 switch_normalize_to_16bit(z);
254 *(fp+x) = (int16_t) z;
255 }
256
257 frame->datalen = bytes;
258
259
260 return SWITCH_STATUS_SUCCESS;
261 }
262
263 return SWITCH_STATUS_FALSE;
264}
265
266#define MAX_BUG_BUFFER 1024 * 512
267SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
268 switch_media_bug_callback_t callback,
269 void *user_data,
270 switch_media_bug_flag_t flags,
271 switch_media_bug_t **new_bug)
272
273{
274 switch_media_bug_t *bug;
275 switch_size_t bytes;
276
277 if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) {
278 return SWITCH_STATUS_MEMERR;
279 }
280
281 bug->callback = callback;
282 bug->user_data = user_data;
283 bug->session = session;
284 bug->flags = flags;
285 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel));
286 bytes = session->read_codec->implementation->bytes_per_frame;
287
288 if (!bug->flags) {
289 bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM);
290 }
291
292 if (switch_test_flag(bug, SMBF_READ_STREAM)) {
293 switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
294 switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
295 }
296
297 bytes = session->write_codec->implementation->bytes_per_frame;
298
299 if (switch_test_flag(bug, SMBF_WRITE_STREAM)) {
300 switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
301 switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
302 }
303
304 switch_thread_rwlock_wrlock(session->bug_rwlock);
305 bug->next = session->bugs;
306 session->bugs = bug;
307 switch_thread_rwlock_unlock(session->bug_rwlock);
308 *new_bug = bug;
309
310 if (bug->callback) {
311 bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT);
312 }
313
314 return SWITCH_STATUS_SUCCESS;
315}
316
317
318SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(switch_core_session_t *session)
319{
320 switch_media_bug_t *bp;
321
322 if (session->bugs) {
323 switch_thread_rwlock_wrlock(session->bug_rwlock);
324 for (bp = session->bugs; bp; bp = bp->next) {
325 if (bp->callback) {
326 bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
327 }
328 switch_core_media_bug_destroy(bp);
329 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(session->channel));
330 }
331 switch_thread_rwlock_unlock(session->bug_rwlock);
332 session->bugs = NULL;
333 return SWITCH_STATUS_SUCCESS;
334 }
335
336 return SWITCH_STATUS_FALSE;
337}
338
339SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(switch_core_session_t *session, switch_media_bug_t **bug)
340{
341 switch_media_bug_t *bp = NULL, *last = NULL;
342
343 if (session->bugs) {
344 switch_thread_rwlock_wrlock(session->bug_rwlock);
345 for (bp = session->bugs; bp; bp = bp->next) {
346 if (bp == *bug) {
347 if (last) {
348 last->next = bp->next;
349 } else {
350 session->bugs = bp->next;
351 }
352 break;
353 }
354 last = bp;
355 }
356 switch_thread_rwlock_unlock(session->bug_rwlock);
357
358 if (bp) {
359 if (bp->callback) {
360 bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
361 }
362 switch_core_media_bug_destroy(bp);
363 *bug = NULL;
364 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(session->channel));
365 return SWITCH_STATUS_SUCCESS;
366 }
367 }
368
369 return SWITCH_STATUS_FALSE;
370}
371
372struct switch_core_port_allocator {
373 switch_port_t start;
374 switch_port_t end;
375 switch_port_t next;
376 uint8_t inc;
377 switch_mutex_t *mutex;
378 switch_memory_pool_t *pool;
379};
380
381SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_new(switch_port_t start,
382 switch_port_t end,
383 uint8_t inc,
384 switch_core_port_allocator_t **new_allocator)
385{
386 switch_status_t status;
387 switch_memory_pool_t *pool;
388 switch_core_port_allocator_t *alloc;
389
390 if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
391 return status;
392 }
393
394 if (!(alloc = switch_core_alloc(pool, sizeof(*alloc)))) {
395 switch_core_destroy_memory_pool(&pool);
396 return SWITCH_STATUS_MEMERR;
397 }
398
399 alloc->start = start;
400 alloc->next = start;
401 alloc->end = end;
402 if (!(alloc->inc = inc)) {
403 alloc->inc = 2;
404 }
405 switch_mutex_init(&alloc->mutex, SWITCH_MUTEX_NESTED, pool);
406 alloc->pool = pool;
407 *new_allocator = alloc;
408
409 return SWITCH_STATUS_SUCCESS;
410}
411
412SWITCH_DECLARE(switch_port_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc)
413{
414 switch_port_t port;
415
416 switch_mutex_lock(alloc->mutex);
417 port = alloc->next;
418 alloc->next = alloc->next + alloc->inc;
419 if (alloc->next > alloc->end) {
420 alloc->next = alloc->start;
421 }
422 switch_mutex_unlock(alloc->mutex);
423 return port;
424}
425
426SWITCH_DECLARE(void) switch_core_port_allocator_destroy(switch_core_port_allocator_t **alloc)
427{
428 switch_memory_pool_t *pool = (*alloc)->pool;
429 switch_core_destroy_memory_pool(&pool);
430 *alloc = NULL;
431}
432
433SWITCH_DECLARE(switch_core_db_t *) switch_core_db_open_file(char *filename)
434{
435 switch_core_db_t *db;
436 char path[1024];
437
438 db_pick_path(filename, path, sizeof(path));
439 if (switch_core_db_open(path, &db)) {
440 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", switch_core_db_errmsg(db));
441 switch_core_db_close(db);
442 db = NULL;
443 }
444 return db;
445}
446
447
448SWITCH_DECLARE(void) switch_core_db_test_reactive(switch_core_db_t *db, char *test_sql, char *reactive_sql)
449{
450 char *errmsg;
451
452 if(db) {
453 if(test_sql) {
454 switch_core_db_exec(
455 db,
456 test_sql,
457 NULL,
458 NULL,
459 &errmsg
460 );
461
462 if (errmsg) {
463 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\nAuto Generating Table!\n", errmsg, test_sql);
464 switch_core_db_free(errmsg);
465 errmsg = NULL;
466 switch_core_db_exec(
467 db,
468 reactive_sql,
469 NULL,
470 NULL,
471 &errmsg
472 );
473 if (errmsg) {
474 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
475 switch_core_db_free(errmsg);
476 errmsg = NULL;
477 }
478 }
479 }
480 }
481
482}
483
484
485
486SWITCH_DECLARE(switch_status_t) switch_core_set_console(char *console)
487{
488 if ((runtime.console = fopen(console, "a")) == 0) {
489 fprintf(stderr, "Cannot open output file %s.\n", console);
490 return SWITCH_STATUS_FALSE;
491 }
492
493 return SWITCH_STATUS_SUCCESS;
494}
495
496SWITCH_DECLARE(FILE *) switch_core_get_console(void)
497{
498 return runtime.console;
499}
500
501SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel)
502{
503 FILE *handle = stdout;
504
505 switch (channel) {
506 case SWITCH_CHANNEL_ID_LOG:
507 case SWITCH_CHANNEL_ID_LOG_CLEAN:
508 handle = runtime.console;
509 break;
510 default:
511 handle = runtime.console;
512 break;
513 }
514
515 return handle;
516}
517
518SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler)
519{
520 int index = runtime.state_handler_index++;
521
522 if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
523 return -1;
524 }
525
526 runtime.state_handlers[index] = state_handler;
527 return index;
528}
529
530SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index)
531{
532
533 if (index > SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {
534 return NULL;
535 }
536
537 return runtime.state_handlers[index];
538}
539
540SWITCH_DECLARE(switch_status_t) switch_core_session_read_lock(switch_core_session_t *session)
541{
542 switch_status_t status = SWITCH_STATUS_SUCCESS;
543
544
545 status = (switch_status_t) switch_thread_rwlock_tryrdlock(session->rwlock);
546
547 return status;
548}
549
550SWITCH_DECLARE(void) switch_core_session_write_lock(switch_core_session_t *session)
551{
552 switch_thread_rwlock_wrlock(session->rwlock);
553}
554
555SWITCH_DECLARE(void) switch_core_session_rwunlock(switch_core_session_t *session)
556{
557
558 switch_thread_rwlock_unlock(session->rwlock);
559
560}
561
562SWITCH_DECLARE(char *) switch_core_get_variable(char *varname)
563{
564 return (char *) switch_core_hash_find(runtime.global_vars, varname);
565}
566
567SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(char *uuid_str)
568{
569 switch_core_session_t *session;
570
571 if (uuid_str) {
572 switch_mutex_lock(runtime.session_table_mutex);
573 if ((session = switch_core_hash_find(runtime.session_table, uuid_str))) {
574 /* Acquire a read lock on the session */
575 if (switch_thread_rwlock_tryrdlock(session->rwlock) != SWITCH_STATUS_SUCCESS) {
576 /* not available, forget it */
577 session = NULL;
578 }
579 }
580 switch_mutex_unlock(runtime.session_table_mutex);
581
582 /* if its not NULL, now it's up to you to rwunlock this */
583 return session;
584 } else {
585 return NULL;
586 }
587}
588
589SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause)
590{
591 switch_hash_index_t *hi;
592 void *val;
593 switch_core_session_t *session;
594 switch_channel_t *channel;
595
596 switch_mutex_lock(runtime.session_table_mutex);
597 for (hi = switch_hash_first(runtime.memory_pool, runtime.session_table); hi; hi = switch_hash_next(hi)) {
598 switch_hash_this(hi, NULL, NULL, &val);
599 if (val) {
600 session = (switch_core_session_t *) val;
601 channel = switch_core_session_get_channel(session);
602 switch_channel_hangup(channel, cause);
603 }
604 }
605 switch_mutex_unlock(runtime.session_table_mutex);
606
607 while(runtime.session_count > 0) {
608 switch_yield(10000);
609 }
610}
611
612SWITCH_DECLARE(switch_status_t) switch_core_session_message_send(char *uuid_str, switch_core_session_message_t *message)
613{
614 switch_core_session_t *session = NULL;
615 switch_status_t status = SWITCH_STATUS_FALSE;
616
617 switch_mutex_lock(runtime.session_table_mutex);
618 if ((session = switch_core_hash_find(runtime.session_table, uuid_str)) != 0) {
619 /* Acquire a read lock on the session or forget it the channel is dead */
620 if (switch_thread_rwlock_tryrdlock(session->rwlock) == SWITCH_STATUS_SUCCESS) {
621 if (switch_channel_get_state(session->channel) < CS_HANGUP) {
622 status = switch_core_session_receive_message(session, message);
623 }
624 switch_thread_rwlock_unlock(session->rwlock);
625 }
626 }
627 switch_mutex_unlock(runtime.session_table_mutex);
628
629 return status;
630}
631
632SWITCH_DECLARE(switch_status_t) switch_core_session_event_send(char *uuid_str, switch_event_t **event)
633{
634 switch_core_session_t *session = NULL;
635 switch_status_t status = SWITCH_STATUS_FALSE;
636
637 switch_mutex_lock(runtime.session_table_mutex);
638 if ((session = switch_core_hash_find(runtime.session_table, uuid_str)) != 0) {
639 /* Acquire a read lock on the session or forget it the channel is dead */
640 if (switch_thread_rwlock_tryrdlock(session->rwlock) == SWITCH_STATUS_SUCCESS) {
641 if (switch_channel_get_state(session->channel) < CS_HANGUP) {
642 status = switch_core_session_queue_event(session, event);
643 }
644 switch_thread_rwlock_unlock(session->rwlock);
645 }
646 }
647 switch_mutex_unlock(runtime.session_table_mutex);
648
649 return status;
650}
651
652SWITCH_DECLARE(char *) switch_core_session_get_uuid(switch_core_session_t *session)
653{
654 return session->uuid_str;
655}
656
657SWITCH_DECLARE(switch_status_t) switch_core_session_set_read_codec(switch_core_session_t *session, switch_codec_t *codec)
658{
659 switch_event_t *event;
660
661 assert(session != NULL);
662
663 if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) {
664 switch_channel_event_set_data(session->channel, event);
665 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", codec->implementation->iananame);
666 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", codec->implementation->samples_per_second);
667 switch_event_fire(&event);
668 }
669
670 session->read_codec = codec;
671 return SWITCH_STATUS_SUCCESS;
672}
673
674SWITCH_DECLARE(switch_codec_t *) switch_core_session_get_read_codec(switch_core_session_t *session)
675{
676 return session->read_codec;
677}
678
679SWITCH_DECLARE(switch_status_t) switch_core_session_set_write_codec(switch_core_session_t *session, switch_codec_t *codec)
680{
681 switch_event_t *event;
682 assert(session != NULL);
683
684 if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) {
685 switch_channel_event_set_data(session->channel, event);
686 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-write-codec-name", codec->implementation->iananame);
687 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-write-codec-rate", "%d", codec->implementation->samples_per_second);
688 switch_event_fire(&event);
689 }
690
691 session->write_codec = codec;
692 return SWITCH_STATUS_SUCCESS;
693}
694
695SWITCH_DECLARE(switch_codec_t *) switch_core_session_get_write_codec(switch_core_session_t *session)
696{
697 return session->write_codec;
698}
699
700SWITCH_DECLARE(switch_status_t) switch_core_codec_init(switch_codec_t *codec, char *codec_name, char *fmtp, uint32_t rate, int ms,
701 int channels, uint32_t flags,
702 const switch_codec_settings_t *codec_settings,
703 switch_memory_pool_t *pool)
704{
705 const switch_codec_interface_t *codec_interface;
706 const switch_codec_implementation_t *iptr, *implementation = NULL;
707
708 assert(codec != NULL);
709 assert(codec_name != NULL);
710
711 memset(codec, 0, sizeof(*codec));
712
713 if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name)) == 0) {
714 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid codec %s!\n", codec_name);
715 return SWITCH_STATUS_GENERR;
716 }
717
718 for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
719 if ((!rate || rate == iptr->samples_per_second) &&
720 (!ms || ms == (iptr->microseconds_per_frame / 1000)) &&
721 (!channels || channels == iptr->number_of_channels)) {
722 implementation = iptr;
723 break;
724 }
725 }
726
727 if (implementation) {
728 switch_status_t status;
729 codec->codec_interface = codec_interface;
730 codec->implementation = implementation;
731 codec->flags = flags;
732
733 if (pool) {
734 codec->memory_pool = pool;
735 } else {
736 if ((status = switch_core_new_memory_pool(&codec->memory_pool)) != SWITCH_STATUS_SUCCESS) {
737 return status;
738 }
739 switch_set_flag(codec, SWITCH_CODEC_FLAG_FREE_POOL);
740 }
741
742 if (fmtp) {
743 codec->fmtp_in = switch_core_strdup(codec->memory_pool, fmtp);
744 }
745
746 implementation->init(codec, flags, codec_settings);
747
748 return SWITCH_STATUS_SUCCESS;
749 } else {
750 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms\n",
751 codec_name,
752 rate,
753 ms);
754 }
755
756 return SWITCH_STATUS_NOTIMPL;
757
758}
759
760SWITCH_DECLARE(switch_status_t) switch_core_codec_encode(switch_codec_t *codec,
761 switch_codec_t *other_codec,
762 void *decoded_data,
763 uint32_t decoded_data_len,
764 uint32_t decoded_rate,
765 void *encoded_data,
766 uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
767{
768 assert(codec != NULL);
769 assert(encoded_data != NULL);
770 assert(decoded_data != NULL);
771
772 if (!codec->implementation) {
773 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initilized!\n");
774 return SWITCH_STATUS_GENERR;
775 }
776
777 if (!switch_test_flag(codec, SWITCH_CODEC_FLAG_ENCODE)) {
778 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec's encoder is not initilized!\n");
779 return SWITCH_STATUS_GENERR;
780 }
781
782
783 return codec->implementation->encode(codec,
784 other_codec,
785 decoded_data,
786 decoded_data_len,
787 decoded_rate, encoded_data, encoded_data_len, encoded_rate, flag);
788
789}
790
791SWITCH_DECLARE(switch_status_t) switch_core_codec_decode(switch_codec_t *codec,
792 switch_codec_t *other_codec,
793 void *encoded_data,
794 uint32_t encoded_data_len,
795 uint32_t encoded_rate,
796 void *decoded_data,
797 uint32_t *decoded_data_len,
798 uint32_t *decoded_rate,
799 unsigned int *flag)
800{
801
802 assert(codec != NULL);
803 assert(encoded_data != NULL);
804 assert(decoded_data != NULL);
805
806
807
808 if (!codec->implementation) {
809 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initilized!\n");
810 return SWITCH_STATUS_GENERR;
811 }
812
813 if (!switch_test_flag(codec, SWITCH_CODEC_FLAG_DECODE)) {
814 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec's decoder is not initilized!\n");
815 return SWITCH_STATUS_GENERR;
816 }
817
818
819 return codec->implementation->decode(codec,
820 other_codec,
821 encoded_data,
822 encoded_data_len,
823 encoded_rate, decoded_data, decoded_data_len, decoded_rate, flag);
824
825}
826
827SWITCH_DECLARE(switch_status_t) switch_core_codec_destroy(switch_codec_t *codec)
828{
829 assert(codec != NULL);
830
831 if (!codec->implementation) {
832 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initilized!\n");
833 return SWITCH_STATUS_GENERR;
834 }
835
836 codec->implementation->destroy(codec);
837
838 if (switch_test_flag(codec, SWITCH_CODEC_FLAG_FREE_POOL)) {
839 switch_core_destroy_memory_pool(&codec->memory_pool);
840 }
841
842 return SWITCH_STATUS_SUCCESS;
843}
844
845SWITCH_DECLARE(switch_status_t) switch_core_file_open(switch_file_handle_t *fh, char *file_path, unsigned int flags,
846 switch_memory_pool_t *pool)
847{
848 char *ext;
849 switch_status_t status;
850
851 if ((ext = strrchr(file_path, '.')) == 0) {
852 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n");
853 return SWITCH_STATUS_FALSE;
854 }
855 ext++;
856
857 if ((fh->file_interface = switch_loadable_module_get_file_interface(ext)) == 0) {
858 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid file format [%s]!\n", ext);
859 return SWITCH_STATUS_GENERR;
860 }
861
862 fh->flags = flags;
863 if (pool) {
864 fh->memory_pool = pool;
865 } else {
866 if ((status = switch_core_new_memory_pool(&fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
867 return status;
868 }
869 switch_set_flag(fh, SWITCH_FILE_FLAG_FREE_POOL);
870 }
871
872 return fh->file_interface->file_open(fh, file_path);
873}
874
875SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh, void *data, switch_size_t *len)
876{
877 assert(fh != NULL);
878
879 return fh->file_interface->file_read(fh, data, len);
880}
881
882SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, void *data, switch_size_t *len)
883{
884 assert(fh != NULL);
885
886 return fh->file_interface->file_write(fh, data, len);
887}
888
889SWITCH_DECLARE(switch_status_t) switch_core_file_seek(switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples,
890 int whence)
891{
892 assert(fh != NULL);
893 return fh->file_interface->file_seek(fh, cur_pos, samples, whence);
894}
895
896SWITCH_DECLARE(switch_status_t) switch_core_file_set_string(switch_file_handle_t *fh, switch_audio_col_t col, const char *string)
897{
898 assert(fh != NULL);
899
900 return fh->file_interface->file_set_string(fh, col, string);
901}
902
903SWITCH_DECLARE(switch_status_t) switch_core_file_get_string(switch_file_handle_t *fh, switch_audio_col_t col, const char **string)
904{
905 assert(fh != NULL);
906
907 return fh->file_interface->file_get_string(fh, col, string);
908
909}
910
911
912SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
913{
914 return fh->file_interface->file_close(fh);
915}
916
917SWITCH_DECLARE(switch_status_t) switch_core_directory_open(switch_directory_handle_t *dh,
918 char *module_name,
919 char *source,
920 char *dsn,
921 char *passwd,
922 switch_memory_pool_t *pool)
923{
924 switch_status_t status;
925
926 if ((dh->directory_interface = switch_loadable_module_get_directory_interface(module_name)) == 0) {
927 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid directory module [%s]!\n", module_name);
928 return SWITCH_STATUS_GENERR;
929 }
930
931 if (pool) {
932 dh->memory_pool = pool;
933 } else {
934 if ((status = switch_core_new_memory_pool(&dh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
935 return status;
936 }
937 switch_set_flag(dh, SWITCH_DIRECTORY_FLAG_FREE_POOL);
938 }
939
940 return dh->directory_interface->directory_open(dh, source, dsn, passwd);
941}
942
943SWITCH_DECLARE(switch_status_t) switch_core_directory_query(switch_directory_handle_t *dh, char *base, char *query)
944{
945 return dh->directory_interface->directory_query(dh, base, query);
946}
947
948SWITCH_DECLARE(switch_status_t) switch_core_directory_next(switch_directory_handle_t *dh)
949{
950 return dh->directory_interface->directory_next(dh);
951}
952
953SWITCH_DECLARE(switch_status_t) switch_core_directory_next_pair(switch_directory_handle_t *dh, char **var, char **val)
954{
955 return dh->directory_interface->directory_next_pair(dh, var, val);
956}
957
958SWITCH_DECLARE(switch_status_t) switch_core_directory_close(switch_directory_handle_t *dh)
959{
960 return dh->directory_interface->directory_close(dh);
961}
962
963SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t *sh,
964 char *module_name,
965 char *voice_name,
966 unsigned int rate,
967 switch_speech_flag_t *flags,
968 switch_memory_pool_t *pool)
969{
970 switch_status_t status;
971
972 if ((sh->speech_interface = switch_loadable_module_get_speech_interface(module_name)) == 0) {
973 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid speech module [%s]!\n", module_name);
974 return SWITCH_STATUS_GENERR;
975 }
976
977 switch_copy_string(sh->engine, module_name, sizeof(sh->engine));
978 sh->flags = *flags;
979 if (pool) {
980 sh->memory_pool = pool;
981 } else {
982 if ((status = switch_core_new_memory_pool(&sh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
983 return status;
984 }
985 switch_set_flag(sh, SWITCH_SPEECH_FLAG_FREE_POOL);
986 }
987 sh->rate = rate;
988 sh->name = switch_core_strdup(pool, module_name);
989 return sh->speech_interface->speech_open(sh, voice_name, rate, flags);
990}
991
992SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah,
993 char *module_name,
994 char *codec,
995 int rate,
996 char *dest,
997 switch_asr_flag_t *flags,
998 switch_memory_pool_t *pool)
999{
1000 switch_status_t status;
1001
1002 assert(ah != NULL);
1003
1004 if ((ah->asr_interface = switch_loadable_module_get_asr_interface(module_name)) == 0) {
1005 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid asr module [%s]!\n", module_name);
1006 return SWITCH_STATUS_GENERR;
1007 }
1008
1009 ah->flags = *flags;
1010
1011 if (pool) {
1012 ah->memory_pool = pool;
1013 } else {
1014 if ((status = switch_core_new_memory_pool(&ah->memory_pool)) != SWITCH_STATUS_SUCCESS) {
1015 return status;
1016 }
1017 switch_set_flag(ah, SWITCH_ASR_FLAG_FREE_POOL);
1018 }
1019
1020 ah->rate = rate;
1021 ah->name = switch_core_strdup(ah->memory_pool, module_name);
1022
1023 return ah->asr_interface->asr_open(ah, codec, rate, dest, flags);
1024}
1025
1026SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, char *grammar, char *path)
1027{
1028 char *epath = NULL;
1029 switch_status_t status;
1030
1031 assert(ah != NULL);
1032
1033 if (*path != '/') {
1034 epath = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, path);
1035 path = epath;
1036 }
1037
1038 status = ah->asr_interface->asr_load_grammar(ah, grammar, path);
1039 switch_safe_free(epath);
1040
1041 return status;
1042}
1043
1044SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, char *grammar)
1045{
1046 switch_status_t status;
1047
1048 assert(ah != NULL);
1049 status = ah->asr_interface->asr_unload_grammar(ah, grammar);
1050
1051 return status;
1052}
1053
1054SWITCH_DECLARE(switch_status_t) switch_core_asr_pause(switch_asr_handle_t *ah)
1055{
1056 assert(ah != NULL);
1057
1058 return ah->asr_interface->asr_pause(ah);
1059}
1060
1061SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah)
1062{
1063 assert(ah != NULL);
1064
1065 return ah->asr_interface->asr_resume(ah);
1066}
1067
1068SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
1069{
1070 assert(ah != NULL);
1071
1072 return ah->asr_interface->asr_close(ah, flags);
1073}
1074
1075SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags)
1076{
1077 assert(ah != NULL);
1078
1079 return ah->asr_interface->asr_feed(ah, data, len, flags);
1080}
1081
1082SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
1083{
1084 assert(ah != NULL);
1085
1086 return ah->asr_interface->asr_check_results(ah, flags);
1087}
1088
1089SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
1090{
1091 assert(ah != NULL);
1092
1093 return ah->asr_interface->asr_get_results(ah, xmlstr, flags);
1094}
1095
1096SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags)
1097{
1098 assert(sh != NULL);
1099
1100 return sh->speech_interface->speech_feed_tts(sh, text, flags);
1101}
1102
1103SWITCH_DECLARE(void) switch_core_speech_flush_tts(switch_speech_handle_t *sh)
1104{
1105 assert(sh != NULL);
1106
1107 if (sh->speech_interface->speech_flush_tts) {
1108 sh->speech_interface->speech_flush_tts(sh);
1109 }
1110}
1111
1112SWITCH_DECLARE(void) switch_core_speech_text_param_tts(switch_speech_handle_t *sh, char *param, char *val)
1113{
1114 assert(sh != NULL);
1115
1116 if (sh->speech_interface->speech_text_param_tts) {
1117 sh->speech_interface->speech_text_param_tts(sh, param, val);
1118 }
1119}
1120
1121SWITCH_DECLARE(void) switch_core_speech_numeric_param_tts(switch_speech_handle_t *sh, char *param, int val)
1122{
1123 assert(sh != NULL);
1124
1125 if (sh->speech_interface->speech_numeric_param_tts) {
1126 sh->speech_interface->speech_numeric_param_tts(sh, param, val);
1127 }
1128}
1129
1130SWITCH_DECLARE(void) switch_core_speech_float_param_tts(switch_speech_handle_t *sh, char *param, double val)
1131{
1132 assert(sh != NULL);
1133
1134 if (sh->speech_interface->speech_float_param_tts) {
1135 sh->speech_interface->speech_float_param_tts(sh, param, val);
1136 }
1137}
1138
1139SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle_t *sh,
1140 void *data,
1141 switch_size_t *datalen,
1142 uint32_t *rate,
1143 switch_speech_flag_t *flags)
1144{
1145 assert(sh != NULL);
1146
1147 return sh->speech_interface->speech_read_tts(sh, data, datalen, rate, flags);
1148}
1149
1150
1151SWITCH_DECLARE(switch_status_t) switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags)
1152{
1153 return sh->speech_interface->speech_close(sh, flags);
1154}
1155
1156SWITCH_DECLARE(switch_status_t) switch_core_timer_init(switch_timer_t *timer, char *timer_name, int interval, int samples,
1157 switch_memory_pool_t *pool)
1158{
1159 switch_timer_interface_t *timer_interface;
1160 switch_status_t status;
1161 memset(timer, 0, sizeof(*timer));
1162 if ((timer_interface = switch_loadable_module_get_timer_interface(timer_name)) == 0) {
1163 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid timer %s!\n", timer_name);
1164 return SWITCH_STATUS_GENERR;
1165 }
1166
1167 timer->interval = interval;
1168 timer->samples = samples;
1169 timer->samplecount = 0;
1170 timer->timer_interface = timer_interface;
1171
1172 if (pool) {
1173 timer->memory_pool = pool;
1174 } else {
1175 if ((status = switch_core_new_memory_pool(&timer->memory_pool)) != SWITCH_STATUS_SUCCESS) {
1176 return status;
1177 }
1178 switch_set_flag(timer, SWITCH_TIMER_FLAG_FREE_POOL);
1179 }
1180
1181 timer->timer_interface->timer_init(timer);
1182 return SWITCH_STATUS_SUCCESS;
1183
1184}
1185
1186SWITCH_DECLARE(int) switch_core_timer_next(switch_timer_t *timer)
1187{
1188 if (!timer->timer_interface) {
1189 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timer is not initilized!\n");
1190 return SWITCH_STATUS_GENERR;
1191 }
1192
1193 if (timer->timer_interface->timer_next(timer) == SWITCH_STATUS_SUCCESS) {
1194 return timer->samplecount;
1195 } else {
1196 return -1;
1197 }
1198
1199}
1200
1201SWITCH_DECLARE(switch_status_t) switch_core_timer_step(switch_timer_t *timer)
1202{
1203 if (!timer->timer_interface) {
1204 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timer is not initilized!\n");
1205 return SWITCH_STATUS_GENERR;
1206 }
1207
1208 return timer->timer_interface->timer_step(timer);
1209}
1210
1211SWITCH_DECLARE(switch_status_t) switch_core_timer_check(switch_timer_t *timer)
1212{
1213 if (!timer->timer_interface) {
1214 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timer is not initilized!\n");
1215 return SWITCH_STATUS_GENERR;
1216 }
1217
1218 return timer->timer_interface->timer_check(timer);
1219}
1220
1221
1222SWITCH_DECLARE(switch_status_t) switch_core_timer_destroy(switch_timer_t *timer)
1223{
1224 if (!timer->timer_interface) {
1225 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timer is not initilized!\n");
1226 return SWITCH_STATUS_GENERR;
1227 }
1228
1229 timer->timer_interface->timer_destroy(timer);
1230
1231 if (switch_test_flag(timer, SWITCH_TIMER_FLAG_FREE_POOL)) {
1232 switch_core_destroy_memory_pool(&timer->memory_pool);
1233 }
1234
1235 return SWITCH_STATUS_SUCCESS;
1236}
1237
1238static void *switch_core_service_thread(switch_thread_t *thread, void *obj)
1239{
1240 switch_core_thread_session_t *data = obj;
1241 switch_core_session_t *session = data->objs[0];
1242 int *stream_id_p = data->objs[1];
1243 switch_channel_t *channel;
1244 switch_frame_t *read_frame;
1245 int stream_id = *stream_id_p;
1246
1247 assert(thread != NULL);
1248 assert(session != NULL);
1249 channel = switch_core_session_get_channel(session);
1250 assert(channel != NULL);
1251
1252 switch_channel_set_flag(channel, CF_SERVICE);
1253 while (data->running > 0) {
1254 switch (switch_core_session_read_frame(session, &read_frame, -1, stream_id)) {
1255 case SWITCH_STATUS_SUCCESS:
1256 case SWITCH_STATUS_TIMEOUT:
1257 case SWITCH_STATUS_BREAK:
1258 break;
1259 default:
1260 data->running = -1;
1261 continue;
1262 }
1263 }
1264
1265 switch_channel_clear_flag(channel, CF_SERVICE);
1266 data->running = 0;
1267 return NULL;
1268}
1269
1270/* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */
1271SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_thread_session_t *thread_session)
1272{
1273 if (thread_session->running > 0) {
1274 thread_session->running = -1;
1275
1276 while (thread_session->running) {
1277 switch_yield(1000);
1278 }
1279 }
1280}
1281
1282SWITCH_DECLARE(void) switch_core_service_session(switch_core_session_t *session,
1283 switch_core_thread_session_t *thread_session, int stream_id)
1284{
1285 thread_session->running = 1;
1286 thread_session->objs[0] = session;
1287 thread_session->objs[1] = &stream_id;
1288 switch_core_session_launch_thread(session, switch_core_service_thread, thread_session);
1289}
1290
1291SWITCH_DECLARE(switch_memory_pool_t *) switch_core_session_get_pool(switch_core_session_t *session)
1292{
1293 return session->pool;
1294}
1295
1296/* **ONLY** alloc things with this function that **WILL NOT** outlive
1297 the session itself or expect an earth shattering KABOOM!*/
1298SWITCH_DECLARE(void *) switch_core_session_alloc(switch_core_session_t *session, switch_size_t memory)
1299{
1300 void *ptr = NULL;
1301 assert(session != NULL);
1302 assert(session->pool != NULL);
1303
1304#ifdef DEBUG_ALLOC
1305 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Allocate %d\n", memory);
1306#endif
1307
1308
1309 if ((ptr = apr_palloc(session->pool, memory)) != 0) {
1310 memset(ptr, 0, memory);
1311 }
1312 return ptr;
1313}
1314
1315/* **ONLY** alloc things with these functions that **WILL NOT** need
1316 to be freed *EVER* ie this is for *PERMANENT* memory allocation */
1317
1318SWITCH_DECLARE(void *) switch_core_permanent_alloc(switch_size_t memory)
1319{
1320 void *ptr = NULL;
1321 assert(runtime.memory_pool != NULL);
1322
1323#ifdef DEBUG_ALLOC
1324 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Perm Allocate %d\n", memory);
1325#endif
1326
1327 if ((ptr = apr_palloc(runtime.memory_pool, memory)) != 0) {
1328 memset(ptr, 0, memory);
1329 }
1330 return ptr;
1331}
1332
1333SWITCH_DECLARE(char *) switch_core_permanent_strdup(char *todup)
1334{
1335 char *duped = NULL;
1336 switch_size_t len;
1337
1338 assert(runtime.memory_pool != NULL);
1339
1340 if (!todup)
1341 return NULL;
1342
1343 len = strlen(todup) + 1;
1344
1345#ifdef DEBUG_ALLOC
1346 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Perm Allocate %d\n", len);
1347#endif
1348
1349 if (todup && (duped = apr_palloc(runtime.memory_pool, len)) != 0) {
1350 strncpy(duped, todup, len);
1351 }
1352 return duped;
1353}
1354
1355
1356SWITCH_DECLARE(char *) switch_core_session_strdup(switch_core_session_t *session, char *todup)
1357{
1358 char *duped = NULL;
1359 switch_size_t len;
1360 assert(session != NULL);
1361 assert(session->pool != NULL);
1362
1363 if (!todup) {
1364 return NULL;
1365 }
1366 len = strlen(todup) + 1;
1367
1368#ifdef DEBUG_ALLOC
1369 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Allocate %d\n", len);
1370#endif
1371
1372 if (todup && (duped = apr_palloc(session->pool, len)) != 0) {
1373 strncpy(duped, todup, len);
1374 }
1375 return duped;
1376}
1377
1378
1379SWITCH_DECLARE(char *) switch_core_strdup(switch_memory_pool_t *pool, char *todup)
1380{
1381 char *duped = NULL;
1382 switch_size_t len;
1383 assert(pool != NULL);
1384
1385 if (!todup) {
1386 return NULL;
1387 }
1388
1389 len = strlen(todup) + 1;
1390
1391#ifdef DEBUG_ALLOC
1392 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Allocate %d\n", len);
1393#endif
1394
1395 if (todup && (duped = apr_palloc(pool, len)) != 0) {
1396 strncpy(duped, todup, len);
1397 }
1398 return duped;
1399}
1400
1401SWITCH_DECLARE(void *) switch_core_session_get_private(switch_core_session_t *session)
1402{
1403 assert(session != NULL);
1404 return session->private_info;
1405}
1406
1407
1408SWITCH_DECLARE(switch_status_t) switch_core_session_set_private(switch_core_session_t *session, void *private_info)
1409{
1410 assert(session != NULL);
1411 session->private_info = private_info;
1412 return SWITCH_STATUS_SUCCESS;
1413}
1414
1415SWITCH_DECLARE(int) switch_core_session_add_stream(switch_core_session_t *session, void *private_info)
1416{
1417 session->streams[session->stream_count++] = private_info;
1418 return session->stream_count - 1;
1419}
1420
1421SWITCH_DECLARE(void *) switch_core_session_get_stream(switch_core_session_t *session, int index)
1422{
1423 return session->streams[index];
1424}
1425
1426
1427SWITCH_DECLARE(int) switch_core_session_get_stream_count(switch_core_session_t *session)
1428{
1429 return session->stream_count;
1430}
1431
1432SWITCH_DECLARE(switch_status_t) switch_core_session_outgoing_channel(switch_core_session_t *session,
1433 char *endpoint_name,
1434 switch_caller_profile_t *caller_profile,
1435 switch_core_session_t **new_session,
1436 switch_memory_pool_t *pool)
1437{
1438 switch_io_event_hook_outgoing_channel_t *ptr;
1439 switch_status_t status = SWITCH_STATUS_FALSE;
1440 const switch_endpoint_interface_t *endpoint_interface;
1441 switch_channel_t *channel = NULL;
1442 switch_caller_profile_t *outgoing_profile = caller_profile;
1443
1444 if ((endpoint_interface = switch_loadable_module_get_endpoint_interface(endpoint_name)) == 0) {
1445 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not locate channel type %s\n", endpoint_name);
1446 return SWITCH_STATUS_FALSE;
1447 }
1448
1449 if (endpoint_interface->io_routines->outgoing_channel) {
1450 if (session) {
1451 channel = switch_core_session_get_channel(session);
1452 if (caller_profile) {
1453 char *ecaller_id_name = NULL, *ecaller_id_number = NULL;
1454
1455 ecaller_id_name = switch_channel_get_variable(channel, "effective_caller_id_name");
1456 ecaller_id_number = switch_channel_get_variable(channel, "effective_caller_id_number");
1457
1458 if (ecaller_id_name || ecaller_id_number) {
1459 outgoing_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
1460 caller_profile->username,
1461 caller_profile->dialplan,
1462 ecaller_id_name,
1463 ecaller_id_number,
1464 caller_profile->network_addr,
1465 caller_profile->ani,
1466 caller_profile->aniii,
1467 caller_profile->rdnis,
1468 caller_profile->source,
1469 caller_profile->context,
1470 caller_profile->destination_number);
1471 outgoing_profile->flags = caller_profile->flags;
1472 }
1473 }
1474 if (!outgoing_profile) {
1475 outgoing_profile = switch_channel_get_caller_profile(channel);
1476 }
1477 }
1478
1479 if ((status = endpoint_interface->io_routines->outgoing_channel(session,
1480 outgoing_profile,
1481 new_session,
1482 pool)) == SWITCH_STATUS_SUCCESS) {
1483 if (session) {
1484 for (ptr = session->event_hooks.outgoing_channel; ptr; ptr = ptr->next) {
1485 if ((status = ptr->outgoing_channel(session, caller_profile, *new_session)) != SWITCH_STATUS_SUCCESS) {
1486 break;
1487 }
1488 }
1489 }
1490 } else {
1491 return status;
1492 }
1493 } else {
1494 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not locate outgoing channel interface for %s\n", endpoint_name);
1495 return SWITCH_STATUS_FALSE;
1496 }
1497
1498 if (*new_session) {
1499 switch_caller_profile_t *profile = NULL, *peer_profile = NULL, *cloned_profile = NULL;
1500 switch_event_t *event;
1501 switch_channel_t *peer_channel = switch_core_session_get_channel(*new_session);
1502
1503
1504 if (session && channel) {
1505 profile = switch_channel_get_caller_profile(channel);
1506 }
1507 if (peer_channel) {
1508 peer_profile = switch_channel_get_caller_profile(peer_channel);
1509 }
1510
1511 if (channel && peer_channel) {
1512 char *export_vars, *val;
1513
1514 switch_channel_set_variable(peer_channel, SWITCH_ORIGINATOR_VARIABLE, switch_core_session_get_uuid(session));
1515
1516 /* A comma (,) separated list of variable names that should ne propagated from originator to originatee */
1517 if ((export_vars = switch_channel_get_variable(channel, "export_vars"))) {
1518 char *cptmp = switch_core_session_strdup(session, export_vars);
1519 int argc;
1520 char *argv[256];
1521
1522 if ((argc = switch_separate_string(cptmp, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
1523 int x;
1524
1525 for (x = 0; x < argc; x++) {
1526 char *val;
1527 if ((val = switch_channel_get_variable(channel, argv[x]))) {
1528 switch_channel_set_variable(peer_channel, argv[x], val);
1529 }
1530 }
1531 }
1532 }
1533
1534 if ((val = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE))) {
1535 switch_channel_set_variable(peer_channel, SWITCH_B_SDP_VARIABLE, val);
1536 }
1537
1538 if (switch_channel_test_flag(channel, CF_NOMEDIA)) {
1539 switch_channel_set_flag(peer_channel, CF_NOMEDIA);
1540 }
1541
1542 if (profile) {
1543 if ((cloned_profile = switch_caller_profile_clone(*new_session, profile)) != 0) {
1544 switch_channel_set_originator_caller_profile(peer_channel, cloned_profile);
1545 }
1546 }
1547
1548 if (peer_profile) {
1549 if (session && (cloned_profile = switch_caller_profile_clone(session, peer_profile)) != 0) {
1550 switch_channel_set_originatee_caller_profile(channel, cloned_profile);
1551 }
1552 }
1553 }
1554
1555 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_OUTGOING) == SWITCH_STATUS_SUCCESS) {
1556 switch_channel_event_set_data(peer_channel, event);
1557 switch_event_fire(&event);
1558 }
1559 }
1560
1561 return status;
1562}
1563
1564SWITCH_DECLARE(switch_status_t) switch_core_session_answer_channel(switch_core_session_t *session)
1565{
1566 switch_io_event_hook_answer_channel_t *ptr;
1567 switch_status_t status = SWITCH_STATUS_FALSE;
1568
1569 assert(session != NULL);
1570 if (session->endpoint_interface->io_routines->answer_channel) {
1571 if ((status = session->endpoint_interface->io_routines->answer_channel(session)) == SWITCH_STATUS_SUCCESS) {
1572 for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
1573 if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
1574 break;
1575 }
1576 }
1577 }
1578 } else {
1579 status = SWITCH_STATUS_SUCCESS;
1580 }
1581
1582 return status;
1583}
1584
1585SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_session_t *session, switch_core_session_message_t *message)
1586{
1587 switch_io_event_hook_receive_message_t *ptr;
1588 switch_status_t status = SWITCH_STATUS_FALSE;
1589
1590 assert(session != NULL);
1591 if (session->endpoint_interface->io_routines->receive_message) {
1592 if ((status =
1593 session->endpoint_interface->io_routines->receive_message(session, message)) == SWITCH_STATUS_SUCCESS) {
1594 for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
1595 if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
1596 break;
1597 }
1598 }
1599 }
1600 }
1601 return status;
1602}
1603
1604SWITCH_DECLARE(switch_status_t) switch_core_session_queue_message(switch_core_session_t *session, switch_core_session_message_t *message)
1605{
1606 switch_status_t status = SWITCH_STATUS_FALSE;
1607
1608 assert(session != NULL);
1609
1610 if (!session->message_queue) {
1611 switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool);
1612 }
1613
1614 if (session->message_queue) {
1615 if (switch_queue_trypush(session->message_queue, message) == SWITCH_STATUS_SUCCESS) {
1616 status = SWITCH_STATUS_SUCCESS;
1617 }
1618 }
1619
1620 return status;
1621}
1622
1623SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_message(switch_core_session_t *session, switch_core_session_message_t **message)
1624{
1625 switch_status_t status = SWITCH_STATUS_FALSE;
1626 void *pop;
1627
1628 assert(session != NULL);
1629
1630 if (session->message_queue) {
1631 if ((status = (switch_status_t) switch_queue_trypop(session->message_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
1632 *message = (switch_core_session_message_t *) pop;
1633 }
1634 }
1635
1636 return status;
1637}
1638
1639SWITCH_DECLARE(switch_status_t) switch_core_session_receive_event(switch_core_session_t *session, switch_event_t **event)
1640
1641{
1642 switch_io_event_hook_receive_event_t *ptr;
1643 switch_status_t status = SWITCH_STATUS_FALSE;
1644
1645 assert(session != NULL);
1646
1647 /* Acquire a read lock on the session or forget it the channel is dead */
1648 if (switch_thread_rwlock_tryrdlock(session->rwlock) == SWITCH_STATUS_SUCCESS) {
1649 if (switch_channel_get_state(session->channel) < CS_HANGUP) {
1650 if (session->endpoint_interface->io_routines->receive_event) {
1651 status = session->endpoint_interface->io_routines->receive_event(session, *event);
1652 }
1653
1654 if (status == SWITCH_STATUS_SUCCESS) {
1655 for (ptr = session->event_hooks.receive_event; ptr; ptr = ptr->next) {
1656 if ((status = ptr->receive_event(session, *event)) != SWITCH_STATUS_SUCCESS) {
1657 break;
1658 }
1659 }
1660 }
1661
1662 if (status == SWITCH_STATUS_BREAK) {
1663 status = SWITCH_STATUS_SUCCESS;
1664 }
1665
1666 if (status == SWITCH_STATUS_SUCCESS) {
1667 switch_event_destroy(event);
1668 }
1669 }
1670 switch_thread_rwlock_unlock(session->rwlock);
1671 }
1672
1673 return status;
1674}
1675
1676SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_session_t *session, switch_event_t **event)
1677{
1678 switch_status_t status = SWITCH_STATUS_FALSE;
1679
1680 assert(session != NULL);
1681
1682 if (!session->event_queue) {
1683 switch_queue_create(&session->event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
1684 }
1685
1686 if (session->event_queue) {
1687 if (switch_queue_trypush(session->event_queue, *event) == SWITCH_STATUS_SUCCESS) {
1688 *event = NULL;
1689 status = SWITCH_STATUS_SUCCESS;
1690 }
1691 }
1692
1693 return status;
1694}
1695
1696SWITCH_DECLARE(int32_t) switch_core_session_event_count(switch_core_session_t *session)
1697{
1698 if (session->event_queue) {
1699 return (int32_t) switch_queue_size(session->event_queue);
1700 }
1701
1702 return -1;
1703}
1704
1705SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_event(switch_core_session_t *session, switch_event_t **event)
1706
1707{
1708 switch_status_t status = SWITCH_STATUS_FALSE;
1709 void *pop;
1710
1711 assert(session != NULL);
1712
1713 if (session->event_queue) {
1714 if ((status = (switch_status_t) switch_queue_trypop(session->event_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
1715 *event = (switch_event_t *) pop;
1716 }
1717 }
1718
1719 return status;
1720}
1721
1722SWITCH_DECLARE(switch_status_t) switch_core_session_queue_private_event(switch_core_session_t *session, switch_event_t **event)
1723{
1724 switch_status_t status = SWITCH_STATUS_FALSE;
1725
1726 assert(session != NULL);
1727
1728 if (!session->private_event_queue) {
1729 switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
1730 }
1731
1732 if (session->private_event_queue) {
1733 if (switch_queue_trypush(session->private_event_queue, *event) == SWITCH_STATUS_SUCCESS) {
1734 *event = NULL;
1735 status = SWITCH_STATUS_SUCCESS;
1736 }
1737 }
1738
1739 return status;
1740}
1741
1742SWITCH_DECLARE(int32_t) switch_core_session_private_event_count(switch_core_session_t *session)
1743{
1744 if (session->private_event_queue) {
1745 return (int32_t) switch_queue_size(session->private_event_queue);
1746 }
1747
1748 return -1;
1749}
1750
1751SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_private_event(switch_core_session_t *session, switch_event_t **event)
1752
1753{
1754 switch_status_t status = SWITCH_STATUS_FALSE;
1755 void *pop;
1756 switch_channel_t *channel;
1757
1758 assert(session != NULL);
1759
1760 channel = switch_core_session_get_channel(session);
1761 assert(channel != NULL);
1762
1763 if (switch_channel_test_flag(channel, CF_EVENT_PARSE)) {
1764 return status;
1765 }
1766
1767
1768 if (session->private_event_queue) {
1769 if ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
1770 *event = (switch_event_t *) pop;
1771 }
1772 }
1773
1774 return status;
1775}
1776
1777SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame,
1778 int timeout, int stream_id)
1779{
1780 switch_io_event_hook_read_frame_t *ptr;
1781 switch_status_t status;
1782 int need_codec, perfect, do_bugs = 0;
1783 unsigned int flag = 0;
1784 top:
1785
1786 status = SWITCH_STATUS_FALSE;
1787 need_codec = perfect = 0;
1788
1789 assert(session != NULL);
1790 *frame = NULL;
1791
1792 if (switch_channel_test_flag(session->channel, CF_HOLD)) {
1793 status = SWITCH_STATUS_BREAK;
1794 goto done;
1795 }
1796
1797 if (session->endpoint_interface->io_routines->read_frame) {
1798 if ((status = session->endpoint_interface->io_routines->read_frame(session,
1799 frame,
1800 timeout,
1801 SWITCH_IO_FLAG_NOOP,
1802 stream_id)) == SWITCH_STATUS_SUCCESS) {
1803 for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) {
1804 if ((status =
1805 ptr->read_frame(session, frame, timeout, SWITCH_IO_FLAG_NOOP,
1806 stream_id)) != SWITCH_STATUS_SUCCESS) {
1807 break;
1808 }
1809 }
1810 }
1811 }
1812
1813 if (status != SWITCH_STATUS_SUCCESS) {
1814 goto done;
1815 }
1816
1817 if (!(*frame)) {
1818 goto done;
1819 }
1820
1821 assert(session != NULL);
1822 assert(*frame != NULL);
1823
1824 if (switch_test_flag(*frame, SFF_CNG)) {
1825 status = SWITCH_STATUS_SUCCESS;
1826 goto done;
1827 }
1828
1829 if ((session->read_codec && (*frame)->codec && session->read_codec->implementation != (*frame)->codec->implementation)) {
1830 need_codec = TRUE;
1831 }
1832
1833 if (session->read_codec && !(*frame)->codec) {
1834 need_codec = TRUE;
1835 }
1836
1837 if (!session->read_codec && (*frame)->codec) {
1838 need_codec = TRUE;
1839 }
1840
1841 if (session->bugs && !need_codec) {
1842 do_bugs = 1;
1843 need_codec = 1;
1844 }
1845
1846 if (status == SWITCH_STATUS_SUCCESS && need_codec) {
1847 switch_frame_t *enc_frame, *read_frame = *frame;
1848
1849 if (read_frame->codec) {
1850 session->raw_read_frame.datalen = session->raw_read_frame.buflen;
1851 status = switch_core_codec_decode(read_frame->codec,
1852 session->read_codec,
1853 read_frame->data,
1854 read_frame->datalen,
1855 session->read_codec->implementation->samples_per_second,
1856 session->raw_read_frame.data,
1857 &session->raw_read_frame.datalen,
1858 &session->raw_read_frame.rate,
1859 &flag);
1860
1861 switch (status) {
1862 case SWITCH_STATUS_RESAMPLE:
1863 if (!session->read_resampler) {
1864 switch_resample_create(&session->read_resampler,
1865 read_frame->codec->implementation->samples_per_second,
1866 read_frame->codec->implementation->bytes_per_frame * 20,
1867 session->read_codec->implementation->samples_per_second,
1868 session->read_codec->implementation->bytes_per_frame * 20, session->pool);
1869 }
1870 case SWITCH_STATUS_SUCCESS:
1871 read_frame = &session->raw_read_frame;
1872 break;
1873 case SWITCH_STATUS_NOOP:
1874 status = SWITCH_STATUS_SUCCESS;
1875 break;
1876 default:
1877 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
1878 session->read_codec->codec_interface->interface_name);
1879 goto done;
1880 }
1881 }
1882 if (session->read_resampler) {
1883 short *data = read_frame->data;
1884
1885 session->read_resampler->from_len =
1886 switch_short_to_float(data, session->read_resampler->from, (int) read_frame->datalen / 2);
1887 session->read_resampler->to_len =
1888 switch_resample_process(session->read_resampler, session->read_resampler->from,
1889 session->read_resampler->from_len, session->read_resampler->to,
1890 session->read_resampler->to_size, 0);
1891 switch_float_to_short(session->read_resampler->to, data, read_frame->datalen);
1892 read_frame->samples = session->read_resampler->to_len;
1893 read_frame->datalen = session->read_resampler->to_len * 2;
1894 read_frame->rate = session->read_resampler->to_rate;
1895 }
1896
1897 if (session->bugs) {
1898 switch_media_bug_t *bp;
1899 switch_thread_rwlock_rdlock(session->bug_rwlock);
1900 for (bp = session->bugs; bp; bp = bp->next) {
1901 if (switch_test_flag(bp, SMBF_READ_STREAM)) {
1902 switch_mutex_lock(bp->read_mutex);
1903 switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
1904 if (bp->callback) {
1905 bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
1906 }
1907 switch_mutex_unlock(bp->read_mutex);
1908 }
1909 }
1910 switch_thread_rwlock_unlock(session->bug_rwlock);
1911 }
1912
1913 if (do_bugs) {
1914 goto done;
1915 }
1916
1917 if (session->read_codec) {
1918 if ((*frame)->datalen == session->read_codec->implementation->bytes_per_frame) {
1919 perfect = TRUE;
1920 } else {
1921 if (!session->raw_read_buffer) {
1922 switch_size_t bytes = session->read_codec->implementation->bytes_per_frame;
1923 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes\n", bytes);
1924 switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0);
1925 }
1926 if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
1927 status = SWITCH_STATUS_MEMERR;
1928 goto done;
1929 }
1930 }
1931
1932 if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_codec->implementation->bytes_per_frame) {
1933 if (perfect) {
1934 enc_frame = *frame;
1935 session->raw_read_frame.rate = (*frame)->rate;
1936 } else {
1937 session->raw_read_frame.datalen = (uint32_t)switch_buffer_read(session->raw_read_buffer,
1938 session->raw_read_frame.data,
1939 session->read_codec->implementation->bytes_per_frame);
1940
1941 session->raw_read_frame.rate = session->read_codec->implementation->samples_per_second;
1942 enc_frame = &session->raw_read_frame;
1943 }
1944 session->enc_read_frame.datalen = session->enc_read_frame.buflen;
1945 assert(session->read_codec != NULL);
1946 assert(enc_frame != NULL);
1947 assert(enc_frame->data != NULL);
1948
1949 status = switch_core_codec_encode(session->read_codec,
1950 enc_frame->codec,
1951 enc_frame->data,
1952 enc_frame->datalen,
1953 session->read_codec->implementation->samples_per_second,
1954 session->enc_read_frame.data,
1955 &session->enc_read_frame.datalen,
1956 &session->enc_read_frame.rate,
1957 &flag);
1958
1959
1960 switch (status) {
1961 case SWITCH_STATUS_RESAMPLE:
1962 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "fixme 1\n");
1963 case SWITCH_STATUS_SUCCESS:
1964 *frame = &session->enc_read_frame;
1965 break;
1966 case SWITCH_STATUS_NOOP:
1967 *frame = &session->raw_read_frame;
1968 status = SWITCH_STATUS_SUCCESS;
1969 break;
1970 default:
1971 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
1972 session->read_codec->codec_interface->interface_name);
1973 *frame = NULL;
1974 status = SWITCH_STATUS_GENERR;
1975 break;
1976 }
1977 } else {
1978 goto top;
1979 }
1980 }
1981 }
1982
1983 done:
1984 if (!(*frame)) {
1985 status = SWITCH_STATUS_FALSE;
1986 } else {
1987 if (flag & SFF_CNG) {
1988 switch_set_flag((*frame), SFF_CNG);
1989 }
1990 }
1991
1992 return status;
1993}
1994
1995static switch_status_t perform_write(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id)
1996{
1997 switch_io_event_hook_write_frame_t *ptr;
1998 switch_status_t status = SWITCH_STATUS_FALSE;
1999
2000 if (session->endpoint_interface->io_routines->write_frame) {
2001 if ((status =
2002 session->endpoint_interface->io_routines->write_frame(session, frame, timeout, flags,
2003 stream_id)) == SWITCH_STATUS_SUCCESS) {
2004 for (ptr = session->event_hooks.write_frame; ptr; ptr = ptr->next) {
2005 if ((status = ptr->write_frame(session, frame, timeout, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
2006 break;
2007 }
2008 }
2009 }
2010 }
2011 return status;
2012}
2013
2014SWITCH_DECLARE(void) switch_core_session_reset(switch_core_session_t *session)
2015{
2016 /* sweep theese under the rug, they wont be leaked they will be reclaimed
2017 when the session ends.
2018 */
2019
2020 session->read_resampler = NULL;
2021 session->write_resampler = NULL;
2022
2023 /* wipe theese, they will be recreated if need be */
2024 switch_buffer_destroy(&session->raw_read_buffer);
2025 switch_buffer_destroy(&session->raw_write_buffer);
2026}
2027
2028SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_session_t *session, switch_frame_t *frame,
2029 int timeout, int stream_id)
2030{
2031
2032 switch_status_t status = SWITCH_STATUS_FALSE;
2033 switch_frame_t *enc_frame = NULL, *write_frame = frame;
2034 unsigned int flag = 0, need_codec = 0, perfect = 0, do_bugs = 0, do_write = 0;
2035 switch_io_flag_t io_flag = SWITCH_IO_FLAG_NOOP;
2036
2037 assert(session != NULL);
2038 assert(frame != NULL);
2039
2040
2041 if (switch_channel_test_flag(session->channel, CF_HOLD)) {
2042 return SWITCH_STATUS_SUCCESS;
2043 }
2044
2045 if (switch_test_flag(frame, SFF_CNG)) {
2046
2047 if (switch_channel_test_flag(session->channel, CF_ACCEPT_CNG)) {
2048 return perform_write(session, frame, timeout, flag, stream_id);
2049 }
2050
2051 return SWITCH_STATUS_SUCCESS;
2052 }
2053
2054 assert(frame->codec != NULL);
2055
2056 if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) {
2057 need_codec = TRUE;
2058 }
2059
2060 if (session->write_codec && !frame->codec) {
2061 need_codec = TRUE;
2062 }
2063
2064 if (!session->write_codec && frame->codec) {
2065 need_codec = TRUE;
2066 }
2067
2068 if (session->bugs && !need_codec) {
2069 do_bugs = 1;
2070 need_codec = 1;
2071 }
2072
2073 if (need_codec) {
2074 if (frame->codec) {
2075 session->raw_write_frame.datalen = session->raw_write_frame.buflen;
2076 status = switch_core_codec_decode(frame->codec,
2077 session->write_codec,
2078 frame->data,
2079 frame->datalen,
2080 session->write_codec->implementation->samples_per_second,
2081 session->raw_write_frame.data,
2082 &session->raw_write_frame.datalen, &session->raw_write_frame.rate, &flag);
2083
2084
2085 switch (status) {
2086 case SWITCH_STATUS_RESAMPLE:
2087 write_frame = &session->raw_write_frame;
2088 if (!session->write_resampler) {
2089 status = switch_resample_create(&session->write_resampler,
2090 frame->codec->implementation->samples_per_second,
2091 frame->codec->implementation->bytes_per_frame * 20,
2092 session->write_codec->implementation->samples_per_second,
2093 session->write_codec->implementation->bytes_per_frame * 20,
2094 session->pool);
2095 }
2096 break;
2097 case SWITCH_STATUS_SUCCESS:
2098 write_frame = &session->raw_write_frame;
2099 break;
2100 case SWITCH_STATUS_BREAK:
2101 return SWITCH_STATUS_SUCCESS;
2102 case SWITCH_STATUS_NOOP:
2103 write_frame = frame;
2104 status = SWITCH_STATUS_SUCCESS;
2105 break;
2106 default:
2107 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
2108 frame->codec->codec_interface->interface_name);
2109 return status;
2110 }
2111 }
2112 if (session->write_resampler) {
2113 short *data = write_frame->data;
2114
2115 session->write_resampler->from_len = write_frame->datalen / 2;
2116 switch_short_to_float(data, session->write_resampler->from, session->write_resampler->from_len);
2117
2118
2119
2120 session->write_resampler->to_len = (uint32_t)
2121 switch_resample_process(session->write_resampler, session->write_resampler->from,
2122 session->write_resampler->from_len, session->write_resampler->to,
2123 session->write_resampler->to_size, 0);
2124
2125
2126 switch_float_to_short(session->write_resampler->to, data, session->write_resampler->to_len);
2127
2128 write_frame->samples = session->write_resampler->to_len;
2129 write_frame->datalen = write_frame->samples * 2;
2130 write_frame->rate = session->write_resampler->to_rate;
2131 }
2132
2133 if (session->bugs) {
2134 switch_media_bug_t *bp;
2135 switch_thread_rwlock_rdlock(session->bug_rwlock);
2136 for (bp = session->bugs; bp; bp = bp->next) {
2137 if (switch_test_flag(bp, SMBF_WRITE_STREAM)) {
2138 switch_mutex_lock(bp->write_mutex);
2139 switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
2140 switch_mutex_unlock(bp->write_mutex);
2141 if (bp->callback) {
2142 bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
2143 }
2144 }
2145 }
2146 switch_thread_rwlock_unlock(session->bug_rwlock);
2147 }
2148 if (do_bugs) {
2149 do_write = 1;
2150 write_frame = frame;
2151 goto done;
2152 }
2153 if (session->write_codec) {
2154 if (write_frame->datalen == session->write_codec->implementation->bytes_per_frame) {
2155 perfect = TRUE;
2156 } else {
2157 if (!session->raw_write_buffer) {
2158 switch_size_t bytes = session->write_codec->implementation->bytes_per_frame;
2159 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
2160 "Engaging Write Buffer at %u bytes to accomodate %u->%u\n",
2161 bytes,
2162 write_frame->datalen, session->write_codec->implementation->bytes_per_frame);
2163 if ((status =switch_buffer_create_dynamic(&session->raw_write_buffer,
2164 bytes * SWITCH_BUFFER_BLOCK_FRAMES,
2165 bytes * SWITCH_BUFFER_START_FRAMES,
2166 0)) != SWITCH_STATUS_SUCCESS) {
2167 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Write Buffer Failed!\n");
2168 return status;
2169 }
2170 }
2171
2172 if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) {
2173 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Write Buffer %u bytes Failed!\n", write_frame->datalen);
2174 return SWITCH_STATUS_MEMERR;
2175 }
2176 }
2177
2178
2179 if (perfect) {
2180 enc_frame = write_frame;
2181 session->enc_write_frame.datalen = session->enc_write_frame.buflen;
2182
2183 status = switch_core_codec_encode(session->write_codec,
2184 frame->codec,
2185 enc_frame->data,
2186 enc_frame->datalen,
2187 session->write_codec->implementation->samples_per_second,
2188 session->enc_write_frame.data,
2189 &session->enc_write_frame.datalen,
2190 &session->enc_write_frame.rate, &flag);
2191
2192 switch (status) {
2193 case SWITCH_STATUS_RESAMPLE:
2194 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "fixme 2\n");
2195 case SWITCH_STATUS_SUCCESS:
2196 write_frame = &session->enc_write_frame;
2197 break;
2198 case SWITCH_STATUS_NOOP:
2199 write_frame = enc_frame;
2200 status = SWITCH_STATUS_SUCCESS;
2201 break;
2202 default:
2203 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
2204 session->read_codec->codec_interface->interface_name);
2205 write_frame = NULL;
2206 return status;
2207 }
2208 if (flag & SFF_CNG) {
2209 switch_set_flag(write_frame, SFF_CNG);
2210 }
2211 status = perform_write(session, write_frame, timeout, io_flag, stream_id);
2212 return status;
2213 } else {
2214 switch_size_t used = switch_buffer_inuse(session->raw_write_buffer);
2215 uint32_t bytes = session->write_codec->implementation->bytes_per_frame;
2216 switch_size_t frames = (used / bytes);
2217
2218 status = SWITCH_STATUS_SUCCESS;
2219 if (!frames) {
2220 return status;
2221 } else {
2222 switch_size_t x;
2223 for (x = 0; x < frames; x++) {
2224 if ((session->raw_write_frame.datalen = (uint32_t)
2225 switch_buffer_read(session->raw_write_buffer, session->raw_write_frame.data, bytes)) != 0) {
2226 enc_frame = &session->raw_write_frame;
2227 session->raw_write_frame.rate = session->write_codec->implementation->samples_per_second;
2228 session->enc_write_frame.datalen = session->enc_write_frame.buflen;
2229
2230
2231 status = switch_core_codec_encode(session->write_codec,
2232 frame->codec,
2233 enc_frame->data,
2234 enc_frame->datalen,
2235 frame->codec->implementation->samples_per_second,
2236 session->enc_write_frame.data,
2237 &session->enc_write_frame.datalen,
2238 &session->enc_write_frame.rate, &flag);
2239
2240
2241 switch (status) {
2242 case SWITCH_STATUS_RESAMPLE:
2243 write_frame = &session->enc_write_frame;
2244 if (!session->read_resampler) {
2245 status = switch_resample_create(&session->read_resampler,
2246 frame->codec->implementation->samples_per_second,
2247 frame->codec->implementation->bytes_per_frame * 20,
2248 session->write_codec->implementation->
2249 samples_per_second,
2250 session->write_codec->implementation->
2251 bytes_per_frame * 20, session->pool);
2252 }
2253 break;
2254 case SWITCH_STATUS_SUCCESS:
2255 write_frame = &session->enc_write_frame;
2256 break;
2257 case SWITCH_STATUS_NOOP:
2258 write_frame = enc_frame;
2259 status = SWITCH_STATUS_SUCCESS;
2260 break;
2261 default:
2262 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec %s encoder error %d!\n",
2263 session->read_codec->codec_interface->interface_name, status);
2264 write_frame = NULL;
2265 return status;
2266 }
2267
2268 if (session->read_resampler) {
2269 short *data = write_frame->data;
2270
2271 session->read_resampler->from_len = switch_short_to_float(data,
2272 session->read_resampler->from,
2273 (int) write_frame->datalen /
2274 2);
2275 session->read_resampler->to_len = (uint32_t)
2276 switch_resample_process(session->read_resampler, session->read_resampler->from,
2277 session->read_resampler->from_len,
2278 session->read_resampler->to,
2279 session->read_resampler->to_size, 0);
2280 switch_float_to_short(session->read_resampler->to, data, write_frame->datalen * 2);
2281 write_frame->samples = session->read_resampler->to_len;
2282 write_frame->datalen = session->read_resampler->to_len * 2;
2283 write_frame->rate = session->read_resampler->to_rate;
2284 }
2285 if (flag & SFF_CNG) {
2286 switch_set_flag(write_frame, SFF_CNG);
2287 }
2288 if ((status = perform_write(session, write_frame, timeout, io_flag, stream_id)) != SWITCH_STATUS_SUCCESS) {
2289 break;
2290 }
2291 }
2292 }
2293 return status;
2294 }
2295 }
2296 }
2297 } else {
2298 do_write = 1;
2299 }
2300
2301 done:
2302 if (do_write) {
2303 return perform_write(session, frame, timeout, io_flag, stream_id);
2304 }
2305
2306 return status;
2307}
2308
2309SWITCH_DECLARE(switch_status_t) switch_core_session_perform_kill_channel(switch_core_session_t *session,
2310 const char *file,
2311 const char *func,
2312 int line,
2313 switch_signal_t sig)
2314{
2315 switch_io_event_hook_kill_channel_t *ptr;
2316 switch_status_t status = SWITCH_STATUS_FALSE;
2317
2318 switch_log_printf(SWITCH_CHANNEL_ID_LOG, (char *) file, func, line, SWITCH_LOG_INFO, "Kill %s [%d]\n", switch_channel_get_name(session->channel), sig);
2319
2320 if (session->endpoint_interface->io_routines->kill_channel) {
2321 if ((status = session->endpoint_interface->io_routines->kill_channel(session, sig)) == SWITCH_STATUS_SUCCESS) {
2322 for (ptr = session->event_hooks.kill_channel; ptr; ptr = ptr->next) {
2323 if ((status = ptr->kill_channel(session, sig)) != SWITCH_STATUS_SUCCESS) {
2324 break;
2325 }
2326 }
2327 }
2328 }
2329
2330 return status;
2331
2332}
2333
2334SWITCH_DECLARE(switch_status_t) switch_core_session_waitfor_read(switch_core_session_t *session, int timeout, int stream_id)
2335{
2336 switch_io_event_hook_waitfor_read_t *ptr;
2337 switch_status_t status = SWITCH_STATUS_FALSE;
2338
2339 if (session->endpoint_interface->io_routines->waitfor_read) {
2340 if ((status =
2341 session->endpoint_interface->io_routines->waitfor_read(session, timeout,
2342 stream_id)) == SWITCH_STATUS_SUCCESS) {
2343 for (ptr = session->event_hooks.waitfor_read; ptr; ptr = ptr->next) {
2344 if ((status = ptr->waitfor_read(session, timeout, stream_id)) != SWITCH_STATUS_SUCCESS) {
2345 break;
2346 }
2347 }
2348 }
2349 }
2350
2351 return status;
2352
2353}
2354
2355SWITCH_DECLARE(switch_status_t) switch_core_session_waitfor_write(switch_core_session_t *session, int timeout,
2356 int stream_id)
2357{
2358 switch_io_event_hook_waitfor_write_t *ptr;
2359 switch_status_t status = SWITCH_STATUS_FALSE;
2360
2361 if (session->endpoint_interface->io_routines->waitfor_write) {
2362 if ((status =
2363 session->endpoint_interface->io_routines->waitfor_write(session, timeout,
2364 stream_id)) == SWITCH_STATUS_SUCCESS) {
2365 for (ptr = session->event_hooks.waitfor_write; ptr; ptr = ptr->next) {
2366 if ((status = ptr->waitfor_write(session, timeout, stream_id)) != SWITCH_STATUS_SUCCESS) {
2367 break;
2368 }
2369 }
2370 }
2371 }
2372
2373 return status;
2374}
2375
2376
2377SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, char *dtmf)
2378{
2379 switch_io_event_hook_send_dtmf_t *ptr;
2380 switch_status_t status = SWITCH_STATUS_FALSE;
2381
2382 if (session->endpoint_interface->io_routines->send_dtmf) {
2383 if ((status = session->endpoint_interface->io_routines->send_dtmf(session, dtmf)) == SWITCH_STATUS_SUCCESS) {
2384 for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) {
2385 if ((status = ptr->send_dtmf(session, dtmf)) != SWITCH_STATUS_SUCCESS) {
2386 break;
2387 }
2388 }
2389 }
2390 }
2391
2392 return status;
2393}
2394
2395SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_outgoing(switch_core_session_t *session,
2396 switch_outgoing_channel_hook_t outgoing_channel)
2397{
2398 switch_io_event_hook_outgoing_channel_t *hook, *ptr;
2399
2400 assert(outgoing_channel != NULL);
2401 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2402 hook->outgoing_channel = outgoing_channel;
2403 if (!session->event_hooks.outgoing_channel) {
2404 session->event_hooks.outgoing_channel = hook;
2405 } else {
2406 for (ptr = session->event_hooks.outgoing_channel; ptr && ptr->next; ptr = ptr->next);
2407 ptr->next = hook;
2408
2409 }
2410
2411 return SWITCH_STATUS_SUCCESS;
2412 }
2413
2414 return SWITCH_STATUS_MEMERR;
2415}
2416
2417SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_answer_channel(switch_core_session_t *session,
2418 switch_answer_channel_hook_t
2419 answer_channel)
2420{
2421 switch_io_event_hook_answer_channel_t *hook, *ptr;
2422
2423 assert(answer_channel != NULL);
2424 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2425 hook->answer_channel = answer_channel;
2426 if (!session->event_hooks.answer_channel) {
2427 session->event_hooks.answer_channel = hook;
2428 } else {
2429 for (ptr = session->event_hooks.answer_channel; ptr && ptr->next; ptr = ptr->next);
2430 ptr->next = hook;
2431
2432 }
2433
2434 return SWITCH_STATUS_SUCCESS;
2435 }
2436
2437 return SWITCH_STATUS_MEMERR;
2438
2439}
2440
2441SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_read_frame(switch_core_session_t *session,
2442 switch_read_frame_hook_t read_frame)
2443{
2444 switch_io_event_hook_read_frame_t *hook, *ptr;
2445
2446 assert(read_frame != NULL);
2447 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2448 hook->read_frame = read_frame;
2449 if (!session->event_hooks.read_frame) {
2450 session->event_hooks.read_frame = hook;
2451 } else {
2452 for (ptr = session->event_hooks.read_frame; ptr && ptr->next; ptr = ptr->next);
2453 ptr->next = hook;
2454
2455 }
2456
2457 return SWITCH_STATUS_SUCCESS;
2458 }
2459
2460 return SWITCH_STATUS_MEMERR;
2461
2462}
2463
2464SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_write_frame(switch_core_session_t *session,
2465 switch_write_frame_hook_t write_frame)
2466{
2467 switch_io_event_hook_write_frame_t *hook, *ptr;
2468
2469 assert(write_frame != NULL);
2470 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2471 hook->write_frame = write_frame;
2472 if (!session->event_hooks.write_frame) {
2473 session->event_hooks.write_frame = hook;
2474 } else {
2475 for (ptr = session->event_hooks.write_frame; ptr && ptr->next; ptr = ptr->next);
2476 ptr->next = hook;
2477
2478 }
2479
2480 return SWITCH_STATUS_SUCCESS;
2481 }
2482
2483 return SWITCH_STATUS_MEMERR;
2484
2485}
2486
2487SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_kill_channel(switch_core_session_t *session,
2488 switch_kill_channel_hook_t kill_channel)
2489{
2490 switch_io_event_hook_kill_channel_t *hook, *ptr;
2491
2492 assert(kill_channel != NULL);
2493 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2494 hook->kill_channel = kill_channel;
2495 if (!session->event_hooks.kill_channel) {
2496 session->event_hooks.kill_channel = hook;
2497 } else {
2498 for (ptr = session->event_hooks.kill_channel; ptr && ptr->next; ptr = ptr->next);
2499 ptr->next = hook;
2500
2501 }
2502
2503 return SWITCH_STATUS_SUCCESS;
2504 }
2505
2506 return SWITCH_STATUS_MEMERR;
2507
2508}
2509
2510SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_waitfor_read(switch_core_session_t *session,
2511 switch_waitfor_read_hook_t waitfor_read)
2512{
2513 switch_io_event_hook_waitfor_read_t *hook, *ptr;
2514
2515 assert(waitfor_read != NULL);
2516 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2517 hook->waitfor_read = waitfor_read;
2518 if (!session->event_hooks.waitfor_read) {
2519 session->event_hooks.waitfor_read = hook;
2520 } else {
2521 for (ptr = session->event_hooks.waitfor_read; ptr && ptr->next; ptr = ptr->next);
2522 ptr->next = hook;
2523
2524 }
2525
2526 return SWITCH_STATUS_SUCCESS;
2527 }
2528
2529 return SWITCH_STATUS_MEMERR;
2530
2531}
2532
2533SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_waitfor_write(switch_core_session_t *session,
2534 switch_waitfor_write_hook_t waitfor_write)
2535{
2536 switch_io_event_hook_waitfor_write_t *hook, *ptr;
2537
2538 assert(waitfor_write != NULL);
2539 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2540 hook->waitfor_write = waitfor_write;
2541 if (!session->event_hooks.waitfor_write) {
2542 session->event_hooks.waitfor_write = hook;
2543 } else {
2544 for (ptr = session->event_hooks.waitfor_write; ptr && ptr->next; ptr = ptr->next);
2545 ptr->next = hook;
2546
2547 }
2548
2549 return SWITCH_STATUS_SUCCESS;
2550 }
2551
2552 return SWITCH_STATUS_MEMERR;
2553
2554}
2555
2556
2557SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_send_dtmf(switch_core_session_t *session,
2558 switch_send_dtmf_hook_t send_dtmf)
2559{
2560 switch_io_event_hook_send_dtmf_t *hook, *ptr;
2561
2562 assert(send_dtmf != NULL);
2563 if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
2564 hook->send_dtmf = send_dtmf;
2565 if (!session->event_hooks.send_dtmf) {
2566 session->event_hooks.send_dtmf = hook;
2567 } else {
2568 for (ptr = session->event_hooks.send_dtmf; ptr && ptr->next; ptr = ptr->next);
2569 ptr->next = hook;
2570
2571 }
2572
2573 return SWITCH_STATUS_SUCCESS;
2574 }
2575
2576 return SWITCH_STATUS_MEMERR;
2577
2578}
2579
2580
2581SWITCH_DECLARE(switch_status_t) switch_core_new_memory_pool(switch_memory_pool_t **pool)
2582{
2583
2584 assert(runtime.memory_pool != NULL);
2585
2586 if ((apr_pool_create(pool, NULL)) != SWITCH_STATUS_SUCCESS) {
2587 *pool = NULL;
2588 return SWITCH_STATUS_MEMERR;
2589 }
2590 return SWITCH_STATUS_SUCCESS;
2591}
2592
2593SWITCH_DECLARE(switch_status_t) switch_core_destroy_memory_pool(switch_memory_pool_t **pool)
2594{
2595 apr_pool_destroy(*pool);
2596 return SWITCH_STATUS_SUCCESS;
2597}
2598
2599SWITCH_DECLARE(switch_channel_t *) switch_core_session_get_channel(switch_core_session_t *session)
2600{
2601 return session->channel;
2602}
2603
2604static void switch_core_standard_on_init(switch_core_session_t *session)
2605{
2606 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard INIT %s\n", switch_channel_get_name(session->channel));
2607}
2608
2609static void switch_core_standard_on_hangup(switch_core_session_t *session)
2610{
2611
2612 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard HANGUP %s, cause: %s\n", switch_channel_get_name(session->channel),switch_channel_cause2str(switch_channel_get_cause(session->channel)));
2613
2614}
2615
2616static void switch_core_standard_on_ring(switch_core_session_t *session)
2617{
2618 switch_dialplan_interface_t *dialplan_interface = NULL;
2619 switch_caller_profile_t *caller_profile;
2620 switch_caller_extension_t *extension;
2621
2622 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard RING %s\n", switch_channel_get_name(session->channel));
2623
2624 if ((caller_profile = switch_channel_get_caller_profile(session->channel)) == 0) {
2625 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't get profile!\n");
2626 switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
2627 } else {
2628 char *dp[25];
2629 int argc, x, count = 0;
2630
2631 if (!switch_strlen_zero(caller_profile->dialplan)) {
2632 argc = switch_separate_string(caller_profile->dialplan, ',', dp, (sizeof(dp) / sizeof(dp[0])));
2633 for (x = 0; x < argc; x++) {
2634 if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dp[x]))) {
2635 continue;
2636 }
2637
2638 count++;
2639
2640 if ((extension = dialplan_interface->hunt_function(session)) != 0) {
2641 switch_channel_set_caller_extension(session->channel, extension);
2642 break;
2643 }
2644 }
2645 }
2646
2647 if (!count) {
2648 if (switch_channel_test_flag(session->channel, CF_OUTBOUND)) {
2649 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "No Dialplan, changing state to HOLD\n");
2650 switch_channel_set_state(session->channel, CS_HOLD);
2651 return;
2652 } else {
2653 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "No Dialplan, Aborting\n");
2654 switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
2655 }
2656 }
2657 }
2658
2659}
2660
2661static void switch_core_standard_on_execute(switch_core_session_t *session)
2662{
2663 switch_caller_extension_t *extension;
2664 switch_event_t *event;
2665 const switch_application_interface_t *application_interface;
2666
2667
2668 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard EXECUTE\n");
2669 if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) {
2670 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Extension!\n");
2671 switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
2672 return;
2673 }
2674
2675 while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) {
2676 char *expanded = NULL;
2677
2678 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Execute %s(%s)\n",
2679 extension->current_application->application_name,
2680 extension->current_application->application_data);
2681 if (
2682 (application_interface =
2683 switch_loadable_module_get_application_interface(extension->current_application->application_name)) == 0) {
2684 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n",
2685 extension->current_application->application_name);
2686 switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
2687 return;
2688 }
2689
2690 if (!application_interface->application_function) {
2691 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n",
2692 extension->current_application->application_name);
2693 switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
2694 return;
2695 }
2696
2697 if ((expanded = switch_channel_expand_variables(session->channel, extension->current_application->application_data)) !=
2698 extension->current_application->application_data) {
2699 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Expanded String %s(%s)\n",
2700 extension->current_application->application_name,
2701 expanded);
2702 }
2703
2704 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
2705 switch_channel_event_set_data(session->channel, event);
2706 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", extension->current_application->application_name);
2707 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data-Orig", "%s", extension->current_application->application_data);
2708 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", expanded);
2709 switch_event_fire(&event);
2710 }
2711
2712
2713 if (switch_channel_get_variable(session->channel, "presence_id")) {
2714 char *arg = switch_mprintf("%s(%s)", extension->current_application->application_name, expanded);
2715 if (arg) {
2716 switch_channel_presence(session->channel, "unknown", arg);
2717 switch_safe_free(arg);
2718 }
2719 }
2720
2721 application_interface->application_function(session, expanded);
2722
2723 if (expanded != extension->current_application->application_data) {
2724 switch_safe_free(expanded);
2725 }
2726 extension->current_application = extension->current_application->next;
2727 }
2728
2729 if (switch_channel_get_state(session->channel) == CS_EXECUTE) {
2730 switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING);
2731 }
2732}
2733
2734static void switch_core_standard_on_loopback(switch_core_session_t *session)
2735{
2736 switch_frame_t *frame;
2737 int stream_id;
2738
2739 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard LOOPBACK\n");
2740
2741 while (switch_channel_get_state(session->channel) == CS_LOOPBACK) {
2742 for (stream_id = 0; stream_id < session->stream_count; stream_id++) {
2743 if (switch_core_session_read_frame(session, &frame, -1, stream_id) == SWITCH_STATUS_SUCCESS) {
2744 switch_core_session_write_frame(session, frame, -1, stream_id);
2745 }
2746 }
2747 }
2748}
2749
2750static void switch_core_standard_on_transmit(switch_core_session_t *session)
2751{
2752 assert(session != NULL);
2753 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard TRANSMIT\n");
2754}
2755
2756static void switch_core_standard_on_hold(switch_core_session_t *session)
2757{
2758 assert(session != NULL);
2759 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard HOLD\n");
2760}
2761
2762static void switch_core_standard_on_hibernate(switch_core_session_t *session)
2763{
2764 assert(session != NULL);
2765 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard HIBERNATE\n");
2766}
2767
2768SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
2769{
2770
2771 /* If trylock fails the signal is already awake so we needn't bother */
2772 if (switch_mutex_trylock(session->mutex) == SWITCH_STATUS_SUCCESS) {
2773 switch_thread_cond_signal(session->cond);
2774 switch_mutex_unlock(session->mutex);
2775 }
2776
2777}
2778
2779SWITCH_DECLARE(unsigned int) switch_core_session_running(switch_core_session_t *session)
2780{
2781 return session->thread_running;
2782}
2783#ifdef CRASH_PROT
2784#if defined (__GNUC__) && defined (LINUX)
2785#include <execinfo.h>
2786#include <stdio.h>
2787#include <stdlib.h>
2788#define STACK_LEN 10
2789
2790/* Obtain a backtrace and print it to stdout. */
2791static void print_trace (void)
2792{
2793 void *array[STACK_LEN];
2794 size_t size;
2795 char **strings;
2796 size_t i;
2797
2798 size = backtrace (array, STACK_LEN);
2799 strings = backtrace_symbols (array, size);
2800
2801 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Obtained %zd stack frames.\n", size);
2802
2803 for (i = 0; i < size; i++) {
2804 switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CRIT, "%s\n", strings[i]);
2805 }
2806
2807 free (strings);
2808}
2809#else
2810static void print_trace (void)
2811{
2812 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Trace not avaliable =(\n");
2813}
2814#endif
2815
2816
2817static int handle_fatality(int sig)
2818{
2819 switch_thread_id_t thread_id;
2820 jmp_buf *env;
2821
2822 if (sig && (thread_id = switch_thread_self()) && (env = (jmp_buf *) apr_hash_get(runtime.stack_table, &thread_id, sizeof(thread_id)))) {
2823 print_trace();
2824 longjmp(*env, sig);
2825 } else {
2826 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Caught signal %d for unmapped thread!", sig);
2827 abort();
2828 }
2829
2830 return 0;
2831}
2832#endif
2833
2834SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
2835{
2836 switch_channel_state_t state = CS_NEW, laststate = CS_HANGUP, midstate = CS_DONE, endstate;
2837 const switch_endpoint_interface_t *endpoint_interface;
2838 const switch_state_handler_table_t *driver_state_handler = NULL;
2839 const switch_state_handler_table_t *application_state_handler = NULL;
2840#ifdef CRASH_PROT
2841 switch_thread_id_t thread_id = switch_thread_self();
2842 jmp_buf env;
2843 int sig;
2844
2845 signal(SIGSEGV, (void *) handle_fatality);
2846 signal(SIGFPE, (void *) handle_fatality);
2847#ifndef WIN32
2848 signal(SIGBUS, (void *) handle_fatality);
2849#endif
2850
2851 if ((sig = setjmp(env)) != 0) {
2852 switch_event_t *event;
2853
2854 if (switch_event_create(&event, SWITCH_EVENT_SESSION_CRASH) == SWITCH_STATUS_SUCCESS) {
2855 switch_channel_event_set_data(session->channel, event);
2856 switch_event_fire(&event);
2857 }
2858 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Thread has crashed for channel %s\n", switch_channel_get_name(session->channel));
2859 switch_channel_hangup(session->channel, SWITCH_CAUSE_CRASH);
2860 } else {
2861 apr_hash_set(runtime.stack_table, &thread_id, sizeof(thread_id), &env);
2862 }
2863#endif
2864 /*
2865 Life of the channel. you have channel and pool in your session
2866 everywhere you go you use the session to malloc with
2867 switch_core_session_alloc(session, <size>)
2868
2869 The enpoint module gets the first crack at implementing the state
2870 if it wants to, it can cancel the default behaviour by returning SWITCH_STATUS_FALSE
2871
2872 Next comes the channel's event handler table that can be set by an application
2873 which also can veto the next behaviour in line by returning SWITCH_STATUS_FALSE
2874
2875 Finally the default state behaviour is called.
2876
2877
2878 */
2879 assert(session != NULL);
2880
2881 session->thread_running = 1;
2882 endpoint_interface = session->endpoint_interface;
2883 assert(endpoint_interface != NULL);
2884
2885 driver_state_handler = endpoint_interface->state_handler;
2886 assert(driver_state_handler != NULL);
2887
2888 switch_mutex_lock(session->mutex);
2889
2890 while ((state = switch_channel_get_state(session->channel)) != CS_DONE) {
2891 if (state != laststate) {
2892 int index = 0;
2893 int proceed = 1;
2894 midstate = state;
2895
2896 switch (state) {
2897 case CS_NEW: /* Just created, Waiting for first instructions */
2898 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel));
2899 break;
2900 case CS_DONE:
2901 goto done;
2902 case CS_HANGUP: /* Deactivate and end the thread */
2903 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State HANGUP\n", switch_channel_get_name(session->channel));
2904 if (!driver_state_handler->on_hangup ||
2905 (driver_state_handler->on_hangup &&
2906 driver_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
2907 midstate == switch_channel_get_state(session->channel))) {
2908 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
2909 if (!application_state_handler || !application_state_handler->on_hangup ||
2910 (application_state_handler->on_hangup &&
2911 application_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
2912 midstate == switch_channel_get_state(session->channel))) {
2913 proceed++;
2914 continue;
2915 } else {
2916 proceed = 0;
2917 break;
2918 }
2919 }
2920 index = 0;
2921 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
2922 if (!application_state_handler || !application_state_handler->on_hangup ||
2923 (application_state_handler->on_hangup &&
2924 application_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
2925 midstate == switch_channel_get_state(session->channel))) {
2926 proceed++;
2927 continue;
2928 } else {
2929 proceed = 0;
2930 break;
2931 }
2932 }
2933
2934 if (proceed) {
2935 switch_core_standard_on_hangup(session);
2936 }
2937 }
2938 goto done;
2939 case CS_INIT: /* Basic setup tasks */
2940 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State INIT\n", switch_channel_get_name(session->channel));
2941 if (!driver_state_handler->on_init ||
2942 (driver_state_handler->on_init &&
2943 driver_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
2944 midstate == switch_channel_get_state(session->channel))) {
2945 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
2946 if (!application_state_handler || !application_state_handler->on_init ||
2947 (application_state_handler->on_init &&
2948 application_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
2949 midstate == switch_channel_get_state(session->channel))) {
2950 proceed++;
2951 continue;
2952 } else {
2953 proceed = 0;
2954 break;
2955 }
2956 }
2957 index = 0;
2958 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
2959 if (!application_state_handler || !application_state_handler->on_init ||
2960 (application_state_handler->on_init &&
2961 application_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
2962 midstate == switch_channel_get_state(session->channel))) {
2963 proceed++;
2964 continue;
2965 } else {
2966 proceed = 0;
2967 break;
2968 }
2969 }
2970 if (proceed) {
2971 switch_core_standard_on_init(session);
2972 }
2973 }
2974 break;
2975 case CS_RING: /* Look for a dialplan and find something to do */
2976 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State RING\n", switch_channel_get_name(session->channel));
2977 if (!driver_state_handler->on_ring ||
2978 (driver_state_handler->on_ring &&
2979 driver_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
2980 midstate == switch_channel_get_state(session->channel))) {
2981 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
2982 if (!application_state_handler || !application_state_handler->on_ring ||
2983 (application_state_handler->on_ring &&
2984 application_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
2985 midstate == switch_channel_get_state(session->channel))) {
2986 proceed++;
2987 continue;
2988 } else {
2989 proceed = 0;
2990 break;
2991 }
2992 }
2993 index = 0;
2994 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
2995 if (!application_state_handler || !application_state_handler->on_ring ||
2996 (application_state_handler->on_ring &&
2997 application_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
2998 midstate == switch_channel_get_state(session->channel))) {
2999 proceed++;
3000 continue;
3001 } else {
3002 proceed = 0;
3003 break;
3004 }
3005 }
3006 if (proceed) {
3007 switch_core_standard_on_ring(session);
3008 }
3009 }
3010 break;
3011 case CS_EXECUTE: /* Execute an Operation */
3012 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State EXECUTE\n", switch_channel_get_name(session->channel));
3013 if (!driver_state_handler->on_execute ||
3014 (driver_state_handler->on_execute &&
3015 driver_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
3016 midstate == switch_channel_get_state(session->channel))) {
3017 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
3018 if (!application_state_handler || !application_state_handler->on_execute ||
3019 (application_state_handler->on_execute &&
3020 application_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
3021 midstate == switch_channel_get_state(session->channel))) {
3022 proceed++;
3023 continue;
3024 } else {
3025 proceed = 0;
3026 break;
3027 }
3028 }
3029 index = 0;
3030 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
3031 if (!application_state_handler || !application_state_handler->on_execute ||
3032 (application_state_handler->on_execute &&
3033 application_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
3034 midstate == switch_channel_get_state(session->channel))) {
3035 proceed++;
3036 continue;
3037 } else {
3038 proceed = 0;
3039 break;
3040 }
3041 }
3042 if (proceed) {
3043 switch_core_standard_on_execute(session);
3044 }
3045 }
3046 break;
3047 case CS_LOOPBACK: /* loop all data back to source */
3048 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State LOOPBACK\n", switch_channel_get_name(session->channel));
3049 if (!driver_state_handler->on_loopback ||
3050 (driver_state_handler->on_loopback &&
3051 driver_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
3052 midstate == switch_channel_get_state(session->channel))) {
3053 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
3054 if (!application_state_handler || !application_state_handler->on_loopback ||
3055 (application_state_handler->on_loopback &&
3056 application_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
3057 midstate == switch_channel_get_state(session->channel))) {
3058 proceed++;
3059 continue;
3060 } else {
3061 proceed = 0;
3062 break;
3063 }
3064 }
3065 index = 0;
3066 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
3067 if (!application_state_handler || !application_state_handler->on_loopback ||
3068 (application_state_handler->on_loopback &&
3069 application_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
3070 midstate == switch_channel_get_state(session->channel))) {
3071 proceed++;
3072 continue;
3073 } else {
3074 proceed = 0;
3075 break;
3076 }
3077 }
3078 if (proceed) {
3079 switch_core_standard_on_loopback(session);
3080 }
3081 }
3082 break;
3083 case CS_TRANSMIT: /* send/recieve data to/from another channel */
3084 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State TRANSMIT\n", switch_channel_get_name(session->channel));
3085 if (!driver_state_handler->on_transmit ||
3086 (driver_state_handler->on_transmit &&
3087 driver_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
3088 midstate == switch_channel_get_state(session->channel))) {
3089
3090 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
3091 if (!application_state_handler || !application_state_handler->on_transmit ||
3092 (application_state_handler->on_transmit &&
3093 application_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
3094 midstate == switch_channel_get_state(session->channel))) {
3095 proceed++;
3096 continue;
3097 } else {
3098 proceed = 0;
3099 break;
3100 }
3101 }
3102 index = 0;
3103 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
3104 if (!application_state_handler || !application_state_handler->on_transmit ||
3105 (application_state_handler->on_transmit &&
3106 application_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
3107 midstate == switch_channel_get_state(session->channel))) {
3108 proceed++;
3109 continue;
3110 } else {
3111 proceed = 0;
3112 break;
3113 }
3114 }
3115 if (proceed) {
3116 switch_core_standard_on_transmit(session);
3117 }
3118 }
3119 break;
3120 case CS_HOLD: /* wait in limbo */
3121 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State HOLD\n", switch_channel_get_name(session->channel));
3122 if (!driver_state_handler->on_hold ||
3123 (driver_state_handler->on_hold &&
3124 driver_state_handler->on_hold(session) == SWITCH_STATUS_SUCCESS &&
3125 midstate == switch_channel_get_state(session->channel))) {
3126
3127 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
3128 if (!application_state_handler || !application_state_handler->on_hold ||
3129 (application_state_handler->on_hold &&
3130 application_state_handler->on_hold(session) == SWITCH_STATUS_SUCCESS &&
3131 midstate == switch_channel_get_state(session->channel))) {
3132 proceed++;
3133 continue;
3134 } else {
3135 proceed = 0;
3136 break;
3137 }
3138 }
3139 index = 0;
3140 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
3141 if (!application_state_handler || !application_state_handler->on_hold ||
3142 (application_state_handler->on_hold &&
3143 application_state_handler->on_hold(session) == SWITCH_STATUS_SUCCESS &&
3144 midstate == switch_channel_get_state(session->channel))) {
3145 proceed++;
3146 continue;
3147 } else {
3148 proceed = 0;
3149 break;
3150 }
3151 }
3152 if (proceed) {
3153 switch_core_standard_on_hold(session);
3154 }
3155 }
3156 break;
3157 case CS_HIBERNATE: /* wait in limbo */
3158 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State HIBERNATE\n", switch_channel_get_name(session->channel));
3159 if (!driver_state_handler->on_hibernate ||
3160 (driver_state_handler->on_hibernate &&
3161 driver_state_handler->on_hibernate(session) == SWITCH_STATUS_SUCCESS &&
3162 midstate == switch_channel_get_state(session->channel))) {
3163
3164 while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
3165 if (!application_state_handler || !application_state_handler->on_hibernate ||
3166 (application_state_handler->on_hibernate &&
3167 application_state_handler->on_hibernate(session) == SWITCH_STATUS_SUCCESS &&
3168 midstate == switch_channel_get_state(session->channel))) {
3169 proceed++;
3170 continue;
3171 } else {
3172 proceed = 0;
3173 break;
3174 }
3175 }
3176 index = 0;
3177 while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
3178 if (!application_state_handler || !application_state_handler->on_hibernate ||
3179 (application_state_handler->on_hibernate &&
3180 application_state_handler->on_hibernate(session) == SWITCH_STATUS_SUCCESS &&
3181 midstate == switch_channel_get_state(session->channel))) {
3182 proceed++;
3183 continue;
3184 } else {
3185 proceed = 0;
3186 break;
3187 }
3188 }
3189 if (proceed) {
3190 switch_core_standard_on_hibernate(session);
3191 }
3192 }
3193 break;
3194 }
3195
3196 if (midstate == CS_DONE) {
3197 break;
3198 }
3199
3200 laststate = midstate;
3201 }
3202
3203
3204 endstate = switch_channel_get_state(session->channel);
3205
3206
3207 if (midstate == endstate) {
3208 switch_thread_cond_wait(session->cond, session->mutex);
3209 }
3210
3211 }
3212 done:
3213 switch_mutex_unlock(session->mutex);
3214
3215#ifdef CRASH_PROT
3216 apr_hash_set(runtime.stack_table, &thread_id, sizeof(thread_id), NULL);
3217#endif
3218 session->thread_running = 0;
3219
3220}
3221
3222SWITCH_DECLARE(void) switch_core_session_destroy(switch_core_session_t **session)
3223{
3224 switch_memory_pool_t *pool;
3225 switch_event_t *event;
3226
3227 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Close Channel %s\n", switch_channel_get_name((*session)->channel));
3228
3229 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DESTROY) == SWITCH_STATUS_SUCCESS) {
3230 switch_channel_event_set_data((*session)->channel, event);
3231 switch_event_fire(&event);
3232 }
3233
3234 switch_core_media_bug_remove_all(*session);
3235 switch_buffer_destroy(&(*session)->raw_read_buffer);
3236 switch_buffer_destroy(&(*session)->raw_write_buffer);
3237 switch_channel_uninit((*session)->channel);
3238
3239 pool = (*session)->pool;
3240 *session = NULL;
3241 apr_pool_destroy(pool);
3242 pool = NULL;
3243
3244 switch_mutex_lock(runtime.session_table_mutex);
3245 if (runtime.session_count) {
3246 runtime.session_count--;
3247 }
3248 switch_mutex_unlock(runtime.session_table_mutex);
3249}
3250
3251SWITCH_DECLARE(switch_status_t) switch_core_hash_init(switch_hash_t **hash, switch_memory_pool_t *pool)
3252{
3253 assert(pool != NULL);
3254
3255 if ((*hash = apr_hash_make(pool)) != 0) {
3256 return SWITCH_STATUS_SUCCESS;
3257 }
3258
3259 return SWITCH_STATUS_GENERR;
3260}
3261
3262SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(switch_hash_t *hash)
3263{
3264 assert(hash != NULL);
3265 return SWITCH_STATUS_SUCCESS;
3266}
3267
3268SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup(switch_hash_t *hash, char *key, void *data)
3269{
3270 apr_hash_set(hash, switch_core_strdup(apr_hash_pool_get(hash), key), APR_HASH_KEY_STRING, data);
3271 return SWITCH_STATUS_SUCCESS;
3272}
3273
3274SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(switch_hash_t *hash, char *key, void *data)
3275{
3276 apr_hash_set(hash, key, APR_HASH_KEY_STRING, data);
3277 return SWITCH_STATUS_SUCCESS;
3278}
3279
3280SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t *hash, char *key)
3281{
3282 apr_hash_set(hash, key, APR_HASH_KEY_STRING, NULL);
3283 return SWITCH_STATUS_SUCCESS;
3284}
3285
3286SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t *hash, char *key)
3287{
3288 return apr_hash_get(hash, key, APR_HASH_KEY_STRING);
3289}
3290
3291/* This function abstracts the thread creation for modules by allowing you to pass a function ptr and
3292 a void object and trust that that the function will be run in a thread with arg This lets
3293 you request and activate a thread without giving up any knowledge about what is in the thread
3294 neither the core nor the calling module know anything about each other.
3295
3296 This thread is expected to never exit until the application exits so the func is responsible
3297 to make sure that is the case.
3298
3299 The typical use for this is so switch_loadable_module.c can start up a thread for each module
3300 passing the table of module methods as a session obj into the core without actually allowing
3301 the core to have any clue and keeping switch_loadable_module.c from needing any thread code.
3302
3303*/
3304
3305SWITCH_DECLARE(void) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool)
3306{
3307 switch_thread_t *thread;
3308 switch_threadattr_t *thd_attr = NULL;
3309 switch_core_thread_session_t *ts;
3310 int mypool;
3311
3312 mypool = pool ? 0 : 1;
3313
3314 if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
3315 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n");
3316 return;
3317 }
3318
3319 switch_threadattr_create(&thd_attr, pool);
3320 switch_threadattr_detach_set(thd_attr, 1);
3321
3322 if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) {
3323 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n");
3324 } else {
3325 if (mypool) {
3326 ts->pool = pool;
3327 }
3328 ts->objs[0] = obj;
3329 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3330 switch_thread_create(&thread, thd_attr, func, ts, pool);
3331 }
3332
3333}
3334
3335static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj)
3336{
3337 switch_core_session_t *session = obj;
3338 session->thread = thread;
3339 snprintf(session->name, sizeof(session->name), "%u", session->id);
3340 switch_mutex_lock(runtime.session_table_mutex);
3341 session->id = runtime.session_id++;
3342 switch_core_hash_insert(runtime.session_table, session->uuid_str, session);
3343 switch_mutex_unlock(runtime.session_table_mutex);
3344
3345 switch_core_session_run(session);
3346 switch_core_media_bug_remove_all(session);
3347 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %u (%s) Locked, Waiting on external entities\n", session->id, switch_channel_get_name(session->channel));
3348 switch_core_session_write_lock(session);
3349 switch_core_session_rwunlock(session);
3350
3351 switch_mutex_lock(runtime.session_table_mutex);
3352 switch_core_hash_delete(runtime.session_table, session->uuid_str);
3353 switch_mutex_unlock(runtime.session_table_mutex);
3354 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Session %u (%s) Ended\n", session->id, switch_channel_get_name(session->channel));
3355 switch_core_session_destroy(&session);
3356 return NULL;
3357}
3358
3359
3360SWITCH_DECLARE(void) switch_core_session_thread_launch(switch_core_session_t *session)
3361{
3362 switch_thread_t *thread;
3363 switch_threadattr_t *thd_attr;;
3364 switch_threadattr_create(&thd_attr, session->pool);
3365 switch_threadattr_detach_set(thd_attr, 1);
3366
3367 if (! session->thread_running) {
3368 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3369 if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) != SWITCH_STATUS_SUCCESS) {
3370 switch_core_session_destroy(&session);
3371 }
3372 }
3373}
3374
3375
3376SWITCH_DECLARE(void) switch_core_session_launch_thread(switch_core_session_t *session, switch_thread_start_t func,
3377 void *obj)
3378{
3379 switch_thread_t *thread;
3380 switch_threadattr_t *thd_attr = NULL;
3381 switch_threadattr_create(&thd_attr, session->pool);
3382 switch_threadattr_detach_set(thd_attr, 1);
3383
3384 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3385 switch_thread_create(&thread, thd_attr, func, obj, session->pool);
3386
3387}
3388
3389
3390SWITCH_DECLARE(void *) switch_core_alloc(switch_memory_pool_t *pool, switch_size_t memory)
3391{
3392 void *ptr = NULL;
3393 assert(pool != NULL);
3394
3395#ifdef DEBUG_ALLOC
3396 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Allocate %d\n", memory);
3397 //assert(memory < 600000);
3398#endif
3399
3400 if ((ptr = apr_palloc(pool, memory)) != 0) {
3401 memset(ptr, 0, memory);
3402 }
3403 return ptr;
3404}
3405
3406SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request(const switch_endpoint_interface_t *endpoint_interface,
3407 switch_memory_pool_t *pool)
3408{
3409 switch_memory_pool_t *usepool;
3410 switch_core_session_t *session;
3411 switch_uuid_t uuid;
3412 uint32_t count = 0;
3413
3414 assert(endpoint_interface != NULL);
3415
3416 switch_mutex_lock(runtime.session_table_mutex);
3417 count = runtime.session_count;
3418 switch_mutex_unlock(runtime.session_table_mutex);
3419
3420 if ((count + 1) > runtime.session_limit) {
3421 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit!\n");
3422 return NULL;
3423 }
3424
3425 if (runtime.no_new_sessions || runtime.shutting_down) {
3426 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Read my lips: no new sessions!\n");
3427 return NULL;
3428 }
3429
3430 if (pool) {
3431 usepool = pool;
3432 } else if (switch_core_new_memory_pool(&usepool) != SWITCH_STATUS_SUCCESS) {
3433 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n");
3434 return NULL;
3435 }
3436
3437 if ((session = switch_core_alloc(usepool, sizeof(switch_core_session_t))) == 0) {
3438 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate session\n");
3439 apr_pool_destroy(usepool);
3440 return NULL;
3441 }
3442
3443 if (switch_channel_alloc(&session->channel, usepool) != SWITCH_STATUS_SUCCESS) {
3444 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate channel structure\n");
3445 apr_pool_destroy(usepool);
3446 return NULL;
3447 }
3448
3449 switch_channel_init(session->channel, session, CS_NEW, 0);
3450
3451 /* The session *IS* the pool you may not alter it because you have no idea how
3452 its all private it will be passed to the thread run function */
3453
3454 switch_uuid_get(&uuid);
3455 switch_uuid_format(session->uuid_str, &uuid);
3456
3457 session->pool = usepool;
3458 session->endpoint_interface = endpoint_interface;
3459
3460 session->raw_write_frame.data = session->raw_write_buf;
3461 session->raw_write_frame.buflen = sizeof(session->raw_write_buf);
3462 session->raw_read_frame.data = session->raw_read_buf;
3463 session->raw_read_frame.buflen = sizeof(session->raw_read_buf);
3464
3465
3466 session->enc_write_frame.data = session->enc_write_buf;
3467 session->enc_write_frame.buflen = sizeof(session->enc_write_buf);
3468 session->enc_read_frame.data = session->enc_read_buf;
3469 session->enc_read_frame.buflen = sizeof(session->enc_read_buf);
3470
3471 switch_mutex_init(&session->mutex, SWITCH_MUTEX_NESTED, session->pool);
3472 switch_thread_rwlock_create(&session->bug_rwlock, session->pool);
3473 switch_thread_cond_create(&session->cond, session->pool);
3474 switch_thread_rwlock_create(&session->rwlock, session->pool);
3475
3476 switch_mutex_lock(runtime.session_table_mutex);
3477 runtime.session_count++;
3478 switch_mutex_unlock(runtime.session_table_mutex);
3479 return session;
3480}
3481
3482SWITCH_DECLARE(uint32_t) switch_core_session_count(void)
3483{
3484 return runtime.session_count;
3485}
3486
3487SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_by_name(char *endpoint_name, switch_memory_pool_t *pool)
3488{
3489 const switch_endpoint_interface_t *endpoint_interface;
3490
3491 if ((endpoint_interface = switch_loadable_module_get_endpoint_interface(endpoint_name)) == 0) {
3492 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not locate channel type %s\n", endpoint_name);
3493 return NULL;
3494 }
3495
3496 return switch_core_session_request(endpoint_interface, pool);
3497}
3498
3499SWITCH_DECLARE(switch_status_t) switch_core_db_persistant_execute(switch_core_db_t *db, char *sql, uint32_t retries)
3500{
3501 char *errmsg;
3502 switch_status_t status = SWITCH_STATUS_FALSE;
3503 uint8_t forever = 0;
3504
3505 if (!retries) {
3506 forever = 1;
3507 retries = 1000;
3508 }
3509
3510 while(retries > 0) {
3511 switch_core_db_exec(
3512 db,
3513 sql,
3514 NULL,
3515 NULL,
3516 &errmsg
3517 );
3518 if (errmsg) {
3519 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg);
3520 switch_core_db_free(errmsg);
3521 switch_yield(100000);
3522 retries--;
3523 if (retries == 0 && forever) {
3524 retries = 1000;
3525 continue;
3526 }
3527 } else {
3528 status = SWITCH_STATUS_SUCCESS;
3529 break;
3530 }
3531 }
3532
3533 return status;
3534}
3535
3536#ifdef DO_EVENTS
3537#define SQLLEN 1024 * 64
3538static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, void *obj)
3539{
3540 void *pop;
3541 uint32_t itterations = 0;
3542 uint8_t trans = 0, nothing_in_queue = 0;
3543 uint32_t freq = 1000, target = 1000;
3544 uint32_t len = 0;
3545 uint32_t sql_len = SQLLEN;
3546 char *sqlbuf = (char *) malloc(sql_len);
3547
3548 if (!runtime.event_db) {
3549 runtime.event_db = switch_core_db_handle();
3550 }
3551 switch_queue_create(&runtime.sql_queue, SWITCH_SQL_QUEUE_LEN, runtime.memory_pool);
3552
3553 for(;;) {
3554 if (switch_queue_trypop(runtime.sql_queue, &pop) == SWITCH_STATUS_SUCCESS) {
3555 char *sql = (char *) pop;
3556 uint32_t newlen;
3557
3558 if (sql) {
3559 if (itterations == 0) {
3560 char *isql = "begin transaction CORE1;\n";
3561 switch_core_db_persistant_execute(runtime.event_db, isql, 0);
3562 trans = 1;
3563
3564 }
3565
3566 itterations++;
3567 newlen = (uint32_t)strlen(sql) + 2;
3568 if (len + newlen > sql_len) {
3569 sql_len = len + SQLLEN;
3570 if (!(sqlbuf = realloc(sqlbuf, sql_len))) {
3571 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n");
3572 break;
3573 }
3574 }
3575 snprintf(sqlbuf + len, sql_len - len, "%s;\n", sql);
3576 len += newlen;
3577 switch_core_db_free(sql);
3578 } else {
3579 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SQL thread ending\n");
3580 break;
3581 }
3582 } else {
3583 nothing_in_queue = 1;
3584 }
3585
3586
3587 if (trans && ((itterations == target) || nothing_in_queue)) {
3588 char *isql = "end transaction CORE1";
3589
3590 switch_core_db_persistant_execute(runtime.event_db, sqlbuf, 0);
3591 switch_core_db_persistant_execute(runtime.event_db, isql, 0);
3592 itterations = 0;
3593 trans = 0;
3594 nothing_in_queue = 0;
3595 len = 0;
3596 *sqlbuf = '\0';
3597 }
3598
3599 if (nothing_in_queue) {
3600 switch_yield(freq);
3601 }
3602 }
3603
3604
3605 free(sqlbuf);
3606 return NULL;
3607}
3608
3609
3610static void switch_core_sql_thread_launch(void)
3611{
3612 switch_thread_t *thread;
3613 switch_threadattr_t *thd_attr;;
3614
3615 assert(runtime.memory_pool != NULL);
3616
3617 switch_threadattr_create(&thd_attr, runtime.memory_pool);
3618 switch_threadattr_detach_set(thd_attr, 1);
3619 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3620 switch_thread_create(&thread, thd_attr, switch_core_sql_thread, NULL, runtime.memory_pool);
3621
3622}
3623
3624static void core_event_handler(switch_event_t *event)
3625{
3626 char *sql = NULL;
3627
3628 switch (event->event_id) {
3629 case SWITCH_EVENT_CHANNEL_DESTROY:
3630 sql = switch_mprintf("delete from channels where uuid='%s'", switch_event_get_header(event, "unique-id"));
3631 break;
3632 case SWITCH_EVENT_CHANNEL_CREATE:
3633 sql = switch_mprintf("insert into channels (uuid,created,name,state) values('%q','%q','%q','%q')",
3634 switch_event_get_header(event, "unique-id"),
3635 switch_event_get_header(event, "event-date-local"),
3636 switch_event_get_header(event, "channel-name"),
3637 switch_event_get_header(event, "channel-state")
3638 );
3639 break;
3640 case SWITCH_EVENT_CODEC:
3641 sql = switch_mprintf("update channels set read_codec='%q',read_rate='%q',write_codec='%q',write_rate='%q' where uuid='%q'",
3642 switch_event_get_header(event, "channel-read-codec-name"),
3643 switch_event_get_header(event, "channel-read-codec-rate"),
3644 switch_event_get_header(event, "channel-write-codec-name"),
3645 switch_event_get_header(event, "channel-write-codec-rate"),
3646 switch_event_get_header(event, "unique-id"));
3647 break;
3648 case SWITCH_EVENT_CHANNEL_EXECUTE:
3649 sql = switch_mprintf("update channels set application='%q',application_data='%q' where uuid='%q'",
3650 switch_event_get_header(event, "application"),
3651 switch_event_get_header(event, "application-data"),
3652 switch_event_get_header(event, "unique-id")
3653 );
3654 break;
3655 case SWITCH_EVENT_CHANNEL_STATE:
3656 if (event) {
3657 char *state = switch_event_get_header(event, "channel-state-number");
3658 switch_channel_state_t state_i = atoi(state);
3659
3660 switch(state_i) {
3661 case CS_HANGUP:
3662 case CS_DONE:
3663 break;
3664 case CS_RING:
3665 sql = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',ip_addr='%s',dest='%q'"
3666 "where uuid='%s'",
3667 switch_event_get_header(event, "channel-state"),
3668 switch_event_get_header(event, "caller-caller-id-name"),
3669 switch_event_get_header(event, "caller-caller-id-number"),
3670 switch_event_get_header(event, "caller-network-addr"),
3671 switch_event_get_header(event, "caller-destination-number"),
3672 switch_event_get_header(event, "unique-id")
3673 );
3674 break;
3675 default:
3676 sql = switch_mprintf("update channels set state='%s' where uuid='%s'",
3677 switch_event_get_header(event, "channel-state"),
3678 switch_event_get_header(event, "unique-id")
3679 );
3680 break;
3681 }
3682
3683 }
3684 break;
3685 case SWITCH_EVENT_CHANNEL_BRIDGE:
3686 sql = switch_mprintf("insert into calls values ('%s','%q','%q','%q','%q','%s','%q','%q','%q','%q','%s')",
3687 switch_event_get_header(event, "event-calling-function"),
3688 switch_event_get_header(event, "caller-caller-id-name"),
3689 switch_event_get_header(event, "caller-caller-id-number"),
3690 switch_event_get_header(event, "caller-destination-number"),
3691 switch_event_get_header(event, "caller-channel-name"),
3692 switch_event_get_header(event, "caller-unique-id"),
3693 switch_event_get_header(event, "originatee-caller-id-name"),
3694 switch_event_get_header(event, "originatee-caller-id-number"),
3695 switch_event_get_header(event, "originatee-destination-number"),
3696 switch_event_get_header(event, "originatee-channel-name"),
3697 switch_event_get_header(event, "originatee-unique-id")
3698 );
3699 break;
3700 case SWITCH_EVENT_CHANNEL_UNBRIDGE:
3701 sql = switch_mprintf("delete from calls where caller_uuid='%s'", switch_event_get_header(event, "caller-unique-id"));
3702 break;
3703 case SWITCH_EVENT_SHUTDOWN:
3704 sql = switch_mprintf("delete from channels;delete from interfaces;delete from calls");
3705 break;
3706 case SWITCH_EVENT_LOG:
3707 return;
3708 case SWITCH_EVENT_MODULE_LOAD:
3709 sql = switch_mprintf("insert into interfaces (type,name,description,syntax) values('%q','%q','%q','%q')",
3710 switch_event_get_header(event, "type"),
3711 switch_event_get_header(event, "name"),
3712 switch_event_get_header(event, "description"),
3713 switch_event_get_header(event, "syntax")
3714 );
3715 break;
3716 default:
3717 break;
3718 }
3719
3720 if (sql) {
3721 switch_queue_push(runtime.sql_queue, sql);
3722 sql = NULL;
3723 }
3724}
3725#endif
3726
3727SWITCH_DECLARE(void) switch_core_set_globals(void)
3728{
3729#ifdef WIN32
3730#define BUFSIZE 1024
3731 char lpPathBuffer[BUFSIZE];
3732 DWORD dwBufSize=BUFSIZE;
3733 char exePath[1024];
3734 char *lastbacklash;
3735 GetModuleFileName( NULL, exePath, BUFSIZE );
3736 lastbacklash = strrchr( exePath, '\\');
3737 exePath[(lastbacklash - exePath + 1)] = '\0';
3738 if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) {
3739 snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", exePath);
3740 }
3741 if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) {
3742 snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%smod", exePath);
3743 }
3744 if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) {
3745 snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%sconf", exePath);
3746 }
3747 if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) {
3748 snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%slog", exePath);
3749 }
3750 if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) {
3751 snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%sdb", exePath);
3752 }
3753 if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) {
3754 snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%sscripts", exePath);
3755 }
3756 if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
3757 snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%shtdocs", exePath);
3758 }
3759 if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) {
3760 snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%sgrammar", exePath);
3761 }
3762#else
3763 SWITCH_GLOBAL_dirs.base_dir = SWITCH_PREFIX_DIR;
3764 SWITCH_GLOBAL_dirs.mod_dir = SWITCH_MOD_DIR;
3765 SWITCH_GLOBAL_dirs.conf_dir = SWITCH_CONF_DIR;
3766 SWITCH_GLOBAL_dirs.log_dir = SWITCH_LOG_DIR;
3767 SWITCH_GLOBAL_dirs.db_dir = SWITCH_DB_DIR;
3768 SWITCH_GLOBAL_dirs.script_dir = SWITCH_SCRIPT_DIR;
3769 SWITCH_GLOBAL_dirs.htdocs_dir = SWITCH_HTDOCS_DIR;
3770 SWITCH_GLOBAL_dirs.grammar_dir = SWITCH_GRAMMAR_DIR;
3771#endif
3772#ifdef SWITCH_TEMP_DIR
3773 SWITCH_GLOBAL_dirs.temp_dir = SWITCH_TEMP_DIR;
3774#else
3775#ifdef WIN32
3776 GetTempPath(dwBufSize, lpPathBuffer);
3777 if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
3778 snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", lpPathBuffer);
3779 }
3780#else
3781 SWITCH_GLOBAL_dirs.temp_dir = "/tmp/";
3782#endif
3783#endif
3784}
3785
3786
3787SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new_limit)
3788{
3789 if (new_limit) {
3790 runtime.session_limit = new_limit;
3791 }
3792
3793 return runtime.session_limit;
3794}
3795
3796
3797SWITCH_DECLARE(int32_t) set_high_priority(void)
3798{
3799#ifdef __linux__
3800 struct sched_param sched = {0};
3801 sched.sched_priority = 1;
3802 if (sched_setscheduler(0, SCHED_RR, &sched)) {
3803 sched.sched_priority = 0;
3804 if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
3805 return -1;
3806 }
3807 }
3808#endif
3809
3810#ifdef WIN32
3811 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
3812#else
3813 nice(-10);
3814#endif
3815
3816#define USE_MLOCKALL
3817#ifdef HAVE_MLOCKALL
3818#ifdef USE_MLOCKALL
3819 mlockall(MCL_CURRENT|MCL_FUTURE);
3820#endif
3821#endif
3822 return 0;
3823}
3824
3825SWITCH_DECLARE(void) switch_core_runtime_loop(int bg)
3826{
3827#ifdef WIN32
3828 HANDLE shutdown_event;
3829 char path[256] = "";
3830#endif
3831 if (bg) {
3832 bg = 0;
3833#ifdef WIN32
3834 snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());
3835 shutdown_event = CreateEvent(NULL, FALSE, FALSE, path);
3836 WaitForSingleObject(shutdown_event, INFINITE);
3837#else
3838 runtime.running = 1;
3839 while(runtime.running) {
3840 switch_yield(1000000);
3841 }
3842#endif
3843 } else {
3844 /* wait for console input */
3845 switch_console_loop();
3846 }
3847}
3848
3849
3850SWITCH_DECLARE(switch_status_t) switch_core_init(char *console, const char **err)
3851{
3852 switch_xml_t xml = NULL, cfg = NULL;
3853 memset(&runtime, 0, sizeof(runtime));
3854 runtime.session_limit = 1000;
3855
3856 switch_core_set_globals();
3857
3858 /* INIT APR and Create the pool context */
3859 if (apr_initialize() != SWITCH_STATUS_SUCCESS) {
3860 apr_terminate();
3861 *err = "FATAL ERROR! Could not initilize APR\n";
3862 return SWITCH_STATUS_MEMERR;
3863 }
3864
3865 if (apr_pool_create(&runtime.memory_pool, NULL) != SWITCH_STATUS_SUCCESS) {
3866 apr_terminate();
3867 *err = "FATAL ERROR! Could not allocate memory pool\n";
3868 return SWITCH_STATUS_MEMERR;
3869 }
3870
3871 switch_core_hash_init(&runtime.global_vars, runtime.memory_pool);
3872
3873 if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {
3874 apr_terminate();
3875 return SWITCH_STATUS_MEMERR;
3876 }
3877
3878
3879 if ((xml = switch_xml_open_cfg("switch.conf", &cfg, NULL))) {
3880 switch_xml_t settings, param;
3881
3882 if ((settings = switch_xml_child(cfg, "settings"))) {
3883 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
3884 char *var = (char *) switch_xml_attr_soft(param, "name");
3885 char *val = (char *) switch_xml_attr_soft(param, "value");
3886
3887 if (!strcasecmp(var, "max-sessions")) {
3888 runtime.session_limit = atoi(val);
3889 }
3890 }
3891 }
3892
3893 if ((settings = switch_xml_child(cfg, "variables"))) {
3894 for (param = switch_xml_child(settings, "variable"); param; param = param->next) {
3895 char *var = (char *) switch_xml_attr_soft(param, "name");
3896 char *val = (char *) switch_xml_attr_soft(param, "value");
3897 char *varr = NULL, *vall = NULL;
3898
3899 varr = switch_core_strdup(runtime.memory_pool, var);
3900 vall = switch_core_strdup(runtime.memory_pool, val);
3901 switch_core_hash_insert(runtime.global_vars, varr, vall);
3902 }
3903 }
3904 switch_xml_free(xml);
3905 }
3906
3907 *err = NULL;
3908
3909 if(console) {
3910 if (*console != '/') {
3911 char path[265];
3912 snprintf(path, sizeof(path), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, console);
3913 console = path;
3914 }
3915 if (switch_core_set_console(console) != SWITCH_STATUS_SUCCESS) {
3916 *err = "FATAL ERROR! Could not open console\n";
3917 apr_terminate();
3918 return SWITCH_STATUS_GENERR;
3919 }
3920 } else {
3921 runtime.console = stdout;
3922 }
3923
3924 assert(runtime.memory_pool != NULL);
3925 switch_log_init(runtime.memory_pool);
3926
3927#ifdef DO_EVENTS
3928 switch_core_sql_thread_launch();
3929#endif
3930
3931 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Allocated memory pool. Sessions are %u bytes\n", sizeof(switch_core_session_t));
3932 switch_event_init(runtime.memory_pool);
3933 switch_rtp_init(runtime.memory_pool);
3934
3935 /* Activate SQL database */
3936 if ((runtime.db = switch_core_db_handle()) == 0 ) {
3937 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
3938 } else {
3939 char create_channels_sql[] =
3940 "CREATE TABLE channels (\n"
3941 " uuid VARCHAR(255),\n"
3942 " created VARCHAR(255),\n"
3943 " name VARCHAR(255),\n"
3944 " state VARCHAR(255),\n"
3945 " cid_name VARCHAR(255),\n"
3946 " cid_num VARCHAR(255),\n"
3947 " ip_addr VARCHAR(255),\n"
3948 " dest VARCHAR(255),\n"
3949 " application VARCHAR(255),\n"
3950 " application_data VARCHAR(255),\n"
3951 " read_codec VARCHAR(255),\n"
3952 " read_rate VARCHAR(255),\n"
3953 " write_codec VARCHAR(255),\n"
3954 " write_rate VARCHAR(255)\n"
3955 ");\n";
3956 char create_calls_sql[] =
3957 "CREATE TABLE calls (\n"
3958 " function VARCHAR(255),\n"
3959 " caller_cid_name VARCHAR(255),\n"
3960 " caller_cid_num VARCHAR(255),\n"
3961 " caller_dest_num VARCHAR(255),\n"
3962 " caller_chan_name VARCHAR(255),\n"
3963 " caller_uuid VARCHAR(255),\n"
3964 " callee_cid_name VARCHAR(255),\n"
3965 " callee_cid_num VARCHAR(255),\n"
3966 " callee_dest_num VARCHAR(255),\n"
3967 " callee_chan_name VARCHAR(255),\n"
3968 " callee_uuid VARCHAR(255)\n"
3969 ");\n";
3970 char create_interfaces_sql[] =
3971 "CREATE TABLE interfaces (\n"
3972 " type VARCHAR(255),\n"
3973 " name VARCHAR(255),\n"
3974 " description VARCHAR(255),\n"
3975 " syntax VARCHAR(255)\n"
3976 ");\n";
3977
3978 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening DB\n");
3979 switch_core_db_exec(runtime.db, "drop table channels", NULL, NULL, NULL);
3980 switch_core_db_exec(runtime.db, "drop table calls", NULL, NULL, NULL);
3981 switch_core_db_exec(runtime.db, "drop table interfaces", NULL, NULL, NULL);
3982 switch_core_db_exec(runtime.db, create_channels_sql, NULL, NULL, NULL);
3983 switch_core_db_exec(runtime.db, create_calls_sql, NULL, NULL, NULL);
3984 switch_core_db_exec(runtime.db, create_interfaces_sql, NULL, NULL, NULL);
3985#ifdef DO_EVENTS
3986 if (switch_event_bind("core_db", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, core_event_handler, NULL) !=
3987 SWITCH_STATUS_SUCCESS) {
3988 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event handler!\n");
3989 }
3990#endif
3991 }
3992
3993 runtime.session_id = 1;
3994 runtime.running = 1;
3995 switch_core_hash_init(&runtime.session_table, runtime.memory_pool);
3996 switch_mutex_init(&runtime.session_table_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
3997#ifdef CRASH_PROT
3998 switch_core_hash_init(&runtime.stack_table, runtime.memory_pool);
3999#endif
4000 runtime.initiated = switch_time_now();
4001 return SWITCH_STATUS_SUCCESS;
4002}
4003
4004#ifdef SIGPIPE
4005static void handle_SIGPIPE(int sig)
4006{
4007 if(sig);
4008 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig Pipe!\n");
4009 return;
4010}
4011#endif
4012
4013#ifdef SIGPOLL
4014static void handle_SIGPOLL(int sig)
4015{
4016 if(sig);
4017 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig Poll!\n");
4018 return;
4019}
4020#endif
4021
4022#ifdef SIGIO
4023static void handle_SIGIO(int sig)
4024{
4025 if(sig);
4026 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig I/O!\n");
4027 return;
4028}
4029#endif
4030
4031#ifdef TRAP_BUS
4032static void handle_SIGBUS(int sig)
4033{
4034 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig BUS!\n");
4035 return;
4036}
4037#endif
4038
4039/* no ctl-c mofo */
4040static void handle_SIGINT(int sig)
4041{
4042 if (sig);
4043 return;
4044}
4045SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(char *console, const char **err)
4046{
4047 switch_event_t *event;
4048 if (switch_core_init(console, err) != SWITCH_STATUS_SUCCESS) {
4049 return SWITCH_STATUS_GENERR;
4050 }
4051
4052 /* set signal handlers */
4053 signal(SIGINT, handle_SIGINT);
4054#ifdef SIGPIPE
4055 signal(SIGPIPE, handle_SIGPIPE);
4056#endif
4057#ifdef SIGPOLL
4058 signal(SIGPIPE, handle_SIGPOLL);
4059#endif
4060#ifdef SIGIO
4061 signal(SIGPIPE, handle_SIGIO);
4062#endif
4063#ifdef TRAP_BUS
4064 signal(SIGBUS, handle_SIGBUS);
4065#endif
4066
4067 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n");
4068 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n");
4069 if (switch_loadable_module_init() != SWITCH_STATUS_SUCCESS) {
4070 *err = "Cannot load modules";
4071 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s", err);
4072 return SWITCH_STATUS_GENERR;
4073 }
4074
4075 if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
4076 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
4077 switch_event_fire(&event);
4078 }
4079
4080 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nFreeSWITCH Version %s Started.\nCrash Protection [%s]\nMax Sessions[%u]\n\n", SWITCH_VERSION_FULL, __CP, switch_core_session_limit(0));
4081 return SWITCH_STATUS_SUCCESS;
4082
4083}
4084
4085SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration)
4086{
4087 switch_time_t temp = total_ms / 1000;
4088 memset(duration, 0, sizeof(*duration));
4089 duration->mms = (uint32_t)(total_ms % 1000);
4090 duration->ms = (uint32_t)(temp % 1000);
4091 temp = temp / 1000;
4092 duration->sec = (uint32_t)(temp % 60);
4093 temp = temp / 60;
4094 duration->min = (uint32_t)(temp % 60);
4095 temp = temp / 60;
4096 duration->hr = (uint32_t)(temp % 24);
4097 temp = temp / 24;
4098 duration->day = (uint32_t)(temp % 365);
4099 duration->yr = (uint32_t)(temp / 365);
4100}
4101
4102SWITCH_DECLARE(switch_time_t) switch_core_uptime(void)
4103{
4104 return switch_time_now() - runtime.initiated;
4105}
4106
4107SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, uint32_t *val)
4108{
4109
4110 if (runtime.shutting_down) {
4111 return -1;
4112 }
4113
4114 switch (cmd) {
4115 case SCSC_PAUSE_INBOUND:
4116 runtime.no_new_sessions = *val;
4117 break;
4118 case SCSC_HUPALL:
4119 switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST);
4120 break;
4121 case SCSC_SHUTDOWN:
4122 runtime.running = 0;
4123 break;
4124 case SCSC_CHECK_RUNNING:
4125 *val = runtime.running;
4126 break;
4127 }
4128
4129 return 0;
4130}
4131
4132SWITCH_DECLARE(switch_status_t) switch_core_destroy(int vg)
4133{
4134 switch_event_t *event;
4135 if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) {
4136 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down");
4137 switch_event_fire(&event);
4138 }
4139 runtime.shutting_down = 1;
4140 runtime.no_new_sessions = 1;
4141
4142 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n");
4143 switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN);
4144 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n");
4145 switch_loadable_module_shutdown();
4146
4147 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n");
4148 switch_event_shutdown();
4149
4150 switch_queue_push(runtime.sql_queue, NULL);
4151
4152 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Waiting for unfinished SQL transactions\n");
4153 while (switch_queue_size(runtime.sql_queue) > 0) {
4154 switch_yield(10000);
4155 }
4156 switch_core_db_close(runtime.db);
4157 switch_core_db_close(runtime.event_db);
4158 switch_xml_destroy();
4159 if (vg) {
4160 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Full destruction of the core disabled for memory debugging purposes.\n");
4161 }
4162 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
4163 switch_log_shutdown();
4164
4165 if(runtime.console != stdout && runtime.console != stderr) {
4166 fclose(runtime.console);
4167 runtime.console = NULL;
4168 }
4169
4170 if (runtime.memory_pool) {
4171 apr_pool_destroy(runtime.memory_pool);
4172 if (!vg) {
4173 apr_terminate();
4174 }
4175 }
4176
4177#ifdef WIN32
4178 free(SWITCH_GLOBAL_dirs.base_dir);
4179 free(SWITCH_GLOBAL_dirs.mod_dir);
4180 free(SWITCH_GLOBAL_dirs.conf_dir);
4181 free(SWITCH_GLOBAL_dirs.log_dir);
4182 free(SWITCH_GLOBAL_dirs.db_dir);
4183 free(SWITCH_GLOBAL_dirs.script_dir);
4184 free(SWITCH_GLOBAL_dirs.htdocs_dir);
4185 free(SWITCH_GLOBAL_dirs.grammar_dir);
4186 free(SWITCH_GLOBAL_dirs.temp_dir);
4187#endif
4188
4189 return SWITCH_STATUS_SUCCESS;
4190}
4191
4192/* For Emacs:
4193 * Local Variables:
4194 * mode:c
4195 * indent-tabs-mode:nil
4196 * tab-width:4
4197 * c-basic-offset:4
4198 * End:
4199 * For VIM:
4200 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
4201 */
4202