changeset 637:22e8fac3b2d6

Split interface file in modules
author Sebastien Decugis <sdecugis@nict.go.jp>
date Thu, 16 Dec 2010 18:56:41 +0900
parents c23ca590fa57
children 9448cba86673
files doc/dbg_interactive.py.sample extensions/dbg_interactive/CMakeLists.txt extensions/dbg_interactive/dbg_interactive.i extensions/dbg_interactive/dictionary.i extensions/dbg_interactive/dispatch.i extensions/dbg_interactive/lists.i extensions/dbg_interactive/messages.i extensions/dbg_interactive/peers.i extensions/dbg_interactive/queues.i extensions/dbg_interactive/routing.i extensions/dbg_interactive/sessions.i include/freeDiameter/libfreeDiameter.h libfreeDiameter/messages.c
diffstat 13 files changed, 1413 insertions(+), 643 deletions(-) [+]
line wrap: on
line diff
--- 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"
--- 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
--- 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 <stdint.i>
-%include <cdata.i>
+//%include <cdata.i>
 %include <cstring.i>
 %include <typemaps.i>
 
-/* 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"
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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 ? "..." : "");
+	}
+}
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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 */
+
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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;
+	}
+};
+
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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);
+		}
+	}
+}
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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 */
+
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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 */
+
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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);
+	}
+}
+
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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;
+	}
+}	
+
--- 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.
--- 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;
"Welcome to our mercurial repository"