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