FreeSWITCH API Documentation  1.7.0
switch_loadable_module.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Seven Du <dujinfang@gmail.com>
28  *
29  * switch_loadable_module.c -- Loadable Modules
30  *
31  */
32 
33 #include <switch.h>
34 
35 /* for apr_pstrcat */
36 #include <apr_strings.h>
37 
38 /* for apr_env_get and apr_env_set */
39 #include <apr_env.h>
40 
41 /* for apr file and directory handling */
42 #include <apr_file_io.h>
43 
44 typedef struct switch_file_node_s {
46  const char *interface_name;
49 
50 typedef struct switch_codec_node_s {
52  const char *interface_name;
55 
56 
58  char *key;
59  char *filename;
60  int perm;
63  switch_module_load_t switch_module_load;
64  switch_module_runtime_t switch_module_runtime;
65  switch_module_shutdown_t switch_module_shutdown;
70 };
71 
93 };
94 
97  const char **err);
98 static switch_status_t switch_loadable_module_load_module_ex(char *dir, char *fname, switch_bool_t runtime, switch_bool_t global, const char **err);
99 
101 {
102 
103 
106  switch_loadable_module_t *module = ts->objs[0];
107  int restarts;
108 
109  switch_assert(thread != NULL);
110  switch_assert(module != NULL);
111 
112  for (restarts = 0; status != SWITCH_STATUS_TERM && !module->shutting_down; restarts++) {
113  status = module->switch_module_runtime();
114  }
116 
117  if (ts->pool) {
119  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroying Pool for %s\n", module->module_interface->module_name);
121  }
122  switch_thread_exit(thread, 0);
123  return NULL;
124 }
125 
126 
128 {
130  void *val;
131  switch_loadable_module_t *module;
132 
135  switch_core_hash_this(hi, NULL, NULL, &val);
136  module = (switch_loadable_module_t *) val;
137 
138  if (module->switch_module_runtime) {
139  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Starting runtime thread for %s\n", module->module_interface->module_name);
141  }
142  }
144 }
145 
147 {
148  switch_event_t *event;
149  int added = 0;
150 
151  new_module->key = switch_core_strdup(new_module->pool, key);
152 
155 
156  if (new_module->module_interface->endpoint_interface) {
157  const switch_endpoint_interface_t *ptr;
158  for (ptr = new_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) {
159  if (!ptr->interface_name) {
160  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load endpoint interface from %s due to no interface name.\n", key);
161  } else {
162  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Endpoint '%s'\n", ptr->interface_name);
165  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "endpoint");
167  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
168  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
169  switch_event_fire(&event);
170  added++;
171  }
172  }
173  }
174  }
175 
176  if (new_module->module_interface->codec_interface) {
177  const switch_codec_implementation_t *impl;
178  const switch_codec_interface_t *ptr;
179 
180  for (ptr = new_module->module_interface->codec_interface; ptr; ptr = ptr->next) {
181  if (!ptr->interface_name) {
182  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load codec interface from %s due to no interface name.\n", key);
183  } else {
184  unsigned load_interface = 1;
185  switch_codec_node_t *node, *head;
186 
187  for (impl = ptr->implementations; impl; impl = impl->next) {
188  if (!impl->iananame) {
189  load_interface = 0;
191  "Failed to load codec interface %s from %s due to no iana name in an implementation.\n", ptr->interface_name,
192  key);
193  break;
194  }
196  load_interface = 0;
198  "Failed to load codec interface %s from %s due to bytes per frame %d exceeding buffer size %d.\n",
199  ptr->interface_name,
201  break;
202  }
203  }
204  if (load_interface) {
205  for (impl = ptr->implementations; impl; impl = impl->next) {
206  if (impl->bits_per_second) {
208  "Adding Codec %s %d %s %dhz %dms %dbps\n",
209  impl->iananame, impl->ianacode,
211  impl->microseconds_per_packet / 1000, impl->bits_per_second);
212  } else {
214  "Adding Codec %s %d %s %dhz %dms (VBR)\n",
215  impl->iananame, impl->ianacode,
217  }
218 
219  node = switch_core_alloc(new_module->pool, sizeof(*node));
220  node->ptr = ptr;
221  node->interface_name = switch_core_strdup(new_module->pool, new_module->module_interface->module_name);
223  node->next = head;
224  }
225 
226  switch_core_hash_insert(loadable_modules.codec_hash, impl->iananame, (const void *) node);
227  }
228 
230  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "codec");
232  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
233  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
235  switch_event_fire(&event);
236  added++;
237  }
238  }
239  }
240  }
241  }
242 
243  if (new_module->module_interface->dialplan_interface) {
244  const switch_dialplan_interface_t *ptr;
245 
246  for (ptr = new_module->module_interface->dialplan_interface; ptr; ptr = ptr->next) {
247  if (!ptr->interface_name) {
248  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load dialplan interface from %s due to no interface name.\n", key);
249  } else {
250  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Dialplan '%s'\n", ptr->interface_name);
252  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "dialplan");
254  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
255  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
256  switch_event_fire(&event);
257  added++;
258  }
260  }
261  }
262  }
263 
264  if (new_module->module_interface->timer_interface) {
265  const switch_timer_interface_t *ptr;
266 
267  for (ptr = new_module->module_interface->timer_interface; ptr; ptr = ptr->next) {
268  if (!ptr->interface_name) {
269  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load timer interface from %s due to no interface name.\n", key);
270  } else {
273  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "timer");
275  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
276  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
277  switch_event_fire(&event);
278  added++;
279  }
281  }
282  }
283  }
284 
285  if (new_module->module_interface->application_interface) {
287 
288  for (ptr = new_module->module_interface->application_interface; ptr; ptr = ptr->next) {
289  if (!ptr->interface_name) {
290  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load application interface from %s due to no interface name.\n", key);
291  } else {
292  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Application '%s'\n", ptr->interface_name);
294  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application");
298  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
299  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
300  switch_event_fire(&event);
301  added++;
302  }
304  }
305  }
306  }
307 
308  if (new_module->module_interface->chat_application_interface) {
310 
311  for (ptr = new_module->module_interface->chat_application_interface; ptr; ptr = ptr->next) {
312  if (!ptr->interface_name) {
313  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load application interface from %s due to no interface name.\n", key);
314  } else {
315  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Chat Application '%s'\n", ptr->interface_name);
317  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application");
321  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
322  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
323  switch_event_fire(&event);
324  added++;
325  }
327  }
328  }
329  }
330 
331  if (new_module->module_interface->api_interface) {
332  const switch_api_interface_t *ptr;
333 
334  for (ptr = new_module->module_interface->api_interface; ptr; ptr = ptr->next) {
335  if (!ptr->interface_name) {
336  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load api interface from %s due to no interface name.\n", key);
337  } else {
338  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding API Function '%s'\n", ptr->interface_name);
344  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
345  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
346  switch_event_fire(&event);
347  added++;
348  }
350  }
351  }
352  }
353 
354  if (new_module->module_interface->json_api_interface) {
355  const switch_json_api_interface_t *ptr;
356 
357  for (ptr = new_module->module_interface->json_api_interface; ptr; ptr = ptr->next) {
358  if (!ptr->interface_name) {
359  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load JSON api interface from %s due to no interface name.\n", key);
360  } else {
361  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding JSON API Function '%s'\n", ptr->interface_name);
363  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "json_api");
367  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
368  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
369  switch_event_fire(&event);
370  added++;
371  }
373  }
374  }
375  }
376 
377  if (new_module->module_interface->file_interface) {
378  const switch_file_interface_t *ptr;
379 
380  for (ptr = new_module->module_interface->file_interface; ptr; ptr = ptr->next) {
381  if (!ptr->interface_name) {
382  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load file interface from %s due to no interface name.\n", key);
383  } else if (!ptr->extens) {
384  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load file interface from %s due to no file extensions.\n", key);
385  } else {
386  int i;
387  switch_file_node_t *node, *head;
388 
389  for (i = 0; ptr->extens[i]; i++) {
390  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding File Format '%s'\n", ptr->extens[i]);
392  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "file");
394  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
395  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
397  switch_event_fire(&event);
398  added++;
399  }
400  node = switch_core_alloc(new_module->pool, sizeof(*node));
401  node->ptr = ptr;
402  node->interface_name = switch_core_strdup(new_module->pool, new_module->module_interface->module_name);
403  if ((head = switch_core_hash_find(loadable_modules.file_hash, ptr->extens[i]))) {
404  node->next = head;
405  }
406 
407  switch_core_hash_insert(loadable_modules.file_hash, ptr->extens[i], (const void *) node);
408  }
409  }
410  }
411  }
412 
413  if (new_module->module_interface->speech_interface) {
414  const switch_speech_interface_t *ptr;
415 
416  for (ptr = new_module->module_interface->speech_interface; ptr; ptr = ptr->next) {
417  if (!ptr->interface_name) {
418  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load speech interface from %s due to no interface name.\n", key);
419  } else {
420  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Speech interface '%s'\n", ptr->interface_name);
422  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "speech");
424  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
425  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
426  switch_event_fire(&event);
427  added++;
428  }
430  }
431  }
432  }
433 
434  if (new_module->module_interface->asr_interface) {
435  const switch_asr_interface_t *ptr;
436 
437  for (ptr = new_module->module_interface->asr_interface; ptr; ptr = ptr->next) {
438  if (!ptr->interface_name) {
439  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load asr interface from %s due to no interface name.\n", key);
440  } else {
441  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding ASR interface '%s'\n", ptr->interface_name);
445  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
446  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
447  switch_event_fire(&event);
448  added++;
449  }
451  }
452  }
453  }
454 
455  if (new_module->module_interface->directory_interface) {
456  const switch_directory_interface_t *ptr;
457 
458  for (ptr = new_module->module_interface->directory_interface; ptr; ptr = ptr->next) {
459  if (!ptr->interface_name) {
460  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load directory interface from %s due to no interface name.\n", key);
461  } else {
462  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Directory interface '%s'\n", ptr->interface_name);
464  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "directory");
466  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
467  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
468  switch_event_fire(&event);
469  added++;
470  }
472  }
473  }
474  }
475 
476  if (new_module->module_interface->chat_interface) {
477  const switch_chat_interface_t *ptr;
478 
479  for (ptr = new_module->module_interface->chat_interface; ptr; ptr = ptr->next) {
480  if (!ptr->interface_name) {
481  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load chat interface from %s due to no interface name.\n", key);
482  } else {
483  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Chat interface '%s'\n", ptr->interface_name);
485  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "chat");
487  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
488  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
489  switch_event_fire(&event);
490  added++;
491  }
493  }
494  }
495  }
496 
497  if (new_module->module_interface->say_interface) {
498  const switch_say_interface_t *ptr;
499 
500  for (ptr = new_module->module_interface->say_interface; ptr; ptr = ptr->next) {
501  if (!ptr->interface_name) {
502  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load say interface from %s due to no interface name.\n", key);
503  } else {
504  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Say interface '%s'\n", ptr->interface_name);
508  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
509  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
510  switch_event_fire(&event);
511  added++;
512  }
514  }
515  }
516  }
517 
518  if (new_module->module_interface->management_interface) {
520 
521  for (ptr = new_module->module_interface->management_interface; ptr; ptr = ptr->next) {
522  if (!ptr->relative_oid) {
523  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load management interface from %s due to no interface name.\n", key);
524  } else {
527  "Failed to load management interface %s. OID %s already exists\n", key, ptr->relative_oid);
528  } else {
530  "Adding Management interface '%s' OID[%s.%s]\n", key, FREESWITCH_OID_PREFIX, ptr->relative_oid);
533  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "management");
535  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
536  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
537  switch_event_fire(&event);
538  added++;
539  }
540  }
541 
542  }
543  }
544  }
545  if (new_module->module_interface->limit_interface) {
546  const switch_limit_interface_t *ptr;
547 
548  for (ptr = new_module->module_interface->limit_interface; ptr; ptr = ptr->next) {
549  if (!ptr->interface_name) {
550  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load limit interface from %s due to no interface name.\n", key);
551  } else {
554  "Failed to load limit interface %s. Name %s already exists\n", key, ptr->interface_name);
555  } else {
557  "Adding Limit interface '%s'\n", ptr->interface_name);
560  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "limit");
562  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
563  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
564  switch_event_fire(&event);
565  added++;
566  }
567  }
568 
569  }
570  }
571  }
572 
573  if (!added) {
575  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "generic");
576  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", new_module->key);
577  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
578  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
579  switch_event_fire(&event);
580  added++;
581  }
582  }
583 
585  return SWITCH_STATUS_SUCCESS;
586 
587 }
588 
589 #define CHAT_MAX_MSG_QUEUE 101
590 #define CHAT_QUEUE_SIZE 5000
591 
592 static struct {
598  int running;
599 } chat_globals;
600 
601 static int IDX = 0;
602 
603 
605 
606 {
610  switch_event_t *dup = NULL;
611  const void *var;
612  void *val;
613  const char *proto;
614  const char *replying;
615  const char *dest_proto;
616  int do_skip = 0;
617 
618  /*
619 
620  const char *from;
621  const char *to;
622  const char *subject;
623  const char *body;
624  const char *type;
625  const char *hint;
626  */
627 
628  dest_proto = switch_event_get_header(message_event, "dest_proto");
629 
630  if (!dest_proto) {
631  return SWITCH_STATUS_FALSE;
632  }
633 
634  /*
635 
636  from = switch_event_get_header(message_event, "from");
637  to = switch_event_get_header(message_event, "to");
638  subject = switch_event_get_header(message_event, "subject");
639  body = switch_event_get_body(message_event);
640  type = switch_event_get_header(message_event, "type");
641  hint = switch_event_get_header(message_event, "hint");
642  */
643 
644  if (!(proto = switch_event_get_header(message_event, "proto"))) {
645  proto = "global";
646  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto);
647  }
648 
649  replying = switch_event_get_header(message_event, "replying");
650 
651  if (!switch_true(replying) && !switch_stristr("global", proto) && !switch_true(switch_event_get_header(message_event, "skip_global_process"))) {
654  switch_core_hash_this(hi, &var, NULL, &val);
655 
656  if ((ci = (switch_chat_interface_t *) val)) {
657  if (ci->chat_send && !strncasecmp(ci->interface_name, "GLOBAL_", 7)) {
658  status = ci->chat_send(message_event);
659 
660  if (status == SWITCH_STATUS_SUCCESS) {
661  if (switch_true(switch_event_get_header(message_event, "final_delivery"))) {
662  /* The event was handled by an extension in the chatplan,
663  * so the event will be duplicated, modified and queued again,
664  * but it won't be processed by the chatplan again.
665  * So this copy of the event can be destroyed by the caller.
666  */
667  do_skip = 1;
668  }
669  } else if (status == SWITCH_STATUS_BREAK) {
670  /* The event went through the chatplan, but no extension matched
671  * to handle the sms messsage. It'll be attempted to be delivered
672  * directly, and unless that works the sms delivery will have failed.
673  */
674  } else {
675  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Chat Interface Error [%s]!\n", dest_proto);
676  break;
677  }
678  }
679  }
680  }
681  switch_safe_free(hi);
683  }
684 
685 
686  if (!do_skip && !switch_stristr("GLOBAL", dest_proto)) {
687  if ((ci = switch_loadable_module_get_chat_interface(dest_proto)) && ci->chat_send) {
688  status = ci->chat_send(message_event);
690  } else {
691  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid chat interface [%s]!\n", dest_proto);
692  status = SWITCH_STATUS_FALSE;
693  }
694  }
695 
696 
697  switch_event_dup(&dup, message_event);
698 
699  if ( switch_true(switch_event_get_header(message_event, "blocking")) ) {
700  if (status == SWITCH_STATUS_SUCCESS) {
701  switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Delivery-Failure", "false");
702  } else {
703  switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Delivery-Failure", "true");
704  }
705  } else {
706  switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Nonblocking-Delivery", "true");
707  }
708 
709  switch_event_fire(&dup);
710  return status;
711 }
712 
714 {
715  switch_event_t *event;
716  switch_status_t status;
717 
718  switch_assert(eventp);
719 
720  event = *eventp;
721  *eventp = NULL;
722 
723  status = do_chat_send(event);
724  switch_event_destroy(&event);
725 
726  return status;
727 }
728 
729 
731 {
732  void *pop;
733  switch_queue_t *q = (switch_queue_t *) obj;
734 
735  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Chat Thread Started\n");
736 
737 
738  while(switch_queue_pop(q, &pop) == SWITCH_STATUS_SUCCESS && pop) {
739  switch_event_t *event = (switch_event_t *) pop;
740  chat_process_event(&event);
742  }
743 
744  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Chat Thread Ended\n");
745 
746  return NULL;
747 }
748 
749 
750 static void chat_thread_start(int idx)
751 {
752 
753  if (idx >= CHAT_MAX_MSG_QUEUE || (idx < chat_globals.msg_queue_len && chat_globals.msg_queue_thread[idx])) {
754  return;
755  }
756 
758 
759  if (idx >= chat_globals.msg_queue_len) {
760  int i;
761  chat_globals.msg_queue_len = idx + 1;
762 
763  for (i = 0; i < chat_globals.msg_queue_len; i++) {
764  if (!chat_globals.msg_queue[i]) {
765  switch_threadattr_t *thd_attr = NULL;
766 
768 
769  switch_threadattr_create(&thd_attr, chat_globals.pool);
771  switch_thread_create(&chat_globals.msg_queue_thread[i],
772  thd_attr,
774  chat_globals.msg_queue[i],
775  chat_globals.pool);
776  }
777  }
778  }
779 
781 }
782 
783 
784 static void chat_queue_message(switch_event_t **eventp)
785 {
786  int idx = 0;
787  switch_event_t *event;
788 
789  switch_assert(eventp);
790 
791  event = *eventp;
792  *eventp = NULL;
793 
794  if (chat_globals.running == 0) {
795  chat_process_event(&event);
796  return;
797  }
798 
799  again:
800 
802  idx = IDX;
803  IDX++;
804  if (IDX >= chat_globals.msg_queue_len) IDX = 0;
806 
807  chat_thread_start(idx);
808 
809  if (switch_queue_trypush(chat_globals.msg_queue[idx], event) != SWITCH_STATUS_SUCCESS) {
810  if (chat_globals.msg_queue_len < CHAT_MAX_MSG_QUEUE) {
811  chat_thread_start(idx + 1);
812  goto again;
813  } else {
814  switch_queue_push(chat_globals.msg_queue[idx], event);
815  }
816  }
817 }
818 
819 
820 SWITCH_DECLARE(switch_status_t) switch_core_execute_chat_app(switch_event_t *message, const char *app, const char *data)
821 {
824  char *expanded;
825 
827  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid chat application interface [%s]!\n", app);
828  return SWITCH_STATUS_FALSE;
829  }
830 
831  if (switch_test_flag(message, EF_NO_CHAT_EXEC)) {
832  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Message is not allowed to execute apps\n");
834  }
835 
836  if (data && !strcmp(data, "__undef")) {
837  data = NULL;
838  }
839 
840  expanded = switch_event_expand_headers(message, data);
841 
842  status = cai->chat_application_function(message, expanded);
843 
844  if (expanded != data) {
845  free(expanded);
846  }
847 
848  end:
849 
850  UNPROTECT_INTERFACE(cai);
851 
852  return status;
853 
854 }
855 
856 
857 
858 SWITCH_DECLARE(switch_status_t) switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to,
859  const char *subject, const char *body, const char *type, const char *hint, switch_bool_t blocking)
860 {
861  switch_event_t *message_event;
862  switch_status_t status;
863 
865  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto);
866  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "from", from);
867  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "to", to);
868  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "subject", subject);
869  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "type", type);
870  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "hint", hint);
871  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "skip_global_process", "true");
872  if (blocking) {
873  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "blocking", "true");
874  }
875 
876  if (body) {
877  switch_event_add_body(message_event, "%s", body);
878  }
879  } else {
880  abort();
881  }
882 
883  if (dest_proto) {
884  switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "dest_proto", dest_proto);
885  }
886 
887 
888  if (blocking) {
889  status = chat_process_event(&message_event);
890  } else {
891  chat_queue_message(&message_event);
892  status = SWITCH_STATUS_SUCCESS;
893  }
894 
895  return status;
896 
897 }
898 
899 
900 SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *dest_proto, switch_event_t *message_event)
901 {
902  switch_event_t *dup;
903 
904  switch_event_dup(&dup, message_event);
905 
906  if (dest_proto) {
907  switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "dest_proto", dest_proto);
908  }
909 
910  chat_queue_message(&dup);
911  return SWITCH_STATUS_SUCCESS;
912 }
913 
914 
916 {
917 
918  if (dest_proto) {
919  switch_event_add_header_string(*message_event, SWITCH_STACK_BOTTOM, "dest_proto", dest_proto);
920  }
921 
922  chat_queue_message(message_event);
923 
924  return SWITCH_STATUS_SUCCESS;
925 }
926 
927 
929 {
930  switch_event_t *event;
931  int removed = 0;
932 
934 
935  if (old_module->module_interface->endpoint_interface) {
936  const switch_endpoint_interface_t *ptr;
937 
938  for (ptr = old_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) {
939  if (ptr->interface_name) {
940 
942  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
943  ptr->interface_name);
946  } else {
947  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
948  }
949 
950  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Endpoint '%s'\n", ptr->interface_name);
952  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "endpoint");
954  switch_event_fire(&event);
955  removed++;
956  }
958  }
959  }
960  }
961 
962  if (old_module->module_interface->codec_interface) {
963  const switch_codec_implementation_t *impl;
964  const switch_codec_interface_t *ptr;
965  switch_codec_node_t *node, *head, *last = NULL;
966 
967  for (ptr = old_module->module_interface->codec_interface; ptr; ptr = ptr->next) {
968  if (ptr->interface_name) {
969  unsigned load_interface = 1;
970  for (impl = ptr->implementations; impl; impl = impl->next) {
971  if (!impl->iananame) {
972  load_interface = 0;
973  break;
974  }
975  }
976  if (load_interface) {
977  for (impl = ptr->implementations; impl; impl = impl->next) {
979  "Deleting Codec %s %d %s %dhz %dms\n",
980  impl->iananame, impl->ianacode,
984 
986  for(node = head; node; node = node->next) {
987  if (!strcmp(node->interface_name, old_module->module_interface->module_name)) {
988  if (node == head) {
989  if ((node = node->next)) {
990  switch_core_hash_insert(loadable_modules.codec_hash, impl->iananame, (const void *) node);
991  } else {
993  }
994  } else {
995  if (last) {
996  last->next = node->next;
997  }
998  }
999  break;
1000  }
1001  last = node;
1002  }
1003  }
1004  }
1006  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "codec");
1009  switch_event_fire(&event);
1010  removed++;
1011  }
1012  }
1013  }
1014  }
1015  }
1016 
1017  if (old_module->module_interface->dialplan_interface) {
1018  const switch_dialplan_interface_t *ptr;
1019 
1020  for (ptr = old_module->module_interface->dialplan_interface; ptr; ptr = ptr->next) {
1021  if (ptr->interface_name) {
1022  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Dialplan '%s'\n", ptr->interface_name);
1024  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "dialplan");
1026  switch_event_fire(&event);
1027  removed++;
1028  }
1030  }
1031  }
1032  }
1033 
1034  if (old_module->module_interface->timer_interface) {
1035  const switch_timer_interface_t *ptr;
1036 
1037  for (ptr = old_module->module_interface->timer_interface; ptr; ptr = ptr->next) {
1038  if (ptr->interface_name) {
1039  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Timer '%s'\n", ptr->interface_name);
1041  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "timer");
1043  switch_event_fire(&event);
1044  removed++;
1045  }
1047  }
1048  }
1049  }
1050 
1051  if (old_module->module_interface->application_interface) {
1052  const switch_application_interface_t *ptr;
1053  for (ptr = old_module->module_interface->application_interface; ptr; ptr = ptr->next) {
1054  if (ptr->interface_name) {
1055  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name);
1057  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1058  ptr->interface_name);
1061  } else {
1062  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1063  }
1064 
1066  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application");
1070  switch_event_fire(&event);
1071  removed++;
1072  }
1074  }
1075  }
1076  }
1077 
1078  if (old_module->module_interface->chat_application_interface) {
1080  for (ptr = old_module->module_interface->chat_application_interface; ptr; ptr = ptr->next) {
1081  if (ptr->interface_name) {
1082  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name);
1084  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1085  ptr->interface_name);
1088  } else {
1089  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1090  }
1091 
1093  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application");
1097  switch_event_fire(&event);
1098  removed++;
1099  }
1101  }
1102  }
1103  }
1104 
1105  if (old_module->module_interface->api_interface) {
1106  const switch_api_interface_t *ptr;
1107 
1108  for (ptr = old_module->module_interface->api_interface; ptr; ptr = ptr->next) {
1109  if (ptr->interface_name) {
1110  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name);
1111 
1112  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1113  ptr->interface_name);
1114 
1117  } else {
1118  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1119  }
1120 
1121 
1123  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "api");
1127  switch_event_fire(&event);
1128  removed++;
1129  }
1131  }
1132  }
1133  }
1134 
1135  if (old_module->module_interface->json_api_interface) {
1136  const switch_json_api_interface_t *ptr;
1137 
1138  for (ptr = old_module->module_interface->json_api_interface; ptr; ptr = ptr->next) {
1139  if (ptr->interface_name) {
1140  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name);
1141 
1142  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1143  ptr->interface_name);
1144 
1147  } else {
1148  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1149  }
1150 
1151 
1153  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "api");
1157  switch_event_fire(&event);
1158  removed++;
1159  }
1161  }
1162  }
1163  }
1164 
1165  if (old_module->module_interface->file_interface) {
1166  const switch_file_interface_t *ptr;
1167  switch_file_node_t *node, *head, *last = NULL;
1168 
1169  for (ptr = old_module->module_interface->file_interface; ptr; ptr = ptr->next) {
1170  if (ptr->interface_name) {
1171  int i;
1172 
1173  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1174  ptr->interface_name);
1175 
1178  } else {
1179  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1180  }
1181 
1182  for (i = 0; ptr->extens[i]; i++) {
1183  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting File Format '%s'\n", ptr->extens[i]);
1185  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "file");
1188  switch_event_fire(&event);
1189  removed++;
1190  }
1191 
1192  if ((head = switch_core_hash_find(loadable_modules.file_hash, ptr->extens[i]))) {
1193  for(node = head; node; node = node->next) {
1194  if (!strcmp(node->interface_name, old_module->module_interface->module_name)) {
1195  if (node == head) {
1196  if ((node = node->next)) {
1197  switch_core_hash_insert(loadable_modules.file_hash, ptr->extens[i], (const void *) node);
1198  } else {
1200  }
1201  } else {
1202  if (last) {
1203  last->next = node->next;
1204  }
1205  }
1206  break;
1207  }
1208  last = node;
1209  }
1210  }
1211  }
1212  }
1213  }
1214  }
1215 
1216  if (old_module->module_interface->speech_interface) {
1217  const switch_speech_interface_t *ptr;
1218 
1219  for (ptr = old_module->module_interface->speech_interface; ptr; ptr = ptr->next) {
1220 
1221  if (ptr->interface_name) {
1222 
1223  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1224  ptr->interface_name);
1225 
1228  } else {
1229  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1230  }
1231 
1232  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Speech interface '%s'\n", ptr->interface_name);
1234  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "speech");
1236  switch_event_fire(&event);
1237  removed++;
1238  }
1240  }
1241  }
1242  }
1243 
1244  if (old_module->module_interface->asr_interface) {
1245  const switch_asr_interface_t *ptr;
1246 
1247  for (ptr = old_module->module_interface->asr_interface; ptr; ptr = ptr->next) {
1248  if (ptr->interface_name) {
1249 
1250  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1251  ptr->interface_name);
1252 
1255  } else {
1256  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1257  }
1258 
1259  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Asr interface '%s'\n", ptr->interface_name);
1261  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "asr");
1263  switch_event_fire(&event);
1264  removed++;
1265  }
1267  }
1268  }
1269  }
1270 
1271  if (old_module->module_interface->directory_interface) {
1272  const switch_directory_interface_t *ptr;
1273 
1274  for (ptr = old_module->module_interface->directory_interface; ptr; ptr = ptr->next) {
1275  if (ptr->interface_name) {
1276 
1277  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1278  ptr->interface_name);
1279 
1282  } else {
1283  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1284  }
1285 
1286  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Directory interface '%s'\n", ptr->interface_name);
1288  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "directory");
1290  switch_event_fire(&event);
1291  removed++;
1292  }
1294  }
1295  }
1296  }
1297 
1298 
1299  if (old_module->module_interface->chat_interface) {
1300  const switch_chat_interface_t *ptr;
1301 
1302  for (ptr = old_module->module_interface->chat_interface; ptr; ptr = ptr->next) {
1303  if (ptr->interface_name) {
1304  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1305  ptr->interface_name);
1306 
1309  } else {
1310  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1311  }
1312 
1313  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Chat interface '%s'\n", ptr->interface_name);
1315  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "chat");
1317  switch_event_fire(&event);
1318  removed++;
1319  }
1321  }
1322  }
1323  }
1324 
1325  if (old_module->module_interface->say_interface) {
1326  const switch_say_interface_t *ptr;
1327 
1328  for (ptr = old_module->module_interface->say_interface; ptr; ptr = ptr->next) {
1329  if (ptr->interface_name) {
1330  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
1331  ptr->interface_name);
1332 
1335  } else {
1336  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
1337  }
1338  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Say interface '%s'\n", ptr->interface_name);
1340  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "say");
1342  switch_event_fire(&event);
1343  removed++;
1344  }
1346  }
1347  }
1348  }
1349 
1350  if (old_module->module_interface->management_interface) {
1351  const switch_management_interface_t *ptr;
1352 
1353  for (ptr = old_module->module_interface->management_interface; ptr; ptr = ptr->next) {
1354  if (ptr->relative_oid) {
1356  "Deleting Management interface '%s' OID[%s.%s]\n", old_module->key, FREESWITCH_OID_PREFIX, ptr->relative_oid);
1359  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "management");
1361  switch_event_fire(&event);
1362  removed++;
1363  }
1364  }
1365  }
1366  }
1367 
1368  if (old_module->module_interface->limit_interface) {
1369  const switch_limit_interface_t *ptr;
1370 
1371  for (ptr = old_module->module_interface->limit_interface; ptr; ptr = ptr->next) {
1372  if (ptr->interface_name) {
1374  "Deleting Limit interface '%s'\n", ptr->interface_name);
1377  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "limit");
1379  switch_event_fire(&event);
1380  removed++;
1381  }
1382  }
1383  }
1384  }
1385 
1386  if (!removed) {
1388  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "generic");
1389  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", old_module->key);
1390  switch_event_fire(&event);
1391  removed++;
1392  }
1393  }
1395 
1396  return SWITCH_STATUS_SUCCESS;
1397 
1398 }
1399 
1400 
1402 {
1403  switch_loadable_module_t *module = NULL;
1404  switch_dso_lib_t dso = NULL;
1405  apr_status_t status = SWITCH_STATUS_SUCCESS;
1406  switch_loadable_module_function_table_t *interface_struct_handle = NULL;
1407  switch_loadable_module_function_table_t *mod_interface_functions = NULL;
1408  char *struct_name = NULL;
1409  switch_module_load_t load_func_ptr = NULL;
1410  int loading = 1;
1411  switch_loadable_module_interface_t *module_interface = NULL;
1412  char *derr = NULL;
1413  const char *err = NULL;
1414  switch_memory_pool_t *pool = NULL;
1415  switch_bool_t load_global = global;
1416 
1417  switch_assert(path != NULL);
1418 
1420  *new_module = NULL;
1421 
1422  struct_name = switch_core_sprintf(pool, "%s_module_interface", filename);
1423 
1424 #ifdef WIN32
1425  dso = switch_dso_open("FreeSwitch.dll", load_global, &derr);
1426 #elif defined (MACOSX) || defined(DARWIN)
1427  {
1428  char *lib_path = switch_mprintf("%s/libfreeswitch.dylib", SWITCH_GLOBAL_dirs.lib_dir);
1429  dso = switch_dso_open(lib_path, load_global, &derr);
1430  switch_safe_free(lib_path);
1431  }
1432 #else
1433  dso = switch_dso_open(NULL, load_global, &derr);
1434 #endif
1435  if (!derr && dso) {
1436  interface_struct_handle = switch_dso_data_sym(dso, struct_name, &derr);
1437  }
1438 
1439  switch_safe_free(derr);
1440 
1441  if (!interface_struct_handle) {
1442  if (dso) switch_dso_destroy(&dso);
1443  dso = switch_dso_open(path, load_global, &derr);
1444  }
1445 
1446  while (loading) {
1447  if (derr) {
1448  err = derr;
1449  break;
1450  }
1451 
1452  if (!interface_struct_handle) {
1453  interface_struct_handle = switch_dso_data_sym(dso, struct_name, &derr);
1454  }
1455 
1456  if (derr) {
1457  err = derr;
1458  break;
1459  }
1460 
1461  if (interface_struct_handle && interface_struct_handle->switch_api_version != SWITCH_API_VERSION) {
1462  err = "Trying to load an out of date module, please rebuild the module.";
1463  break;
1464  }
1465 
1466  if (!load_global && interface_struct_handle && switch_test_flag(interface_struct_handle, SMODF_GLOBAL_SYMBOLS)) {
1467  load_global = SWITCH_TRUE;
1468  switch_dso_destroy(&dso);
1469  interface_struct_handle = NULL;
1470  dso = switch_dso_open(path, load_global, &derr);
1471  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading module with global namespace at request of module\n");
1472  continue;
1473  }
1474 
1475  if (interface_struct_handle) {
1476  mod_interface_functions = interface_struct_handle;
1477  load_func_ptr = mod_interface_functions->load;
1478  }
1479 
1480  if (load_func_ptr == NULL) {
1481  err = "Cannot locate symbol 'switch_module_load' please make sure this is a valid module.";
1482  break;
1483  }
1484 
1485  status = load_func_ptr(&module_interface, pool);
1486 
1487  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) {
1488  err = "Module load routine returned an error";
1489  module_interface = NULL;
1490  break;
1491  }
1492 
1493  if (!module_interface) {
1494  err = "Module failed to initialize its module_interface. Is this a valid module?";
1495  break;
1496  }
1497 
1498  if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
1499  err = "Could not allocate memory\n";
1500  abort();
1501  }
1502 
1503  if (status == SWITCH_STATUS_NOUNLOAD) {
1504  module->perm++;
1505  }
1506 
1507  loading = 0;
1508  }
1509 
1510 
1511  if (err) {
1512 
1513  if (dso) {
1514  switch_dso_destroy(&dso);
1515  }
1516 
1517  if (pool) {
1519  }
1520  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Loading module %s\n**%s**\n", path, err);
1521  switch_safe_free(derr);
1522  return SWITCH_STATUS_GENERR;
1523  }
1524 
1525  module->pool = pool;
1526  module->filename = switch_core_strdup(module->pool, path);
1527  module->module_interface = module_interface;
1528  module->switch_module_load = load_func_ptr;
1529 
1530  if (mod_interface_functions) {
1531  module->switch_module_shutdown = mod_interface_functions->shutdown;
1532  module->switch_module_runtime = mod_interface_functions->runtime;
1533  }
1534 
1535  module->lib = dso;
1536 
1537  *new_module = module;
1538  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module_interface->module_name);
1539 
1541 
1542  return SWITCH_STATUS_SUCCESS;
1543 
1544 }
1546 {
1547  return switch_loadable_module_load_module_ex(dir, fname, runtime, SWITCH_FALSE, err);
1548 }
1549 
1550 static switch_status_t switch_loadable_module_load_module_ex(char *dir, char *fname, switch_bool_t runtime, switch_bool_t global, const char **err)
1551 {
1552  switch_size_t len = 0;
1553  char *path;
1554  char *file, *dot;
1555  switch_loadable_module_t *new_module = NULL;
1557 
1558 #ifdef WIN32
1559  const char *ext = ".dll";
1560 #else
1561  const char *ext = ".so";
1562 #endif
1563 
1564  *err = "";
1565 
1566  if ((file = switch_core_strdup(loadable_modules.pool, fname)) == 0) {
1567  *err = "allocation error";
1568  return SWITCH_STATUS_FALSE;
1569  }
1570 
1571  if (switch_is_file_path(file)) {
1573  file = (char *) switch_cut_path(file);
1574  if ((dot = strchr(file, '.'))) {
1575  *dot = '\0';
1576  }
1577  } else {
1578  if ((dot = strchr(file, '.'))) {
1579  *dot = '\0';
1580  }
1581  len = strlen(dir);
1582  len += strlen(file);
1583  len += 8;
1584  path = (char *) switch_core_alloc(loadable_modules.pool, len);
1585  switch_snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext);
1586  }
1587 
1588 
1590  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Module %s Already Loaded!\n", file);
1591  *err = "Module already loaded";
1592  status = SWITCH_STATUS_FALSE;
1593  } else if ((status = switch_loadable_module_load_file(path, file, global, &new_module)) == SWITCH_STATUS_SUCCESS) {
1594  if ((status = switch_loadable_module_process(file, new_module)) == SWITCH_STATUS_SUCCESS && runtime) {
1595  if (new_module->switch_module_runtime) {
1596  new_module->thread = switch_core_launch_thread(switch_loadable_module_exec, new_module, new_module->pool);
1597  }
1598  } else if (status != SWITCH_STATUS_SUCCESS) {
1599  *err = "module load routine returned an error";
1600  }
1601  } else {
1602  *err = "module load file routine returned an error";
1603  }
1604 
1605 
1606  return status;
1607 
1608 }
1609 
1611 {
1612  switch_status_t status;
1613 
1614  if (zstr(mod)) {
1615  return SWITCH_STATUS_FALSE;
1616  }
1617 
1620  status = SWITCH_STATUS_SUCCESS;
1621  } else {
1622  status = SWITCH_STATUS_FALSE;
1623  }
1625 
1626  return status;
1627 }
1628 
1630 {
1631  switch_loadable_module_t *module = NULL;
1633 
1634  if (force) {
1635  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Spin the barrel and pull the trigger.......!\n");
1636  }
1637 
1639  if ((module = switch_core_hash_find(loadable_modules.module_hash, fname))) {
1640  if (module->perm) {
1641  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Module is not unloadable.\n");
1642  *err = "Module is not unloadable";
1643  status = SWITCH_STATUS_NOUNLOAD;
1644  goto unlock;
1645  } else {
1646  /* Prevent anything from using the module while it's shutting down */
1649  if ((status = do_shutdown(module, SWITCH_TRUE, SWITCH_TRUE, !force, err)) != SWITCH_STATUS_SUCCESS) {
1650  /* Something went wrong in the module's shutdown function, add it again */
1652  }
1653  goto end;
1654  }
1655  } else {
1656  *err = "No such module!";
1657  status = SWITCH_STATUS_FALSE;
1658  }
1659 unlock:
1661  end:
1662  if (force) {
1663  switch_yield(1000000);
1665  }
1666 
1667  return status;
1668 
1669 }
1670 
1672 {
1673  switch_dir_t *dir = NULL;
1674  switch_status_t status;
1675  char buffer[256];
1676  const char *fname;
1677  const char *fname_ext;
1678  char *fname_base;
1679 
1680 #ifdef WIN32
1681  const char *ext = ".dll";
1682 #else
1683  const char *ext = ".so";
1684 #endif
1685 
1686  if ((status = switch_dir_open(&dir, dir_path, loadable_modules.pool)) != SWITCH_STATUS_SUCCESS) {
1687  return status;
1688  }
1689 
1690  while((fname = switch_dir_next_file(dir, buffer, sizeof(buffer)))) {
1691  if ((fname_ext = strrchr(fname, '.'))) {
1692  if (!strcmp(fname_ext, ext)) {
1693  if (!(fname_base = switch_mprintf("%.*s", (int)(fname_ext-fname), fname))) {
1694  status = SWITCH_STATUS_GENERR;
1695  goto end;
1696  }
1697  callback(user_data, fname_base);
1698  switch_safe_free(fname_base)
1699  }
1700  }
1701  }
1702 
1703 
1704  end:
1705  switch_dir_close(dir);
1706  return status;
1707 }
1708 
1710 {
1711  switch_hash_index_t *hi;
1712  void *val;
1713  switch_loadable_module_t *module;
1714 
1717  switch_core_hash_this(hi, NULL, NULL, &val);
1718  module = (switch_loadable_module_t *) val;
1719 
1720  callback(user_data, module->module_interface->module_name);
1721  }
1723 
1724  return SWITCH_STATUS_SUCCESS;
1725 }
1726 
1728  switch_module_load_t switch_module_load,
1729  switch_module_runtime_t switch_module_runtime,
1730  switch_module_shutdown_t switch_module_shutdown, switch_bool_t runtime)
1731 {
1732  switch_loadable_module_t *module = NULL;
1733  switch_module_load_t load_func_ptr = NULL;
1734  int loading = 1;
1735  const char *err = NULL;
1736  switch_loadable_module_interface_t *module_interface = NULL;
1738 
1739 
1742  abort();
1743  }
1744 
1745  if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
1746  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Couldn't allocate memory\n");
1747  abort();
1748  }
1749 
1750 
1751 
1752  while (loading) {
1753  switch_status_t status;
1754  load_func_ptr = (switch_module_load_t) switch_module_load;
1755 
1756  if (load_func_ptr == NULL) {
1757  err = "Cannot Load";
1758  break;
1759  }
1760 
1761  status = load_func_ptr(&module_interface, pool);
1762 
1763  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) {
1764  err = "Module load routine returned an error";
1765  module_interface = NULL;
1766  break;
1767  }
1768 
1769  if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
1770  err = "Could not allocate memory\n";
1771  abort();
1772  }
1773 
1774  if (status == SWITCH_STATUS_NOUNLOAD) {
1775  module->perm++;
1776  }
1777 
1778  loading = 0;
1779  }
1780 
1781  if (err) {
1783  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error Loading module %s\n**%s**\n", filename, err);
1784  return SWITCH_STATUS_GENERR;
1785  }
1786 
1787  module->pool = pool;
1788  module->filename = switch_core_strdup(module->pool, filename);
1789  module->module_interface = module_interface;
1790  module->switch_module_load = load_func_ptr;
1791 
1792  if (switch_module_shutdown) {
1793  module->switch_module_shutdown = switch_module_shutdown;
1794  }
1795  if (switch_module_runtime) {
1796  module->switch_module_runtime = switch_module_runtime;
1797  }
1798  if (runtime && module->switch_module_runtime) {
1800  }
1801  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module_interface->module_name);
1802  return switch_loadable_module_process((char *) module->filename, module);
1803 }
1804 
1805 #ifdef WIN32
1806 static void switch_loadable_module_path_init()
1807 {
1808  char *path = NULL, *working = NULL;
1809  apr_dir_t *perl_dir_handle = NULL;
1810 
1811  apr_env_get(&path, "path", loadable_modules.pool);
1812  apr_filepath_get(&working, APR_FILEPATH_NATIVE, loadable_modules.pool);
1813 
1814  if (apr_dir_open(&perl_dir_handle, ".\\perl", loadable_modules.pool) == APR_SUCCESS) {
1815  apr_dir_close(perl_dir_handle);
1816  apr_env_set("path", apr_pstrcat(loadable_modules.pool, path, ";", working, "\\perl", NULL), loadable_modules.pool);
1817  }
1818 }
1819 #endif
1820 
1822 {
1823 
1824  apr_finfo_t finfo = { 0 };
1825  apr_dir_t *module_dir_handle = NULL;
1826  apr_int32_t finfo_flags = APR_FINFO_DIRENT | APR_FINFO_TYPE | APR_FINFO_NAME;
1827  char *cf = "modules.conf";
1828  char *pcf = "post_load_modules.conf";
1829  switch_xml_t cfg, xml;
1830  unsigned char all = 0;
1831  unsigned int count = 0;
1832  const char *err;
1833 
1834 
1835 #ifdef WIN32
1836  const char *ext = ".dll";
1837  const char *EXT = ".DLL";
1838 #elif defined (MACOSX) || defined (DARWIN)
1839  const char *ext = ".dylib";
1840  const char *EXT = ".DYLIB";
1841 #else
1842  const char *ext = ".so";
1843  const char *EXT = ".SO";
1844 #endif
1845 
1848 
1849 
1850 #ifdef WIN32
1851  switch_loadable_module_path_init();
1852 #endif
1853 
1873 
1874  if (!autoload) return SWITCH_STATUS_SUCCESS;
1875 
1876  switch_loadable_module_load_module("", "CORE_SOFTTIMER_MODULE", SWITCH_FALSE, &err);
1877  switch_loadable_module_load_module("", "CORE_PCM_MODULE", SWITCH_FALSE, &err);
1878  switch_loadable_module_load_module("", "CORE_SPEEX_MODULE", SWITCH_FALSE, &err);
1879 #ifdef SWITCH_HAVE_YUV
1880 #ifdef SWITCH_HAVE_VPX
1881  switch_loadable_module_load_module("", "CORE_VPX_MODULE", SWITCH_FALSE, &err);
1882 #endif
1883 #endif
1884 
1885  if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
1886  switch_xml_t mods, ld;
1887  if ((mods = switch_xml_child(cfg, "modules"))) {
1888  for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) {
1889  switch_bool_t global = SWITCH_FALSE;
1890  const char *val = switch_xml_attr_soft(ld, "module");
1891  const char *path = switch_xml_attr_soft(ld, "path");
1892  const char *critical = switch_xml_attr_soft(ld, "critical");
1893  const char *sglobal = switch_xml_attr_soft(ld, "global");
1894  if (zstr(val) || (strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT))) {
1895  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
1896  continue;
1897  }
1898  global = switch_true(sglobal);
1899 
1900  if (path && zstr(path)) {
1901  path = SWITCH_GLOBAL_dirs.mod_dir;
1902  }
1903  if (switch_loadable_module_load_module_ex((char *) path, (char *) val, SWITCH_FALSE, global, &err) == SWITCH_STATUS_GENERR) {
1904  if (critical && switch_true(critical)) {
1905  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load critical module '%s', abort()\n", val);
1906  abort();
1907  }
1908  }
1909  count++;
1910  }
1911  }
1912  switch_xml_free(xml);
1913 
1914  } else {
1915  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "open of %s failed\n", cf);
1916  }
1917 
1918  if ((xml = switch_xml_open_cfg(pcf, &cfg, NULL))) {
1919  switch_xml_t mods, ld;
1920 
1921  if ((mods = switch_xml_child(cfg, "modules"))) {
1922  for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) {
1923  switch_bool_t global = SWITCH_FALSE;
1924  const char *val = switch_xml_attr_soft(ld, "module");
1925  const char *path = switch_xml_attr_soft(ld, "path");
1926  const char *sglobal = switch_xml_attr_soft(ld, "global");
1927  if (zstr(val) || (strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT))) {
1928  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
1929  continue;
1930  }
1931  global = switch_true(sglobal);
1932 
1933  if (path && zstr(path)) {
1934  path = SWITCH_GLOBAL_dirs.mod_dir;
1935  }
1936  switch_loadable_module_load_module_ex((char *) path, (char *) val, SWITCH_FALSE, global, &err);
1937  count++;
1938  }
1939  }
1940  switch_xml_free(xml);
1941 
1942  } else {
1943  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "open of %s failed\n", pcf);
1944  }
1945 
1946  if (!count) {
1947  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "No modules loaded, assuming 'load all'\n");
1948  all = 1;
1949  }
1950 
1951  if (all) {
1952  if (apr_dir_open(&module_dir_handle, SWITCH_GLOBAL_dirs.mod_dir, loadable_modules.pool) != APR_SUCCESS) {
1954  return SWITCH_STATUS_GENERR;
1955  }
1956 
1957  while (apr_dir_read(&finfo, finfo_flags, module_dir_handle) == APR_SUCCESS) {
1958  const char *fname = finfo.fname;
1959 
1960  if (finfo.filetype != APR_REG) {
1961  continue;
1962  }
1963 
1964  if (!fname) {
1965  fname = finfo.name;
1966  }
1967 
1968  if (!fname) {
1969  continue;
1970  }
1971 
1972  if (zstr(fname) || (!strstr(fname, ext) && !strstr(fname, EXT))) {
1973  continue;
1974  }
1975 
1977  }
1978  apr_dir_close(module_dir_handle);
1979  }
1980 
1982 
1983  memset(&chat_globals, 0, sizeof(chat_globals));
1984  chat_globals.running = 1;
1987 
1988  chat_thread_start(1);
1989 
1990  return SWITCH_STATUS_SUCCESS;
1991 }
1992 
1994  const char **err)
1995 {
1996  int32_t flags = switch_core_flags();
1997  switch_assert(module != NULL);
1998 
2000  if (err) {
2001  *err = "Module in use.";
2002  }
2003  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Module %s is in use, cannot unload.\n", module->module_interface->module_name);
2004  return SWITCH_STATUS_FALSE;
2005  }
2006 
2007  module->shutting_down = SWITCH_TRUE;
2008 
2009  if (shutdown) {
2011  if (module->switch_module_shutdown) {
2013  module->status = module->switch_module_shutdown();
2014  } else {
2015  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name);
2016  }
2017  }
2018 
2019  if (fail_if_busy && module->module_interface->rwlock) {
2021  }
2022 
2023  if (unload && module->status != SWITCH_STATUS_NOUNLOAD && !(flags & SCF_VG)) {
2025  switch_status_t st;
2026 
2027  if (module->thread) {
2028  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s stopping runtime thread.\n", module->module_interface->module_name);
2029  switch_thread_join(&st, module->thread);
2030  }
2031 
2033  switch_dso_destroy(&module->lib);
2034  if ((pool = module->pool)) {
2035  module = NULL;
2037  }
2038  }
2039 
2040  return SWITCH_STATUS_SUCCESS;
2041 
2042 }
2043 
2045 {
2046  switch_hash_index_t *hi;
2047  void *val;
2048  switch_loadable_module_t *module;
2049  int i;
2050 
2052  return;
2053  }
2054 
2055  chat_globals.running = 0;
2056 
2057  for (i = 0; i < chat_globals.msg_queue_len; i++) {
2058  switch_queue_push(chat_globals.msg_queue[i], NULL);
2059  }
2060 
2061  for (i = 0; i < chat_globals.msg_queue_len; i++) {
2062  switch_status_t st;
2063  switch_thread_join(&st, chat_globals.msg_queue_thread[i]);
2064  }
2065 
2066 
2068  switch_core_hash_this(hi, NULL, NULL, &val);
2069  module = (switch_loadable_module_t *) val;
2070  if (!module->perm) {
2072  }
2073  }
2074 
2075  switch_yield(1000000);
2076 
2078  switch_core_hash_this(hi, NULL, NULL, &val);
2079  module = (switch_loadable_module_t *) val;
2080  if (!module->perm) {
2082  }
2083  }
2084 
2102 
2104 }
2105 
2107 {
2109 
2112  if (ptr) {
2113  PROTECT_INTERFACE(ptr);
2114  }
2116 
2117 
2118  return ptr;
2119 }
2120 
2122 {
2123  switch_file_interface_t *i = NULL;
2124  switch_file_node_t *node, *head;
2125 
2127 
2128  if ((head = switch_core_hash_find(loadable_modules.file_hash, name))) {
2129  if (modname) {
2130  for (node = head; node; node = node->next) {
2131  if (!strcasecmp(node->interface_name, modname)) {
2132  i = (switch_file_interface_t *) node->ptr;
2133  break;
2134  }
2135  }
2136  } else {
2137  i = (switch_file_interface_t *) head->ptr;
2138  }
2139  }
2140 
2142 
2143  if (i) PROTECT_INTERFACE(i);
2144 
2145  return i;
2146 }
2147 
2149 {
2150  switch_codec_interface_t *codec = NULL;
2151  switch_codec_node_t *node, *head;
2152 
2154 
2155  if ((head = switch_core_hash_find(loadable_modules.codec_hash, name))) {
2156  if (modname) {
2157  for (node = head; node; node = node->next) {
2158  if (!strcasecmp(node->interface_name, modname)) {
2159  codec = (switch_codec_interface_t *) node->ptr;
2160  break;
2161  }
2162  }
2163  } else {
2164  codec = (switch_codec_interface_t *) head->ptr;
2165  }
2166  }
2167 
2169 
2170  if (codec) {
2171  PROTECT_INTERFACE(codec);
2172  }
2173 
2174  return codec;
2175 }
2176 
2177 #define HASH_FUNC(_kind_) SWITCH_DECLARE(switch_##_kind_##_interface_t *) switch_loadable_module_get_##_kind_##_interface(const char *name) \
2178  { \
2179  switch_##_kind_##_interface_t *i = NULL; \
2180  if (loadable_modules._kind_##_hash && (i = switch_core_hash_find_locked(loadable_modules._kind_##_hash, name, loadable_modules.mutex))) { \
2181  PROTECT_INTERFACE(i); \
2182  } \
2183  return i; \
2184  }
2185 
2186 HASH_FUNC(dialplan)
2187 HASH_FUNC(timer)
2188 HASH_FUNC(application)
2189 HASH_FUNC(chat_application)
2190 HASH_FUNC(api)
2191 HASH_FUNC(json_api)
2192 HASH_FUNC(speech)
2193 HASH_FUNC(asr)
2194 HASH_FUNC(directory)
2195 HASH_FUNC(chat)
2196 HASH_FUNC(limit)
2197 
2198 
2200 {
2202 }
2203 
2205 {
2207 }
2208 
2209 #ifdef DEBUG_CODEC_SORTING
2210 static void do_print(const switch_codec_implementation_t **array, int arraylen)
2211 {
2212  int i;
2213 
2214  for(i = 0; i < arraylen; i++) {
2216  "DEBUG %d %s:%d %d\n", i, array[i]->iananame, array[i]->ianacode, array[i]->microseconds_per_packet / 1000);
2217  }
2218 
2219 }
2220 #endif
2221 
2222 /* helper only -- bounds checking enforced by caller */
2223 static void do_swap(const switch_codec_implementation_t **array, int a, int b)
2224 {
2225  const switch_codec_implementation_t *tmp = array[b];
2226  array[b] = array[a];
2227  array[a] = tmp;
2228 }
2229 
2231 {
2232  int i = 0, sorted_ptime = 0;
2233 
2234 #ifdef DEBUG_CODEC_SORTING
2236  do_print(array, arraylen);
2238 #endif
2239 
2240  for (i = 0; i < arraylen; i++) {
2241  int this_ptime = array[i]->microseconds_per_packet / 1000;
2242 
2243  if (!strcasecmp(array[i]->iananame, "ilbc")) {
2244  this_ptime = 20;
2245  }
2246 
2247  if (!sorted_ptime) {
2248  sorted_ptime = this_ptime;
2249 #ifdef DEBUG_CODEC_SORTING
2250  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sorted1 = %d\n", sorted_ptime);
2251 #endif
2252  }
2253 
2254  if (i > 0 && strcasecmp(array[i]->iananame, array[i-1]->iananame) && this_ptime != sorted_ptime) {
2255  int j;
2256  int swapped = 0;
2257 
2258 #ifdef DEBUG_CODEC_SORTING
2259  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%d != %d\n", this_ptime, sorted_ptime);
2260 #endif
2261  for(j = i; j < arraylen; j++) {
2262  int check_ptime = array[j]->microseconds_per_packet / 1000;
2263 
2264  if (!strcasecmp(array[i]->iananame, "ilbc")) {
2265  check_ptime = 20;
2266  }
2267 
2268  if (check_ptime == sorted_ptime) {
2269 #ifdef DEBUG_CODEC_SORTING
2270  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "swap %d %d ptime %d\n", i, j, check_ptime);
2271 #endif
2272  do_swap(array, i, j);
2273  swapped = 1;
2274  break;
2275  }
2276  }
2277 
2278  if (!swapped) {
2279  sorted_ptime = this_ptime;
2280 #ifdef DEBUG_CODEC_SORTING
2281  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sorted2 = %d\n", sorted_ptime);
2282 #endif
2283  }
2284  }
2285  }
2286 
2287 #ifdef DEBUG_CODEC_SORTING
2289  do_print(array, arraylen);
2291 #endif
2292 
2293 }
2294 
2295 
2297 {
2298  switch_hash_index_t *hi;
2299  void *val;
2300  switch_codec_interface_t *codec_interface;
2301  int i = 0;
2302  const switch_codec_implementation_t *imp;
2303  switch_codec_node_t *node, *head;
2304 
2307  switch_core_hash_this(hi, NULL, NULL, &val);
2308  head = (switch_codec_node_t *) val;
2309 
2310  for (node = head; node; node = node->next) {
2311  codec_interface = (switch_codec_interface_t *) node->ptr;
2312 
2313  /* Look for the default ptime of the codec because it's the safest choice */
2314  for (imp = codec_interface->implementations; imp; imp = imp->next) {
2315  uint32_t default_ptime = switch_default_ptime(imp->iananame, imp->ianacode);
2316 
2317  if (imp->microseconds_per_packet / 1000 == (int)default_ptime) {
2318  array[i++] = imp;
2319  goto found;
2320  }
2321  }
2322  /* oh well we will use what we have */
2323  array[i++] = codec_interface->implementations;
2324  }
2325 
2326  found:
2327 
2328  if (i > arraylen) {
2329  break;
2330  }
2331 
2332  }
2333  switch_safe_free(hi);
2334 
2336 
2338 
2339  return i;
2340 
2341 }
2342 
2343 SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit, uint32_t *channels, char **modname)
2344 {
2345  char *cur, *next = NULL, *name, *p;
2346 
2347  name = next = cur = buf;
2348 
2349  *channels = 1;
2350 
2351  for (;;) {
2352  if (!next) {
2353  break;
2354  }
2355 
2356  if ((p = strchr(next, '@'))) {
2357  *p++ = '\0';
2358  }
2359  next = p;
2360 
2361  if (cur != name) {
2362  if (strchr(cur, 'i')) {
2363  *interval = atoi(cur);
2364  } else if ((strchr(cur, 'k') || strchr(cur, 'h'))) {
2365  *rate = atoi(cur);
2366  } else if (strchr(cur, 'b')) {
2367  *bit = atoi(cur);
2368  } else if (strchr(cur, 'c')) {
2369  *channels = atoi(cur);
2370  } else {
2371  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad syntax for codec string. Missing qualifier [h|k|i|b|c] for part [%s]!\n", cur);
2372  }
2373  }
2374  cur = next;
2375  }
2376 
2377  if ((p = strchr(name, '.'))) {
2378  *p++ = '\0';
2379  *modname = name;
2380  name = p;
2381  }
2382 
2383  return name;
2384 }
2385 
2386 SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array, int arraylen, char **prefs, int preflen)
2387 {
2388  int x, i = 0, j = 0;
2389  switch_codec_interface_t *codec_interface;
2390  const switch_codec_implementation_t *imp;
2391 
2393 
2394  for (x = 0; x < preflen; x++) {
2395  char *name, buf[256], jbuf[256], *modname = NULL;
2396  uint32_t interval = 0, rate = 0, bit = 0, channels = 1;
2397 
2398  switch_copy_string(buf, prefs[x], sizeof(buf));
2399  name = switch_parse_codec_buf(buf, &interval, &rate, &bit, &channels, &modname);
2400 
2401  for(j = 0; j < x; j++) {
2402  char *jname, *jmodname = NULL;
2403  uint32_t jinterval = 0, jrate = 0, jbit = 0, jchannels = 1;
2404  uint32_t ointerval = interval, orate = rate, ochannels = channels;
2405 
2406  if (ointerval == 0) {
2407  ointerval = switch_default_ptime(name, 0);
2408  }
2409 
2410  if (orate == 0) {
2411  orate = switch_default_rate(name, 0);
2412  }
2413 
2414  if (ochannels == 0) {
2415  ochannels = 1;
2416  }
2417 
2418  switch_copy_string(jbuf, prefs[j], sizeof(jbuf));
2419  jname = switch_parse_codec_buf(jbuf, &jinterval, &jrate, &jbit, &jchannels, &jmodname);
2420 
2421  if (jinterval == 0) {
2422  jinterval = switch_default_ptime(jname, 0);
2423  }
2424 
2425  if (jrate == 0) {
2426  jrate = switch_default_rate(jname, 0);
2427  }
2428 
2429  if (jchannels == 0) {
2430  jchannels = 1;
2431  }
2432 
2433  if (!strcasecmp(name, jname) && ointerval == jinterval && orate == jrate && ochannels == jchannels) {
2434  goto next_x;
2435  }
2436  }
2437 
2438  if ((codec_interface = switch_loadable_module_get_codec_interface(name, modname)) != 0) {
2439  /* If no specific codec interval is requested opt for the default above all else because lots of stuff assumes it */
2440  for (imp = codec_interface->implementations; imp; imp = imp->next) {
2441  uint32_t default_ptime = switch_default_ptime(imp->iananame, imp->ianacode);
2442  uint32_t default_rate = switch_default_rate(imp->iananame, imp->ianacode);
2443 
2444  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
2445  uint32_t crate = !strcasecmp(imp->iananame, "g722") ? imp->samples_per_second : imp->actual_samples_per_second;
2446 
2447  if ((!interval && (uint32_t) (imp->microseconds_per_packet / 1000) != default_ptime) ||
2448  (interval && (uint32_t) (imp->microseconds_per_packet / 1000) != interval)) {
2449  continue;
2450  }
2451 
2452  if (((!rate && crate != default_rate) || (rate && (uint32_t) imp->actual_samples_per_second != rate))) {
2453  continue;
2454  }
2455 
2456  if (bit && (uint32_t) imp->bits_per_second != bit) {
2457  continue;
2458  }
2459 
2460  if (channels && imp->number_of_channels != channels) {
2461  continue;
2462  }
2463  }
2464 
2465 
2466  array[i++] = imp;
2467  goto found;
2468 
2469  }
2470 
2471  /* Either looking for a specific interval or there was no interval specified and there wasn't one at the default ptime available */
2472  for (imp = codec_interface->implementations; imp; imp = imp->next) {
2473  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
2474  uint32_t crate = !strcasecmp(imp->iananame, "g722") ? imp->samples_per_second : imp->actual_samples_per_second;
2475 
2476  if (interval && (uint32_t) (imp->microseconds_per_packet / 1000) != interval) {
2477  continue;
2478  }
2479 
2480  if (rate && (uint32_t) crate != rate) {
2481  continue;
2482  }
2483 
2484  if (bit && (uint32_t) imp->bits_per_second != bit) {
2485  continue;
2486  }
2487 
2488  if (channels && imp->number_of_channels != channels) {
2489  continue;
2490  }
2491  }
2492 
2493  array[i++] = imp;
2494  goto found;
2495 
2496  }
2497 
2498  found:
2499 
2500  UNPROTECT_INTERFACE(codec_interface);
2501 
2502  if (i > arraylen) {
2503  break;
2504  }
2505 
2506  }
2507 
2508  next_x:
2509 
2510  continue;
2511  }
2512 
2514 
2516 
2517  return i;
2518 }
2519 
2521 {
2523  switch_status_t status;
2524  char *arg_used;
2525  char *cmd_used;
2526 
2527  switch_assert(stream != NULL);
2528  switch_assert(stream->data != NULL);
2529  switch_assert(stream->write_function != NULL);
2530 
2531  if (strcasecmp(cmd, "console_complete")) {
2532  cmd_used = switch_strip_whitespace(cmd);
2533  arg_used = switch_strip_whitespace(arg);
2534  } else {
2535  cmd_used = (char *) cmd;
2536  arg_used = (char *) arg;
2537  }
2538 
2539 
2540  if (!stream->param_event) {
2541  switch_event_create(&stream->param_event, SWITCH_EVENT_API);
2542  }
2543 
2544  if (stream->param_event) {
2545  if (cmd_used && *cmd_used) {
2546  switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_used);
2547  }
2548  if (arg_used && *arg_used) {
2549  switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_used);
2550  }
2551  }
2552 
2553 
2554  if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) {
2555  if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) {
2556  stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
2557  }
2558  UNPROTECT_INTERFACE(api);
2559  } else {
2560  status = SWITCH_STATUS_FALSE;
2561  stream->write_function(stream, "INVALID COMMAND!\n");
2562  }
2563 
2564  if (stream->param_event) {
2565  switch_event_fire(&stream->param_event);
2566  }
2567 
2568  if (cmd_used != cmd) {
2569  switch_safe_free(cmd_used);
2570  }
2571 
2572  if (arg_used != arg) {
2573  switch_safe_free(arg_used);
2574  }
2575 
2576  return status;
2577 }
2578 
2580 {
2581  switch_json_api_interface_t *json_api;
2582  switch_status_t status;
2583  cJSON *function, *json_reply = NULL;
2584 
2585  switch_assert(json);
2586 
2587  function = cJSON_GetObjectItem(json, "command");
2588 
2589  if (function && function->valuestring
2590  && cJSON_GetObjectItem(json, "data") && (json_api = switch_loadable_module_get_json_api_interface(function->valuestring)) != 0) {
2591  if ((status = json_api->function(json, session, &json_reply)) != SWITCH_STATUS_SUCCESS) {
2592  cJSON_AddItemToObject(json, "status", cJSON_CreateString("error"));
2593  cJSON_AddItemToObject(json, "message", cJSON_CreateString("The command returned an error"));
2594  } else {
2595  cJSON_AddItemToObject(json, "status", cJSON_CreateString("success"));
2596  }
2597 
2598  if (!json_reply) {
2599  json_reply = cJSON_CreateNull();
2600  }
2601 
2602  if (retval) {
2603  *retval = json_reply;
2604  } else {
2605  cJSON_AddItemToObject(json, "response", json_reply);
2606  }
2607 
2608  UNPROTECT_INTERFACE(json_api);
2609  } else {
2610  status = SWITCH_STATUS_FALSE;
2611  cJSON_AddItemToObject(json, "status", cJSON_CreateString("error"));
2612  cJSON_AddItemToObject(json, "message", cJSON_CreateString("Invalid request or non-existant command"));
2613  cJSON_AddItemToObject(json, "response", cJSON_CreateNull());
2614  }
2615 
2616  return status;
2617 }
2618 
2619 
2621 {
2623 
2625  switch_assert(mod != NULL);
2626 
2627  mod->pool = pool;
2628 
2629  mod->module_name = switch_core_strdup(mod->pool, name);
2631  return mod;
2632 }
2633 
2634 #define ALLOC_INTERFACE(_TYPE_) { \
2635  switch_##_TYPE_##_interface_t *i, *ptr; \
2636  i = switch_core_alloc(mod->pool, sizeof(switch_##_TYPE_##_interface_t)); \
2637  switch_assert(i != NULL); \
2638  for (ptr = mod->_TYPE_##_interface; ptr && ptr->next; ptr = ptr->next); \
2639  if (ptr) { \
2640  ptr->next = i; \
2641  } else { \
2642  mod->_TYPE_##_interface = i; \
2643  } \
2644  switch_thread_rwlock_create(&i->rwlock, mod->pool); \
2645  switch_mutex_init(&i->reflock, SWITCH_MUTEX_NESTED, mod->pool); \
2646  i->parent = mod; \
2647  return i; }
2648 
2649 
2651 {
2652 
2653  switch (iname) {
2655  ALLOC_INTERFACE(endpoint)
2656 
2658  ALLOC_INTERFACE(timer)
2659 
2661  ALLOC_INTERFACE(dialplan)
2662 
2664  ALLOC_INTERFACE(codec)
2665 
2667  ALLOC_INTERFACE(application)
2668 
2670  ALLOC_INTERFACE(chat_application)
2671 
2672  case SWITCH_API_INTERFACE:
2673  ALLOC_INTERFACE(api)
2674 
2676  ALLOC_INTERFACE(json_api)
2677 
2678  case SWITCH_FILE_INTERFACE:
2679  ALLOC_INTERFACE(file)
2680 
2682  ALLOC_INTERFACE(speech)
2683 
2685  ALLOC_INTERFACE(directory)
2686 
2687  case SWITCH_CHAT_INTERFACE:
2688  ALLOC_INTERFACE(chat)
2689 
2690  case SWITCH_SAY_INTERFACE:
2691  ALLOC_INTERFACE(say)
2692 
2693  case SWITCH_ASR_INTERFACE:
2694  ALLOC_INTERFACE(asr)
2695 
2697  ALLOC_INTERFACE(management)
2698 
2700  ALLOC_INTERFACE(limit)
2701 
2702  default:
2703  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Module Type!\n");
2704  return NULL;
2705  }
2706 }
2707 
2709  char *ext;
2710  int cnt;
2713 };
2714 
2716 {
2717  char *ret = NULL;
2718 
2719  if (sh->param_event) {
2720  ret = switch_event_get_header(sh->param_event, var);
2721  }
2722 
2723  return ret;
2724 
2725 }
2726 
2728 {
2729  return (char *) sh->stream.data;
2730 }
2731 
2733 {
2734  char *path;
2735 
2736  switch_assert(sh);
2737  path = (char *) sh->stream.data;
2738  sh->stream.data = NULL;
2739  return path;
2740 }
2741 
2742 
2744 {
2745  switch_assert(sh);
2746 
2747  switch_safe_free((*sh)->stream.data);
2748  switch_safe_free((*sh)->ext);
2749 
2750  if ((*sh)->param_event) {
2751  switch_event_destroy(&(*sh)->param_event);
2752  }
2753  free(*sh);
2754  *sh = NULL;
2755 }
2756 
2758 {
2759  switch_assert(sh);
2760 
2761  if (zstr(ext)) {
2762  ext = "wav";
2763  }
2764 
2765  *sh = malloc(sizeof(**sh));
2766  memset(*sh, 0, sizeof(**sh));
2767 
2768  SWITCH_STANDARD_STREAM((*sh)->stream);
2769 
2770  if (var_event) {
2771  (*sh)->param_event = *var_event;
2772  *var_event = NULL;
2773  }
2774 
2775  (*sh)->ext = strdup(ext);
2776 
2777  return SWITCH_STATUS_SUCCESS;
2778 }
2779 
2781 {
2782  char buf[256] = "";
2783  int ret;
2784  va_list ap;
2785 
2786  va_start(ap, fmt);
2787 
2788  if ((ret = switch_vsnprintf(buf, sizeof(buf), fmt, ap)) > 0) {
2789  if (!sh->cnt++) {
2790  sh->stream.write_function(&sh->stream, "file_string://%s.%s", buf, sh->ext);
2791  } else if (strstr(buf, "://")) {
2792  sh->stream.write_function(&sh->stream, "!%s", buf);
2793  } else {
2794  sh->stream.write_function(&sh->stream, "!%s.%s", buf, sh->ext);
2795  }
2796 
2797  }
2798 
2799  va_end(ap);
2800 }
2801 
2803 {
2805 
2809 
2810  return cb;
2811 }
2812 
2813 
2815 {
2817 
2818  switch_assert(cb);
2819 
2822  status = SWITCH_STATUS_FALSE;
2823  } else {
2825  }
2827 
2828  return status;
2829 }
2830 
2831 
2833 {
2837 }
2838 
2839 
2840 /* For Emacs:
2841  * Local Variables:
2842  * mode:c
2843  * indent-tabs-mode:t
2844  * tab-width:4
2845  * c-basic-offset:4
2846  * End:
2847  * For VIM:
2848  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2849  */
struct apr_queue_t switch_queue_t
Definition: switch_apr.h:590
void * switch_core_hash_find_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_mutex_t *mutex)
Retrieve data from a given hash.
char * switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var)
static struct switch_loadable_module_container loadable_modules
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
void switch_say_file(switch_say_file_handle_t *sh, const char *fmt,...)
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
A module interface to implement an application.
switch_status_t switch_thread_rwlock_unlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:263
const char * switch_xml_attr_soft(_In_ switch_xml_t xml, _In_z_ const char *attr)
returns the value of the requested tag attribute, or "" if not found
switch_module_load_t switch_module_load
switch_memory_pool_t * pool
struct switch_directory_interface * next
#define switch_event_expand_headers(_event, _in)
Definition: switch_event.h:354
#define ALLOC_INTERFACE(_TYPE_)
#define SWITCH_THREAD_FUNC
Abstract interface to a limit module.
cJSON * cJSON_CreateNull(void)
Definition: switch_json.c:537
static int IDX
#define SWITCH_CHANNEL_LOG
switch_status_t switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime, const char **err)
Load a module.
static void chat_queue_message(switch_event_t **eventp)
switch_status_t switch_core_hash_destroy(_Inout_ switch_hash_t **hash)
Destroy an existing hash table.
switch_api_function_t function
switch_thread_rwlock_t * rwlock
void * switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ const char *key)
Retrieve data from a given hash.
switch_dialplan_interface_t * dialplan_interface
switch_json_api_interface_t * switch_loadable_module_get_json_api_interface(const char *name)
Retrieve the JSON API interface by it's registered name.
Abstraction of an module endpoint interface This is the glue between the abstract idea of a "channel"...
switch_directory_interface_t * directory_interface
#define switch_core_hash_init(_hash)
Definition: switch_core.h:1390
const switch_codec_interface_t * ptr
struct switch_management_interface * next
switch_thread_rwlock_t * rwlock
#define switch_core_session_hupall_matching_var(_vn, _vv, _c)
Definition: switch_core.h:984
switch_core_recover_callback_t switch_core_get_secondary_recover_callback(const char *key)
switch_status_t switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data)
Enumerates a list of all modules discovered in a directory.
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
switch_status_t switch_loadable_module_build_dynamic(char *filename, switch_module_load_t switch_module_load, switch_module_runtime_t switch_module_runtime, switch_module_shutdown_t switch_module_shutdown, switch_bool_t runtime)
build a dynamic module object and register it (for use in double embeded modules) ...
switch_bool_t
Definition: switch_types.h:405
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
switch_status_t(* chat_send)(switch_event_t *message_event)
switch_chat_application_function_t chat_application_function
switch_status_t switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
Execute a registered API command.
switch_codec_interface_t * codec_interface
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:660
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
struct switch_stream_handle stream
Representation of an event.
Definition: switch_event.h:80
A module interface to implement a chat application.
switch_codec_implementation_t * implementations
switch_status_t switch_event_add_body(switch_event_t *event, const char *fmt,...) PRINTF_FUNCTION(2
Add a body to an event.
struct switch_endpoint_interface * next
#define FREESWITCH_OID_PREFIX
Definition: switch.h:53
int msg_queue_len
switch_management_interface_t * switch_loadable_module_get_management_interface(const char *relative_oid)
Retrieve the management interface by it's registered name.
Abstract interface to a chat module.
char * switch_strip_whitespace(const char *str)
static void switch_loadable_module_sort_codecs(const switch_codec_implementation_t **array, int arraylen)
A representation of an XML tree.
Definition: switch_xml.h:76
Abstract interface to a dialplan module.
switch_status_t switch_queue_pop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1119
switch_status_t switch_json_api_execute(cJSON *json, switch_core_session_t *session, cJSON **retval)
Execute a registered JSON API command.
struct switch_speech_interface * next
A table of functions that a timer module implements.
void *SWITCH_THREAD_FUNC chat_thread_run(switch_thread_t *thread, void *obj)
switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
Duplicate an event.
#define SWITCH_API_VERSION
pack cur
static switch_thread_t * thread
Definition: switch_log.c:279
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
struct switch_runtime runtime
Definition: switch_core.c:64
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
switch_thread_rwlock_t * rwlock
Abstract interface to an asr module.
switch_thread_rwlock_t * rwlock
void switch_loadable_module_shutdown(void)
Shutdown the module backend and call the shutdown routine in all loaded modules.
switch_api_interface_t * switch_loadable_module_get_api_interface(const char *name)
Retrieve the API interface by it's registered name.
Abstract interface to a file format module.
switch_memory_pool_t * pool
Definition: switch_core.h:223
#define zstr(x)
Definition: switch_utils.h:281
static switch_status_t chat_process_event(switch_event_t **eventp)
struct switch_codec_node_s switch_codec_node_t
switch_memory_pool_t * pool
int(* switch_modulename_callback_func_t)(void *user_data, const char *module_name)
struct switch_json_api_interface * next
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
switch_thread_t * msg_queue_thread[CHAT_MAX_MSG_QUEUE]
switch_status_t switch_thread_exit(switch_thread_t *thd, switch_status_t retval)
Definition: switch_apr.c:1245
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1255
struct switch_timer_interface * next
#define UNPROTECT_INTERFACE(_it)
switch_status_t switch_core_chat_send(const char *dest_proto, switch_event_t *message_event)
#define HASH_FUNC(_kind_)
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
void switch_core_unregister_secondary_recover_callback(const char *key)
switch_timer_interface_t * timer_interface
switch_thread_rwlock_t * rwlock
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:122
switch_xml_t next
Definition: switch_xml.h:88
switch_chat_interface_t * switch_loadable_module_get_chat_interface(const char *name)
Retrieve the chat interface by it's registered name.
Abstract interface to a speech module.
switch_byte_t switch_byte_t * buf
static switch_status_t switch_loadable_module_load_file(char *path, char *filename, switch_bool_t global, switch_loadable_module_t **new_module)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
A module interface to implement an api function.
static void switch_loadable_module_runtime(void)
switch_status_t switch_core_hash_insert_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const void *data, _In_opt_ switch_mutex_t *mutex)
Insert data into a hash.
#define CHAT_MAX_MSG_QUEUE
struct switch_dialplan_interface * next
Abstract interface to a say module.
switch_status_t switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
switch_core_flag_t switch_core_flags(void)
return core flags
Definition: switch_core.c:2852
void switch_dso_destroy(switch_dso_lib_t *lib)
Definition: switch_dso.c:87
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
Abstract interface to a management module.
switch_chat_interface_t * chat_interface
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:551
switch_speech_interface_t * speech_interface
#define CHAT_QUEUE_SIZE
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
struct switch_api_interface * next
switch_file_interface_t * switch_loadable_module_get_file_interface(const char *name, const char *modname)
Retrieve the file format interface by it's registered name.
static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t *old_module)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
Top level module interface to implement a series of codec implementations.
switch_endpoint_interface_t * endpoint_interface
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
int switch_loadable_module_get_codecs(const switch_codec_implementation_t **array, int arraylen)
Retrieve the list of loaded codecs into an array.
switch_status_t switch_loadable_module_exists(const char *mod)
Check if a module is loaded.
void switch_core_hash_this(_In_ switch_hash_index_t *hi, _Out_opt_ptrdiff_cap_(klen) const void **key, _Out_opt_ switch_ssize_t *klen, _Out_ void **val)
Gets the key and value of the current hash element.
switch_module_interface_name_t
Definition: switch_types.h:378
uintptr_t switch_size_t
struct switch_codec_interface * next
struct switch_chat_interface * next
static switch_status_t switch_loadable_module_load_module_ex(char *dir, char *fname, switch_bool_t runtime, switch_bool_t global, const char **err)
switch_hash_index_t * switch_core_hash_next(_In_ switch_hash_index_t **hi)
Gets the next element of a hashtable.
uint32_t switch_default_ptime(const char *name, uint32_t number)
Definition: switch_core.c:2026
char * switch_say_file_handle_detach_path(switch_say_file_handle_t *sh)
switch_status_t switch_dir_open(switch_dir_t **new_dir, const char *dirname, switch_memory_pool_t *pool)
Definition: switch_apr.c:538
struct switch_chat_application_interface * next
struct switch_codec_node_s * next
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
Definition: switch_json.c:520
void switch_cond_next(void)
Definition: switch_time.c:638
switch_queue_t * msg_queue[CHAT_MAX_MSG_QUEUE]
#define SWITCH_STANDARD_STREAM(s)
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
cJSON * cJSON_GetObjectItem(const cJSON *object, const char *string)
Definition: switch_json.c:498
switch_thread_rwlock_t * rwlock
switch_dso_lib_t switch_dso_open(const char *path, int global, char **err)
Definition: switch_dso.c:95
void * objs[SWITCH_MAX_CORE_THREAD_SESSION_OBJS]
Definition: switch_core.h:220
switch_file_interface_t * file_interface
void * switch_core_hash_delete(_In_ switch_hash_t *hash, _In_z_ const char *key)
Delete data from a hash based on desired key.
switch_application_interface_t * application_interface
const char * switch_dir_next_file(switch_dir_t *thedir, char *buf, switch_size_t len)
Definition: switch_apr.c:595
switch_codec_interface_t * switch_loadable_module_get_codec_interface(const char *name, const char *modname)
Retrieve the codec interface by it's registered name.
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:60
switch_limit_interface_t * limit_interface
cJSON * cJSON_CreateString(const char *string)
Definition: switch_json.c:542
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
switch_management_interface_t * management_interface
static struct @5 chat_globals
struct apr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
int switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array, int arraylen, char **prefs, int preflen)
Retrieve the list of loaded codecs into an array based on another array showing the sorted order...
switch_status_t
Common return values.
switch_chat_application_interface_t * switch_loadable_module_get_chat_application_interface(const char *name)
Retrieve the chat application interface by it's registered name.
switch_status_t switch_loadable_module_unload_module(char *dir, char *fname, switch_bool_t force, const char **err)
Unoad a module.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:256
switch_loadable_module_interface_t * module_interface
switch_endpoint_interface_t * switch_loadable_module_get_endpoint_interface(const char *name)
Retrieve the endpoint interface by it's registered name.
switch_say_interface_t * switch_loadable_module_get_say_interface(const char *name)
Retrieve the say interface by it's registered name.
switch_xml_t switch_xml_open_cfg(_In_z_ const char *file_path, _Out_ switch_xml_t *node, _In_opt_ switch_event_t *params)
open a config in the core registry
char * switch_say_file_handle_get_path(switch_say_file_handle_t *sh)
static switch_status_t do_chat_send(switch_event_t *message_event)
switch_thread_rwlock_t * rwlock
struct switch_file_node_s * next
switch_thread_t * switch_core_launch_thread(void *(SWITCH_THREAD_FUNC *func)(switch_thread_t *, void *), void *obj, switch_memory_pool_t *pool)
Launch a thread.
switch_status_t switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint, switch_bool_t blocking)
switch_loadable_module_interface_t * switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name)
switch_json_api_interface_t * json_api_interface
#define switch_core_hash_insert(_h, _k, _d)
Definition: switch_core.h:1410
struct apr_thread_t switch_thread_t
Definition: switch_apr.h:941
Main Library Header.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
static switch_bool_t switch_is_file_path(const char *file)
switch_status_t switch_core_register_secondary_recover_callback(const char *key, switch_core_recover_callback_t cb)
#define SWITCH_DECLARE(type)
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
static void *SWITCH_THREAD_FUNC switch_loadable_module_exec(switch_thread_t *thread, void *obj)
switch_status_t switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data)
Enumerates a list of all currently loaded modules.
static void do_swap(const switch_codec_implementation_t **array, int a, int b)
switch_status_t switch_core_execute_chat_app(switch_event_t *message, const char *app, const char *data)
switch_status_t switch_queue_trypush(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1155
struct switch_say_interface * next
void switch_core_session_hupall_endpoint(const switch_endpoint_interface_t *endpoint_interface, switch_call_cause_t cause)
Hangup all sessions that belong to an endpoint.
int(* switch_core_recover_callback_t)(switch_core_session_t *session)
struct switch_codec_implementation * next
switch_module_runtime_t switch_module_runtime
switch_thread_rwlock_t * rwlock
switch_status_t switch_loadable_module_init(switch_bool_t autoload)
Initilize the module backend and load all the modules.
A generic object to pass as a thread's session object to allow mutiple arguements and a pool...
Definition: switch_core.h:214
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1129
switch_status_t switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event)
void * switch_dso_data_sym(switch_dso_lib_t lib, const char *sym, char **err)
Definition: switch_dso.c:126
struct apr_pool_t switch_memory_pool_t
static void chat_thread_start(int idx)
struct switch_application_interface * next
switch_status_t switch_thread_rwlock_create(switch_thread_rwlock_t **rwlock, switch_memory_pool_t *pool)
Definition: switch_apr.c:212
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
switch_module_shutdown_t shutdown
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
const char * switch_stristr(const char *instr, const char *str)
#define SWITCH_CURRENT_APPLICATION_VARIABLE
Definition: switch_types.h:140
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:642
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:675
A table of settings and callbacks that define a paticular implementation of a codec.
#define PROTECT_INTERFACE(_it)
A module interface to implement a json api function.
void * switch_dso_lib_t
Definition: switch_dso.h:30
const switch_file_interface_t * ptr
void switch_say_file_handle_destroy(switch_say_file_handle_t **sh)
struct switch_limit_interface * next
switch_api_interface_t * api_interface
switch_status_t switch_thread_rwlock_trywrlock_timeout(switch_thread_rwlock_t *rwlock, int timeout)
Definition: switch_apr.c:247
switch_status_t switch_queue_create(switch_queue_t **queue, unsigned int queue_capacity, switch_memory_pool_t *pool)
Definition: switch_apr.c:1109
void switch_core_set_signal_handlers(void)
Definition: switch_core.c:2494
void switch_event_destroy(switch_event_t **event)
Destroy an event.
switch_json_api_function_t function
int switch_vsnprintf(char *buf, switch_size_t len, const char *format, va_list ap)
Definition: switch_apr.c:194
char * filename
switch_asr_interface_t * asr_interface
char * switch_core_sprintf(_In_ switch_memory_pool_t *pool, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the pool ...
#define switch_assert(expr)
static switch_status_t switch_loadable_module_process(char *key, switch_loadable_module_t *new_module)
const char * switch_cut_path(const char *in)
Create a pointer to the file name in a given file path eliminating the directory name.
switch_say_interface_t * say_interface
switch_module_shutdown_t switch_module_shutdown
switch_chat_application_interface_t * chat_application_interface
char * switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit, uint32_t *channels, char **modname)
struct switch_file_interface * next
#define switch_core_hash_first(_h)
Definition: switch_core.h:1501
switch_thread_rwlock_t * rwlock
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
uint32_t switch_default_rate(const char *name, uint32_t number)
Definition: switch_core.c:2037
memset(buf, 0, buflen)
#define switch_core_hash_init_nocase(_hash)
Definition: switch_core.h:1391
The abstraction of a loadable module.
static switch_status_t do_shutdown(switch_loadable_module_t *module, switch_bool_t shutdown, switch_bool_t unload, switch_bool_t fail_if_busy, const char **err)
void * switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname)
Abstract interface to a directory module.
struct switch_asr_interface * next
switch_status_t switch_thread_rwlock_trywrlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:242
switch_status_t switch_dir_close(switch_dir_t *thedir)
Definition: switch_apr.c:559
struct switch_file_node_s switch_file_node_t