Mercurial > hg > freeDiameter
changeset 636:c23ca590fa57
Still making progress on the dbg_interactive interface.
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Wed, 15 Dec 2010 18:24:33 +0900 |
parents | 134e4fb9eef5 |
children | 22e8fac3b2d6 |
files | doc/dbg_interactive.py.sample extensions/dbg_interactive/dbg_interactive.i |
diffstat | 2 files changed, 420 insertions(+), 179 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/dbg_interactive.py.sample Tue Dec 14 17:34:46 2010 +0900 +++ b/doc/dbg_interactive.py.sample Wed Dec 15 18:24:33 2010 +0900 @@ -94,7 +94,7 @@ v = dict_vendor_data() v.vendor_id = 123 v.vendor_name = "My test vendor" -r, my_vendor = fd_dict_new(d, DICT_VENDOR, v, None) +my_vendor = d.new_obj(DICT_VENDOR, v) del v d.dump() d.vendors_list() @@ -103,29 +103,29 @@ a = dict_application_data() a.application_id = 99 a.application_name = "My test appl" -r, my_appl = fd_dict_new(d, DICT_APPLICATION, a, my_vendor) +my_appl = d.new_obj(DICT_APPLICATION, a, my_vendor) del a # New type (callbacks are not supported yet...) t = dict_type_data() t.type_base = AVP_TYPE_INTEGER32 t.type_name = "My integer AVP" -r, my_type_int = fd_dict_new(d, DICT_TYPE, t, my_appl) +my_type_int = d.new_obj(DICT_TYPE, t, my_appl) t.type_base = AVP_TYPE_OCTETSTRING t.type_name = "My binary buffer AVP" -r, my_type_os = fd_dict_new(d, DICT_TYPE, t, my_appl) +my_type_os = d.new_obj(DICT_TYPE, t, my_appl) del t # Constants c = dict_enumval_data() c.enum_name = "AVP_VALUE_TROIS" c.enum_value.i32 = 3 -fd_dict_new(d, DICT_ENUMVAL, c, my_type_int) +d.new_obj(DICT_ENUMVAL, c, my_type_int) c.enum_name = "A_BUFFER_CONSTANT" c.enum_value.os = "This is a very long AVP value that we prefer to represent as a constant" c.enum_value.os.dump() -fd_dict_new(d, DICT_ENUMVAL, c, my_type_os) +d.new_obj(DICT_ENUMVAL, c, my_type_os) del c # AVP @@ -134,14 +134,14 @@ a.avp_name = "my integer avp" a.avp_flag_mask = AVP_FLAG_MANDATORY a.avp_basetype = AVP_TYPE_INTEGER32 -r, my_avp_int = fd_dict_new(d, DICT_AVP, a, my_type_int) +my_avp_int = d.new_obj(DICT_AVP, a, my_type_int) a.avp_vendor = 123 a.avp_name = "my OS avp" a.avp_flag_mask = AVP_FLAG_MANDATORY + AVP_FLAG_VENDOR a.avp_flag_val = AVP_FLAG_VENDOR a.avp_basetype = AVP_TYPE_OCTETSTRING -r, my_avp_os = fd_dict_new(d, DICT_AVP, a, my_type_os) +my_avp_os = d.new_obj(DICT_AVP, a, my_type_os) del a # Command @@ -150,24 +150,24 @@ c.cmd_name = "My-Python-Request" c.cmd_flag_mask = CMD_FLAG_REQUEST + CMD_FLAG_PROXIABLE c.cmd_flag_val = CMD_FLAG_REQUEST + CMD_FLAG_PROXIABLE -r, my_req = fd_dict_new(d, DICT_COMMAND, c, my_appl) +my_req = d.new_obj(DICT_COMMAND, c, my_appl) c.cmd_name = "My-Python-Answer" c.cmd_flag_val = CMD_FLAG_PROXIABLE -r, my_ans = fd_dict_new(d, DICT_COMMAND, c, my_appl) +my_ans = d.new_obj(DICT_COMMAND, c, my_appl) del c # Rule -rd = dict_rule_data() -rd.rule_avp = my_avp_int -rd.rule_position = RULE_REQUIRED -rd.rule_min = -1 -rd.rule_max = -1 -r, my_rule1 = fd_dict_new(d, DICT_RULE, rd, my_req) -r, my_rule2 = fd_dict_new(d, DICT_RULE, rd, my_ans) -rd.rule_avp = my_avp_os -r, my_rule3 = fd_dict_new(d, DICT_RULE, rd, my_req) -r, my_rule4 = fd_dict_new(d, DICT_RULE, rd, my_ans) -del rd +r = dict_rule_data() +r.rule_avp = my_avp_int +r.rule_position = RULE_REQUIRED +r.rule_min = -1 +r.rule_max = -1 +d.new_obj(DICT_RULE, r, my_req) +d.new_obj(DICT_RULE, r, my_ans) +r.rule_avp = my_avp_os +d.new_obj(DICT_RULE, r, my_req) +d.new_obj(DICT_RULE, r, my_ans) +del r d.dump() del d @@ -177,70 +177,70 @@ gdict = cvar.fd_g_config.cnf_dict -r, appl = fd_dict_search ( gdict, DICT_APPLICATION, APPLICATION_BY_ID, 3, -1 ) -obj.dump() -r, avp = fd_dict_search( gdict, DICT_AVP, AVP_BY_NAME, "Origin-Host", -1) -obj.dump() -r, errcmd = fd_dict_get_error_cmd( gdict ) +appl = gdict.search ( DICT_APPLICATION, APPLICATION_BY_ID, 3 ) +appl.dump() +avp = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host") +avp.dump() +errcmd = gdict.error_cmd() -data = dict_avp_data() -fd_dict_getval(avp, data) -print data.avp_code -del data +v = avp.getval() +print v.avp_code +del v -r, t = fd_dict_gettype(appl) +t = avp.gettype() +print t del t -r, dict = fd_dict_getdict(avp) +dict = avp.getdict() del dict - ############# Sessions ############ # handler def my_cleanup(state,sid): print "Cleaning up python state for session:", sid print "Received state:", state + del state hdl = session_handler(my_cleanup) hdl.dump() del hdl +# Session hdl = session_handler(my_cleanup) - - -# Session s1 = session() 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.settimeout(30) # the python wrapper takes a number of seconds as parameter for simplicity s4.dump() - -# state -mystate = [ 34, "clah", [ 32, 12 ] ] - -s4.store(hdl, mystate) - +# states +mystate = [ 34, "blah", [ 32, 12 ] ] +s1.store(hdl, mystate) +del mystate +gotstate = s1.retrieve(hdl) +print gotstate +del gotstate -## TODO : debug the following (segfault) +############# Routing ############ -def my_cleanup(state,sid): - print "Cleaning up python state for session:", sid - print "Received state:", state +rd = rt_data() -hdl = session_handler(my_cleanup) -s4 = session("host.id", "opt.part") -mystate = [ 34, "clah", [ 32, 12 ] ] -s4.store(hdl, mystate) -del hdl +rd.add("p1.testbed.aaa", "testbed.aaa") +rd.add("p2.testbed.aaa", "testbed.aaa") +rd.add("p3.testbed.aaa", "testbed.aaa") +rd.add("p4.testbed.aaa", "testbed.aaa") +rd.remove("p2.testbed.aaa") +rd.error("p3.testbed.aaa", "relay.testbed.aaa", 3002) + +list = rd.extract(-1) +list[0].dump() @@ -249,22 +249,6 @@ ######################### old stuff (need update) ###################### -# Routing data -prtd = new_rt_data_pptr() -fd_rtd_init(prtd) -fd_rtd_candidate_add(rt_data_pptr_value(prtd), "p1.testbed.aaa", "testbed.aaa") -fd_rtd_candidate_add(rt_data_pptr_value(prtd), "p2.testbed.aaa", "testbed.aaa") -fd_rtd_candidate_add(rt_data_pptr_value(prtd), "p3.testbed.aaa", "testbed.aaa") -fd_rtd_candidate_del(rt_data_pptr_value(prtd), "p2.testbed.aaa", 0) -pcands = new_fd_list_pptr() -fd_rtd_candidate_extract(rt_data_pptr_value(prtd), pcands, 0) -li = fd_list_pptr_value(pcands) -li = fd_list_next_get(li) -c = fd_list_to_rtd_candidate(li) -rtd_candidate_diamid_get(c) -li = fd_list_next_get(li) -c = fd_list_to_rtd_candidate(li) -rtd_candidate_diamid_get(c) # Messages
--- a/extensions/dbg_interactive/dbg_interactive.i Tue Dec 14 17:34:46 2010 +0900 +++ b/extensions/dbg_interactive/dbg_interactive.i Wed Dec 15 18:24:33 2010 +0900 @@ -50,9 +50,10 @@ %include <cstring.i> %include <typemaps.i> -/* Some functions are not available through the wrapper, or accessed differently */ +/* 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; @@ -63,7 +64,13 @@ %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__ @@ -74,30 +81,77 @@ %immutable peer_state_str; +/* Create a generic error handling mechanism so that functions can provoke an exception */ +%{ +/* 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) */ +#define DI_ERROR(code, pycode, str) { \ + fd_log_debug("[dbg_interactive] ERROR: %s: %s\n", __PRETTY_FUNCTION__, str ? str : strerror(code)); \ + wrapper_errno = code; \ + wrapper_errno_py = pycode; \ + wrapper_error_txt = str; \ +} + +#define DI_ERROR_MALLOC \ + DI_ERROR(ENOMEM, PyExc_MemoryError, NULL) + +%} + +%exception { + /* reset the errno */ + wrapper_errno = 0; + /* Call the function -- it will use DI_ERROR macro in case of error */ + $action + /* Now, test for error */ + if (wrapper_errno) { + char * str = wrapper_error_txt ? wrapper_error_txt : strerror(wrapper_errno); + PyObject * exc = wrapper_errno_py; + if (!exc) { + switch (wrapper_errno) { + case ENOMEM: exc = PyExc_MemoryError; break; + case EINVAL: exc = PyExc_ValueError; break; + default: exc = PyExc_RuntimeError; + } + } + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetString(exc, str); + SWIG_fail; + SWIG_PYTHON_THREAD_END_BLOCK; + } +} + /*********************************** Some types & typemaps for usability ***********************************/ -/* for fd_hash */ %apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; -/* for dictionary functions */ %typemap(in, numinputs=0,noblock=1) SWIGTYPE ** OUTPUT (void *temp = NULL) { $1 = (void *)&temp; } %typemap(argout,noblock=1) SWIGTYPE ** OUTPUT { %append_output(SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } -%apply SWIGTYPE ** OUTPUT { struct dict_object ** ref }; -%apply SWIGTYPE ** OUTPUT { struct dict_object ** obj }; -%apply SWIGTYPE ** OUTPUT { struct dict_object ** result }; -%apply SWIGTYPE ** OUTPUT { struct dictionary ** dict }; /* this is for fd_dict_getdict, not fd_dict_init (use constructor) */ + %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 */ +%typemap(in) PyObject *PyCb { + if (!PyCallable_Check($input)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + SWIG_fail; + } + $1 = $input; +} + + + /********************************************************* Now, create wrappers for (almost) all objects from fD API *********************************************************/ @@ -120,8 +174,7 @@ struct fd_list * li; li = (struct fd_list *) malloc(sizeof(struct fd_list)); if (!li) { - fd_log_debug("Out of memory!\n"); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + DI_ERROR_MALLOC; return NULL; } fd_list_init(li, o); @@ -152,43 +205,80 @@ struct dictionary * r = NULL; int ret = fd_dict_init(&r); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + DI_ERROR(ret, NULL, NULL); return NULL; } return r; } ~dictionary() { - if (self) { - struct dictionary *d = self; - int ret = fd_dict_fini(&d); - if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - } - return; + struct dictionary *d = self; + int ret = fd_dict_fini(&d); + if (ret != 0) { + DI_ERROR(ret, NULL, NULL); } + return; } void dump() { - if ($self) { - fd_dict_dump($self); - } + fd_dict_dump($self); } PyObject * vendors_list() { uint32_t *list = NULL, *li; PyObject * ret; - if (!$self) { - PyErr_SetString(PyExc_SyntaxError,"dict_object cannot be created directly. Use fd_dict_new."); - return NULL; - } + 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 { @@ -196,34 +286,80 @@ %extend dict_object { dict_object() { - fd_log_debug("Error: dict_object cannot be created directly. Use fd_dict_new\n"); - PyErr_SetString(PyExc_SyntaxError,"dict_object cannot be created directly. Use fd_dict_new."); + DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be created directly. Use fd_dict_new()."); return NULL; } ~dict_object() { - fd_log_debug("Error: dict_object cannot be destroyed directly. Destroy the parent dictionary.\n"); + DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be destroyed directly. Destroy the parent dictionary."); return; } void dump() { - if ($self) { - fd_dict_dump_object($self); + 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; } } -/* overload the search function to allow passing integers & string criteria directly */ -%rename(fd_dict_search) fd_dict_search_int; -%inline %{ -int fd_dict_search_int ( struct dictionary * dict, enum dict_object_type type, int criteria, int what_by_val, struct dict_object ** result, int retval ) { - return fd_dict_search ( dict, type, criteria, &what_by_val, result, retval ); -} -%} -%rename(fd_dict_search) fd_dict_search_string; -%inline %{ -int fd_dict_search_string ( struct dictionary * dict, enum dict_object_type type, int criteria, char * what_by_string, struct dict_object ** result, int retval ) { - return fd_dict_search ( dict, type, criteria, what_by_string, result, retval ); -} -%} /* The following wrapper leaks memory each time an union avp_value is assigned an octet string. TODO: fix this leak by better understanding SWIG... @@ -243,8 +379,7 @@ /* 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) { - fd_log_debug("Out of memory!\n"); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + DI_ERROR_MALLOC; return; } memcpy($self->os.data, STRING, LENGTH); @@ -254,8 +389,7 @@ /* 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) { - fd_log_debug("Out of memory!\n"); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + DI_ERROR_MALLOC; return; } memcpy($self->os.data, os->data, os->len); @@ -265,33 +399,33 @@ %extend avp_value_os { void dump() { - if ($self) { - %#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 ? "..." : ""); - } + %#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 *********/ %{ -/* At the moment, only 1 callback is supported... */ +/* 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; } %} @@ -301,47 +435,39 @@ %extend session_handler { session_handler() { - fd_log_debug("Error: a cleanup callback parameter is required.\n"); - PyErr_SetString(PyExc_SyntaxError,"Error: a cleanup callback parameter is required.\n"); + DI_ERROR(EINVAL, PyExc_SyntaxError, "a cleanup callback parameter is required."); return NULL; } - session_handler(PyObject * PyCleanupCb) { + session_handler(PyObject * PyCb) { struct session_handler * hdl = NULL; int ret; if (py_cleanup_cb) { - fd_log_debug("dbg_interactive supports only 1 session handler in python at the moment\n"); - PyErr_SetString(PyExc_SyntaxError,"dbg_interactive supports only 1 session handler in python at the moment\n"); + DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one session handler at a time is supported at the moment in this extension\n."); return NULL; } - if (!PyCallable_Check(PyCleanupCb)) { - PyErr_SetString(PyExc_TypeError, "Need a callable object!"); - return NULL; - } - py_cleanup_cb = PyCleanupCb; + py_cleanup_cb = PyCb; Py_XINCREF(py_cleanup_cb); ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback ); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + DI_ERROR(ret, NULL, NULL); return NULL; } return hdl; } ~session_handler() { - if (self) { - struct session_handler * hdl = self; - int ret = fd_sess_handler_destroy(&hdl); - if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - } - return; + 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() { - if ($self) { - fd_sess_dump_hdl(0, $self); - } + fd_sess_dump_hdl(0, $self); } } @@ -355,8 +481,7 @@ struct session * s = NULL; ret = fd_sess_new(&s, fd_g_config->cnf_diamid, "dbg_interactive", sizeof("dbg_interactive")); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + DI_ERROR(ret, NULL, NULL); return NULL; } return s; @@ -366,8 +491,7 @@ struct session * s = NULL; ret = fd_sess_new(&s, diamid, STRING, LENGTH); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + DI_ERROR(ret, NULL, NULL); return NULL; } return s; @@ -377,37 +501,34 @@ struct session * s = NULL; ret = fd_sess_fromsid(STRING, LENGTH, &s, &n); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + 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() { - if (self) { - struct session * s = self; - int ret = fd_sess_reclaim(&s); - if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - } - return; + 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; - if (!$self) - return NULL; ret = fd_sess_getsid( $self, &sid); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Problem..."); + DI_ERROR(ret, NULL, NULL); return NULL; } return sid; @@ -419,23 +540,19 @@ timeout.tv_sec += seconds; ret = fd_sess_settimeout( $self, &timeout ); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Problem..."); + DI_ERROR(ret, NULL, NULL); } } void dump() { - if ($self) { - fd_sess_dump(0, $self); - } + fd_sess_dump(0, $self); } void store(struct session_handler * handler, PyObject * state) { int ret; void * store = state; - Py_INCREF(state); + Py_XINCREF(state); ret = fd_sess_state_store_internal(handler, $self, (void *) &store); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Problem..."); + DI_ERROR(ret, NULL, NULL); } } PyObject * retrieve(struct session_handler * handler) { @@ -443,21 +560,161 @@ PyObject * state = NULL; ret = fd_sess_state_retrieve_internal(handler, $self, (void *) &state); if (ret != 0) { - fd_log_debug("Error: %s\n", strerror(ret)); - PyErr_SetString(PyExc_MemoryError,"Problem..."); + DI_ERROR(ret, NULL, NULL); + return NULL; } if (state == NULL) { + Py_INCREF(Py_None); return Py_None; } - Py_DECREF(state); return state; } } +/****** 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_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 %{