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