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

Finally got the proxy aka shadow class to work

parent 260872a2
......@@ -29,8 +29,8 @@ cvar.fd_debug_one_function = "gc_th_fct"
# Print messages to freeDiameter's debug facility
fd_log_debug("3 + 4 = %d\n", 7)
# Hum... Currently I get "3 + 4 = 0" output... need some fix...
fd_log_debug("3 + 4 = %d\n" % (7))
# See SWIG documentation about varargs functions for more information
# SWIG deals with structures as follow:
......@@ -41,6 +41,12 @@ fd_log_debug("3 + 4 = %d\n", 7)
# foo_a_set(s, 2) --> s->a = 2
# foo_a_get(s) --> returns s->a value
# delete_foo(s) --> free(s)
#
# In addition, thanks to proxy (aka shadow) class, we can also do:
# s = foo()
# s.a = 2
# s.a
# del s
# Display the local Diameter Identity:
......@@ -62,6 +68,7 @@ myconfig = peer_info_config_get(mypeer)
mypicflag = peer_info_config_pic_flags_get(myconfig)
peer_info_config_pic_flags_pro4_set(mypicflag, 1) # 1 for TCP
fd_peer_add(mypeer, "python", None, None)
delete_peer_info(mypeer)
# Lists
......@@ -77,17 +84,100 @@ delete_fd_list(l1)
# Dictionary
gdict = fd_config_cnf_dict_get(cvar.fd_g_config)
id = new_int_ptr()
int_ptr_assign(id, 3)
res = new_dict_object_ptr()
err = fd_dict_search ( gdict, DICT_APPLICATION, APPLICATION_BY_ID, id, res, -1 )
obj = dict_object_ptr_value(res)
pobj = new_dict_object_pptr()
fd_dict_search ( gdict, DICT_APPLICATION, APPLICATION_BY_ID, id, pobj, -1 )
delete_int_ptr(id)
obj = dict_object_pptr_value(pobj)
delete_dict_object_pptr(pobj)
t = new_dict_object_type_ptr()
err = fd_dict_gettype(obj, t)
fd_dict_gettype(obj, t)
dict_object_type_ptr_dump(t)
v = new_dict_application_data()
err = fd_dict_getval(obj, v)
dict_application_data_application_name_get(v)
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)
# 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
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)
......@@ -10,19 +10,47 @@ INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
# Wrapper to fD in python
FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})
SET(CMAKE_SWIG_FLAGS "")
SET(CMAKE_SWIG_FLAGS -castmode -threads)
# Add the dependencies for re-swig-ing the file
SET(SWIG_MODULE_diwrap_EXTRA_DEPS
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)
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
SWIG_MODULE_INITIALIZE(fDpy python)
SWIG_ADD_SOURCE_TO_MODULE(fDpy swig_generated_sources "dbg_interactive.i")
# In order to avoid shipping the python file that contains the shadow class definitions,
# we transform this file in a C-style string and compile it within our software.
# We use for this purpose xxd tool provided with vim package.
FIND_PROGRAM(XXD_EXECUTABLE xxd)
# To avoid the dependency, simply compile it if not provided
if (NOT XXD_EXECUTABLE)
SET_SOURCE_FILES_PROPERTIES(helper/xxd.c PROPERTIES COMPILE_DEFINITIONS UNIX)
ADD_EXECUTABLE(xxd helper/xxd.c)
SET(XXD_EXECUTABLE xxd)
endif (NOT XXD_EXECUTABLE)
# And now the magic command
ADD_CUSTOM_COMMAND(
OUTPUT "fDpy-inc.c"
COMMAND "${XXD_EXECUTABLE}"
ARGS "-i"
"fDpy.py"
"fDpy-inc.c"
MAIN_DEPENDENCY "${swig_extra_generated_files}"
COMMENT "Converting swig proxy class to C string")
# Ensure that the generated source files are removed
GET_DIRECTORY_PROPERTY(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
SET_DIRECTORY_PROPERTIES(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources};fDpy-inc.c")
# We create the module even if we don't use it, so that intermediate values are defined (OK, this is stupid...)
SWIG_ADD_MODULE(diwrap python diwrap.i)
#####
# Extension that embeds the python interpreter
FD_ADD_EXTENSION(dbg_interactive dbg_interactive.c ${swig_generated_sources} ${swig_other_sources})
FD_ADD_EXTENSION(dbg_interactive dbg_interactive.c ${swig_generated_sources} fDpy-inc.c)
TARGET_LINK_LIBRARIES(dbg_interactive ${PYTHON_LIBRARIES})
......@@ -37,7 +37,17 @@
#include <freeDiameter/extension.h>
/* wrapper generated by SWIG */
extern void init_diwrap(void);
#if PY_VERSION_HEX >= 0x03000000
extern void PyInit__fDpy(void);
#define WRAPPER_INIT PyInit__fDpy()
#else /* PY_VERSION_HEX */
extern void init_fDpy(void);
#define WRAPPER_INIT init_fDpy()
#endif /* PY_VERSION_HEX */
/* The string created in the shadow proxy C string file */
extern unsigned char fDpy_py[];
extern unsigned int fDpy_py_len;
/* Run an interactive interpreter in a separate thread */
static pthread_t pyinterp = (pthread_t)NULL;
......@@ -62,18 +72,34 @@ static void * myinterp (void * arg)
/* Register the callbacks to the daemon */
static int di_main(char * conffile)
{
char * shadow_hlp = NULL;
int mustfree = 0;
TRACE_ENTRY("%p", conffile);
Py_Initialize();
#if PY_VERSION_HEX >= 0x03000000
PyInit__diwrap();
#else /* PY_VERSION_HEX */
init_diwrap();
#endif /* PY_VERSION_HEX */
WRAPPER_INIT;
/* Small hack to avoid duplicating the string, we replace the last char by a \0.
It works if the python file is terminated with several \n */
if ( (fDpy_py[fDpy_py_len - 2] == '\n')
&& (fDpy_py[fDpy_py_len - 1] == '\n')) {
fDpy_py[fDpy_py_len - 1] = '\0';
shadow_hlp = (char *)&fDpy_py[0];
} else {
CHECK_MALLOC(shadow_hlp = malloc(fDpy_py_len + 1));
memcpy(shadow_hlp, fDpy_py, fDpy_py_len);
shadow_hlp[fDpy_py_len] = '\0';
mustfree=1;
}
PyRun_SimpleString("__file__ = \"\"\n");
PyRun_SimpleString(shadow_hlp);
if (mustfree)
free(shadow_hlp);
/* In future version, it might be better to use the diwrap.py file generated by SWIG here to get the proxy classes definitions */
PyRun_SimpleString("from _diwrap import *\n");
if (TRACE_BOOL(INFO)) {
PyRun_SimpleString("print \"[dbg_interactive] \",FD_PROJECT_NAME,FD_PROJECT_VERSION_MAJOR,FD_PROJECT_VERSION_MINOR,FD_PROJECT_VERSION_REV\n");
}
......
/* This interface file is processed by SWIG to create a python wrapper interface to freeDiameter framework. */
%module diwrap
%module fDpy
%begin %{
/*********************************************************************************************************
* Software License Agreement (BSD License) *
......@@ -37,13 +37,8 @@
*********************************************************************************************************/
%}
%init %{
/* TODO: How to load the proxy classes here? */
%}
%{
/* Define types etc. */
/* This text is included in the generated wrapper verbatim */
#define SWIG
#include <freeDiameter/extension.h>
%}
......@@ -52,6 +47,8 @@
/* Include standard types & functions used in freeDiameter headers */
%include <stdint.i>
%include <cpointer.i>
%include <cdata.i>
%include <cstring.i>
%include <typemaps.i>
/* Some functions are not available through the wrapper */
......@@ -79,7 +76,6 @@ extern int fd_dict_getval ( struct dict_object * object, void * INOUT);
extern int fd_dict_getdict ( struct dict_object * object, struct dictionary ** OUTPUT);
*/
/* Retrieve the compile-time definitions of freeDiameter */
%include "freeDiameter/freeDiameter-host.h"
%include "freeDiameter/libfreeDiameter.h"
......@@ -87,12 +83,26 @@ extern int fd_dict_getdict ( struct dict_object * object, struct dictionary ** O
/* Some pointer types that are useful */
%pointer_class(int, int_ptr);
%pointer_class(enum dict_object_type, dict_object_type_ptr);
%pointer_functions(struct dict_object *, dict_object_ptr);
%pointer_functions(struct session *, session_ptr);
%pointer_functions(int, int_ptr);
%pointer_functions(uint8_t *, uint8_t_pptr);
%pointer_cast(char *, void *, char_to_void);
%pointer_functions(struct fd_list *, fd_list_pptr);
%pointer_functions(enum dict_object_type, dict_object_type_ptr);
%pointer_functions(struct dict_object *, dict_object_pptr);
%pointer_functions(struct session *, session_pptr);
%pointer_functions(struct session_handler *, session_handler_pptr);
%pointer_functions(session_state *, session_state_pptr);
%pointer_functions(struct rt_data *, rt_data_pptr);
%pointer_cast(struct fd_list *, struct rtd_candidate *, fd_list_to_rtd_candidate);
%pointer_functions(struct msg *, msg_pptr);
%pointer_functions(struct msg_hdr *, msg_hdr_pptr);
%pointer_functions(struct avp *, avp_pptr);
%pointer_functions(struct avp_hdr *, avp_hdr_pptr);
/* Extend some structures for usability/debug in python */
......@@ -102,6 +112,7 @@ extern int fd_dict_getdict ( struct dict_object * object, struct dictionary ** O
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");
return NULL;
}
fd_list_init(li, o);
......@@ -120,31 +131,62 @@ extern int fd_dict_getdict ( struct dict_object * object, struct dictionary ** O
}
};
%extend dict_object_type_ptr {
void dump() {
%#define CASE_STR(x) case x: fd_log_debug(#x "\n"); break;
switch (*$self) {
CASE_STR(DICT_VENDOR)
CASE_STR(DICT_APPLICATION)
CASE_STR(DICT_TYPE)
CASE_STR(DICT_ENUMVAL)
CASE_STR(DICT_AVP)
CASE_STR(DICT_COMMAND)
CASE_STR(DICT_RULE)
default: fd_log_debug("Invalid value (%d)", *$self); break;
}
%inline %{
void dict_object_type_ptr_dump(enum dict_object_type * t) {
#define CASE_STR(x) case x: fd_log_debug(#x "\n"); break;
switch (*t) {
CASE_STR(DICT_VENDOR)
CASE_STR(DICT_APPLICATION)
CASE_STR(DICT_TYPE)
CASE_STR(DICT_ENUMVAL)
CASE_STR(DICT_AVP)
CASE_STR(DICT_COMMAND)
CASE_STR(DICT_RULE)
default:
fd_log_debug("Invalid value (%d)", *t);
PyErr_SetString(PyExc_IndexError,"Invalid dictionary type object");
}
}
%}
%inline %{
void session_ptr_showsid(struct session * s) {
char * sid;
int ret = fd_sess_getsid ( s, &sid );
if (ret != 0) {
fd_log_debug("Error %d\n", ret);
/* throw an exception in SWIG? */
return;
%extend avp_value_os {
void fromstr(char * string) {
if ($self->data) free($self->data);
$self->data = (uint8_t *)strdup(string);
if (!$self->data) {
fd_log_debug("Out of memory!\n");
PyErr_SetString(PyExc_MemoryError,"Not enough memory");
$self->len = 0;
return;
}
$self->len = strlen(string);
}
%newobject as_str;
char * tostr() {
char * r;
if ($self->len == 0)
return NULL;
r = malloc($self->len + 1);
if (r) {
strncpy(r, (char *)$self->data, $self->len + 1);
} else {
fd_log_debug("Out of memory!\n");
PyErr_SetString(PyExc_MemoryError,"Not enough memory");
}
return r;
}
fd_log_debug("%s\n", sid);
};
%extend avp_value {
void os_set(void * os) {
memcpy(&$self->os, os, sizeof($self->os));
}
};
%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);
}
%}
%};
This diff is collapsed.
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