Commit bcdce685 authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Continued work on python interface

parent 2892ba85
......@@ -86,7 +86,7 @@ hex(fd_hash("hello world")) # A typemap is applied to accept binary data
############# Dictionary ############
# Create a dedicated dictionary for our tests
##### Create a dedicated dictionary for our tests
d = dictionary()
d.dump()
......@@ -123,57 +123,131 @@ c.enum_value.i32 = 3
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, obj = fd_dict_search( gdict, DICT_AVP, AVP_BY_NAME, "Origin-Host", -1)
r, avp = 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
r, dict = fd_dict_getdict(avp)
del dict
############# Sessions ############
# 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)
# 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)
## 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
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)
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)
# 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)
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)
######################### old stuff (need update) ######################
# Routing data
prtd = new_rt_data_pptr()
......
......@@ -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 @@ int fd_dict_search_string ( struct dictionary * dict, enum dict_object_type type
}
%}
/* 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 @@ int fd_dict_search_string ( struct dictionary * dict, enum dict_object_type type
}
}
%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 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");
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;
}
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 %{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment