Navigation


Changeset 637:22e8fac3b2d6 in freeDiameter


Ignore:
Timestamp:
Dec 16, 2010, 6:56:41 PM (13 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Split interface file in modules

Files:
8 added
5 edited

Legend:

Unmodified
Added
Removed
  • doc/dbg_interactive.py.sample

    r636 r637  
    6666# Display the local Diameter Identity:
    6767print "Local Diameter Identity:", cvar.fd_g_config.cnf_diamid
    68 # Display realm, without using the low-level functions (skip proxy classe definitions):
     68
     69# Display realm, using the low-level functions (skip proxy classe definitions):
    6970print "Realm:", _fDpy.fd_config_cnf_diamrlm_get(_fDpy.cvar.fd_g_config)
    7071
     
    7273
    7374############# Lists ############
    74 l1 = fd_list()   # The creator has an implicit fd_list_init call
     75
     76# Note: we use different names from the C API here, for usability.
     77l1 = fd_list()   # Will be our sentinel
    7578l2 = fd_list()
    76 fd_list_insert_after(l1, l2)
     79l3 = fd_list()
     80l1.isempty()
     81l1.insert_next(l2)   # l1 -> l2
     82l1.isempty()
     83l1.insert_prev(l3)   # l1 -> l2 -> l3 (circular list)
    7784l1.dump()
    78 del l2           # The destructor has an implicit fd_list_unlink call
    79 l1.dump()
     85l3.detach()          # l1 -> l2
     86l4=fd_list()
     87l5=fd_list()
     88l3.insert_next(l4)   #   l3 -> l4
     89l3.insert_next(l5)   #   l3 -> l5 -> l4
     90l1.concat(l3)        # l1 -> l2 -> l5 -> l4
     91
     92elements = l1.enum_as()  # default: enumerates as fd_list. Warning: this a copy, changing the python list has no effect on the underlying list.
     93for li in elements:
     94  li.dump()
     95
     96del elements
     97del l2
     98del l3
     99del l4
     100del l5
     101l1.isempty() # The destructor has an implicit fd_list_unlink call
    80102del l1
    81103
     
    214236s2 = session("this.is.a.full.session.id")
    215237r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id")
    216 s4 = session("host.id", "opt.part")
     238s4 = session("host.id", "optional.part")
    217239s4.settimeout(30) # the python wrapper takes a number of seconds as parameter for simplicity
    218240s4.dump()
     
    241263
    242264list = rd.extract(-1)
    243 list[0].dump()
     265for c in list.enum_as("struct rtd_candidate *"):
     266  print "%s (%s): %s" % (c.diamid, c.realm, c.score)
     267
     268
     269
     270############# Messages, AVPs ############
     271
     272## AVP
     273
     274# Create empty (as for messages, pass None or a dictionary object as 1st param, and flags as optional 2nd param)
     275blank_avp = avp()
     276del blank_avp
     277
     278oh = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host"))                      # Octet String
     279vi = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Id"))                        # U32
     280vsai = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Specific-Application-Id")) # Grouped
     281
     282# Set values
     283val = avp_value()
     284val.u32 = 123
     285vi.setval(None)  # this cleans a previous value (not needed)
     286vi.setval(val)
     287val.os = "my.origin.host"
     288oh.setval(val)
     289vsai.add_child(vi) # call as add_child(vi, 1) to add the new AVP at the beginning, default is at the end
     290
     291
     292## Messages
     293
     294# Create empty
     295a_msg = msg()
     296a_msg.dump()
     297del a_msg
     298
     299# It is also possible to pass MSGFL_* flags in second parameter (ALLOC_ETEID is default)
     300msg_no_eid = msg(None, 0)
     301msg_no_eid.dump()
     302del msg_no_eid
     303
     304# Create from dictionary
     305dwr_dict = cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" )
     306dwr = msg(dwr_dict)
     307dwr.dump()
     308
     309# Create msg from a binary buffer (then you should call parse_dict and parse_rules methods)
     310dwr2 = msg("\x01\x00\x00\x14\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00\x1b\xf0\x00\x01")
     311
     312# Create answer from request (optional parameters: dictionary to use, and flags):
     313dwr3 = msg(cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" ))
     314dwa3 = dwr3.create_answer()
     315dwr3cpy = dwa3.get_query()
     316
     317
     318## Other functions with AVPs & messages
     319
     320# Add the AVPs in the message
     321dwr.add_child(oh)
     322oh.add_next(vsai)   # equivalent to add_child on the parent
     323
     324# Create a network byte buffer from the message
     325dwr.bufferize()
     326
     327# Get first child AVP (fast)
     328avp = dwr.first_child()
     329
     330# then:
     331avp = avp.get_next() # when last AVP, returns None
     332
     333
     334# Get all 1st level children (slower) -- warning, changes to the python list will not be reflected on the underlying message. read-only use.
     335dwr.children()
     336# example use:
     337for a in dwr.children()
     338  a.dump(0)  # 0 means: dump only this object, do not walk the tree
     339
     340
     341# Search the first AVP of a given type
     342oh_dict = cvar.fd_g_config.cnf_dict.search( DICT_AVP, AVP_BY_NAME, "Origin-Host")
     343oh = dwr.search( oh_dict )
     344
     345# After adding AVPs, the length in the message header is outdated, refresh as follow:
     346dwr.update_length()
     347
     348# Get dictionary model for a message or avp
     349dwr.model()
     350oh.model().dump()
     351
     352# Retrieve the header of messages & avp:
     353dwr_hdr = dwr.header()
     354dwr_hdr.msg_version
     355dwr_hdr.msg_hbhid
     356
     357oh_hdr = oh.header()
     358hex(oh_hdr.avp_flags)
     359oh_hdr.avp_vendor
     360oh_hdr.avp_value.os.dump()  # The initial avp value must be set with setval(), but then this accessor is allowed.
     361
     362# Get or set the routing data
     363rd = rt_data()
     364dwr.set_rtd(rd)
     365rd = dwr.get_rtd()
     366
     367# Test if message is routable
     368dwr.is_routable()
     369
     370# Which peer the message was received from (when received from network)
     371dwr.source()
     372
     373# The session corresponding to this message (returns None when no Session-Id AVP is included)
     374dwr.get_session()
     375
     376
     377# Parse a buffer
     378buf = "\x01\x00\x00@\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00N\x10\x00\x00\x00\x00\x01\x08@\x00\x00\x16my.origin.host\x00\x00\x00\x00\x01\x04@\x00\x00\x14\x00\x00\x01\n@\x00\x00\x0c\x00\x00\x00{"
     379mydwr = msg(buf)
     380# Resolve objects in the dictionary. Return value is None or a struct pei_error in case of problem.
     381mydwr.parse_dict()  # if not using the fD global dict, pass it as parameter
     382err = mydwr.parse_rules()
     383err.pei_errcode
     384
     385
     386# Grouped AVPs are browsed with same methods as messages:
     387gavp = dwr.children()[1]
     388gavp.first_child().dump()
     389gavp.children()
     390
     391
     392
     393
    244394
    245395
     
    249399
    250400######################### old stuff (need update) ######################
    251 
    252 
    253 
    254 # Messages
    255 gdict = fd_config_cnf_dict_get(cvar.fd_g_config)
    256 pobj = new_dict_object_pptr()
    257 fd_dict_search ( gdict, DICT_COMMAND, CMD_BY_NAME, char_to_void("Capabilities-Exchange-Request"), pobj, -1 )
    258 cerdict = dict_object_pptr_value(pobj)
    259 fd_dict_search ( gdict, DICT_AVP, AVP_BY_NAME, char_to_void("Origin-Host"), pobj, -1 )
    260 ohdict = dict_object_pptr_value(pobj)
    261 delete_dict_object_pptr(pobj)
    262 
    263 pmsg = new_msg_pptr()
    264 fd_msg_new(cerdict, MSGFL_ALLOC_ETEID, pmsg)
    265 msg = msg_pptr_value(pmsg);
    266 pavp = new_avp_pptr()
    267 fd_msg_avp_new(ohdict, 0, pavp)
    268 avp = avp_pptr_value(pavp);
    269 fd_msg_avp_add(msg, MSG_BRW_FIRST_CHILD, avp)
    270 fd_msg_dump_walk(0, msg)
    271 
    272 pahdr = new_avp_hdr_pptr()
    273 fd_msg_avp_hdr(avp, pahdr)
    274 ahdr = avp_hdr_pptr_value(pahdr)
    275 delete_avp_hdr_pptr(pahdr)
    276 avp_hdr_avp_code_get(ahdr)
    277 os = new_avp_value_os()
    278 avp_value_os_fromstr(os, fd_config_cnf_diamid_get(cvar.fd_g_config))
    279 val = new_avp_value()
    280 avp_value_os_set(val, os)
    281 delete_avp_value_os(os)
    282 fd_msg_avp_setvalue(avp, val)
    283 delete_avp_value(val)
    284 
    285 r,buf = fd_msg_bufferize_py(msg)
    286 fd_msg_free(msg)
    287 delete_avp_pptr(pavp)
    288401
    289402
  • extensions/dbg_interactive/CMakeLists.txt

    r625 r637  
    1717        ${CMAKE_BINARY_DIR}/include/freeDiameter/freeDiameter-host.h
    1818        ${CMAKE_SOURCE_DIR}/include/freeDiameter/libfreeDiameter.h
    19         ${CMAKE_SOURCE_DIR}/include/freeDiameter/freeDiameter.h)
     19        ${CMAKE_SOURCE_DIR}/include/freeDiameter/freeDiameter.h
     20        lists.i
     21        dictionary.i
     22        sessions.i
     23        routing.i
     24        messages.i
     25        dispatch.i
     26        queues.i
     27        peers.i
     28        )
    2029SET_SOURCE_FILES_PROPERTIES(dbg_interactive.i PROPERTIES SWIG_MODULE_NAME fDpy)
    2130
  • extensions/dbg_interactive/dbg_interactive.i

    r636 r637  
    4747/* Include standard types & functions used in freeDiameter headers */
    4848%include <stdint.i>
    49 %include <cdata.i>
     49//%include <cdata.i>
    5050%include <cstring.i>
    5151%include <typemaps.i>
    5252
    53 /* Some functions are not available through the wrapper */
    54 %ignore fd_lib_init;
    55 %ignore fd_lib_fini;
    56 /* -- the following functions are better accessed differently, but we leave their definitions just in case
    57 %ignore fd_dict_init;
    58 %ignore fd_dict_fini;
    59 %ignore fd_sess_handler_create_internal;
    60 %ignore fd_sess_handler_destroy;
    61 %ignore fd_sess_new;
    62 %ignore fd_sess_getsid;
    63 %ignore fd_sess_destroy;
    64 %ignore fd_sess_reclaim;
    65 %ignore fd_sess_state_store_internal;
    66 %ignore fd_sess_state_retrieve_internal;
    67 %ignore fd_rtd_init;
    68 %ignore fd_rtd_free;
    69 %ignore fd_rtd_candidate_add;
    70 %ignore fd_rtd_candidate_del;
    71 %ignore fd_rtd_candidate_extract;
    72 %ignore fd_rtd_error_add;
    73 */
    7453
    7554/* Inline functions seems to give problems to SWIG -- just remove the inline definition */
     
    7756%enddef
    7857
     58
    7959/* Make some global-variables read-only (mainly to avoid warnings) */
    8060%immutable fd_g_config;
    8161%immutable peer_state_str;
    8262
    83 
    84 /* Create a generic error handling mechanism so that functions can provoke an exception */
     63/*****************
     64 *  Exceptions  *
     65*****************/
    8566%{
    8667/* This is not thread-safe etc. but it should work /most of the time/. */
     
    128109 ***********************************/
    129110
    130 %apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) };
     111%apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; /* fd_hash */
    131112
     113/* Generic typemap for functions that create something */
    132114%typemap(in, numinputs=0,noblock=1) SWIGTYPE ** OUTPUT (void *temp = NULL) {
    133115        $1 = (void *)&temp;
     
    137119}
    138120
    139 %apply int * OUTPUT { enum dict_object_type * type };
    140 %apply (char *STRING, size_t LENGTH) { (char * sid, size_t len) };
    141 %apply SWIGTYPE ** OUTPUT { struct session ** session };
    142 %apply int * OUTPUT { int * new };
    143 
    144 /* Callbacks defined in python */
     121/* To allow passing callback functions defined in python */
    145122%typemap(in) PyObject *PyCb {
    146123        if (!PyCallable_Check($input)) {
     
    152129
    153130
    154 
    155131/*********************************************************
    156132 Now, create wrappers for (almost) all objects from fD API
     
    160136%include "freeDiameter/freeDiameter.h"
    161137
     138/* Most of the functions from the API are not directly usable "as is".
     139See the specific following files and the dbg_interactive.py.sample file
     140for more usable python-style versions.
     141*/
    162142
     143%include "lists.i"
     144%include "dictionary.i"
     145%include "sessions.i"
     146%include "routing.i"
     147%include "messages.i"
     148%include "dispatch.i"
     149%include "queues.i"
    163150
    164 /**********************************************************/
    165 /* The remaining of this file allows easier manipulation of
    166 the structures and functions of fD by providing wrapper-specific
    167 extensions to the freeDiameter API.
    168 
    169 /****** LISTS *********/
    170 
    171 %extend fd_list {
    172         /* allow a parameter in the constructor, and perform the fd_list_init operation */
    173         fd_list(void * o = NULL) {
    174                 struct fd_list * li;
    175                 li = (struct fd_list *) malloc(sizeof(struct fd_list));
    176                 if (!li) {
    177                         DI_ERROR_MALLOC;
    178                         return NULL;
    179                 }
    180                 fd_list_init(li, o);
    181                 return li;
    182         }
    183         /* Unlink before freeing */
    184         ~fd_list() {
    185                 fd_list_unlink($self);
    186                 free($self);
    187         }
    188         /* For debug, show the values of the list */
    189         void dump() {
    190                 fd_log_debug("list: %p\n", $self);
    191                 fd_log_debug("  - next: %p\n", $self->next);
    192                 fd_log_debug("  - prev: %p\n", $self->prev);
    193                 fd_log_debug("  - head: %p\n", $self->head);
    194                 fd_log_debug("  - o   : %p\n", $self->o);
    195         }
    196 };
    197 
    198 /****** DICTIONARY *********/
    199 
    200 struct dictionary {
    201 };
    202 
    203 %extend dictionary {
    204         dictionary() {
    205                 struct dictionary * r = NULL;
    206                 int ret = fd_dict_init(&r);
    207                 if (ret != 0) {
    208                         DI_ERROR(ret, NULL, NULL);
    209                         return NULL;
    210                 }
    211                 return r;
    212         }
    213         ~dictionary() {
    214                 struct dictionary *d = self;
    215                 int ret = fd_dict_fini(&d);
    216                 if (ret != 0) {
    217                         DI_ERROR(ret, NULL, NULL);
    218                 }
    219                 return;
    220         }
    221         void dump() {
    222                 fd_dict_dump($self);
    223         }
    224         PyObject * vendors_list() {
    225                 uint32_t *list = NULL, *li;
    226                 PyObject * ret;
    227                 SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    228                 ret = PyList_New(0);
    229                 list = fd_dict_get_vendorid_list($self);
    230                 for (li = list; *li != 0; li++) {
    231                         PyList_Append(ret, PyInt_FromLong((long)*li));
    232                 }
    233                 free(list);
    234                 SWIG_PYTHON_THREAD_END_BLOCK;
    235                 return ret;
    236         }
    237         struct dict_object * new_obj(enum dict_object_type type, void * data, struct dict_object * parent = NULL) {
    238                 struct dict_object * obj = NULL;
    239                 int ret = fd_dict_new($self, type, data, parent, &obj);
    240                 if (ret != 0) {
    241                         DI_ERROR(ret, NULL, NULL);
    242                         return NULL;
    243                 }
    244                 return obj;
    245         }
    246         struct dict_object * search(enum dict_object_type type, int criteria, int what_by_val) {
    247                 struct dict_object * obj = NULL;
    248                 int ret = fd_dict_search ( $self, type, criteria, &what_by_val, &obj, ENOENT );
    249                 if (ret != 0) {
    250                         DI_ERROR(ret, NULL, NULL);
    251                         return NULL;
    252                 }
    253                 return obj;
    254         }
    255         struct dict_object * search(enum dict_object_type type, int criteria, char * what_by_string) {
    256                 struct dict_object * obj = NULL;
    257                 int ret = fd_dict_search ( $self, type, criteria, what_by_string, &obj, ENOENT );
    258                 if (ret != 0) {
    259                         DI_ERROR(ret, NULL, NULL);
    260                         return NULL;
    261                 }
    262                 return obj;
    263         }
    264         struct dict_object * search(enum dict_object_type type, int criteria, void * what) {
    265                 struct dict_object * obj = NULL;
    266                 int ret = fd_dict_search ( $self, type, criteria, what, &obj, ENOENT );
    267                 if (ret != 0) {
    268                         DI_ERROR(ret, NULL, NULL);
    269                         return NULL;
    270                 }
    271                 return obj;
    272         }
    273         struct dict_object * error_cmd() {
    274                 struct dict_object * obj = NULL;
    275                 int ret = fd_dict_get_error_cmd ( $self, &obj );
    276                 if (ret != 0) {
    277                         DI_ERROR(ret, NULL, NULL);
    278                         return NULL;
    279                 }
    280                 return obj;
    281         }
    282 }
    283 
    284 struct dict_object {
    285 };
    286 
    287 %extend dict_object {
    288         dict_object() {
    289                 DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be created directly. Use fd_dict_new().");
    290                 return NULL;
    291         }
    292         ~dict_object() {
    293                 DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be destroyed directly. Destroy the parent dictionary.");
    294                 return;
    295         }
    296         void dump() {
    297                 fd_dict_dump_object($self);
    298         }
    299         enum dict_object_type gettype() {
    300                 enum dict_object_type t;
    301                 int ret = fd_dict_gettype ( $self, &t);
    302                 if (ret != 0) {
    303                         DI_ERROR(ret, NULL, NULL);
    304                         return 0;
    305                 }
    306                 return t;
    307         }
    308         struct dictionary * getdict() {
    309                 struct dictionary *d;
    310                 int ret = fd_dict_getdict ( $self, &d );
    311                 if (ret != 0) {
    312                         DI_ERROR(ret, NULL, NULL);
    313                         return NULL;
    314                 }
    315                 return d;
    316         }
    317         /* Since casting the pointer requires intelligence, we do it here instead of giving it to SWIG */
    318         PyObject * getval() {
    319                 /* first, get the type */
    320                 enum dict_object_type t;
    321                 int ret = fd_dict_gettype ( $self, &t);
    322                 if (ret != 0) {
    323                         DI_ERROR(ret, NULL, NULL);
    324                         return NULL;
    325                 }
    326                 switch (t) {
    327 %define %GETVAL_CASE(TYPE,STRUCT)
    328                         case TYPE: {
    329                                 PyObject * v = NULL;
    330                                 struct STRUCT * data = NULL;
    331                                 data = malloc(sizeof(struct STRUCT));
    332                                 if (!data) {
    333                                         DI_ERROR_MALLOC;
    334                                         return NULL;
    335                                 }
    336                                 ret = fd_dict_getval($self, data);
    337                                 if (ret != 0) {
    338                                         DI_ERROR(ret, NULL, NULL);
    339                                         free(data);
    340                                         return NULL;
    341                                 }
    342                                 SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    343                                 v = SWIG_NewPointerObj((void *)data, SWIGTYPE_p_##STRUCT, SWIG_POINTER_OWN );
    344                                 Py_XINCREF(v);
    345                                 SWIG_PYTHON_THREAD_END_BLOCK;
    346                                 return v;
    347                         } break
    348 %enddef
    349                         %GETVAL_CASE( DICT_VENDOR,      dict_vendor_data );
    350                         %GETVAL_CASE( DICT_APPLICATION, dict_application_data );
    351                         %GETVAL_CASE( DICT_TYPE,        dict_type_data );
    352                         %GETVAL_CASE( DICT_ENUMVAL,     dict_enumval_data );
    353                         %GETVAL_CASE( DICT_AVP,         dict_avp_data );
    354                         %GETVAL_CASE( DICT_COMMAND,     dict_cmd_data );
    355                         %GETVAL_CASE( DICT_RULE,        dict_rule_data );
    356                         default:
    357                                 DI_ERROR(EINVAL, PyExc_SystemError, "Internal error: Got invalid object type");
    358                 }
    359                 return NULL;
    360         }
    361 }
    362 
    363 
    364 /* The following wrapper leaks memory each time an union avp_value is assigned an octet string.
    365  TODO: fix this leak by better understanding SWIG...
    366    -- the alternative is to uncomment the "free" statements bellow, but then it is easy to
    367    create a segmentation fault by assigning first an integer, then an octetstring.
    368  */
    369 %extend avp_value {
    370         /* The following hack in the proxy file allows assigning the octet string directly like this:
    371         avp_value.os = "blabla"
    372         */
    373         %pythoncode
    374         {
    375     __swig_setmethods__["os"] = _fDpy.avp_value_os_set
    376     if _newclass:os = _swig_property(_fDpy.avp_value_os_get, _fDpy.avp_value_os_set)
    377         }
    378         void os_set(char *STRING, size_t LENGTH) {
    379                 /* free($self->os.data);  -- do not free, in case the previous value was not an OS */
    380                 $self->os.data = malloc(LENGTH);
    381                 if (!$self->os.data) {
    382                         DI_ERROR_MALLOC;
    383                         return;
    384                 }
    385                 memcpy($self->os.data, STRING, LENGTH);
    386                 $self->os.len = LENGTH;
    387         }
    388         void os_set(avp_value_os * os) {
    389                 /* free($self->os.data);  -- do not free, in case the previous value was not an OS */
    390                 $self->os.data = malloc(os->len);
    391                 if (!$self->os.data) {
    392                         DI_ERROR_MALLOC;
    393                         return;
    394                 }
    395                 memcpy($self->os.data, os->data, os->len);
    396                 $self->os.len = os->len;
    397         }
    398 };
    399 
    400 %extend avp_value_os {
    401         void dump() {
    402                 %#define LEN_MAX 20
    403                 int i, n=LEN_MAX;
    404                 if ($self->len < LEN_MAX)
    405                         n = $self->len;
    406                 fd_log_debug("l:%u, v:[", $self->len);
    407                 for (i=0; i < n; i++)
    408                         fd_log_debug("%02.2X", $self->data[i]);
    409                 fd_log_debug("] '%.*s%s'\n", n, $self->data, n == LEN_MAX ? "..." : "");
    410         }
    411 }
    412 
    413 /****** SESSIONS *********/
    414 
    415 %{
    416 /* store the python callback function here */
    417 static PyObject * py_cleanup_cb = NULL;
    418 /* call it (might be called from a different thread than the interpreter, when session times out) */
    419 static void call_the_python_cleanup_callback(session_state * state, char * sid) {
    420         PyObject *result;
    421         if (!py_cleanup_cb)
    422                 return;
    423        
    424         /* Call the function */
    425         SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    426         result = PyEval_CallFunction(py_cleanup_cb, "(Os)", state, sid);
    427         Py_XDECREF(result);
    428         SWIG_PYTHON_THREAD_END_BLOCK;
    429         return;
    430 }
    431 %}
    432 
    433 struct session_handler {
    434 };
    435 
    436 %extend session_handler {
    437         session_handler() {
    438                 DI_ERROR(EINVAL, PyExc_SyntaxError, "a cleanup callback parameter is required.");
    439                 return NULL;
    440         }
    441         session_handler(PyObject * PyCb) {
    442                 struct session_handler * hdl = NULL;
    443                 int ret;
    444                 if (py_cleanup_cb) {
    445                         DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one session handler at a time is supported at the moment in this extension\n.");
    446                         return NULL;
    447                 }
    448                 py_cleanup_cb = PyCb;
    449                 Py_XINCREF(py_cleanup_cb);
    450                
    451                 ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback );
    452                 if (ret != 0) {
    453                         DI_ERROR(ret, NULL, NULL);
    454                         return NULL;
    455                 }
    456                 return hdl;
    457         }
    458         ~session_handler() {
    459                 struct session_handler * hdl = self;
    460                 int ret = fd_sess_handler_destroy(&hdl);
    461                 if (ret != 0) {
    462                         DI_ERROR(ret, NULL, NULL);
    463                 }
    464                 /* Now free the callback */
    465                 Py_XDECREF(py_cleanup_cb);
    466                 py_cleanup_cb = NULL;
    467                 return;
    468         }
    469         void dump() {
    470                 fd_sess_dump_hdl(0, $self);
    471         }
    472 }
    473 
    474 struct session {
    475 };
    476 
    477 %extend session {
    478         /* The first two versions create a new session string. The third one allow to use an existing string. */
    479         session() {
    480                 int ret;
    481                 struct session * s = NULL;
    482                 ret = fd_sess_new(&s, fd_g_config->cnf_diamid, "dbg_interactive", sizeof("dbg_interactive"));
    483                 if (ret != 0) {
    484                         DI_ERROR(ret, NULL, NULL);
    485                         return NULL;
    486                 }
    487                 return s;
    488         }
    489         session(char * diamid, char * STRING, size_t LENGTH) {
    490                 int ret;
    491                 struct session * s = NULL;
    492                 ret = fd_sess_new(&s, diamid, STRING, LENGTH);
    493                 if (ret != 0) {
    494                         DI_ERROR(ret, NULL, NULL);
    495                         return NULL;
    496                 }
    497                 return s;
    498         }
    499         session(char * STRING, size_t LENGTH) {
    500                 int ret, n;
    501                 struct session * s = NULL;
    502                 ret = fd_sess_fromsid(STRING, LENGTH, &s, &n);
    503                 if (ret != 0) {
    504                         DI_ERROR(ret, NULL, NULL);
    505                         return NULL;
    506                 }
    507                 /* When defining n as OUTPUT parameter, we get something strange... Use fd_sess_fromsid if you need it */
    508                 #if 0
    509                 if (n) {
    510                         fd_log_debug("A new session has been created\n");
    511                 } else {
    512                         fd_log_debug("A session with same id already existed\n");
    513                 }
    514                 #endif /* 0 */
    515                
    516                 return s;
    517         }
    518         ~session() {
    519                 struct session * s = self;
    520                 int ret = fd_sess_reclaim(&s);
    521                 if (ret != 0) {
    522                         DI_ERROR(ret, NULL, NULL);
    523                 }
    524                 return;
    525         }
    526         char * getsid() {
    527                 int ret;
    528                 char * sid = NULL;
    529                 ret = fd_sess_getsid( $self, &sid);
    530                 if (ret != 0) {
    531                         DI_ERROR(ret, NULL, NULL);
    532                         return NULL;
    533                 }
    534                 return sid;
    535         }
    536         void settimeout(long seconds) {
    537                 struct timespec timeout;
    538                 int ret;
    539                 clock_gettime(CLOCK_REALTIME, &timeout);
    540                 timeout.tv_sec += seconds;
    541                 ret = fd_sess_settimeout( $self, &timeout );
    542                 if (ret != 0) {
    543                         DI_ERROR(ret, NULL, NULL);
    544                 }
    545         }
    546         void dump() {
    547                 fd_sess_dump(0, $self);
    548         }
    549         void store(struct session_handler * handler, PyObject * state) {
    550                 int ret;
    551                 void * store = state;
    552                 Py_XINCREF(state);
    553                 ret = fd_sess_state_store_internal(handler, $self, (void *) &store);
    554                 if (ret != 0) {
    555                         DI_ERROR(ret, NULL, NULL);
    556                 }
    557         }
    558         PyObject *  retrieve(struct session_handler * handler) {
    559                 int ret;
    560                 PyObject * state = NULL;
    561                 ret = fd_sess_state_retrieve_internal(handler, $self, (void *) &state);
    562                 if (ret != 0) {
    563                         DI_ERROR(ret, NULL, NULL);
    564                         return NULL;
    565                 }
    566                 if (state == NULL) {
    567                         Py_INCREF(Py_None);
    568                         return Py_None;
    569                 }
    570                 return state;
    571         }
    572 }       
    573 
    574 /****** ROUTING *********/
    575 
    576 struct rt_data {
    577 };
    578 
    579 %extend rt_data {
    580         rt_data() {
    581                 struct rt_data * r = NULL;
    582                 int ret = fd_rtd_init(&r);
    583                 if (ret != 0) {
    584                         DI_ERROR(ret, NULL, NULL);
    585                         return NULL;
    586                 }
    587                 return r;
    588         }
    589         ~rt_data() {
    590                 struct rt_data *r = self;
    591                 fd_rtd_free(&r);
    592         }
    593         void add(char * peerid, char * realm) {
    594                 int ret = fd_rtd_candidate_add($self, peerid, realm);
    595                 if (ret != 0) {
    596                         DI_ERROR(ret, NULL, NULL);
    597                 }
    598         }
    599         void remove(char * STRING, size_t LENGTH) {
    600                 fd_rtd_candidate_del($self, STRING, LENGTH);
    601         }
    602         void error(char * dest, char * STRING, size_t LENGTH, uint32_t rcode) {
    603                 int ret =  fd_rtd_error_add($self, dest, (uint8_t *)STRING, LENGTH, rcode);
    604                 if (ret != 0) {
    605                         DI_ERROR(ret, NULL, NULL);
    606                 }
    607         }
    608         struct fd_list * extract_li(int score = 0) {
    609                 struct fd_list * li = NULL;
    610                 fd_rtd_candidate_extract($self, &li, score);
    611                 return li;
    612         }
    613         PyObject * extract(int score = 0) {
    614                 struct fd_list * list = NULL, *li;
    615                 PyObject * rl;
    616                 fd_rtd_candidate_extract($self, &list, score);
    617                 rl = PyList_New(0);
    618                 SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    619                 for (li = list->next; li != list; li = li->next) {
    620                         PyList_Append(rl, SWIG_NewPointerObj((void *)li, SWIGTYPE_p_rtd_candidate, 0 ));
    621                 }
    622                 Py_XINCREF(rl);
    623                 SWIG_PYTHON_THREAD_END_BLOCK;
    624                
    625                 return rl;
    626         }
    627 }
    628 
    629 %extend rtd_candidate {
    630         void dump() {
    631                 fd_log_debug("candidate %p\n", $self);
    632                 fd_log_debug("  id : %s\n",  $self->diamid);
    633                 fd_log_debug("  rlm: %s\n", $self->realm);
    634                 fd_log_debug("  sc : %d\n", $self->score);
    635         }
    636 }
    637 
    638 
    639 
    640 /****** MESSAGES *********/
    641 
    642 struct msg {
    643 };
    644 
    645 %extend msg {
    646         msg() {
    647                 DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_COMMAND object parameter (or None) is required.");
    648                 return NULL;
    649         }
    650         msg(struct dict_object * model, int flags = MSGFL_ALLOC_ETEID) {
    651                 struct msg * m = NULL;
    652                 int ret = fd_msg_new( model, flags, &m);
    653                 if (ret != 0) {
    654                         DI_ERROR(ret, NULL, NULL);
    655                 }
    656                 return m;
    657         }
    658         ~msg() {
    659                 int ret = fd_msg_free($self);
    660                 if (ret != 0) {
    661                         DI_ERROR(ret, NULL, NULL);
    662                 }
    663         }
    664         %newobject create_answer;
    665         struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) {
    666                 /* if dict is not provided, attempt to get it from the request model */
    667                 struct dictionary * d = dict;
    668                 struct msg * m = $self;
    669                 int ret;
    670                 if (!d) {
    671                         struct dict_object * mo = NULL;
    672                         ret = fd_msg_model($self, &mo);
    673                         if (ret != 0) {
    674                                 DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
    675                                 return NULL;
    676                         }
    677                         ret = fd_dict_getdict ( mo, &d );
    678                         if (ret != 0) {
    679                                 DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
    680                                 return NULL;
    681                         }
    682                 }
    683                 ret = fd_msg_new_answer_from_req(d, &m, flags);
    684                 if (ret != 0) {
    685                         DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
    686                         return NULL;
    687                 }
    688                 return m;
    689         }
    690 }
    691 
    692 struct avp {
    693 };
    694 
    695 %extend avp {
    696         avp() {
    697                 DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_AVP object parameter (or None) is required.");
    698                 return NULL;
    699         }
    700         avp(struct dict_object * model, int flags = 0) {
    701                 struct avp * a = NULL;
    702                 int ret = fd_msg_avp_new( model, flags, &a);
    703                 if (ret != 0) {
    704                         DI_ERROR(ret, NULL, NULL);
    705                 }
    706                 return a;
    707         }
    708         ~avp() {
    709                 int ret = fd_msg_free($self);
    710                 if (ret != 0) {
    711                         DI_ERROR(ret, NULL, NULL);
    712                 }
    713         }
    714 }
    715        
    716 
    717 
    718 
    719 %cstring_output_allocate_size(char ** swig_buffer, size_t * swig_len, free(*$1))
    720 %inline %{
    721 int fd_msg_bufferize_py ( struct msg * msg, char ** swig_buffer, size_t * swig_len ) {
    722         return fd_msg_bufferize(msg, (void *)swig_buffer, swig_len);
    723 }
    724 %};
    725 
     151%include "peers.i"
  • include/freeDiameter/libfreeDiameter.h

    r621 r637  
    21822182 *  msg         : A msg object.
    21832183 *  diamid      : The diameter id of the peer from which this message was received.
    2184  *  hash        : The hash for the diamid value.
    21852184 *  add_rr      : if true, a Route-Record AVP is added to the message with content diamid. In that case, dict must be supplied.
    21862185 *  dict        : a dictionary with definition of Route-Record AVP (if add_rr is true)
     
    23612360 *  If the dictionary definition is not found, avp_model is set to NULL and
    23622361 *  the content of the AVP is saved as an octetstring in an internal structure. avp_value is NULL.
    2363  *  As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is be freed.
     2362 *  As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is freed.
    23642363 *
    23652364 * RETURN VALUE:
  • libfreeDiameter/messages.c

    r400 r637  
    118118        int                      msg_routable;          /* Is this a routable message? (0: undef, 1: routable, 2: non routable) */
    119119        struct msg              *msg_query;             /* the associated query if the message is a received answer */
     120        int                      msg_associated;        /* and the counter part information in the query, to avoid double free */
    120121        struct rt_data          *msg_rtdata;            /* Routing list for the query */
    121122        struct session          *msg_sess;              /* Cached message session if any */
     
    342343        /* associate with query */
    343344        ans->msg_query = qry;
     345        qry->msg_associated = 1;
    344346       
    345347        /* Done */
     
    629631        if (CHECK_MSG(object)) {
    630632                if (_M(object)->msg_query) {
     633                        _M(_M(object)->msg_query)->msg_associated = 0;
    631634                        CHECK_FCT(  fd_msg_free( _M(object)->msg_query )  );
    632635                        _M(object)->msg_query = NULL;
     636                } else {
     637                        if (_M(object)->msg_associated) {
     638                                TRACE_DEBUG(INFO, "Not freeing query %p referenced in an answer (will be freed along the answer).", object);
     639                                return 0;
     640                        }
    633641                }
    634642        }
     
    689697                msg->msg_public.msg_eteid
    690698                );
    691         fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p sess:%p src:%s\n",
    692                         INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_sess, msg->msg_src_id?:"(nil)");
     699        fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n",
     700                        INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)");
    693701}
    694702
     
    862870       
    863871        answer->msg_query = query;
     872        query->msg_associated = 1;
    864873       
    865874        return 0;
     
    883892        CHECK_PARAMS(  CHECK_MSG(answer) );
    884893       
     894        answer->msg_query->msg_associated = 0;
    885895        answer->msg_query = NULL;
    886896       
Note: See TracChangeset for help on using the changeset viewer.