Changeset 637:22e8fac3b2d6 in freeDiameter
- Timestamp:
- Dec 16, 2010, 6:56:41 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 8 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/dbg_interactive.py.sample
r636 r637 66 66 # Display the local Diameter Identity: 67 67 print "Local Diameter Identity:", cvar.fd_g_config.cnf_diamid 68 # Display realm, without using the low-level functions (skip proxy classe definitions): 68 69 # Display realm, using the low-level functions (skip proxy classe definitions): 69 70 print "Realm:", _fDpy.fd_config_cnf_diamrlm_get(_fDpy.cvar.fd_g_config) 70 71 … … 72 73 73 74 ############# Lists ############ 74 l1 = fd_list() # The creator has an implicit fd_list_init call 75 76 # Note: we use different names from the C API here, for usability. 77 l1 = fd_list() # Will be our sentinel 75 78 l2 = fd_list() 76 fd_list_insert_after(l1, l2) 79 l3 = fd_list() 80 l1.isempty() 81 l1.insert_next(l2) # l1 -> l2 82 l1.isempty() 83 l1.insert_prev(l3) # l1 -> l2 -> l3 (circular list) 77 84 l1.dump() 78 del l2 # The destructor has an implicit fd_list_unlink call 79 l1.dump() 85 l3.detach() # l1 -> l2 86 l4=fd_list() 87 l5=fd_list() 88 l3.insert_next(l4) # l3 -> l4 89 l3.insert_next(l5) # l3 -> l5 -> l4 90 l1.concat(l3) # l1 -> l2 -> l5 -> l4 91 92 elements = l1.enum_as() # default: enumerates as fd_list. Warning: this a copy, changing the python list has no effect on the underlying list. 93 for li in elements: 94 li.dump() 95 96 del elements 97 del l2 98 del l3 99 del l4 100 del l5 101 l1.isempty() # The destructor has an implicit fd_list_unlink call 80 102 del l1 81 103 … … 214 236 s2 = session("this.is.a.full.session.id") 215 237 r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id") 216 s4 = session("host.id", "opt .part")238 s4 = session("host.id", "optional.part") 217 239 s4.settimeout(30) # the python wrapper takes a number of seconds as parameter for simplicity 218 240 s4.dump() … … 241 263 242 264 list = rd.extract(-1) 243 list[0].dump() 265 for c in list.enum_as("struct rtd_candidate *"): 266 print "%s (%s): %s" % (c.diamid, c.realm, c.score) 267 268 269 270 ############# Messages, AVPs ############ 271 272 ## AVP 273 274 # Create empty (as for messages, pass None or a dictionary object as 1st param, and flags as optional 2nd param) 275 blank_avp = avp() 276 del blank_avp 277 278 oh = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host")) # Octet String 279 vi = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Id")) # U32 280 vsai = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Specific-Application-Id")) # Grouped 281 282 # Set values 283 val = avp_value() 284 val.u32 = 123 285 vi.setval(None) # this cleans a previous value (not needed) 286 vi.setval(val) 287 val.os = "my.origin.host" 288 oh.setval(val) 289 vsai.add_child(vi) # call as add_child(vi, 1) to add the new AVP at the beginning, default is at the end 290 291 292 ## Messages 293 294 # Create empty 295 a_msg = msg() 296 a_msg.dump() 297 del a_msg 298 299 # It is also possible to pass MSGFL_* flags in second parameter (ALLOC_ETEID is default) 300 msg_no_eid = msg(None, 0) 301 msg_no_eid.dump() 302 del msg_no_eid 303 304 # Create from dictionary 305 dwr_dict = cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" ) 306 dwr = msg(dwr_dict) 307 dwr.dump() 308 309 # Create msg from a binary buffer (then you should call parse_dict and parse_rules methods) 310 dwr2 = msg("\x01\x00\x00\x14\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00\x1b\xf0\x00\x01") 311 312 # Create answer from request (optional parameters: dictionary to use, and flags): 313 dwr3 = msg(cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" )) 314 dwa3 = dwr3.create_answer() 315 dwr3cpy = dwa3.get_query() 316 317 318 ## Other functions with AVPs & messages 319 320 # Add the AVPs in the message 321 dwr.add_child(oh) 322 oh.add_next(vsai) # equivalent to add_child on the parent 323 324 # Create a network byte buffer from the message 325 dwr.bufferize() 326 327 # Get first child AVP (fast) 328 avp = dwr.first_child() 329 330 # then: 331 avp = avp.get_next() # when last AVP, returns None 332 333 334 # Get all 1st level children (slower) -- warning, changes to the python list will not be reflected on the underlying message. read-only use. 335 dwr.children() 336 # example use: 337 for a in dwr.children() 338 a.dump(0) # 0 means: dump only this object, do not walk the tree 339 340 341 # Search the first AVP of a given type 342 oh_dict = cvar.fd_g_config.cnf_dict.search( DICT_AVP, AVP_BY_NAME, "Origin-Host") 343 oh = dwr.search( oh_dict ) 344 345 # After adding AVPs, the length in the message header is outdated, refresh as follow: 346 dwr.update_length() 347 348 # Get dictionary model for a message or avp 349 dwr.model() 350 oh.model().dump() 351 352 # Retrieve the header of messages & avp: 353 dwr_hdr = dwr.header() 354 dwr_hdr.msg_version 355 dwr_hdr.msg_hbhid 356 357 oh_hdr = oh.header() 358 hex(oh_hdr.avp_flags) 359 oh_hdr.avp_vendor 360 oh_hdr.avp_value.os.dump() # The initial avp value must be set with setval(), but then this accessor is allowed. 361 362 # Get or set the routing data 363 rd = rt_data() 364 dwr.set_rtd(rd) 365 rd = dwr.get_rtd() 366 367 # Test if message is routable 368 dwr.is_routable() 369 370 # Which peer the message was received from (when received from network) 371 dwr.source() 372 373 # The session corresponding to this message (returns None when no Session-Id AVP is included) 374 dwr.get_session() 375 376 377 # Parse a buffer 378 buf = "\x01\x00\x00@\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00N\x10\x00\x00\x00\x00\x01\x08@\x00\x00\x16my.origin.host\x00\x00\x00\x00\x01\x04@\x00\x00\x14\x00\x00\x01\n@\x00\x00\x0c\x00\x00\x00{" 379 mydwr = msg(buf) 380 # Resolve objects in the dictionary. Return value is None or a struct pei_error in case of problem. 381 mydwr.parse_dict() # if not using the fD global dict, pass it as parameter 382 err = mydwr.parse_rules() 383 err.pei_errcode 384 385 386 # Grouped AVPs are browsed with same methods as messages: 387 gavp = dwr.children()[1] 388 gavp.first_child().dump() 389 gavp.children() 390 391 392 393 244 394 245 395 … … 249 399 250 400 ######################### old stuff (need update) ###################### 251 252 253 254 # Messages255 gdict = fd_config_cnf_dict_get(cvar.fd_g_config)256 pobj = new_dict_object_pptr()257 fd_dict_search ( gdict, DICT_COMMAND, CMD_BY_NAME, char_to_void("Capabilities-Exchange-Request"), pobj, -1 )258 cerdict = dict_object_pptr_value(pobj)259 fd_dict_search ( gdict, DICT_AVP, AVP_BY_NAME, char_to_void("Origin-Host"), pobj, -1 )260 ohdict = dict_object_pptr_value(pobj)261 delete_dict_object_pptr(pobj)262 263 pmsg = new_msg_pptr()264 fd_msg_new(cerdict, MSGFL_ALLOC_ETEID, pmsg)265 msg = msg_pptr_value(pmsg);266 pavp = new_avp_pptr()267 fd_msg_avp_new(ohdict, 0, pavp)268 avp = avp_pptr_value(pavp);269 fd_msg_avp_add(msg, MSG_BRW_FIRST_CHILD, avp)270 fd_msg_dump_walk(0, msg)271 272 pahdr = new_avp_hdr_pptr()273 fd_msg_avp_hdr(avp, pahdr)274 ahdr = avp_hdr_pptr_value(pahdr)275 delete_avp_hdr_pptr(pahdr)276 avp_hdr_avp_code_get(ahdr)277 os = new_avp_value_os()278 avp_value_os_fromstr(os, fd_config_cnf_diamid_get(cvar.fd_g_config))279 val = new_avp_value()280 avp_value_os_set(val, os)281 delete_avp_value_os(os)282 fd_msg_avp_setvalue(avp, val)283 delete_avp_value(val)284 285 r,buf = fd_msg_bufferize_py(msg)286 fd_msg_free(msg)287 delete_avp_pptr(pavp)288 401 289 402 -
extensions/dbg_interactive/CMakeLists.txt
r625 r637 17 17 ${CMAKE_BINARY_DIR}/include/freeDiameter/freeDiameter-host.h 18 18 ${CMAKE_SOURCE_DIR}/include/freeDiameter/libfreeDiameter.h 19 ${CMAKE_SOURCE_DIR}/include/freeDiameter/freeDiameter.h) 19 ${CMAKE_SOURCE_DIR}/include/freeDiameter/freeDiameter.h 20 lists.i 21 dictionary.i 22 sessions.i 23 routing.i 24 messages.i 25 dispatch.i 26 queues.i 27 peers.i 28 ) 20 29 SET_SOURCE_FILES_PROPERTIES(dbg_interactive.i PROPERTIES SWIG_MODULE_NAME fDpy) 21 30 -
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" -
include/freeDiameter/libfreeDiameter.h
r621 r637 2182 2182 * msg : A msg object. 2183 2183 * diamid : The diameter id of the peer from which this message was received. 2184 * hash : The hash for the diamid value.2185 2184 * add_rr : if true, a Route-Record AVP is added to the message with content diamid. In that case, dict must be supplied. 2186 2185 * dict : a dictionary with definition of Route-Record AVP (if add_rr is true) … … 2361 2360 * If the dictionary definition is not found, avp_model is set to NULL and 2362 2361 * the content of the AVP is saved as an octetstring in an internal structure. avp_value is NULL. 2363 * As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is befreed.2362 * As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is freed. 2364 2363 * 2365 2364 * RETURN VALUE: -
libfreeDiameter/messages.c
r400 r637 118 118 int msg_routable; /* Is this a routable message? (0: undef, 1: routable, 2: non routable) */ 119 119 struct msg *msg_query; /* the associated query if the message is a received answer */ 120 int msg_associated; /* and the counter part information in the query, to avoid double free */ 120 121 struct rt_data *msg_rtdata; /* Routing list for the query */ 121 122 struct session *msg_sess; /* Cached message session if any */ … … 342 343 /* associate with query */ 343 344 ans->msg_query = qry; 345 qry->msg_associated = 1; 344 346 345 347 /* Done */ … … 629 631 if (CHECK_MSG(object)) { 630 632 if (_M(object)->msg_query) { 633 _M(_M(object)->msg_query)->msg_associated = 0; 631 634 CHECK_FCT( fd_msg_free( _M(object)->msg_query ) ); 632 635 _M(object)->msg_query = NULL; 636 } else { 637 if (_M(object)->msg_associated) { 638 TRACE_DEBUG(INFO, "Not freeing query %p referenced in an answer (will be freed along the answer).", object); 639 return 0; 640 } 633 641 } 634 642 } … … 689 697 msg->msg_public.msg_eteid 690 698 ); 691 fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p sess:%p src:%s\n",692 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_ sess, msg->msg_src_id?:"(nil)");699 fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n", 700 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)"); 693 701 } 694 702 … … 862 870 863 871 answer->msg_query = query; 872 query->msg_associated = 1; 864 873 865 874 return 0; … … 883 892 CHECK_PARAMS( CHECK_MSG(answer) ); 884 893 894 answer->msg_query->msg_associated = 0; 885 895 answer->msg_query = NULL; 886 896
Note: See TracChangeset
for help on using the changeset viewer.