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