68e079d648767bfa7ae8341e448cd63cc4b82f6c
[sip-router] / src / modules / app_lua / app_lua_api.c
1 /**
2  * Copyright (C) 2010-2016 Daniel-Constantin Mierla (asipto.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <sys/stat.h>
26
27 #include "../../core/sr_module.h"
28 #include "../../core/dprint.h"
29 #include "../../core/ut.h"
30 #include "../../core/mem/mem.h"
31 #include "../../core/locking.h"
32 #include "../../core/data_lump.h"
33 #include "../../core/data_lump_rpl.h"
34 #include "../../core/strutils.h"
35
36 #include "app_lua_api.h"
37 #include "app_lua_sr.h"
38 #include "app_lua_exp.h"
39
40
41 #define SRVERSION "1.0"
42
43 /**
44  * reload enabled param
45  * default: 0 (off)
46  */
47 static unsigned int _app_lua_sr_reload = 1;
48 /**
49  *
50  */
51 static sr_lua_env_t _sr_L_env;
52
53 /**
54  *
55  */
56 static int *_app_lua_sv = NULL;
57
58 /**
59  * @return the static Lua env
60  */
61 sr_lua_env_t *sr_lua_env_get(void)
62 {
63         return &_sr_L_env;
64 }
65
66 /**
67  *
68  */
69 static sr_lua_load_t *_sr_lua_load_list = NULL;
70 /**
71  * set of locks to manage the shared variable.
72  */
73 static gen_lock_set_t *sr_lua_locks = NULL;
74 static sr_lua_script_ver_t *sr_lua_script_ver = NULL;
75
76
77 int lua_sr_alloc_script_ver(void)
78 {
79         int size = _sr_L_env.nload;
80
81         sr_lua_script_ver = (sr_lua_script_ver_t *) shm_malloc(sizeof(sr_lua_script_ver_t));
82         if(sr_lua_script_ver==NULL)
83         {
84                 SHM_MEM_ERROR;
85                 return -1;
86         }
87
88         sr_lua_script_ver->version = (unsigned int *) shm_malloc(sizeof(unsigned int)*size);
89         if(sr_lua_script_ver->version==NULL)
90         {
91                 SHM_MEM_ERROR;
92                 goto error;
93         }
94         memset(sr_lua_script_ver->version, 0, sizeof(unsigned int)*size);
95         sr_lua_script_ver->len = size;
96
97         if((sr_lua_locks=lock_set_alloc(size))==0)
98         {
99                 LM_CRIT("failed to alloc lock set\n");
100                 goto error;
101         }
102         if(lock_set_init(sr_lua_locks)==0 )
103         {
104                 LM_CRIT("failed to init lock set\n");
105                 goto error;
106         }
107
108         return 0;
109 error:
110         if(sr_lua_script_ver!=NULL)
111         {
112                 if(sr_lua_script_ver->version!=NULL)
113                 {
114                         shm_free(sr_lua_script_ver->version);
115                         sr_lua_script_ver->version = NULL;
116                 }
117                 shm_free(sr_lua_script_ver);
118                 sr_lua_script_ver = NULL;
119         }
120         if(sr_lua_locks!=NULL)
121         {
122                 lock_set_destroy( sr_lua_locks );
123                 lock_set_dealloc( sr_lua_locks );
124                 sr_lua_locks = NULL;
125         }
126         return -1;
127 }
128
129 /**
130  *
131  */
132 int sr_lua_load_script(char *script)
133 {
134         sr_lua_load_t *li;
135
136         li = (sr_lua_load_t*)pkg_malloc(sizeof(sr_lua_load_t));
137         if(li==NULL)
138         {
139                 PKG_MEM_ERROR;
140                 return -1;
141         }
142         memset(li, 0, sizeof(sr_lua_load_t));
143         li->script = script;
144         li->version = 0;
145         li->next = _sr_lua_load_list;
146         _sr_lua_load_list = li;
147         _sr_L_env.nload += 1;
148         LM_DBG("loaded script:[%s].\n", script);
149         LM_DBG("Now there are %d scripts loaded\n", _sr_L_env.nload);
150
151         return 0;
152 }
153
154
155 /**
156  *
157  */
158 int sr_lua_register_module(char *mname)
159 {
160         if(lua_sr_exp_register_mod(mname)==0)
161                 return 0;
162         return -1;
163 }
164
165 /**
166  *
167  */
168 int sr_lua_reload_module(unsigned int reload)
169 {
170         LM_DBG("reload:%d\n", reload);
171         if(reload!=0) {
172                 _app_lua_sr_reload = 1;
173                 LM_DBG("reload param activated!\n");
174         }
175         return 0;
176 }
177
178 /**
179  *
180  */
181 void lua_sr_openlibs(lua_State *L)
182 {
183         lua_sr_core_openlibs(L);
184         lua_sr_exp_openlibs(L);
185         lua_sr_kemi_register_libs(L);
186 }
187
188 /**
189  *
190  */
191 int lua_sr_init_mod(void)
192 {
193         /* allocate shm */
194         if(lua_sr_alloc_script_ver()<0)
195         {
196                 LM_CRIT("failed to alloc shm for version\n");
197                 return -1;
198         }
199
200         memset(&_sr_L_env, 0, sizeof(sr_lua_env_t));
201         if(lua_sr_exp_init_mod()<0)
202                 return -1;
203
204         return 0;
205
206 }
207
208 /**
209  *
210  */
211 int lua_sr_init_probe(void)
212 {
213         lua_State *L;
214         char *txt;
215         sr_lua_load_t *li;
216         struct stat sbuf;
217
218         L = luaL_newstate();
219         if(L==NULL)
220         {
221                 LM_ERR("cannot open lua\n");
222                 return -1;
223         }
224         luaL_openlibs(L);
225         lua_sr_openlibs(L);
226
227         /* force loading lua lib now */
228         if(luaL_dostring(L, "sr.probe()")!=0)
229         {
230                 txt = (char*)lua_tostring(L, -1);
231                 LM_ERR("error initializing Lua: %s\n", (txt)?txt:"unknown");
232                 lua_pop(L, 1);
233                 lua_close(L);
234                 return -1;
235         }
236
237         /* test if files to be loaded exist */
238         if(_sr_lua_load_list != NULL)
239         {
240                 li = _sr_lua_load_list;
241                 while(li)
242                 {
243                         if(stat(li->script, &sbuf)!=0)
244                         {
245                                 /* file does not exist */
246                                 LM_ERR("cannot find script: %s (wrong path?)\n",
247                                                 li->script);
248                                 lua_close(L);
249                                 return -1;
250                         }
251                         li = li->next;
252                 }
253         }
254         lua_close(L);
255         LM_DBG("Lua probe was ok!\n");
256         return 0;
257 }
258
259 /**
260  *
261  */
262 int lua_sr_init_child(void)
263 {
264         sr_lua_load_t *li;
265         int ret;
266         char *txt;
267
268         memset(&_sr_L_env, 0, sizeof(sr_lua_env_t));
269         _sr_L_env.L = luaL_newstate();
270         if(_sr_L_env.L==NULL)
271         {
272                 LM_ERR("cannot open lua\n");
273                 return -1;
274         }
275         luaL_openlibs(_sr_L_env.L);
276         lua_sr_openlibs(_sr_L_env.L);
277
278         /* set SR lib version */
279 #if LUA_VERSION_NUM >= 502
280         lua_pushstring(_sr_L_env.L, SRVERSION);
281         lua_setglobal(_sr_L_env.L, "SRVERSION");
282 #else
283         lua_pushstring(_sr_L_env.L, "SRVERSION");
284         lua_pushstring(_sr_L_env.L, SRVERSION);
285         lua_settable(_sr_L_env.L, LUA_GLOBALSINDEX);
286 #endif
287         if(_sr_lua_load_list != NULL)
288         {
289                 _sr_L_env.LL = luaL_newstate();
290                 if(_sr_L_env.LL==NULL)
291                 {
292                         LM_ERR("cannot open lua loading state\n");
293                         return -1;
294                 }
295                 luaL_openlibs(_sr_L_env.LL);
296                 lua_sr_openlibs(_sr_L_env.LL);
297
298                 /* set SR lib version */
299 #if LUA_VERSION_NUM >= 502
300                 lua_pushstring(_sr_L_env.LL, SRVERSION);
301                 lua_setglobal(_sr_L_env.LL, "SRVERSION");
302 #else
303                 lua_pushstring(_sr_L_env.LL, "SRVERSION");
304                 lua_pushstring(_sr_L_env.LL, SRVERSION);
305                 lua_settable(_sr_L_env.LL, LUA_GLOBALSINDEX);
306 #endif
307                 /* force loading lua lib now */
308                 if(luaL_dostring(_sr_L_env.LL, "sr.probe()")!=0)
309                 {
310                         txt = (char*)lua_tostring(_sr_L_env.LL, -1);
311                         LM_ERR("error initializing Lua: %s\n", (txt)?txt:"unknown");
312                         lua_pop(_sr_L_env.LL, 1);
313                         lua_sr_destroy();
314                         return -1;
315                 }
316
317                 li = _sr_lua_load_list;
318                 while(li)
319                 {
320                         ret = luaL_dofile(_sr_L_env.LL, (const char*)li->script);
321                         if(ret!=0)
322                         {
323                                 LM_ERR("failed to load Lua script: %s (err: %d)\n",
324                                                 li->script, ret);
325                                 txt = (char*)lua_tostring(_sr_L_env.LL, -1);
326                                 LM_ERR("error from Lua: %s\n", (txt)?txt:"unknown");
327                                 lua_pop(_sr_L_env.LL, 1);
328                                 lua_sr_destroy();
329                                 return -1;
330                         }
331                         li = li->next;
332                 }
333         }
334         LM_DBG("Lua initialized!\n");
335         return 0;
336 }
337
338 /**
339  *
340  */
341 void lua_sr_destroy(void)
342 {
343         if(_sr_L_env.L!=NULL)
344         {
345                 lua_close(_sr_L_env.L);
346                 _sr_L_env.L = NULL;
347         }
348         if(_sr_L_env.LL!=NULL)
349         {
350                 lua_close(_sr_L_env.LL);
351                 _sr_L_env.LL = NULL;
352         }
353         memset(&_sr_L_env, 0, sizeof(sr_lua_env_t));
354
355         if(sr_lua_script_ver!=NULL)
356         {
357                 shm_free(sr_lua_script_ver->version);
358                 shm_free(sr_lua_script_ver);
359         }
360
361         if (sr_lua_locks!=NULL)
362         {
363                 lock_set_destroy( sr_lua_locks );
364                 lock_set_dealloc( sr_lua_locks );
365                 sr_lua_locks = 0;
366         }
367
368         if(_app_lua_sv!=NULL) {
369                 pkg_free(_app_lua_sv);
370                 _app_lua_sv = 0;
371         }
372 }
373
374 /**
375  *
376  */
377 int lua_sr_list_script(sr_lua_load_t **list)
378 {
379         *list = _sr_lua_load_list;
380         return 0;
381 }
382
383 /**
384  * Mark script in pos to be reloaded
385  * pos -1: reload all scritps
386  */
387 int lua_sr_reload_script(int pos)
388 {
389         int i, len = sr_lua_script_ver->len;
390         if(_sr_lua_load_list!= NULL)
391         {
392                 if (!sr_lua_script_ver)
393                 {
394                         LM_CRIT("shm for version not allocated\n");
395                         return -1;
396                 }
397                 if (_app_lua_sr_reload==0)
398                 {
399                         LM_ERR("reload is not activated\n");
400                         return -3;
401                 }
402                 if (pos<0)
403                 {
404                         // let's mark all the scripts to be reloaded
405                         for (i=0;i<len;i++)
406                         {
407                                 lock_set_get(sr_lua_locks, i);
408                                 sr_lua_script_ver->version[i] += 1;
409                                 lock_set_release(sr_lua_locks, i);
410                         }
411                 }
412                 else
413                 {
414                         if (pos>=0 && pos<len)
415                         {
416                                 lock_set_get(sr_lua_locks, pos);
417                                 sr_lua_script_ver->version[pos] += 1;
418                                 lock_set_release(sr_lua_locks, pos);
419                                 LM_DBG("pos: %d set to reloaded\n", pos);
420                         }
421                         else
422                         {
423                                 LM_ERR("pos out of range\n");
424                                 return -2;
425                         }
426                 }
427                 return 0;
428         }
429         LM_ERR("No script loaded\n");
430         return -1;
431 }
432
433 /**
434  * Checks if loaded version matches the shared
435  * counter. If not equal reloads the script.
436  */
437 int sr_lua_reload_script(void)
438 {
439         sr_lua_load_t *li = _sr_lua_load_list;
440         int ret, i;
441         char *txt;
442         int sv_len = sr_lua_script_ver->len;
443
444         if(li==NULL)
445         {
446                 LM_DBG("No script loaded\n");
447                 return 0;
448         }
449
450         if(_app_lua_sv==NULL) {
451                 _app_lua_sv = (int *) pkg_malloc(sizeof(int)*sv_len);
452                 if(_app_lua_sv==NULL)
453                 {
454                         PKG_MEM_ERROR;
455                         return -1;
456                 }
457         }
458
459         for(i=0;i<sv_len;i++)
460         {
461                 lock_set_get(sr_lua_locks, i);
462                 _app_lua_sv[i] = sr_lua_script_ver->version[i];
463                 lock_set_release(sr_lua_locks, i);
464
465                 if(li->version!=_app_lua_sv[i])
466                 {
467                         LM_DBG("loaded version:%d needed: %d Let's reload <%s>\n",
468                                 li->version, _app_lua_sv[i], li->script);
469                         ret = luaL_dofile(_sr_L_env.LL, (const char*)li->script);
470                         if(ret!=0)
471                         {
472                                 LM_ERR("failed to load Lua script: %s (err: %d)\n",
473                                                 li->script, ret);
474                                 txt = (char*)lua_tostring(_sr_L_env.LL, -1);
475                                 LM_ERR("error from Lua: %s\n", (txt)?txt:"unknown");
476                                 lua_pop(_sr_L_env.LL, 1);
477                                 return -1;
478                         }
479                         li->version = _app_lua_sv[i];
480                         LM_DBG("<%s> set to version %d\n", li->script, li->version);
481                 }
482                 else LM_DBG("No need to reload [%s] is version %d\n",
483                         li->script, li->version);
484                 li = li->next;
485         }
486         return 1;
487 }
488
489 /**
490  *
491  */
492 int lua_sr_initialized(void)
493 {
494         if(_sr_L_env.L==NULL)
495                 return 0;
496
497         return 1;
498 }
499
500 /**
501  *
502  */
503 int app_lua_return_int(lua_State *L, int v)
504 {
505         lua_pushinteger(L, v);
506         return 1;
507 }
508
509 /**
510  *
511  */
512 int app_lua_return_error(lua_State *L)
513 {
514         lua_pushinteger(L, -1);
515         return 1;
516 }
517
518 /**
519  *
520  */
521 int app_lua_return_boolean(lua_State *L, int b)
522 {
523         if(b==SRLUA_FALSE)
524                 lua_pushboolean(L, SRLUA_FALSE);
525         else
526                 lua_pushboolean(L, SRLUA_TRUE);
527         return 1;
528 }
529
530 /**
531  *
532  */
533 int app_lua_return_false(lua_State *L)
534 {
535         lua_pushboolean(L, SRLUA_FALSE);
536         return 1;
537 }
538
539 /**
540  *
541  */
542 int app_lua_return_true(lua_State *L)
543 {
544         lua_pushboolean(L, SRLUA_TRUE);
545         return 1;
546 }
547
548 /**
549  *
550  */
551 int app_lua_dostring(sip_msg_t *msg, char *script)
552 {
553         int ret;
554         char *txt;
555         sip_msg_t *bmsg;
556
557         LM_DBG("executing Lua string: [[%s]]\n", script);
558         LM_DBG("lua top index is: %d\n", lua_gettop(_sr_L_env.L));
559         bmsg = _sr_L_env.msg;
560         _sr_L_env.msg = msg;
561         ret = luaL_dostring(_sr_L_env.L, script);
562         if(ret!=0)
563         {
564                 txt = (char*)lua_tostring(_sr_L_env.L, -1);
565                 LM_ERR("error from Lua: %s\n", (txt)?txt:"unknown");
566                 lua_pop (_sr_L_env.L, 1);
567         }
568         _sr_L_env.msg = bmsg;
569         return (ret==0)?1:-1;
570 }
571
572 /**
573  *
574  */
575 int app_lua_dofile(sip_msg_t *msg, char *script)
576 {
577         int ret;
578         char *txt;
579         sip_msg_t *bmsg;
580
581         LM_DBG("executing Lua file: [[%s]]\n", script);
582         LM_DBG("lua top index is: %d\n", lua_gettop(_sr_L_env.L));
583         bmsg = _sr_L_env.msg;
584         _sr_L_env.msg = msg;
585         ret = luaL_dofile(_sr_L_env.L, script);
586         if(ret!=0)
587         {
588                 txt = (char*)lua_tostring(_sr_L_env.L, -1);
589                 LM_ERR("error from Lua: %s\n", (txt)?txt:"unknown");
590                 lua_pop(_sr_L_env.L, 1);
591         }
592         _sr_L_env.msg = bmsg;
593         return (ret==0)?1:-1;
594 }
595
596 /**
597  *
598  */
599 int app_lua_runstring(sip_msg_t *msg, char *script)
600 {
601         int ret;
602         char *txt;
603         sip_msg_t *bmsg;
604
605         if(_sr_L_env.LL==NULL)
606         {
607                 LM_ERR("lua loading state not initialized (call: %s)\n", script);
608                 return -1;
609         }
610
611         LM_DBG("running Lua string: [[%s]]\n", script);
612         LM_DBG("lua top index is: %d\n", lua_gettop(_sr_L_env.LL));
613         bmsg = _sr_L_env.msg;
614         _sr_L_env.msg = msg;
615         ret = luaL_dostring(_sr_L_env.LL, script);
616         if(ret!=0)
617         {
618                 txt = (char*)lua_tostring(_sr_L_env.LL, -1);
619                 LM_ERR("error from Lua: %s\n", (txt)?txt:"unknown");
620                 lua_pop (_sr_L_env.LL, 1);
621         }
622         _sr_L_env.msg = bmsg;
623         return (ret==0)?1:-1;
624 }
625
626 /**
627  *
628  */
629 static str _sr_kemi_lua_exit_string = str_init("~~ksr~exit~~");
630
631 /**
632  *
633  */
634 str* sr_kemi_lua_exit_string_get(void)
635 {
636         return &_sr_kemi_lua_exit_string;
637 }
638
639 /**
640  *
641  */
642 int app_lua_run_ex(sip_msg_t *msg, char *func, char *p1, char *p2,
643                 char *p3, int emode)
644 {
645         int n;
646         int ret;
647         str txt;
648         sip_msg_t *bmsg;
649         int ltop;
650
651         if(_sr_L_env.LL==NULL)
652         {
653                 LM_ERR("lua loading state not initialized (call: %s)\n", func);
654                 return -1;
655         }
656         if(_app_lua_sr_reload!=0)
657         {
658                 /* check the script version loaded */
659                 if(!sr_lua_reload_script())
660                 {
661                         LM_ERR("lua reload failed\n");
662                         return -1;
663                 }
664         }
665         else LM_DBG("reload deactivated\n");
666         LM_DBG("executing Lua function: [[%s]]\n", func);
667         ltop = lua_gettop(_sr_L_env.LL);
668         LM_DBG("lua top index is: %d\n", ltop);
669         lua_getglobal(_sr_L_env.LL, func);
670         if(!lua_isfunction(_sr_L_env.LL, -1))
671         {
672                 if(emode) {
673                         LM_ERR("no such function [%s] in lua scripts\n", func);
674                         LM_ERR("top stack type [%d - %s]\n",
675                                 lua_type(_sr_L_env.LL, -1),
676                                 lua_typename(_sr_L_env.LL,lua_type(_sr_L_env.LL, -1)));
677                         txt.s = (char*)lua_tostring(_sr_L_env.LL, -1);
678                         LM_ERR("error from Lua: %s\n", (txt.s)?txt.s:"unknown");
679                         /* restores the original stack size */
680                         lua_settop(_sr_L_env.LL, ltop);
681                         return -1;
682                 } else {
683                         /* restores the original stack size */
684                         lua_settop(_sr_L_env.LL, ltop);
685                         return 1;
686                 }
687         }
688         n = 0;
689         if(p1!=NULL)
690         {
691                 lua_pushstring(_sr_L_env.LL, p1);
692                 n++;
693                 if(p2!=NULL)
694                 {
695                         lua_pushstring(_sr_L_env.LL, p2);
696                         n++;
697                         if(p3!=NULL)
698                         {
699                                 lua_pushstring(_sr_L_env.LL, p3);
700                                 n++;
701                         }
702                 }
703         }
704         bmsg = _sr_L_env.msg;
705         _sr_L_env.msg = msg;
706         ret = lua_pcall(_sr_L_env.LL, n, 0, 0);
707         _sr_L_env.msg = bmsg;
708         if(ret!=0)
709         {
710                 txt.s = (char*)lua_tostring(_sr_L_env.LL, -1);
711                 n = 0;
712                 if(txt.s!=NULL) {
713                         for(n=0; txt.s[n]!='\0' && _sr_kemi_lua_exit_string.s[n]!='\0';
714                                         n++) {
715                                 if(txt.s[n] != _sr_kemi_lua_exit_string.s[n])
716                                         break;
717                         }
718                         if(txt.s[n]!='\0' || _sr_kemi_lua_exit_string.s[n]!='\0') {
719                                 LM_ERR("error from Lua: %s\n", txt.s);
720                                 n = 0;
721                         } else {
722                                 LM_DBG("ksr error call from Lua: %s\n", txt.s);
723                                 n = 1;
724                         }
725                 } else {
726                         LM_ERR("error from Lua: unknown\n");
727                 }
728                 lua_pop(_sr_L_env.LL, 1);
729                 if(n==1) {
730                         /* restores the original stack size */
731                         lua_settop(_sr_L_env.LL, ltop);
732                         return 1;
733                 } else {
734                         LM_ERR("error executing: %s (err: %d)\n", func, ret);
735                         /* restores the original stack size */
736                         lua_settop(_sr_L_env.LL, ltop);
737                         return -1;
738                 }
739         }
740
741         /* restores the original stack size */
742         lua_settop(_sr_L_env.LL, ltop);
743
744         return 1;
745 }
746
747 /**
748  *
749  */
750 int app_lua_run(sip_msg_t *msg, char *func, char *p1, char *p2,
751                 char *p3)
752 {
753         return app_lua_run_ex(msg, func, p1, p2, p3, 1);
754 }
755
756 void app_lua_dump_stack(lua_State *L)
757 {
758         int i;
759         int t;
760         int top;
761
762         top = lua_gettop(L);
763
764         LM_DBG("lua stack top index: %d\n", top);
765         for (i = 1; i <= top; i++)
766         {
767                 t = lua_type(L, i);
768                 switch (t)
769                 {
770                         case LUA_TSTRING:  /* strings */
771                                 LM_DBG("[%i:s> %s\n", i, lua_tostring(L, i));
772                         break;
773                         case LUA_TBOOLEAN:  /* booleans */
774                                 LM_DBG("[%i:b> %s\n", i,
775                                         lua_toboolean(L, i) ? "true" : "false");
776                         break;
777                         case LUA_TNUMBER:  /* numbers */
778                                 LM_DBG("[%i:n> %g\n", i, lua_tonumber(L, i));
779                         break;
780                         default:  /* other values */
781                                 LM_DBG("[%i:t> %s\n", i, lua_typename(L, t));
782                         break;
783                 }
784         }
785 }