Mercurial > hg > freeDiameter
changeset 635:134e4fb9eef5
Continued work on python interface
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Tue, 14 Dec 2010 17:34:46 +0900 |
parents | 49ff9df2d008 |
children | c23ca590fa57 |
files | doc/dbg_interactive.py.sample extensions/dbg_interactive/dbg_interactive.i |
diffstat | 2 files changed, 340 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/dbg_interactive.py.sample Tue Dec 14 14:01:26 2010 +0900 +++ b/doc/dbg_interactive.py.sample Tue Dec 14 17:34:46 2010 +0900 @@ -86,7 +86,7 @@ ############# Dictionary ############ -# Create a dedicated dictionary for our tests +##### Create a dedicated dictionary for our tests d = dictionary() d.dump() @@ -123,57 +123,131 @@ fd_dict_new(d, DICT_ENUMVAL, c, my_type_int) c.enum_name = "A_BUFFER_CONSTANT" -osval = avp_value_os("This is a very long AVP value that we prefer to represent as a constant") -c.enum_value.os = osval +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) +del c + +# AVP +a = dict_avp_data() +a.avp_code = 234 +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) + +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) +del a + +# Command +c = dict_cmd_data() +c.cmd_code = 345 +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) +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) +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 + +d.dump() del d -c = dict_enumval_data() -c.enum_value.os = "coucou" -c.enum_value.os.dump() +####### Now play with the "real" dictionary gdict = cvar.fd_g_config.cnf_dict -r, obj = fd_dict_search ( gdict, DICT_APPLICATION, APPLICATION_BY_ID, 3, -1 ) + +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, obj = fd_dict_search( gdict, DICT_AVP, AVP_BY_NAME, "Origin-Host", -1) -obj.dump() +r, errcmd = fd_dict_get_error_cmd( gdict ) + +data = dict_avp_data() +fd_dict_getval(avp, data) +print data.avp_code +del data + +r, t = fd_dict_gettype(appl) +del t -t = new_dict_object_type_ptr() -fd_dict_gettype(obj, t) -dict_object_type_ptr_dump(t) -delete_dict_object_type_ptr(t) -objdata = new_dict_application_data() -fd_dict_getval(obj, objdata) -dict_application_data_application_name_get(objdata) -delete_dict_application_data(objdata) +r, dict = fd_dict_getdict(avp) +del dict + + + +############# Sessions ############ -vd = new_dict_vendor_data() -dict_vendor_data_vendor_id_set(vd, 123) -dict_vendor_data_vendor_name_set(vd, "my test vendor") -pobj = new_dict_object_pptr() -fd_dict_new ( gdict, DICT_VENDOR, vd, None, pobj) -delete_dict_vendor_data(vd) -obj = dict_object_pptr_value(pobj) -delete_dict_object_pptr(pobj) -fd_dict_dump_object(obj) +# handler +def my_cleanup(state,sid): + print "Cleaning up python state for session:", sid + print "Received state:", state + +hdl = session_handler(my_cleanup) +hdl.dump() +del hdl + +hdl = session_handler(my_cleanup) -# Sessions -pmyhdl = new_session_handler_pptr() -fd_sess_handler_create_internal(pmyhdl, None) -### Have to work on this one, a cleanup handler is actually required. -### How to define the handler in python ? -myhdl = session_handler_pptr_value(pmyhdl) -delete_session_handler_pptr(pmyhdl) +# 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) + + -psess = new_session_pptr() -fd_sess_new (psess, fd_config_cnf_diamid_get(cvar.fd_g_config), "dbg_interactive", 0) -sess = session_pptr_value(psess) -fd_sess_dump(0, sess) -fd_sess_destroy(psess) -delete_session_pptr(psess) +## TODO : debug the following (segfault) + +def my_cleanup(state,sid): + print "Cleaning up python state for session:", sid + print "Received state:", state +hdl = session_handler(my_cleanup) +s4 = session("host.id", "opt.part") +mystate = [ 34, "clah", [ 32, 12 ] ] +s4.store(hdl, mystate) +del hdl + + + + + + + + +######################### old stuff (need update) ###################### # Routing data prtd = new_rt_data_pptr()
--- a/extensions/dbg_interactive/dbg_interactive.i Tue Dec 14 14:01:26 2010 +0900 +++ b/extensions/dbg_interactive/dbg_interactive.i Tue Dec 14 17:34:46 2010 +0900 @@ -50,9 +50,20 @@ %include <cstring.i> %include <typemaps.i> -/* Some functions are not available through the wrapper */ +/* Some functions are not available through the wrapper, or accessed differently */ %ignore fd_lib_init; %ignore fd_lib_fini; +%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; + /* Inline functions seems to give problems to SWIG -- just remove the inline definition */ %define __inline__ @@ -79,9 +90,13 @@ %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 }; /********************************************************* Now, create wrappers for (almost) all objects from fD API @@ -210,12 +225,45 @@ } %} +/* 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) { + fd_log_debug("Out of memory!\n"); + PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + 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) { + fd_log_debug("Out of memory!\n"); + PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + return; + } + memcpy($self->os.data, os->data, os->len); + $self->os.len = os->len; + } +}; %extend avp_value_os { - ~avp_value_os() { - if (self) - free(self->data); - } void dump() { if ($self) { %#define LEN_MAX 20 @@ -230,30 +278,186 @@ } } -%extend avp_value { - void os_set(char *STRING, size_t LENGTH) { - free($self->os.data); - $self->os.data = malloc(LENGTH); - if (!$self->os.data) { - fd_log_debug("Out of memory!\n"); +/****** SESSIONS *********/ + +%{ +/* At the moment, only 1 callback is supported... */ +static PyObject * py_cleanup_cb = NULL; +static void call_the_python_cleanup_callback(session_state * state, char * sid) { + PyObject *result; + if (!py_cleanup_cb) + return; + + /* Call the function */ + result = PyEval_CallFunction(py_cleanup_cb, "(Os)", state, sid); + + Py_XDECREF(result); + return; +} +%} + +struct session_handler { +}; + +%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"); + return NULL; + } + session_handler(PyObject * PyCleanupCb) { + 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"); + return NULL; + } + if (!PyCallable_Check(PyCleanupCb)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return NULL; + } + py_cleanup_cb = PyCleanupCb; + 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"); + 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; } - memcpy($self->os.data, STRING, LENGTH); - $self->os.len = LENGTH; + } + void dump() { + if ($self) { + 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) { + fd_log_debug("Error: %s\n", strerror(ret)); + PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + return NULL; + } + return s; } - void os_set(avp_value_os * os) { - free($self->os.data); - $self->os.data = malloc(os->len); - if (!$self->os.data) { - fd_log_debug("Out of memory!\n"); + 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) { + fd_log_debug("Error: %s\n", strerror(ret)); + PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + 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) { + fd_log_debug("Error: %s\n", strerror(ret)); PyErr_SetString(PyExc_MemoryError,"Not enough memory"); + return NULL; + } + /* When defining n as OUTPUT parameter, we get something strange... Use fd_sess_fromsid if you need it */ + if (n) { + fd_log_debug("A new session has been created\n"); + } else { + fd_log_debug("A session with same id already existed\n"); + } + 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; } - memcpy($self->os.data, os->data, os->len); - $self->os.len = os->len; + } + 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..."); + 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) { + fd_log_debug("Error: %s\n", strerror(ret)); + PyErr_SetString(PyExc_MemoryError,"Problem..."); + } + } + void dump() { + if ($self) { + fd_sess_dump(0, $self); + } } -}; + void store(struct session_handler * handler, PyObject * state) { + int ret; + void * store = state; + Py_INCREF(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..."); + } + } + PyObject * retrieve(struct session_handler * handler) { + int ret; + 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..."); + } + if (state == NULL) { + return Py_None; + } + Py_DECREF(state); + return state; + } +} + + + +/****** MESSAGES *********/ + %cstring_output_allocate_size(char ** swig_buffer, size_t * swig_len, free(*$1)) %inline %{