Changeset 637:22e8fac3b2d6 in freeDiameter for extensions/dbg_interactive/dbg_interactive.i
- Timestamp:
- Dec 16, 2010, 6:56:41 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/dbg_interactive/dbg_interactive.i
r636 r637 47 47 /* Include standard types & functions used in freeDiameter headers */ 48 48 %include <stdint.i> 49 %include <cdata.i>49 //%include <cdata.i> 50 50 %include <cstring.i> 51 51 %include <typemaps.i> 52 52 53 /* Some functions are not available through the wrapper */54 %ignore fd_lib_init;55 %ignore fd_lib_fini;56 /* -- the following functions are better accessed differently, but we leave their definitions just in case57 %ignore fd_dict_init;58 %ignore fd_dict_fini;59 %ignore fd_sess_handler_create_internal;60 %ignore fd_sess_handler_destroy;61 %ignore fd_sess_new;62 %ignore fd_sess_getsid;63 %ignore fd_sess_destroy;64 %ignore fd_sess_reclaim;65 %ignore fd_sess_state_store_internal;66 %ignore fd_sess_state_retrieve_internal;67 %ignore fd_rtd_init;68 %ignore fd_rtd_free;69 %ignore fd_rtd_candidate_add;70 %ignore fd_rtd_candidate_del;71 %ignore fd_rtd_candidate_extract;72 %ignore fd_rtd_error_add;73 */74 53 75 54 /* Inline functions seems to give problems to SWIG -- just remove the inline definition */ … … 77 56 %enddef 78 57 58 79 59 /* Make some global-variables read-only (mainly to avoid warnings) */ 80 60 %immutable fd_g_config; 81 61 %immutable peer_state_str; 82 62 83 84 /* Create a generic error handling mechanism so that functions can provoke an exception */ 63 /***************** 64 * Exceptions * 65 *****************/ 85 66 %{ 86 67 /* This is not thread-safe etc. but it should work /most of the time/. */ … … 128 109 ***********************************/ 129 110 130 %apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; 111 %apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; /* fd_hash */ 131 112 113 /* Generic typemap for functions that create something */ 132 114 %typemap(in, numinputs=0,noblock=1) SWIGTYPE ** OUTPUT (void *temp = NULL) { 133 115 $1 = (void *)&temp; … … 137 119 } 138 120 139 %apply int * OUTPUT { enum dict_object_type * type }; 140 %apply (char *STRING, size_t LENGTH) { (char * sid, size_t len) }; 141 %apply SWIGTYPE ** OUTPUT { struct session ** session }; 142 %apply int * OUTPUT { int * new }; 143 144 /* Callbacks defined in python */ 121 /* To allow passing callback functions defined in python */ 145 122 %typemap(in) PyObject *PyCb { 146 123 if (!PyCallable_Check($input)) { … … 152 129 153 130 154 155 131 /********************************************************* 156 132 Now, create wrappers for (almost) all objects from fD API … … 160 136 %include "freeDiameter/freeDiameter.h" 161 137 138 /* Most of the functions from the API are not directly usable "as is". 139 See the specific following files and the dbg_interactive.py.sample file 140 for more usable python-style versions. 141 */ 162 142 143 %include "lists.i" 144 %include "dictionary.i" 145 %include "sessions.i" 146 %include "routing.i" 147 %include "messages.i" 148 %include "dispatch.i" 149 %include "queues.i" 163 150 164 /**********************************************************/ 165 /* The remaining of this file allows easier manipulation of 166 the structures and functions of fD by providing wrapper-specific 167 extensions to the freeDiameter API. 168 169 /****** LISTS *********/ 170 171 %extend fd_list { 172 /* allow a parameter in the constructor, and perform the fd_list_init operation */ 173 fd_list(void * o = NULL) { 174 struct fd_list * li; 175 li = (struct fd_list *) malloc(sizeof(struct fd_list)); 176 if (!li) { 177 DI_ERROR_MALLOC; 178 return NULL; 179 } 180 fd_list_init(li, o); 181 return li; 182 } 183 /* Unlink before freeing */ 184 ~fd_list() { 185 fd_list_unlink($self); 186 free($self); 187 } 188 /* For debug, show the values of the list */ 189 void dump() { 190 fd_log_debug("list: %p\n", $self); 191 fd_log_debug(" - next: %p\n", $self->next); 192 fd_log_debug(" - prev: %p\n", $self->prev); 193 fd_log_debug(" - head: %p\n", $self->head); 194 fd_log_debug(" - o : %p\n", $self->o); 195 } 196 }; 197 198 /****** DICTIONARY *********/ 199 200 struct dictionary { 201 }; 202 203 %extend dictionary { 204 dictionary() { 205 struct dictionary * r = NULL; 206 int ret = fd_dict_init(&r); 207 if (ret != 0) { 208 DI_ERROR(ret, NULL, NULL); 209 return NULL; 210 } 211 return r; 212 } 213 ~dictionary() { 214 struct dictionary *d = self; 215 int ret = fd_dict_fini(&d); 216 if (ret != 0) { 217 DI_ERROR(ret, NULL, NULL); 218 } 219 return; 220 } 221 void dump() { 222 fd_dict_dump($self); 223 } 224 PyObject * vendors_list() { 225 uint32_t *list = NULL, *li; 226 PyObject * ret; 227 SWIG_PYTHON_THREAD_BEGIN_BLOCK; 228 ret = PyList_New(0); 229 list = fd_dict_get_vendorid_list($self); 230 for (li = list; *li != 0; li++) { 231 PyList_Append(ret, PyInt_FromLong((long)*li)); 232 } 233 free(list); 234 SWIG_PYTHON_THREAD_END_BLOCK; 235 return ret; 236 } 237 struct dict_object * new_obj(enum dict_object_type type, void * data, struct dict_object * parent = NULL) { 238 struct dict_object * obj = NULL; 239 int ret = fd_dict_new($self, type, data, parent, &obj); 240 if (ret != 0) { 241 DI_ERROR(ret, NULL, NULL); 242 return NULL; 243 } 244 return obj; 245 } 246 struct dict_object * search(enum dict_object_type type, int criteria, int what_by_val) { 247 struct dict_object * obj = NULL; 248 int ret = fd_dict_search ( $self, type, criteria, &what_by_val, &obj, ENOENT ); 249 if (ret != 0) { 250 DI_ERROR(ret, NULL, NULL); 251 return NULL; 252 } 253 return obj; 254 } 255 struct dict_object * search(enum dict_object_type type, int criteria, char * what_by_string) { 256 struct dict_object * obj = NULL; 257 int ret = fd_dict_search ( $self, type, criteria, what_by_string, &obj, ENOENT ); 258 if (ret != 0) { 259 DI_ERROR(ret, NULL, NULL); 260 return NULL; 261 } 262 return obj; 263 } 264 struct dict_object * search(enum dict_object_type type, int criteria, void * what) { 265 struct dict_object * obj = NULL; 266 int ret = fd_dict_search ( $self, type, criteria, what, &obj, ENOENT ); 267 if (ret != 0) { 268 DI_ERROR(ret, NULL, NULL); 269 return NULL; 270 } 271 return obj; 272 } 273 struct dict_object * error_cmd() { 274 struct dict_object * obj = NULL; 275 int ret = fd_dict_get_error_cmd ( $self, &obj ); 276 if (ret != 0) { 277 DI_ERROR(ret, NULL, NULL); 278 return NULL; 279 } 280 return obj; 281 } 282 } 283 284 struct dict_object { 285 }; 286 287 %extend dict_object { 288 dict_object() { 289 DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be created directly. Use fd_dict_new()."); 290 return NULL; 291 } 292 ~dict_object() { 293 DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be destroyed directly. Destroy the parent dictionary."); 294 return; 295 } 296 void dump() { 297 fd_dict_dump_object($self); 298 } 299 enum dict_object_type gettype() { 300 enum dict_object_type t; 301 int ret = fd_dict_gettype ( $self, &t); 302 if (ret != 0) { 303 DI_ERROR(ret, NULL, NULL); 304 return 0; 305 } 306 return t; 307 } 308 struct dictionary * getdict() { 309 struct dictionary *d; 310 int ret = fd_dict_getdict ( $self, &d ); 311 if (ret != 0) { 312 DI_ERROR(ret, NULL, NULL); 313 return NULL; 314 } 315 return d; 316 } 317 /* Since casting the pointer requires intelligence, we do it here instead of giving it to SWIG */ 318 PyObject * getval() { 319 /* first, get the type */ 320 enum dict_object_type t; 321 int ret = fd_dict_gettype ( $self, &t); 322 if (ret != 0) { 323 DI_ERROR(ret, NULL, NULL); 324 return NULL; 325 } 326 switch (t) { 327 %define %GETVAL_CASE(TYPE,STRUCT) 328 case TYPE: { 329 PyObject * v = NULL; 330 struct STRUCT * data = NULL; 331 data = malloc(sizeof(struct STRUCT)); 332 if (!data) { 333 DI_ERROR_MALLOC; 334 return NULL; 335 } 336 ret = fd_dict_getval($self, data); 337 if (ret != 0) { 338 DI_ERROR(ret, NULL, NULL); 339 free(data); 340 return NULL; 341 } 342 SWIG_PYTHON_THREAD_BEGIN_BLOCK; 343 v = SWIG_NewPointerObj((void *)data, SWIGTYPE_p_##STRUCT, SWIG_POINTER_OWN ); 344 Py_XINCREF(v); 345 SWIG_PYTHON_THREAD_END_BLOCK; 346 return v; 347 } break 348 %enddef 349 %GETVAL_CASE( DICT_VENDOR, dict_vendor_data ); 350 %GETVAL_CASE( DICT_APPLICATION, dict_application_data ); 351 %GETVAL_CASE( DICT_TYPE, dict_type_data ); 352 %GETVAL_CASE( DICT_ENUMVAL, dict_enumval_data ); 353 %GETVAL_CASE( DICT_AVP, dict_avp_data ); 354 %GETVAL_CASE( DICT_COMMAND, dict_cmd_data ); 355 %GETVAL_CASE( DICT_RULE, dict_rule_data ); 356 default: 357 DI_ERROR(EINVAL, PyExc_SystemError, "Internal error: Got invalid object type"); 358 } 359 return NULL; 360 } 361 } 362 363 364 /* The following wrapper leaks memory each time an union avp_value is assigned an octet string. 365 TODO: fix this leak by better understanding SWIG... 366 -- the alternative is to uncomment the "free" statements bellow, but then it is easy to 367 create a segmentation fault by assigning first an integer, then an octetstring. 368 */ 369 %extend avp_value { 370 /* The following hack in the proxy file allows assigning the octet string directly like this: 371 avp_value.os = "blabla" 372 */ 373 %pythoncode 374 { 375 __swig_setmethods__["os"] = _fDpy.avp_value_os_set 376 if _newclass:os = _swig_property(_fDpy.avp_value_os_get, _fDpy.avp_value_os_set) 377 } 378 void os_set(char *STRING, size_t LENGTH) { 379 /* free($self->os.data); -- do not free, in case the previous value was not an OS */ 380 $self->os.data = malloc(LENGTH); 381 if (!$self->os.data) { 382 DI_ERROR_MALLOC; 383 return; 384 } 385 memcpy($self->os.data, STRING, LENGTH); 386 $self->os.len = LENGTH; 387 } 388 void os_set(avp_value_os * os) { 389 /* free($self->os.data); -- do not free, in case the previous value was not an OS */ 390 $self->os.data = malloc(os->len); 391 if (!$self->os.data) { 392 DI_ERROR_MALLOC; 393 return; 394 } 395 memcpy($self->os.data, os->data, os->len); 396 $self->os.len = os->len; 397 } 398 }; 399 400 %extend avp_value_os { 401 void dump() { 402 %#define LEN_MAX 20 403 int i, n=LEN_MAX; 404 if ($self->len < LEN_MAX) 405 n = $self->len; 406 fd_log_debug("l:%u, v:[", $self->len); 407 for (i=0; i < n; i++) 408 fd_log_debug("%02.2X", $self->data[i]); 409 fd_log_debug("] '%.*s%s'\n", n, $self->data, n == LEN_MAX ? "..." : ""); 410 } 411 } 412 413 /****** SESSIONS *********/ 414 415 %{ 416 /* store the python callback function here */ 417 static PyObject * py_cleanup_cb = NULL; 418 /* call it (might be called from a different thread than the interpreter, when session times out) */ 419 static void call_the_python_cleanup_callback(session_state * state, char * sid) { 420 PyObject *result; 421 if (!py_cleanup_cb) 422 return; 423 424 /* Call the function */ 425 SWIG_PYTHON_THREAD_BEGIN_BLOCK; 426 result = PyEval_CallFunction(py_cleanup_cb, "(Os)", state, sid); 427 Py_XDECREF(result); 428 SWIG_PYTHON_THREAD_END_BLOCK; 429 return; 430 } 431 %} 432 433 struct session_handler { 434 }; 435 436 %extend session_handler { 437 session_handler() { 438 DI_ERROR(EINVAL, PyExc_SyntaxError, "a cleanup callback parameter is required."); 439 return NULL; 440 } 441 session_handler(PyObject * PyCb) { 442 struct session_handler * hdl = NULL; 443 int ret; 444 if (py_cleanup_cb) { 445 DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one session handler at a time is supported at the moment in this extension\n."); 446 return NULL; 447 } 448 py_cleanup_cb = PyCb; 449 Py_XINCREF(py_cleanup_cb); 450 451 ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback ); 452 if (ret != 0) { 453 DI_ERROR(ret, NULL, NULL); 454 return NULL; 455 } 456 return hdl; 457 } 458 ~session_handler() { 459 struct session_handler * hdl = self; 460 int ret = fd_sess_handler_destroy(&hdl); 461 if (ret != 0) { 462 DI_ERROR(ret, NULL, NULL); 463 } 464 /* Now free the callback */ 465 Py_XDECREF(py_cleanup_cb); 466 py_cleanup_cb = NULL; 467 return; 468 } 469 void dump() { 470 fd_sess_dump_hdl(0, $self); 471 } 472 } 473 474 struct session { 475 }; 476 477 %extend session { 478 /* The first two versions create a new session string. The third one allow to use an existing string. */ 479 session() { 480 int ret; 481 struct session * s = NULL; 482 ret = fd_sess_new(&s, fd_g_config->cnf_diamid, "dbg_interactive", sizeof("dbg_interactive")); 483 if (ret != 0) { 484 DI_ERROR(ret, NULL, NULL); 485 return NULL; 486 } 487 return s; 488 } 489 session(char * diamid, char * STRING, size_t LENGTH) { 490 int ret; 491 struct session * s = NULL; 492 ret = fd_sess_new(&s, diamid, STRING, LENGTH); 493 if (ret != 0) { 494 DI_ERROR(ret, NULL, NULL); 495 return NULL; 496 } 497 return s; 498 } 499 session(char * STRING, size_t LENGTH) { 500 int ret, n; 501 struct session * s = NULL; 502 ret = fd_sess_fromsid(STRING, LENGTH, &s, &n); 503 if (ret != 0) { 504 DI_ERROR(ret, NULL, NULL); 505 return NULL; 506 } 507 /* When defining n as OUTPUT parameter, we get something strange... Use fd_sess_fromsid if you need it */ 508 #if 0 509 if (n) { 510 fd_log_debug("A new session has been created\n"); 511 } else { 512 fd_log_debug("A session with same id already existed\n"); 513 } 514 #endif /* 0 */ 515 516 return s; 517 } 518 ~session() { 519 struct session * s = self; 520 int ret = fd_sess_reclaim(&s); 521 if (ret != 0) { 522 DI_ERROR(ret, NULL, NULL); 523 } 524 return; 525 } 526 char * getsid() { 527 int ret; 528 char * sid = NULL; 529 ret = fd_sess_getsid( $self, &sid); 530 if (ret != 0) { 531 DI_ERROR(ret, NULL, NULL); 532 return NULL; 533 } 534 return sid; 535 } 536 void settimeout(long seconds) { 537 struct timespec timeout; 538 int ret; 539 clock_gettime(CLOCK_REALTIME, &timeout); 540 timeout.tv_sec += seconds; 541 ret = fd_sess_settimeout( $self, &timeout ); 542 if (ret != 0) { 543 DI_ERROR(ret, NULL, NULL); 544 } 545 } 546 void dump() { 547 fd_sess_dump(0, $self); 548 } 549 void store(struct session_handler * handler, PyObject * state) { 550 int ret; 551 void * store = state; 552 Py_XINCREF(state); 553 ret = fd_sess_state_store_internal(handler, $self, (void *) &store); 554 if (ret != 0) { 555 DI_ERROR(ret, NULL, NULL); 556 } 557 } 558 PyObject * retrieve(struct session_handler * handler) { 559 int ret; 560 PyObject * state = NULL; 561 ret = fd_sess_state_retrieve_internal(handler, $self, (void *) &state); 562 if (ret != 0) { 563 DI_ERROR(ret, NULL, NULL); 564 return NULL; 565 } 566 if (state == NULL) { 567 Py_INCREF(Py_None); 568 return Py_None; 569 } 570 return state; 571 } 572 } 573 574 /****** ROUTING *********/ 575 576 struct rt_data { 577 }; 578 579 %extend rt_data { 580 rt_data() { 581 struct rt_data * r = NULL; 582 int ret = fd_rtd_init(&r); 583 if (ret != 0) { 584 DI_ERROR(ret, NULL, NULL); 585 return NULL; 586 } 587 return r; 588 } 589 ~rt_data() { 590 struct rt_data *r = self; 591 fd_rtd_free(&r); 592 } 593 void add(char * peerid, char * realm) { 594 int ret = fd_rtd_candidate_add($self, peerid, realm); 595 if (ret != 0) { 596 DI_ERROR(ret, NULL, NULL); 597 } 598 } 599 void remove(char * STRING, size_t LENGTH) { 600 fd_rtd_candidate_del($self, STRING, LENGTH); 601 } 602 void error(char * dest, char * STRING, size_t LENGTH, uint32_t rcode) { 603 int ret = fd_rtd_error_add($self, dest, (uint8_t *)STRING, LENGTH, rcode); 604 if (ret != 0) { 605 DI_ERROR(ret, NULL, NULL); 606 } 607 } 608 struct fd_list * extract_li(int score = 0) { 609 struct fd_list * li = NULL; 610 fd_rtd_candidate_extract($self, &li, score); 611 return li; 612 } 613 PyObject * extract(int score = 0) { 614 struct fd_list * list = NULL, *li; 615 PyObject * rl; 616 fd_rtd_candidate_extract($self, &list, score); 617 rl = PyList_New(0); 618 SWIG_PYTHON_THREAD_BEGIN_BLOCK; 619 for (li = list->next; li != list; li = li->next) { 620 PyList_Append(rl, SWIG_NewPointerObj((void *)li, SWIGTYPE_p_rtd_candidate, 0 )); 621 } 622 Py_XINCREF(rl); 623 SWIG_PYTHON_THREAD_END_BLOCK; 624 625 return rl; 626 } 627 } 628 629 %extend rtd_candidate { 630 void dump() { 631 fd_log_debug("candidate %p\n", $self); 632 fd_log_debug(" id : %s\n", $self->diamid); 633 fd_log_debug(" rlm: %s\n", $self->realm); 634 fd_log_debug(" sc : %d\n", $self->score); 635 } 636 } 637 638 639 640 /****** MESSAGES *********/ 641 642 struct msg { 643 }; 644 645 %extend msg { 646 msg() { 647 DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_COMMAND object parameter (or None) is required."); 648 return NULL; 649 } 650 msg(struct dict_object * model, int flags = MSGFL_ALLOC_ETEID) { 651 struct msg * m = NULL; 652 int ret = fd_msg_new( model, flags, &m); 653 if (ret != 0) { 654 DI_ERROR(ret, NULL, NULL); 655 } 656 return m; 657 } 658 ~msg() { 659 int ret = fd_msg_free($self); 660 if (ret != 0) { 661 DI_ERROR(ret, NULL, NULL); 662 } 663 } 664 %newobject create_answer; 665 struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) { 666 /* if dict is not provided, attempt to get it from the request model */ 667 struct dictionary * d = dict; 668 struct msg * m = $self; 669 int ret; 670 if (!d) { 671 struct dict_object * mo = NULL; 672 ret = fd_msg_model($self, &mo); 673 if (ret != 0) { 674 DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); 675 return NULL; 676 } 677 ret = fd_dict_getdict ( mo, &d ); 678 if (ret != 0) { 679 DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); 680 return NULL; 681 } 682 } 683 ret = fd_msg_new_answer_from_req(d, &m, flags); 684 if (ret != 0) { 685 DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); 686 return NULL; 687 } 688 return m; 689 } 690 } 691 692 struct avp { 693 }; 694 695 %extend avp { 696 avp() { 697 DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_AVP object parameter (or None) is required."); 698 return NULL; 699 } 700 avp(struct dict_object * model, int flags = 0) { 701 struct avp * a = NULL; 702 int ret = fd_msg_avp_new( model, flags, &a); 703 if (ret != 0) { 704 DI_ERROR(ret, NULL, NULL); 705 } 706 return a; 707 } 708 ~avp() { 709 int ret = fd_msg_free($self); 710 if (ret != 0) { 711 DI_ERROR(ret, NULL, NULL); 712 } 713 } 714 } 715 716 717 718 719 %cstring_output_allocate_size(char ** swig_buffer, size_t * swig_len, free(*$1)) 720 %inline %{ 721 int fd_msg_bufferize_py ( struct msg * msg, char ** swig_buffer, size_t * swig_len ) { 722 return fd_msg_bufferize(msg, (void *)swig_buffer, swig_len); 723 } 724 %}; 725 151 %include "peers.i"
Note: See TracChangeset
for help on using the changeset viewer.