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