1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2012, 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 *
28 *
29 * mod_basic.c -- BASIC Module
30 *
31 */
32 #include <switch.h>
33 #include "my_basic.h"
34
35 /* Prototypes */
36 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_basic_shutdown);
37 SWITCH_MODULE_RUNTIME_FUNCTION(mod_basic_runtime);
38 SWITCH_MODULE_LOAD_FUNCTION(mod_basic_load);
39
40 /* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)
41 * Defines a switch_loadable_module_function_table_t and a static const char[] modname
42 */
43 SWITCH_MODULE_DEFINITION(mod_basic, mod_basic_load, mod_basic_shutdown, NULL);
44
45 static struct {
46 int integer;
47 } globals;
48
49
50
do_config(switch_bool_t reload)51 static switch_status_t do_config(switch_bool_t reload)
52 {
53 memset(&globals, 0, sizeof(globals));
54
55 return SWITCH_STATUS_SUCCESS;
56 }
57
_on_error(mb_interpreter_t * s,mb_error_e e,char * m,int p,unsigned short row,unsigned short col,int abort_code)58 static void _on_error(mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) {
59 mb_unrefvar(s);
60 if(SE_NO_ERR != e) {
61 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
62 "Error:\n [POS] %d, [ROW] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", p, row, col, e, m, abort_code);
63 }
64 }
65
66 typedef struct fs_data {
67 switch_core_session_t *session;
68 int argc;
69 char *argv[128];
70 switch_event_t *vars;
71 } fs_data_t;
72
73
fun_execute(mb_interpreter_t * s,void ** l)74 static int fun_execute(mb_interpreter_t* s, void** l)
75 {
76 int result = MB_FUNC_OK;
77 fs_data_t *fsdata = (fs_data_t *) mb_get_user_data(s);
78 mb_value_t app;
79 mb_value_t arg;
80 int null_arg = 0;
81
82 mb_assert(s && l);
83
84 mb_check(mb_attempt_func_begin(s, l));
85
86 if ((result = mb_pop_value(s, l, &app)) != MB_FUNC_OK) {
87 goto end;
88 }
89
90 if ((result = mb_pop_value(s, l, &arg)) != MB_FUNC_OK) {
91 null_arg++;
92 result = 0;
93 }
94
95 if (app.type == MB_DT_STRING && (arg.type == MB_DT_STRING || null_arg) && fsdata->session) {
96 switch_core_session_execute_application(fsdata->session, app.value.string, null_arg ? NULL : arg.value.string);
97 } else {
98 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad args or no fsdata->session\n");
99 result = MB_FUNC_WARNING;
100 }
101
102 mb_check(mb_attempt_func_end(s, l));
103
104 end:
105
106 return result;
107 }
108
109
fun_setvar(mb_interpreter_t * s,void ** l)110 static int fun_setvar(mb_interpreter_t* s, void** l)
111 {
112 int result = MB_FUNC_OK;
113 fs_data_t *fsdata = (fs_data_t *) mb_get_user_data(s);
114 mb_value_t var;
115 mb_value_t val;
116
117 mb_assert(s && l);
118
119 mb_check(mb_attempt_func_begin(s, l));
120
121 if ((result = mb_pop_value(s, l, &var)) != MB_FUNC_OK) {
122 goto end;
123 }
124
125 if ((result = mb_pop_value(s, l, &val)) != MB_FUNC_OK) {
126 goto end;
127 }
128
129 if (var.type == MB_DT_STRING && val.type == MB_DT_STRING && fsdata->session) {
130 switch_channel_t *channel = switch_core_session_get_channel(fsdata->session);
131 switch_channel_set_variable(channel, var.value.string, val.value.string);
132 } else {
133 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad args or no session\n");
134 result = MB_FUNC_WARNING;
135 }
136
137 mb_check(mb_attempt_func_end(s, l));
138
139 end:
140
141 return result;
142 }
143
fun_getarg(mb_interpreter_t * s,void ** l)144 static int fun_getarg(mb_interpreter_t* s, void** l)
145 {
146 int result = MB_FUNC_OK;
147 fs_data_t *fsdata = (fs_data_t *) mb_get_user_data(s);
148 mb_value_t idx;
149
150 mb_assert(s && l);
151
152 mb_check(mb_attempt_func_begin(s, l));
153
154 if ((result = mb_pop_value(s, l, &idx)) != MB_FUNC_OK) {
155 goto end;
156 }
157
158 if (idx.type == MB_DT_INT && fsdata->argc) {
159 if (idx.value.integer < fsdata->argc) {
160 mb_push_string(s, l, strdup(fsdata->argv[idx.value.integer]));
161 }
162 } else {
163 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad args or no session\n");
164 result = MB_FUNC_WARNING;
165 }
166
167 mb_check(mb_attempt_func_end(s, l));
168
169 end:
170
171 return result;
172 }
173
fun_getvar(mb_interpreter_t * s,void ** l)174 static int fun_getvar(mb_interpreter_t* s, void** l)
175 {
176 int result = MB_FUNC_OK;
177 fs_data_t *fsdata = (fs_data_t *) mb_get_user_data(s);
178 mb_value_t var;
179
180 mb_assert(s && l);
181
182 mb_check(mb_attempt_func_begin(s, l));
183
184 if ((result = mb_pop_value(s, l, &var)) != MB_FUNC_OK) {
185 goto end;
186 }
187
188 if (var.type == MB_DT_STRING && fsdata->session) {
189 switch_channel_t *channel = switch_core_session_get_channel(fsdata->session);
190 const char *value = switch_channel_get_variable(channel, var.value.string);
191
192 mb_push_string(s, l, strdup(value));
193
194 } else {
195 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad args or no session\n");
196 result = MB_FUNC_WARNING;
197 }
198
199 mb_check(mb_attempt_func_end(s, l));
200
201 end:
202
203 return result;
204 }
205
fun_api(mb_interpreter_t * s,void ** l)206 static int fun_api(mb_interpreter_t* s, void** l)
207 {
208 int result = MB_FUNC_OK;
209 fs_data_t *fsdata = (fs_data_t *) mb_get_user_data(s);
210 mb_value_t app;
211 mb_value_t arg;
212
213 mb_assert(s && l);
214
215 mb_check(mb_attempt_func_begin(s, l));
216
217 if ((result = mb_pop_value(s, l, &app)) != MB_FUNC_OK) {
218 goto end;
219 }
220
221 if ((result = mb_pop_value(s, l, &arg)) != MB_FUNC_OK) {
222 goto end;
223 }
224
225 if (app.type == MB_DT_STRING && arg.type == MB_DT_STRING) {
226 switch_stream_handle_t stream = { 0 };
227 SWITCH_STANDARD_STREAM(stream);
228
229 switch_api_execute(app.value.string, arg.value.string, fsdata->session, &stream);
230 mb_push_string(s, l, (char *) stream.data);
231 //switch_safe_free(stream.data);
232 } else {
233 result = MB_FUNC_WARNING;
234 }
235
236 mb_check(mb_attempt_func_end(s, l));
237
238 end:
239
240 return result;
241 }
242
243
fun_log(mb_interpreter_t * s,void ** l)244 static int fun_log(mb_interpreter_t* s, void** l)
245 {
246 int result = MB_FUNC_OK;
247 fs_data_t *fsdata = (fs_data_t *) mb_get_user_data(s);
248 mb_value_t level;
249 mb_value_t data;
250
251 mb_assert(s && l);
252
253 mb_check(mb_attempt_func_begin(s, l));
254
255 if ((result = mb_pop_value(s, l, &level)) != MB_FUNC_OK) {
256 goto end;
257 }
258
259 if ((result = mb_pop_value(s, l, &data)) != MB_FUNC_OK) {
260 goto end;
261 }
262
263 if (level.type == MB_DT_STRING && data.type == MB_DT_STRING) {
264 switch_log_level_t fslevel = SWITCH_LOG_DEBUG;
265
266 fslevel = switch_log_str2level(level.value.string);
267 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fsdata->session), fslevel, "%s\n", data.value.string);
268 } else {
269 result = MB_FUNC_WARNING;
270 }
271
272 mb_check(mb_attempt_func_end(s, l));
273
274 end:
275
276 return result;
277 }
278
279
bprint(const char * fmt,...)280 static int bprint(const char *fmt, ...)
281 {
282 char *data = NULL;
283 va_list ap;
284 int ret = 0;
285
286 va_start(ap, fmt);
287 ret = switch_vasprintf(&data, fmt, ap);
288 va_end(ap);
289
290 if (data) {
291 switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "%s\n", data);
292 }
293
294 switch_safe_free(data);
295
296 return ret;
297
298 }
299
300
SWITCH_STANDARD_APP(basic_function)301 SWITCH_STANDARD_APP(basic_function)
302 {
303 const char *file;
304 char *fdup = NULL;
305 mb_interpreter_t *bi = 0;
306 fs_data_t fsdata = { 0 };
307 char *mydata = NULL;
308
309 if (data) {
310 mydata = strdup((char *) data);
311 } else {
312 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing data\n");
313 return;
314 }
315
316 fsdata.argc = switch_split(mydata, ' ', fsdata.argv);
317
318 file = fsdata.argv[0];
319
320 if (zstr(file)) {
321 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing file\n");
322 goto end;
323 }
324
325 if (!switch_is_file_path(file)) {
326 fdup = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.script_dir, file);
327 switch_assert(fdup);
328 file = fdup;
329 }
330
331 mb_open(&bi);
332 mb_set_error_handler(bi, _on_error);
333 mb_set_printer(bi, bprint);
334 fsdata.session = session;
335 mb_set_user_data(bi, (void *) &fsdata);
336
337 mb_register_func(bi, "FS_EXECUTE", fun_execute);
338 mb_register_func(bi, "FS_GETARG", fun_getarg);
339 mb_register_func(bi, "FS_GETVAR", fun_getvar);
340 mb_register_func(bi, "FS_SETVAR", fun_setvar);
341 mb_register_func(bi, "FS_API", fun_api);
342 mb_register_func(bi, "FS_LOG", fun_log);
343
344 if (mb_load_file(bi, file) == MB_FUNC_OK) {
345 mb_run(bi);
346 } else {
347 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error executing file\n");
348 }
349
350 mb_close(&bi);
351
352 end:
353 switch_safe_free(fdup);
354 switch_safe_free(mydata);
355 }
356
SWITCH_STANDARD_API(basic_api_function)357 SWITCH_STANDARD_API(basic_api_function)
358 {
359
360 basic_function(session, cmd);
361
362 return SWITCH_STATUS_SUCCESS;
363 }
364
365 /* Macro expands to: switch_status_t mod_basic_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_basic_load)366 SWITCH_MODULE_LOAD_FUNCTION(mod_basic_load)
367 {
368 switch_api_interface_t *api_interface;
369 switch_application_interface_t *app_interface;
370
371 /* connect my internal structure to the blank pointer passed to me */
372 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
373
374 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
375
376 do_config(SWITCH_FALSE);
377
378 SWITCH_ADD_API(api_interface, "basic", "Basic API", basic_api_function, "syntax");
379 SWITCH_ADD_APP(app_interface, "basic", "", "", basic_function, "<file>", SAF_NONE);
380
381 mb_init();
382
383 /* indicate that the module should continue to be loaded */
384 return SWITCH_STATUS_SUCCESS;
385 }
386
387 /*
388 Called when the system shuts down
389 Macro expands to: switch_status_t mod_basic_shutdown() */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_basic_shutdown)390 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_basic_shutdown)
391 {
392 /* Cleanup dynamically allocated config settings */
393 mb_dispose();
394
395 return SWITCH_STATUS_SUCCESS;
396 }
397
398
399 /*
400 If it exists, this is called in it's own thread when the module-load completes
401 If it returns anything but SWITCH_STATUS_TERM it will be called again automatically
402 Macro expands to: switch_status_t mod_basic_runtime()
403 SWITCH_MODULE_RUNTIME_FUNCTION(mod_basic_runtime)
404 {
405 while(looping)
406 {
407 switch_cond_next();
408 }
409 return SWITCH_STATUS_TERM;
410 }
411 */
412
413 /* For Emacs:
414 * Local Variables:
415 * mode:c
416 * indent-tabs-mode:t
417 * tab-width:4
418 * c-basic-offset:4
419 * End:
420 * For VIM:
421 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
422 */
423