Mercurial > hg > freeDiameter
changeset 640:237cf6339546
dbg_interactive almost complete
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Mon, 20 Dec 2010 19:36:40 +0900 |
parents | 95a784729cac |
children | 69d3579f6c6c |
files | doc/dbg_interactive.py.sample extensions/dbg_interactive/CMakeLists.txt extensions/dbg_interactive/dbg_interactive.i extensions/dbg_interactive/endpoints.i extensions/dbg_interactive/events.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 freeDiameter/endpoints.c include/freeDiameter/freeDiameter.h |
diffstat | 12 files changed, 740 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/dbg_interactive.py.sample Mon Dec 20 13:07:06 2010 +0900 +++ b/doc/dbg_interactive.py.sample Mon Dec 20 19:36:40 2010 +0900 @@ -89,7 +89,7 @@ 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. +elements = l1.enum_as() # default: enumerates as fd_list. Warning: this a copy, changing the python list has no effect on the underlying fd_list. for li in elements: li.dump() @@ -223,9 +223,6 @@ d.new_obj(DICT_RULE, r, my_ans) del r -d.dump() -del d - r2 = dict_rule_data(my_avp_int, RULE_REQUIRED) # min & max are optional parameters, default to -1 r3 = dict_rule_data(my_avp_int, RULE_REQUIRED, 2, 3) # min is 2, max is 3 r4 = dict_rule_data(my_avp_int, RULE_FIXED_HEAD) # The r4.rule_order = 1 by default, change afterwards if needed. @@ -233,6 +230,9 @@ del r3 del r4 +d.dump() +del d + ####### Now play with the "real" dictionary gdict = cvar.fd_g_config.cnf_dict @@ -272,7 +272,7 @@ s1 = session() s1.getsid() s2 = session("this.is.a.full.session.id") -r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id") +r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id") # use this call if "isnew" is really needed... s4 = session("host.id", "optional.part") s4.settimeout(30) # the python wrapper takes a number of seconds as parameter for simplicity s4.dump() @@ -303,6 +303,31 @@ for c in list.enum_as("struct rtd_candidate *"): print "%s (%s): %s" % (c.diamid, c.realm, c.score) +del rd + + +# A rt_fwd callback has the following prototype: +def my_rtfwd_cb(msg): + print "Forwarding the following message:" + msg.dump() + return [ 0, msg ] # return None instead of msg to stop forwarding. + +fwdhdl = fd_rt_fwd_hdl( my_rtfwd_cb, RT_FWD_REQ ) + + +# A rt_out cb has the following prototype: +def my_rtout_cb(msg, list): + print "Sending out the following message:" + msg.dump() + print "The possible candidates are:" + for c in list.enum_as("struct rtd_candidate *"): + print "%s (%s): %s" % (c.diamid, c.realm, c.score) + return 0 # returns an error code (standard errno values) + +outhdl = fd_rt_out_hdl( my_rtout_cb ) # a priority can be specified as 2nd parameter, default is 0. + + + ############# Messages, AVPs ############ @@ -321,7 +346,7 @@ # Set values val = avp_value() val.u32 = 123 -vi.setval(None) # this cleans a previous value (not needed) +vi.setval(None) # this cleans a previous value (usually not needed) vi.setval(val) val.os = "my.origin.host" oh.setval(val) @@ -378,7 +403,7 @@ # 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() +for a in dwr.children(): a.dump(0) # 0 means: dump only this object, do not walk the tree @@ -435,6 +460,7 @@ # Send a message: +mydwr = msg(buf) mydwr.send() # Optionaly, a callback can be registered when a message is sent, with an optional object. @@ -446,10 +472,12 @@ obj return None +mydwr = msg(buf) mydwr.send(send_callback, some_object) # Set a result code in an answer message. +mydwr = msg(buf) dwa = mydwr.create_answer() dwa.rescode_set() # This adds the DIAMETER_SUCCESS result code dwa.rescode_set("DIAMETER_LIMITED_SUCCESS" ) # This adds a different result code @@ -597,6 +625,21 @@ # Show the number of items in the queue myqueue.length() + +## Variants: +# All the previous calls are suitable to queue Python objects. +# In order to interact with objects queued / poped by C counterpart, +# a second parameter must be passed to specify the object type, +# as follow: +ev = fd_event() +ev.code = FDEV_DUMP_EXT +cvar.fd_g_config.cnf_main_ev.post(ev, "struct fd_event *") + +# Similarly, for *get, we can specify the structure that was queued: +myqueue.get("struct fd_event *") +myqueue.tryget("struct fd_event *") +myqueue.timedget(3, "struct fd_event *") + del myqueue @@ -613,9 +656,7 @@ # Create a new peer np = peer_info() np.pi_diamid = "nas.localdomain" -np.config.pic_flags.pro4 = 1 # 1 for TCP, for some reason PI_P4_TCP is not defined - - +np.config.pic_flags.pro4 = PI_P4_TCP # Add this peer into the framework. @@ -633,7 +674,55 @@ else: print "The peer has been destroyed before it completed the connection." -# Then add the peer simply like this: +# Then add the peer like this: np.add(add_cb) +# Search a peer by its diameter id (returns a peer_hdr object if found) -- similar to fd_peer_getbyid +p = peer_search("nas.domain.aaa") + + +## Validation callback (see fd_peer_validate_register documentation) + +# cb2 prototype: +def my_validate_cb2(pinfo): + print "Cb2 callback trigged for peer %s" % (pinfo.pi_diamid) + # Usually, this would be used only to check some TLS properties, + # which is not really possible yet through the python interpreter... + return 0 # return an error code if the peer is not validated + +# cb prototype: +def my_validate_cb(pinfo): + print "Validate callback trigged for peer %s" % (pinfo.pi_diamid) + # If the peer is not allowed to connect: + #return -1 + # If the peer is authorized: + #return 1 + # In addition, if IPsec is allowed, + #pinfo.config.pic_flags.sec = PI_SEC_NONE + # If no decision has been made: + #return 0 + # If the peer is temporarily authorized but a second callback must be called after TLS negociation: + return my_validate_cb2 + +# Register the callback, it will be called on new incoming connections. +peer_validate_register(my_validate_cb) + + + +############# ENDPOINTS ############ + +ep = fd_endpoint("129.168.168.192") + +# with port: +ep = fd_endpoint("129.168.168.192", 3868) + +# With different flags: +ep = fd_endpoint("129.168.168.192", 3868, EP_FL_PRIMARY) + +# Add IP information for the peer +np = peer_info() +ep.add_merge(np.pi_endpoints) +fd_ep_dump(0, np.pi_endpoints) + +
--- a/extensions/dbg_interactive/CMakeLists.txt Mon Dec 20 13:07:06 2010 +0900 +++ b/extensions/dbg_interactive/CMakeLists.txt Mon Dec 20 19:36:40 2010 +0900 @@ -25,6 +25,8 @@ dispatch.i queues.i peers.i + events.i + endpoints.i ) SET_SOURCE_FILES_PROPERTIES(dbg_interactive.i PROPERTIES SWIG_MODULE_NAME fDpy)
--- a/extensions/dbg_interactive/dbg_interactive.i Mon Dec 20 13:07:06 2010 +0900 +++ b/extensions/dbg_interactive/dbg_interactive.i Mon Dec 20 19:36:40 2010 +0900 @@ -67,7 +67,7 @@ /* This is not thread-safe etc. but it should work /most of the time/. */ static int wrapper_errno; static PyObject* wrapper_errno_py; -static char * wrapper_error_txt; /* if NULL, use strerror(errno) */ +static const char * wrapper_error_txt; /* if NULL, use strerror(errno) */ #define DI_ERROR(code, pycode, str) { \ fd_log_debug("[dbg_interactive] ERROR: %s: %s\n", __PRETTY_FUNCTION__, str ? str : strerror(code)); \ wrapper_errno = code; \ @@ -87,7 +87,7 @@ $action /* Now, test for error */ if (wrapper_errno) { - char * str = wrapper_error_txt ? wrapper_error_txt : strerror(wrapper_errno); + const char * str = wrapper_error_txt ? wrapper_error_txt : strerror(wrapper_errno); PyObject * exc = wrapper_errno_py; if (!exc) { switch (wrapper_errno) { @@ -108,7 +108,7 @@ Some types & typemaps for usability ***********************************/ -%apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; /* fd_hash */ +%apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; /* Generic typemap for functions that create something */ %typemap(in, numinputs=0,noblock=1) SWIGTYPE ** OUTPUT (void *temp = NULL) { @@ -118,21 +118,42 @@ %append_output(SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } +/* Typemap to return a boolean value as output parameter */ +%typemap(in, numinputs=0,noblock=1) int * BOOL_OUT (int temp) { + $1 = &temp; +} +%typemap(argout,noblock=1) int * BOOL_OUT { + PyObject * r; + if (*$1) + r = Py_True; + else + r = Py_False; + Py_XINCREF(r); + %append_output(r); +} + /* To allow passing callback functions defined in python */ %typemap(in) PyObject *PyCb { - if (!PyCallable_Check($input)) { - PyErr_SetString(PyExc_TypeError, "Need a callable object!"); - SWIG_fail; + if (!$input || ($input == Py_None)) { + $1 = NULL; + } else { + if (!PyCallable_Check($input)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + SWIG_fail; + } + $1 = $input; } - $1 = $input; } - +%{ /* Forward declaration for the peers module */ -%{ static void fd_add_cb(struct peer_info *peer, void *data); %} +/* Overwrite declaration to apply typemaps */ +int fd_sess_fromsid ( char * STRING, size_t LENGTH, struct session ** OUTPUT, int * BOOL_OUT); + + /********************************************************* Now, create wrappers for (almost) all objects from fD API *********************************************************/ @@ -154,3 +175,5 @@ %include "queues.i" %include "peers.i" +%include "events.i" +%include "endpoints.i"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/endpoints.i Mon Dec 20 19:36:40 2010 +0900 @@ -0,0 +1,130 @@ +/********************************************************************************************************* +* 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 */ + +/****** ENDPOINTS *********/ + +%{ + +#include <sys/socket.h> +#include <netdb.h> + +%} + +%extend fd_endpoint { + fd_endpoint() { + struct fd_endpoint *np = (struct fd_endpoint *)calloc(1, sizeof(struct fd_endpoint)); + if (!np) { + DI_ERROR_MALLOC; + return NULL; + } + fd_list_init(&np->chain, np); + return np; + } + + fd_endpoint(const char * endpoint, uint16_t port = 0, uint32_t flags = EP_FL_CONF) { + struct addrinfo hints; + struct addrinfo *ai = NULL; + int ret; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family= AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + + ret = getaddrinfo(endpoint, NULL, &hints, &ai); + if (ret) { + DI_ERROR(ret, PyExc_ValueError, gai_strerror(ret)); + return NULL; + } + + if (port) { + switch (ai->ai_family) { + case AF_INET: + ((sSA4 *)ai->ai_addr)->sin_port = htons(port); + break; + case AF_INET6: + ((sSA6 *)ai->ai_addr)->sin6_port = htons(port); + break; + default: + DI_ERROR(EINVAL, PyExc_RuntimeError, "Unknown family returned by getaddrinfo"); + return NULL; + } + } + + struct fd_endpoint *np = (struct fd_endpoint *)calloc(1, sizeof(struct fd_endpoint)); + if (!np) { + DI_ERROR_MALLOC; + return NULL; + } + fd_list_init(&np->chain, np); + + memcpy(&np->s.sa, ai->ai_addr, ai->ai_addrlen); + + freeaddrinfo(ai); + + np->flags = flags; + + return np; + } + + ~fd_endpoint() { + fd_list_unlink(&$self->chain); + free($self); + } + + /* Merge to a list */ + %delobject add_merge; + void add_merge(struct fd_list * eplist) { + int ret; + + if (!eplist) { + DI_ERROR(EINVAL, NULL, NULL); + return; + } + + ret = fd_ep_add_merge( eplist, &$self->s.sa, sSAlen(&$self->s.sa), $self->flags ); + if (ret) { + DI_ERROR(ret, NULL, NULL); + return; + } + + return; + } + + void dump() { + fd_ep_dump_one( "", $self, "\n" ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_interactive/events.i Mon Dec 20 19:36:40 2010 +0900 @@ -0,0 +1,52 @@ +/********************************************************************************************************* +* 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 */ + +/****** EVENTS *********/ + +%extend fd_event { + fd_event(int code, char *STRING, size_t LENGTH) { + struct fd_event * fd = calloc(1, sizeof(struct fd_event)); + if (!fd) { + DI_ERROR_MALLOC; + return NULL; + } + fd->code = code; + fd->data = STRING; /* Should maybe malloc it ? */ + fd->size = LENGTH; + return fd; + } +}
--- a/extensions/dbg_interactive/lists.i Mon Dec 20 13:07:06 2010 +0900 +++ b/extensions/dbg_interactive/lists.i Mon Dec 20 19:36:40 2010 +0900 @@ -70,8 +70,14 @@ fd_list_insert_after($self, li); } /* Test for emptyness */ - int isempty() { - return FD_IS_LIST_EMPTY($self); + PyObject * isempty() { + PyObject * ret; + if (FD_IS_LIST_EMPTY($self)) + ret = Py_True; + else + ret = Py_False; + Py_XINCREF(ret); + return ret; } /* Concatenate two lists */ void concat(struct fd_list * li) {
--- a/extensions/dbg_interactive/messages.i Mon Dec 20 13:07:06 2010 +0900 +++ b/extensions/dbg_interactive/messages.i Mon Dec 20 19:36:40 2010 +0900 @@ -292,8 +292,14 @@ } /* Is routable? */ - int is_routable() { - return fd_msg_is_routable($self); + PyObject * is_routable() { + PyObject * r; + if (fd_msg_is_routable($self)) + r = Py_True; + else + r = Py_False; + Py_XINCREF(r); + return r; } /* Get the source */
--- a/extensions/dbg_interactive/peers.i Mon Dec 20 13:07:06 2010 +0900 +++ b/extensions/dbg_interactive/peers.i Mon Dec 20 19:36:40 2010 +0900 @@ -66,7 +66,20 @@ %} %extend peer_info { + peer_info () { + struct peer_info *np = (struct peer_info *)calloc(1, sizeof(struct peer_info)); + if (!np) { + DI_ERROR_MALLOC; + return NULL; + } + + fd_list_init(&np->pi_endpoints, NULL); + + return np; + } + /* Wrapper around fd_peer_add to allow calling the python callback */ + %delobject add; void add(PyObject * PyCb=NULL) { int ret; @@ -80,10 +93,135 @@ DI_ERROR(ret, NULL, NULL); } } +} - /* Add an endpoint */ - void add_endpoint(char * endpoint) { - fd_log_debug("What is the best way in python to pass an endpoint? (ip + port)"); +%inline %{ +static struct peer_hdr * peer_search(char *diamid) { + struct peer_hdr *r = NULL; + int ret = fd_peer_getbyid( diamid, &r ); + if (ret) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return r; +} +%} + +%{ +static PyObject * validate_cb_py = NULL; +static PyObject * validate_cb2_py = NULL; + +/* C wrapper that calls validate_cb2_py */ +int call_the_python_validate_callback2(struct peer_info * info) { + PyObject *PyInfo; + PyObject *result = NULL; + int ret = 0; + + if (!validate_cb2_py) { + fd_log_debug("Internal error: missing the callback2!\n"); + return ENOTSUP; + } + + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + /* Convert the arguments */ + PyInfo = SWIG_NewPointerObj((void *)info, SWIGTYPE_p_peer_info, 0 ); + + /* Call the function */ + result = PyEval_CallFunction(validate_cb2_py, "(O)", PyInfo); + + /* The result is an integer */ + if ((result == NULL) || !SWIG_IsOK(SWIG_AsVal_int(result, &ret))) { + fd_log_debug("Error: The Python callback did not return an integer.\n"); + ret = EINVAL; + goto out; + } + +out: + Py_XDECREF(result); + SWIG_PYTHON_THREAD_END_BLOCK; + return ret; +} + +/* C wrapper that calls validate_cb_py */ +int call_the_python_validate_callback(struct peer_info * info, int * auth, int (**cb2)(struct peer_info *)) { + PyObject *PyInfo; + PyObject *result = NULL; + int ret = 0; + + if (!validate_cb_py) { + fd_log_debug("Internal error: missing the callback!\n"); + return ENOTSUP; } + + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + /* Convert the arguments */ + PyInfo = SWIG_NewPointerObj((void *)info, SWIGTYPE_p_peer_info, 0 ); + + /* Call the function */ + result = PyEval_CallFunction(validate_cb_py, "(O)", PyInfo); + + /* The result is supposedly -1, 1, or a cb2 */ + if (result == NULL) { + fd_log_debug("Error: The Python callback did not return a value.\n"); + ret = EINVAL; + goto out; + } + + if (PyCallable_Check(result)) { + if (cb2) { + if (validate_cb2_py && (validate_cb2_py != result)) { + fd_log_debug("Only 1 register callback2 is supported currently\n"); + ret = ENOTSUP; + goto out; + } + validate_cb2_py = result; + *cb2 = call_the_python_validate_callback2; + *auth = 1; + goto out_nodec; + } else { + *auth = 1; + goto out; /* ignore the callback since it won't be used */ + } + } else { /* In this case, the return value must be -1, 0, or 1 */ + if (!SWIG_IsOK(SWIG_AsVal_int(result, auth))) { + fd_log_debug("Error: Cannot convert the return value to integer.\n"); + ret = EINVAL; + goto out; + } + } + +out: + Py_XDECREF(result); +out_nodec: + SWIG_PYTHON_THREAD_END_BLOCK; + TRACE_DEBUG(FULL, "ret=%d, *auth=%d, cb2=%p, *cb2=%p", ret, *auth, cb2, cb2 ? *cb2 : NULL); + return ret; +} +%} + +%inline %{ +static void peer_validate_register(PyObject * PyCb) { + int ret ; + + if (!PyCb) { + DI_ERROR(EINVAL, NULL, "The callback must be provided"); + return; + } + + if (validate_cb_py) { + if (PyCb != validate_cb_py) { + DI_ERROR(ENOTSUP, PyExc_RuntimeError, "Only 1 register callback is supported currently"); + return; + } + } else { + validate_cb_py = PyCb; + Py_XINCREF(PyCb); + } + + ret = fd_peer_validate_register ( call_the_python_validate_callback ); + if (ret) { + DI_ERROR(ret, NULL, NULL); + } } +%}
--- a/extensions/dbg_interactive/queues.i Mon Dec 20 13:07:06 2010 +0900 +++ b/extensions/dbg_interactive/queues.i Mon Dec 20 19:36:40 2010 +0900 @@ -76,36 +76,75 @@ /* Is the threashold function useful here? TODO... */ /* Post an item */ - void post(PyObject * item) { + void post(PyObject * item, char * type = NULL) { int ret; - PyObject * i = item; - - Py_XINCREF(i); - ret = fd_fifo_post($self, &i); + if (type) { + void * real_obj = NULL; + swig_type_info * desttype = NULL; + desttype = SWIG_TypeQuery(type); + if (!desttype) { + DI_ERROR(EINVAL, NULL, "Unable to resolve this type. Please check the form: 'struct blahbla *'"); + return; + } + /* Now, get the "real" value under the shadow umbrella */ + ret = SWIG_ConvertPtr(item, &real_obj, desttype, SWIG_POINTER_DISOWN ); + if (!SWIG_IsOK(ret)) { + DI_ERROR(EINVAL, SWIG_ErrorType(ret), "Unable to convert the item to given type"); + return; + } + ret = fd_fifo_post($self, &real_obj); + } else { + PyObject * i = item; + Py_XINCREF(i); + ret = fd_fifo_post($self, &i); + } if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* Get (blocking) */ - PyObject * get() { + PyObject * get(char * type = NULL) { int ret; PyObject * i = NULL; + void * obj = NULL; + swig_type_info * desttype = 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; + } + } - ret = fd_fifo_get($self, &i); + ret = fd_fifo_get($self, &obj); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } - return i; + if (type) { + return SWIG_NewPointerObj(obj, desttype, 0 ); + } else { + i = obj; + return i; + } } /* TryGet (non-blocking, returns None on empty queue) */ - PyObject * tryget() { + PyObject * tryget(char * type = NULL) { int ret; PyObject * i = NULL; + void * obj = NULL; + swig_type_info * desttype = 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; + } + } - ret = fd_fifo_tryget($self, &i); + ret = fd_fifo_tryget($self, &obj); if (ret == EWOULDBLOCK) { Py_XINCREF(Py_None); return Py_None; @@ -114,19 +153,33 @@ DI_ERROR(ret, NULL, NULL); } - return i; + if (type) { + return SWIG_NewPointerObj(obj, desttype, 0 ); + } else { + i = obj; + return i; + } } /* TimedGet (blocking for a while) */ - PyObject * timedget(long seconds) { + PyObject * timedget(long seconds, char * type = NULL) { int ret; PyObject * i = NULL; struct timespec ts; + void * obj = NULL; + swig_type_info * desttype = 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; + } + } clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += seconds; - ret = fd_fifo_timedget($self, &i, &ts); + ret = fd_fifo_timedget($self, &obj, &ts); if (ret == ETIMEDOUT) { Py_XINCREF(Py_None); return Py_None; @@ -135,7 +188,12 @@ DI_ERROR(ret, NULL, NULL); } - return i; + if (type) { + return SWIG_NewPointerObj(obj, desttype, 0 ); + } else { + i = obj; + return i; + } } }
--- a/extensions/dbg_interactive/routing.i Mon Dec 20 13:07:06 2010 +0900 +++ b/extensions/dbg_interactive/routing.i Mon Dec 20 19:36:40 2010 +0900 @@ -76,6 +76,8 @@ } } + + %extend rtd_candidate { void dump() { fd_log_debug("candidate %p\n", $self); @@ -85,3 +87,161 @@ } } + +%{ +/* call it (will be called from a different thread than the interpreter, when message arrives) */ +static int call_the_python_rt_fwd_callback(void * pycb, struct msg **msg) { + PyObject *PyMsg; + PyObject *cb, *result = NULL; + int ret = 0; + + if (!pycb) { + fd_log_debug("Internal error: missing the callback!\n"); + return ENOTSUP; + } + cb = pycb; + + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + /* Convert the arguments */ + PyMsg = SWIG_NewPointerObj((void *)*msg, SWIGTYPE_p_msg, 0 ); + + /* Call the function */ + result = PyEval_CallFunction(cb, "(O)", PyMsg); + + /* The result is supposedly composed of: [ ret, *msg ] */ + if ((result == NULL) || (!PyList_Check(result)) || (PyList_Size(result) != 2)) { + fd_log_debug("Error: The Python callback did not return [ ret, msg ].\n"); + ret = EINVAL; + goto out; + } + + /* Convert the return values */ + if (!SWIG_IsOK(SWIG_AsVal_int(PyList_GetItem(result, 0), &ret))) { + fd_log_debug("Error: Cannot convert the first return value to integer.\n"); + ret = EINVAL; + goto out; + } + if (ret) { + TRACE_DEBUG(INFO, "The Python callback returned the error code %d (%s)\n", ret, strerror(ret)); + goto out; + } + + if (!SWIG_IsOK(SWIG_ConvertPtr(PyList_GetItem(result, 1), (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) { + fd_log_debug("Error: Cannot convert the second return value to message.\n"); + ret = EINVAL; + goto out; + } + +out: + Py_XDECREF(result); + + SWIG_PYTHON_THREAD_END_BLOCK; + return ret; +} +%} + + +struct fd_rt_fwd_hdl { +}; + +%extend fd_rt_fwd_hdl{ + fd_rt_fwd_hdl(PyObject * PyCb, enum fd_rt_fwd_dir dir) { + struct fd_rt_fwd_hdl * r = NULL; + int ret; + + Py_XINCREF(PyCb); + + ret = fd_rt_fwd_register( call_the_python_rt_fwd_callback, PyCb, dir, &r ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return r; + } + + ~fd_rt_fwd_hdl() { + PyObject * func; + int ret = fd_rt_fwd_unregister ( $self, (void *) &func ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return; + } + Py_XDECREF(func); + return; + } +} + + +%{ +/* call it (will be called from a different thread than the interpreter, when message arrives) */ +static int call_the_python_rt_out_callback(void * pycb, struct msg *msg, struct fd_list * candidates) { + PyObject *PyMsg, *PyCands; + PyObject *cb, *result = NULL; + int ret = 0; + + if (!pycb) { + fd_log_debug("Internal error: missing the callback!\n"); + return ENOTSUP; + } + cb = pycb; + + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + /* Convert the arguments */ + PyMsg = SWIG_NewPointerObj((void *)msg, SWIGTYPE_p_msg, 0 ); + PyCands = SWIG_NewPointerObj((void *)candidates, SWIGTYPE_p_fd_list, 0 ); + + /* Call the function */ + result = PyEval_CallFunction(cb, "(OO)", PyMsg, PyCands); + + /* The result is supposedly composed of: [ ret, *msg ] */ + if (result == NULL){ + fd_log_debug("Error: The Python callback raised an exception.\n"); + ret = EINVAL; + goto out; + } + + /* Convert the return values */ + if (!SWIG_IsOK(SWIG_AsVal_int(result, &ret))) { + fd_log_debug("Error: Cannot convert the return value to integer.\n"); + ret = EINVAL; + goto out; + } +out: + Py_XDECREF(result); + + SWIG_PYTHON_THREAD_END_BLOCK; + return ret; +} +%} + + +struct fd_rt_out_hdl { +}; + +%extend fd_rt_out_hdl{ + fd_rt_out_hdl(PyObject * PyCb, int priority = 0) { + struct fd_rt_out_hdl * r = NULL; + int ret; + + Py_XINCREF(PyCb); + + ret = fd_rt_out_register( call_the_python_rt_out_callback, PyCb, priority, &r ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return NULL; + } + return r; + } + + ~fd_rt_out_hdl() { + PyObject * func; + int ret = fd_rt_out_unregister ( $self, (void *) &func ); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); + return; + } + Py_XDECREF(func); + return; + } +} +
--- a/freeDiameter/endpoints.c Mon Dec 20 13:07:06 2010 +0900 +++ b/freeDiameter/endpoints.c Mon Dec 20 19:36:40 2010 +0900 @@ -52,6 +52,11 @@ TRACE_ENTRY("%p %p %u %x", list, sa, sl, flags); CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) ); + if (list->next == NULL) { + /* the list is not initialized yet, do it */ + fd_list_init(list, NULL); + } + if (TRACE_BOOL(ANNOYING + 1)) { TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Current list:"); fd_ep_dump( 4, list );
--- a/include/freeDiameter/freeDiameter.h Mon Dec 20 13:07:06 2010 +0900 +++ b/include/freeDiameter/freeDiameter.h Mon Dec 20 19:36:40 2010 +0900 @@ -69,9 +69,9 @@ } /* Structure to hold the configuration of the freeDiameter daemon */ +#define EYEC_CONFIG 0xC011F16 struct fd_config { int cnf_eyec; /* Eye catcher: EYEC_CONFIG */ - #define EYEC_CONFIG 0xC011F16 char *cnf_file; /* Configuration file to parse, default is DEFAULT_CONF_FILE */ @@ -177,6 +177,29 @@ #define STATE_STR(state) \ (((unsigned)(state)) <= STATE_MAX ? peer_state_str[((unsigned)(state)) ] : "<Invalid>") +/* Constants for the peer_info structure bellow */ +#define PI_P3_DEFAULT 0 /* Use any available protocol */ +#define PI_P3_IP 1 /* Use only IP to connect to this peer */ +#define PI_P3_IPv6 2 /* resp, IPv6 */ + +#define PI_P4_DEFAULT 0 /* Attempt any available protocol */ +#define PI_P4_TCP 1 /* Only use TCP */ +#define PI_P4_SCTP 2 /* Only use SCTP */ + +#define PI_ALGPREF_SCTP 0 /* SCTP is attempted first (default) */ +#define PI_ALGPREF_TCP 1 /* TCP is attempted first */ + +#define PI_SEC_DEFAULT 0 /* New TLS security (handshake after connection, protecting also CER/CEA) */ +#define PI_SEC_NONE 1 /* Transparent security with this peer (IPsec) */ +#define PI_SEC_TLS_OLD 2 /* Old TLS security (use Inband-Security-Id AVP during CER/CEA) */ + /* Set sec = 3 to authorize use of (Inband-Security-Id == NONE) with this peer, sec = 2 only authorizing TLS */ + +#define PI_EXP_NONE 0 /* the peer entry does not expire */ +#define PI_EXP_INACTIVE 1 /* the peer entry expires (i.e. is deleted) after pi_lft seconds without activity */ + +#define PI_PRST_NONE 0 /* the peer entry is deleted after disconnection / error */ +#define PI_PRST_ALWAYS 1 /* the peer entry is persistant (will be kept as ZOMBIE in case of error) */ + /* Information about a remote peer */ struct peer_info { @@ -184,32 +207,12 @@ struct { struct { - #define PI_P3_DEFAULT 0 /* Use any available protocol */ - #define PI_P3_IP 1 /* Use only IP to connect to this peer */ - #define PI_P3_IPv6 2 /* resp, IPv6 */ - unsigned pro3 :2; - - #define PI_P4_DEFAULT 0 /* Attempt any available protocol */ - #define PI_P4_TCP 1 /* Only use TCP */ - #define PI_P4_SCTP 2 /* Only use SCTP */ - unsigned pro4 :2; - - #define PI_ALGPREF_SCTP 0 /* SCTP is attempted first (default) */ - #define PI_ALGPREF_TCP 1 /* TCP is attempted first */ - unsigned alg :1; - - #define PI_SEC_DEFAULT 0 /* New TLS security (handshake after connection, protecting also CER/CEA) */ - #define PI_SEC_NONE 1 /* Transparent security with this peer (IPsec) */ - #define PI_SEC_TLS_OLD 2 /* Old TLS security (use Inband-Security-Id AVP during CER/CEA) */ - unsigned sec :2; /* Set sec = 3 to authorize use of (Inband-Security-Id == NONE) with this peer, sec = 2 only authorizing TLS */ - - #define PI_EXP_NONE 0 /* the peer entry does not expire */ - #define PI_EXP_INACTIVE 1 /* the peer entry expires (i.e. is deleted) after pi_lft seconds without activity */ - unsigned exp :1; - - #define PI_PRST_NONE 0 /* the peer entry is deleted after disconnection / error */ - #define PI_PRST_ALWAYS 1 /* the peer entry is persistant (will be kept as ZOMBIE in case of error) */ - unsigned persist :1; + unsigned pro3 :2; /* PI_P3_* */ + unsigned pro4 :2; /* PI_P4_* */ + unsigned alg :1; /* PI_ALGPREF_* */ + unsigned sec :2; /* PI_SEC_* */ + unsigned exp :1; /* PI_EXP_* */ + unsigned persist :1; /* PI_PRST_* */ } pic_flags; /* Flags influencing the connection to the remote peer */