- controlled via xval_mode module parameter
- workaround for a reported regression causing crash by using core
KSR::PV exports (GH #2180)
(cherry picked from commit 9bafd4c4e09825b25a84bb35a6dc4a39dbd07b73)
... | ... |
@@ -41,6 +41,8 @@ |
41 | 41 |
#undef xmalloc |
42 | 42 |
#undef xfree |
43 | 43 |
|
44 |
+extern int _ksr_app_ruby_xval_mode; |
|
45 |
+ |
|
44 | 46 |
int app_ruby_kemi_export_libs(void); |
45 | 47 |
|
46 | 48 |
typedef struct _sr_ruby_env |
... | ... |
@@ -245,6 +247,333 @@ int sr_kemi_ruby_return_int(sr_kemi_t *ket, int rc) |
245 | 247 |
return Qfalse; |
246 | 248 |
} |
247 | 249 |
|
250 |
+/** |
|
251 |
+ * |
|
252 |
+ */ |
|
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 |
+ */ |
|
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 |
+ */ |
|
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 |
+ */ |
|
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 |
+ */ |
|
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 |
+ */ |
|
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 |
+ */ |
|
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 |
+ */ |
|
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 |
+ */ |
|
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 |
+ |
|
248 | 577 |
/** |
249 | 578 |
* |
250 | 579 |
*/ |
... | ... |
@@ -428,7 +757,12 @@ VALUE sr_kemi_ruby_return_xval(sr_kemi_t *ket, sr_kemi_xval_t *rx) |
428 | 757 |
case SR_KEMIP_INT: |
429 | 758 |
return INT2NUM(rx->v.n); |
430 | 759 |
case SR_KEMIP_STR: |
431 |
- return rb_str_new(rx->v.s.s, rx->v.s.len); |
|
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 |
+ } |
|
432 | 766 |
case SR_KEMIP_BOOL: |
433 | 767 |
if(rx->v.n!=SR_KEMI_FALSE) { |
434 | 768 |
return Qtrue; |
... | ... |
@@ -1274,6 +1608,18 @@ int app_ruby_kemi_export_libs(void) |
1274 | 1608 |
|
1275 | 1609 |
m = 0; |
1276 | 1610 |
|
1611 |
+ if(_ksr_app_ruby_xval_mode==0) { |
|
1612 |
+ /* pv submodule */ |
|
1613 |
+ _ksr_mSMD[m] = rb_define_module_under(_ksr_mKSR, "PV"); |
|
1614 |
+ for(i=0; _sr_kemi_pv_R_Map[i].fname!=0; i++) { |
|
1615 |
+ LM_DBG("exporting KSR.PV.%s(...)\n", _sr_kemi_pv_R_Map[i].fname); |
|
1616 |
+ rb_define_singleton_method(_ksr_mSMD[m], _sr_kemi_pv_R_Map[i].fname, |
|
1617 |
+ _sr_kemi_pv_R_Map[i].func, -1); |
|
1618 |
+ } |
|
1619 |
+ LM_DBG("initialized kemi sub-module: KSR.PV\n"); |
|
1620 |
+ m++; |
|
1621 |
+ } |
|
1622 |
+ |
|
1277 | 1623 |
/* x submodule */ |
1278 | 1624 |
_ksr_mSMD[m] = rb_define_module_under(_ksr_mKSR, "X"); |
1279 | 1625 |
for(i=0; _sr_kemi_x_R_Map[i].fname!=0; i++) { |
... | ... |
@@ -1287,6 +1633,11 @@ int app_ruby_kemi_export_libs(void) |
1287 | 1633 |
/* registered kemi modules */ |
1288 | 1634 |
if(emods_size>1) { |
1289 | 1635 |
for(k=1; k<emods_size; k++) { |
1636 |
+ if((_ksr_app_ruby_xval_mode==0) && emods[k].kexp[0].mname.len==2 |
|
1637 |
+ && strncasecmp(emods[k].kexp[0].mname.s, "pv", 2)==0) { |
|
1638 |
+ LM_DBG("skipping external pv sub-module\n"); |
|
1639 |
+ continue; |
|
1640 |
+ } |
|
1290 | 1641 |
n++; |
1291 | 1642 |
_sr_crt_R_KSRMethods = _sr_R_KSRMethods + n; |
1292 | 1643 |
ksr_app_ruby_toupper(emods[k].kexp[0].mname.s, rmname); |
... | ... |
@@ -52,6 +52,7 @@ static int w_app_ruby_run3(sip_msg_t *msg, char *func, char *p1, char *p2, |
52 | 52 |
static int fixup_ruby_run(void** param, int param_no); |
53 | 53 |
|
54 | 54 |
extern str _sr_ruby_load_file; |
55 |
+int _ksr_app_ruby_xval_mode = 0; |
|
55 | 56 |
|
56 | 57 |
/* clang-format off */ |
57 | 58 |
static cmd_export_t cmds[]={ |
... | ... |
@@ -69,6 +70,7 @@ static cmd_export_t cmds[]={ |
69 | 70 |
|
70 | 71 |
static param_export_t params[]={ |
71 | 72 |
{"load", PARAM_STR, &_sr_ruby_load_file}, |
73 |
+ {"xval_mode", PARAM_INT, &_ksr_app_ruby_xval_mode}, |
|
72 | 74 |
{0, 0, 0} |
73 | 75 |
}; |
74 | 76 |
|