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