File: | switch_loadable_module.c |
Warning: | line 792, column 2 Potential leak of memory pointed to by 'event_num' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | * Andrey Volk <andywolk@gmail.com> | |||
29 | * | |||
30 | * switch_loadable_module.c -- Loadable Modules | |||
31 | * | |||
32 | */ | |||
33 | ||||
34 | #include <switch.h> | |||
35 | #include "private/switch_core_pvt.h" | |||
36 | ||||
37 | /* for apr_pstrcat */ | |||
38 | #include <apr_strings.h> | |||
39 | ||||
40 | /* for apr_env_get and apr_env_set */ | |||
41 | #include <apr_env.h> | |||
42 | ||||
43 | /* for apr file and directory handling */ | |||
44 | #include <apr_file_io.h> | |||
45 | ||||
46 | typedef struct switch_file_node_s { | |||
47 | const switch_file_interface_t *ptr; | |||
48 | const char *interface_name; | |||
49 | struct switch_file_node_s *next; | |||
50 | } switch_file_node_t; | |||
51 | ||||
52 | typedef struct switch_database_node_s { | |||
53 | const switch_database_interface_t *ptr; | |||
54 | const char *interface_name; | |||
55 | struct switch_database_node_s *next; | |||
56 | } switch_database_node_t; | |||
57 | ||||
58 | typedef struct switch_codec_node_s { | |||
59 | const switch_codec_interface_t *ptr; | |||
60 | const char *interface_name; | |||
61 | struct switch_codec_node_s *next; | |||
62 | } switch_codec_node_t; | |||
63 | ||||
64 | ||||
65 | struct switch_loadable_module { | |||
66 | char *key; | |||
67 | char *filename; | |||
68 | int perm; | |||
69 | switch_loadable_module_interface_t *module_interface; | |||
70 | switch_dso_lib_t lib; | |||
71 | switch_module_load_t switch_module_load; | |||
72 | switch_module_runtime_t switch_module_runtime; | |||
73 | switch_module_shutdown_t switch_module_shutdown; | |||
74 | switch_memory_pool_t *pool; | |||
75 | switch_status_t status; | |||
76 | switch_thread_t *thread; | |||
77 | switch_bool_t shutting_down; | |||
78 | switch_loadable_module_type_t type; | |||
79 | }; | |||
80 | ||||
81 | struct switch_loadable_module_container { | |||
82 | switch_hash_t *module_hash; | |||
83 | switch_hash_t *endpoint_hash; | |||
84 | switch_hash_t *codec_hash; | |||
85 | switch_hash_t *dialplan_hash; | |||
86 | switch_hash_t *timer_hash; | |||
87 | switch_hash_t *application_hash; | |||
88 | switch_hash_t *chat_application_hash; | |||
89 | switch_hash_t *api_hash; | |||
90 | switch_hash_t *json_api_hash; | |||
91 | switch_hash_t *file_hash; | |||
92 | switch_hash_t *speech_hash; | |||
93 | switch_hash_t *asr_hash; | |||
94 | switch_hash_t *directory_hash; | |||
95 | switch_hash_t *chat_hash; | |||
96 | switch_hash_t *say_hash; | |||
97 | switch_hash_t *management_hash; | |||
98 | switch_hash_t *limit_hash; | |||
99 | switch_hash_t *database_hash; | |||
100 | switch_hash_t *secondary_recover_hash; | |||
101 | switch_mutex_t *mutex; | |||
102 | switch_memory_pool_t *pool; | |||
103 | }; | |||
104 | ||||
105 | static struct switch_loadable_module_container loadable_modules; | |||
106 | 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, | |||
107 | const char **err); | |||
108 | static switch_status_t switch_loadable_module_load_module_ex(const char *dir, const char *fname, switch_bool_t runtime, switch_bool_t global, const char **err, switch_loadable_module_type_t type, switch_hash_t *event_hash); | |||
109 | ||||
110 | static void *SWITCH_THREAD_FUNC switch_loadable_module_exec(switch_thread_t *thread, void *obj) | |||
111 | { | |||
112 | ||||
113 | ||||
114 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||
115 | switch_core_thread_session_t *ts = obj; | |||
116 | switch_loadable_module_t *module = ts->objs[0]; | |||
117 | int restarts; | |||
118 | ||||
119 | switch_assert(thread != NULL)((thread != ((void*)0)) ? (void) (0) : __assert_fail ("thread != ((void*)0)" , "src/switch_loadable_module.c", 119, __extension__ __PRETTY_FUNCTION__ )); | |||
120 | switch_assert(module != NULL)((module != ((void*)0)) ? (void) (0) : __assert_fail ("module != ((void*)0)" , "src/switch_loadable_module.c", 120, __extension__ __PRETTY_FUNCTION__ )); | |||
121 | ||||
122 | for (restarts = 0; status != SWITCH_STATUS_TERM && !module->shutting_down; restarts++) { | |||
123 | status = module->switch_module_runtime(); | |||
124 | } | |||
125 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 125, ((void*)0), SWITCH_LOG_NOTICE, "Thread ended for %s\n", module->module_interface->module_name); | |||
126 | ||||
127 | if (ts->pool) { | |||
128 | switch_memory_pool_t *pool = ts->pool; | |||
129 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 129, ((void*)0), SWITCH_LOG_DEBUG, "Destroying Pool for %s\n", module->module_interface->module_name); | |||
130 | switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_loadable_module.c" , (const char *)__func__, 130); | |||
131 | } | |||
132 | switch_thread_exit(thread, 0); | |||
133 | return NULL((void*)0); | |||
134 | } | |||
135 | ||||
136 | ||||
137 | static void switch_loadable_module_runtime(void) | |||
138 | { | |||
139 | switch_hash_index_t *hi; | |||
140 | void *val; | |||
141 | switch_loadable_module_t *module; | |||
142 | ||||
143 | switch_mutex_lock(loadable_modules.mutex); | |||
144 | for (hi = switch_core_hash_first(loadable_modules.module_hash)switch_core_hash_first_iter(loadable_modules.module_hash, ((void *)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
145 | switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val); | |||
146 | module = (switch_loadable_module_t *) val; | |||
147 | ||||
148 | if (module->switch_module_runtime) { | |||
149 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 149, ((void*)0), SWITCH_LOG_CONSOLE, "Starting runtime thread for %s\n", module->module_interface->module_name); | |||
150 | module->thread = switch_core_launch_thread(switch_loadable_module_exec, module, loadable_modules.pool); | |||
151 | } | |||
152 | } | |||
153 | switch_mutex_unlock(loadable_modules.mutex); | |||
154 | } | |||
155 | ||||
156 | static switch_status_t switch_loadable_module_process(char *key, switch_loadable_module_t *new_module, switch_hash_t *event_hash) | |||
157 | { | |||
158 | switch_event_t *event; | |||
159 | int *event_num = NULL((void*)0); | |||
160 | char str_event_num[12]; | |||
161 | void *val; | |||
162 | int added = 0; | |||
163 | ||||
164 | if (event_hash) { | |||
| ||||
165 | if ((val = switch_core_hash_find(event_hash, "0"))) { | |||
166 | event_num = (int*)val; | |||
167 | } else { | |||
168 | if (!(event_num = malloc(sizeof(int)))) { | |||
169 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 169, ((void*)0), SWITCH_LOG_CRIT, "Allocation error.\n"); | |||
170 | return SWITCH_STATUS_MEMERR; | |||
171 | } | |||
172 | ||||
173 | *event_num = 0; | |||
174 | switch_core_hash_insert(event_hash, "0", (const void*)event_num)switch_core_hash_insert_destructor(event_hash, "0", (const void *)event_num, ((void*)0)); | |||
175 | } | |||
176 | } | |||
177 | ||||
178 | new_module->key = switch_core_strdup(new_module->pool, key)switch_core_perform_strdup(new_module->pool, key, "src/switch_loadable_module.c" , (const char *)__func__, 178); | |||
179 | ||||
180 | switch_mutex_lock(loadable_modules.mutex); | |||
181 | switch_core_hash_insert(loadable_modules.module_hash, key, new_module)switch_core_hash_insert_destructor(loadable_modules.module_hash , key, new_module, ((void*)0)); | |||
182 | ||||
183 | if (new_module->module_interface->endpoint_interface) { | |||
184 | const switch_endpoint_interface_t *ptr; | |||
185 | for (ptr = new_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) { | |||
186 | if (!ptr->interface_name) { | |||
187 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 187, ((void*)0), SWITCH_LOG_CRIT, "Failed to load endpoint interface from %s due to no interface name.\n", key); | |||
188 | } else { | |||
189 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 189, ((void*)0), SWITCH_LOG_NOTICE, "Adding Endpoint '%s'\n", ptr->interface_name); | |||
190 | switch_core_hash_insert(loadable_modules.endpoint_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.endpoint_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
191 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 191, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
192 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "endpoint"); | |||
193 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
194 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
195 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
196 | ||||
197 | if (!event_hash) { | |||
198 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 198, &event, ((void*)0)); | |||
199 | } else { | |||
200 | sprintf(str_event_num, "%i", ++*event_num); | |||
201 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
202 | } | |||
203 | ||||
204 | added++; | |||
205 | } | |||
206 | } | |||
207 | } | |||
208 | } | |||
209 | ||||
210 | if (new_module->module_interface->codec_interface) { | |||
211 | const switch_codec_implementation_t *impl; | |||
212 | const switch_codec_interface_t *ptr; | |||
213 | ||||
214 | for (ptr = new_module->module_interface->codec_interface; ptr; ptr = ptr->next) { | |||
215 | if (!ptr->interface_name) { | |||
216 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 216, ((void*)0), SWITCH_LOG_CRIT, "Failed to load codec interface from %s due to no interface name.\n", key); | |||
217 | } else { | |||
218 | unsigned load_interface = 1; | |||
219 | switch_codec_node_t *node, *head; | |||
220 | ||||
221 | for (impl = ptr->implementations; impl; impl = impl->next) { | |||
222 | if (!impl->iananame) { | |||
223 | load_interface = 0; | |||
224 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 224, ((void*)0), SWITCH_LOG_CRIT, | |||
225 | "Failed to load codec interface %s from %s due to no iana name in an implementation.\n", ptr->interface_name, | |||
226 | key); | |||
227 | break; | |||
228 | } | |||
229 | if (impl->decoded_bytes_per_packet > SWITCH_RECOMMENDED_BUFFER_SIZE8192) { | |||
230 | load_interface = 0; | |||
231 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 231, ((void*)0), SWITCH_LOG_CRIT, | |||
232 | "Failed to load codec interface %s from %s due to bytes per frame %d exceeding buffer size %d.\n", | |||
233 | ptr->interface_name, | |||
234 | key, impl->decoded_bytes_per_packet, SWITCH_RECOMMENDED_BUFFER_SIZE8192); | |||
235 | break; | |||
236 | } | |||
237 | } | |||
238 | if (load_interface) { | |||
239 | for (impl = ptr->implementations; impl; impl = impl->next) { | |||
240 | if (impl->bits_per_second) { | |||
241 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 241, ((void*)0), SWITCH_LOG_NOTICE, | |||
242 | "Adding Codec %s %d %s %dhz %dms %dch %dbps\n", | |||
243 | impl->iananame, impl->ianacode, | |||
244 | ptr->interface_name, impl->actual_samples_per_second, | |||
245 | impl->microseconds_per_packet / 1000, impl->number_of_channels, impl->bits_per_second); | |||
246 | } else { | |||
247 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 247, ((void*)0), SWITCH_LOG_NOTICE, | |||
248 | "Adding Codec %s %d %s %dhz %dms %dch (VBR)\n", | |||
249 | impl->iananame, impl->ianacode, | |||
250 | ptr->interface_name, impl->actual_samples_per_second, impl->microseconds_per_packet / 1000, impl->number_of_channels); | |||
251 | } | |||
252 | ||||
253 | node = switch_core_alloc(new_module->pool, sizeof(*node))switch_core_perform_alloc(new_module->pool, sizeof(*node), "src/switch_loadable_module.c", (const char *)__func__, 253); | |||
254 | node->ptr = ptr; | |||
255 | node->interface_name = switch_core_strdup(new_module->pool, new_module->module_interface->module_name)switch_core_perform_strdup(new_module->pool, new_module-> module_interface->module_name, "src/switch_loadable_module.c" , (const char *)__func__, 255); | |||
256 | if ((head = switch_core_hash_find(loadable_modules.codec_hash, impl->iananame))) { | |||
257 | node->next = head; | |||
258 | } | |||
259 | ||||
260 | switch_core_hash_insert(loadable_modules.codec_hash, impl->iananame, (const void *) node)switch_core_hash_insert_destructor(loadable_modules.codec_hash , impl->iananame, (const void *) node, ((void*)0)); | |||
261 | } | |||
262 | ||||
263 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 263, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
264 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "codec"); | |||
265 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
266 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
267 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
268 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", new_module->module_interface->module_name); | |||
269 | ||||
270 | if (!event_hash) { | |||
271 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 271, &event, ((void*)0)); | |||
272 | } | |||
273 | else { | |||
274 | sprintf(str_event_num, "%i", ++*event_num); | |||
275 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
276 | } | |||
277 | ||||
278 | added++; | |||
279 | } | |||
280 | } | |||
281 | } | |||
282 | } | |||
283 | } | |||
284 | ||||
285 | if (new_module->module_interface->dialplan_interface) { | |||
286 | const switch_dialplan_interface_t *ptr; | |||
287 | ||||
288 | for (ptr = new_module->module_interface->dialplan_interface; ptr; ptr = ptr->next) { | |||
289 | if (!ptr->interface_name) { | |||
290 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 290, ((void*)0), SWITCH_LOG_CRIT, "Failed to load dialplan interface from %s due to no interface name.\n", key); | |||
291 | } else { | |||
292 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 292, ((void*)0), SWITCH_LOG_NOTICE, "Adding Dialplan '%s'\n", ptr->interface_name); | |||
293 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 293, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
294 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "dialplan"); | |||
295 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
296 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
297 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
298 | ||||
299 | if (!event_hash) { | |||
300 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 300, &event, ((void*)0)); | |||
301 | } | |||
302 | else { | |||
303 | sprintf(str_event_num, "%i", ++*event_num); | |||
304 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
305 | } | |||
306 | ||||
307 | added++; | |||
308 | } | |||
309 | switch_core_hash_insert(loadable_modules.dialplan_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.dialplan_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
310 | } | |||
311 | } | |||
312 | } | |||
313 | ||||
314 | if (new_module->module_interface->timer_interface) { | |||
315 | const switch_timer_interface_t *ptr; | |||
316 | ||||
317 | for (ptr = new_module->module_interface->timer_interface; ptr; ptr = ptr->next) { | |||
318 | if (!ptr->interface_name) { | |||
319 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 319, ((void*)0), SWITCH_LOG_CRIT, "Failed to load timer interface from %s due to no interface name.\n", key); | |||
320 | } else { | |||
321 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 321, ((void*)0), SWITCH_LOG_NOTICE, "Adding Timer '%s'\n", ptr->interface_name); | |||
322 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 322, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
323 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "timer"); | |||
324 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
325 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
326 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
327 | ||||
328 | if (!event_hash) { | |||
329 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 329, &event, ((void*)0)); | |||
330 | } | |||
331 | else { | |||
332 | sprintf(str_event_num, "%i", ++*event_num); | |||
333 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
334 | } | |||
335 | ||||
336 | added++; | |||
337 | } | |||
338 | switch_core_hash_insert(loadable_modules.timer_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.timer_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
339 | } | |||
340 | } | |||
341 | } | |||
342 | ||||
343 | if (new_module->module_interface->application_interface) { | |||
344 | const switch_application_interface_t *ptr; | |||
345 | ||||
346 | for (ptr = new_module->module_interface->application_interface; ptr; ptr = ptr->next) { | |||
347 | if (!ptr->interface_name) { | |||
348 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 348, ((void*)0), SWITCH_LOG_CRIT, "Failed to load application interface from %s due to no interface name.\n", key); | |||
349 | } else { | |||
350 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 350, ((void*)0), SWITCH_LOG_NOTICE, "Adding Application '%s'\n", ptr->interface_name); | |||
351 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 351, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
352 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application"); | |||
353 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
354 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->short_desc)(ptr->short_desc ? ptr->short_desc : "")); | |||
355 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
356 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
357 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
358 | ||||
359 | if (!event_hash) { | |||
360 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 360, &event, ((void*)0)); | |||
361 | } | |||
362 | else { | |||
363 | sprintf(str_event_num, "%i", ++*event_num); | |||
364 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
365 | } | |||
366 | ||||
367 | added++; | |||
368 | } | |||
369 | switch_core_hash_insert(loadable_modules.application_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.application_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
370 | } | |||
371 | } | |||
372 | } | |||
373 | ||||
374 | if (new_module->module_interface->chat_application_interface) { | |||
375 | const switch_chat_application_interface_t *ptr; | |||
376 | ||||
377 | for (ptr = new_module->module_interface->chat_application_interface; ptr; ptr = ptr->next) { | |||
378 | if (!ptr->interface_name) { | |||
379 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 379, ((void*)0), SWITCH_LOG_CRIT, "Failed to load application interface from %s due to no interface name.\n", key); | |||
380 | } else { | |||
381 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 381, ((void*)0), SWITCH_LOG_NOTICE, "Adding Chat Application '%s'\n", ptr->interface_name); | |||
382 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 382, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
383 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application"); | |||
384 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
385 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->short_desc)(ptr->short_desc ? ptr->short_desc : "")); | |||
386 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
387 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
388 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
389 | ||||
390 | if (!event_hash) { | |||
391 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 391, &event, ((void*)0)); | |||
392 | } | |||
393 | else { | |||
394 | sprintf(str_event_num, "%i", ++*event_num); | |||
395 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
396 | } | |||
397 | ||||
398 | added++; | |||
399 | } | |||
400 | switch_core_hash_insert(loadable_modules.chat_application_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.chat_application_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
401 | } | |||
402 | } | |||
403 | } | |||
404 | ||||
405 | if (new_module->module_interface->api_interface) { | |||
406 | const switch_api_interface_t *ptr; | |||
407 | ||||
408 | for (ptr = new_module->module_interface->api_interface; ptr; ptr = ptr->next) { | |||
409 | if (!ptr->interface_name) { | |||
410 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 410, ((void*)0), SWITCH_LOG_CRIT, "Failed to load api interface from %s due to no interface name.\n", key); | |||
411 | } else { | |||
412 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 412, ((void*)0), SWITCH_LOG_NOTICE, "Adding API Function '%s'\n", ptr->interface_name); | |||
413 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 413, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
414 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "api"); | |||
415 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
416 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->desc)(ptr->desc ? ptr->desc : "")); | |||
417 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
418 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
419 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
420 | ||||
421 | if (!event_hash) { | |||
422 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 422, &event, ((void*)0)); | |||
423 | } | |||
424 | else { | |||
425 | sprintf(str_event_num, "%i", ++*event_num); | |||
426 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
427 | } | |||
428 | ||||
429 | added++; | |||
430 | } | |||
431 | switch_core_hash_insert(loadable_modules.api_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.api_hash, ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
432 | } | |||
433 | } | |||
434 | } | |||
435 | ||||
436 | if (new_module->module_interface->json_api_interface) { | |||
437 | const switch_json_api_interface_t *ptr; | |||
438 | ||||
439 | for (ptr = new_module->module_interface->json_api_interface; ptr; ptr = ptr->next) { | |||
440 | if (!ptr->interface_name) { | |||
441 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 441, ((void*)0), SWITCH_LOG_CRIT, "Failed to load JSON api interface from %s due to no interface name.\n", key); | |||
442 | } else { | |||
443 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 443, ((void*)0), SWITCH_LOG_NOTICE, "Adding JSON API Function '%s'\n", ptr->interface_name); | |||
444 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 444, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
445 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "json_api"); | |||
446 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
447 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->desc)(ptr->desc ? ptr->desc : "")); | |||
448 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
449 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
450 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
451 | ||||
452 | if (!event_hash) { | |||
453 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 453, &event, ((void*)0)); | |||
454 | } | |||
455 | else { | |||
456 | sprintf(str_event_num, "%i", ++*event_num); | |||
457 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
458 | } | |||
459 | ||||
460 | added++; | |||
461 | } | |||
462 | switch_core_hash_insert(loadable_modules.json_api_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.json_api_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
463 | } | |||
464 | } | |||
465 | } | |||
466 | ||||
467 | if (new_module->module_interface->file_interface) { | |||
468 | const switch_file_interface_t *ptr; | |||
469 | ||||
470 | for (ptr = new_module->module_interface->file_interface; ptr; ptr = ptr->next) { | |||
471 | if (!ptr->interface_name) { | |||
472 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 472, ((void*)0), SWITCH_LOG_CRIT, "Failed to load file interface from %s due to no interface name.\n", key); | |||
473 | } else if (!ptr->extens) { | |||
474 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 474, ((void*)0), SWITCH_LOG_CRIT, "Failed to load file interface from %s due to no file extensions.\n", key); | |||
475 | } else { | |||
476 | int i; | |||
477 | switch_file_node_t *node, *head; | |||
478 | ||||
479 | for (i = 0; ptr->extens[i]; i++) { | |||
480 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 480, ((void*)0), SWITCH_LOG_NOTICE, "Adding File Format '%s'\n", ptr->extens[i]); | |||
481 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 481, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
482 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "file"); | |||
483 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->extens[i]); | |||
484 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
485 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
486 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", new_module->module_interface->module_name); | |||
487 | ||||
488 | if (!event_hash) { | |||
489 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 489, &event, ((void*)0)); | |||
490 | } | |||
491 | else { | |||
492 | sprintf(str_event_num, "%i", ++*event_num); | |||
493 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
494 | } | |||
495 | ||||
496 | added++; | |||
497 | } | |||
498 | node = switch_core_alloc(new_module->pool, sizeof(*node))switch_core_perform_alloc(new_module->pool, sizeof(*node), "src/switch_loadable_module.c", (const char *)__func__, 498); | |||
499 | node->ptr = ptr; | |||
500 | node->interface_name = switch_core_strdup(new_module->pool, new_module->module_interface->module_name)switch_core_perform_strdup(new_module->pool, new_module-> module_interface->module_name, "src/switch_loadable_module.c" , (const char *)__func__, 500); | |||
501 | if ((head = switch_core_hash_find(loadable_modules.file_hash, ptr->extens[i]))) { | |||
502 | node->next = head; | |||
503 | } | |||
504 | ||||
505 | switch_core_hash_insert(loadable_modules.file_hash, ptr->extens[i], (const void *) node)switch_core_hash_insert_destructor(loadable_modules.file_hash , ptr->extens[i], (const void *) node, ((void*)0)); | |||
506 | } | |||
507 | } | |||
508 | } | |||
509 | } | |||
510 | ||||
511 | if (new_module->module_interface->database_interface) { | |||
512 | const switch_database_interface_t *ptr; | |||
513 | ||||
514 | for (ptr = new_module->module_interface->database_interface; ptr; ptr = ptr->next) { | |||
515 | if (!ptr->interface_name) { | |||
516 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 516, ((void*)0), SWITCH_LOG_CRIT, "Failed to load database interface from %s due to no interface name.\n", key); | |||
517 | } | |||
518 | else if (!ptr->prefixes) { | |||
519 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 519, ((void*)0), SWITCH_LOG_CRIT, "Failed to load database interface from %s due to no prefixes.\n", key); | |||
520 | } | |||
521 | else { | |||
522 | int i; | |||
523 | switch_database_node_t *node, *head; | |||
524 | ||||
525 | for (i = 0; ptr->prefixes[i]; i++) { | |||
526 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 526, ((void*)0), SWITCH_LOG_NOTICE, "Adding dsn prefix '%s'\n", ptr->prefixes[i]); | |||
527 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 527, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
528 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "database"); | |||
529 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->prefixes[i]); | |||
530 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
531 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
532 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", new_module->module_interface->module_name); | |||
533 | ||||
534 | if (!event_hash) { | |||
535 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 535, &event, ((void*)0)); | |||
536 | } | |||
537 | else { | |||
538 | sprintf(str_event_num, "%i", ++*event_num); | |||
539 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
540 | } | |||
541 | ||||
542 | added++; | |||
543 | } | |||
544 | node = switch_core_alloc(new_module->pool, sizeof(*node))switch_core_perform_alloc(new_module->pool, sizeof(*node), "src/switch_loadable_module.c", (const char *)__func__, 544); | |||
545 | node->ptr = ptr; | |||
546 | node->interface_name = switch_core_strdup(new_module->pool, new_module->module_interface->module_name)switch_core_perform_strdup(new_module->pool, new_module-> module_interface->module_name, "src/switch_loadable_module.c" , (const char *)__func__, 546); | |||
547 | if ((head = switch_core_hash_find(loadable_modules.database_hash, ptr->prefixes[i]))) { | |||
548 | node->next = head; | |||
549 | } | |||
550 | ||||
551 | switch_core_hash_insert(loadable_modules.database_hash, ptr->prefixes[i], (const void *)node)switch_core_hash_insert_destructor(loadable_modules.database_hash , ptr->prefixes[i], (const void *)node, ((void*)0)); | |||
552 | } | |||
553 | } | |||
554 | } | |||
555 | } | |||
556 | ||||
557 | if (new_module->module_interface->speech_interface) { | |||
558 | const switch_speech_interface_t *ptr; | |||
559 | ||||
560 | for (ptr = new_module->module_interface->speech_interface; ptr; ptr = ptr->next) { | |||
561 | if (!ptr->interface_name) { | |||
562 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 562, ((void*)0), SWITCH_LOG_CRIT, "Failed to load speech interface from %s due to no interface name.\n", key); | |||
563 | } else { | |||
564 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 564, ((void*)0), SWITCH_LOG_NOTICE, "Adding Speech interface '%s'\n", ptr->interface_name); | |||
565 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 565, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
566 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "speech"); | |||
567 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
568 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
569 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
570 | ||||
571 | if (!event_hash) { | |||
572 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 572, &event, ((void*)0)); | |||
573 | } | |||
574 | else { | |||
575 | sprintf(str_event_num, "%i", ++*event_num); | |||
576 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
577 | } | |||
578 | ||||
579 | added++; | |||
580 | } | |||
581 | switch_core_hash_insert(loadable_modules.speech_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.speech_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
582 | } | |||
583 | } | |||
584 | } | |||
585 | ||||
586 | if (new_module->module_interface->asr_interface) { | |||
587 | const switch_asr_interface_t *ptr; | |||
588 | ||||
589 | for (ptr = new_module->module_interface->asr_interface; ptr; ptr = ptr->next) { | |||
590 | if (!ptr->interface_name) { | |||
591 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 591, ((void*)0), SWITCH_LOG_CRIT, "Failed to load asr interface from %s due to no interface name.\n", key); | |||
592 | } else { | |||
593 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 593, ((void*)0), SWITCH_LOG_NOTICE, "Adding ASR interface '%s'\n", ptr->interface_name); | |||
594 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 594, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
595 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "asr"); | |||
596 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
597 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
598 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
599 | ||||
600 | if (!event_hash) { | |||
601 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 601, &event, ((void*)0)); | |||
602 | } | |||
603 | else { | |||
604 | sprintf(str_event_num, "%i", ++*event_num); | |||
605 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
606 | } | |||
607 | ||||
608 | added++; | |||
609 | } | |||
610 | switch_core_hash_insert(loadable_modules.asr_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.asr_hash, ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
611 | } | |||
612 | } | |||
613 | } | |||
614 | ||||
615 | if (new_module->module_interface->directory_interface) { | |||
616 | const switch_directory_interface_t *ptr; | |||
617 | ||||
618 | for (ptr = new_module->module_interface->directory_interface; ptr; ptr = ptr->next) { | |||
619 | if (!ptr->interface_name) { | |||
620 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 620, ((void*)0), SWITCH_LOG_CRIT, "Failed to load directory interface from %s due to no interface name.\n", key); | |||
621 | } else { | |||
622 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 622, ((void*)0), SWITCH_LOG_NOTICE, "Adding Directory interface '%s'\n", ptr->interface_name); | |||
623 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 623, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
624 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "directory"); | |||
625 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
626 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
627 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
628 | ||||
629 | if (!event_hash) { | |||
630 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 630, &event, ((void*)0)); | |||
631 | } | |||
632 | else { | |||
633 | sprintf(str_event_num, "%i", ++*event_num); | |||
634 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
635 | } | |||
636 | ||||
637 | added++; | |||
638 | } | |||
639 | switch_core_hash_insert(loadable_modules.directory_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.directory_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
640 | } | |||
641 | } | |||
642 | } | |||
643 | ||||
644 | if (new_module->module_interface->chat_interface) { | |||
645 | const switch_chat_interface_t *ptr; | |||
646 | ||||
647 | for (ptr = new_module->module_interface->chat_interface; ptr; ptr = ptr->next) { | |||
648 | if (!ptr->interface_name) { | |||
649 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 649, ((void*)0), SWITCH_LOG_CRIT, "Failed to load chat interface from %s due to no interface name.\n", key); | |||
650 | } else { | |||
651 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 651, ((void*)0), SWITCH_LOG_NOTICE, "Adding Chat interface '%s'\n", ptr->interface_name); | |||
652 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 652, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
653 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "chat"); | |||
654 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
655 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
656 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
657 | ||||
658 | if (!event_hash) { | |||
659 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 659, &event, ((void*)0)); | |||
660 | } | |||
661 | else { | |||
662 | sprintf(str_event_num, "%i", ++*event_num); | |||
663 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
664 | } | |||
665 | ||||
666 | added++; | |||
667 | } | |||
668 | switch_core_hash_insert(loadable_modules.chat_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.chat_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
669 | } | |||
670 | } | |||
671 | } | |||
672 | ||||
673 | if (new_module->module_interface->say_interface) { | |||
674 | const switch_say_interface_t *ptr; | |||
675 | ||||
676 | for (ptr = new_module->module_interface->say_interface; ptr; ptr = ptr->next) { | |||
677 | if (!ptr->interface_name) { | |||
678 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 678, ((void*)0), SWITCH_LOG_CRIT, "Failed to load say interface from %s due to no interface name.\n", key); | |||
679 | } else { | |||
680 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 680, ((void*)0), SWITCH_LOG_NOTICE, "Adding Say interface '%s'\n", ptr->interface_name); | |||
681 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 681, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
682 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "say"); | |||
683 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
684 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
685 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
686 | ||||
687 | if (!event_hash) { | |||
688 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 688, &event, ((void*)0)); | |||
689 | } | |||
690 | else { | |||
691 | sprintf(str_event_num, "%i", ++*event_num); | |||
692 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
693 | } | |||
694 | ||||
695 | added++; | |||
696 | } | |||
697 | switch_core_hash_insert(loadable_modules.say_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.say_hash, ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
698 | } | |||
699 | } | |||
700 | } | |||
701 | ||||
702 | if (new_module->module_interface->management_interface) { | |||
703 | const switch_management_interface_t *ptr; | |||
704 | ||||
705 | for (ptr = new_module->module_interface->management_interface; ptr; ptr = ptr->next) { | |||
706 | if (!ptr->relative_oid) { | |||
707 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 707, ((void*)0), SWITCH_LOG_CRIT, "Failed to load management interface from %s due to no interface name.\n", key); | |||
708 | } else { | |||
709 | if (switch_core_hash_find(loadable_modules.management_hash, ptr->relative_oid)) { | |||
710 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 710, ((void*)0), SWITCH_LOG_CRIT, | |||
711 | "Failed to load management interface %s. OID %s already exists\n", key, ptr->relative_oid); | |||
712 | } else { | |||
713 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 713, ((void*)0), SWITCH_LOG_NOTICE, | |||
714 | "Adding Management interface '%s' OID[%s.%s]\n", key, FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880", ptr->relative_oid); | |||
715 | switch_core_hash_insert(loadable_modules.management_hash, ptr->relative_oid, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.management_hash , ptr->relative_oid, (const void *) ptr, ((void*)0)); | |||
716 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 716, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
717 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "management"); | |||
718 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->relative_oid); | |||
719 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
720 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
721 | ||||
722 | if (!event_hash) { | |||
723 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 723, &event, ((void*)0)); | |||
724 | } | |||
725 | else { | |||
726 | sprintf(str_event_num, "%i", ++*event_num); | |||
727 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
728 | } | |||
729 | ||||
730 | added++; | |||
731 | } | |||
732 | } | |||
733 | ||||
734 | } | |||
735 | } | |||
736 | } | |||
737 | if (new_module->module_interface->limit_interface) { | |||
738 | const switch_limit_interface_t *ptr; | |||
739 | ||||
740 | for (ptr = new_module->module_interface->limit_interface; ptr; ptr = ptr->next) { | |||
741 | if (!ptr->interface_name) { | |||
742 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 742, ((void*)0), SWITCH_LOG_CRIT, "Failed to load limit interface from %s due to no interface name.\n", key); | |||
743 | } else { | |||
744 | if (switch_core_hash_find(loadable_modules.limit_hash, ptr->interface_name)) { | |||
745 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 745, ((void*)0), SWITCH_LOG_CRIT, | |||
746 | "Failed to load limit interface %s. Name %s already exists\n", key, ptr->interface_name); | |||
747 | } else { | |||
748 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 748, ((void*)0), SWITCH_LOG_NOTICE, | |||
749 | "Adding Limit interface '%s'\n", ptr->interface_name); | |||
750 | switch_core_hash_insert(loadable_modules.limit_hash, ptr->interface_name, (const void *) ptr)switch_core_hash_insert_destructor(loadable_modules.limit_hash , ptr->interface_name, (const void *) ptr, ((void*)0)); | |||
751 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 751, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
752 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "limit"); | |||
753 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
754 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
755 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
756 | ||||
757 | if (!event_hash) { | |||
758 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 758, &event, ((void*)0)); | |||
759 | } | |||
760 | else { | |||
761 | sprintf(str_event_num, "%i", ++*event_num); | |||
762 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
763 | } | |||
764 | ||||
765 | added++; | |||
766 | } | |||
767 | } | |||
768 | ||||
769 | } | |||
770 | } | |||
771 | } | |||
772 | ||||
773 | if (!added) { | |||
774 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 774, &event, SWITCH_EVENT_MODULE_LOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
775 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "generic"); | |||
776 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", new_module->key); | |||
777 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key); | |||
778 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename); | |||
779 | ||||
780 | if (!event_hash) { | |||
781 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 781, &event, ((void*)0)); | |||
782 | } | |||
783 | else { | |||
784 | sprintf(str_event_num, "%i", ++*event_num); | |||
785 | switch_core_hash_insert(event_hash, (const char*)str_event_num, (const void*)event)switch_core_hash_insert_destructor(event_hash, (const char*)str_event_num , (const void*)event, ((void*)0)); | |||
786 | } | |||
787 | ||||
788 | added++; | |||
789 | } | |||
790 | } | |||
791 | ||||
792 | switch_mutex_unlock(loadable_modules.mutex); | |||
| ||||
793 | return SWITCH_STATUS_SUCCESS; | |||
794 | ||||
795 | } | |||
796 | ||||
797 | #define CHAT_MAX_MSG_QUEUE101 101 | |||
798 | #define CHAT_QUEUE_SIZE5000 5000 | |||
799 | ||||
800 | static struct { | |||
801 | switch_queue_t *msg_queue[CHAT_MAX_MSG_QUEUE101]; | |||
802 | switch_thread_t *msg_queue_thread[CHAT_MAX_MSG_QUEUE101]; | |||
803 | int msg_queue_len; | |||
804 | switch_mutex_t *mutex; | |||
805 | switch_memory_pool_t *pool; | |||
806 | int running; | |||
807 | } chat_globals; | |||
808 | ||||
809 | static int IDX = 0; | |||
810 | ||||
811 | ||||
812 | static switch_status_t do_chat_send(switch_event_t *message_event) | |||
813 | ||||
814 | { | |||
815 | switch_chat_interface_t *ci; | |||
816 | switch_status_t status = SWITCH_STATUS_FALSE; | |||
817 | switch_hash_index_t *hi; | |||
818 | switch_event_t *dup = NULL((void*)0); | |||
819 | const void *var; | |||
820 | void *val; | |||
821 | const char *proto; | |||
822 | const char *replying; | |||
823 | const char *dest_proto; | |||
824 | int do_skip = 0; | |||
825 | ||||
826 | /* | |||
827 | ||||
828 | const char *from; | |||
829 | const char *to; | |||
830 | const char *subject; | |||
831 | const char *body; | |||
832 | const char *type; | |||
833 | const char *hint; | |||
834 | */ | |||
835 | ||||
836 | dest_proto = switch_event_get_header(message_event, "dest_proto")switch_event_get_header_idx(message_event, "dest_proto", -1); | |||
837 | ||||
838 | if (!dest_proto) { | |||
839 | return SWITCH_STATUS_FALSE; | |||
840 | } | |||
841 | ||||
842 | /* | |||
843 | ||||
844 | from = switch_event_get_header(message_event, "from"); | |||
845 | to = switch_event_get_header(message_event, "to"); | |||
846 | subject = switch_event_get_header(message_event, "subject"); | |||
847 | body = switch_event_get_body(message_event); | |||
848 | type = switch_event_get_header(message_event, "type"); | |||
849 | hint = switch_event_get_header(message_event, "hint"); | |||
850 | */ | |||
851 | ||||
852 | if (!(proto = switch_event_get_header(message_event, "proto")switch_event_get_header_idx(message_event, "proto", -1))) { | |||
853 | proto = "global"; | |||
854 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto); | |||
855 | } | |||
856 | ||||
857 | replying = switch_event_get_header(message_event, "replying")switch_event_get_header_idx(message_event, "replying", -1); | |||
858 | ||||
859 | if (!switch_true(replying) && !switch_stristr("global", proto) && !switch_true(switch_event_get_header(message_event, "skip_global_process")switch_event_get_header_idx(message_event, "skip_global_process" , -1))) { | |||
860 | switch_mutex_lock(loadable_modules.mutex); | |||
861 | for (hi = switch_core_hash_first(loadable_modules.chat_hash)switch_core_hash_first_iter(loadable_modules.chat_hash, ((void *)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
862 | switch_core_hash_this(hi, &var, NULL((void*)0), &val); | |||
863 | ||||
864 | if ((ci = (switch_chat_interface_t *) val)) { | |||
865 | if (ci->chat_send && !strncasecmp(ci->interface_name, "GLOBAL_", 7)) { | |||
866 | status = ci->chat_send(message_event); | |||
867 | ||||
868 | if (status == SWITCH_STATUS_SUCCESS) { | |||
869 | if (switch_true(switch_event_get_header(message_event, "final_delivery")switch_event_get_header_idx(message_event, "final_delivery", - 1))) { | |||
870 | /* The event was handled by an extension in the chatplan, | |||
871 | * so the event will be duplicated, modified and queued again, | |||
872 | * but it won't be processed by the chatplan again. | |||
873 | * So this copy of the event can be destroyed by the caller. | |||
874 | */ | |||
875 | do_skip = 1; | |||
876 | } | |||
877 | } else if (status == SWITCH_STATUS_BREAK) { | |||
878 | /* The event went through the chatplan, but no extension matched | |||
879 | * to handle the sms messsage. It'll be attempted to be delivered | |||
880 | * directly, and unless that works the sms delivery will have failed. | |||
881 | */ | |||
882 | } else { | |||
883 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 883, ((void*)0), SWITCH_LOG_ERROR, "Chat Interface Error [%s]!\n", dest_proto); | |||
884 | break; | |||
885 | } | |||
886 | } | |||
887 | } | |||
888 | } | |||
889 | switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);}; | |||
890 | switch_mutex_unlock(loadable_modules.mutex); | |||
891 | } | |||
892 | ||||
893 | ||||
894 | if (!do_skip && !switch_stristr("GLOBAL", dest_proto)) { | |||
895 | if ((ci = switch_loadable_module_get_chat_interface(dest_proto)) && ci->chat_send) { | |||
896 | status = ci->chat_send(message_event); | |||
897 | UNPROTECT_INTERFACE(ci)if (ci) {switch_mutex_lock(ci->reflock); ci->refs--; ci ->parent->refs--; switch_mutex_unlock(ci->reflock); switch_thread_rwlock_unlock (ci->rwlock); switch_thread_rwlock_unlock(ci->parent-> rwlock);}; | |||
898 | } else { | |||
899 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 899, ((void*)0), SWITCH_LOG_ERROR, "Invalid chat interface [%s]!\n", dest_proto); | |||
900 | status = SWITCH_STATUS_FALSE; | |||
901 | } | |||
902 | } | |||
903 | ||||
904 | ||||
905 | switch_event_dup(&dup, message_event); | |||
906 | ||||
907 | if ( switch_true(switch_event_get_header(message_event, "blocking")switch_event_get_header_idx(message_event, "blocking", -1)) ) { | |||
908 | if (status == SWITCH_STATUS_SUCCESS) { | |||
909 | switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Delivery-Failure", "false"); | |||
910 | } else { | |||
911 | switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Delivery-Failure", "true"); | |||
912 | } | |||
913 | } else { | |||
914 | switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Nonblocking-Delivery", "true"); | |||
915 | } | |||
916 | ||||
917 | switch_event_fire(&dup)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 917, &dup, ((void*)0)); | |||
918 | return status; | |||
919 | } | |||
920 | ||||
921 | static switch_status_t chat_process_event(switch_event_t **eventp) | |||
922 | { | |||
923 | switch_event_t *event; | |||
924 | switch_status_t status; | |||
925 | ||||
926 | switch_assert(eventp)((eventp) ? (void) (0) : __assert_fail ("eventp", "src/switch_loadable_module.c" , 926, __extension__ __PRETTY_FUNCTION__)); | |||
927 | ||||
928 | event = *eventp; | |||
929 | *eventp = NULL((void*)0); | |||
930 | ||||
931 | status = do_chat_send(event); | |||
932 | switch_event_destroy(&event); | |||
933 | ||||
934 | return status; | |||
935 | } | |||
936 | ||||
937 | ||||
938 | void *SWITCH_THREAD_FUNC chat_thread_run(switch_thread_t *thread, void *obj) | |||
939 | { | |||
940 | void *pop; | |||
941 | switch_queue_t *q = (switch_queue_t *) obj; | |||
942 | ||||
943 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 943, ((void*)0), SWITCH_LOG_DEBUG, "Chat Thread Started\n"); | |||
944 | ||||
945 | ||||
946 | while(switch_queue_pop(q, &pop) == SWITCH_STATUS_SUCCESS && pop) { | |||
947 | switch_event_t *event = (switch_event_t *) pop; | |||
948 | chat_process_event(&event); | |||
949 | switch_cond_next(); | |||
950 | } | |||
951 | ||||
952 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 952, ((void*)0), SWITCH_LOG_DEBUG, "Chat Thread Ended\n"); | |||
953 | ||||
954 | return NULL((void*)0); | |||
955 | } | |||
956 | ||||
957 | ||||
958 | static void chat_thread_start(int idx) | |||
959 | { | |||
960 | ||||
961 | if (idx >= CHAT_MAX_MSG_QUEUE101 || (idx < chat_globals.msg_queue_len && chat_globals.msg_queue_thread[idx])) { | |||
962 | return; | |||
963 | } | |||
964 | ||||
965 | switch_mutex_lock(chat_globals.mutex); | |||
966 | ||||
967 | if (idx >= chat_globals.msg_queue_len) { | |||
968 | int i; | |||
969 | chat_globals.msg_queue_len = idx + 1; | |||
970 | ||||
971 | for (i = 0; i < chat_globals.msg_queue_len; i++) { | |||
972 | if (!chat_globals.msg_queue[i]) { | |||
973 | switch_threadattr_t *thd_attr = NULL((void*)0); | |||
974 | ||||
975 | switch_queue_create(&chat_globals.msg_queue[i], CHAT_QUEUE_SIZE5000, chat_globals.pool); | |||
976 | ||||
977 | switch_threadattr_create(&thd_attr, chat_globals.pool); | |||
978 | switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024); | |||
979 | switch_thread_create(&chat_globals.msg_queue_thread[i], | |||
980 | thd_attr, | |||
981 | chat_thread_run, | |||
982 | chat_globals.msg_queue[i], | |||
983 | chat_globals.pool); | |||
984 | } | |||
985 | } | |||
986 | } | |||
987 | ||||
988 | switch_mutex_unlock(chat_globals.mutex); | |||
989 | } | |||
990 | ||||
991 | ||||
992 | static void chat_queue_message(switch_event_t **eventp) | |||
993 | { | |||
994 | int idx = 0; | |||
995 | switch_event_t *event; | |||
996 | ||||
997 | switch_assert(eventp)((eventp) ? (void) (0) : __assert_fail ("eventp", "src/switch_loadable_module.c" , 997, __extension__ __PRETTY_FUNCTION__)); | |||
998 | ||||
999 | event = *eventp; | |||
1000 | *eventp = NULL((void*)0); | |||
1001 | ||||
1002 | if (chat_globals.running == 0) { | |||
1003 | chat_process_event(&event); | |||
1004 | return; | |||
1005 | } | |||
1006 | ||||
1007 | again: | |||
1008 | ||||
1009 | switch_mutex_lock(chat_globals.mutex); | |||
1010 | idx = IDX; | |||
1011 | IDX++; | |||
1012 | if (IDX >= chat_globals.msg_queue_len) IDX = 0; | |||
1013 | switch_mutex_unlock(chat_globals.mutex); | |||
1014 | ||||
1015 | chat_thread_start(idx); | |||
1016 | ||||
1017 | if (switch_queue_trypush(chat_globals.msg_queue[idx], event) != SWITCH_STATUS_SUCCESS) { | |||
1018 | if (chat_globals.msg_queue_len < CHAT_MAX_MSG_QUEUE101) { | |||
1019 | chat_thread_start(idx + 1); | |||
1020 | goto again; | |||
1021 | } else { | |||
1022 | switch_queue_push(chat_globals.msg_queue[idx], event); | |||
1023 | } | |||
1024 | } | |||
1025 | } | |||
1026 | ||||
1027 | ||||
1028 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_execute_chat_app(switch_event_t *message, const char *app, const char *data) | |||
1029 | { | |||
1030 | switch_chat_application_interface_t *cai; | |||
1031 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||
1032 | char *expanded; | |||
1033 | ||||
1034 | if (!(cai = switch_loadable_module_get_chat_application_interface(app)) || !cai->chat_application_function) { | |||
1035 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1035, ((void*)0), SWITCH_LOG_ERROR, "Invalid chat application interface [%s]!\n", app); | |||
1036 | return SWITCH_STATUS_FALSE; | |||
1037 | } | |||
1038 | ||||
1039 | if (switch_test_flag(message, EF_NO_CHAT_EXEC)((message)->flags & EF_NO_CHAT_EXEC)) { | |||
1040 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1040, ((void*)0), SWITCH_LOG_DEBUG, "Message is not allowed to execute apps\n"); | |||
1041 | switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end; | |||
1042 | } | |||
1043 | ||||
1044 | if (data && !strcmp(data, "__undef")) { | |||
1045 | data = NULL((void*)0); | |||
1046 | } | |||
1047 | ||||
1048 | expanded = switch_event_expand_headers(message, data)switch_event_expand_headers_check(message, data, ((void*)0), ( (void*)0), 0); | |||
1049 | ||||
1050 | status = cai->chat_application_function(message, expanded); | |||
1051 | ||||
1052 | if (expanded != data) { | |||
1053 | free(expanded); | |||
1054 | } | |||
1055 | ||||
1056 | end: | |||
1057 | ||||
1058 | UNPROTECT_INTERFACE(cai)if (cai) {switch_mutex_lock(cai->reflock); cai->refs--; cai->parent->refs--; switch_mutex_unlock(cai->reflock ); switch_thread_rwlock_unlock(cai->rwlock); switch_thread_rwlock_unlock (cai->parent->rwlock);}; | |||
1059 | ||||
1060 | return status; | |||
1061 | ||||
1062 | } | |||
1063 | ||||
1064 | ||||
1065 | ||||
1066 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to, | |||
1067 | const char *subject, const char *body, const char *type, const char *hint, switch_bool_t blocking) | |||
1068 | { | |||
1069 | switch_event_t *message_event; | |||
1070 | switch_status_t status; | |||
1071 | ||||
1072 | if (switch_event_create(&message_event, SWITCH_EVENT_MESSAGE)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1072, &message_event , SWITCH_EVENT_MESSAGE, ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1073 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto); | |||
1074 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "from", from); | |||
1075 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "to", to); | |||
1076 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "subject", subject); | |||
1077 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "type", type); | |||
1078 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "hint", hint); | |||
1079 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "skip_global_process", "true"); | |||
1080 | if (blocking) { | |||
1081 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "blocking", "true"); | |||
1082 | } | |||
1083 | ||||
1084 | if (body) { | |||
1085 | switch_event_add_body(message_event, "%s", body); | |||
1086 | } | |||
1087 | } else { | |||
1088 | abort(); | |||
1089 | } | |||
1090 | ||||
1091 | if (dest_proto) { | |||
1092 | switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "dest_proto", dest_proto); | |||
1093 | } | |||
1094 | ||||
1095 | ||||
1096 | if (blocking) { | |||
1097 | status = chat_process_event(&message_event); | |||
1098 | } else { | |||
1099 | chat_queue_message(&message_event); | |||
1100 | status = SWITCH_STATUS_SUCCESS; | |||
1101 | } | |||
1102 | ||||
1103 | return status; | |||
1104 | ||||
1105 | } | |||
1106 | ||||
1107 | ||||
1108 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_send(const char *dest_proto, switch_event_t *message_event) | |||
1109 | { | |||
1110 | switch_event_t *dup; | |||
1111 | ||||
1112 | switch_event_dup(&dup, message_event); | |||
1113 | ||||
1114 | if (dest_proto) { | |||
1115 | switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "dest_proto", dest_proto); | |||
1116 | } | |||
1117 | ||||
1118 | chat_queue_message(&dup); | |||
1119 | return SWITCH_STATUS_SUCCESS; | |||
1120 | } | |||
1121 | ||||
1122 | ||||
1123 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event) | |||
1124 | { | |||
1125 | ||||
1126 | if (dest_proto) { | |||
1127 | switch_event_add_header_string(*message_event, SWITCH_STACK_BOTTOM, "dest_proto", dest_proto); | |||
1128 | } | |||
1129 | ||||
1130 | chat_queue_message(message_event); | |||
1131 | ||||
1132 | return SWITCH_STATUS_SUCCESS; | |||
1133 | } | |||
1134 | ||||
1135 | ||||
1136 | static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t *old_module) | |||
1137 | { | |||
1138 | switch_event_t *event; | |||
1139 | int removed = 0; | |||
1140 | ||||
1141 | switch_mutex_lock(loadable_modules.mutex); | |||
1142 | ||||
1143 | if (old_module->module_interface->endpoint_interface) { | |||
1144 | const switch_endpoint_interface_t *ptr; | |||
1145 | ||||
1146 | for (ptr = old_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) { | |||
1147 | if (ptr->interface_name) { | |||
1148 | ||||
1149 | switch_core_session_hupall_endpoint(ptr, SWITCH_CAUSE_MANAGER_REQUEST); | |||
1150 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1150, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1151 | ptr->interface_name); | |||
1152 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1153 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1154 | } else { | |||
1155 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1155, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1156 | } | |||
1157 | ||||
1158 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1158, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Endpoint '%s'\n", ptr->interface_name); | |||
1159 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1159, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1160 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "endpoint"); | |||
1161 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1162 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1162, &event, ((void*)0) ); | |||
1163 | removed++; | |||
1164 | } | |||
1165 | switch_core_hash_delete(loadable_modules.endpoint_hash, ptr->interface_name); | |||
1166 | } | |||
1167 | } | |||
1168 | } | |||
1169 | ||||
1170 | if (old_module->module_interface->codec_interface) { | |||
1171 | const switch_codec_implementation_t *impl; | |||
1172 | const switch_codec_interface_t *ptr; | |||
1173 | switch_codec_node_t *node, *head, *last = NULL((void*)0); | |||
1174 | ||||
1175 | for (ptr = old_module->module_interface->codec_interface; ptr; ptr = ptr->next) { | |||
1176 | if (ptr->interface_name) { | |||
1177 | unsigned load_interface = 1; | |||
1178 | for (impl = ptr->implementations; impl; impl = impl->next) { | |||
1179 | if (!impl->iananame) { | |||
1180 | load_interface = 0; | |||
1181 | break; | |||
1182 | } | |||
1183 | } | |||
1184 | if (load_interface) { | |||
1185 | for (impl = ptr->implementations; impl; impl = impl->next) { | |||
1186 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1186, ((void*)0), SWITCH_LOG_NOTICE, | |||
1187 | "Deleting Codec %s %d %s %dhz %dms\n", | |||
1188 | impl->iananame, impl->ianacode, | |||
1189 | ptr->interface_name, impl->actual_samples_per_second, impl->microseconds_per_packet / 1000); | |||
1190 | switch_core_session_hupall_matching_var("read_codec", impl->iananame, SWITCH_CAUSE_MANAGER_REQUEST)switch_core_session_hupall_matching_var_ans("read_codec", impl ->iananame, SWITCH_CAUSE_MANAGER_REQUEST, SHT_UNANSWERED | SHT_ANSWERED); | |||
1191 | switch_core_session_hupall_matching_var("write_codec", impl->iananame, SWITCH_CAUSE_MANAGER_REQUEST)switch_core_session_hupall_matching_var_ans("write_codec", impl ->iananame, SWITCH_CAUSE_MANAGER_REQUEST, SHT_UNANSWERED | SHT_ANSWERED); | |||
1192 | ||||
1193 | if ((head = switch_core_hash_find(loadable_modules.codec_hash, impl->iananame))) { | |||
1194 | for(node = head; node; node = node->next) { | |||
1195 | if (!strcmp(node->interface_name, old_module->module_interface->module_name)) { | |||
1196 | if (node == head) { | |||
1197 | if ((node = node->next)) { | |||
1198 | switch_core_hash_insert(loadable_modules.codec_hash, impl->iananame, (const void *) node)switch_core_hash_insert_destructor(loadable_modules.codec_hash , impl->iananame, (const void *) node, ((void*)0)); | |||
1199 | } else { | |||
1200 | switch_core_hash_delete(loadable_modules.codec_hash, impl->iananame); | |||
1201 | } | |||
1202 | } else { | |||
1203 | if (last) { | |||
1204 | last->next = node->next; | |||
1205 | } | |||
1206 | } | |||
1207 | break; | |||
1208 | } | |||
1209 | last = node; | |||
1210 | } | |||
1211 | } | |||
1212 | } | |||
1213 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1213, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1214 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "codec"); | |||
1215 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1216 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", old_module->module_interface->module_name); | |||
1217 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1217, &event, ((void*)0) ); | |||
1218 | removed++; | |||
1219 | } | |||
1220 | } | |||
1221 | } | |||
1222 | } | |||
1223 | } | |||
1224 | ||||
1225 | if (old_module->module_interface->dialplan_interface) { | |||
1226 | const switch_dialplan_interface_t *ptr; | |||
1227 | ||||
1228 | for (ptr = old_module->module_interface->dialplan_interface; ptr; ptr = ptr->next) { | |||
1229 | if (ptr->interface_name) { | |||
1230 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1230, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Dialplan '%s'\n", ptr->interface_name); | |||
1231 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1231, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1232 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "dialplan"); | |||
1233 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1234 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1234, &event, ((void*)0) ); | |||
1235 | removed++; | |||
1236 | } | |||
1237 | switch_core_hash_delete(loadable_modules.dialplan_hash, ptr->interface_name); | |||
1238 | } | |||
1239 | } | |||
1240 | } | |||
1241 | ||||
1242 | if (old_module->module_interface->timer_interface) { | |||
1243 | const switch_timer_interface_t *ptr; | |||
1244 | ||||
1245 | for (ptr = old_module->module_interface->timer_interface; ptr; ptr = ptr->next) { | |||
1246 | if (ptr->interface_name) { | |||
1247 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1247, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Timer '%s'\n", ptr->interface_name); | |||
1248 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1248, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1249 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "timer"); | |||
1250 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1251 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1251, &event, ((void*)0) ); | |||
1252 | removed++; | |||
1253 | } | |||
1254 | switch_core_hash_delete(loadable_modules.timer_hash, ptr->interface_name); | |||
1255 | } | |||
1256 | } | |||
1257 | } | |||
1258 | ||||
1259 | if (old_module->module_interface->application_interface) { | |||
1260 | const switch_application_interface_t *ptr; | |||
1261 | for (ptr = old_module->module_interface->application_interface; ptr; ptr = ptr->next) { | |||
1262 | if (ptr->interface_name) { | |||
1263 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1263, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name); | |||
1264 | switch_core_session_hupall_matching_var(SWITCH_CURRENT_APPLICATION_VARIABLE, ptr->interface_name, SWITCH_CAUSE_MANAGER_REQUEST)switch_core_session_hupall_matching_var_ans("current_application" , ptr->interface_name, SWITCH_CAUSE_MANAGER_REQUEST, SHT_UNANSWERED | SHT_ANSWERED); | |||
1265 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1265, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1266 | ptr->interface_name); | |||
1267 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1268 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1269 | } else { | |||
1270 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1270, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1271 | } | |||
1272 | ||||
1273 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1273, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1274 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application"); | |||
1275 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1276 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->short_desc)(ptr->short_desc ? ptr->short_desc : "")); | |||
1277 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
1278 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1278, &event, ((void*)0) ); | |||
1279 | removed++; | |||
1280 | } | |||
1281 | switch_core_hash_delete(loadable_modules.application_hash, ptr->interface_name); | |||
1282 | } | |||
1283 | } | |||
1284 | } | |||
1285 | ||||
1286 | if (old_module->module_interface->chat_application_interface) { | |||
1287 | const switch_chat_application_interface_t *ptr; | |||
1288 | for (ptr = old_module->module_interface->chat_application_interface; ptr; ptr = ptr->next) { | |||
1289 | if (ptr->interface_name) { | |||
1290 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1290, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name); | |||
1291 | switch_core_session_hupall_matching_var(SWITCH_CURRENT_APPLICATION_VARIABLE, ptr->interface_name, SWITCH_CAUSE_MANAGER_REQUEST)switch_core_session_hupall_matching_var_ans("current_application" , ptr->interface_name, SWITCH_CAUSE_MANAGER_REQUEST, SHT_UNANSWERED | SHT_ANSWERED); | |||
1292 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1292, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1293 | ptr->interface_name); | |||
1294 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1295 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1296 | } else { | |||
1297 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1297, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1298 | } | |||
1299 | ||||
1300 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1300, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1301 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "application"); | |||
1302 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1303 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->short_desc)(ptr->short_desc ? ptr->short_desc : "")); | |||
1304 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
1305 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1305, &event, ((void*)0) ); | |||
1306 | removed++; | |||
1307 | } | |||
1308 | switch_core_hash_delete(loadable_modules.chat_application_hash, ptr->interface_name); | |||
1309 | } | |||
1310 | } | |||
1311 | } | |||
1312 | ||||
1313 | if (old_module->module_interface->api_interface) { | |||
1314 | const switch_api_interface_t *ptr; | |||
1315 | ||||
1316 | for (ptr = old_module->module_interface->api_interface; ptr; ptr = ptr->next) { | |||
1317 | if (ptr->interface_name) { | |||
1318 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1318, ((void*)0), SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name); | |||
1319 | ||||
1320 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1320, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1321 | ptr->interface_name); | |||
1322 | ||||
1323 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1324 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1325 | } else { | |||
1326 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1326, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1327 | } | |||
1328 | ||||
1329 | ||||
1330 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1330, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1331 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "api"); | |||
1332 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1333 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->desc)(ptr->desc ? ptr->desc : "")); | |||
1334 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
1335 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", old_module->key); | |||
1336 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", old_module->filename); | |||
1337 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1337, &event, ((void*)0) ); | |||
1338 | removed++; | |||
1339 | } | |||
1340 | switch_core_hash_delete(loadable_modules.api_hash, ptr->interface_name); | |||
1341 | } | |||
1342 | } | |||
1343 | } | |||
1344 | ||||
1345 | if (old_module->module_interface->json_api_interface) { | |||
1346 | const switch_json_api_interface_t *ptr; | |||
1347 | ||||
1348 | for (ptr = old_module->module_interface->json_api_interface; ptr; ptr = ptr->next) { | |||
1349 | if (ptr->interface_name) { | |||
1350 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1350, ((void*)0), SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name); | |||
1351 | ||||
1352 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1352, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1353 | ptr->interface_name); | |||
1354 | ||||
1355 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1356 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1357 | } else { | |||
1358 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1358, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1359 | } | |||
1360 | ||||
1361 | ||||
1362 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1362, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1363 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "json_api"); | |||
1364 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1365 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->desc)(ptr->desc ? ptr->desc : "")); | |||
1366 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)(ptr->syntax ? ptr->syntax : "")); | |||
1367 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1367, &event, ((void*)0) ); | |||
1368 | removed++; | |||
1369 | } | |||
1370 | switch_core_hash_delete(loadable_modules.json_api_hash, ptr->interface_name); | |||
1371 | } | |||
1372 | } | |||
1373 | } | |||
1374 | ||||
1375 | if (old_module->module_interface->file_interface) { | |||
1376 | const switch_file_interface_t *ptr; | |||
1377 | switch_file_node_t *node, *head, *last = NULL((void*)0); | |||
1378 | ||||
1379 | for (ptr = old_module->module_interface->file_interface; ptr; ptr = ptr->next) { | |||
1380 | if (ptr->interface_name) { | |||
1381 | int i; | |||
1382 | ||||
1383 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1383, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1384 | ptr->interface_name); | |||
1385 | ||||
1386 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1387 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1388 | } else { | |||
1389 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1389, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1390 | } | |||
1391 | ||||
1392 | for (i = 0; ptr->extens[i]; i++) { | |||
1393 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1393, ((void*)0), SWITCH_LOG_NOTICE, "Deleting File Format '%s'\n", ptr->extens[i]); | |||
1394 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1394, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1395 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "file"); | |||
1396 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->extens[i]); | |||
1397 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", old_module->module_interface->module_name); | |||
1398 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1398, &event, ((void*)0) ); | |||
1399 | removed++; | |||
1400 | } | |||
1401 | ||||
1402 | if ((head = switch_core_hash_find(loadable_modules.file_hash, ptr->extens[i]))) { | |||
1403 | for(node = head; node; node = node->next) { | |||
1404 | if (!strcmp(node->interface_name, old_module->module_interface->module_name)) { | |||
1405 | if (node == head) { | |||
1406 | if ((node = node->next)) { | |||
1407 | switch_core_hash_insert(loadable_modules.file_hash, ptr->extens[i], (const void *) node)switch_core_hash_insert_destructor(loadable_modules.file_hash , ptr->extens[i], (const void *) node, ((void*)0)); | |||
1408 | } else { | |||
1409 | switch_core_hash_delete(loadable_modules.file_hash, ptr->extens[i]); | |||
1410 | } | |||
1411 | } else { | |||
1412 | if (last) { | |||
1413 | last->next = node->next; | |||
1414 | } | |||
1415 | } | |||
1416 | break; | |||
1417 | } | |||
1418 | last = node; | |||
1419 | } | |||
1420 | } | |||
1421 | } | |||
1422 | } | |||
1423 | } | |||
1424 | } | |||
1425 | ||||
1426 | if (old_module->module_interface->database_interface) { | |||
1427 | const switch_database_interface_t *ptr; | |||
1428 | switch_database_node_t *node, *head, *last = NULL((void*)0); | |||
1429 | ||||
1430 | for (ptr = old_module->module_interface->database_interface; ptr; ptr = ptr->next) { | |||
1431 | if (ptr->interface_name) { | |||
1432 | int i; | |||
1433 | ||||
1434 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1434, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1435 | ptr->interface_name); | |||
1436 | ||||
1437 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1438 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1439 | } | |||
1440 | else { | |||
1441 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1441, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1442 | } | |||
1443 | ||||
1444 | for (i = 0; ptr->prefixes[i]; i++) { | |||
1445 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1445, ((void*)0), SWITCH_LOG_NOTICE, "Deleting dsn prefix '%s'\n", ptr->prefixes[i]); | |||
1446 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1446, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1447 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "database"); | |||
1448 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->prefixes[i]); | |||
1449 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", old_module->module_interface->module_name); | |||
1450 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1450, &event, ((void*)0) ); | |||
1451 | removed++; | |||
1452 | } | |||
1453 | ||||
1454 | if ((head = switch_core_hash_find(loadable_modules.database_hash, ptr->prefixes[i]))) { | |||
1455 | for (node = head; node; node = node->next) { | |||
1456 | if (!strcmp(node->interface_name, old_module->module_interface->module_name)) { | |||
1457 | if (node == head) { | |||
1458 | if ((node = node->next)) { | |||
1459 | switch_core_hash_insert(loadable_modules.database_hash, ptr->prefixes[i], (const void *)node)switch_core_hash_insert_destructor(loadable_modules.database_hash , ptr->prefixes[i], (const void *)node, ((void*)0)); | |||
1460 | } | |||
1461 | else { | |||
1462 | switch_core_hash_delete(loadable_modules.database_hash, ptr->prefixes[i]); | |||
1463 | } | |||
1464 | } | |||
1465 | else { | |||
1466 | if (last) { | |||
1467 | last->next = node->next; | |||
1468 | } | |||
1469 | } | |||
1470 | break; | |||
1471 | } | |||
1472 | last = node; | |||
1473 | } | |||
1474 | } | |||
1475 | } | |||
1476 | ||||
1477 | switch_cache_db_database_interface_flush_handles(old_module->module_interface->database_interface); | |||
1478 | } | |||
1479 | } | |||
1480 | } | |||
1481 | ||||
1482 | if (old_module->module_interface->speech_interface) { | |||
1483 | const switch_speech_interface_t *ptr; | |||
1484 | ||||
1485 | for (ptr = old_module->module_interface->speech_interface; ptr; ptr = ptr->next) { | |||
1486 | ||||
1487 | if (ptr->interface_name) { | |||
1488 | ||||
1489 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1489, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1490 | ptr->interface_name); | |||
1491 | ||||
1492 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1493 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1494 | } else { | |||
1495 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1495, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1496 | } | |||
1497 | ||||
1498 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1498, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Speech interface '%s'\n", ptr->interface_name); | |||
1499 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1499, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1500 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "speech"); | |||
1501 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1502 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1502, &event, ((void*)0) ); | |||
1503 | removed++; | |||
1504 | } | |||
1505 | switch_core_hash_delete(loadable_modules.speech_hash, ptr->interface_name); | |||
1506 | } | |||
1507 | } | |||
1508 | } | |||
1509 | ||||
1510 | if (old_module->module_interface->asr_interface) { | |||
1511 | const switch_asr_interface_t *ptr; | |||
1512 | ||||
1513 | for (ptr = old_module->module_interface->asr_interface; ptr; ptr = ptr->next) { | |||
1514 | if (ptr->interface_name) { | |||
1515 | ||||
1516 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1516, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1517 | ptr->interface_name); | |||
1518 | ||||
1519 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1520 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1521 | } else { | |||
1522 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1522, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1523 | } | |||
1524 | ||||
1525 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1525, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Asr interface '%s'\n", ptr->interface_name); | |||
1526 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1526, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1527 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "asr"); | |||
1528 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1529 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1529, &event, ((void*)0) ); | |||
1530 | removed++; | |||
1531 | } | |||
1532 | switch_core_hash_delete(loadable_modules.asr_hash, ptr->interface_name); | |||
1533 | } | |||
1534 | } | |||
1535 | } | |||
1536 | ||||
1537 | if (old_module->module_interface->directory_interface) { | |||
1538 | const switch_directory_interface_t *ptr; | |||
1539 | ||||
1540 | for (ptr = old_module->module_interface->directory_interface; ptr; ptr = ptr->next) { | |||
1541 | if (ptr->interface_name) { | |||
1542 | ||||
1543 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1543, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1544 | ptr->interface_name); | |||
1545 | ||||
1546 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1547 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1548 | } else { | |||
1549 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1549, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1550 | } | |||
1551 | ||||
1552 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1552, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Directory interface '%s'\n", ptr->interface_name); | |||
1553 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1553, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1554 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "directory"); | |||
1555 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1556 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1556, &event, ((void*)0) ); | |||
1557 | removed++; | |||
1558 | } | |||
1559 | switch_core_hash_delete(loadable_modules.directory_hash, ptr->interface_name); | |||
1560 | } | |||
1561 | } | |||
1562 | } | |||
1563 | ||||
1564 | ||||
1565 | if (old_module->module_interface->chat_interface) { | |||
1566 | const switch_chat_interface_t *ptr; | |||
1567 | ||||
1568 | for (ptr = old_module->module_interface->chat_interface; ptr; ptr = ptr->next) { | |||
1569 | if (ptr->interface_name) { | |||
1570 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1570, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1571 | ptr->interface_name); | |||
1572 | ||||
1573 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1574 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1575 | } else { | |||
1576 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1576, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1577 | } | |||
1578 | ||||
1579 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1579, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Chat interface '%s'\n", ptr->interface_name); | |||
1580 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1580, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1581 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "chat"); | |||
1582 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1583 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1583, &event, ((void*)0) ); | |||
1584 | removed++; | |||
1585 | } | |||
1586 | switch_core_hash_delete(loadable_modules.chat_hash, ptr->interface_name); | |||
1587 | } | |||
1588 | } | |||
1589 | } | |||
1590 | ||||
1591 | if (old_module->module_interface->say_interface) { | |||
1592 | const switch_say_interface_t *ptr; | |||
1593 | ||||
1594 | for (ptr = old_module->module_interface->say_interface; ptr; ptr = ptr->next) { | |||
1595 | if (ptr->interface_name) { | |||
1596 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1596, ((void*)0), SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", | |||
1597 | ptr->interface_name); | |||
1598 | ||||
1599 | if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { | |||
1600 | switch_thread_rwlock_unlock(ptr->rwlock); | |||
1601 | } else { | |||
1602 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1602, ((void*)0), SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name); | |||
1603 | } | |||
1604 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1604, ((void*)0), SWITCH_LOG_NOTICE, "Deleting Say interface '%s'\n", ptr->interface_name); | |||
1605 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1605, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1606 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "say"); | |||
1607 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1608 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1608, &event, ((void*)0) ); | |||
1609 | removed++; | |||
1610 | } | |||
1611 | switch_core_hash_delete(loadable_modules.say_hash, ptr->interface_name); | |||
1612 | } | |||
1613 | } | |||
1614 | } | |||
1615 | ||||
1616 | if (old_module->module_interface->management_interface) { | |||
1617 | const switch_management_interface_t *ptr; | |||
1618 | ||||
1619 | for (ptr = old_module->module_interface->management_interface; ptr; ptr = ptr->next) { | |||
1620 | if (ptr->relative_oid) { | |||
1621 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1621, ((void*)0), SWITCH_LOG_NOTICE, | |||
1622 | "Deleting Management interface '%s' OID[%s.%s]\n", old_module->key, FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880", ptr->relative_oid); | |||
1623 | switch_core_hash_delete(loadable_modules.management_hash, ptr->relative_oid); | |||
1624 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1624, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1625 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "management"); | |||
1626 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->relative_oid); | |||
1627 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1627, &event, ((void*)0) ); | |||
1628 | removed++; | |||
1629 | } | |||
1630 | } | |||
1631 | } | |||
1632 | } | |||
1633 | ||||
1634 | if (old_module->module_interface->limit_interface) { | |||
1635 | const switch_limit_interface_t *ptr; | |||
1636 | ||||
1637 | for (ptr = old_module->module_interface->limit_interface; ptr; ptr = ptr->next) { | |||
1638 | if (ptr->interface_name) { | |||
1639 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1639, ((void*)0), SWITCH_LOG_NOTICE, | |||
1640 | "Deleting Limit interface '%s'\n", ptr->interface_name); | |||
1641 | switch_core_hash_delete(loadable_modules.limit_hash, ptr->interface_name); | |||
1642 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1642, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1643 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "limit"); | |||
1644 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); | |||
1645 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1645, &event, ((void*)0) ); | |||
1646 | removed++; | |||
1647 | } | |||
1648 | } | |||
1649 | } | |||
1650 | } | |||
1651 | ||||
1652 | if (!removed) { | |||
1653 | if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 1653, &event, SWITCH_EVENT_MODULE_UNLOAD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
1654 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "generic"); | |||
1655 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", old_module->key); | |||
1656 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 1656, &event, ((void*)0) ); | |||
1657 | removed++; | |||
1658 | } | |||
1659 | } | |||
1660 | switch_mutex_unlock(loadable_modules.mutex); | |||
1661 | ||||
1662 | return SWITCH_STATUS_SUCCESS; | |||
1663 | ||||
1664 | } | |||
1665 | ||||
1666 | ||||
1667 | static switch_status_t switch_loadable_module_load_file(char *path, char *filename, switch_bool_t global, switch_loadable_module_t **new_module) | |||
1668 | { | |||
1669 | switch_loadable_module_t *module = NULL((void*)0); | |||
1670 | switch_dso_lib_t dso = NULL((void*)0); | |||
1671 | apr_status_t status = SWITCH_STATUS_SUCCESS; | |||
1672 | switch_loadable_module_function_table_t *interface_struct_handle = NULL((void*)0); | |||
1673 | switch_loadable_module_function_table_t *mod_interface_functions = NULL((void*)0); | |||
1674 | char *struct_name = NULL((void*)0); | |||
1675 | switch_module_load_t load_func_ptr = NULL((void*)0); | |||
1676 | int loading = 1; | |||
1677 | switch_loadable_module_interface_t *module_interface = NULL((void*)0); | |||
1678 | char *derr = NULL((void*)0); | |||
1679 | const char *err = NULL((void*)0); | |||
1680 | switch_memory_pool_t *pool = NULL((void*)0); | |||
1681 | switch_bool_t load_global = global; | |||
1682 | ||||
1683 | switch_assert(path != NULL)((path != ((void*)0)) ? (void) (0) : __assert_fail ("path != ((void*)0)" , "src/switch_loadable_module.c", 1683, __extension__ __PRETTY_FUNCTION__ )); | |||
1684 | ||||
1685 | switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_loadable_module.c" , (const char *)__func__, 1685); | |||
1686 | *new_module = NULL((void*)0); | |||
1687 | ||||
1688 | struct_name = switch_core_sprintf(pool, "%s_module_interface", filename); | |||
1689 | ||||
1690 | #ifdef WIN32 | |||
1691 | dso = switch_dso_open("FreeSwitch.dll", load_global, &derr); | |||
1692 | #elif defined (MACOSX) || defined(DARWIN) | |||
1693 | { | |||
1694 | char *lib_path = switch_mprintf("%s/libfreeswitch.dylib", SWITCH_GLOBAL_dirs.lib_dir); | |||
1695 | dso = switch_dso_open(lib_path, load_global, &derr); | |||
1696 | switch_safe_free(lib_path)if (lib_path) {free(lib_path);lib_path=((void*)0);}; | |||
1697 | } | |||
1698 | #else | |||
1699 | dso = switch_dso_open(NULL((void*)0), load_global, &derr); | |||
1700 | #endif | |||
1701 | if (!derr && dso) { | |||
1702 | interface_struct_handle = switch_dso_data_sym(dso, struct_name, &derr); | |||
1703 | } | |||
1704 | ||||
1705 | switch_safe_free(derr)if (derr) {free(derr);derr=((void*)0);}; | |||
1706 | ||||
1707 | if (!interface_struct_handle) { | |||
1708 | if (dso) switch_dso_destroy(&dso); | |||
1709 | dso = switch_dso_open(path, load_global, &derr); | |||
1710 | } | |||
1711 | ||||
1712 | while (loading) { | |||
1713 | if (derr) { | |||
1714 | err = derr; | |||
1715 | break; | |||
1716 | } | |||
1717 | ||||
1718 | if (!interface_struct_handle) { | |||
1719 | interface_struct_handle = switch_dso_data_sym(dso, struct_name, &derr); | |||
1720 | } | |||
1721 | ||||
1722 | if (derr) { | |||
1723 | err = derr; | |||
1724 | break; | |||
1725 | } | |||
1726 | ||||
1727 | if (interface_struct_handle && interface_struct_handle->switch_api_version != SWITCH_API_VERSION5) { | |||
1728 | err = "Trying to load an out of date module, please rebuild the module."; | |||
1729 | break; | |||
1730 | } | |||
1731 | ||||
1732 | if (!load_global && interface_struct_handle && switch_test_flag(interface_struct_handle, SMODF_GLOBAL_SYMBOLS)((interface_struct_handle)->flags & SMODF_GLOBAL_SYMBOLS )) { | |||
1733 | load_global = SWITCH_TRUE; | |||
1734 | switch_dso_destroy(&dso); | |||
1735 | interface_struct_handle = NULL((void*)0); | |||
1736 | dso = switch_dso_open(path, load_global, &derr); | |||
1737 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1737, ((void*)0), SWITCH_LOG_DEBUG, "Loading module with global namespace at request of module\n"); | |||
1738 | continue; | |||
1739 | } | |||
1740 | ||||
1741 | if (interface_struct_handle) { | |||
1742 | mod_interface_functions = interface_struct_handle; | |||
1743 | load_func_ptr = mod_interface_functions->load; | |||
1744 | } | |||
1745 | ||||
1746 | if (load_func_ptr == NULL((void*)0)) { | |||
1747 | err = "Cannot locate symbol 'switch_module_load' please make sure this is a valid module."; | |||
1748 | break; | |||
1749 | } | |||
1750 | ||||
1751 | status = load_func_ptr(&module_interface, pool); | |||
1752 | ||||
1753 | if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) { | |||
1754 | err = "Module load routine returned an error"; | |||
1755 | module_interface = NULL((void*)0); | |||
1756 | break; | |||
1757 | } | |||
1758 | ||||
1759 | if (!module_interface) { | |||
1760 | err = "Module failed to initialize its module_interface. Is this a valid module?"; | |||
1761 | break; | |||
1762 | } | |||
1763 | ||||
1764 | if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))switch_core_perform_alloc(pool, sizeof(switch_loadable_module_t ), "src/switch_loadable_module.c", (const char *)__func__, 1764 )) == 0) { | |||
1765 | abort(); | |||
1766 | } | |||
1767 | ||||
1768 | if (status == SWITCH_STATUS_NOUNLOAD) { | |||
1769 | module->perm++; | |||
1770 | } | |||
1771 | ||||
1772 | loading = 0; | |||
1773 | } | |||
1774 | ||||
1775 | ||||
1776 | if (err) { | |||
1777 | ||||
1778 | if (dso) { | |||
1779 | switch_dso_destroy(&dso); | |||
1780 | } | |||
1781 | ||||
1782 | if (pool) { | |||
1783 | switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_loadable_module.c" , (const char *)__func__, 1783); | |||
1784 | } | |||
1785 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1785, ((void*)0), SWITCH_LOG_CRIT, "Error Loading module %s\n**%s**\n", path, err); | |||
1786 | switch_safe_free(derr)if (derr) {free(derr);derr=((void*)0);}; | |||
1787 | return SWITCH_STATUS_GENERR; | |||
1788 | } | |||
1789 | ||||
1790 | module->pool = pool; | |||
1791 | module->filename = switch_core_strdup(module->pool, path)switch_core_perform_strdup(module->pool, path, "src/switch_loadable_module.c" , (const char *)__func__, 1791); | |||
1792 | module->module_interface = module_interface; | |||
1793 | module->switch_module_load = load_func_ptr; | |||
1794 | ||||
1795 | if (mod_interface_functions) { | |||
1796 | module->switch_module_shutdown = mod_interface_functions->shutdown; | |||
1797 | module->switch_module_runtime = mod_interface_functions->runtime; | |||
1798 | } | |||
1799 | ||||
1800 | module->lib = dso; | |||
1801 | ||||
1802 | *new_module = module; | |||
1803 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1803, ((void*)0), SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module_interface->module_name); | |||
1804 | ||||
1805 | switch_core_set_signal_handlers(); | |||
1806 | ||||
1807 | return SWITCH_STATUS_SUCCESS; | |||
1808 | ||||
1809 | } | |||
1810 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_load_module(const char *dir, const char *fname, switch_bool_t runtime, const char **err) | |||
1811 | { | |||
1812 | return switch_loadable_module_load_module_ex(dir, fname, runtime, SWITCH_FALSE, err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, NULL((void*)0)); | |||
1813 | } | |||
1814 | ||||
1815 | static switch_status_t switch_loadable_module_load_module_ex(const char *dir, const char *fname, switch_bool_t runtime, switch_bool_t global, const char **err, switch_loadable_module_type_t type, switch_hash_t *event_hash) | |||
1816 | { | |||
1817 | switch_size_t len = 0; | |||
1818 | char *path; | |||
1819 | char *file, *dot; | |||
1820 | switch_loadable_module_t *new_module = NULL((void*)0); | |||
1821 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||
1822 | ||||
1823 | #ifdef WIN32 | |||
1824 | const char *ext = ".dll"; | |||
1825 | #else | |||
1826 | const char *ext = ".so"; | |||
1827 | #endif | |||
1828 | ||||
1829 | *err = ""; | |||
1830 | ||||
1831 | if ((file = switch_core_strdup(loadable_modules.pool, fname)switch_core_perform_strdup(loadable_modules.pool, fname, "src/switch_loadable_module.c" , (const char *)__func__, 1831)) == 0) { | |||
1832 | *err = "allocation error"; | |||
1833 | return SWITCH_STATUS_FALSE; | |||
1834 | } | |||
1835 | ||||
1836 | if (switch_is_file_path(file)) { | |||
1837 | path = switch_core_strdup(loadable_modules.pool, file)switch_core_perform_strdup(loadable_modules.pool, file, "src/switch_loadable_module.c" , (const char *)__func__, 1837); | |||
1838 | file = (char *) switch_cut_path(file); | |||
1839 | if ((dot = strchr(file, '.'))) { | |||
1840 | *dot = '\0'; | |||
1841 | } | |||
1842 | } else { | |||
1843 | if ((dot = strchr(file, '.'))) { | |||
1844 | *dot = '\0'; | |||
1845 | } | |||
1846 | len = strlen(switch_str_nil(dir)(dir ? dir : "")); | |||
1847 | len += strlen(file); | |||
1848 | len += 8; | |||
1849 | path = (char *) switch_core_alloc(loadable_modules.pool, len)switch_core_perform_alloc(loadable_modules.pool, len, "src/switch_loadable_module.c" , (const char *)__func__, 1849); | |||
1850 | switch_snprintf(path, len, "%s%s%s%s", switch_str_nil(dir)(dir ? dir : ""), SWITCH_PATH_SEPARATOR"/", file, ext); | |||
1851 | } | |||
1852 | ||||
1853 | ||||
1854 | if (switch_core_hash_find_locked(loadable_modules.module_hash, file, loadable_modules.mutex)) { | |||
1855 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1855, ((void*)0), SWITCH_LOG_WARNING, "Module %s Already Loaded!\n", file); | |||
1856 | *err = "Module already loaded"; | |||
1857 | status = SWITCH_STATUS_FALSE; | |||
1858 | } else if ((status = switch_loadable_module_load_file(path, file, global, &new_module)) == SWITCH_STATUS_SUCCESS) { | |||
1859 | new_module->type = type; | |||
1860 | ||||
1861 | if ((status = switch_loadable_module_process(file, new_module, event_hash)) == SWITCH_STATUS_SUCCESS && runtime) { | |||
1862 | if (new_module->switch_module_runtime) { | |||
1863 | new_module->thread = switch_core_launch_thread(switch_loadable_module_exec, new_module, new_module->pool); | |||
1864 | } | |||
1865 | } else if (status != SWITCH_STATUS_SUCCESS) { | |||
1866 | *err = "module load routine returned an error"; | |||
1867 | } | |||
1868 | } else { | |||
1869 | *err = "module load file routine returned an error"; | |||
1870 | } | |||
1871 | ||||
1872 | ||||
1873 | return status; | |||
1874 | ||||
1875 | } | |||
1876 | ||||
1877 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_exists(const char *mod) | |||
1878 | { | |||
1879 | switch_status_t status; | |||
1880 | ||||
1881 | if (zstr(mod)_zstr(mod)) { | |||
1882 | return SWITCH_STATUS_FALSE; | |||
1883 | } | |||
1884 | ||||
1885 | switch_mutex_lock(loadable_modules.mutex); | |||
1886 | if (switch_core_hash_find(loadable_modules.module_hash, mod)) { | |||
1887 | status = SWITCH_STATUS_SUCCESS; | |||
1888 | } else { | |||
1889 | status = SWITCH_STATUS_FALSE; | |||
1890 | } | |||
1891 | switch_mutex_unlock(loadable_modules.mutex); | |||
1892 | ||||
1893 | return status; | |||
1894 | } | |||
1895 | ||||
1896 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_protect(const char *mod) | |||
1897 | { | |||
1898 | switch_loadable_module_t *module = NULL((void*)0); | |||
1899 | switch_status_t status = SWITCH_STATUS_FALSE; | |||
1900 | ||||
1901 | if (zstr(mod)_zstr(mod)) { | |||
1902 | return SWITCH_STATUS_FALSE; | |||
1903 | } | |||
1904 | ||||
1905 | switch_mutex_lock(loadable_modules.mutex); | |||
1906 | if ((module = switch_core_hash_find(loadable_modules.module_hash, mod))) { | |||
1907 | if (!module->perm) { | |||
1908 | module->perm++; | |||
1909 | } | |||
1910 | status = SWITCH_STATUS_SUCCESS; | |||
1911 | } | |||
1912 | else { | |||
1913 | status = SWITCH_STATUS_FALSE; | |||
1914 | } | |||
1915 | switch_mutex_unlock(loadable_modules.mutex); | |||
1916 | ||||
1917 | return status; | |||
1918 | } | |||
1919 | ||||
1920 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_unload_module(const char *dir, const char *fname, switch_bool_t force, const char **err) | |||
1921 | { | |||
1922 | switch_loadable_module_t *module = NULL((void*)0); | |||
1923 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||
1924 | ||||
1925 | if (force) { | |||
1926 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1926, ((void*)0), SWITCH_LOG_WARNING, "Spin the barrel and pull the trigger.......!\n"); | |||
1927 | } | |||
1928 | ||||
1929 | switch_mutex_lock(loadable_modules.mutex); | |||
1930 | if ((module = switch_core_hash_find(loadable_modules.module_hash, fname))) { | |||
1931 | if (module->perm) { | |||
1932 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1932, ((void*)0), SWITCH_LOG_CRIT, "Module is not unloadable.\n"); | |||
1933 | *err = "Module is not unloadable"; | |||
1934 | status = SWITCH_STATUS_NOUNLOAD; | |||
1935 | goto unlock; | |||
1936 | } else { | |||
1937 | /* Prevent anything from using the module while it's shutting down */ | |||
1938 | switch_core_hash_delete(loadable_modules.module_hash, fname); | |||
1939 | switch_mutex_unlock(loadable_modules.mutex); | |||
1940 | if ((status = do_shutdown(module, SWITCH_TRUE, SWITCH_TRUE, !force, err)) != SWITCH_STATUS_SUCCESS) { | |||
1941 | /* Something went wrong in the module's shutdown function, add it again */ | |||
1942 | switch_core_hash_insert_locked(loadable_modules.module_hash, fname, module, loadable_modules.mutex); | |||
1943 | } | |||
1944 | goto end; | |||
1945 | } | |||
1946 | } else { | |||
1947 | *err = "No such module!"; | |||
1948 | status = SWITCH_STATUS_FALSE; | |||
1949 | } | |||
1950 | unlock: | |||
1951 | switch_mutex_unlock(loadable_modules.mutex); | |||
1952 | end: | |||
1953 | if (force) { | |||
1954 | switch_yield(1000000)switch_sleep(1000000);; | |||
1955 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 1955, ((void*)0), SWITCH_LOG_WARNING, "PHEW!\n"); | |||
1956 | } | |||
1957 | ||||
1958 | return status; | |||
1959 | ||||
1960 | } | |||
1961 | ||||
1962 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data) | |||
1963 | { | |||
1964 | switch_dir_t *dir = NULL((void*)0); | |||
1965 | switch_status_t status; | |||
1966 | char buffer[256]; | |||
1967 | const char *fname; | |||
1968 | const char *fname_ext; | |||
1969 | char *fname_base; | |||
1970 | ||||
1971 | #ifdef WIN32 | |||
1972 | const char *ext = ".dll"; | |||
1973 | #else | |||
1974 | const char *ext = ".so"; | |||
1975 | #endif | |||
1976 | ||||
1977 | if ((status = switch_dir_open(&dir, dir_path, loadable_modules.pool)) != SWITCH_STATUS_SUCCESS) { | |||
1978 | return status; | |||
1979 | } | |||
1980 | ||||
1981 | while((fname = switch_dir_next_file(dir, buffer, sizeof(buffer)))) { | |||
1982 | if ((fname_ext = strrchr(fname, '.'))) { | |||
1983 | if (!strcmp(fname_ext, ext)) { | |||
1984 | if (!(fname_base = switch_mprintf("%.*s", (int)(fname_ext-fname), fname))) { | |||
1985 | status = SWITCH_STATUS_GENERR; | |||
1986 | goto end; | |||
1987 | } | |||
1988 | callback(user_data, fname_base); | |||
1989 | switch_safe_free(fname_base)if (fname_base) {free(fname_base);fname_base=((void*)0);} | |||
1990 | } | |||
1991 | } | |||
1992 | } | |||
1993 | ||||
1994 | ||||
1995 | end: | |||
1996 | switch_dir_close(dir); | |||
1997 | return status; | |||
1998 | } | |||
1999 | ||||
2000 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data) | |||
2001 | { | |||
2002 | switch_hash_index_t *hi; | |||
2003 | void *val; | |||
2004 | switch_loadable_module_t *module; | |||
2005 | ||||
2006 | switch_mutex_lock(loadable_modules.mutex); | |||
2007 | for (hi = switch_core_hash_first(loadable_modules.module_hash)switch_core_hash_first_iter(loadable_modules.module_hash, ((void *)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
2008 | switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val); | |||
2009 | module = (switch_loadable_module_t *) val; | |||
2010 | ||||
2011 | callback(user_data, module->module_interface->module_name); | |||
2012 | } | |||
2013 | switch_mutex_unlock(loadable_modules.mutex); | |||
2014 | ||||
2015 | return SWITCH_STATUS_SUCCESS; | |||
2016 | } | |||
2017 | ||||
2018 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_build_dynamic(char *filename, | |||
2019 | switch_module_load_t switch_module_load, | |||
2020 | switch_module_runtime_t switch_module_runtime, | |||
2021 | switch_module_shutdown_t switch_module_shutdown, switch_bool_t runtime) | |||
2022 | { | |||
2023 | switch_loadable_module_t *module = NULL((void*)0); | |||
2024 | switch_module_load_t load_func_ptr = NULL((void*)0); | |||
2025 | int loading = 1; | |||
2026 | const char *err = NULL((void*)0); | |||
2027 | switch_loadable_module_interface_t *module_interface = NULL((void*)0); | |||
2028 | switch_memory_pool_t *pool; | |||
2029 | ||||
2030 | ||||
2031 | if (switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_loadable_module.c" , (const char *)__func__, 2031) != SWITCH_STATUS_SUCCESS) { | |||
2032 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2032, ((void*)0), SWITCH_LOG_CRIT, "OH OH no pool\n"); | |||
2033 | abort(); | |||
2034 | } | |||
2035 | ||||
2036 | if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))switch_core_perform_alloc(pool, sizeof(switch_loadable_module_t ), "src/switch_loadable_module.c", (const char *)__func__, 2036 )) == 0) { | |||
2037 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2037, ((void*)0), SWITCH_LOG_CONSOLE, "Couldn't allocate memory\n"); | |||
2038 | abort(); | |||
2039 | } | |||
2040 | ||||
2041 | ||||
2042 | ||||
2043 | while (loading) { | |||
2044 | switch_status_t status; | |||
2045 | load_func_ptr = (switch_module_load_t) switch_module_load; | |||
2046 | ||||
2047 | if (load_func_ptr == NULL((void*)0)) { | |||
2048 | err = "Cannot Load"; | |||
2049 | break; | |||
2050 | } | |||
2051 | ||||
2052 | status = load_func_ptr(&module_interface, pool); | |||
2053 | ||||
2054 | if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) { | |||
2055 | err = "Module load routine returned an error"; | |||
2056 | module_interface = NULL((void*)0); | |||
2057 | break; | |||
2058 | } | |||
2059 | ||||
2060 | if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))switch_core_perform_alloc(pool, sizeof(switch_loadable_module_t ), "src/switch_loadable_module.c", (const char *)__func__, 2060 )) == 0) { | |||
2061 | abort(); | |||
2062 | } | |||
2063 | ||||
2064 | if (status == SWITCH_STATUS_NOUNLOAD) { | |||
2065 | module->perm++; | |||
2066 | } | |||
2067 | ||||
2068 | loading = 0; | |||
2069 | } | |||
2070 | ||||
2071 | if (err) { | |||
2072 | switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_loadable_module.c" , (const char *)__func__, 2072); | |||
2073 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2073, ((void*)0), SWITCH_LOG_CONSOLE, "Error Loading module %s\n**%s**\n", filename, err); | |||
2074 | return SWITCH_STATUS_GENERR; | |||
2075 | } | |||
2076 | ||||
2077 | module->pool = pool; | |||
2078 | module->filename = switch_core_strdup(module->pool, filename)switch_core_perform_strdup(module->pool, filename, "src/switch_loadable_module.c" , (const char *)__func__, 2078); | |||
2079 | module->module_interface = module_interface; | |||
2080 | module->switch_module_load = load_func_ptr; | |||
2081 | ||||
2082 | if (switch_module_shutdown) { | |||
2083 | module->switch_module_shutdown = switch_module_shutdown; | |||
2084 | } | |||
2085 | if (switch_module_runtime) { | |||
2086 | module->switch_module_runtime = switch_module_runtime; | |||
2087 | } | |||
2088 | if (runtime && module->switch_module_runtime) { | |||
2089 | module->thread = switch_core_launch_thread(switch_loadable_module_exec, module, module->pool); | |||
2090 | } | |||
2091 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2091, ((void*)0), SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module_interface->module_name); | |||
2092 | return switch_loadable_module_process((char *) module->filename, module, NULL((void*)0)); | |||
2093 | } | |||
2094 | ||||
2095 | #ifdef WIN32 | |||
2096 | static void switch_loadable_module_path_init() | |||
2097 | { | |||
2098 | char *path = NULL((void*)0), *working = NULL((void*)0); | |||
2099 | apr_dir_t *perl_dir_handle = NULL((void*)0); | |||
2100 | ||||
2101 | apr_env_get(&path, "path", loadable_modules.pool); | |||
2102 | apr_filepath_get(&working, APR_FILEPATH_NATIVE0x10, loadable_modules.pool); | |||
2103 | ||||
2104 | if (apr_dir_open(&perl_dir_handle, ".\\perl", loadable_modules.pool) == APR_SUCCESS0) { | |||
2105 | apr_dir_close(perl_dir_handle); | |||
2106 | apr_env_set("path", apr_pstrcat(loadable_modules.pool, path, ";", working, "\\perl", NULL((void*)0)), loadable_modules.pool); | |||
2107 | } | |||
2108 | } | |||
2109 | #endif | |||
2110 | ||||
2111 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_loadable_module_init(switch_bool_t autoload) | |||
2112 | { | |||
2113 | ||||
2114 | apr_finfo_t finfo = { 0 }; | |||
2115 | apr_dir_t *module_dir_handle = NULL((void*)0); | |||
2116 | apr_int32_t finfo_flags = APR_FINFO_DIRENT0x02000000 | APR_FINFO_TYPE0x00008000 | APR_FINFO_NAME0x02000000; | |||
2117 | char *precf = "pre_load_modules.conf"; | |||
2118 | char *cf = "modules.conf"; | |||
2119 | char *pcf = "post_load_modules.conf"; | |||
2120 | switch_xml_t cfg, xml; | |||
2121 | unsigned char all = 0; | |||
2122 | unsigned int count = 0; | |||
2123 | const char *err; | |||
2124 | switch_hash_t *event_hash; | |||
2125 | switch_hash_index_t *hi; | |||
2126 | void *hash_val; | |||
2127 | switch_event_t *event; | |||
2128 | ||||
2129 | ||||
2130 | #ifdef WIN32 | |||
2131 | const char *ext = ".dll"; | |||
2132 | const char *EXT = ".DLL"; | |||
2133 | #elif defined (MACOSX) || defined (DARWIN) | |||
2134 | const char *ext = ".dylib"; | |||
2135 | const char *EXT = ".DYLIB"; | |||
2136 | #else | |||
2137 | const char *ext = ".so"; | |||
2138 | const char *EXT = ".SO"; | |||
2139 | #endif | |||
2140 | ||||
2141 | memset(&loadable_modules, 0, sizeof(loadable_modules)); | |||
2142 | switch_core_new_memory_pool(&loadable_modules.pool)switch_core_perform_new_memory_pool(&loadable_modules.pool , "src/switch_loadable_module.c", (const char *)__func__, 2142 ); | |||
2143 | ||||
2144 | ||||
2145 | #ifdef WIN32 | |||
2146 | switch_loadable_module_path_init(); | |||
2147 | #endif | |||
2148 | ||||
2149 | switch_core_hash_init(&loadable_modules.module_hash)switch_core_hash_init_case(&loadable_modules.module_hash, SWITCH_TRUE); | |||
2150 | switch_core_hash_init_nocase(&loadable_modules.endpoint_hash)switch_core_hash_init_case(&loadable_modules.endpoint_hash , SWITCH_FALSE); | |||
2151 | switch_core_hash_init_nocase(&loadable_modules.codec_hash)switch_core_hash_init_case(&loadable_modules.codec_hash, SWITCH_FALSE ); | |||
2152 | switch_core_hash_init_nocase(&loadable_modules.timer_hash)switch_core_hash_init_case(&loadable_modules.timer_hash, SWITCH_FALSE ); | |||
2153 | switch_core_hash_init_nocase(&loadable_modules.application_hash)switch_core_hash_init_case(&loadable_modules.application_hash , SWITCH_FALSE); | |||
2154 | switch_core_hash_init_nocase(&loadable_modules.chat_application_hash)switch_core_hash_init_case(&loadable_modules.chat_application_hash , SWITCH_FALSE); | |||
2155 | switch_core_hash_init_nocase(&loadable_modules.api_hash)switch_core_hash_init_case(&loadable_modules.api_hash, SWITCH_FALSE ); | |||
2156 | switch_core_hash_init_nocase(&loadable_modules.json_api_hash)switch_core_hash_init_case(&loadable_modules.json_api_hash , SWITCH_FALSE); | |||
2157 | switch_core_hash_init(&loadable_modules.file_hash)switch_core_hash_init_case(&loadable_modules.file_hash, SWITCH_TRUE ); | |||
2158 | switch_core_hash_init_nocase(&loadable_modules.speech_hash)switch_core_hash_init_case(&loadable_modules.speech_hash, SWITCH_FALSE); | |||
2159 | switch_core_hash_init_nocase(&loadable_modules.asr_hash)switch_core_hash_init_case(&loadable_modules.asr_hash, SWITCH_FALSE ); | |||
2160 | switch_core_hash_init_nocase(&loadable_modules.directory_hash)switch_core_hash_init_case(&loadable_modules.directory_hash , SWITCH_FALSE); | |||
2161 | switch_core_hash_init_nocase(&loadable_modules.chat_hash)switch_core_hash_init_case(&loadable_modules.chat_hash, SWITCH_FALSE ); | |||
2162 | switch_core_hash_init_nocase(&loadable_modules.say_hash)switch_core_hash_init_case(&loadable_modules.say_hash, SWITCH_FALSE ); | |||
2163 | switch_core_hash_init_nocase(&loadable_modules.management_hash)switch_core_hash_init_case(&loadable_modules.management_hash , SWITCH_FALSE); | |||
2164 | switch_core_hash_init_nocase(&loadable_modules.limit_hash)switch_core_hash_init_case(&loadable_modules.limit_hash, SWITCH_FALSE ); | |||
2165 | switch_core_hash_init_nocase(&loadable_modules.database_hash)switch_core_hash_init_case(&loadable_modules.database_hash , SWITCH_FALSE); | |||
2166 | switch_core_hash_init_nocase(&loadable_modules.dialplan_hash)switch_core_hash_init_case(&loadable_modules.dialplan_hash , SWITCH_FALSE); | |||
2167 | switch_core_hash_init(&loadable_modules.secondary_recover_hash)switch_core_hash_init_case(&loadable_modules.secondary_recover_hash , SWITCH_TRUE); | |||
2168 | switch_mutex_init(&loadable_modules.mutex, SWITCH_MUTEX_NESTED0x1, loadable_modules.pool); | |||
2169 | ||||
2170 | if (!autoload) return SWITCH_STATUS_SUCCESS; | |||
2171 | ||||
2172 | /* | |||
2173 | switch_core_sqldb_init() is not yet ready and is executed after starting modules from pre_load_modules.conf | |||
2174 | Modules loading procedure generates events used by sqldb. | |||
2175 | This is why we should hold those events (storing in the event_hash) not firing them until sqldb is ready. | |||
2176 | */ | |||
2177 | switch_core_hash_init(&event_hash)switch_core_hash_init_case(&event_hash, SWITCH_TRUE); | |||
2178 | ||||
2179 | /* | |||
2180 | Pre-load core modules. | |||
2181 | Do not pre-load modules which may use databases, | |||
2182 | use appropriate section. | |||
2183 | */ | |||
2184 | switch_loadable_module_load_module_ex("", "CORE_SOFTTIMER_MODULE", SWITCH_FALSE, SWITCH_FALSE, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash); | |||
2185 | switch_loadable_module_load_module_ex("", "CORE_PCM_MODULE", SWITCH_FALSE, SWITCH_FALSE, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash); | |||
2186 | switch_loadable_module_load_module_ex("", "CORE_SPEEX_MODULE", SWITCH_FALSE, SWITCH_FALSE, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash); | |||
2187 | ||||
2188 | /* | |||
2189 | Loading pre-load modules. | |||
2190 | Database modules must be loaded here. | |||
2191 | */ | |||
2192 | if ((xml = switch_xml_open_cfg(precf, &cfg, NULL((void*)0)))) { | |||
2193 | switch_xml_t mods, ld; | |||
2194 | if ((mods = switch_xml_child(cfg, "modules"))) { | |||
2195 | for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) { | |||
2196 | switch_bool_t global = SWITCH_FALSE; | |||
2197 | const char *val = switch_xml_attr_soft(ld, "module"); | |||
2198 | const char *path = switch_xml_attr_soft(ld, "path"); | |||
2199 | const char *critical = switch_xml_attr_soft(ld, "critical"); | |||
2200 | const char *sglobal = switch_xml_attr_soft(ld, "global"); | |||
2201 | ||||
2202 | if (zstr(val)_zstr(val) || (strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT))) { | |||
2203 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2203, ((void*)0), SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val); | |||
2204 | continue; | |||
2205 | } | |||
2206 | global = switch_true(sglobal); | |||
2207 | ||||
2208 | if (path && zstr(path)_zstr(path)) { | |||
2209 | path = SWITCH_GLOBAL_dirs.mod_dir; | |||
2210 | } | |||
2211 | if (switch_loadable_module_load_module_ex((char *)path, (char *)val, SWITCH_FALSE, global, &err, SWITCH_LOADABLE_MODULE_TYPE_PRELOAD, event_hash) == SWITCH_STATUS_GENERR) { | |||
2212 | if (critical && switch_true(critical)) { | |||
2213 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2213, ((void*)0), SWITCH_LOG_CRIT, "Failed to load critical module '%s', abort()\n", val); | |||
2214 | ||||
2215 | if ((hash_val = switch_core_hash_find(event_hash, "0"))) { | |||
2216 | switch_safe_free(hash_val)if (hash_val) {free(hash_val);hash_val=((void*)0);}; | |||
2217 | } | |||
2218 | switch_core_hash_destroy(&event_hash); | |||
2219 | ||||
2220 | abort(); | |||
2221 | } | |||
2222 | } | |||
2223 | count++; | |||
2224 | } | |||
2225 | } | |||
2226 | switch_xml_free(xml); | |||
2227 | ||||
2228 | } | |||
2229 | else { | |||
2230 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2230, ((void*)0), SWITCH_LOG_CONSOLE, "open of %s failed\n", precf); | |||
2231 | } | |||
2232 | ||||
2233 | if (switch_core_sqldb_init(&err) != SWITCH_STATUS_SUCCESS) | |||
2234 | { | |||
2235 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2235, ((void*)0), SWITCH_LOG_CRIT, "Loading modules interrupted. [Error: %s]\n", err); | |||
2236 | if ((hash_val = switch_core_hash_find(event_hash, "0"))) { | |||
2237 | switch_safe_free(hash_val)if (hash_val) {free(hash_val);hash_val=((void*)0);}; | |||
2238 | } | |||
2239 | switch_core_hash_destroy(&event_hash); | |||
2240 | return SWITCH_STATUS_GENERR; | |||
2241 | } | |||
2242 | ||||
2243 | /* sqldb is ready. Fire holding events! */ | |||
2244 | if ((hash_val = switch_core_hash_find(event_hash, "0"))) { | |||
2245 | switch_safe_free(hash_val)if (hash_val) {free(hash_val);hash_val=((void*)0);}; | |||
2246 | switch_core_hash_delete(event_hash, "0"); | |||
2247 | } | |||
2248 | ||||
2249 | for (hi = switch_core_hash_first(event_hash)switch_core_hash_first_iter(event_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
2250 | switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &hash_val); | |||
2251 | event = (switch_event_t *)hash_val; | |||
2252 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 2252, &event, ((void*)0) ); | |||
2253 | } | |||
2254 | ||||
2255 | switch_core_hash_destroy(&event_hash); | |||
2256 | ||||
2257 | /* | |||
2258 | To perevent locking. | |||
2259 | Core modules which may use databases should be pre-loaded here | |||
2260 | (databases are loaded already). | |||
2261 | */ | |||
2262 | #ifdef SWITCH_HAVE_YUV1 | |||
2263 | #ifdef SWITCH_HAVE_VPX1 | |||
2264 | switch_loadable_module_load_module("", "CORE_VPX_MODULE", SWITCH_FALSE, &err); | |||
2265 | #endif | |||
2266 | #endif | |||
2267 | ||||
2268 | /* Loading common modules */ | |||
2269 | if ((xml = switch_xml_open_cfg(cf, &cfg, NULL((void*)0)))) { | |||
2270 | switch_xml_t mods, ld; | |||
2271 | if ((mods = switch_xml_child(cfg, "modules"))) { | |||
2272 | for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) { | |||
2273 | switch_bool_t global = SWITCH_FALSE; | |||
2274 | const char *val = switch_xml_attr_soft(ld, "module"); | |||
2275 | const char *path = switch_xml_attr_soft(ld, "path"); | |||
2276 | const char *critical = switch_xml_attr_soft(ld, "critical"); | |||
2277 | const char *sglobal = switch_xml_attr_soft(ld, "global"); | |||
2278 | if (zstr(val)_zstr(val) || (strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT))) { | |||
2279 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2279, ((void*)0), SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val); | |||
2280 | continue; | |||
2281 | } | |||
2282 | global = switch_true(sglobal); | |||
2283 | ||||
2284 | if (path && zstr(path)_zstr(path)) { | |||
2285 | path = SWITCH_GLOBAL_dirs.mod_dir; | |||
2286 | } | |||
2287 | if (switch_loadable_module_load_module_ex(path, val, SWITCH_FALSE, global, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, NULL((void*)0)) == SWITCH_STATUS_GENERR) { | |||
2288 | if (critical && switch_true(critical)) { | |||
2289 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2289, ((void*)0), SWITCH_LOG_CRIT, "Failed to load critical module '%s', abort()\n", val); | |||
2290 | abort(); | |||
2291 | } | |||
2292 | } | |||
2293 | count++; | |||
2294 | } | |||
2295 | } | |||
2296 | switch_xml_free(xml); | |||
2297 | ||||
2298 | } else { | |||
2299 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2299, ((void*)0), SWITCH_LOG_CONSOLE, "open of %s failed\n", cf); | |||
2300 | } | |||
2301 | ||||
2302 | if ((xml = switch_xml_open_cfg(pcf, &cfg, NULL((void*)0)))) { | |||
2303 | switch_xml_t mods, ld; | |||
2304 | ||||
2305 | if ((mods = switch_xml_child(cfg, "modules"))) { | |||
2306 | for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) { | |||
2307 | switch_bool_t global = SWITCH_FALSE; | |||
2308 | const char *val = switch_xml_attr_soft(ld, "module"); | |||
2309 | const char *path = switch_xml_attr_soft(ld, "path"); | |||
2310 | const char *sglobal = switch_xml_attr_soft(ld, "global"); | |||
2311 | if (zstr(val)_zstr(val) || (strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT))) { | |||
2312 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2312, ((void*)0), SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val); | |||
2313 | continue; | |||
2314 | } | |||
2315 | global = switch_true(sglobal); | |||
2316 | ||||
2317 | if (path && zstr(path)_zstr(path)) { | |||
2318 | path = SWITCH_GLOBAL_dirs.mod_dir; | |||
2319 | } | |||
2320 | switch_loadable_module_load_module_ex(path, val, SWITCH_FALSE, global, &err, SWITCH_LOADABLE_MODULE_TYPE_POSTLOAD, NULL((void*)0)); | |||
2321 | count++; | |||
2322 | } | |||
2323 | } | |||
2324 | switch_xml_free(xml); | |||
2325 | ||||
2326 | } else { | |||
2327 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2327, ((void*)0), SWITCH_LOG_CONSOLE, "open of %s failed\n", pcf); | |||
2328 | } | |||
2329 | ||||
2330 | if (!count) { | |||
2331 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2331, ((void*)0), SWITCH_LOG_CONSOLE, "No modules loaded, assuming 'load all'\n"); | |||
2332 | all = 1; | |||
2333 | } | |||
2334 | ||||
2335 | if (all) { | |||
2336 | if (apr_dir_open(&module_dir_handle, SWITCH_GLOBAL_dirs.mod_dir, loadable_modules.pool) != APR_SUCCESS0) { | |||
2337 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2337, ((void*)0), SWITCH_LOG_CONSOLE, "Can't open directory: %s\n", SWITCH_GLOBAL_dirs.mod_dir); | |||
2338 | return SWITCH_STATUS_GENERR; | |||
2339 | } | |||
2340 | ||||
2341 | while (apr_dir_read(&finfo, finfo_flags, module_dir_handle) == APR_SUCCESS0) { | |||
2342 | const char *fname = finfo.fname; | |||
2343 | ||||
2344 | if (finfo.filetype != APR_REG) { | |||
2345 | continue; | |||
2346 | } | |||
2347 | ||||
2348 | if (!fname) { | |||
2349 | fname = finfo.name; | |||
2350 | } | |||
2351 | ||||
2352 | if (!fname) { | |||
2353 | continue; | |||
2354 | } | |||
2355 | ||||
2356 | if (zstr(fname)_zstr(fname) || (!strstr(fname, ext) && !strstr(fname, EXT))) { | |||
2357 | continue; | |||
2358 | } | |||
2359 | ||||
2360 | switch_loadable_module_load_module(SWITCH_GLOBAL_dirs.mod_dir, fname, SWITCH_FALSE, &err); | |||
2361 | } | |||
2362 | apr_dir_close(module_dir_handle); | |||
2363 | } | |||
2364 | ||||
2365 | switch_loadable_module_runtime(); | |||
2366 | ||||
2367 | memset(&chat_globals, 0, sizeof(chat_globals)); | |||
2368 | chat_globals.running = 1; | |||
2369 | chat_globals.pool = loadable_modules.pool; | |||
2370 | switch_mutex_init(&chat_globals.mutex, SWITCH_MUTEX_NESTED0x1, chat_globals.pool); | |||
2371 | ||||
2372 | chat_thread_start(1); | |||
2373 | ||||
2374 | return SWITCH_STATUS_SUCCESS; | |||
2375 | } | |||
2376 | ||||
2377 | 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, | |||
2378 | const char **err) | |||
2379 | { | |||
2380 | int32_t flags = switch_core_flags(); | |||
2381 | switch_assert(module != NULL)((module != ((void*)0)) ? (void) (0) : __assert_fail ("module != ((void*)0)" , "src/switch_loadable_module.c", 2381, __extension__ __PRETTY_FUNCTION__ )); | |||
2382 | ||||
2383 | if (fail_if_busy && module->module_interface->rwlock && switch_thread_rwlock_trywrlock(module->module_interface->rwlock) != SWITCH_STATUS_SUCCESS) { | |||
2384 | if (err) { | |||
2385 | *err = "Module in use."; | |||
2386 | } | |||
2387 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2387, ((void*)0), SWITCH_LOG_WARNING, "Module %s is in use, cannot unload.\n", module->module_interface->module_name); | |||
2388 | return SWITCH_STATUS_FALSE; | |||
2389 | } | |||
2390 | ||||
2391 | module->shutting_down = SWITCH_TRUE; | |||
2392 | ||||
2393 | if (shutdown) { | |||
2394 | switch_loadable_module_unprocess(module); | |||
2395 | if (module->switch_module_shutdown) { | |||
2396 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2396, ((void*)0), SWITCH_LOG_CONSOLE, "Stopping: %s\n", module->module_interface->module_name); | |||
2397 | module->status = module->switch_module_shutdown(); | |||
2398 | } else { | |||
2399 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2399, ((void*)0), SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name); | |||
2400 | } | |||
2401 | } | |||
2402 | ||||
2403 | if (fail_if_busy && module->module_interface->rwlock) { | |||
2404 | switch_thread_rwlock_unlock(module->module_interface->rwlock); | |||
2405 | } | |||
2406 | ||||
2407 | if (unload && module->status != SWITCH_STATUS_NOUNLOAD && !(flags & SCF_VG)) { | |||
2408 | switch_memory_pool_t *pool; | |||
2409 | switch_status_t st; | |||
2410 | ||||
2411 | if (module->thread) { | |||
2412 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2412, ((void*)0), SWITCH_LOG_CONSOLE, "%s stopping runtime thread.\n", module->module_interface->module_name); | |||
2413 | switch_thread_join(&st, module->thread); | |||
2414 | } | |||
2415 | ||||
2416 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2416, ((void*)0), SWITCH_LOG_CONSOLE, "%s unloaded.\n", module->module_interface->module_name); | |||
2417 | switch_dso_destroy(&module->lib); | |||
2418 | if ((pool = module->pool)) { | |||
2419 | module = NULL((void*)0); | |||
2420 | switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_loadable_module.c" , (const char *)__func__, 2420); | |||
2421 | } | |||
2422 | } | |||
2423 | ||||
2424 | return SWITCH_STATUS_SUCCESS; | |||
2425 | ||||
2426 | } | |||
2427 | ||||
2428 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_loadable_module_shutdown(void) | |||
2429 | { | |||
2430 | switch_hash_index_t *hi; | |||
2431 | void *val; | |||
2432 | const void *key; | |||
2433 | switch_loadable_module_t *module; | |||
2434 | int i; | |||
2435 | ||||
2436 | if (!loadable_modules.module_hash) { | |||
2437 | return; | |||
2438 | } | |||
2439 | ||||
2440 | chat_globals.running = 0; | |||
2441 | ||||
2442 | for (i = 0; i < chat_globals.msg_queue_len; i++) { | |||
2443 | switch_queue_push(chat_globals.msg_queue[i], NULL((void*)0)); | |||
2444 | } | |||
2445 | ||||
2446 | for (i = 0; i < chat_globals.msg_queue_len; i++) { | |||
2447 | switch_status_t st; | |||
2448 | switch_thread_join(&st, chat_globals.msg_queue_thread[i]); | |||
2449 | } | |||
2450 | ||||
2451 | ||||
2452 | for (hi = switch_core_hash_first(loadable_modules.module_hash)switch_core_hash_first_iter(loadable_modules.module_hash, ((void *)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
2453 | switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val); | |||
2454 | module = (switch_loadable_module_t *)val; | |||
2455 | if (module->type != SWITCH_LOADABLE_MODULE_TYPE_PRELOAD && !module->perm) { | |||
2456 | do_shutdown(module, SWITCH_TRUE, SWITCH_FALSE, SWITCH_FALSE, NULL((void*)0)); | |||
2457 | } | |||
2458 | } | |||
2459 | ||||
2460 | switch_yield(1000000)switch_sleep(1000000);; | |||
2461 | ||||
2462 | for (hi = switch_core_hash_first(loadable_modules.module_hash)switch_core_hash_first_iter(loadable_modules.module_hash, ((void *)0)); hi;) { | |||
2463 | switch_core_hash_this(hi, &key, NULL((void*)0), &val); | |||
2464 | module = (switch_loadable_module_t *)val; | |||
2465 | ||||
2466 | hi = switch_core_hash_next(&hi); | |||
2467 | ||||
2468 | if (module->type != SWITCH_LOADABLE_MODULE_TYPE_PRELOAD && !module->perm) { | |||
2469 | if (do_shutdown(module, SWITCH_FALSE, SWITCH_TRUE, SWITCH_FALSE, NULL((void*)0)) == SWITCH_STATUS_SUCCESS) | |||
2470 | { | |||
2471 | switch_core_hash_delete(loadable_modules.module_hash, key); | |||
2472 | } | |||
2473 | } | |||
2474 | } | |||
2475 | ||||
2476 | switch_core_sqldb_destroy(); | |||
2477 | ||||
2478 | for (hi = switch_core_hash_first(loadable_modules.module_hash)switch_core_hash_first_iter(loadable_modules.module_hash, ((void *)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
2479 | switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val); | |||
2480 | if ((module = (switch_loadable_module_t *)val)) { | |||
2481 | if (module->type == SWITCH_LOADABLE_MODULE_TYPE_PRELOAD && !module->perm) { | |||
2482 | do_shutdown(module, SWITCH_TRUE, SWITCH_FALSE, SWITCH_FALSE, NULL((void*)0)); | |||
2483 | } | |||
2484 | } | |||
2485 | } | |||
2486 | ||||
2487 | switch_yield(1000000)switch_sleep(1000000);; | |||
2488 | ||||
2489 | for (hi = switch_core_hash_first(loadable_modules.module_hash)switch_core_hash_first_iter(loadable_modules.module_hash, ((void *)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
2490 | switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val); | |||
2491 | if ((module = (switch_loadable_module_t *)val)) { | |||
2492 | if (module->type == SWITCH_LOADABLE_MODULE_TYPE_PRELOAD && !module->perm) { | |||
2493 | do_shutdown(module, SWITCH_FALSE, SWITCH_TRUE, SWITCH_FALSE, NULL((void*)0)); | |||
2494 | } | |||
2495 | } | |||
2496 | } | |||
2497 | ||||
2498 | switch_core_hash_destroy(&loadable_modules.module_hash); | |||
2499 | switch_core_hash_destroy(&loadable_modules.endpoint_hash); | |||
2500 | switch_core_hash_destroy(&loadable_modules.codec_hash); | |||
2501 | switch_core_hash_destroy(&loadable_modules.timer_hash); | |||
2502 | switch_core_hash_destroy(&loadable_modules.application_hash); | |||
2503 | switch_core_hash_destroy(&loadable_modules.chat_application_hash); | |||
2504 | switch_core_hash_destroy(&loadable_modules.api_hash); | |||
2505 | switch_core_hash_destroy(&loadable_modules.json_api_hash); | |||
2506 | switch_core_hash_destroy(&loadable_modules.file_hash); | |||
2507 | switch_core_hash_destroy(&loadable_modules.speech_hash); | |||
2508 | switch_core_hash_destroy(&loadable_modules.asr_hash); | |||
2509 | switch_core_hash_destroy(&loadable_modules.directory_hash); | |||
2510 | switch_core_hash_destroy(&loadable_modules.chat_hash); | |||
2511 | switch_core_hash_destroy(&loadable_modules.say_hash); | |||
2512 | switch_core_hash_destroy(&loadable_modules.management_hash); | |||
2513 | switch_core_hash_destroy(&loadable_modules.limit_hash); | |||
2514 | switch_core_hash_destroy(&loadable_modules.database_hash); | |||
2515 | switch_core_hash_destroy(&loadable_modules.dialplan_hash); | |||
2516 | switch_core_hash_destroy(&loadable_modules.secondary_recover_hash); | |||
2517 | ||||
2518 | switch_core_destroy_memory_pool(&loadable_modules.pool)switch_core_perform_destroy_memory_pool(&loadable_modules .pool, "src/switch_loadable_module.c", (const char *)__func__ , 2518); | |||
2519 | } | |||
2520 | ||||
2521 | SWITCH_DECLARE(switch_endpoint_interface_t *)__attribute__((visibility("default"))) switch_endpoint_interface_t * switch_loadable_module_get_endpoint_interface(const char *name) | |||
2522 | { | |||
2523 | switch_endpoint_interface_t *ptr; | |||
2524 | ||||
2525 | switch_mutex_lock(loadable_modules.mutex); | |||
2526 | ptr = switch_core_hash_find(loadable_modules.endpoint_hash, name); | |||
2527 | PROTECT_INTERFACE(ptr)if (ptr) {switch_thread_rwlock_rdlock(ptr->parent->rwlock ); switch_thread_rwlock_rdlock(ptr->rwlock); switch_mutex_lock (ptr->reflock); ptr->refs++; ptr->parent->refs++; switch_mutex_unlock(ptr->reflock);}; | |||
2528 | switch_mutex_unlock(loadable_modules.mutex); | |||
2529 | ||||
2530 | ||||
2531 | return ptr; | |||
2532 | } | |||
2533 | ||||
2534 | SWITCH_DECLARE(switch_file_interface_t *)__attribute__((visibility("default"))) switch_file_interface_t * switch_loadable_module_get_file_interface(const char *name, const char *modname) | |||
2535 | { | |||
2536 | switch_file_interface_t *i = NULL((void*)0); | |||
2537 | switch_file_node_t *node, *head; | |||
2538 | ||||
2539 | switch_mutex_lock(loadable_modules.mutex); | |||
2540 | ||||
2541 | if ((head = switch_core_hash_find(loadable_modules.file_hash, name))) { | |||
2542 | if (modname) { | |||
2543 | for (node = head; node; node = node->next) { | |||
2544 | if (!strcasecmp(node->interface_name, modname)) { | |||
2545 | i = (switch_file_interface_t *) node->ptr; | |||
2546 | break; | |||
2547 | } | |||
2548 | } | |||
2549 | } else { | |||
2550 | i = (switch_file_interface_t *) head->ptr; | |||
2551 | } | |||
2552 | } | |||
2553 | ||||
2554 | switch_mutex_unlock(loadable_modules.mutex); | |||
2555 | ||||
2556 | if (i) PROTECT_INTERFACE(i)if (i) {switch_thread_rwlock_rdlock(i->parent->rwlock); switch_thread_rwlock_rdlock(i->rwlock); switch_mutex_lock (i->reflock); i->refs++; i->parent->refs++; switch_mutex_unlock (i->reflock);}; | |||
2557 | ||||
2558 | return i; | |||
2559 | } | |||
2560 | ||||
2561 | SWITCH_DECLARE(switch_database_interface_t *)__attribute__((visibility("default"))) switch_database_interface_t * switch_loadable_module_get_database_interface(const char *name, const char *modname) | |||
2562 | { | |||
2563 | switch_database_interface_t *i = NULL((void*)0); | |||
2564 | switch_database_node_t *node, *head; | |||
2565 | ||||
2566 | switch_mutex_lock(loadable_modules.mutex); | |||
2567 | ||||
2568 | if ((head = switch_core_hash_find(loadable_modules.database_hash, name))) { | |||
2569 | if (modname) { | |||
2570 | for (node = head; node; node = node->next) { | |||
2571 | if (!strcasecmp(node->interface_name, modname)) { | |||
2572 | i = (switch_database_interface_t *)node->ptr; | |||
2573 | break; | |||
2574 | } | |||
2575 | } | |||
2576 | } | |||
2577 | else { | |||
2578 | i = (switch_database_interface_t *)head->ptr; | |||
2579 | } | |||
2580 | } | |||
2581 | ||||
2582 | switch_mutex_unlock(loadable_modules.mutex); | |||
2583 | ||||
2584 | if (i) PROTECT_INTERFACE(i)if (i) {switch_thread_rwlock_rdlock(i->parent->rwlock); switch_thread_rwlock_rdlock(i->rwlock); switch_mutex_lock (i->reflock); i->refs++; i->parent->refs++; switch_mutex_unlock (i->reflock);}; | |||
2585 | ||||
2586 | return i; | |||
2587 | } | |||
2588 | ||||
2589 | SWITCH_DECLARE(switch_codec_interface_t *)__attribute__((visibility("default"))) switch_codec_interface_t * switch_loadable_module_get_codec_interface(const char *name, const char *modname) | |||
2590 | { | |||
2591 | switch_codec_interface_t *codec = NULL((void*)0); | |||
2592 | switch_codec_node_t *node, *head; | |||
2593 | ||||
2594 | switch_mutex_lock(loadable_modules.mutex); | |||
2595 | ||||
2596 | if ((head = switch_core_hash_find(loadable_modules.codec_hash, name))) { | |||
2597 | if (modname) { | |||
2598 | for (node = head; node; node = node->next) { | |||
2599 | if (!strcasecmp(node->interface_name, modname)) { | |||
2600 | codec = (switch_codec_interface_t *) node->ptr; | |||
2601 | break; | |||
2602 | } | |||
2603 | } | |||
2604 | } else { | |||
2605 | codec = (switch_codec_interface_t *) head->ptr; | |||
2606 | } | |||
2607 | } | |||
2608 | ||||
2609 | switch_mutex_unlock(loadable_modules.mutex); | |||
2610 | ||||
2611 | PROTECT_INTERFACE(codec)if (codec) {switch_thread_rwlock_rdlock(codec->parent-> rwlock); switch_thread_rwlock_rdlock(codec->rwlock); switch_mutex_lock (codec->reflock); codec->refs++; codec->parent->refs ++; switch_mutex_unlock(codec->reflock);}; | |||
2612 | ||||
2613 | return codec; | |||
2614 | } | |||
2615 | ||||
2616 | #define HASH_FUNC(_kind_)__attribute__((visibility("default"))) switch__kind__interface_t * switch_loadable_module_get__kind__interface(const char *name ) { switch__kind__interface_t *i = ((void*)0); if (loadable_modules ._kind__hash && (i = switch_core_hash_find_locked(loadable_modules ._kind__hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } SWITCH_DECLARE(switch_##_kind_##_interface_t *)__attribute__((visibility("default"))) switch_##_kind_##_interface_t * switch_loadable_module_get_##_kind_##_interface(const char *name) \ | |||
2617 | { \ | |||
2618 | switch_##_kind_##_interface_t *i = NULL((void*)0); \ | |||
2619 | if (loadable_modules._kind_##_hash && (i = switch_core_hash_find_locked(loadable_modules._kind_##_hash, name, loadable_modules.mutex))) { \ | |||
2620 | PROTECT_INTERFACE(i)if (i) {switch_thread_rwlock_rdlock(i->parent->rwlock); switch_thread_rwlock_rdlock(i->rwlock); switch_mutex_lock (i->reflock); i->refs++; i->parent->refs++; switch_mutex_unlock (i->reflock);}; \ | |||
2621 | } \ | |||
2622 | return i; \ | |||
2623 | } | |||
2624 | ||||
2625 | HASH_FUNC(dialplan)__attribute__((visibility("default"))) switch_dialplan_interface_t * switch_loadable_module_get_dialplan_interface(const char * name) { switch_dialplan_interface_t *i = ((void*)0); if (loadable_modules .dialplan_hash && (i = switch_core_hash_find_locked(loadable_modules .dialplan_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2626 | HASH_FUNC(timer)__attribute__((visibility("default"))) switch_timer_interface_t * switch_loadable_module_get_timer_interface(const char *name ) { switch_timer_interface_t *i = ((void*)0); if (loadable_modules .timer_hash && (i = switch_core_hash_find_locked(loadable_modules .timer_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2627 | HASH_FUNC(application)__attribute__((visibility("default"))) switch_application_interface_t * switch_loadable_module_get_application_interface(const char *name) { switch_application_interface_t *i = ((void*)0); if ( loadable_modules.application_hash && (i = switch_core_hash_find_locked (loadable_modules.application_hash, name, loadable_modules.mutex ))) { if (i) {switch_thread_rwlock_rdlock(i->parent->rwlock ); switch_thread_rwlock_rdlock(i->rwlock); switch_mutex_lock (i->reflock); i->refs++; i->parent->refs++; switch_mutex_unlock (i->reflock);}; } return i; } | |||
2628 | HASH_FUNC(chat_application)__attribute__((visibility("default"))) switch_chat_application_interface_t * switch_loadable_module_get_chat_application_interface(const char *name) { switch_chat_application_interface_t *i = ((void *)0); if (loadable_modules.chat_application_hash && ( i = switch_core_hash_find_locked(loadable_modules.chat_application_hash , name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2629 | HASH_FUNC(api)__attribute__((visibility("default"))) switch_api_interface_t * switch_loadable_module_get_api_interface(const char *name) { switch_api_interface_t *i = ((void*)0); if (loadable_modules .api_hash && (i = switch_core_hash_find_locked(loadable_modules .api_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2630 | HASH_FUNC(json_api)__attribute__((visibility("default"))) switch_json_api_interface_t * switch_loadable_module_get_json_api_interface(const char * name) { switch_json_api_interface_t *i = ((void*)0); if (loadable_modules .json_api_hash && (i = switch_core_hash_find_locked(loadable_modules .json_api_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2631 | HASH_FUNC(speech)__attribute__((visibility("default"))) switch_speech_interface_t * switch_loadable_module_get_speech_interface(const char *name ) { switch_speech_interface_t *i = ((void*)0); if (loadable_modules .speech_hash && (i = switch_core_hash_find_locked(loadable_modules .speech_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2632 | HASH_FUNC(asr)__attribute__((visibility("default"))) switch_asr_interface_t * switch_loadable_module_get_asr_interface(const char *name) { switch_asr_interface_t *i = ((void*)0); if (loadable_modules .asr_hash && (i = switch_core_hash_find_locked(loadable_modules .asr_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2633 | HASH_FUNC(directory)__attribute__((visibility("default"))) switch_directory_interface_t * switch_loadable_module_get_directory_interface(const char * name) { switch_directory_interface_t *i = ((void*)0); if (loadable_modules .directory_hash && (i = switch_core_hash_find_locked( loadable_modules.directory_hash, name, loadable_modules.mutex ))) { if (i) {switch_thread_rwlock_rdlock(i->parent->rwlock ); switch_thread_rwlock_rdlock(i->rwlock); switch_mutex_lock (i->reflock); i->refs++; i->parent->refs++; switch_mutex_unlock (i->reflock);}; } return i; } | |||
2634 | HASH_FUNC(chat)__attribute__((visibility("default"))) switch_chat_interface_t * switch_loadable_module_get_chat_interface(const char *name ) { switch_chat_interface_t *i = ((void*)0); if (loadable_modules .chat_hash && (i = switch_core_hash_find_locked(loadable_modules .chat_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2635 | HASH_FUNC(limit)__attribute__((visibility("default"))) switch_limit_interface_t * switch_loadable_module_get_limit_interface(const char *name ) { switch_limit_interface_t *i = ((void*)0); if (loadable_modules .limit_hash && (i = switch_core_hash_find_locked(loadable_modules .limit_hash, name, loadable_modules.mutex))) { if (i) {switch_thread_rwlock_rdlock (i->parent->rwlock); switch_thread_rwlock_rdlock(i-> rwlock); switch_mutex_lock(i->reflock); i->refs++; i-> parent->refs++; switch_mutex_unlock(i->reflock);}; } return i; } | |||
2636 | ||||
2637 | ||||
2638 | SWITCH_DECLARE(switch_say_interface_t *)__attribute__((visibility("default"))) switch_say_interface_t * switch_loadable_module_get_say_interface(const char *name) | |||
2639 | { | |||
2640 | return switch_core_hash_find_locked(loadable_modules.say_hash, name, loadable_modules.mutex); | |||
2641 | } | |||
2642 | ||||
2643 | SWITCH_DECLARE(switch_management_interface_t *)__attribute__((visibility("default"))) switch_management_interface_t * switch_loadable_module_get_management_interface(const char *relative_oid) | |||
2644 | { | |||
2645 | return switch_core_hash_find_locked(loadable_modules.management_hash, relative_oid, loadable_modules.mutex); | |||
2646 | } | |||
2647 | ||||
2648 | #ifdef DEBUG_CODEC_SORTING | |||
2649 | static void do_print(const switch_codec_implementation_t **array, int arraylen) | |||
2650 | { | |||
2651 | int i; | |||
2652 | ||||
2653 | for(i = 0; i < arraylen; i++) { | |||
2654 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2654, ((void*)0), SWITCH_LOG_ERROR, | |||
2655 | "DEBUG %d %s:%d %d\n", i, array[i]->iananame, array[i]->ianacode, array[i]->microseconds_per_packet / 1000); | |||
2656 | } | |||
2657 | ||||
2658 | } | |||
2659 | #endif | |||
2660 | ||||
2661 | /* helper only -- bounds checking enforced by caller */ | |||
2662 | static void do_swap(const switch_codec_implementation_t **array, int a, int b) | |||
2663 | { | |||
2664 | const switch_codec_implementation_t *tmp = array[b]; | |||
2665 | array[b] = array[a]; | |||
2666 | array[a] = tmp; | |||
2667 | } | |||
2668 | ||||
2669 | static void switch_loadable_module_sort_codecs(const switch_codec_implementation_t **array, int arraylen) | |||
2670 | { | |||
2671 | int i = 0, sorted_ptime = 0; | |||
2672 | ||||
2673 | #ifdef DEBUG_CODEC_SORTING | |||
2674 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2674, ((void*)0), SWITCH_LOG_ERROR, "--BEFORE\n"); | |||
2675 | do_print(array, arraylen); | |||
2676 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2676, ((void*)0), SWITCH_LOG_ERROR, "--BEFORE\n"); | |||
2677 | #endif | |||
2678 | ||||
2679 | for (i = 0; i < arraylen; i++) { | |||
2680 | int this_ptime; | |||
2681 | ||||
2682 | if (!array[i]) { | |||
2683 | continue; | |||
2684 | } | |||
2685 | ||||
2686 | this_ptime = array[i]->microseconds_per_packet / 1000; | |||
2687 | ||||
2688 | if (!strcasecmp(array[i]->iananame, "ilbc")) { | |||
2689 | this_ptime = 20; | |||
2690 | } | |||
2691 | ||||
2692 | if (!sorted_ptime) { | |||
2693 | sorted_ptime = this_ptime; | |||
2694 | #ifdef DEBUG_CODEC_SORTING | |||
2695 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2695, ((void*)0), SWITCH_LOG_ERROR, "sorted1 = %d\n", sorted_ptime); | |||
2696 | #endif | |||
2697 | } | |||
2698 | ||||
2699 | if (i > 0 && array[i-1] && strcasecmp(array[i]->iananame, array[i-1]->iananame) && this_ptime != sorted_ptime) { | |||
2700 | int j; | |||
2701 | int swapped = 0; | |||
2702 | ||||
2703 | #ifdef DEBUG_CODEC_SORTING | |||
2704 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2704, ((void*)0), SWITCH_LOG_ERROR, "%d != %d\n", this_ptime, sorted_ptime); | |||
2705 | #endif | |||
2706 | for(j = i; j < arraylen; j++) { | |||
2707 | int check_ptime = array[j]->microseconds_per_packet / 1000; | |||
2708 | ||||
2709 | if (!strcasecmp(array[i]->iananame, "ilbc")) { | |||
2710 | check_ptime = 20; | |||
2711 | } | |||
2712 | ||||
2713 | if (check_ptime == sorted_ptime) { | |||
2714 | #ifdef DEBUG_CODEC_SORTING | |||
2715 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2715, ((void*)0), SWITCH_LOG_ERROR, "swap %d %d ptime %d\n", i, j, check_ptime); | |||
2716 | #endif | |||
2717 | do_swap(array, i, j); | |||
2718 | swapped = 1; | |||
2719 | break; | |||
2720 | } | |||
2721 | } | |||
2722 | ||||
2723 | if (!swapped) { | |||
2724 | sorted_ptime = this_ptime; | |||
2725 | #ifdef DEBUG_CODEC_SORTING | |||
2726 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2726, ((void*)0), SWITCH_LOG_ERROR, "sorted2 = %d\n", sorted_ptime); | |||
2727 | #endif | |||
2728 | } | |||
2729 | } | |||
2730 | } | |||
2731 | ||||
2732 | #ifdef DEBUG_CODEC_SORTING | |||
2733 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2733, ((void*)0), SWITCH_LOG_ERROR, "--AFTER\n"); | |||
2734 | do_print(array, arraylen); | |||
2735 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2735, ((void*)0), SWITCH_LOG_ERROR, "--AFTER\n"); | |||
2736 | #endif | |||
2737 | ||||
2738 | } | |||
2739 | ||||
2740 | ||||
2741 | SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_loadable_module_get_codecs(const switch_codec_implementation_t **array, int arraylen) | |||
2742 | { | |||
2743 | switch_hash_index_t *hi; | |||
2744 | void *val; | |||
2745 | switch_codec_interface_t *codec_interface; | |||
2746 | int i = 0; | |||
2747 | const switch_codec_implementation_t *imp; | |||
2748 | switch_codec_node_t *node, *head; | |||
2749 | ||||
2750 | switch_mutex_lock(loadable_modules.mutex); | |||
2751 | for (hi = switch_core_hash_first(loadable_modules.codec_hash)switch_core_hash_first_iter(loadable_modules.codec_hash, ((void *)0)); hi; hi = switch_core_hash_next(&hi)) { | |||
2752 | switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val); | |||
2753 | head = (switch_codec_node_t *) val; | |||
2754 | ||||
2755 | for (node = head; node; node = node->next) { | |||
2756 | codec_interface = (switch_codec_interface_t *) node->ptr; | |||
2757 | ||||
2758 | /* Look for the default ptime of the codec because it's the safest choice */ | |||
2759 | for (imp = codec_interface->implementations; imp; imp = imp->next) { | |||
2760 | uint32_t default_ptime = switch_default_ptime(imp->iananame, imp->ianacode); | |||
2761 | ||||
2762 | if (imp->microseconds_per_packet / 1000 == (int)default_ptime) { | |||
2763 | array[i++] = imp; | |||
2764 | goto found; | |||
2765 | } | |||
2766 | } | |||
2767 | /* oh well we will use what we have */ | |||
2768 | array[i++] = codec_interface->implementations; | |||
2769 | } | |||
2770 | ||||
2771 | found: | |||
2772 | ||||
2773 | if (i > arraylen) { | |||
2774 | break; | |||
2775 | } | |||
2776 | ||||
2777 | } | |||
2778 | switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);}; | |||
2779 | ||||
2780 | switch_mutex_unlock(loadable_modules.mutex); | |||
2781 | ||||
2782 | switch_loadable_module_sort_codecs(array, i); | |||
2783 | ||||
2784 | return i; | |||
2785 | ||||
2786 | } | |||
2787 | ||||
2788 | SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit, uint32_t *channels, char **modname, char **fmtp) | |||
2789 | { | |||
2790 | char *cur, *next = NULL((void*)0), *name, *p; | |||
2791 | ||||
2792 | name = next = cur = buf; | |||
2793 | ||||
2794 | *channels = 1; | |||
2795 | ||||
2796 | for (;;) { | |||
2797 | if (!next) { | |||
2798 | break; | |||
2799 | } | |||
2800 | ||||
2801 | if ((p = strchr(next, '@'))) { | |||
2802 | *p++ = '\0'; | |||
2803 | } | |||
2804 | next = p; | |||
2805 | ||||
2806 | if (cur != name) { | |||
2807 | if (strchr(cur, 'i')) { | |||
2808 | *interval = atoi(cur); | |||
2809 | } else if ((strchr(cur, 'k') || strchr(cur, 'h'))) { | |||
2810 | *rate = atoi(cur); | |||
2811 | } else if (strchr(cur, 'b')) { | |||
2812 | *bit = atoi(cur); | |||
2813 | } else if (strchr(cur, 'c')) { | |||
2814 | *channels = atoi(cur); | |||
2815 | } else { | |||
2816 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 2816, ((void*)0), SWITCH_LOG_ERROR, "Bad syntax for codec string. Missing qualifier [h|k|i|b|c] for part [%s]!\n", cur); | |||
2817 | } | |||
2818 | } | |||
2819 | cur = next; | |||
2820 | } | |||
2821 | ||||
2822 | if ((p = strchr(name, '.'))) { | |||
2823 | *p++ = '\0'; | |||
2824 | *modname = name; | |||
2825 | name = p; | |||
2826 | } | |||
2827 | ||||
2828 | if ((p = strchr(name, '~'))) { | |||
2829 | *p++ = '\0'; | |||
2830 | if (fmtp) { | |||
2831 | *fmtp = p; | |||
2832 | } | |||
2833 | } | |||
2834 | ||||
2835 | return name; | |||
2836 | } | |||
2837 | ||||
2838 | SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array, char fmtp_array[SWITCH_MAX_CODECS50][MAX_FMTP_LEN256], int arraylen, char **prefs, int preflen) | |||
2839 | { | |||
2840 | int x, i = 0, j = 0; | |||
2841 | switch_codec_interface_t *codec_interface; | |||
2842 | const switch_codec_implementation_t *imp; | |||
2843 | ||||
2844 | switch_mutex_lock(loadable_modules.mutex); | |||
2845 | ||||
2846 | for (x = 0; x < preflen; x++) { | |||
2847 | char *name, buf[256], jbuf[256], *modname = NULL((void*)0), *fmtp = NULL((void*)0); | |||
2848 | uint32_t interval = 0, rate = 0, bit = 0, channels = 1; | |||
2849 | ||||
2850 | switch_copy_string(buf, prefs[x], sizeof(buf)); | |||
2851 | name = switch_parse_codec_buf(buf, &interval, &rate, &bit, &channels, &modname, &fmtp); | |||
2852 | ||||
2853 | for(j = 0; j < x; j++) { | |||
2854 | char *jname, *jmodname = NULL((void*)0), *jfmtp = NULL((void*)0); | |||
2855 | uint32_t jinterval = 0, jrate = 0, jbit = 0, jchannels = 1; | |||
2856 | uint32_t ointerval = interval, orate = rate, ochannels = channels; | |||
2857 | ||||
2858 | if (ointerval == 0) { | |||
2859 | ointerval = switch_default_ptime(name, 0); | |||
2860 | } | |||
2861 | ||||
2862 | if (orate == 0) { | |||
2863 | orate = switch_default_rate(name, 0); | |||
2864 | } | |||
2865 | ||||
2866 | if (ochannels == 0) { | |||
2867 | ochannels = 1; | |||
2868 | } | |||
2869 | ||||
2870 | switch_copy_string(jbuf, prefs[j], sizeof(jbuf)); | |||
2871 | jname = switch_parse_codec_buf(jbuf, &jinterval, &jrate, &jbit, &jchannels, &jmodname, &jfmtp); | |||
2872 | ||||
2873 | if (jinterval == 0) { | |||
2874 | jinterval = switch_default_ptime(jname, 0); | |||
2875 | } | |||
2876 | ||||
2877 | if (jrate == 0) { | |||
2878 | jrate = switch_default_rate(jname, 0); | |||
2879 | } | |||
2880 | ||||
2881 | if (jchannels == 0) { | |||
2882 | jchannels = 1; | |||
2883 | } | |||
2884 | ||||
2885 | if (!strcasecmp(name, jname) && ointerval == jinterval && orate == jrate && ochannels == jchannels && | |||
2886 | !strcasecmp(switch_str_nil(fmtp)(fmtp ? fmtp : ""), switch_str_nil(jfmtp)(jfmtp ? jfmtp : ""))) { | |||
2887 | goto next_x; | |||
2888 | } | |||
2889 | } | |||
2890 | ||||
2891 | if ((codec_interface = switch_loadable_module_get_codec_interface(name, modname)) != 0) { | |||
2892 | /* If no specific codec interval is requested opt for the default above all else because lots of stuff assumes it */ | |||
2893 | for (imp = codec_interface->implementations; imp; imp = imp->next) { | |||
2894 | uint32_t default_ptime = switch_default_ptime(imp->iananame, imp->ianacode); | |||
2895 | uint32_t default_rate = switch_default_rate(imp->iananame, imp->ianacode); | |||
2896 | ||||
2897 | if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { | |||
2898 | uint32_t crate = !strcasecmp(imp->iananame, "g722") ? imp->samples_per_second : imp->actual_samples_per_second; | |||
2899 | ||||
2900 | if ((!interval && (uint32_t) (imp->microseconds_per_packet / 1000) != default_ptime) || | |||
2901 | (interval && (uint32_t) (imp->microseconds_per_packet / 1000) != interval)) { | |||
2902 | continue; | |||
2903 | } | |||
2904 | ||||
2905 | if (((!rate && crate != default_rate) || (rate && (uint32_t) imp->actual_samples_per_second != rate))) { | |||
2906 | continue; | |||
2907 | } | |||
2908 | ||||
2909 | if (bit && (uint32_t) imp->bits_per_second != bit) { | |||
2910 | continue; | |||
2911 | } | |||
2912 | ||||
2913 | if (channels && imp->number_of_channels != channels) { | |||
2914 | continue; | |||
2915 | } | |||
2916 | } | |||
2917 | ||||
2918 | if (!zstr(fmtp)_zstr(fmtp)) { | |||
2919 | switch_set_string(fmtp_array[i], fmtp)switch_copy_string(fmtp_array[i], fmtp, sizeof(fmtp_array[i]) ); | |||
2920 | } | |||
2921 | array[i++] = imp; | |||
2922 | goto found; | |||
2923 | ||||
2924 | } | |||
2925 | ||||
2926 | /* Either looking for a specific interval or there was no interval specified and there wasn't one at the default ptime available */ | |||
2927 | for (imp = codec_interface->implementations; imp; imp = imp->next) { | |||
2928 | if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { | |||
2929 | uint32_t crate = !strcasecmp(imp->iananame, "g722") ? imp->samples_per_second : imp->actual_samples_per_second; | |||
2930 | ||||
2931 | if (interval && (uint32_t) (imp->microseconds_per_packet / 1000) != interval) { | |||
2932 | continue; | |||
2933 | } | |||
2934 | ||||
2935 | if (rate && (uint32_t) crate != rate) { | |||
2936 | continue; | |||
2937 | } | |||
2938 | ||||
2939 | if (bit && (uint32_t) imp->bits_per_second != bit) { | |||
2940 | continue; | |||
2941 | } | |||
2942 | ||||
2943 | if (channels && imp->number_of_channels != channels) { | |||
2944 | continue; | |||
2945 | } | |||
2946 | } | |||
2947 | ||||
2948 | array[i++] = imp; | |||
2949 | goto found; | |||
2950 | ||||
2951 | } | |||
2952 | ||||
2953 | found: | |||
2954 | ||||
2955 | UNPROTECT_INTERFACE(codec_interface)if (codec_interface) {switch_mutex_lock(codec_interface->reflock ); codec_interface->refs--; codec_interface->parent-> refs--; switch_mutex_unlock(codec_interface->reflock); switch_thread_rwlock_unlock (codec_interface->rwlock); switch_thread_rwlock_unlock(codec_interface ->parent->rwlock);}; | |||
2956 | ||||
2957 | if (i > arraylen) { | |||
2958 | break; | |||
2959 | } | |||
2960 | ||||
2961 | } | |||
2962 | ||||
2963 | next_x: | |||
2964 | ||||
2965 | continue; | |||
2966 | } | |||
2967 | ||||
2968 | switch_mutex_unlock(loadable_modules.mutex); | |||
2969 | ||||
2970 | switch_loadable_module_sort_codecs(array, i); | |||
2971 | ||||
2972 | return i; | |||
2973 | } | |||
2974 | ||||
2975 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream) | |||
2976 | { | |||
2977 | switch_api_interface_t *api; | |||
2978 | switch_status_t status; | |||
2979 | char *arg_used; | |||
2980 | char *cmd_used; | |||
2981 | ||||
2982 | switch_assert(stream != NULL)((stream != ((void*)0)) ? (void) (0) : __assert_fail ("stream != ((void*)0)" , "src/switch_loadable_module.c", 2982, __extension__ __PRETTY_FUNCTION__ )); | |||
2983 | switch_assert(stream->data != NULL)((stream->data != ((void*)0)) ? (void) (0) : __assert_fail ("stream->data != ((void*)0)", "src/switch_loadable_module.c" , 2983, __extension__ __PRETTY_FUNCTION__)); | |||
2984 | switch_assert(stream->write_function != NULL)((stream->write_function != ((void*)0)) ? (void) (0) : __assert_fail ("stream->write_function != ((void*)0)", "src/switch_loadable_module.c" , 2984, __extension__ __PRETTY_FUNCTION__)); | |||
2985 | ||||
2986 | if (strcasecmp(cmd, "console_complete")) { | |||
2987 | cmd_used = switch_strip_whitespace(cmd); | |||
2988 | arg_used = switch_strip_whitespace(arg); | |||
2989 | } else { | |||
2990 | cmd_used = (char *) cmd; | |||
2991 | arg_used = (char *) arg; | |||
2992 | } | |||
2993 | ||||
2994 | ||||
2995 | if (!stream->param_event) { | |||
2996 | switch_event_create(&stream->param_event, SWITCH_EVENT_API)switch_event_create_subclass_detailed("src/switch_loadable_module.c" , (const char * )(const char *)__func__, 2996, &stream-> param_event, SWITCH_EVENT_API, ((void*)0)); | |||
2997 | } | |||
2998 | ||||
2999 | if (stream->param_event) { | |||
3000 | if (cmd_used && *cmd_used) { | |||
3001 | switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_used); | |||
3002 | } | |||
3003 | if (arg_used && *arg_used) { | |||
3004 | switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_used); | |||
3005 | } | |||
3006 | } | |||
3007 | ||||
3008 | ||||
3009 | if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) { | |||
3010 | if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) { | |||
3011 | stream->write_function(stream, "COMMAND RETURNED ERROR!\n"); | |||
3012 | } | |||
3013 | UNPROTECT_INTERFACE(api)if (api) {switch_mutex_lock(api->reflock); api->refs--; api->parent->refs--; switch_mutex_unlock(api->reflock ); switch_thread_rwlock_unlock(api->rwlock); switch_thread_rwlock_unlock (api->parent->rwlock);}; | |||
3014 | } else { | |||
3015 | status = SWITCH_STATUS_FALSE; | |||
3016 | stream->write_function(stream, "INVALID COMMAND!\n"); | |||
3017 | } | |||
3018 | ||||
3019 | if (stream->param_event) { | |||
3020 | switch_event_fire(&stream->param_event)switch_event_fire_detailed("src/switch_loadable_module.c", (const char * )(const char *)__func__, 3020, &stream->param_event , ((void*)0)); | |||
3021 | } | |||
3022 | ||||
3023 | if (cmd_used != cmd) { | |||
3024 | switch_safe_free(cmd_used)if (cmd_used) {free(cmd_used);cmd_used=((void*)0);}; | |||
3025 | } | |||
3026 | ||||
3027 | if (arg_used != arg) { | |||
3028 | switch_safe_free(arg_used)if (arg_used) {free(arg_used);arg_used=((void*)0);}; | |||
3029 | } | |||
3030 | ||||
3031 | return status; | |||
3032 | } | |||
3033 | ||||
3034 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_json_api_execute(cJSON *json, switch_core_session_t *session, cJSON **retval) | |||
3035 | { | |||
3036 | switch_json_api_interface_t *json_api; | |||
3037 | switch_status_t status; | |||
3038 | cJSON *function, *json_reply = NULL((void*)0); | |||
3039 | ||||
3040 | switch_assert(json)((json) ? (void) (0) : __assert_fail ("json", "src/switch_loadable_module.c" , 3040, __extension__ __PRETTY_FUNCTION__)); | |||
3041 | ||||
3042 | function = cJSON_GetObjectItem(json, "command"); | |||
3043 | ||||
3044 | if (function && function->valuestring | |||
3045 | && cJSON_GetObjectItem(json, "data") && (json_api = switch_loadable_module_get_json_api_interface(function->valuestring)) != 0) { | |||
3046 | if ((status = json_api->function(json, session, &json_reply)) != SWITCH_STATUS_SUCCESS) { | |||
3047 | cJSON_AddItemToObject(json, "status", cJSON_CreateString("error")); | |||
3048 | cJSON_AddItemToObject(json, "message", cJSON_CreateString("The command returned an error")); | |||
3049 | } else { | |||
3050 | cJSON_AddItemToObject(json, "status", cJSON_CreateString("success")); | |||
3051 | } | |||
3052 | ||||
3053 | if (!json_reply) { | |||
3054 | json_reply = cJSON_CreateNull(); | |||
3055 | } | |||
3056 | ||||
3057 | if (retval) { | |||
3058 | *retval = json_reply; | |||
3059 | } else { | |||
3060 | cJSON_AddItemToObject(json, "response", json_reply); | |||
3061 | } | |||
3062 | ||||
3063 | UNPROTECT_INTERFACE(json_api)if (json_api) {switch_mutex_lock(json_api->reflock); json_api ->refs--; json_api->parent->refs--; switch_mutex_unlock (json_api->reflock); switch_thread_rwlock_unlock(json_api-> rwlock); switch_thread_rwlock_unlock(json_api->parent-> rwlock);}; | |||
3064 | } else { | |||
3065 | status = SWITCH_STATUS_FALSE; | |||
3066 | cJSON_AddItemToObject(json, "status", cJSON_CreateString("error")); | |||
3067 | cJSON_AddItemToObject(json, "message", cJSON_CreateString("Invalid request or non-existant command")); | |||
3068 | cJSON_AddItemToObject(json, "response", cJSON_CreateNull()); | |||
3069 | } | |||
3070 | ||||
3071 | return status; | |||
3072 | } | |||
3073 | ||||
3074 | ||||
3075 | SWITCH_DECLARE(switch_loadable_module_interface_t *)__attribute__((visibility("default"))) switch_loadable_module_interface_t * switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name) | |||
3076 | { | |||
3077 | switch_loadable_module_interface_t *mod; | |||
3078 | ||||
3079 | mod = switch_core_alloc(pool, sizeof(switch_loadable_module_interface_t))switch_core_perform_alloc(pool, sizeof(switch_loadable_module_interface_t ), "src/switch_loadable_module.c", (const char *)__func__, 3079 ); | |||
3080 | switch_assert(mod != NULL)((mod != ((void*)0)) ? (void) (0) : __assert_fail ("mod != ((void*)0)" , "src/switch_loadable_module.c", 3080, __extension__ __PRETTY_FUNCTION__ )); | |||
3081 | ||||
3082 | mod->pool = pool; | |||
3083 | ||||
3084 | mod->module_name = switch_core_strdup(mod->pool, name)switch_core_perform_strdup(mod->pool, name, "src/switch_loadable_module.c" , (const char *)__func__, 3084); | |||
3085 | switch_thread_rwlock_create(&mod->rwlock, mod->pool); | |||
3086 | return mod; | |||
3087 | } | |||
3088 | ||||
3089 | #define ALLOC_INTERFACE(_TYPE_){ switch__TYPE__interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch__TYPE__interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3089); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3089, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> _TYPE__interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->_TYPE__interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } { \ | |||
3090 | switch_##_TYPE_##_interface_t *i, *ptr; \ | |||
3091 | i = switch_core_alloc(mod->pool, sizeof(switch_##_TYPE_##_interface_t))switch_core_perform_alloc(mod->pool, sizeof(switch_##_TYPE_ ##_interface_t), "src/switch_loadable_module.c", (const char * )__func__, 3091); \ | |||
3092 | switch_assert(i != NULL)((i != ((void*)0)) ? (void) (0) : __assert_fail ("i != ((void*)0)" , "src/switch_loadable_module.c", 3092, __extension__ __PRETTY_FUNCTION__ )); \ | |||
3093 | for (ptr = mod->_TYPE_##_interface; ptr && ptr->next; ptr = ptr->next); \ | |||
3094 | if (ptr) { \ | |||
3095 | ptr->next = i; \ | |||
3096 | } else { \ | |||
3097 | mod->_TYPE_##_interface = i; \ | |||
3098 | } \ | |||
3099 | switch_thread_rwlock_create(&i->rwlock, mod->pool); \ | |||
3100 | switch_mutex_init(&i->reflock, SWITCH_MUTEX_NESTED0x1, mod->pool); \ | |||
3101 | i->parent = mod; \ | |||
3102 | return i; } | |||
3103 | ||||
3104 | ||||
3105 | SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname) | |||
3106 | { | |||
3107 | ||||
3108 | switch (iname) { | |||
3109 | case SWITCH_ENDPOINT_INTERFACE: | |||
3110 | ALLOC_INTERFACE(endpoint){ switch_endpoint_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_endpoint_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3110); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3110, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> endpoint_interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->endpoint_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3111 | ||||
3112 | case SWITCH_TIMER_INTERFACE: | |||
3113 | ALLOC_INTERFACE(timer){ switch_timer_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_timer_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3113); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3113, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> timer_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->timer_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3114 | ||||
3115 | case SWITCH_DIALPLAN_INTERFACE: | |||
3116 | ALLOC_INTERFACE(dialplan){ switch_dialplan_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_dialplan_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3116); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3116, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> dialplan_interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->dialplan_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3117 | ||||
3118 | case SWITCH_CODEC_INTERFACE: | |||
3119 | ALLOC_INTERFACE(codec){ switch_codec_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_codec_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3119); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3119, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> codec_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->codec_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3120 | ||||
3121 | case SWITCH_APPLICATION_INTERFACE: | |||
3122 | ALLOC_INTERFACE(application){ switch_application_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_application_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3122); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3122, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> application_interface; ptr && ptr->next; ptr = ptr ->next); if (ptr) { ptr->next = i; } else { mod->application_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3123 | ||||
3124 | case SWITCH_CHAT_APPLICATION_INTERFACE: | |||
3125 | ALLOC_INTERFACE(chat_application){ switch_chat_application_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_chat_application_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3125); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3125, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> chat_application_interface; ptr && ptr->next; ptr = ptr->next); if (ptr) { ptr->next = i; } else { mod-> chat_application_interface = i; } switch_thread_rwlock_create (&i->rwlock, mod->pool); switch_mutex_init(&i-> reflock, 0x1, mod->pool); i->parent = mod; return i; } | |||
3126 | ||||
3127 | case SWITCH_API_INTERFACE: | |||
3128 | ALLOC_INTERFACE(api){ switch_api_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_api_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3128); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3128, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> api_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->api_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3129 | ||||
3130 | case SWITCH_JSON_API_INTERFACE: | |||
3131 | ALLOC_INTERFACE(json_api){ switch_json_api_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_json_api_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3131); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3131, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> json_api_interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->json_api_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3132 | ||||
3133 | case SWITCH_FILE_INTERFACE: | |||
3134 | ALLOC_INTERFACE(file){ switch_file_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_file_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3134); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3134, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> file_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->file_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3135 | ||||
3136 | case SWITCH_SPEECH_INTERFACE: | |||
3137 | ALLOC_INTERFACE(speech){ switch_speech_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_speech_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3137); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3137, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> speech_interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->speech_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3138 | ||||
3139 | case SWITCH_DIRECTORY_INTERFACE: | |||
3140 | ALLOC_INTERFACE(directory){ switch_directory_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_directory_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3140); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3140, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> directory_interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->directory_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3141 | ||||
3142 | case SWITCH_CHAT_INTERFACE: | |||
3143 | ALLOC_INTERFACE(chat){ switch_chat_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_chat_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3143); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3143, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> chat_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->chat_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3144 | ||||
3145 | case SWITCH_SAY_INTERFACE: | |||
3146 | ALLOC_INTERFACE(say){ switch_say_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_say_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3146); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3146, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> say_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->say_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3147 | ||||
3148 | case SWITCH_ASR_INTERFACE: | |||
3149 | ALLOC_INTERFACE(asr){ switch_asr_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_asr_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3149); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3149, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> asr_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->asr_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3150 | ||||
3151 | case SWITCH_MANAGEMENT_INTERFACE: | |||
3152 | ALLOC_INTERFACE(management){ switch_management_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_management_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3152); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3152, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> management_interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->management_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3153 | ||||
3154 | case SWITCH_LIMIT_INTERFACE: | |||
3155 | ALLOC_INTERFACE(limit){ switch_limit_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_limit_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3155); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3155, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> limit_interface; ptr && ptr->next; ptr = ptr->next ); if (ptr) { ptr->next = i; } else { mod->limit_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3156 | ||||
3157 | case SWITCH_DATABASE_INTERFACE: | |||
3158 | ALLOC_INTERFACE(database){ switch_database_interface_t *i, *ptr; i = switch_core_perform_alloc (mod->pool, sizeof(switch_database_interface_t), "src/switch_loadable_module.c" , (const char *)__func__, 3158); ((i != ((void*)0)) ? (void) ( 0) : __assert_fail ("i != ((void*)0)", "src/switch_loadable_module.c" , 3158, __extension__ __PRETTY_FUNCTION__)); for (ptr = mod-> database_interface; ptr && ptr->next; ptr = ptr-> next); if (ptr) { ptr->next = i; } else { mod->database_interface = i; } switch_thread_rwlock_create(&i->rwlock, mod-> pool); switch_mutex_init(&i->reflock, 0x1, mod->pool ); i->parent = mod; return i; } | |||
3159 | ||||
3160 | default: | |||
3161 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_loadable_module.c", (const char *)__func__, 3161, ((void*)0), SWITCH_LOG_WARNING, "Invalid Module Type!\n"); | |||
3162 | return NULL((void*)0); | |||
3163 | } | |||
3164 | } | |||
3165 | ||||
3166 | struct switch_say_file_handle { | |||
3167 | char *ext; | |||
3168 | int cnt; | |||
3169 | struct switch_stream_handle stream; | |||
3170 | switch_event_t *param_event; | |||
3171 | }; | |||
3172 | ||||
3173 | SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var) | |||
3174 | { | |||
3175 | char *ret = NULL((void*)0); | |||
3176 | ||||
3177 | if (sh->param_event) { | |||
3178 | ret = switch_event_get_header(sh->param_event, var)switch_event_get_header_idx(sh->param_event, var, -1); | |||
3179 | } | |||
3180 | ||||
3181 | return ret; | |||
3182 | ||||
3183 | } | |||
3184 | ||||
3185 | SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_get_path(switch_say_file_handle_t *sh) | |||
3186 | { | |||
3187 | return (char *) sh->stream.data; | |||
3188 | } | |||
3189 | ||||
3190 | SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_detach_path(switch_say_file_handle_t *sh) | |||
3191 | { | |||
3192 | char *path; | |||
3193 | ||||
3194 | switch_assert(sh)((sh) ? (void) (0) : __assert_fail ("sh", "src/switch_loadable_module.c" , 3194, __extension__ __PRETTY_FUNCTION__)); | |||
3195 | path = (char *) sh->stream.data; | |||
3196 | sh->stream.data = NULL((void*)0); | |||
3197 | return path; | |||
3198 | } | |||
3199 | ||||
3200 | ||||
3201 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_say_file_handle_destroy(switch_say_file_handle_t **sh) | |||
3202 | { | |||
3203 | switch_assert(sh)((sh) ? (void) (0) : __assert_fail ("sh", "src/switch_loadable_module.c" , 3203, __extension__ __PRETTY_FUNCTION__)); | |||
3204 | ||||
3205 | switch_safe_free((*sh)->stream.data)if ((*sh)->stream.data) {free((*sh)->stream.data);(*sh) ->stream.data=((void*)0);}; | |||
3206 | switch_safe_free((*sh)->ext)if ((*sh)->ext) {free((*sh)->ext);(*sh)->ext=((void* )0);}; | |||
3207 | ||||
3208 | if ((*sh)->param_event) { | |||
3209 | switch_event_destroy(&(*sh)->param_event); | |||
3210 | } | |||
3211 | free(*sh); | |||
3212 | *sh = NULL((void*)0); | |||
3213 | } | |||
3214 | ||||
3215 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event) | |||
3216 | { | |||
3217 | switch_assert(sh)((sh) ? (void) (0) : __assert_fail ("sh", "src/switch_loadable_module.c" , 3217, __extension__ __PRETTY_FUNCTION__)); | |||
3218 | ||||
3219 | if (zstr(ext)_zstr(ext)) { | |||
3220 | ext = "wav"; | |||
3221 | } | |||
3222 | ||||
3223 | *sh = malloc(sizeof(**sh)); | |||
3224 | memset(*sh, 0, sizeof(**sh)); | |||
3225 | ||||
3226 | SWITCH_STANDARD_STREAM((*sh)->stream)memset(&(*sh)->stream, 0, sizeof((*sh)->stream)); ( *sh)->stream.data = malloc(1024); (((*sh)->stream.data) ? (void) (0) : __assert_fail ("(*sh)->stream.data", "src/switch_loadable_module.c" , 3226, __extension__ __PRETTY_FUNCTION__)); memset((*sh)-> stream.data, 0, 1024); (*sh)->stream.end = (*sh)->stream .data; (*sh)->stream.data_size = 1024; (*sh)->stream.write_function = switch_console_stream_write; (*sh)->stream.raw_write_function = switch_console_stream_raw_write; (*sh)->stream.alloc_len = 1024; (*sh)->stream.alloc_chunk = 1024; | |||
3227 | ||||
3228 | if (var_event) { | |||
3229 | (*sh)->param_event = *var_event; | |||
3230 | *var_event = NULL((void*)0); | |||
3231 | } | |||
3232 | ||||
3233 | (*sh)->ext = strdup(ext); | |||
3234 | ||||
3235 | return SWITCH_STATUS_SUCCESS; | |||
3236 | } | |||
3237 | ||||
3238 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...) | |||
3239 | { | |||
3240 | char buf[256] = ""; | |||
3241 | int ret; | |||
3242 | va_list ap; | |||
3243 | ||||
3244 | va_start(ap, fmt)__builtin_va_start(ap, fmt); | |||
3245 | ||||
3246 | if ((ret = switch_vsnprintf(buf, sizeof(buf), fmt, ap)) > 0) { | |||
3247 | if (!sh->cnt++) { | |||
3248 | sh->stream.write_function(&sh->stream, "file_string://%s.%s", buf, sh->ext); | |||
3249 | } else if (strstr(buf, "://")) { | |||
3250 | sh->stream.write_function(&sh->stream, "!%s", buf); | |||
3251 | } else { | |||
3252 | sh->stream.write_function(&sh->stream, "!%s.%s", buf, sh->ext); | |||
3253 | } | |||
3254 | ||||
3255 | } | |||
3256 | ||||
3257 | va_end(ap)__builtin_va_end(ap); | |||
3258 | } | |||
3259 | ||||
3260 | SWITCH_DECLARE(switch_core_recover_callback_t)__attribute__((visibility("default"))) switch_core_recover_callback_t switch_core_get_secondary_recover_callback(const char *key) | |||
3261 | { | |||
3262 | switch_core_recover_callback_t cb; | |||
3263 | ||||
3264 | switch_mutex_lock(loadable_modules.mutex); | |||
3265 | cb = (switch_core_recover_callback_t) (intptr_t) switch_core_hash_find(loadable_modules.secondary_recover_hash, key); | |||
3266 | switch_mutex_unlock(loadable_modules.mutex); | |||
3267 | ||||
3268 | return cb; | |||
3269 | } | |||
3270 | ||||
3271 | ||||
3272 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_register_secondary_recover_callback(const char *key, switch_core_recover_callback_t cb) | |||
3273 | { | |||
3274 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||
3275 | ||||
3276 | switch_assert(cb)((cb) ? (void) (0) : __assert_fail ("cb", "src/switch_loadable_module.c" , 3276, __extension__ __PRETTY_FUNCTION__)); | |||
3277 | ||||
3278 | switch_mutex_lock(loadable_modules.mutex); | |||
3279 | if (switch_core_hash_find(loadable_modules.secondary_recover_hash, key)) { | |||
3280 | status = SWITCH_STATUS_FALSE; | |||
3281 | } else { | |||
3282 | switch_core_hash_insert(loadable_modules.secondary_recover_hash, key, (void *)(intptr_t) cb)switch_core_hash_insert_destructor(loadable_modules.secondary_recover_hash , key, (void *)(intptr_t) cb, ((void*)0)); | |||
3283 | } | |||
3284 | switch_mutex_unlock(loadable_modules.mutex); | |||
3285 | ||||
3286 | return status; | |||
3287 | } | |||
3288 | ||||
3289 | ||||
3290 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_unregister_secondary_recover_callback(const char *key) | |||
3291 | { | |||
3292 | switch_mutex_lock(loadable_modules.mutex); | |||
3293 | switch_core_hash_delete(loadable_modules.secondary_recover_hash, key); | |||
3294 | switch_mutex_unlock(loadable_modules.mutex); | |||
3295 | } | |||
3296 | ||||
3297 | ||||
3298 | /* For Emacs: | |||
3299 | * Local Variables: | |||
3300 | * mode:c | |||
3301 | * indent-tabs-mode:t | |||
3302 | * tab-width:4 | |||
3303 | * c-basic-offset:4 | |||
3304 | * End: | |||
3305 | * For VIM: | |||
3306 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: | |||
3307 | */ |