1 /**
2 * Copyright (C) 2018 Daniel-Constantin Mierla (asipto.com)
3 *
4 * This file is part of Kamailio, a free SIP server.
5 *
6 * This file 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 *
12 * This file is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28
29 #include "../../core/dprint.h"
30 #include "../../core/pvar.h"
31 #include "../../core/sr_module.h"
32 #include "../../core/mem/shm.h"
33 #include "../../core/kemi.h"
34 #include "../../core/rpc.h"
35 #include "../../core/rpc_lookup.h"
36
37 #include "app_ruby_api.h"
38 #include "app_ruby_kemi_export.h"
39
40 /* ruby.h defines xmalloc macro, replacing the shm.xmalloc field name */
41 #undef xmalloc
42 #undef xfree
43
44 extern int _ksr_app_ruby_xval_mode;
45
46 int app_ruby_kemi_export_libs(void);
47
48 typedef struct _sr_ruby_env
49 {
50 ksr_ruby_context_t *R;
51 sip_msg_t *msg;
52 int rinit;
53 unsigned int flags;
54 unsigned int nload; /* number of scripts loaded */
55 } sr_ruby_env_t;
56
57 typedef struct ksr_ruby_data {
58 VALUE robj;
59 ID metid;
60 int nargs;
61 VALUE vargs[4];
62 } ksr_ruby_data_t;
63
64 static sr_ruby_env_t _sr_R_env = {0};
65
66 str _sr_ruby_load_file = STR_NULL;
67
68 static int *_sr_ruby_reload_version = NULL;
69 static int _sr_ruby_local_version = 0;
70
71 /**
72 *
73 */
app_ruby_sr_env_get(void)74 sr_ruby_env_t *app_ruby_sr_env_get(void)
75 {
76 return &_sr_R_env;
77 }
78
79 /**
80 *
81 */
ruby_sr_init_mod(void)82 int ruby_sr_init_mod(void)
83 {
84 if(_sr_ruby_load_file.s == NULL || _sr_ruby_load_file.len<=0) {
85 LM_ERR("no ruby script file to load was provided\n");
86 return -1;
87 }
88 if(_sr_ruby_reload_version == NULL) {
89 _sr_ruby_reload_version = (int*)shm_malloc(sizeof(int));
90 if(_sr_ruby_reload_version == NULL) {
91 LM_ERR("failed to allocated reload version\n");
92 return -1;
93 }
94 *_sr_ruby_reload_version = 0;
95 }
96 memset(&_sr_R_env, 0, sizeof(sr_ruby_env_t));
97 return 0;
98 }
99
app_ruby_print_last_exception()100 static int app_ruby_print_last_exception()
101 {
102 VALUE rException, rExceptStr;
103
104 rException = rb_errinfo(); /* get last exception */
105 rb_set_errinfo(Qnil); /* clear last exception */
106 rExceptStr = rb_funcall(rException, rb_intern("to_s"), 0, Qnil);
107 if(RSTRING_LEN(rExceptStr)!=4
108 || strncmp(RSTRING_PTR(rExceptStr), "exit", 4)!=0) {
109 LM_ERR("exception: %.*s\n", (int)RSTRING_LEN(rExceptStr),
110 RSTRING_PTR(rExceptStr));
111 return 0;
112 }
113 return 1;
114 }
115
116 /**
117 *
118 */
app_ruby_kemi_load_script(void)119 int app_ruby_kemi_load_script(void)
120 {
121 int state = 0;
122 VALUE script;
123
124 script = rb_str_new_cstr(_sr_ruby_load_file.s);
125
126 /* handle exceptions like rb_eval_string_protect() */
127 rb_load_protect(script, 0, &state);
128
129 if (state) {
130 /* got exception */
131 app_ruby_print_last_exception();
132 LM_ERR("failed to load rb script file: %.*s (%d)\n",
133 _sr_ruby_load_file.len, _sr_ruby_load_file.s, state);
134 // return -1;
135 }
136 LM_DBG("rb script loaded: %s\n", _sr_ruby_load_file.s);
137
138 return 0;
139 }
140
141 /**
142 *
143 */
app_ruby_kemi_reload_script(void)144 int app_ruby_kemi_reload_script(void)
145 {
146 int v;
147 if(_sr_ruby_load_file.s == NULL && _sr_ruby_load_file.len<=0) {
148 LM_WARN("script file path not provided\n");
149 return -1;
150 }
151 if(_sr_ruby_reload_version == NULL) {
152 LM_WARN("reload not enabled\n");
153 return -1;
154 }
155 if(_sr_R_env.rinit == 0) {
156 LM_ERR("load ruby context not created\n");
157 return -1;
158 }
159
160 v = *_sr_ruby_reload_version;
161 if(v == _sr_ruby_local_version) {
162 /* same version */
163 return 0;
164 }
165 LM_DBG("reloading ruby script file: %.*s (%d => %d)\n",
166 _sr_ruby_load_file.len, _sr_ruby_load_file.s,
167 _sr_ruby_local_version, v);
168 app_ruby_kemi_load_script();
169 _sr_ruby_local_version = v;
170 return 0;
171 }
172
173 /**
174 *
175 */
ruby_sr_init_child(void)176 int ruby_sr_init_child(void)
177 {
178 int state = 0;
179 VALUE rbres;
180
181 /* construct the VM */
182 ruby_init();
183 ruby_init_loadpath();
184 ruby_script(_sr_ruby_load_file.s);
185
186 /* Ruby goes here */
187 rbres = rb_eval_string_protect("puts 'Hello " NAME "!'", &state);
188
189 if (state) {
190 /* handle exception */
191 app_ruby_print_last_exception();
192 LM_ERR("test execution with error (res type: %d)\n", TYPE(rbres));
193 return -1;
194 } else {
195 LM_DBG("test execution without error\n");
196 }
197
198 if(app_ruby_kemi_export_libs()<0) {
199 return -1;
200 }
201
202 if(app_ruby_kemi_load_script()<0) {
203 return -1;
204 }
205
206 _sr_R_env.rinit = 1;
207
208 return 0;
209 }
210
211 /**
212 *
213 */
ruby_sr_destroy(void)214 void ruby_sr_destroy(void)
215 {
216 if(_sr_R_env.rinit == 1) {
217 return;
218 }
219 memset(&_sr_R_env, 0, sizeof(sr_ruby_env_t));
220 /* destruct the VM */
221 ruby_cleanup(0);
222 return;
223 }
224
225 /**
226 *
227 */
ruby_sr_initialized(void)228 int ruby_sr_initialized(void)
229 {
230 if(_sr_R_env.rinit==1) {
231 return 1;
232 }
233 return 0;
234 }
235
236 /**
237 *
238 */
sr_kemi_ruby_return_int(sr_kemi_t * ket,int rc)239 int sr_kemi_ruby_return_int(sr_kemi_t *ket, int rc)
240 {
241 if(ket->rtype==SR_KEMIP_INT || ket->rtype==SR_KEMIP_XVAL) {
242 return INT2NUM(rc);
243 }
244 if(ket->rtype==SR_KEMIP_BOOL && rc!=SR_KEMI_FALSE) {
245 return Qtrue;
246 }
247 return Qfalse;
248 }
249
250 /**
251 *
252 */
sr_kemi_ruby_return_none(int rmode)253 static VALUE sr_kemi_ruby_return_none(int rmode)
254 {
255 if(rmode==1) {
256 return rb_str_new_cstr("<<null>>");
257 } else if(rmode==2) {
258 return rb_str_new_cstr("");
259 }
260 return Qnil;
261 }
262
263 /**
264 *
265 */
app_ruby_pv_get_mode(int argc,VALUE * argv,VALUE self,int rmode)266 static VALUE app_ruby_pv_get_mode(int argc, VALUE* argv, VALUE self, int rmode)
267 {
268 str pvn;
269 pv_spec_t *pvs;
270 pv_value_t val;
271 sr_ruby_env_t *env_R;
272 int pl;
273
274 env_R = app_ruby_sr_env_get();
275
276 if(env_R==NULL || env_R->msg==NULL || argc!=1) {
277 LM_ERR("invalid ruby environment attributes or parameters\n");
278 return sr_kemi_ruby_return_none(rmode);
279 }
280
281 if(!RB_TYPE_P(argv[0], T_STRING)) {
282 LM_ERR("invalid parameter type\n");
283 return sr_kemi_ruby_return_none(rmode);
284 }
285
286 pvn.s = StringValuePtr(argv[0]);
287 if(pvn.s==NULL)
288 return sr_kemi_ruby_return_none(rmode);
289 pvn.len = strlen(pvn.s);
290
291 LM_DBG("pv get: %s\n", pvn.s);
292 pl = pv_locate_name(&pvn);
293 if(pl != pvn.len) {
294 LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
295 return sr_kemi_ruby_return_none(rmode);
296 }
297 pvs = pv_cache_get(&pvn);
298 if(pvs==NULL) {
299 LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
300 return sr_kemi_ruby_return_none(rmode);
301 }
302 memset(&val, 0, sizeof(pv_value_t));
303 if(pv_get_spec_value(env_R->msg, pvs, &val) != 0) {
304 LM_ERR("unable to get pv value for [%s]\n", pvn.s);
305 return sr_kemi_ruby_return_none(rmode);
306 }
307 if(val.flags&PV_VAL_NULL) {
308 return sr_kemi_ruby_return_none(rmode);
309 }
310 if(val.flags&PV_TYPE_INT) {
311 return INT2NUM(val.ri);
312 }
313 return rb_str_new(val.rs.s, val.rs.len);
314 }
315
316 /**
317 *
318 */
app_ruby_pv_get(int argc,VALUE * argv,VALUE self)319 static VALUE app_ruby_pv_get(int argc, VALUE* argv, VALUE self)
320 {
321 return app_ruby_pv_get_mode(argc, argv, self, 0);
322 }
323
324 /**
325 *
326 */
app_ruby_pv_getw(int argc,VALUE * argv,VALUE self)327 static VALUE app_ruby_pv_getw(int argc, VALUE* argv, VALUE self)
328 {
329 return app_ruby_pv_get_mode(argc, argv, self, 1);
330 }
331
332 /**
333 *
334 */
app_ruby_pv_gete(int argc,VALUE * argv,VALUE self)335 static VALUE app_ruby_pv_gete(int argc, VALUE* argv, VALUE self)
336 {
337 return app_ruby_pv_get_mode(argc, argv, self, 2);
338 }
339
340 /**
341 *
342 */
app_ruby_pv_seti(int argc,VALUE * argv,VALUE self)343 static VALUE app_ruby_pv_seti(int argc, VALUE* argv, VALUE self)
344 {
345 str pvn;
346 pv_spec_t *pvs;
347 pv_value_t val;
348 sr_ruby_env_t *env_R;
349 int pl;
350
351 env_R = app_ruby_sr_env_get();
352
353 if(env_R==NULL || env_R->msg==NULL || argc!=2) {
354 LM_ERR("invalid ruby environment attributes or parameters\n");
355 return Qfalse;
356 }
357
358 if(!RB_TYPE_P(argv[0], T_STRING)) {
359 LM_ERR("invalid pv name parameter type\n");
360 return Qfalse;
361 }
362
363 if(!RB_TYPE_P(argv[1], T_FIXNUM)) {
364 LM_ERR("invalid pv val parameter type\n");
365 return Qfalse;
366 }
367
368 pvn.s = StringValuePtr(argv[0]);
369 if(pvn.s==NULL)
370 return Qfalse;
371 pvn.len = strlen(pvn.s);
372
373 LM_DBG("pv get: %s\n", pvn.s);
374 pl = pv_locate_name(&pvn);
375 if(pl != pvn.len) {
376 LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
377 return Qfalse;
378 }
379 pvs = pv_cache_get(&pvn);
380 if(pvs==NULL) {
381 LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
382 return Qfalse;
383 }
384
385 memset(&val, 0, sizeof(pv_value_t));
386 val.ri = NUM2INT(argv[1]);
387 val.flags |= PV_TYPE_INT|PV_VAL_INT;
388
389 if(pv_set_spec_value(env_R->msg, pvs, 0, &val)<0) {
390 LM_ERR("unable to set pv [%s]\n", pvn.s);
391 return Qfalse;
392 }
393
394 return Qtrue;
395 }
396
397 /**
398 *
399 */
app_ruby_pv_sets(int argc,VALUE * argv,VALUE self)400 static VALUE app_ruby_pv_sets(int argc, VALUE* argv, VALUE self)
401 {
402 str pvn;
403 pv_spec_t *pvs;
404 pv_value_t val;
405 sr_ruby_env_t *env_R;
406 int pl;
407
408 env_R = app_ruby_sr_env_get();
409
410 if(env_R==NULL || env_R->msg==NULL || argc!=2) {
411 LM_ERR("invalid ruby environment attributes or parameters\n");
412 return Qfalse;
413 }
414
415 if(!RB_TYPE_P(argv[0], T_STRING)) {
416 LM_ERR("invalid pv name parameter type\n");
417 return Qfalse;
418 }
419
420 if(!RB_TYPE_P(argv[1], T_STRING)) {
421 LM_ERR("invalid pv val parameter type\n");
422 return Qfalse;
423 }
424
425 pvn.s = StringValuePtr(argv[0]);
426 if(pvn.s==NULL)
427 return Qfalse;
428 pvn.len = strlen(pvn.s);
429
430 LM_DBG("pv get: %s\n", pvn.s);
431 pl = pv_locate_name(&pvn);
432 if(pl != pvn.len) {
433 LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
434 return Qfalse;
435 }
436 pvs = pv_cache_get(&pvn);
437 if(pvs==NULL) {
438 LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
439 return Qfalse;
440 }
441
442 memset(&val, 0, sizeof(pv_value_t));
443 val.rs.s = StringValuePtr(argv[1]);
444 if(val.rs.s==NULL) {
445 LM_ERR("invalid str value\n");
446 return Qfalse;
447 }
448 val.rs.len = strlen(val.rs.s);
449 val.flags |= PV_VAL_STR;
450
451 if(pv_set_spec_value(env_R->msg, pvs, 0, &val)<0) {
452 LM_ERR("unable to set pv [%s]\n", pvn.s);
453 return Qfalse;
454 }
455
456 return Qtrue;
457 }
458
459 /**
460 *
461 */
app_ruby_pv_unset(int argc,VALUE * argv,VALUE self)462 static VALUE app_ruby_pv_unset(int argc, VALUE* argv, VALUE self)
463 {
464 str pvn;
465 pv_spec_t *pvs;
466 pv_value_t val;
467 sr_ruby_env_t *env_R;
468 int pl;
469
470 env_R = app_ruby_sr_env_get();
471
472 if(env_R==NULL || env_R->msg==NULL || argc!=1) {
473 LM_ERR("invalid ruby environment attributes or parameters\n");
474 return Qfalse;
475 }
476
477 if(!RB_TYPE_P(argv[0], T_STRING)) {
478 LM_ERR("invalid parameter type\n");
479 return Qfalse;
480 }
481
482 pvn.s = StringValuePtr(argv[0]);
483 if(pvn.s==NULL)
484 return Qfalse;
485 pvn.len = strlen(pvn.s);
486
487 LM_DBG("pv get: %s\n", pvn.s);
488 pl = pv_locate_name(&pvn);
489 if(pl != pvn.len) {
490 LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
491 return Qfalse;
492 }
493 pvs = pv_cache_get(&pvn);
494 if(pvs==NULL) {
495 LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
496 return Qfalse;
497 }
498
499 memset(&val, 0, sizeof(pv_value_t));
500 val.flags |= PV_VAL_NULL;
501 if(pv_set_spec_value(env_R->msg, pvs, 0, &val)<0)
502 {
503 LM_ERR("unable to unset pv [%s]\n", pvn.s);
504 return Qfalse;
505 }
506
507 return Qtrue;
508 }
509
510 /**
511 *
512 */
app_ruby_pv_is_null(int argc,VALUE * argv,VALUE self)513 static VALUE app_ruby_pv_is_null(int argc, VALUE* argv, VALUE self)
514 {
515 str pvn;
516 pv_spec_t *pvs;
517 pv_value_t val;
518 sr_ruby_env_t *env_R;
519 int pl;
520
521 env_R = app_ruby_sr_env_get();
522
523 if(env_R==NULL || env_R->msg==NULL || argc!=1) {
524 LM_ERR("invalid ruby environment attributes or parameters\n");
525 return Qfalse;
526 }
527
528 if(!RB_TYPE_P(argv[0], T_STRING)) {
529 LM_ERR("invalid parameter type\n");
530 return Qfalse;
531 }
532
533 pvn.s = StringValuePtr(argv[0]);
534 if(pvn.s==NULL)
535 return Qfalse;
536 pvn.len = strlen(pvn.s);
537
538 LM_DBG("pv get: %s\n", pvn.s);
539 pl = pv_locate_name(&pvn);
540 if(pl != pvn.len) {
541 LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
542 return Qfalse;
543 }
544 pvs = pv_cache_get(&pvn);
545 if(pvs==NULL) {
546 LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
547 return Qfalse;
548 }
549
550 memset(&val, 0, sizeof(pv_value_t));
551 if(pv_get_spec_value(env_R->msg, pvs, &val) != 0) {
552 LM_NOTICE("unable to get pv value for [%s]\n", pvn.s);
553 return Qtrue;
554 }
555 if(val.flags&PV_VAL_NULL) {
556 return Qtrue;
557 } else {
558 pv_value_destroy(&val);
559 return Qfalse;
560 }
561 }
562
563 /**
564 *
565 */
566 static ksr_ruby_export_t _sr_kemi_pv_R_Map[] = {
567 {"PV", "get", app_ruby_pv_get},
568 {"PV", "getw", app_ruby_pv_getw},
569 {"PV", "gete", app_ruby_pv_gete},
570 {"PV", "seti", app_ruby_pv_seti},
571 {"PV", "sets", app_ruby_pv_sets},
572 {"PV", "unset", app_ruby_pv_unset},
573 {"PV", "is_null", app_ruby_pv_is_null},
574 {0, 0, 0}
575 };
576
577 /**
578 *
579 */
app_ruby_sr_modf(int argc,VALUE * argv,VALUE self)580 static VALUE app_ruby_sr_modf(int argc, VALUE* argv, VALUE self)
581 {
582 int ret;
583 char *rbv[MAX_ACTIONS];
584 char *paramv[MAX_ACTIONS];
585 int i;
586 int mod_type;
587 struct run_act_ctx ra_ctx;
588 struct action *act;
589 ksr_cmd_export_t* expf;
590 sr_ruby_env_t *env_R;
591
592 ret = 1;
593 act = NULL;
594 memset(rbv, 0, MAX_ACTIONS*sizeof(char*));
595 memset(paramv, 0, MAX_ACTIONS*sizeof(char*));
596 env_R = app_ruby_sr_env_get();
597 if(env_R->msg==NULL)
598 goto error;
599
600 if(argc==0) {
601 LM_ERR("name of module function not provided\n");
602 goto error;
603 }
604 if(argc>=MAX_ACTIONS) {
605 LM_ERR("too many parameters\n");
606 goto error;
607 }
608 /* first is function name, then parameters */
609 for(i=0; i<argc; i++) {
610 if(!RB_TYPE_P(argv[i], T_STRING)) {
611 LM_ERR("invalid parameter type (%d)\n", i);
612 return INT2NUM(-1);
613 }
614 rbv[i] = (char*)StringValuePtr(argv[i]);
615 }
616 LM_ERR("request to execute cfg function '%s'\n", rbv[0]);
617 /* pkg copy only parameters */
618 for(i=1; i<MAX_ACTIONS; i++) {
619 if(rbv[i]!=NULL) {
620 paramv[i] = (char*)pkg_malloc(strlen(rbv[i])+1);
621 if(paramv[i]==NULL) {
622 LM_ERR("no more pkg\n");
623 goto error;
624 }
625 strcpy(paramv[i], rbv[i]);
626 }
627 }
628
629 expf = find_export_record(rbv[0], argc-1, 0);
630 if (expf==NULL) {
631 LM_ERR("function '%s' is not available\n", rbv[0]);
632 goto error;
633 }
634 /* check fixups */
635 if (expf->fixup!=NULL && expf->free_fixup==NULL) {
636 LM_ERR("function '%s' has fixup - cannot be used\n", rbv[0]);
637 goto error;
638 }
639 switch(expf->param_no) {
640 case 0:
641 mod_type = MODULE0_T;
642 break;
643 case 1:
644 mod_type = MODULE1_T;
645 break;
646 case 2:
647 mod_type = MODULE2_T;
648 break;
649 case 3:
650 mod_type = MODULE3_T;
651 break;
652 case 4:
653 mod_type = MODULE4_T;
654 break;
655 case 5:
656 mod_type = MODULE5_T;
657 break;
658 case 6:
659 mod_type = MODULE6_T;
660 break;
661 case VAR_PARAM_NO:
662 mod_type = MODULEX_T;
663 break;
664 default:
665 LM_ERR("unknown/bad definition for function '%s' (%d params)\n",
666 rbv[0], expf->param_no);
667 goto error;
668 }
669
670 act = mk_action(mod_type, argc+1 /* number of (type, value) pairs */,
671 MODEXP_ST, expf, /* function */
672 NUMBER_ST, argc-1, /* parameter number */
673 STRING_ST, paramv[1], /* param. 1 */
674 STRING_ST, paramv[2], /* param. 2 */
675 STRING_ST, paramv[3], /* param. 3 */
676 STRING_ST, paramv[4], /* param. 4 */
677 STRING_ST, paramv[5], /* param. 5 */
678 STRING_ST, paramv[6] /* param. 6 */
679 );
680
681 if (act==NULL) {
682 LM_ERR("action structure could not be created for '%s'\n", rbv[0]);
683 goto error;
684 }
685
686 /* handle fixups */
687 if (expf->fixup) {
688 if(argc==1) {
689 /* no parameters */
690 if(expf->fixup(0, 0)<0) {
691 LM_ERR("Error in fixup (0) for '%s'\n", rbv[0]);
692 goto error;
693 }
694 } else {
695 for(i=1; i<argc; i++) {
696 if(expf->fixup(&(act->val[i+1].u.data), i)<0) {
697 LM_ERR("Error in fixup (%d) for '%s'\n", i, rbv[0]);
698 goto error;
699 }
700 act->val[i+1].type = MODFIXUP_ST;
701 }
702 }
703 }
704 init_run_actions_ctx(&ra_ctx);
705 ret = do_action(&ra_ctx, act, env_R->msg);
706
707 /* free fixups */
708 if (expf->fixup) {
709 for(i=1; i<argc; i++) {
710 if ((act->val[i+1].type == MODFIXUP_ST) && (act->val[i+1].u.data)) {
711 expf->free_fixup(&(act->val[i+1].u.data), i);
712 }
713 }
714 }
715 pkg_free(act);
716 for(i=0; i<MAX_ACTIONS; i++) {
717 if(paramv[i]!=NULL) pkg_free(paramv[i]);
718 paramv[i] = 0;
719 }
720 return INT2NUM(ret);
721
722 error:
723 if(act!=NULL)
724 pkg_free(act);
725 for(i=0; i<MAX_ACTIONS; i++) {
726 if(paramv[i]!=NULL) pkg_free(paramv[i]);
727 paramv[i] = 0;
728 }
729 return INT2NUM(-1);
730 }
731
732 /**
733 *
734 */
735 static ksr_ruby_export_t _sr_kemi_x_R_Map[] = {
736 {"X", "modf", app_ruby_sr_modf},
737 {0, 0, 0}
738 };
739
740 /**
741 *
742 */
ksr_ruby_exec_callback(VALUE ptr)743 static VALUE ksr_ruby_exec_callback(VALUE ptr)
744 {
745 ksr_ruby_data_t *data = (ksr_ruby_data_t *)ptr;
746 return rb_funcall2(data->robj, data->metid, data->nargs, data->vargs);
747 }
748
749 /**
750 *
751 */
sr_kemi_ruby_return_xval(sr_kemi_t * ket,sr_kemi_xval_t * rx)752 VALUE sr_kemi_ruby_return_xval(sr_kemi_t *ket, sr_kemi_xval_t *rx)
753 {
754 switch(rx->vtype) {
755 case SR_KEMIP_NONE:
756 return Qnil;
757 case SR_KEMIP_INT:
758 return INT2NUM(rx->v.n);
759 case SR_KEMIP_STR:
760 if(_ksr_app_ruby_xval_mode==0) {
761 LM_ERR("attempt to return xval str - support disabled - returning null\n");
762 return Qnil;
763 } else {
764 return rb_str_new(rx->v.s.s, rx->v.s.len);
765 }
766 case SR_KEMIP_BOOL:
767 if(rx->v.n!=SR_KEMI_FALSE) {
768 return Qtrue;
769 } else {
770 return Qfalse;
771 }
772 case SR_KEMIP_ARRAY:
773 LM_ERR("unsupported return type: array\n");
774 sr_kemi_xval_free(rx);
775 return Qnil;
776 case SR_KEMIP_DICT:
777 LM_ERR("unsupported return type: map\n");
778 sr_kemi_xval_free(rx);
779 return Qnil;
780 case SR_KEMIP_XVAL:
781 /* unknown content - return false */
782 return Qfalse;
783 case SR_KEMIP_NULL:
784 return Qnil;
785 default:
786 /* unknown type - return false */
787 return Qfalse;
788 }
789 }
790
791 /**
792 *
793 */
sr_kemi_ruby_exec_func_ex(ksr_ruby_context_t * R,sr_kemi_t * ket,int argc,VALUE * argv,VALUE self)794 VALUE sr_kemi_ruby_exec_func_ex(ksr_ruby_context_t *R, sr_kemi_t *ket, int argc,
795 VALUE* argv, VALUE self)
796 {
797 sr_kemi_val_t vps[SR_KEMI_PARAMS_MAX];
798 sr_ruby_env_t *env_R;
799 str *fname;
800 str *mname;
801 int i;
802 int ret = -1;
803 sr_kemi_xval_t *xret;
804
805 env_R = app_ruby_sr_env_get();
806 if(env_R==NULL || env_R->msg==NULL || ket==NULL) {
807 LM_ERR("invalid ruby environment attributes or parameters (%p/%p/%p)\n",
808 env_R, env_R->msg, ket);
809 return Qfalse;
810 }
811
812 if(argc==0 && ket->ptypes[0]==SR_KEMIP_NONE) {
813 if(ket->rtype==SR_KEMIP_XVAL) {
814 xret = ((sr_kemi_xfm_f)(ket->func))(env_R->msg);
815 return sr_kemi_ruby_return_xval(ket, xret);
816 } else {
817 ret = ((sr_kemi_fm_f)(ket->func))(env_R->msg);
818 return sr_kemi_ruby_return_int(ket, ret);
819 }
820 }
821 fname = &ket->fname;
822 mname = &ket->mname;
823 if(argc==0 && ket->ptypes[0]!=SR_KEMIP_NONE) {
824 LM_ERR("invalid number of parameters for: %.*s.%.*s\n",
825 mname->len, mname->s, fname->len, fname->s);
826 return Qfalse;
827 }
828
829 if(argc>SR_KEMI_PARAMS_MAX) {
830 LM_ERR("too many parameters for: %.*s.%.*s\n",
831 mname->len, mname->s, fname->len, fname->s);
832 return Qfalse;
833 }
834
835 memset(vps, 0, SR_KEMI_PARAMS_MAX*sizeof(sr_kemi_val_t));
836 for(i=0; i<SR_KEMI_PARAMS_MAX; i++) {
837 if(ket->ptypes[i]==SR_KEMIP_NONE) {
838 break;
839 } else if(ket->ptypes[i]==SR_KEMIP_STR) {
840 if(!RB_TYPE_P(argv[i], T_STRING)) {
841 LM_ERR("invalid str parameter type %d (%d)\n", ket->ptypes[i], i);
842 return Qfalse;
843 }
844 vps[i].s.s = StringValuePtr(argv[i]);
845 vps[i].s.len = strlen(vps[i].s.s);
846 LM_DBG("param[%d] for: %.*s.%.*s is str: %.*s\n", i,
847 mname->len, mname->s, fname->len, fname->s, vps[i].s.len, vps[i].s.s);
848 } else if(ket->ptypes[i]==SR_KEMIP_INT) {
849 if(!RB_TYPE_P(argv[i], T_FIXNUM)) {
850 LM_ERR("invalid int parameter type %d (%d)\n", ket->ptypes[i], i);
851 return Qfalse;
852 }
853 vps[i].n = NUM2INT(argv[i]);
854 LM_DBG("param[%d] for: %.*s.%.*s is int: %d\n", i,
855 mname->len, mname->s, fname->len, fname->s, vps[i].n);
856 } else {
857 LM_ERR("unknown parameter type %d (%d)\n", ket->ptypes[i], i);
858 return Qfalse;
859 }
860 }
861
862 switch(i) {
863 case 1:
864 if(ket->ptypes[0]==SR_KEMIP_INT) {
865 if(ket->rtype==SR_KEMIP_XVAL) {
866 xret = ((sr_kemi_xfmn_f)(ket->func))(env_R->msg, vps[0].n);
867 return sr_kemi_ruby_return_xval(ket, xret);
868 } else {
869 ret = ((sr_kemi_fmn_f)(ket->func))(env_R->msg, vps[0].n);
870 return sr_kemi_ruby_return_int(ket, ret);
871 }
872 } else if(ket->ptypes[0]==SR_KEMIP_STR) {
873 if(ket->rtype==SR_KEMIP_XVAL) {
874 xret = ((sr_kemi_xfms_f)(ket->func))(env_R->msg, &vps[0].s);
875 return sr_kemi_ruby_return_xval(ket, xret);
876 } else {
877 ret = ((sr_kemi_fms_f)(ket->func))(env_R->msg, &vps[0].s);
878 return sr_kemi_ruby_return_int(ket, ret);
879 }
880 } else {
881 LM_ERR("invalid parameters for: %.*s\n",
882 fname->len, fname->s);
883 return Qfalse;
884 }
885 break;
886 case 2:
887 if(ket->ptypes[0]==SR_KEMIP_INT) {
888 if(ket->ptypes[1]==SR_KEMIP_INT) {
889 if(ket->rtype==SR_KEMIP_XVAL) {
890 xret = ((sr_kemi_xfmnn_f)(ket->func))(env_R->msg, vps[0].n, vps[1].n);
891 return sr_kemi_ruby_return_xval(ket, xret);
892 } else {
893 ret = ((sr_kemi_fmnn_f)(ket->func))(env_R->msg, vps[0].n, vps[1].n);
894 return sr_kemi_ruby_return_int(ket, ret);
895 }
896 } else if(ket->ptypes[1]==SR_KEMIP_STR) {
897 if(ket->rtype==SR_KEMIP_XVAL) {
898 xret = ((sr_kemi_xfmns_f)(ket->func))(env_R->msg, vps[0].n, &vps[1].s);
899 return sr_kemi_ruby_return_xval(ket, xret);
900 } else {
901 ret = ((sr_kemi_fmns_f)(ket->func))(env_R->msg, vps[0].n, &vps[1].s);
902 return sr_kemi_ruby_return_int(ket, ret);
903 }
904 } else {
905 LM_ERR("invalid parameters for: %.*s\n",
906 fname->len, fname->s);
907 return Qfalse;
908 }
909 } else if(ket->ptypes[0]==SR_KEMIP_STR) {
910 if(ket->ptypes[1]==SR_KEMIP_INT) {
911 if(ket->rtype==SR_KEMIP_XVAL) {
912 xret = ((sr_kemi_xfmsn_f)(ket->func))(env_R->msg, &vps[0].s, vps[1].n);
913 return sr_kemi_ruby_return_xval(ket, xret);
914 } else {
915 ret = ((sr_kemi_fmsn_f)(ket->func))(env_R->msg, &vps[0].s, vps[1].n);
916 return sr_kemi_ruby_return_int(ket, ret);
917 }
918 } else if(ket->ptypes[1]==SR_KEMIP_STR) {
919 if(ket->rtype==SR_KEMIP_XVAL) {
920 xret = ((sr_kemi_xfmss_f)(ket->func))(env_R->msg, &vps[0].s, &vps[1].s);
921 return sr_kemi_ruby_return_xval(ket, xret);
922 } else {
923 ret = ((sr_kemi_fmss_f)(ket->func))(env_R->msg, &vps[0].s, &vps[1].s);
924 return sr_kemi_ruby_return_int(ket, ret);
925 }
926 } else {
927 LM_ERR("invalid parameters for: %.*s\n",
928 fname->len, fname->s);
929 return Qfalse;
930 }
931 } else {
932 LM_ERR("invalid parameters for: %.*s\n",
933 fname->len, fname->s);
934 return Qfalse;
935 }
936 break;
937 case 3:
938 if(ket->ptypes[0]==SR_KEMIP_INT) {
939 if(ket->ptypes[1]==SR_KEMIP_INT) {
940 if(ket->ptypes[2]==SR_KEMIP_INT) {
941 ret = ((sr_kemi_fmnnn_f)(ket->func))(env_R->msg,
942 vps[0].n, vps[1].n, vps[2].n);
943 return sr_kemi_ruby_return_int(ket, ret);
944 } else if(ket->ptypes[2]==SR_KEMIP_STR) {
945 ret = ((sr_kemi_fmnns_f)(ket->func))(env_R->msg,
946 vps[0].n, vps[1].n, &vps[2].s);
947 return sr_kemi_ruby_return_int(ket, ret);
948 } else {
949 LM_ERR("invalid parameters for: %.*s\n",
950 fname->len, fname->s);
951 return Qfalse;
952 }
953 } else if(ket->ptypes[1]==SR_KEMIP_STR) {
954 if(ket->ptypes[2]==SR_KEMIP_INT) {
955 ret = ((sr_kemi_fmnsn_f)(ket->func))(env_R->msg,
956 vps[0].n, &vps[1].s, vps[2].n);
957 return sr_kemi_ruby_return_int(ket, ret);
958 } else if(ket->ptypes[2]==SR_KEMIP_STR) {
959 ret = ((sr_kemi_fmnss_f)(ket->func))(env_R->msg,
960 vps[0].n, &vps[1].s, &vps[2].s);
961 return sr_kemi_ruby_return_int(ket, ret);
962 } else {
963 LM_ERR("invalid parameters for: %.*s\n",
964 fname->len, fname->s);
965 return Qfalse;
966 }
967 } else {
968 LM_ERR("invalid parameters for: %.*s\n",
969 fname->len, fname->s);
970 return Qfalse;
971 }
972 } else if(ket->ptypes[0]==SR_KEMIP_STR) {
973 if(ket->ptypes[1]==SR_KEMIP_INT) {
974 if(ket->ptypes[2]==SR_KEMIP_INT) {
975 ret = ((sr_kemi_fmsnn_f)(ket->func))(env_R->msg,
976 &vps[0].s, vps[1].n, vps[2].n);
977 return sr_kemi_ruby_return_int(ket, ret);
978 } else if(ket->ptypes[2]==SR_KEMIP_STR) {
979 ret = ((sr_kemi_fmsns_f)(ket->func))(env_R->msg,
980 &vps[0].s, vps[1].n, &vps[2].s);
981 return sr_kemi_ruby_return_int(ket, ret);
982 } else {
983 LM_ERR("invalid parameters for: %.*s\n",
984 fname->len, fname->s);
985 return Qfalse;
986 }
987 } else if(ket->ptypes[1]==SR_KEMIP_STR) {
988 if(ket->ptypes[2]==SR_KEMIP_INT) {
989 ret = ((sr_kemi_fmssn_f)(ket->func))(env_R->msg,
990 &vps[0].s, &vps[1].s, vps[2].n);
991 return sr_kemi_ruby_return_int(ket, ret);
992 } else if(ket->ptypes[2]==SR_KEMIP_STR) {
993 ret = ((sr_kemi_fmsss_f)(ket->func))(env_R->msg,
994 &vps[0].s, &vps[1].s, &vps[2].s);
995 return sr_kemi_ruby_return_int(ket, ret);
996 } else {
997 LM_ERR("invalid parameters for: %.*s\n",
998 fname->len, fname->s);
999 return Qfalse;
1000 }
1001 } else {
1002 LM_ERR("invalid parameters for: %.*s\n",
1003 fname->len, fname->s);
1004 return Qfalse;
1005 }
1006 } else {
1007 LM_ERR("invalid parameters for: %.*s\n",
1008 fname->len, fname->s);
1009 return Qfalse;
1010 }
1011 break;
1012 case 4:
1013 if(ket->ptypes[0]==SR_KEMIP_STR
1014 && ket->ptypes[1]==SR_KEMIP_STR
1015 && ket->ptypes[2]==SR_KEMIP_STR
1016 && ket->ptypes[3]==SR_KEMIP_STR) {
1017 ret = ((sr_kemi_fmssss_f)(ket->func))(env_R->msg,
1018 &vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s);
1019 return sr_kemi_ruby_return_int(ket, ret);
1020 } else if(ket->ptypes[0]==SR_KEMIP_STR
1021 && ket->ptypes[1]==SR_KEMIP_STR
1022 && ket->ptypes[2]==SR_KEMIP_STR
1023 && ket->ptypes[3]==SR_KEMIP_INT) {
1024 ret = ((sr_kemi_fmsssn_f)(ket->func))(env_R->msg,
1025 &vps[0].s, &vps[1].s, &vps[2].s, vps[3].n);
1026 return sr_kemi_ruby_return_int(ket, ret);
1027 } else if(ket->ptypes[0]==SR_KEMIP_STR
1028 && ket->ptypes[1]==SR_KEMIP_STR
1029 && ket->ptypes[2]==SR_KEMIP_INT
1030 && ket->ptypes[3]==SR_KEMIP_STR) {
1031 ret = ((sr_kemi_fmssns_f)(ket->func))(env_R->msg,
1032 &vps[0].s, &vps[1].s, vps[2].n, &vps[3].s);
1033 return sr_kemi_ruby_return_int(ket, ret);
1034 } else if(ket->ptypes[0]==SR_KEMIP_STR
1035 && ket->ptypes[1]==SR_KEMIP_STR
1036 && ket->ptypes[2]==SR_KEMIP_INT
1037 && ket->ptypes[3]==SR_KEMIP_INT) {
1038 ret = ((sr_kemi_fmssnn_f)(ket->func))(env_R->msg,
1039 &vps[0].s, &vps[1].s, vps[2].n, vps[3].n);
1040 return sr_kemi_ruby_return_int(ket, ret);
1041 } else if(ket->ptypes[0]==SR_KEMIP_STR
1042 && ket->ptypes[1]==SR_KEMIP_INT
1043 && ket->ptypes[2]==SR_KEMIP_STR
1044 && ket->ptypes[3]==SR_KEMIP_STR) {
1045 ret = ((sr_kemi_fmsnss_f)(ket->func))(env_R->msg,
1046 &vps[0].s, vps[1].n, &vps[2].s, &vps[3].s);
1047 return sr_kemi_ruby_return_int(ket, ret);
1048 } else if(ket->ptypes[0]==SR_KEMIP_STR
1049 && ket->ptypes[1]==SR_KEMIP_INT
1050 && ket->ptypes[2]==SR_KEMIP_STR
1051 && ket->ptypes[3]==SR_KEMIP_INT) {
1052 ret = ((sr_kemi_fmsnsn_f)(ket->func))(env_R->msg,
1053 &vps[0].s, vps[1].n, &vps[2].s, vps[3].n);
1054 return sr_kemi_ruby_return_int(ket, ret);
1055 } else if(ket->ptypes[0]==SR_KEMIP_STR
1056 && ket->ptypes[1]==SR_KEMIP_INT
1057 && ket->ptypes[2]==SR_KEMIP_INT
1058 && ket->ptypes[3]==SR_KEMIP_STR) {
1059 ret = ((sr_kemi_fmsnns_f)(ket->func))(env_R->msg,
1060 &vps[0].s, vps[1].n, vps[2].n, &vps[3].s);
1061 return sr_kemi_ruby_return_int(ket, ret);
1062 } else if(ket->ptypes[0]==SR_KEMIP_STR
1063 && ket->ptypes[1]==SR_KEMIP_INT
1064 && ket->ptypes[2]==SR_KEMIP_INT
1065 && ket->ptypes[3]==SR_KEMIP_INT) {
1066 ret = ((sr_kemi_fmsnnn_f)(ket->func))(env_R->msg,
1067 &vps[0].s, vps[1].n, vps[2].n, vps[3].n);
1068 return sr_kemi_ruby_return_int(ket, ret);
1069 } else if(ket->ptypes[0]==SR_KEMIP_INT
1070 && ket->ptypes[1]==SR_KEMIP_STR
1071 && ket->ptypes[2]==SR_KEMIP_STR
1072 && ket->ptypes[3]==SR_KEMIP_STR) {
1073 ret = ((sr_kemi_fmnsss_f)(ket->func))(env_R->msg,
1074 vps[0].n, &vps[1].s, &vps[2].s, &vps[3].s);
1075 return sr_kemi_ruby_return_int(ket, ret);
1076 } else if(ket->ptypes[0]==SR_KEMIP_INT
1077 && ket->ptypes[1]==SR_KEMIP_STR
1078 && ket->ptypes[2]==SR_KEMIP_STR
1079 && ket->ptypes[3]==SR_KEMIP_INT) {
1080 ret = ((sr_kemi_fmnssn_f)(ket->func))(env_R->msg,
1081 vps[0].n, &vps[1].s, &vps[2].s, vps[3].n);
1082 return sr_kemi_ruby_return_int(ket, ret);
1083 } else if(ket->ptypes[0]==SR_KEMIP_INT
1084 && ket->ptypes[1]==SR_KEMIP_STR
1085 && ket->ptypes[2]==SR_KEMIP_INT
1086 && ket->ptypes[3]==SR_KEMIP_STR) {
1087 ret = ((sr_kemi_fmnsns_f)(ket->func))(env_R->msg,
1088 vps[0].n, &vps[1].s, vps[2].n, &vps[3].s);
1089 return sr_kemi_ruby_return_int(ket, ret);
1090 } else if(ket->ptypes[0]==SR_KEMIP_INT
1091 && ket->ptypes[1]==SR_KEMIP_STR
1092 && ket->ptypes[2]==SR_KEMIP_INT
1093 && ket->ptypes[3]==SR_KEMIP_INT) {
1094 ret = ((sr_kemi_fmnsnn_f)(ket->func))(env_R->msg,
1095 vps[0].n, &vps[1].s, vps[2].n, vps[3].n);
1096 return sr_kemi_ruby_return_int(ket, ret);
1097 } else if(ket->ptypes[0]==SR_KEMIP_INT
1098 && ket->ptypes[1]==SR_KEMIP_INT
1099 && ket->ptypes[2]==SR_KEMIP_STR
1100 && ket->ptypes[3]==SR_KEMIP_STR) {
1101 ret = ((sr_kemi_fmnnss_f)(ket->func))(env_R->msg,
1102 vps[0].n, vps[1].n, &vps[2].s, &vps[3].s);
1103 return sr_kemi_ruby_return_int(ket, ret);
1104 } else if(ket->ptypes[0]==SR_KEMIP_INT
1105 && ket->ptypes[1]==SR_KEMIP_INT
1106 && ket->ptypes[2]==SR_KEMIP_STR
1107 && ket->ptypes[3]==SR_KEMIP_INT) {
1108 ret = ((sr_kemi_fmnnsn_f)(ket->func))(env_R->msg,
1109 vps[0].n, vps[1].n, &vps[2].s, vps[3].n);
1110 return sr_kemi_ruby_return_int(ket, ret);
1111 } else if(ket->ptypes[0]==SR_KEMIP_INT
1112 && ket->ptypes[1]==SR_KEMIP_INT
1113 && ket->ptypes[2]==SR_KEMIP_INT
1114 && ket->ptypes[3]==SR_KEMIP_STR) {
1115 ret = ((sr_kemi_fmnnns_f)(ket->func))(env_R->msg,
1116 vps[0].n, vps[1].n, vps[2].n, &vps[3].s);
1117 return sr_kemi_ruby_return_int(ket, ret);
1118 } else if(ket->ptypes[0]==SR_KEMIP_INT
1119 && ket->ptypes[1]==SR_KEMIP_INT
1120 && ket->ptypes[2]==SR_KEMIP_INT
1121 && ket->ptypes[3]==SR_KEMIP_INT) {
1122 ret = ((sr_kemi_fmnnnn_f)(ket->func))(env_R->msg,
1123 vps[0].n, vps[1].n, vps[2].n, vps[3].n);
1124 return sr_kemi_ruby_return_int(ket, ret);
1125 } else {
1126 LM_ERR("invalid parameters for: %.*s\n", fname->len, fname->s);
1127 return Qfalse;
1128 }
1129 break;
1130 case 5:
1131 if(ket->ptypes[0]==SR_KEMIP_STR
1132 && ket->ptypes[1]==SR_KEMIP_STR
1133 && ket->ptypes[2]==SR_KEMIP_STR
1134 && ket->ptypes[3]==SR_KEMIP_STR
1135 && ket->ptypes[4]==SR_KEMIP_STR) {
1136 ret = ((sr_kemi_fmsssss_f)(ket->func))(env_R->msg,
1137 &vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s, &vps[4].s);
1138 return sr_kemi_ruby_return_int(ket, ret);
1139 } else if(ket->ptypes[0]==SR_KEMIP_STR
1140 && ket->ptypes[1]==SR_KEMIP_STR
1141 && ket->ptypes[2]==SR_KEMIP_STR
1142 && ket->ptypes[3]==SR_KEMIP_STR
1143 && ket->ptypes[4]==SR_KEMIP_INT) {
1144 ret = ((sr_kemi_fmssssn_f)(ket->func))(env_R->msg,
1145 &vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s, vps[4].n);
1146 return sr_kemi_ruby_return_int(ket, ret);
1147 } else if(ket->ptypes[0]==SR_KEMIP_STR
1148 && ket->ptypes[1]==SR_KEMIP_STR
1149 && ket->ptypes[2]==SR_KEMIP_STR
1150 && ket->ptypes[3]==SR_KEMIP_INT
1151 && ket->ptypes[4]==SR_KEMIP_STR) {
1152 ret = ((sr_kemi_fmsssns_f)(ket->func))(env_R->msg,
1153 &vps[0].s, &vps[1].s, &vps[2].s, vps[3].n, &vps[4].s);
1154 return sr_kemi_ruby_return_int(ket, ret);
1155 } else if(ket->ptypes[0]==SR_KEMIP_STR
1156 && ket->ptypes[1]==SR_KEMIP_STR
1157 && ket->ptypes[2]==SR_KEMIP_STR
1158 && ket->ptypes[3]==SR_KEMIP_INT
1159 && ket->ptypes[4]==SR_KEMIP_INT) {
1160 ret = ((sr_kemi_fmsssnn_f)(ket->func))(env_R->msg,
1161 &vps[0].s, &vps[1].s, &vps[2].s, vps[3].n, vps[4].n);
1162 return sr_kemi_ruby_return_int(ket, ret);
1163 } else if(ket->ptypes[0]==SR_KEMIP_STR
1164 && ket->ptypes[1]==SR_KEMIP_STR
1165 && ket->ptypes[2]==SR_KEMIP_INT
1166 && ket->ptypes[3]==SR_KEMIP_STR
1167 && ket->ptypes[4]==SR_KEMIP_STR) {
1168 ret = ((sr_kemi_fmssnss_f)(ket->func))(env_R->msg,
1169 &vps[0].s, &vps[1].s, vps[2].n, &vps[3].s, &vps[4].s);
1170 return sr_kemi_ruby_return_int(ket, ret);
1171 } else if(ket->ptypes[0]==SR_KEMIP_STR
1172 && ket->ptypes[1]==SR_KEMIP_STR
1173 && ket->ptypes[2]==SR_KEMIP_INT
1174 && ket->ptypes[3]==SR_KEMIP_STR
1175 && ket->ptypes[4]==SR_KEMIP_INT) {
1176 ret = ((sr_kemi_fmssnsn_f)(ket->func))(env_R->msg,
1177 &vps[0].s, &vps[1].s, vps[2].n, &vps[3].s, vps[4].n);
1178 return sr_kemi_ruby_return_int(ket, ret);
1179 } else if(ket->ptypes[0]==SR_KEMIP_STR
1180 && ket->ptypes[1]==SR_KEMIP_STR
1181 && ket->ptypes[2]==SR_KEMIP_INT
1182 && ket->ptypes[3]==SR_KEMIP_INT
1183 && ket->ptypes[4]==SR_KEMIP_STR) {
1184 ret = ((sr_kemi_fmssnns_f)(ket->func))(env_R->msg,
1185 &vps[0].s, &vps[1].s, vps[2].n, vps[3].n, &vps[4].s);
1186 return sr_kemi_ruby_return_int(ket, ret);
1187 } else if(ket->ptypes[0]==SR_KEMIP_STR
1188 && ket->ptypes[1]==SR_KEMIP_STR
1189 && ket->ptypes[2]==SR_KEMIP_INT
1190 && ket->ptypes[3]==SR_KEMIP_INT
1191 && ket->ptypes[4]==SR_KEMIP_INT) {
1192 ret = ((sr_kemi_fmssnnn_f)(ket->func))(env_R->msg,
1193 &vps[0].s, &vps[1].s, vps[2].n, vps[3].n, vps[4].n);
1194 return sr_kemi_ruby_return_int(ket, ret);
1195 } else if(ket->ptypes[0]==SR_KEMIP_STR
1196 && ket->ptypes[1]==SR_KEMIP_INT
1197 && ket->ptypes[2]==SR_KEMIP_STR
1198 && ket->ptypes[3]==SR_KEMIP_STR
1199 && ket->ptypes[4]==SR_KEMIP_STR) {
1200 ret = ((sr_kemi_fmsnsss_f)(ket->func))(env_R->msg,
1201 &vps[0].s, vps[1].n, &vps[2].s, &vps[3].s, &vps[4].s);
1202 return sr_kemi_ruby_return_int(ket, ret);
1203 } else if(ket->ptypes[0]==SR_KEMIP_STR
1204 && ket->ptypes[1]==SR_KEMIP_INT
1205 && ket->ptypes[2]==SR_KEMIP_STR
1206 && ket->ptypes[3]==SR_KEMIP_STR
1207 && ket->ptypes[4]==SR_KEMIP_INT) {
1208 ret = ((sr_kemi_fmsnssn_f)(ket->func))(env_R->msg,
1209 &vps[0].s, vps[1].n, &vps[2].s, &vps[3].s, vps[4].n);
1210 return sr_kemi_ruby_return_int(ket, ret);
1211 } else if(ket->ptypes[0]==SR_KEMIP_STR
1212 && ket->ptypes[1]==SR_KEMIP_INT
1213 && ket->ptypes[2]==SR_KEMIP_STR
1214 && ket->ptypes[3]==SR_KEMIP_INT
1215 && ket->ptypes[4]==SR_KEMIP_STR) {
1216 ret = ((sr_kemi_fmsnsns_f)(ket->func))(env_R->msg,
1217 &vps[0].s, vps[1].n, &vps[2].s, vps[3].n, &vps[4].s);
1218 return sr_kemi_ruby_return_int(ket, ret);
1219 } else if(ket->ptypes[0]==SR_KEMIP_STR
1220 && ket->ptypes[1]==SR_KEMIP_INT
1221 && ket->ptypes[2]==SR_KEMIP_STR
1222 && ket->ptypes[3]==SR_KEMIP_INT
1223 && ket->ptypes[4]==SR_KEMIP_INT) {
1224 ret = ((sr_kemi_fmsnsnn_f)(ket->func))(env_R->msg,
1225 &vps[0].s, vps[1].n, &vps[2].s, vps[3].n, vps[4].n);
1226 return sr_kemi_ruby_return_int(ket, ret);
1227 } else if(ket->ptypes[0]==SR_KEMIP_STR
1228 && ket->ptypes[1]==SR_KEMIP_INT
1229 && ket->ptypes[2]==SR_KEMIP_INT
1230 && ket->ptypes[3]==SR_KEMIP_STR
1231 && ket->ptypes[4]==SR_KEMIP_STR) {
1232 ret = ((sr_kemi_fmsnnss_f)(ket->func))(env_R->msg,
1233 &vps[0].s, vps[1].n, vps[2].n, &vps[3].s, &vps[4].s);
1234 return sr_kemi_ruby_return_int(ket, ret);
1235 } else if(ket->ptypes[0]==SR_KEMIP_STR
1236 && ket->ptypes[1]==SR_KEMIP_INT
1237 && ket->ptypes[2]==SR_KEMIP_INT
1238 && ket->ptypes[3]==SR_KEMIP_STR
1239 && ket->ptypes[4]==SR_KEMIP_INT) {
1240 ret = ((sr_kemi_fmsnnsn_f)(ket->func))(env_R->msg,
1241 &vps[0].s, vps[1].n, vps[2].n, &vps[3].s, vps[4].n);
1242 return sr_kemi_ruby_return_int(ket, ret);
1243 } else if(ket->ptypes[0]==SR_KEMIP_STR
1244 && ket->ptypes[1]==SR_KEMIP_INT
1245 && ket->ptypes[2]==SR_KEMIP_INT
1246 && ket->ptypes[3]==SR_KEMIP_INT
1247 && ket->ptypes[4]==SR_KEMIP_STR) {
1248 ret = ((sr_kemi_fmsnnns_f)(ket->func))(env_R->msg,
1249 &vps[0].s, vps[1].n, vps[2].n, vps[3].n, &vps[4].s);
1250 return sr_kemi_ruby_return_int(ket, ret);
1251 } else if(ket->ptypes[0]==SR_KEMIP_STR
1252 && ket->ptypes[1]==SR_KEMIP_INT
1253 && ket->ptypes[2]==SR_KEMIP_INT
1254 && ket->ptypes[3]==SR_KEMIP_INT
1255 && ket->ptypes[4]==SR_KEMIP_INT) {
1256 ret = ((sr_kemi_fmsnnnn_f)(ket->func))(env_R->msg,
1257 &vps[0].s, vps[1].n, vps[2].n, vps[3].n, vps[4].n);
1258 return sr_kemi_ruby_return_int(ket, ret);
1259 } else if(ket->ptypes[0]==SR_KEMIP_INT
1260 && ket->ptypes[1]==SR_KEMIP_STR
1261 && ket->ptypes[2]==SR_KEMIP_STR
1262 && ket->ptypes[3]==SR_KEMIP_STR
1263 && ket->ptypes[4]==SR_KEMIP_STR) {
1264 ret = ((sr_kemi_fmnssss_f)(ket->func))(env_R->msg,
1265 vps[0].n, &vps[1].s, &vps[2].s, &vps[3].s, &vps[4].s);
1266 return sr_kemi_ruby_return_int(ket, ret);
1267 } else if(ket->ptypes[0]==SR_KEMIP_INT
1268 && ket->ptypes[1]==SR_KEMIP_STR
1269 && ket->ptypes[2]==SR_KEMIP_STR
1270 && ket->ptypes[3]==SR_KEMIP_STR
1271 && ket->ptypes[4]==SR_KEMIP_INT) {
1272 ret = ((sr_kemi_fmnsssn_f)(ket->func))(env_R->msg,
1273 vps[0].n, &vps[1].s, &vps[2].s, &vps[3].s, vps[4].n);
1274 return sr_kemi_ruby_return_int(ket, ret);
1275 } else if(ket->ptypes[0]==SR_KEMIP_INT
1276 && ket->ptypes[1]==SR_KEMIP_STR
1277 && ket->ptypes[2]==SR_KEMIP_STR
1278 && ket->ptypes[3]==SR_KEMIP_INT
1279 && ket->ptypes[4]==SR_KEMIP_STR) {
1280 ret = ((sr_kemi_fmnssns_f)(ket->func))(env_R->msg,
1281 vps[0].n, &vps[1].s, &vps[2].s, vps[3].n, &vps[4].s);
1282 return sr_kemi_ruby_return_int(ket, ret);
1283 } else if(ket->ptypes[0]==SR_KEMIP_INT
1284 && ket->ptypes[1]==SR_KEMIP_STR
1285 && ket->ptypes[2]==SR_KEMIP_STR
1286 && ket->ptypes[3]==SR_KEMIP_INT
1287 && ket->ptypes[4]==SR_KEMIP_INT) {
1288 ret = ((sr_kemi_fmnssnn_f)(ket->func))(env_R->msg,
1289 vps[0].n, &vps[1].s, &vps[2].s, vps[3].n, vps[4].n);
1290 return sr_kemi_ruby_return_int(ket, ret);
1291 } else if(ket->ptypes[0]==SR_KEMIP_INT
1292 && ket->ptypes[1]==SR_KEMIP_STR
1293 && ket->ptypes[2]==SR_KEMIP_INT
1294 && ket->ptypes[3]==SR_KEMIP_STR
1295 && ket->ptypes[4]==SR_KEMIP_STR) {
1296 ret = ((sr_kemi_fmnsnss_f)(ket->func))(env_R->msg,
1297 vps[0].n, &vps[1].s, vps[2].n, &vps[3].s, &vps[4].s);
1298 return sr_kemi_ruby_return_int(ket, ret);
1299 } else if(ket->ptypes[0]==SR_KEMIP_INT
1300 && ket->ptypes[1]==SR_KEMIP_STR
1301 && ket->ptypes[2]==SR_KEMIP_INT
1302 && ket->ptypes[3]==SR_KEMIP_STR
1303 && ket->ptypes[4]==SR_KEMIP_INT) {
1304 ret = ((sr_kemi_fmnsnsn_f)(ket->func))(env_R->msg,
1305 vps[0].n, &vps[1].s, vps[2].n, &vps[3].s, vps[4].n);
1306 return sr_kemi_ruby_return_int(ket, ret);
1307 } else if(ket->ptypes[0]==SR_KEMIP_INT
1308 && ket->ptypes[1]==SR_KEMIP_STR
1309 && ket->ptypes[2]==SR_KEMIP_INT
1310 && ket->ptypes[3]==SR_KEMIP_INT
1311 && ket->ptypes[4]==SR_KEMIP_STR) {
1312 ret = ((sr_kemi_fmnsnns_f)(ket->func))(env_R->msg,
1313 vps[0].n, &vps[1].s, vps[2].n, vps[3].n, &vps[4].s);
1314 return sr_kemi_ruby_return_int(ket, ret);
1315 } else if(ket->ptypes[0]==SR_KEMIP_INT
1316 && ket->ptypes[1]==SR_KEMIP_STR
1317 && ket->ptypes[2]==SR_KEMIP_INT
1318 && ket->ptypes[3]==SR_KEMIP_INT
1319 && ket->ptypes[4]==SR_KEMIP_INT) {
1320 ret = ((sr_kemi_fmnsnnn_f)(ket->func))(env_R->msg,
1321 vps[0].n, &vps[1].s, vps[2].n, vps[3].n, vps[4].n);
1322 return sr_kemi_ruby_return_int(ket, ret);
1323 } else if(ket->ptypes[0]==SR_KEMIP_INT
1324 && ket->ptypes[1]==SR_KEMIP_INT
1325 && ket->ptypes[2]==SR_KEMIP_STR
1326 && ket->ptypes[3]==SR_KEMIP_STR
1327 && ket->ptypes[4]==SR_KEMIP_STR) {
1328 ret = ((sr_kemi_fmnnsss_f)(ket->func))(env_R->msg,
1329 vps[0].n, vps[1].n, &vps[2].s, &vps[3].s, &vps[4].s);
1330 return sr_kemi_ruby_return_int(ket, ret);
1331 } else if(ket->ptypes[0]==SR_KEMIP_INT
1332 && ket->ptypes[1]==SR_KEMIP_INT
1333 && ket->ptypes[2]==SR_KEMIP_STR
1334 && ket->ptypes[3]==SR_KEMIP_STR
1335 && ket->ptypes[4]==SR_KEMIP_INT) {
1336 ret = ((sr_kemi_fmnnssn_f)(ket->func))(env_R->msg,
1337 vps[0].n, vps[1].n, &vps[2].s, &vps[3].s, vps[4].n);
1338 return sr_kemi_ruby_return_int(ket, ret);
1339 } else if(ket->ptypes[0]==SR_KEMIP_INT
1340 && ket->ptypes[1]==SR_KEMIP_INT
1341 && ket->ptypes[2]==SR_KEMIP_STR
1342 && ket->ptypes[3]==SR_KEMIP_INT
1343 && ket->ptypes[4]==SR_KEMIP_STR) {
1344 ret = ((sr_kemi_fmnnsns_f)(ket->func))(env_R->msg,
1345 vps[0].n, vps[1].n, &vps[2].s, vps[3].n, &vps[4].s);
1346 return sr_kemi_ruby_return_int(ket, ret);
1347 } else if(ket->ptypes[0]==SR_KEMIP_INT
1348 && ket->ptypes[1]==SR_KEMIP_INT
1349 && ket->ptypes[2]==SR_KEMIP_STR
1350 && ket->ptypes[3]==SR_KEMIP_INT
1351 && ket->ptypes[4]==SR_KEMIP_INT) {
1352 ret = ((sr_kemi_fmnnsnn_f)(ket->func))(env_R->msg,
1353 vps[0].n, vps[1].n, &vps[2].s, vps[3].n, vps[4].n);
1354 return sr_kemi_ruby_return_int(ket, ret);
1355 } else if(ket->ptypes[0]==SR_KEMIP_INT
1356 && ket->ptypes[1]==SR_KEMIP_INT
1357 && ket->ptypes[2]==SR_KEMIP_INT
1358 && ket->ptypes[3]==SR_KEMIP_STR
1359 && ket->ptypes[4]==SR_KEMIP_STR) {
1360 ret = ((sr_kemi_fmnnnss_f)(ket->func))(env_R->msg,
1361 vps[0].n, vps[1].n, vps[2].n, &vps[3].s, &vps[4].s);
1362 return sr_kemi_ruby_return_int(ket, ret);
1363 } else if(ket->ptypes[0]==SR_KEMIP_INT
1364 && ket->ptypes[1]==SR_KEMIP_INT
1365 && ket->ptypes[2]==SR_KEMIP_INT
1366 && ket->ptypes[3]==SR_KEMIP_STR
1367 && ket->ptypes[4]==SR_KEMIP_INT) {
1368 ret = ((sr_kemi_fmnnnsn_f)(ket->func))(env_R->msg,
1369 vps[0].n, vps[1].n, vps[2].n, &vps[3].s, vps[4].n);
1370 return sr_kemi_ruby_return_int(ket, ret);
1371 } else if(ket->ptypes[0]==SR_KEMIP_INT
1372 && ket->ptypes[1]==SR_KEMIP_INT
1373 && ket->ptypes[2]==SR_KEMIP_INT
1374 && ket->ptypes[3]==SR_KEMIP_INT
1375 && ket->ptypes[4]==SR_KEMIP_STR) {
1376 ret = ((sr_kemi_fmnnnns_f)(ket->func))(env_R->msg,
1377 vps[0].n, vps[1].n, vps[2].n, vps[3].n, &vps[4].s);
1378 return sr_kemi_ruby_return_int(ket, ret);
1379 } else if(ket->ptypes[0]==SR_KEMIP_INT
1380 && ket->ptypes[1]==SR_KEMIP_INT
1381 && ket->ptypes[2]==SR_KEMIP_INT
1382 && ket->ptypes[3]==SR_KEMIP_INT
1383 && ket->ptypes[4]==SR_KEMIP_INT) {
1384 ret = ((sr_kemi_fmnnnnn_f)(ket->func))(env_R->msg,
1385 vps[0].n, vps[1].n, vps[2].n, vps[3].n, vps[4].n);
1386 return sr_kemi_ruby_return_int(ket, ret);
1387 } else {
1388 LM_ERR("invalid parameters for: %.*s\n", fname->len, fname->s);
1389 return Qfalse;
1390 }
1391 break;
1392 case 6:
1393 if(ket->ptypes[0]==SR_KEMIP_STR
1394 && ket->ptypes[1]==SR_KEMIP_STR
1395 && ket->ptypes[2]==SR_KEMIP_STR
1396 && ket->ptypes[3]==SR_KEMIP_STR
1397 && ket->ptypes[4]==SR_KEMIP_STR
1398 && ket->ptypes[5]==SR_KEMIP_STR) {
1399 ret = ((sr_kemi_fmssssss_f)(ket->func))(env_R->msg,
1400 &vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
1401 &vps[4].s, &vps[5].s);
1402 return sr_kemi_ruby_return_int(ket, ret);
1403 } else {
1404 LM_ERR("invalid parameters for: %.*s\n",
1405 fname->len, fname->s);
1406 return Qfalse;
1407 }
1408 break;
1409 default:
1410 LM_ERR("invalid parameters for: %.*s\n",
1411 fname->len, fname->s);
1412 return Qfalse;
1413 }
1414 }
1415
1416 /**
1417 *
1418 */
sr_kemi_ruby_exec_func(ksr_ruby_context_t * R,int eidx,int argc,VALUE * argv,VALUE self)1419 VALUE sr_kemi_ruby_exec_func(ksr_ruby_context_t *R, int eidx, int argc,
1420 VALUE* argv, VALUE self)
1421 {
1422 sr_kemi_t *ket;
1423 int ret;
1424 struct timeval tvb = {0}, tve = {0};
1425 struct timezone tz;
1426 unsigned int tdiff;
1427
1428 ket = sr_kemi_ruby_export_get(eidx);
1429
1430 LM_DBG("executing %p eidx %d\n", ket, eidx);
1431
1432 if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0)
1433 && is_printable(cfg_get(core, core_cfg, latency_log))) {
1434 gettimeofday(&tvb, &tz);
1435 }
1436
1437 ret = sr_kemi_ruby_exec_func_ex(R, ket, argc, argv, self);
1438
1439 if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0)
1440 && is_printable(cfg_get(core, core_cfg, latency_log))) {
1441 gettimeofday(&tve, &tz);
1442 tdiff = (tve.tv_sec - tvb.tv_sec) * 1000000
1443 + (tve.tv_usec - tvb.tv_usec);
1444 if(tdiff >= cfg_get(core, core_cfg, latency_limit_action)) {
1445 LOG(cfg_get(core, core_cfg, latency_log),
1446 "alert - action KSR.%s%s%s(...)"
1447 " took too long [%u us]\n",
1448 (ket->mname.len>0)?ket->mname.s:"",
1449 (ket->mname.len>0)?".":"", ket->fname.s,
1450 tdiff);
1451 }
1452 }
1453
1454 return ret;
1455 }
1456
1457 /**
1458 *
1459 */
app_ruby_run_ex(sip_msg_t * msg,char * func,char * p1,char * p2,char * p3,int emode)1460 int app_ruby_run_ex(sip_msg_t *msg, char *func, char *p1, char *p2,
1461 char *p3, int emode)
1462 {
1463 sip_msg_t *bmsg;
1464 ksr_ruby_data_t rbdata;
1465 int rberr = 0;
1466 VALUE rbres;
1467
1468 if(_sr_R_env.rinit==0) {
1469 LM_ERR("js loading state not initialized (call: %s)\n", func);
1470 return -1;
1471 }
1472 /* check the script version loaded */
1473 app_ruby_kemi_reload_script();
1474
1475 memset(&rbdata, 0, sizeof(ksr_ruby_data_t));
1476 rbdata.robj = rb_mKernel;
1477 rbdata.metid = rb_intern(func);
1478
1479 LM_DBG("executing ruby function: [[%s]]\n", func);
1480 bmsg = _sr_R_env.msg;
1481 _sr_R_env.msg = msg;
1482 if(p1!=NULL) {
1483 rbdata.vargs[rbdata.nargs] = rb_str_new_cstr(p1);
1484 rbdata.nargs++;
1485 if(p2!=NULL) {
1486 rbdata.vargs[rbdata.nargs] = rb_str_new_cstr(p2);
1487 rbdata.nargs++;
1488 if(p3!=NULL) {
1489 rbdata.vargs[rbdata.nargs] = rb_str_new_cstr(p3);
1490 rbdata.nargs++;
1491 }
1492 }
1493 }
1494
1495 rbres = rb_protect(ksr_ruby_exec_callback, (VALUE)&rbdata, &rberr);
1496
1497 _sr_R_env.msg = bmsg;
1498
1499 if (rberr) {
1500 if(app_ruby_print_last_exception()==0) {
1501 LM_ERR("ruby exception (%d) on callback for: %s (res type: %d)\n",
1502 rberr, func, TYPE(rbres));
1503 return -1;
1504 }
1505 }
1506
1507 return 1;
1508 }
1509
1510 /**
1511 *
1512 */
app_ruby_run(sip_msg_t * msg,char * func,char * p1,char * p2,char * p3)1513 int app_ruby_run(sip_msg_t *msg, char *func, char *p1, char *p2,
1514 char *p3)
1515 {
1516 return app_ruby_run_ex(msg, func, p1, p2, p3, 0);
1517 }
1518
1519 /**
1520 *
1521 */
app_ruby_runstring(sip_msg_t * msg,char * script)1522 int app_ruby_runstring(sip_msg_t *msg, char *script)
1523 {
1524 LM_ERR("not implemented\n");
1525 return -1;
1526 }
1527
1528 /**
1529 *
1530 */
app_ruby_dostring(sip_msg_t * msg,char * script)1531 int app_ruby_dostring(sip_msg_t *msg, char *script)
1532 {
1533 LM_ERR("not implemented\n");
1534 return -1;
1535 }
1536
1537 /**
1538 *
1539 */
app_ruby_dofile(sip_msg_t * msg,char * script)1540 int app_ruby_dofile(sip_msg_t *msg, char *script)
1541 {
1542 LM_ERR("not implemented\n");
1543 return -1;
1544 }
1545
1546 ksr_ruby_export_t *_sr_R_KSRMethods = NULL;
1547 #define SR_RUBY_KSR_MODULES_SIZE 256
1548 #define SR_RUBY_KSR_METHODS_SIZE (SR_KEMI_RUBY_EXPORT_SIZE + SR_RUBY_KSR_MODULES_SIZE)
1549
1550 static VALUE _ksr_mKSR;
1551 static VALUE _ksr_mSMD[SR_RUBY_KSR_MODULES_SIZE];
1552
1553 /**
1554 *
1555 */
ksr_app_ruby_toupper(char * bin,char * bout)1556 void ksr_app_ruby_toupper(char *bin, char *bout)
1557 {
1558 int i;
1559 for(i=0; bin[i]!='\0'; i++) {
1560 bout[i] = (char)toupper(bin[i]);
1561 }
1562 bout[i] = '\0';
1563 }
1564 /**
1565 *
1566 */
app_ruby_kemi_export_libs(void)1567 int app_ruby_kemi_export_libs(void)
1568 {
1569 ksr_ruby_export_t *_sr_crt_R_KSRMethods = NULL;
1570 sr_kemi_module_t *emods = NULL;
1571 int emods_size = 0;
1572 int i;
1573 int k;
1574 int n;
1575 int m;
1576 char rmname[128];
1577
1578 _sr_R_KSRMethods = malloc(SR_RUBY_KSR_METHODS_SIZE * sizeof(ksr_ruby_export_t));
1579 if(_sr_R_KSRMethods==NULL) {
1580 LM_ERR("no more pkg memory\n");
1581 return 0;
1582 }
1583 memset(_sr_R_KSRMethods, 0, SR_RUBY_KSR_METHODS_SIZE * sizeof(ksr_ruby_export_t));
1584
1585 emods_size = sr_kemi_modules_size_get();
1586 emods = sr_kemi_modules_get();
1587
1588 n = 0;
1589 _sr_crt_R_KSRMethods = _sr_R_KSRMethods;
1590 if(emods_size==0 || emods[0].kexp==NULL) {
1591 LM_ERR("no kemi exports registered\n");
1592 return 0;
1593 }
1594
1595 /* toplevel module KSR */
1596 _ksr_mKSR = rb_define_module("KSR");
1597
1598 for(i=0; emods[0].kexp[i].func!=NULL; i++) {
1599 LM_DBG("exporting KSR.%s(...)\n", emods[0].kexp[i].fname.s);
1600 _sr_crt_R_KSRMethods[i].mname = "";
1601 _sr_crt_R_KSRMethods[i].fname = emods[0].kexp[i].fname.s;
1602 _sr_crt_R_KSRMethods[i].func =
1603 sr_kemi_ruby_export_associate(&emods[0].kexp[i]);
1604 if(_sr_crt_R_KSRMethods[i].func == NULL) {
1605 LM_ERR("failed to associate kemi function with ruby export\n");
1606 free(_sr_R_KSRMethods);
1607 _sr_R_KSRMethods = NULL;
1608 return 0;
1609 }
1610
1611 rb_define_singleton_method(_ksr_mKSR, _sr_crt_R_KSRMethods[i].fname,
1612 _sr_crt_R_KSRMethods[i].func, -1);
1613
1614 n++;
1615 }
1616
1617 m = 0;
1618
1619 if(_ksr_app_ruby_xval_mode==0) {
1620 /* pv submodule */
1621 _ksr_mSMD[m] = rb_define_module_under(_ksr_mKSR, "PV");
1622 for(i=0; _sr_kemi_pv_R_Map[i].fname!=0; i++) {
1623 LM_DBG("exporting KSR.PV.%s(...)\n", _sr_kemi_pv_R_Map[i].fname);
1624 rb_define_singleton_method(_ksr_mSMD[m], _sr_kemi_pv_R_Map[i].fname,
1625 _sr_kemi_pv_R_Map[i].func, -1);
1626 }
1627 LM_DBG("initialized kemi sub-module: KSR.PV\n");
1628 m++;
1629 }
1630
1631 /* x submodule */
1632 _ksr_mSMD[m] = rb_define_module_under(_ksr_mKSR, "X");
1633 for(i=0; _sr_kemi_x_R_Map[i].fname!=0; i++) {
1634 LM_DBG("exporting KSR.X.%s(...)\n", _sr_kemi_x_R_Map[i].fname);
1635 rb_define_singleton_method(_ksr_mSMD[m], _sr_kemi_x_R_Map[i].fname,
1636 _sr_kemi_x_R_Map[i].func, -1);
1637 }
1638 LM_DBG("initialized kemi sub-module: KSR.X\n");
1639 m++;
1640
1641 /* registered kemi modules */
1642 if(emods_size>1) {
1643 for(k=1; k<emods_size; k++) {
1644 if((_ksr_app_ruby_xval_mode==0) && emods[k].kexp[0].mname.len==2
1645 && strncasecmp(emods[k].kexp[0].mname.s, "pv", 2)==0) {
1646 LM_DBG("skipping external pv sub-module\n");
1647 continue;
1648 }
1649 n++;
1650 _sr_crt_R_KSRMethods = _sr_R_KSRMethods + n;
1651 ksr_app_ruby_toupper(emods[k].kexp[0].mname.s, rmname);
1652 _ksr_mSMD[m] = rb_define_module_under(_ksr_mKSR, rmname);
1653 for(i=0; emods[k].kexp[i].func!=NULL; i++) {
1654 _sr_crt_R_KSRMethods[i].mname = emods[k].kexp[0].mname.s;
1655 _sr_crt_R_KSRMethods[i].fname = emods[k].kexp[i].fname.s;
1656 _sr_crt_R_KSRMethods[i].func =
1657 sr_kemi_ruby_export_associate(&emods[k].kexp[i]);
1658 LM_DBG("exporting KSR.%s.%s(...)\n", rmname,
1659 emods[k].kexp[i].fname.s);
1660 if(_sr_crt_R_KSRMethods[i].func == NULL) {
1661 LM_ERR("failed to associate kemi function with func export\n");
1662 free(_sr_R_KSRMethods);
1663 _sr_R_KSRMethods = NULL;
1664 return 0;
1665 }
1666
1667 rb_define_singleton_method(_ksr_mSMD[m], _sr_crt_R_KSRMethods[i].fname,
1668 _sr_crt_R_KSRMethods[i].func, -1);
1669
1670 n++;
1671 }
1672 m++;
1673 LM_DBG("initialized kemi sub-module: KSR.%s\n", rmname);
1674 }
1675 }
1676 LM_DBG("module 'KSR' has been initialized\n");
1677
1678 return 1;
1679 }
1680
1681 static const char* app_ruby_rpc_reload_doc[2] = {
1682 "Reload javascript file",
1683 0
1684 };
1685
1686
app_ruby_rpc_reload(rpc_t * rpc,void * ctx)1687 static void app_ruby_rpc_reload(rpc_t* rpc, void* ctx)
1688 {
1689 int v;
1690 void *vh;
1691
1692 if(_sr_ruby_load_file.s == NULL && _sr_ruby_load_file.len<=0) {
1693 LM_WARN("script file path not provided\n");
1694 rpc->fault(ctx, 500, "No script file");
1695 return;
1696 }
1697 if(_sr_ruby_reload_version == NULL) {
1698 LM_WARN("reload not enabled\n");
1699 rpc->fault(ctx, 500, "Reload not enabled");
1700 return;
1701 }
1702
1703 v = *_sr_ruby_reload_version;
1704 *_sr_ruby_reload_version += 1;
1705 LM_INFO("marking for reload ruby script file: %.*s (%d / %d => %d)\n",
1706 _sr_ruby_load_file.len, _sr_ruby_load_file.s,
1707 _sr_ruby_local_version, v, *_sr_ruby_reload_version);
1708
1709 if (rpc->add(ctx, "{", &vh) < 0) {
1710 rpc->fault(ctx, 500, "Server error");
1711 return;
1712 }
1713 rpc->struct_add(vh, "dd",
1714 "old", v,
1715 "new", *_sr_ruby_reload_version);
1716 }
1717
1718 static const char* app_ruby_rpc_api_list_doc[2] = {
1719 "List kemi exports to ruby",
1720 0
1721 };
1722
app_ruby_rpc_api_list(rpc_t * rpc,void * ctx)1723 static void app_ruby_rpc_api_list(rpc_t* rpc, void* ctx)
1724 {
1725 int i;
1726 int n;
1727 sr_kemi_t *ket;
1728 void* th;
1729 void* sh;
1730 void* ih;
1731
1732 if (rpc->add(ctx, "{", &th) < 0) {
1733 rpc->fault(ctx, 500, "Internal error root reply");
1734 return;
1735 }
1736 n = 0;
1737 for(i=0; i<SR_KEMI_RUBY_EXPORT_SIZE; i++) {
1738 ket = sr_kemi_ruby_export_get(i);
1739 if(ket==NULL) continue;
1740 n++;
1741 }
1742
1743 if(rpc->struct_add(th, "d[",
1744 "msize", n,
1745 "methods", &ih)<0)
1746 {
1747 rpc->fault(ctx, 500, "Internal error array structure");
1748 return;
1749 }
1750 for(i=0; i<SR_KEMI_RUBY_EXPORT_SIZE; i++) {
1751 ket = sr_kemi_ruby_export_get(i);
1752 if(ket==NULL) continue;
1753 if(rpc->struct_add(ih, "{", "func", &sh)<0) {
1754 rpc->fault(ctx, 500, "Internal error internal structure");
1755 return;
1756 }
1757 if(rpc->struct_add(sh, "SSSS",
1758 "ret", sr_kemi_param_map_get_name(ket->rtype),
1759 "module", &ket->mname,
1760 "name", &ket->fname,
1761 "params", sr_kemi_param_map_get_params(ket->ptypes))<0) {
1762 LM_ERR("failed to add the structure with attributes (%d)\n", i);
1763 rpc->fault(ctx, 500, "Internal error creating dest struct");
1764 return;
1765 }
1766 }
1767 }
1768
1769 /**
1770 *
1771 */
1772 rpc_export_t app_ruby_rpc_cmds[] = {
1773 {"app_ruby.reload", app_ruby_rpc_reload,
1774 app_ruby_rpc_reload_doc, 0},
1775 {"app_ruby.api_list", app_ruby_rpc_api_list,
1776 app_ruby_rpc_api_list_doc, 0},
1777 {0, 0, 0, 0}
1778 };
1779
1780 /**
1781 *
1782 */
app_ruby_init_rpc(void)1783 int app_ruby_init_rpc(void)
1784 {
1785 if (rpc_register_array(app_ruby_rpc_cmds)!=0) {
1786 LM_ERR("failed to register RPC commands\n");
1787 return -1;
1788 }
1789 return 0;
1790 }
1791