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