# HG changeset patch # User Sebastien Decugis # Date 1292493401 -32400 # Node ID 22e8fac3b2d69cc1722716d779bea50afa613896 # Parent c23ca590fa57455c17f24e4f3706839dfedc50bd Split interface file in modules diff -r c23ca590fa57 -r 22e8fac3b2d6 doc/dbg_interactive.py.sample --- a/doc/dbg_interactive.py.sample Wed Dec 15 18:24:33 2010 +0900 +++ b/doc/dbg_interactive.py.sample Thu Dec 16 18:56:41 2010 +0900 @@ -65,18 +65,40 @@ # Display the local Diameter Identity: print "Local Diameter Identity:", cvar.fd_g_config.cnf_diamid -# Display realm, without using the low-level functions (skip proxy classe definitions): + +# Display realm, using the low-level functions (skip proxy classe definitions): print "Realm:", _fDpy.fd_config_cnf_diamrlm_get(_fDpy.cvar.fd_g_config) ############# Lists ############ -l1 = fd_list() # The creator has an implicit fd_list_init call + +# Note: we use different names from the C API here, for usability. +l1 = fd_list() # Will be our sentinel l2 = fd_list() -fd_list_insert_after(l1, l2) +l3 = fd_list() +l1.isempty() +l1.insert_next(l2) # l1 -> l2 +l1.isempty() +l1.insert_prev(l3) # l1 -> l2 -> l3 (circular list) l1.dump() -del l2 # The destructor has an implicit fd_list_unlink call -l1.dump() +l3.detach() # l1 -> l2 +l4=fd_list() +l5=fd_list() +l3.insert_next(l4) # l3 -> l4 +l3.insert_next(l5) # l3 -> l5 -> l4 +l1.concat(l3) # l1 -> l2 -> l5 -> l4 + +elements = l1.enum_as() # default: enumerates as fd_list. Warning: this a copy, changing the python list has no effect on the underlying list. +for li in elements: + li.dump() + +del elements +del l2 +del l3 +del l4 +del l5 +l1.isempty() # The destructor has an implicit fd_list_unlink call del l1 @@ -213,7 +235,7 @@ s1.getsid() s2 = session("this.is.a.full.session.id") r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id") -s4 = session("host.id", "opt.part") +s4 = session("host.id", "optional.part") s4.settimeout(30) # the python wrapper takes a number of seconds as parameter for simplicity s4.dump() @@ -240,7 +262,135 @@ rd.error("p3.testbed.aaa", "relay.testbed.aaa", 3002) list = rd.extract(-1) -list[0].dump() +for c in list.enum_as("struct rtd_candidate *"): + print "%s (%s): %s" % (c.diamid, c.realm, c.score) + + + +############# Messages, AVPs ############ + +## AVP + +# Create empty (as for messages, pass None or a dictionary object as 1st param, and flags as optional 2nd param) +blank_avp = avp() +del blank_avp + +oh = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host")) # Octet String +vi = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Id")) # U32 +vsai = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Specific-Application-Id")) # Grouped + +# Set values +val = avp_value() +val.u32 = 123 +vi.setval(None) # this cleans a previous value (not needed) +vi.setval(val) +val.os = "my.origin.host" +oh.setval(val) +vsai.add_child(vi) # call as add_child(vi, 1) to add the new AVP at the beginning, default is at the end + + +## Messages + +# Create empty +a_msg = msg() +a_msg.dump() +del a_msg + +# It is also possible to pass MSGFL_* flags in second parameter (ALLOC_ETEID is default) +msg_no_eid = msg(None, 0) +msg_no_eid.dump() +del msg_no_eid + +# Create from dictionary +dwr_dict = cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" ) +dwr = msg(dwr_dict) +dwr.dump() + +# Create msg from a binary buffer (then you should call parse_dict and parse_rules methods) +dwr2 = msg("\x01\x00\x00\x14\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00\x1b\xf0\x00\x01") + +# Create answer from request (optional parameters: dictionary to use, and flags): +dwr3 = msg(cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" )) +dwa3 = dwr3.create_answer() +dwr3cpy = dwa3.get_query() + + +## Other functions with AVPs & messages + +# Add the AVPs in the message +dwr.add_child(oh) +oh.add_next(vsai) # equivalent to add_child on the parent + +# Create a network byte buffer from the message +dwr.bufferize() + +# Get first child AVP (fast) +avp = dwr.first_child() + +# then: +avp = avp.get_next() # when last AVP, returns None + + +# Get all 1st level children (slower) -- warning, changes to the python list will not be reflected on the underlying message. read-only use. +dwr.children() +# example use: +for a in dwr.children() + a.dump(0) # 0 means: dump only this object, do not walk the tree + + +# Search the first AVP of a given type +oh_dict = cvar.fd_g_config.cnf_dict.search( DICT_AVP, AVP_BY_NAME, "Origin-Host") +oh = dwr.search( oh_dict ) + +# After adding AVPs, the length in the message header is outdated, refresh as follow: +dwr.update_length() + +# Get dictionary model for a message or avp +dwr.model() +oh.model().dump() + +# Retrieve the header of messages & avp: +dwr_hdr = dwr.header() +dwr_hdr.msg_version +dwr_hdr.msg_hbhid + +oh_hdr = oh.header() +hex(oh_hdr.avp_flags) +oh_hdr.avp_vendor +oh_hdr.avp_value.os.dump() # The initial avp value must be set with setval(), but then this accessor is allowed. + +# Get or set the routing data +rd = rt_data() +dwr.set_rtd(rd) +rd = dwr.get_rtd() + +# Test if message is routable +dwr.is_routable() + +# Which peer the message was received from (when received from network) +dwr.source() + +# The session corresponding to this message (returns None when no Session-Id AVP is included) +dwr.get_session() + + +# Parse a buffer +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{" +mydwr = msg(buf) +# Resolve objects in the dictionary. Return value is None or a struct pei_error in case of problem. +mydwr.parse_dict() # if not using the fD global dict, pass it as parameter +err = mydwr.parse_rules() +err.pei_errcode + + +# Grouped AVPs are browsed with same methods as messages: +gavp = dwr.children()[1] +gavp.first_child().dump() +gavp.children() + + + + @@ -250,43 +400,6 @@ ######################### old stuff (need update) ###################### - -# Messages -gdict = fd_config_cnf_dict_get(cvar.fd_g_config) -pobj = new_dict_object_pptr() -fd_dict_search ( gdict, DICT_COMMAND, CMD_BY_NAME, char_to_void("Capabilities-Exchange-Request"), pobj, -1 ) -cerdict = dict_object_pptr_value(pobj) -fd_dict_search ( gdict, DICT_AVP, AVP_BY_NAME, char_to_void("Origin-Host"), pobj, -1 ) -ohdict = dict_object_pptr_value(pobj) -delete_dict_object_pptr(pobj) - -pmsg = new_msg_pptr() -fd_msg_new(cerdict, MSGFL_ALLOC_ETEID, pmsg) -msg = msg_pptr_value(pmsg); -pavp = new_avp_pptr() -fd_msg_avp_new(ohdict, 0, pavp) -avp = avp_pptr_value(pavp); -fd_msg_avp_add(msg, MSG_BRW_FIRST_CHILD, avp) -fd_msg_dump_walk(0, msg) - -pahdr = new_avp_hdr_pptr() -fd_msg_avp_hdr(avp, pahdr) -ahdr = avp_hdr_pptr_value(pahdr) -delete_avp_hdr_pptr(pahdr) -avp_hdr_avp_code_get(ahdr) -os = new_avp_value_os() -avp_value_os_fromstr(os, fd_config_cnf_diamid_get(cvar.fd_g_config)) -val = new_avp_value() -avp_value_os_set(val, os) -delete_avp_value_os(os) -fd_msg_avp_setvalue(avp, val) -delete_avp_value(val) - -r,buf = fd_msg_bufferize_py(msg) -fd_msg_free(msg) -delete_avp_pptr(pavp) - - # Create a new peer_info structure and add the peer to the framework. mypeer = peer_info() mypeer.pi_diamid = "nas.testbed.aaa" diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/CMakeLists.txt --- a/extensions/dbg_interactive/CMakeLists.txt Wed Dec 15 18:24:33 2010 +0900 +++ b/extensions/dbg_interactive/CMakeLists.txt Thu Dec 16 18:56:41 2010 +0900 @@ -16,7 +16,16 @@ SET(SWIG_MODULE_fDpy_EXTRA_DEPS ${CMAKE_BINARY_DIR}/include/freeDiameter/freeDiameter-host.h ${CMAKE_SOURCE_DIR}/include/freeDiameter/libfreeDiameter.h - ${CMAKE_SOURCE_DIR}/include/freeDiameter/freeDiameter.h) + ${CMAKE_SOURCE_DIR}/include/freeDiameter/freeDiameter.h + lists.i + dictionary.i + sessions.i + routing.i + messages.i + dispatch.i + queues.i + peers.i + ) SET_SOURCE_FILES_PROPERTIES(dbg_interactive.i PROPERTIES SWIG_MODULE_NAME fDpy) # The following code is inspired from SWIG_ADD_MODULE, but we do only what we need diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/dbg_interactive.i --- a/extensions/dbg_interactive/dbg_interactive.i Wed Dec 15 18:24:33 2010 +0900 +++ b/extensions/dbg_interactive/dbg_interactive.i Thu Dec 16 18:56:41 2010 +0900 @@ -46,42 +46,23 @@ /* Include standard types & functions used in freeDiameter headers */ %include -%include +//%include %include %include -/* Some functions are not available through the wrapper */ -%ignore fd_lib_init; -%ignore fd_lib_fini; -/* -- the following functions are better accessed differently, but we leave their definitions just in case -%ignore fd_dict_init; -%ignore fd_dict_fini; -%ignore fd_sess_handler_create_internal; -%ignore fd_sess_handler_destroy; -%ignore fd_sess_new; -%ignore fd_sess_getsid; -%ignore fd_sess_destroy; -%ignore fd_sess_reclaim; -%ignore fd_sess_state_store_internal; -%ignore fd_sess_state_retrieve_internal; -%ignore fd_rtd_init; -%ignore fd_rtd_free; -%ignore fd_rtd_candidate_add; -%ignore fd_rtd_candidate_del; -%ignore fd_rtd_candidate_extract; -%ignore fd_rtd_error_add; -*/ /* Inline functions seems to give problems to SWIG -- just remove the inline definition */ %define __inline__ %enddef + /* Make some global-variables read-only (mainly to avoid warnings) */ %immutable fd_g_config; %immutable peer_state_str; - -/* Create a generic error handling mechanism so that functions can provoke an exception */ +/***************** + * Exceptions * +*****************/ %{ /* This is not thread-safe etc. but it should work /most of the time/. */ static int wrapper_errno; @@ -127,8 +108,9 @@ Some types & typemaps for usability ***********************************/ -%apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; +%apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; /* fd_hash */ +/* Generic typemap for functions that create something */ %typemap(in, numinputs=0,noblock=1) SWIGTYPE ** OUTPUT (void *temp = NULL) { $1 = (void *)&temp; } @@ -136,12 +118,7 @@ %append_output(SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } -%apply int * OUTPUT { enum dict_object_type * type }; -%apply (char *STRING, size_t LENGTH) { (char * sid, size_t len) }; -%apply SWIGTYPE ** OUTPUT { struct session ** session }; -%apply int * OUTPUT { int * new }; - -/* Callbacks defined in python */ +/* To allow passing callback functions defined in python */ %typemap(in) PyObject *PyCb { if (!PyCallable_Check($input)) { PyErr_SetString(PyExc_TypeError, "Need a callable object!"); @@ -151,7 +128,6 @@ } - /********************************************************* Now, create wrappers for (almost) all objects from fD API *********************************************************/ @@ -159,567 +135,17 @@ %include "freeDiameter/libfreeDiameter.h" %include "freeDiameter/freeDiameter.h" - - -/**********************************************************/ -/* The remaining of this file allows easier manipulation of -the structures and functions of fD by providing wrapper-specific -extensions to the freeDiameter API. - -/****** LISTS *********/ - -%extend fd_list { - /* allow a parameter in the constructor, and perform the fd_list_init operation */ - fd_list(void * o = NULL) { - struct fd_list * li; - li = (struct fd_list *) malloc(sizeof(struct fd_list)); - if (!li) { - DI_ERROR_MALLOC; - return NULL; - } - fd_list_init(li, o); - return li; - } - /* Unlink before freeing */ - ~fd_list() { - fd_list_unlink($self); - free($self); - } - /* For debug, show the values of the list */ - void dump() { - fd_log_debug("list: %p\n", $self); - fd_log_debug(" - next: %p\n", $self->next); - fd_log_debug(" - prev: %p\n", $self->prev); - fd_log_debug(" - head: %p\n", $self->head); - fd_log_debug(" - o : %p\n", $self->o); - } -}; - -/****** DICTIONARY *********/ - -struct dictionary { -}; - -%extend dictionary { - dictionary() { - struct dictionary * r = NULL; - int ret = fd_dict_init(&r); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return r; - } - ~dictionary() { - struct dictionary *d = self; - int ret = fd_dict_fini(&d); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - return; - } - void dump() { - fd_dict_dump($self); - } - PyObject * vendors_list() { - uint32_t *list = NULL, *li; - PyObject * ret; - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - ret = PyList_New(0); - list = fd_dict_get_vendorid_list($self); - for (li = list; *li != 0; li++) { - PyList_Append(ret, PyInt_FromLong((long)*li)); - } - free(list); - SWIG_PYTHON_THREAD_END_BLOCK; - return ret; - } - struct dict_object * new_obj(enum dict_object_type type, void * data, struct dict_object * parent = NULL) { - struct dict_object * obj = NULL; - int ret = fd_dict_new($self, type, data, parent, &obj); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return obj; - } - struct dict_object * search(enum dict_object_type type, int criteria, int what_by_val) { - struct dict_object * obj = NULL; - int ret = fd_dict_search ( $self, type, criteria, &what_by_val, &obj, ENOENT ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return obj; - } - struct dict_object * search(enum dict_object_type type, int criteria, char * what_by_string) { - struct dict_object * obj = NULL; - int ret = fd_dict_search ( $self, type, criteria, what_by_string, &obj, ENOENT ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return obj; - } - struct dict_object * search(enum dict_object_type type, int criteria, void * what) { - struct dict_object * obj = NULL; - int ret = fd_dict_search ( $self, type, criteria, what, &obj, ENOENT ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return obj; - } - struct dict_object * error_cmd() { - struct dict_object * obj = NULL; - int ret = fd_dict_get_error_cmd ( $self, &obj ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return obj; - } -} - -struct dict_object { -}; - -%extend dict_object { - dict_object() { - DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be created directly. Use fd_dict_new()."); - return NULL; - } - ~dict_object() { - DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be destroyed directly. Destroy the parent dictionary."); - return; - } - void dump() { - fd_dict_dump_object($self); - } - enum dict_object_type gettype() { - enum dict_object_type t; - int ret = fd_dict_gettype ( $self, &t); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return 0; - } - return t; - } - struct dictionary * getdict() { - struct dictionary *d; - int ret = fd_dict_getdict ( $self, &d ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return d; - } - /* Since casting the pointer requires intelligence, we do it here instead of giving it to SWIG */ - PyObject * getval() { - /* first, get the type */ - enum dict_object_type t; - int ret = fd_dict_gettype ( $self, &t); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - switch (t) { -%define %GETVAL_CASE(TYPE,STRUCT) - case TYPE: { - PyObject * v = NULL; - struct STRUCT * data = NULL; - data = malloc(sizeof(struct STRUCT)); - if (!data) { - DI_ERROR_MALLOC; - return NULL; - } - ret = fd_dict_getval($self, data); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - free(data); - return NULL; - } - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - v = SWIG_NewPointerObj((void *)data, SWIGTYPE_p_##STRUCT, SWIG_POINTER_OWN ); - Py_XINCREF(v); - SWIG_PYTHON_THREAD_END_BLOCK; - return v; - } break -%enddef - %GETVAL_CASE( DICT_VENDOR, dict_vendor_data ); - %GETVAL_CASE( DICT_APPLICATION, dict_application_data ); - %GETVAL_CASE( DICT_TYPE, dict_type_data ); - %GETVAL_CASE( DICT_ENUMVAL, dict_enumval_data ); - %GETVAL_CASE( DICT_AVP, dict_avp_data ); - %GETVAL_CASE( DICT_COMMAND, dict_cmd_data ); - %GETVAL_CASE( DICT_RULE, dict_rule_data ); - default: - DI_ERROR(EINVAL, PyExc_SystemError, "Internal error: Got invalid object type"); - } - return NULL; - } -} - - -/* The following wrapper leaks memory each time an union avp_value is assigned an octet string. - TODO: fix this leak by better understanding SWIG... - -- the alternative is to uncomment the "free" statements bellow, but then it is easy to - create a segmentation fault by assigning first an integer, then an octetstring. - */ -%extend avp_value { - /* The following hack in the proxy file allows assigning the octet string directly like this: - avp_value.os = "blabla" - */ - %pythoncode - { - __swig_setmethods__["os"] = _fDpy.avp_value_os_set - if _newclass:os = _swig_property(_fDpy.avp_value_os_get, _fDpy.avp_value_os_set) - } - void os_set(char *STRING, size_t LENGTH) { - /* free($self->os.data); -- do not free, in case the previous value was not an OS */ - $self->os.data = malloc(LENGTH); - if (!$self->os.data) { - DI_ERROR_MALLOC; - return; - } - memcpy($self->os.data, STRING, LENGTH); - $self->os.len = LENGTH; - } - void os_set(avp_value_os * os) { - /* free($self->os.data); -- do not free, in case the previous value was not an OS */ - $self->os.data = malloc(os->len); - if (!$self->os.data) { - DI_ERROR_MALLOC; - return; - } - memcpy($self->os.data, os->data, os->len); - $self->os.len = os->len; - } -}; - -%extend avp_value_os { - void dump() { - %#define LEN_MAX 20 - int i, n=LEN_MAX; - if ($self->len < LEN_MAX) - n = $self->len; - fd_log_debug("l:%u, v:[", $self->len); - for (i=0; i < n; i++) - fd_log_debug("%02.2X", $self->data[i]); - fd_log_debug("] '%.*s%s'\n", n, $self->data, n == LEN_MAX ? "..." : ""); - } -} - -/****** SESSIONS *********/ - -%{ -/* store the python callback function here */ -static PyObject * py_cleanup_cb = NULL; -/* call it (might be called from a different thread than the interpreter, when session times out) */ -static void call_the_python_cleanup_callback(session_state * state, char * sid) { - PyObject *result; - if (!py_cleanup_cb) - return; - - /* Call the function */ - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - result = PyEval_CallFunction(py_cleanup_cb, "(Os)", state, sid); - Py_XDECREF(result); - SWIG_PYTHON_THREAD_END_BLOCK; - return; -} -%} - -struct session_handler { -}; +/* Most of the functions from the API are not directly usable "as is". +See the specific following files and the dbg_interactive.py.sample file +for more usable python-style versions. +*/ -%extend session_handler { - session_handler() { - DI_ERROR(EINVAL, PyExc_SyntaxError, "a cleanup callback parameter is required."); - return NULL; - } - session_handler(PyObject * PyCb) { - struct session_handler * hdl = NULL; - int ret; - if (py_cleanup_cb) { - DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one session handler at a time is supported at the moment in this extension\n."); - return NULL; - } - py_cleanup_cb = PyCb; - Py_XINCREF(py_cleanup_cb); - - ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return hdl; - } - ~session_handler() { - struct session_handler * hdl = self; - int ret = fd_sess_handler_destroy(&hdl); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - /* Now free the callback */ - Py_XDECREF(py_cleanup_cb); - py_cleanup_cb = NULL; - return; - } - void dump() { - fd_sess_dump_hdl(0, $self); - } -} - -struct session { -}; - -%extend session { - /* The first two versions create a new session string. The third one allow to use an existing string. */ - session() { - int ret; - struct session * s = NULL; - ret = fd_sess_new(&s, fd_g_config->cnf_diamid, "dbg_interactive", sizeof("dbg_interactive")); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return s; - } - session(char * diamid, char * STRING, size_t LENGTH) { - int ret; - struct session * s = NULL; - ret = fd_sess_new(&s, diamid, STRING, LENGTH); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return s; - } - session(char * STRING, size_t LENGTH) { - int ret, n; - struct session * s = NULL; - ret = fd_sess_fromsid(STRING, LENGTH, &s, &n); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - /* When defining n as OUTPUT parameter, we get something strange... Use fd_sess_fromsid if you need it */ - #if 0 - if (n) { - fd_log_debug("A new session has been created\n"); - } else { - fd_log_debug("A session with same id already existed\n"); - } - #endif /* 0 */ - - return s; - } - ~session() { - struct session * s = self; - int ret = fd_sess_reclaim(&s); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - return; - } - char * getsid() { - int ret; - char * sid = NULL; - ret = fd_sess_getsid( $self, &sid); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return sid; - } - void settimeout(long seconds) { - struct timespec timeout; - int ret; - clock_gettime(CLOCK_REALTIME, &timeout); - timeout.tv_sec += seconds; - ret = fd_sess_settimeout( $self, &timeout ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - } - void dump() { - fd_sess_dump(0, $self); - } - void store(struct session_handler * handler, PyObject * state) { - int ret; - void * store = state; - Py_XINCREF(state); - ret = fd_sess_state_store_internal(handler, $self, (void *) &store); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - } - PyObject * retrieve(struct session_handler * handler) { - int ret; - PyObject * state = NULL; - ret = fd_sess_state_retrieve_internal(handler, $self, (void *) &state); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - if (state == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return state; - } -} - -/****** ROUTING *********/ - -struct rt_data { -}; +%include "lists.i" +%include "dictionary.i" +%include "sessions.i" +%include "routing.i" +%include "messages.i" +%include "dispatch.i" +%include "queues.i" -%extend rt_data { - rt_data() { - struct rt_data * r = NULL; - int ret = fd_rtd_init(&r); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - return NULL; - } - return r; - } - ~rt_data() { - struct rt_data *r = self; - fd_rtd_free(&r); - } - void add(char * peerid, char * realm) { - int ret = fd_rtd_candidate_add($self, peerid, realm); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - } - void remove(char * STRING, size_t LENGTH) { - fd_rtd_candidate_del($self, STRING, LENGTH); - } - void error(char * dest, char * STRING, size_t LENGTH, uint32_t rcode) { - int ret = fd_rtd_error_add($self, dest, (uint8_t *)STRING, LENGTH, rcode); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - } - struct fd_list * extract_li(int score = 0) { - struct fd_list * li = NULL; - fd_rtd_candidate_extract($self, &li, score); - return li; - } - PyObject * extract(int score = 0) { - struct fd_list * list = NULL, *li; - PyObject * rl; - fd_rtd_candidate_extract($self, &list, score); - rl = PyList_New(0); - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - for (li = list->next; li != list; li = li->next) { - PyList_Append(rl, SWIG_NewPointerObj((void *)li, SWIGTYPE_p_rtd_candidate, 0 )); - } - Py_XINCREF(rl); - SWIG_PYTHON_THREAD_END_BLOCK; - - return rl; - } -} - -%extend rtd_candidate { - void dump() { - fd_log_debug("candidate %p\n", $self); - fd_log_debug(" id : %s\n", $self->diamid); - fd_log_debug(" rlm: %s\n", $self->realm); - fd_log_debug(" sc : %d\n", $self->score); - } -} - - - -/****** MESSAGES *********/ - -struct msg { -}; - -%extend msg { - msg() { - DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_COMMAND object parameter (or None) is required."); - return NULL; - } - msg(struct dict_object * model, int flags = MSGFL_ALLOC_ETEID) { - struct msg * m = NULL; - int ret = fd_msg_new( model, flags, &m); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - return m; - } - ~msg() { - int ret = fd_msg_free($self); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - } - %newobject create_answer; - struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) { - /* if dict is not provided, attempt to get it from the request model */ - struct dictionary * d = dict; - struct msg * m = $self; - int ret; - if (!d) { - struct dict_object * mo = NULL; - ret = fd_msg_model($self, &mo); - if (ret != 0) { - DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); - return NULL; - } - ret = fd_dict_getdict ( mo, &d ); - if (ret != 0) { - DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); - return NULL; - } - } - ret = fd_msg_new_answer_from_req(d, &m, flags); - if (ret != 0) { - DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); - return NULL; - } - return m; - } -} - -struct avp { -}; - -%extend avp { - avp() { - DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_AVP object parameter (or None) is required."); - return NULL; - } - avp(struct dict_object * model, int flags = 0) { - struct avp * a = NULL; - int ret = fd_msg_avp_new( model, flags, &a); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - return a; - } - ~avp() { - int ret = fd_msg_free($self); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - } -} - - - - -%cstring_output_allocate_size(char ** swig_buffer, size_t * swig_len, free(*$1)) -%inline %{ -int fd_msg_bufferize_py ( struct msg * msg, char ** swig_buffer, size_t * swig_len ) { - return fd_msg_bufferize(msg, (void *)swig_buffer, swig_len); -} -%}; - +%include "peers.i" diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/dictionary.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/dictionary.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,244 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + +/****** DICTIONARY *********/ + +struct dictionary { +}; + +%extend dictionary { + dictionary() { + struct dictionary * r = NULL; + int ret = fd_dict_init(&r); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return r; + } + ~dictionary() { + struct dictionary *d = self; + int ret = fd_dict_fini(&d); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return; + } + void dump() { + fd_dict_dump($self); + } + PyObject * vendors_list() { + uint32_t *list = NULL, *li; + PyObject * ret; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + ret = PyList_New(0); + list = fd_dict_get_vendorid_list($self); + for (li = list; *li != 0; li++) { + PyList_Append(ret, PyInt_FromLong((long)*li)); + } + free(list); + SWIG_PYTHON_THREAD_END_BLOCK; + return ret; + } + struct dict_object * new_obj(enum dict_object_type type, void * data, struct dict_object * parent = NULL) { + struct dict_object * obj = NULL; + int ret = fd_dict_new($self, type, data, parent, &obj); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return obj; + } + struct dict_object * search(enum dict_object_type type, int criteria, int what_by_val) { + struct dict_object * obj = NULL; + int ret = fd_dict_search ( $self, type, criteria, &what_by_val, &obj, ENOENT ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return obj; + } + struct dict_object * search(enum dict_object_type type, int criteria, char * what_by_string) { + struct dict_object * obj = NULL; + int ret = fd_dict_search ( $self, type, criteria, what_by_string, &obj, ENOENT ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return obj; + } + struct dict_object * search(enum dict_object_type type, int criteria, void * what) { + struct dict_object * obj = NULL; + int ret = fd_dict_search ( $self, type, criteria, what, &obj, ENOENT ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return obj; + } + struct dict_object * error_cmd() { + struct dict_object * obj = NULL; + int ret = fd_dict_get_error_cmd ( $self, &obj ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return obj; + } +} + +%nodefaultctor dict_object; +struct dict_object { +}; + +%extend dict_object { + void dump() { + fd_dict_dump_object($self); + } + enum dict_object_type gettype() { + enum dict_object_type t; + int ret = fd_dict_gettype ( $self, &t); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return 0; + } + return t; + } + struct dictionary * getdict() { + struct dictionary *d; + int ret = fd_dict_getdict ( $self, &d ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return d; + } + /* Since casting the pointer requires intelligence, we do it here instead of giving it to SWIG */ + PyObject * getval() { + /* first, get the type */ + enum dict_object_type t; + int ret = fd_dict_gettype ( $self, &t); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + switch (t) { +%define %GETVAL_CASE(TYPE,STRUCT) + case TYPE: { + PyObject * v = NULL; + struct STRUCT * data = NULL; + data = malloc(sizeof(struct STRUCT)); + if (!data) { + DI_ERROR_MALLOC; + return NULL; + } + ret = fd_dict_getval($self, data); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + free(data); + return NULL; + } + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + v = SWIG_NewPointerObj((void *)data, SWIGTYPE_p_##STRUCT, SWIG_POINTER_OWN ); + Py_XINCREF(v); + SWIG_PYTHON_THREAD_END_BLOCK; + return v; + } break +%enddef + %GETVAL_CASE( DICT_VENDOR, dict_vendor_data ); + %GETVAL_CASE( DICT_APPLICATION, dict_application_data ); + %GETVAL_CASE( DICT_TYPE, dict_type_data ); + %GETVAL_CASE( DICT_ENUMVAL, dict_enumval_data ); + %GETVAL_CASE( DICT_AVP, dict_avp_data ); + %GETVAL_CASE( DICT_COMMAND, dict_cmd_data ); + %GETVAL_CASE( DICT_RULE, dict_rule_data ); + default: + DI_ERROR(EINVAL, PyExc_SystemError, "Internal error: Got invalid object type"); + } + return NULL; + } +} + + +/* The following wrapper leaks memory each time an union avp_value is assigned an octet string. + TODO: fix this leak by better understanding SWIG... + -- the alternative is to uncomment the "free" statements bellow, but then it is easy to + create a segmentation fault by assigning first an integer, then an octetstring. + */ +%extend avp_value { + /* The following hack in the proxy file allows assigning the octet string directly like this: + avp_value.os = "blabla" + */ + %pythoncode + { + __swig_setmethods__["os"] = _fDpy.avp_value_os_set + if _newclass:os = _swig_property(_fDpy.avp_value_os_get, _fDpy.avp_value_os_set) + } + void os_set(char *STRING, size_t LENGTH) { + /* free($self->os.data); -- do not free, in case the previous value was not an OS */ + $self->os.data = malloc(LENGTH); + if (!$self->os.data) { + DI_ERROR_MALLOC; + return; + } + memcpy($self->os.data, STRING, LENGTH); + $self->os.len = LENGTH; + } + void os_set(avp_value_os * os) { + /* free($self->os.data); -- do not free, in case the previous value was not an OS */ + $self->os.data = malloc(os->len); + if (!$self->os.data) { + DI_ERROR_MALLOC; + return; + } + memcpy($self->os.data, os->data, os->len); + $self->os.len = os->len; + } +}; + +%extend avp_value_os { + void dump() { + %#define LEN_MAX 20 + int i, n=LEN_MAX; + if ($self->len < LEN_MAX) + n = $self->len; + fd_log_debug("l:%u, v:[", $self->len); + for (i=0; i < n; i++) + fd_log_debug("%02.2X", $self->data[i]); + fd_log_debug("] '%.*s%s'\n", n, $self->data, n == LEN_MAX ? "..." : ""); + } +} diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/dispatch.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/dispatch.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,37 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/lists.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/lists.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,126 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + +/****** LISTS *********/ + +%extend fd_list { + /* allow a parameter in the constructor, and perform the fd_list_init operation */ + fd_list(void * o = NULL) { + struct fd_list * li; + li = (struct fd_list *) malloc(sizeof(struct fd_list)); + if (!li) { + DI_ERROR_MALLOC; + return NULL; + } + fd_list_init(li, o); + return li; + } + /* Unlink before freeing */ + ~fd_list() { + fd_list_unlink($self); + free($self); + } + /* For debug, show the values of the list */ + void dump() { + fd_log_debug("list: %p\n", $self); + fd_log_debug(" - next: %p\n", $self->next); + fd_log_debug(" - prev: %p\n", $self->prev); + fd_log_debug(" - head: %p\n", $self->head); + fd_log_debug(" - o : %p\n", $self->o); + } + /* Insert before/after wrapper */ + void insert_prev(struct fd_list * li) { + fd_list_insert_before($self, li); + } + void insert_next(struct fd_list * li) { + fd_list_insert_after($self, li); + } + /* Test for emptyness */ + int isempty() { + return FD_IS_LIST_EMPTY($self); + } + /* Concatenate two lists */ + void concat(struct fd_list * li) { + fd_list_move_end($self, li); + } + /* Unlink without freeing */ + void detach() { + fd_list_unlink($self); + } + + /* Return the list as python list of elements */ + PyObject * enum_as(char * type = NULL, int dont_use_o = 0) { + struct fd_list *li; + swig_type_info * desttype = NULL; + PyObject * rl; + + if ($self->head != $self) { + DI_ERROR(EINVAL, NULL, "This method can only be called on the list sentinel."); + return NULL; + } + + if (type) { + desttype = SWIG_TypeQuery(type); + if (!desttype) { + DI_ERROR(EINVAL, NULL, "Unable to resolve this type. Please check the form: 'struct blahbla *'"); + return NULL; + } + } + if (desttype == NULL) { + /* fallback to fd_list */ + desttype = SWIGTYPE_p_fd_list; + /* in this case, don't follow the 'o' link */ + dont_use_o = 1; + } + + rl = PyList_New(0); + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + for (li = $self->next; li != $self; li = li->next) { + void * obj = NULL; + if (dont_use_o || li->o == NULL) + obj = li; + else + obj = li->o; + PyList_Append(rl, SWIG_NewPointerObj(obj, desttype, 0 )); + } + Py_XINCREF(rl); + SWIG_PYTHON_THREAD_END_BLOCK; + + return rl; + } +}; + diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/messages.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/messages.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,446 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + +/****** MESSAGES *********/ + +struct msg { +}; + +%extend msg { + msg(struct dict_object * model=NULL, int flags = MSGFL_ALLOC_ETEID) { + struct msg * m = NULL; + int ret = fd_msg_new( model, flags, &m); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return m; + } + /* construct also from a binary buffer */ + msg(char * STRING, size_t LENGTH) { + int ret; + struct msg * m = NULL; + /* First, copy the string */ + unsigned char * buf = malloc(LENGTH); + if (buf == NULL) { + DI_ERROR_MALLOC; + return NULL; + } + memcpy(buf, STRING, LENGTH); + ret = fd_msg_parse_buffer(&buf, LENGTH, &m); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + free(buf); + return NULL; + } + return m; + } + ~msg() { + int ret = fd_msg_free($self); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + %delobject create_answer; /* when this has been called, the original msg should not be freed anymore */ + struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) { + /* if dict is not provided, attempt to get it from the request model */ + struct dictionary * d = dict; + struct msg * m = $self; + int ret; + if (!d) { + struct dict_object * mo = NULL; + ret = fd_msg_model($self, &mo); + if (ret != 0) { + DI_ERROR(ret, NULL, "Error retrieving query model."); + return NULL; + } + if (mo == NULL) { + /* use the fD dictionary by default */ + d = fd_g_config->cnf_dict; + } else { + ret = fd_dict_getdict ( mo, &d ); + if (ret != 0) { + DI_ERROR(ret, NULL, "Error retrieving query's dictionary."); + return NULL; + } + } + } + ret = fd_msg_new_answer_from_req(d, &m, flags); + if (ret != 0) { + DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); + return NULL; + } + + return m; + } + /* Return the first child AVP if any */ + struct avp * first_child() { + struct avp * a = NULL; + int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return a; + } + + /* Enumerable list of children AVP */ + %newobject children; + PyObject * children() { + struct avp * a = NULL; + PyObject * rl; + int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + rl = PyList_New(0); + while (a) { + PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* do not own the AVPs */ )); + ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + } + Py_XINCREF(rl); + SWIG_PYTHON_THREAD_END_BLOCK; + return rl; + } + + /* Add a new AVP */ + void add_child(struct avp *DISOWN, int begin = 0) { + int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + + /* Search an AVP */ + struct avp * search(struct dict_object * what) { + struct avp * a = NULL; + int ret = fd_msg_search_avp($self, what, &a); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return a; + } + + /* Dump */ + void dump (int tree = 1) { + if (tree) + fd_msg_dump_walk(0, $self); + else + fd_msg_dump_one(0, $self); + } + + /* Model */ + struct dict_object * model() { + struct dict_object * m = NULL; + int ret = fd_msg_model($self, &m); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return m; + } + + /* Header */ + struct msg_hdr * header() { + struct msg_hdr * h = NULL; + int ret = fd_msg_hdr($self, &h); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return h; + } + + /* Get query if message is an answer */ + struct msg * get_query() { + struct msg * q = NULL; + int ret = fd_msg_answ_getq($self, &q); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return q; + } + + /* Get / Set routing data */ + struct rt_data * get_rtd() { + struct rt_data * r = NULL; + int ret = fd_msg_rt_get($self, &r); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return r; + } + void set_rtd(struct rt_data *DISOWN) { + struct rt_data * r = DISOWN; + int ret = fd_msg_rt_associate($self, &r); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return; + } + + /* Is routable? */ + int is_routable() { + return fd_msg_is_routable($self); + } + + /* Get the source */ + char *source() { + char * s = NULL; + int ret = fd_msg_source_get($self, &s); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return s; + } + + /* Get the session */ + %newobject get_session; /* it may be created or not, it is harmless because we only reclaim in ~session */ + struct session *get_session(struct dictionary * dict = NULL) { + struct session *s = NULL; + struct dictionary * d = dict; + int ret = 0; + if (d == NULL) + d = fd_g_config->cnf_dict; /* default: use daemon's */ + ret = fd_msg_sess_get(d, $self, &s, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return s; + } + + /* Bufferize */ + %cstring_output_allocate_size(char ** outbuffer, size_t * outlen, free(*$1)); + void bufferize ( char ** outbuffer, size_t * outlen ) { + int ret = fd_msg_bufferize ( $self, (void *)outbuffer, outlen ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + + /* Dictionary parsing */ + %newobject parse_dict; + struct fd_pei * parse_dict(struct dictionary * dict=NULL) { + int ret; + struct fd_pei pei, *e = NULL; + struct dictionary * d = dict; + memset(&pei, 0, sizeof(struct fd_pei)); + if (d == NULL) + d = fd_g_config->cnf_dict; /* default: use daemon's */ + + ret = fd_msg_parse_dict ( $self, d, &pei ); + if (ret != 0) { + e = malloc(sizeof(struct fd_pei)); + if (!e) { + DI_ERROR_MALLOC; + return NULL; + } + memcpy(e, &pei, sizeof(struct fd_pei)); + } + return e; /* returns NULL when everything went OK */ + } + + /* Rules parsing */ + %newobject parse_rules; + struct fd_pei * parse_rules(struct dictionary * dict=NULL) { + int ret; + struct fd_pei pei, *e = NULL; + struct dictionary * d = dict; + memset(&pei, 0, sizeof(struct fd_pei)); + if (d == NULL) + d = fd_g_config->cnf_dict; /* default: use daemon's */ + + ret = fd_msg_parse_rules ( $self, d, &pei ); + if (ret != 0) { + e = malloc(sizeof(struct fd_pei)); + if (!e) { + DI_ERROR_MALLOC; + return NULL; + } + memcpy(e, &pei, sizeof(struct fd_pei)); + } + return e; /* returns NULL when everything went OK */ + } + + /* Update the length info in header */ + void update_length() { + int ret = fd_msg_update_length ( $self ); + if (ret) { + DI_ERROR(ret, NULL, NULL); + } + } +} + +struct avp { +}; + +%extend avp { + avp(struct dict_object * model = NULL, int flags = 0) { + struct avp * a = NULL; + int ret = fd_msg_avp_new( model, flags, &a); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return a; + } + ~avp() { + int ret = fd_msg_free($self); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + + /* Return the first child AVP if any */ + struct avp * first_child() { + struct avp * a = NULL; + int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return a; + } + + /* Enumerable list of children AVP */ + %newobject children; + PyObject * children() { + struct avp * a = NULL; + PyObject * rl; + int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + rl = PyList_New(0); + while (a) { + PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* the AVPs are not owned */ )); + ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + } + Py_XINCREF(rl); + SWIG_PYTHON_THREAD_END_BLOCK; + return rl; + } + + /* Add a new AVP */ + void add_next(struct avp *avp) { + int ret = fd_msg_avp_add ( $self, MSG_BRW_NEXT, avp); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + void add_prev(struct avp *avp) { + int ret = fd_msg_avp_add ( $self, MSG_BRW_PREV, avp); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + void add_child(struct avp *DISOWN, int begin = 0) { + int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + + /* Get the next AVP at the same level */ + struct avp * get_next() { + struct avp * a = NULL; + int ret = fd_msg_browse($self, MSG_BRW_NEXT, &a, NULL); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return a; + } + + /* Dump */ + void dump (int tree = 1) { + if (tree) + fd_msg_dump_walk(0, $self); + else + fd_msg_dump_one(0, $self); + } + + /* Model */ + struct dict_object * model() { + struct dict_object * m = NULL; + int ret = fd_msg_model($self, &m); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return m; + } + + /* Header */ + struct avp_hdr * header() { + struct avp_hdr * h = NULL; + int ret = fd_msg_avp_hdr($self, &h); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return h; + } + + /* set value */ + void setval(union avp_value * val) { + int ret = fd_msg_avp_setvalue ( $self, val ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + + /* Update the length info in header */ + void update_length() { + int ret = fd_msg_update_length ( $self ); + if (ret) { + DI_ERROR(ret, NULL, NULL); + } + } +} diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/peers.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/peers.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,37 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/queues.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/queues.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,37 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/routing.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/routing.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,87 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + +/****** ROUTING *********/ + +struct rt_data { +}; + +%extend rt_data { + rt_data() { + struct rt_data * r = NULL; + int ret = fd_rtd_init(&r); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return r; + } + ~rt_data() { + struct rt_data *r = self; + fd_rtd_free(&r); + } + void add(char * peerid, char * realm) { + int ret = fd_rtd_candidate_add($self, peerid, realm); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + void remove(char * STRING, size_t LENGTH) { + fd_rtd_candidate_del($self, STRING, LENGTH); + } + void error(char * dest, char * STRING, size_t LENGTH, uint32_t rcode) { + int ret = fd_rtd_error_add($self, dest, (uint8_t *)STRING, LENGTH, rcode); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + struct fd_list * extract(int score = 0) { + struct fd_list * li = NULL; + fd_rtd_candidate_extract($self, &li, score); + return li; + } +} + +%extend rtd_candidate { + void dump() { + fd_log_debug("candidate %p\n", $self); + fd_log_debug(" id : %s\n", $self->diamid); + fd_log_debug(" rlm: %s\n", $self->realm); + fd_log_debug(" sc : %d\n", $self->score); + } +} + diff -r c23ca590fa57 -r 22e8fac3b2d6 extensions/dbg_interactive/sessions.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/sessions.i Thu Dec 16 18:56:41 2010 +0900 @@ -0,0 +1,199 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Do not include this directly, use dbg_interactive.i instead */ + +/****** SESSIONS *********/ + +%{ +/* store the python callback function here */ +static PyObject * py_cleanup_cb = NULL; +/* call it (might be called from a different thread than the interpreter, when session times out) */ +static void call_the_python_cleanup_callback(session_state * state, char * sid) { + PyObject *result; + if (!py_cleanup_cb) + return; + + /* Call the function */ + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + result = PyEval_CallFunction(py_cleanup_cb, "(Os)", state, sid); + Py_XDECREF(result); + SWIG_PYTHON_THREAD_END_BLOCK; + return; +} +%} + +struct session_handler { +}; + +%extend session_handler { + session_handler() { + DI_ERROR(EINVAL, PyExc_SyntaxError, "a cleanup callback parameter is required."); + return NULL; + } + session_handler(PyObject * PyCb) { + struct session_handler * hdl = NULL; + int ret; + if (py_cleanup_cb) { + DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one session handler at a time is supported at the moment in this extension\n."); + return NULL; + } + py_cleanup_cb = PyCb; + Py_XINCREF(py_cleanup_cb); + + ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return hdl; + } + ~session_handler() { + struct session_handler * hdl = self; + int ret = fd_sess_handler_destroy(&hdl); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + /* Now free the callback */ + Py_XDECREF(py_cleanup_cb); + py_cleanup_cb = NULL; + return; + } + void dump() { + fd_sess_dump_hdl(0, $self); + } +} + +struct session { +}; + +%extend session { + /* The first two versions create a new session string. The third one allow to use an existing string. */ + session() { + int ret; + struct session * s = NULL; + ret = fd_sess_new(&s, fd_g_config->cnf_diamid, "dbg_interactive", sizeof("dbg_interactive")); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return s; + } + session(char * diamid, char * STRING, size_t LENGTH) { + int ret; + struct session * s = NULL; + ret = fd_sess_new(&s, diamid, STRING, LENGTH); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return s; + } + session(char * STRING, size_t LENGTH) { + int ret, n; + struct session * s = NULL; + ret = fd_sess_fromsid(STRING, LENGTH, &s, &n); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + /* When defining n as OUTPUT parameter, we get something strange... Use fd_sess_fromsid if you need it */ + #if 0 + if (n) { + fd_log_debug("A new session has been created\n"); + } else { + fd_log_debug("A session with same id already existed\n"); + } + #endif /* 0 */ + + return s; + } + ~session() { + struct session * s = self; + int ret = fd_sess_reclaim(&s); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + return; + } + char * getsid() { + int ret; + char * sid = NULL; + ret = fd_sess_getsid( $self, &sid); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return sid; + } + void settimeout(long seconds) { + struct timespec timeout; + int ret; + clock_gettime(CLOCK_REALTIME, &timeout); + timeout.tv_sec += seconds; + ret = fd_sess_settimeout( $self, &timeout ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + void dump() { + fd_sess_dump(0, $self); + } + void store(struct session_handler * handler, PyObject * DISOWN) { + int ret; + void * store = DISOWN; + Py_XINCREF(DISOWN); + ret = fd_sess_state_store_internal(handler, $self, (void *) &store); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + } + } + %newobject retrieve; + PyObject * retrieve(struct session_handler * handler) { + int ret; + PyObject * state = NULL; + ret = fd_sess_state_retrieve_internal(handler, $self, (void *) &state); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + if (state == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return state; + } +} + diff -r c23ca590fa57 -r 22e8fac3b2d6 include/freeDiameter/libfreeDiameter.h --- a/include/freeDiameter/libfreeDiameter.h Wed Dec 15 18:24:33 2010 +0900 +++ b/include/freeDiameter/libfreeDiameter.h Thu Dec 16 18:56:41 2010 +0900 @@ -2181,7 +2181,6 @@ * PARAMETERS: * msg : A msg object. * diamid : The diameter id of the peer from which this message was received. - * hash : The hash for the diamid value. * add_rr : if true, a Route-Record AVP is added to the message with content diamid. In that case, dict must be supplied. * dict : a dictionary with definition of Route-Record AVP (if add_rr is true) * @@ -2360,7 +2359,7 @@ * - for octetstring AVPs, the string is copied into a new buffer and its address is saved in avp_value. * If the dictionary definition is not found, avp_model is set to NULL and * the content of the AVP is saved as an octetstring in an internal structure. avp_value is NULL. - * As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is be freed. + * 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. * * RETURN VALUE: * 0 : The message has been fully parsed as described. diff -r c23ca590fa57 -r 22e8fac3b2d6 libfreeDiameter/messages.c --- a/libfreeDiameter/messages.c Wed Dec 15 18:24:33 2010 +0900 +++ b/libfreeDiameter/messages.c Thu Dec 16 18:56:41 2010 +0900 @@ -117,6 +117,7 @@ uint8_t *msg_rawbuffer; /* data buffer that was received, saved during fd_msg_parse_buffer and freed in fd_msg_parse_dict */ int msg_routable; /* Is this a routable message? (0: undef, 1: routable, 2: non routable) */ struct msg *msg_query; /* the associated query if the message is a received answer */ + int msg_associated; /* and the counter part information in the query, to avoid double free */ struct rt_data *msg_rtdata; /* Routing list for the query */ struct session *msg_sess; /* Cached message session if any */ struct { @@ -341,6 +342,7 @@ /* associate with query */ ans->msg_query = qry; + qry->msg_associated = 1; /* Done */ *msg = ans; @@ -628,8 +630,14 @@ if (CHECK_MSG(object)) { if (_M(object)->msg_query) { + _M(_M(object)->msg_query)->msg_associated = 0; CHECK_FCT( fd_msg_free( _M(object)->msg_query ) ); _M(object)->msg_query = NULL; + } else { + if (_M(object)->msg_associated) { + TRACE_DEBUG(INFO, "Not freeing query %p referenced in an answer (will be freed along the answer).", object); + return 0; + } } } @@ -688,8 +696,8 @@ msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid ); - fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p sess:%p src:%s\n", - 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)"); + fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n", + 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)"); } /* Dump an avp object */ @@ -861,6 +869,7 @@ CHECK_PARAMS( CHECK_MSG(answer) && CHECK_MSG(query) && (answer->msg_query == NULL ) ); answer->msg_query = query; + query->msg_associated = 1; return 0; } @@ -882,6 +891,7 @@ CHECK_PARAMS( CHECK_MSG(answer) ); + answer->msg_query->msg_associated = 0; answer->msg_query = NULL; return 0;