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: 341809 $")
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 = 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 = 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
00851 lua_pushinteger(L, lua_objlen(L, context_order) + 1);
00852 lua_pushvalue(L, exten);
00853 lua_settable(L, context_order);
00854 }
00855 lua_settable(L, extensions_order);
00856
00857
00858
00859
00860 lua_getglobal(L, "table");
00861 lua_getfield(L, -1, "sort");
00862 lua_remove(L, -2);
00863
00864
00865 lua_pushvalue(L, context_name);
00866 lua_gettable(L, extensions_order);
00867
00868
00869 lua_pushcfunction(L, &lua_extension_cmp);
00870
00871 if (lua_pcall(L, 2, 0, 0)) {
00872 lua_insert(L, -5);
00873 lua_pop(L, 4);
00874 return 1;
00875 }
00876 }
00877
00878
00879 lua_pop(L, 2);
00880 return 0;
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 static int lua_register_switches(lua_State *L)
00892 {
00893 int extensions;
00894 struct ast_context *con = NULL;
00895
00896
00897
00898 if (!local_table)
00899 local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
00900
00901
00902 lua_getglobal(L, "extensions");
00903 extensions = lua_gettop(L);
00904 if (lua_isnil(L, -1)) {
00905 lua_pop(L, 1);
00906 lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00907 return 1;
00908 }
00909
00910
00911
00912
00913 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00914 int context = lua_gettop(L);
00915 int context_name = context - 1;
00916 const char *context_str = lua_tostring(L, context_name);
00917
00918
00919 con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
00920 if (!con) {
00921
00922 lua_pop(L, 3);
00923 lua_pushstring(L, "Failed to find or create context\n");
00924 return 1;
00925 }
00926
00927
00928 if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
00929
00930 lua_pop(L, 3);
00931 lua_pushstring(L, "Unable to create switch for context\n");
00932 return 1;
00933 }
00934 }
00935
00936
00937 lua_pop(L, 1);
00938 return 0;
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 static int lua_extension_cmp(lua_State *L)
00950 {
00951 const char *a = luaL_checkstring(L, -2);
00952 const char *b = luaL_checkstring(L, -1);
00953
00954 if (ast_extension_cmp(a, b) == -1)
00955 lua_pushboolean(L, 1);
00956 else
00957 lua_pushboolean(L, 0);
00958
00959 return 1;
00960 }
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972 static char *lua_read_extensions_file(lua_State *L, long *size)
00973 {
00974 FILE *f;
00975 int error_func;
00976 char *data;
00977 char *path = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
00978 sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
00979
00980 if (!(f = fopen(path, "r"))) {
00981 lua_pushstring(L, "cannot open '");
00982 lua_pushstring(L, path);
00983 lua_pushstring(L, "' for reading: ");
00984 lua_pushstring(L, strerror(errno));
00985 lua_concat(L, 4);
00986
00987 return NULL;
00988 }
00989
00990 if (fseek(f, 0l, SEEK_END)) {
00991 fclose(f);
00992 lua_pushliteral(L, "error determining the size of the config file");
00993 return NULL;
00994 }
00995
00996 *size = ftell(f);
00997
00998 if (fseek(f, 0l, SEEK_SET)) {
00999 *size = 0;
01000 fclose(f);
01001 lua_pushliteral(L, "error reading config file");
01002 return NULL;
01003 }
01004
01005 if (!(data = ast_malloc(*size))) {
01006 *size = 0;
01007 fclose(f);
01008 lua_pushstring(L, "not enough memory");
01009 return NULL;
01010 }
01011
01012 if (fread(data, sizeof(char), *size, f) != *size) {
01013 *size = 0;
01014 fclose(f);
01015 lua_pushliteral(L, "problem reading configuration file");
01016 return NULL;
01017 }
01018 fclose(f);
01019
01020 lua_pushcfunction(L, &lua_error_function);
01021 error_func = lua_gettop(L);
01022
01023 if (luaL_loadbuffer(L, data, *size, "extensions.lua")
01024 || lua_pcall(L, 0, LUA_MULTRET, error_func)
01025 || lua_sort_extensions(L)
01026 || lua_register_switches(L)) {
01027 ast_free(data);
01028 data = NULL;
01029 *size = 0;
01030 }
01031
01032 lua_remove(L, error_func);
01033 return data;
01034 }
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048 static int lua_load_extensions(lua_State *L, struct ast_channel *chan)
01049 {
01050
01051
01052 lua_pushlightuserdata(L, chan);
01053 lua_setfield(L, LUA_REGISTRYINDEX, "channel");
01054
01055 luaL_openlibs(L);
01056
01057
01058 ast_mutex_lock(&config_file_lock);
01059 if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
01060 || lua_pcall(L, 0, LUA_MULTRET, 0)
01061 || lua_sort_extensions(L)) {
01062 ast_mutex_unlock(&config_file_lock);
01063 return 1;
01064 }
01065 ast_mutex_unlock(&config_file_lock);
01066
01067
01068
01069 lua_create_app_table(L);
01070 lua_create_channel_table(L);
01071
01072 lua_create_variable_metatable(L);
01073 lua_create_application_metatable(L);
01074
01075 lua_create_autoservice_functions(L);
01076 lua_create_hangup_function(L);
01077
01078 return 0;
01079 }
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 static int lua_reload_extensions(lua_State *L)
01092 {
01093 long size = 0;
01094 char *data = NULL;
01095
01096 luaL_openlibs(L);
01097
01098 if (!(data = lua_read_extensions_file(L, &size))) {
01099 return 1;
01100 }
01101
01102 ast_mutex_lock(&config_file_lock);
01103
01104 if (config_file_data)
01105 ast_free(config_file_data);
01106
01107 config_file_data = data;
01108 config_file_size = size;
01109
01110
01111 ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
01112
01113
01114
01115
01116 local_table = NULL;
01117 local_contexts = NULL;
01118
01119 ast_mutex_unlock(&config_file_lock);
01120 return 0;
01121 }
01122
01123
01124
01125
01126 static void lua_free_extensions()
01127 {
01128 ast_mutex_lock(&config_file_lock);
01129 config_file_size = 0;
01130 ast_free(config_file_data);
01131 ast_mutex_unlock(&config_file_lock);
01132 }
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147 static lua_State *lua_get_state(struct ast_channel *chan)
01148 {
01149 struct ast_datastore *datastore = NULL;
01150 lua_State *L;
01151
01152 if (!chan) {
01153 lua_State *L = luaL_newstate();
01154 if (!L) {
01155 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01156 return NULL;
01157 }
01158
01159 if (lua_load_extensions(L, NULL)) {
01160 const char *error = lua_tostring(L, -1);
01161 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01162 lua_close(L);
01163 return NULL;
01164 }
01165 return L;
01166 } else {
01167 ast_channel_lock(chan);
01168 datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
01169 ast_channel_unlock(chan);
01170
01171 if (!datastore) {
01172
01173 datastore = ast_datastore_alloc(&lua_datastore, NULL);
01174 if (!datastore) {
01175 ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
01176 return NULL;
01177 }
01178
01179 datastore->data = luaL_newstate();
01180 if (!datastore->data) {
01181 ast_datastore_free(datastore);
01182 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01183 return NULL;
01184 }
01185
01186 ast_channel_lock(chan);
01187 ast_channel_datastore_add(chan, datastore);
01188 ast_channel_unlock(chan);
01189
01190 L = datastore->data;
01191
01192 if (lua_load_extensions(L, chan)) {
01193 const char *error = lua_tostring(L, -1);
01194 ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", chan->name, error);
01195
01196 ast_channel_lock(chan);
01197 ast_channel_datastore_remove(chan, datastore);
01198 ast_channel_unlock(chan);
01199
01200 ast_datastore_free(datastore);
01201 return NULL;
01202 }
01203 }
01204
01205 return datastore->data;
01206 }
01207 }
01208
01209 static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01210 {
01211 int res;
01212 lua_State *L;
01213 struct ast_module_user *u = ast_module_user_add(chan);
01214 if (!u) {
01215 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01216 return 0;
01217 }
01218
01219 L = lua_get_state(chan);
01220 if (!L) {
01221 ast_module_user_remove(u);
01222 return 0;
01223 }
01224
01225 res = lua_find_extension(L, context, exten, priority, &exists, 0);
01226
01227 if (!chan) lua_close(L);
01228 ast_module_user_remove(u);
01229 return res;
01230 }
01231
01232 static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01233 {
01234 int res;
01235 lua_State *L;
01236 struct ast_module_user *u = ast_module_user_add(chan);
01237 if (!u) {
01238 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01239 return 0;
01240 }
01241
01242 L = lua_get_state(chan);
01243 if (!L) {
01244 ast_module_user_remove(u);
01245 return 0;
01246 }
01247
01248 res = lua_find_extension(L, context, exten, priority, &canmatch, 0);
01249
01250 if (!chan) lua_close(L);
01251 ast_module_user_remove(u);
01252 return res;
01253 }
01254
01255 static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01256 {
01257 int res;
01258 lua_State *L;
01259 struct ast_module_user *u = ast_module_user_add(chan);
01260 if (!u) {
01261 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01262 return 0;
01263 }
01264
01265 L = lua_get_state(chan);
01266 if (!L) {
01267 ast_module_user_remove(u);
01268 return 0;
01269 }
01270
01271 res = lua_find_extension(L, context, exten, priority, &matchmore, 0);
01272
01273 if (!chan) lua_close(L);
01274 ast_module_user_remove(u);
01275 return res;
01276 }
01277
01278
01279 static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01280 {
01281 int res, error_func;
01282 lua_State *L;
01283 struct ast_module_user *u = ast_module_user_add(chan);
01284 if (!u) {
01285 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01286 return -1;
01287 }
01288
01289 L = lua_get_state(chan);
01290 if (!L) {
01291 ast_module_user_remove(u);
01292 return -1;
01293 }
01294
01295 lua_pushcfunction(L, &lua_error_function);
01296 error_func = lua_gettop(L);
01297
01298
01299 if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
01300 lua_pop(L, 1);
01301 ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
01302 if (!chan) lua_close(L);
01303 ast_module_user_remove(u);
01304 return -1;
01305 }
01306
01307 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
01308 if (lua_toboolean(L, -1)) {
01309 ast_autoservice_start(chan);
01310 }
01311 lua_pop(L, 1);
01312
01313 lua_update_registry(L, context, exten, priority);
01314
01315 lua_pushstring(L, context);
01316 lua_pushstring(L, exten);
01317
01318 res = lua_pcall(L, 2, 0, error_func);
01319 if (res) {
01320 if (res == LUA_ERRRUN) {
01321 res = -1;
01322 if (lua_isnumber(L, -1)) {
01323 res = lua_tointeger(L, -1);
01324 } else if (lua_isstring(L, -1)) {
01325 const char *error = lua_tostring(L, -1);
01326 ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
01327 }
01328 } else if (res == LUA_ERRERR) {
01329 res = -1;
01330 ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
01331 } else if (res == LUA_ERRMEM) {
01332 res = -1;
01333 ast_log(LOG_ERROR, "Memory allocation error\n");
01334 }
01335 lua_pop(L, 1);
01336 }
01337 lua_remove(L, error_func);
01338
01339 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
01340 if (lua_toboolean(L, -1)) {
01341 ast_autoservice_stop(chan);
01342 }
01343 lua_pop(L, 1);
01344
01345 if (!chan) lua_close(L);
01346 ast_module_user_remove(u);
01347 return res;
01348 }
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363 static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
01364 {
01365 int context_table, context_order_table, i;
01366
01367 ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
01368 if (priority != 1)
01369 return 0;
01370
01371
01372 lua_getglobal(L, "extensions");
01373 if (lua_isnil(L, -1)) {
01374 ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
01375 lua_pop(L, 1);
01376 return 0;
01377 }
01378
01379
01380 lua_getfield(L, -1, context);
01381 if (lua_isnil(L, -1)) {
01382 lua_pop(L, 2);
01383 return 0;
01384 }
01385
01386
01387 lua_remove(L, -2);
01388
01389 context_table = lua_gettop(L);
01390
01391
01392 lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
01393 lua_getfield(L, -1, context);
01394
01395 lua_remove(L, -2);
01396
01397 context_order_table = lua_gettop(L);
01398
01399
01400 for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
01401 int e_index_copy, match = 0;
01402 const char *e;
01403
01404 lua_pushinteger(L, i);
01405 lua_gettable(L, context_order_table);
01406 lua_gettop(L);
01407
01408
01409 lua_pushvalue(L, -1);
01410 e_index_copy = lua_gettop(L);
01411
01412 if (!(e = lua_tostring(L, e_index_copy))) {
01413 lua_pop(L, 2);
01414 continue;
01415 }
01416
01417
01418 if (!strcasecmp(e, "include")) {
01419 lua_pop(L, 2);
01420 continue;
01421 }
01422
01423 if (func == &matchmore)
01424 match = ast_extension_close(e, exten, E_MATCHMORE);
01425 else if (func == &canmatch)
01426 match = ast_extension_close(e, exten, E_CANMATCH);
01427 else
01428 match = ast_extension_match(e, exten);
01429
01430
01431
01432
01433 if (!match) {
01434
01435 lua_pop(L, 2);
01436 continue;
01437 }
01438
01439 if (func == &matchmore && match == 2) {
01440
01441
01442 lua_pop(L, 4);
01443 return 0;
01444 }
01445
01446
01447
01448
01449 if (push_func) {
01450 lua_pop(L, 1);
01451 lua_gettable(L, context_table);
01452 lua_insert(L, -3);
01453 lua_pop(L, 2);
01454 } else {
01455 lua_pop(L, 4);
01456 }
01457
01458 return 1;
01459 }
01460
01461
01462 lua_getfield(L, context_table, "include");
01463 if (lua_isnil(L, -1)) {
01464 lua_pop(L, 3);
01465 return 0;
01466 }
01467
01468
01469 lua_remove(L, context_order_table);
01470 lua_remove(L, context_table);
01471
01472
01473 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
01474 const char *c = lua_tostring(L, -1);
01475 if (!c)
01476 continue;
01477
01478 if (lua_find_extension(L, c, exten, priority, func, push_func)) {
01479
01480
01481
01482
01483 if (push_func)
01484 lua_insert(L, -4);
01485
01486 lua_pop(L, 3);
01487 return 1;
01488 }
01489 }
01490
01491
01492 lua_pop(L, 1);
01493 return 0;
01494 }
01495
01496 static struct ast_switch lua_switch = {
01497 .name = "Lua",
01498 .description = "Lua PBX Switch",
01499 .exists = exists,
01500 .canmatch = canmatch,
01501 .exec = exec,
01502 .matchmore = matchmore,
01503 };
01504
01505
01506 static int load_or_reload_lua_stuff(void)
01507 {
01508 int res = AST_MODULE_LOAD_SUCCESS;
01509
01510 lua_State *L = luaL_newstate();
01511 if (!L) {
01512 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01513 return AST_MODULE_LOAD_DECLINE;
01514 }
01515
01516 if (lua_reload_extensions(L)) {
01517 const char *error = lua_tostring(L, -1);
01518 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01519 res = AST_MODULE_LOAD_DECLINE;
01520 }
01521
01522 lua_close(L);
01523 return res;
01524 }
01525
01526 static int unload_module(void)
01527 {
01528 ast_context_destroy(NULL, registrar);
01529 ast_unregister_switch(&lua_switch);
01530 lua_free_extensions();
01531 return 0;
01532 }
01533
01534 static int reload(void)
01535 {
01536 return load_or_reload_lua_stuff();
01537 }
01538
01539 static int load_module(void)
01540 {
01541 int res;
01542
01543 if ((res = load_or_reload_lua_stuff()))
01544 return res;
01545
01546 if (ast_register_switch(&lua_switch)) {
01547 ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
01548 return AST_MODULE_LOAD_DECLINE;
01549 }
01550
01551 return AST_MODULE_LOAD_SUCCESS;
01552 }
01553
01554 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Lua PBX Switch",
01555 .load = load_module,
01556 .unload = unload_module,
01557 .reload = reload,
01558 );
01559