00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 231190 $")
00034
00035 #include "asterisk/logger.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/module.h"
00039 #include "asterisk/cli.h"
00040 #include "asterisk/utils.h"
00041 #include "asterisk/term.h"
00042 #include "asterisk/paths.h"
00043 #include "asterisk/hashtab.h"
00044
00045 #ifdef LUA51_PREFIX
00046 #include <lua5.1/lua.h>
00047 #include <lua5.1/lauxlib.h>
00048 #include <lua5.1/lualib.h>
00049 #else
00050 #include <lua.h>
00051 #include <lauxlib.h>
00052 #include <lualib.h>
00053 #endif
00054
00055 static char *config = "extensions.lua";
00056 static char *registrar = "pbx_lua";
00057
00058 #define LUA_EXT_DATA_SIZE 256
00059 #define LUA_BUF_SIZE 4096
00060
00061 static char *lua_read_extensions_file(lua_State *L, long *size);
00062 static int lua_load_extensions(lua_State *L, struct ast_channel *chan);
00063 static int lua_reload_extensions(lua_State *L);
00064 static void lua_free_extensions(void);
00065 static int lua_sort_extensions(lua_State *L);
00066 static int lua_register_switches(lua_State *L);
00067 static int lua_extension_cmp(lua_State *L);
00068 static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func);
00069 static int lua_pbx_findapp(lua_State *L);
00070 static int lua_pbx_exec(lua_State *L);
00071
00072 static int lua_get_variable_value(lua_State *L);
00073 static int lua_set_variable_value(lua_State *L);
00074 static int lua_get_variable(lua_State *L);
00075 static int lua_set_variable(lua_State *L);
00076 static int lua_func_read(lua_State *L);
00077
00078 static int lua_autoservice_start(lua_State *L);
00079 static int lua_autoservice_stop(lua_State *L);
00080 static int lua_autoservice_status(lua_State *L);
00081 static int lua_check_hangup(lua_State *L);
00082 static int lua_error_function(lua_State *L);
00083
00084 static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority);
00085 static void lua_push_variable_table(lua_State *L, const char *name);
00086 static void lua_create_app_table(lua_State *L);
00087 static void lua_create_channel_table(lua_State *L);
00088 static void lua_create_variable_metatable(lua_State *L);
00089 static void lua_create_application_metatable(lua_State *L);
00090 static void lua_create_autoservice_functions(lua_State *L);
00091 static void lua_create_hangup_function(lua_State *L);
00092
00093 void lua_state_destroy(void *data);
00094 static lua_State *lua_get_state(struct ast_channel *chan);
00095
00096 static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00097 static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00098 static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00099 static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00100
00101 AST_MUTEX_DEFINE_STATIC(config_file_lock);
00102 char *config_file_data = NULL;
00103 long config_file_size = 0;
00104
00105 static struct ast_context *local_contexts = NULL;
00106 static struct ast_hashtab *local_table = NULL;
00107
00108 static const struct ast_datastore_info lua_datastore = {
00109 .type = "lua",
00110 .destroy = lua_state_destroy,
00111 };
00112
00113
00114
00115
00116
00117 void lua_state_destroy(void *data)
00118 {
00119 if (data)
00120 lua_close(data);
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 static int lua_pbx_findapp(lua_State *L)
00135 {
00136 const char *app_name = luaL_checkstring(L, 2);
00137
00138 lua_newtable(L);
00139
00140 lua_pushstring(L, "name");
00141 lua_pushstring(L, app_name);
00142 lua_settable(L, -3);
00143
00144 luaL_getmetatable(L, "application");
00145 lua_setmetatable(L, -2);
00146
00147 return 1;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 static int lua_pbx_exec(lua_State *L)
00166 {
00167 int res, nargs = lua_gettop(L);
00168 char data[LUA_EXT_DATA_SIZE] = "";
00169 char *data_next = data, *app_name;
00170 char *context, *exten;
00171 char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
00172 int priority, autoservice;
00173 size_t data_left = sizeof(data);
00174 struct ast_app *app;
00175 struct ast_channel *chan;
00176
00177 lua_getfield(L, 1, "name");
00178 app_name = ast_strdupa(lua_tostring(L, -1));
00179 lua_pop(L, 1);
00180
00181 if (!(app = pbx_findapp(app_name))) {
00182 lua_pushstring(L, "application '");
00183 lua_pushstring(L, app_name);
00184 lua_pushstring(L, "' not found");
00185 lua_concat(L, 3);
00186 return lua_error(L);
00187 }
00188
00189
00190 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00191 chan = lua_touserdata(L, -1);
00192 lua_pop(L, 1);
00193
00194
00195 lua_getfield(L, LUA_REGISTRYINDEX, "context");
00196 context = ast_strdupa(lua_tostring(L, -1));
00197 lua_pop(L, 1);
00198
00199 lua_getfield(L, LUA_REGISTRYINDEX, "exten");
00200 exten = ast_strdupa(lua_tostring(L, -1));
00201 lua_pop(L, 1);
00202
00203 lua_getfield(L, LUA_REGISTRYINDEX, "priority");
00204 priority = lua_tointeger(L, -1);
00205 lua_pop(L, 1);
00206
00207
00208 if (nargs > 1) {
00209 int i;
00210
00211 if (!lua_isnil(L, 2))
00212 ast_build_string(&data_next, &data_left, "%s", luaL_checkstring(L, 2));
00213
00214 for (i = 3; i <= nargs; i++) {
00215 if (lua_isnil(L, i))
00216 ast_build_string(&data_next, &data_left, ",");
00217 else
00218 ast_build_string(&data_next, &data_left, ",%s", luaL_checkstring(L, i));
00219 }
00220 }
00221
00222 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
00223 exten, context, priority,
00224 term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
00225 term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
00226 term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));
00227
00228 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00229 autoservice = lua_toboolean(L, -1);
00230 lua_pop(L, 1);
00231
00232 if (autoservice)
00233 ast_autoservice_stop(chan);
00234
00235 res = pbx_exec(chan, app, data);
00236
00237 if (autoservice)
00238 ast_autoservice_start(chan);
00239
00240
00241 if (res) {
00242 lua_pushinteger(L, res);
00243 return lua_error(L);
00244 }
00245 return 0;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 static int lua_get_variable_value(lua_State *L)
00261 {
00262 struct ast_channel *chan;
00263 char *value = NULL, *name;
00264 char *workspace = alloca(LUA_BUF_SIZE);
00265 int autoservice;
00266
00267 workspace[0] = '\0';
00268
00269 if (!lua_istable(L, 1)) {
00270 lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value");
00271 return lua_error(L);
00272 }
00273
00274 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00275 chan = lua_touserdata(L, -1);
00276 lua_pop(L, 1);
00277
00278 lua_getfield(L, 1, "name");
00279 name = ast_strdupa(lua_tostring(L, -1));
00280 lua_pop(L, 1);
00281
00282 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00283 autoservice = lua_toboolean(L, -1);
00284 lua_pop(L, 1);
00285
00286 if (autoservice)
00287 ast_autoservice_stop(chan);
00288
00289
00290
00291 if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') {
00292 value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace;
00293 } else {
00294 pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead);
00295 }
00296
00297 if (autoservice)
00298 ast_autoservice_start(chan);
00299
00300 if (value) {
00301 lua_pushstring(L, value);
00302 } else {
00303 lua_pushnil(L);
00304 }
00305
00306 return 1;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 static int lua_set_variable_value(lua_State *L)
00321 {
00322 const char *name, *value;
00323 struct ast_channel *chan;
00324 int autoservice;
00325
00326 if (!lua_istable(L, 1)) {
00327 lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable");
00328 return lua_error(L);
00329 }
00330
00331 lua_getfield(L, 1, "name");
00332 name = ast_strdupa(lua_tostring(L, -1));
00333 lua_pop(L, 1);
00334
00335 value = luaL_checkstring(L, 2);
00336
00337 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00338 chan = lua_touserdata(L, -1);
00339 lua_pop(L, 1);
00340
00341 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00342 autoservice = lua_toboolean(L, -1);
00343 lua_pop(L, 1);
00344
00345 if (autoservice)
00346 ast_autoservice_stop(chan);
00347
00348 pbx_builtin_setvar_helper(chan, name, value);
00349
00350 if (autoservice)
00351 ast_autoservice_start(chan);
00352
00353 return 0;
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority)
00365 {
00366 lua_pushstring(L, context);
00367 lua_setfield(L, LUA_REGISTRYINDEX, "context");
00368
00369 lua_pushstring(L, exten);
00370 lua_setfield(L, LUA_REGISTRYINDEX, "exten");
00371
00372 lua_pushinteger(L, priority);
00373 lua_setfield(L, LUA_REGISTRYINDEX, "priority");
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383 static void lua_push_variable_table(lua_State *L, const char *name)
00384 {
00385 lua_newtable(L);
00386 luaL_getmetatable(L, "variable");
00387 lua_setmetatable(L, -2);
00388
00389 lua_pushstring(L, name);
00390 lua_setfield(L, -2, "name");
00391
00392 lua_pushcfunction(L, &lua_get_variable_value);
00393 lua_setfield(L, -2, "get");
00394
00395 lua_pushcfunction(L, &lua_set_variable_value);
00396 lua_setfield(L, -2, "set");
00397 }
00398
00399
00400
00401
00402
00403
00404 static void lua_create_app_table(lua_State *L)
00405 {
00406 lua_newtable(L);
00407 luaL_newmetatable(L, "app");
00408
00409 lua_pushstring(L, "__index");
00410 lua_pushcfunction(L, &lua_pbx_findapp);
00411 lua_settable(L, -3);
00412
00413 lua_setmetatable(L, -2);
00414 lua_setglobal(L, "app");
00415 }
00416
00417
00418
00419
00420
00421
00422 static void lua_create_channel_table(lua_State *L)
00423 {
00424 lua_newtable(L);
00425 luaL_newmetatable(L, "channel_data");
00426
00427 lua_pushstring(L, "__index");
00428 lua_pushcfunction(L, &lua_get_variable);
00429 lua_settable(L, -3);
00430
00431 lua_pushstring(L, "__newindex");
00432 lua_pushcfunction(L, &lua_set_variable);
00433 lua_settable(L, -3);
00434
00435 lua_setmetatable(L, -2);
00436 lua_setglobal(L, "channel");
00437 }
00438
00439
00440
00441
00442
00443
00444 static void lua_create_variable_metatable(lua_State *L)
00445 {
00446 luaL_newmetatable(L, "variable");
00447
00448 lua_pushstring(L, "__call");
00449 lua_pushcfunction(L, &lua_func_read);
00450 lua_settable(L, -3);
00451
00452 lua_pop(L, 1);
00453 }
00454
00455
00456
00457
00458
00459
00460
00461 static void lua_create_application_metatable(lua_State *L)
00462 {
00463 luaL_newmetatable(L, "application");
00464
00465 lua_pushstring(L, "__call");
00466 lua_pushcfunction(L, &lua_pbx_exec);
00467 lua_settable(L, -3);
00468
00469 lua_pop(L, 1);
00470 }
00471
00472
00473
00474
00475
00476
00477 static void lua_create_autoservice_functions(lua_State *L)
00478 {
00479 lua_pushcfunction(L, &lua_autoservice_start);
00480 lua_setglobal(L, "autoservice_start");
00481
00482 lua_pushcfunction(L, &lua_autoservice_stop);
00483 lua_setglobal(L, "autoservice_stop");
00484
00485 lua_pushcfunction(L, &lua_autoservice_status);
00486 lua_setglobal(L, "autoservice_status");
00487
00488 lua_pushboolean(L, 0);
00489 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00490 }
00491
00492
00493
00494
00495
00496
00497 static void lua_create_hangup_function(lua_State *L)
00498 {
00499 lua_pushcfunction(L, &lua_check_hangup);
00500 lua_setglobal(L, "check_hangup");
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 static int lua_get_variable(lua_State *L)
00516 {
00517 struct ast_channel *chan;
00518 char *name = ast_strdupa(luaL_checkstring(L, 2));
00519 char *value = NULL;
00520 char *workspace = alloca(LUA_BUF_SIZE);
00521 workspace[0] = '\0';
00522
00523 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00524 chan = lua_touserdata(L, -1);
00525 lua_pop(L, 1);
00526
00527 lua_push_variable_table(L, name);
00528
00529
00530
00531 if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') {
00532 pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead);
00533 }
00534
00535 if (value) {
00536 lua_pushstring(L, value);
00537 lua_setfield(L, -2, "value");
00538 }
00539
00540 return 1;
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 static int lua_set_variable(lua_State *L)
00555 {
00556 struct ast_channel *chan;
00557 int autoservice;
00558 const char *name = luaL_checkstring(L, 2);
00559 const char *value = luaL_checkstring(L, 3);
00560
00561 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00562 chan = lua_touserdata(L, -1);
00563 lua_pop(L, 1);
00564
00565 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00566 autoservice = lua_toboolean(L, -1);
00567 lua_pop(L, 1);
00568
00569 if (autoservice)
00570 ast_autoservice_stop(chan);
00571
00572 pbx_builtin_setvar_helper(chan, name, value);
00573
00574 if (autoservice)
00575 ast_autoservice_start(chan);
00576
00577 return 0;
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 static int lua_func_read(lua_State *L)
00597 {
00598 int nargs = lua_gettop(L);
00599 char fullname[LUA_EXT_DATA_SIZE] = "";
00600 char *fullname_next = fullname, *name;
00601 size_t fullname_left = sizeof(fullname);
00602
00603 lua_getfield(L, 1, "name");
00604 name = ast_strdupa(lua_tostring(L, -1));
00605 lua_pop(L, 1);
00606
00607 ast_build_string(&fullname_next, &fullname_left, "%s(", name);
00608
00609 if (nargs > 1) {
00610 int i;
00611
00612 if (!lua_isnil(L, 2))
00613 ast_build_string(&fullname_next, &fullname_left, "%s", luaL_checkstring(L, 2));
00614
00615 for (i = 3; i <= nargs; i++) {
00616 if (lua_isnil(L, i))
00617 ast_build_string(&fullname_next, &fullname_left, ",");
00618 else
00619 ast_build_string(&fullname_next, &fullname_left, ",%s", luaL_checkstring(L, i));
00620 }
00621 }
00622
00623 ast_build_string(&fullname_next, &fullname_left, ")");
00624
00625 lua_push_variable_table(L, fullname);
00626
00627 return 1;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 static int lua_autoservice_start(lua_State *L)
00644 {
00645 struct ast_channel *chan;
00646 int res;
00647
00648 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00649 chan = lua_touserdata(L, -1);
00650 lua_pop(L, 1);
00651
00652 res = ast_autoservice_start(chan);
00653
00654 lua_pushboolean(L, !res);
00655 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00656
00657 lua_pushboolean(L, !res);
00658 return 1;
00659 }
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 static int lua_autoservice_stop(lua_State *L)
00675 {
00676 struct ast_channel *chan;
00677 int res;
00678
00679 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00680 chan = lua_touserdata(L, -1);
00681 lua_pop(L, 1);
00682
00683 res = ast_autoservice_stop(chan);
00684
00685 lua_pushboolean(L, 0);
00686 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00687
00688 lua_pushboolean(L, !res);
00689 return 1;
00690 }
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 static int lua_autoservice_status(lua_State *L)
00702 {
00703 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00704 return 1;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 static int lua_check_hangup(lua_State *L)
00716 {
00717 struct ast_channel *chan;
00718 lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00719 chan = lua_touserdata(L, -1);
00720 lua_pop(L, 1);
00721
00722 lua_pushboolean(L, ast_check_hangup(chan));
00723 return 1;
00724 }
00725
00726
00727
00728
00729
00730
00731
00732 static int lua_error_function(lua_State *L)
00733 {
00734 int message_index;
00735
00736
00737 if (lua_isnumber(L, -1)) {
00738 return 1;
00739 }
00740
00741
00742
00743 message_index = lua_gettop(L);
00744
00745 lua_getglobal(L, "debug");
00746 lua_getfield(L, -1, "traceback");
00747 lua_remove(L, -2);
00748
00749 lua_pushvalue(L, message_index);
00750 lua_remove(L, message_index);
00751
00752 lua_pushnumber(L, 2);
00753
00754 lua_call(L, 2, 1);
00755
00756 return 1;
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 static int lua_sort_extensions(lua_State *L)
00768 {
00769 int extensions, extensions_order;
00770
00771
00772 lua_newtable(L);
00773 lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order");
00774 lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
00775 extensions_order = lua_gettop(L);
00776
00777
00778
00779 lua_getglobal(L, "extensions");
00780 extensions = lua_gettop(L);
00781 if (lua_isnil(L, -1)) {
00782 lua_pop(L, 1);
00783 lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00784 return 1;
00785 }
00786
00787
00788
00789
00790
00791 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00792 int context = lua_gettop(L);
00793 int context_name = context - 1;
00794 int context_order;
00795
00796 lua_pushvalue(L, context_name);
00797 lua_newtable(L);
00798 context_order = lua_gettop(L);
00799
00800
00801
00802 for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
00803 int exten = lua_gettop(L) - 1;
00804
00805 lua_pushinteger(L, lua_objlen(L, context_order) + 1);
00806 lua_pushvalue(L, exten);
00807 lua_settable(L, context_order);
00808 }
00809 lua_settable(L, extensions_order);
00810
00811
00812
00813
00814 lua_getglobal(L, "table");
00815 lua_getfield(L, -1, "sort");
00816 lua_remove(L, -2);
00817
00818
00819 lua_pushvalue(L, context_name);
00820 lua_gettable(L, extensions_order);
00821
00822
00823 lua_pushcfunction(L, &lua_extension_cmp);
00824
00825 if (lua_pcall(L, 2, 0, 0)) {
00826 lua_insert(L, -5);
00827 lua_pop(L, 4);
00828 return 1;
00829 }
00830 }
00831
00832
00833 lua_pop(L, 2);
00834 return 0;
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 static int lua_register_switches(lua_State *L)
00846 {
00847 int extensions;
00848 struct ast_context *con = NULL;
00849
00850
00851
00852 if (!local_table)
00853 local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
00854
00855
00856 lua_getglobal(L, "extensions");
00857 extensions = lua_gettop(L);
00858 if (lua_isnil(L, -1)) {
00859 lua_pop(L, 1);
00860 lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00861 return 1;
00862 }
00863
00864
00865
00866
00867 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00868 int context = lua_gettop(L);
00869 int context_name = context - 1;
00870 const char *context_str = lua_tostring(L, context_name);
00871
00872
00873 con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
00874 if (!con) {
00875
00876 lua_pop(L, 3);
00877 lua_pushstring(L, "Failed to find or create context\n");
00878 return 1;
00879 }
00880
00881
00882 if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
00883
00884 lua_pop(L, 3);
00885 lua_pushstring(L, "Unable to create switch for context\n");
00886 return 1;
00887 }
00888 }
00889
00890
00891 lua_pop(L, 1);
00892 return 0;
00893 }
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 static int lua_extension_cmp(lua_State *L)
00904 {
00905 const char *a = luaL_checkstring(L, -2);
00906 const char *b = luaL_checkstring(L, -1);
00907
00908 if (ast_extension_cmp(a, b) == -1)
00909 lua_pushboolean(L, 1);
00910 else
00911 lua_pushboolean(L, 0);
00912
00913 return 1;
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926 static char *lua_read_extensions_file(lua_State *L, long *size)
00927 {
00928 FILE *f;
00929 char *data;
00930 char *path = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
00931 sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
00932
00933 if (!(f = fopen(path, "r"))) {
00934 lua_pushstring(L, "cannot open '");
00935 lua_pushstring(L, path);
00936 lua_pushstring(L, "' for reading: ");
00937 lua_pushstring(L, strerror(errno));
00938 lua_concat(L, 4);
00939
00940 return NULL;
00941 }
00942
00943 fseek(f, 0l, SEEK_END);
00944 *size = ftell(f);
00945
00946 fseek(f, 0l, SEEK_SET);
00947
00948 if (!(data = ast_malloc(*size))) {
00949 *size = 0;
00950 fclose(f);
00951 lua_pushstring(L, "not enough memory");
00952 return NULL;
00953 }
00954
00955 if (fread(data, sizeof(char), *size, f) != *size) {
00956 ast_log(LOG_WARNING, "fread() failed: %s\n", strerror(errno));
00957 }
00958 fclose(f);
00959
00960 if (luaL_loadbuffer(L, data, *size, "extensions.lua")
00961 || lua_pcall(L, 0, LUA_MULTRET, 0)
00962 || lua_sort_extensions(L)
00963 || lua_register_switches(L)) {
00964 ast_free(data);
00965 data = NULL;
00966 *size = 0;
00967 }
00968 return data;
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 static int lua_load_extensions(lua_State *L, struct ast_channel *chan)
00984 {
00985
00986
00987 lua_pushlightuserdata(L, chan);
00988 lua_setfield(L, LUA_REGISTRYINDEX, "channel");
00989
00990 luaL_openlibs(L);
00991
00992
00993 ast_mutex_lock(&config_file_lock);
00994 if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
00995 || lua_pcall(L, 0, LUA_MULTRET, 0)
00996 || lua_sort_extensions(L)) {
00997 ast_mutex_unlock(&config_file_lock);
00998 return 1;
00999 }
01000 ast_mutex_unlock(&config_file_lock);
01001
01002
01003
01004 lua_create_app_table(L);
01005 lua_create_channel_table(L);
01006
01007 lua_create_variable_metatable(L);
01008 lua_create_application_metatable(L);
01009
01010 lua_create_autoservice_functions(L);
01011 lua_create_hangup_function(L);
01012
01013 return 0;
01014 }
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 static int lua_reload_extensions(lua_State *L)
01027 {
01028 long size = 0;
01029 char *data = NULL;
01030
01031 luaL_openlibs(L);
01032
01033 if (!(data = lua_read_extensions_file(L, &size))) {
01034 return 1;
01035 }
01036
01037 ast_mutex_lock(&config_file_lock);
01038
01039 if (config_file_data)
01040 ast_free(config_file_data);
01041
01042 config_file_data = data;
01043 config_file_size = size;
01044
01045
01046 ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
01047
01048
01049
01050
01051 local_table = NULL;
01052 local_contexts = NULL;
01053
01054 ast_mutex_unlock(&config_file_lock);
01055 return 0;
01056 }
01057
01058
01059
01060
01061 static void lua_free_extensions()
01062 {
01063 ast_mutex_lock(&config_file_lock);
01064 config_file_size = 0;
01065 ast_free(config_file_data);
01066 ast_mutex_unlock(&config_file_lock);
01067 }
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082 static lua_State *lua_get_state(struct ast_channel *chan)
01083 {
01084 struct ast_datastore *datastore = NULL;
01085 lua_State *L;
01086
01087 if (!chan) {
01088 lua_State *L = luaL_newstate();
01089 if (!L) {
01090 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01091 return NULL;
01092 }
01093
01094 if (lua_load_extensions(L, NULL)) {
01095 const char *error = lua_tostring(L, -1);
01096 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01097 lua_close(L);
01098 return NULL;
01099 }
01100 return L;
01101 } else {
01102 ast_channel_lock(chan);
01103 datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
01104 ast_channel_unlock(chan);
01105
01106 if (!datastore) {
01107
01108 datastore = ast_datastore_alloc(&lua_datastore, NULL);
01109 if (!datastore) {
01110 ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
01111 return NULL;
01112 }
01113
01114 datastore->data = luaL_newstate();
01115 if (!datastore->data) {
01116 ast_datastore_free(datastore);
01117 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01118 return NULL;
01119 }
01120
01121 ast_channel_lock(chan);
01122 ast_channel_datastore_add(chan, datastore);
01123 ast_channel_unlock(chan);
01124
01125 L = datastore->data;
01126
01127 if (lua_load_extensions(L, chan)) {
01128 const char *error = lua_tostring(L, -1);
01129 ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", chan->name, error);
01130
01131 ast_channel_lock(chan);
01132 ast_channel_datastore_remove(chan, datastore);
01133 ast_channel_unlock(chan);
01134
01135 ast_datastore_free(datastore);
01136 return NULL;
01137 }
01138 }
01139
01140 return datastore->data;
01141 }
01142 }
01143
01144 static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01145 {
01146 int res;
01147 lua_State *L;
01148 struct ast_module_user *u = ast_module_user_add(chan);
01149 if (!u) {
01150 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01151 return 0;
01152 }
01153
01154 L = lua_get_state(chan);
01155 if (!L) {
01156 ast_module_user_remove(u);
01157 return 0;
01158 }
01159
01160 res = lua_find_extension(L, context, exten, priority, &exists, 0);
01161
01162 if (!chan) lua_close(L);
01163 ast_module_user_remove(u);
01164 return res;
01165 }
01166
01167 static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01168 {
01169 int res;
01170 lua_State *L;
01171 struct ast_module_user *u = ast_module_user_add(chan);
01172 if (!u) {
01173 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01174 return 0;
01175 }
01176
01177 L = lua_get_state(chan);
01178 if (!L) {
01179 ast_module_user_remove(u);
01180 return 0;
01181 }
01182
01183 res = lua_find_extension(L, context, exten, priority, &canmatch, 0);
01184
01185 if (!chan) lua_close(L);
01186 ast_module_user_remove(u);
01187 return res;
01188 }
01189
01190 static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01191 {
01192 int res;
01193 lua_State *L;
01194 struct ast_module_user *u = ast_module_user_add(chan);
01195 if (!u) {
01196 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01197 return 0;
01198 }
01199
01200 L = lua_get_state(chan);
01201 if (!L) {
01202 ast_module_user_remove(u);
01203 return 0;
01204 }
01205
01206 res = lua_find_extension(L, context, exten, priority, &matchmore, 0);
01207
01208 if (!chan) lua_close(L);
01209 ast_module_user_remove(u);
01210 return res;
01211 }
01212
01213
01214 static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01215 {
01216 int res, error_func;
01217 lua_State *L;
01218 struct ast_module_user *u = ast_module_user_add(chan);
01219 if (!u) {
01220 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01221 return -1;
01222 }
01223
01224 L = lua_get_state(chan);
01225 if (!L) {
01226 ast_module_user_remove(u);
01227 return -1;
01228 }
01229
01230 lua_pushcfunction(L, &lua_error_function);
01231 error_func = lua_gettop(L);
01232
01233
01234 if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
01235 lua_pop(L, 1);
01236 ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
01237 if (!chan) lua_close(L);
01238 ast_module_user_remove(u);
01239 return -1;
01240 }
01241
01242 lua_update_registry(L, context, exten, priority);
01243
01244 lua_pushstring(L, context);
01245 lua_pushstring(L, exten);
01246
01247 res = lua_pcall(L, 2, 0, error_func);
01248 if (res) {
01249 if (res == LUA_ERRRUN) {
01250 res = -1;
01251 if (lua_isnumber(L, -1)) {
01252 res = lua_tointeger(L, -1);
01253 } else if (lua_isstring(L, -1)) {
01254 const char *error = lua_tostring(L, -1);
01255 ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
01256 }
01257 } else if (res == LUA_ERRERR) {
01258 res = -1;
01259 ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
01260 } else if (res == LUA_ERRMEM) {
01261 res = -1;
01262 ast_log(LOG_ERROR, "Memory allocation error\n");
01263 }
01264 lua_pop(L, 1);
01265 }
01266 lua_remove(L, error_func);
01267 if (!chan) lua_close(L);
01268 ast_module_user_remove(u);
01269 return res;
01270 }
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285 static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
01286 {
01287 int context_table, context_order_table, i;
01288
01289 ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
01290 if (priority != 1)
01291 return 0;
01292
01293
01294 lua_getglobal(L, "extensions");
01295 if (lua_isnil(L, -1)) {
01296 ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
01297 lua_pop(L, 1);
01298 return 0;
01299 }
01300
01301
01302 lua_getfield(L, -1, context);
01303 if (lua_isnil(L, -1)) {
01304 lua_pop(L, 2);
01305 return 0;
01306 }
01307
01308
01309 lua_remove(L, -2);
01310
01311 context_table = lua_gettop(L);
01312
01313
01314 lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
01315 lua_getfield(L, -1, context);
01316
01317 lua_remove(L, -2);
01318
01319 context_order_table = lua_gettop(L);
01320
01321
01322 for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
01323 int e_index, e_index_copy, match = 0;
01324 const char *e;
01325
01326 lua_pushinteger(L, i);
01327 lua_gettable(L, context_order_table);
01328 e_index = lua_gettop(L);
01329
01330
01331 lua_pushvalue(L, -1);
01332 e_index_copy = lua_gettop(L);
01333
01334 if (!(e = lua_tostring(L, e_index_copy))) {
01335 lua_pop(L, 2);
01336 continue;
01337 }
01338
01339
01340 if (!strcasecmp(e, "include")) {
01341 lua_pop(L, 2);
01342 continue;
01343 }
01344
01345 if (func == &matchmore)
01346 match = ast_extension_close(e, exten, E_MATCHMORE);
01347 else if (func == &canmatch)
01348 match = ast_extension_close(e, exten, E_CANMATCH);
01349 else
01350 match = ast_extension_match(e, exten);
01351
01352
01353
01354
01355 if (!match) {
01356
01357 lua_pop(L, 2);
01358 continue;
01359 }
01360
01361 if (func == &matchmore && match == 2) {
01362
01363
01364 lua_pop(L, 4);
01365 return 0;
01366 }
01367
01368
01369
01370
01371 if (push_func) {
01372 lua_pop(L, 1);
01373 lua_gettable(L, context_table);
01374 lua_insert(L, -3);
01375 lua_pop(L, 2);
01376 } else {
01377 lua_pop(L, 4);
01378 }
01379
01380 return 1;
01381 }
01382
01383
01384 lua_getfield(L, context_table, "include");
01385 if (lua_isnil(L, -1)) {
01386 lua_pop(L, 3);
01387 return 0;
01388 }
01389
01390
01391 lua_remove(L, context_order_table);
01392 lua_remove(L, context_table);
01393
01394
01395 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
01396 const char *c = lua_tostring(L, -1);
01397 if (!c)
01398 continue;
01399
01400 if (lua_find_extension(L, c, exten, priority, func, push_func)) {
01401
01402
01403
01404
01405 if (push_func)
01406 lua_insert(L, -4);
01407
01408 lua_pop(L, 3);
01409 return 1;
01410 }
01411 }
01412
01413
01414 lua_pop(L, 1);
01415 return 0;
01416 }
01417
01418 static struct ast_switch lua_switch = {
01419 .name = "Lua",
01420 .description = "Lua PBX Switch",
01421 .exists = exists,
01422 .canmatch = canmatch,
01423 .exec = exec,
01424 .matchmore = matchmore,
01425 };
01426
01427
01428 static int load_or_reload_lua_stuff(void)
01429 {
01430 int res = AST_MODULE_LOAD_SUCCESS;
01431
01432 lua_State *L = luaL_newstate();
01433 if (!L) {
01434 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01435 return AST_MODULE_LOAD_DECLINE;
01436 }
01437
01438 if (lua_reload_extensions(L)) {
01439 const char *error = lua_tostring(L, -1);
01440 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01441 res = AST_MODULE_LOAD_DECLINE;
01442 }
01443
01444 lua_close(L);
01445 return res;
01446 }
01447
01448 static int unload_module(void)
01449 {
01450 ast_context_destroy(NULL, registrar);
01451 ast_unregister_switch(&lua_switch);
01452 lua_free_extensions();
01453 return 0;
01454 }
01455
01456 static int reload(void)
01457 {
01458 return load_or_reload_lua_stuff();
01459 }
01460
01461 static int load_module(void)
01462 {
01463 int res;
01464
01465 if ((res = load_or_reload_lua_stuff()))
01466 return res;
01467
01468 if (ast_register_switch(&lua_switch)) {
01469 ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
01470 return AST_MODULE_LOAD_DECLINE;
01471 }
01472
01473 return AST_MODULE_LOAD_SUCCESS;
01474 }
01475
01476 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Lua PBX Switch",
01477 .load = load_module,
01478 .unload = unload_module,
01479 .reload = reload,
01480 );
01481