Navigation


Changeset 638:9448cba86673 in freeDiameter


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

Improved usability of dbg_interactive

Files:
10 edited

Legend:

Unmodified
Added
Removed
  • doc/dbg_interactive.py.sample

    r637 r638  
    104104
    105105############# Hash ############
    106 hex(fd_hash("hello world"))     # A typemap is applied to accept binary data
     106
     107hex(fd_hash("hello world"))     # It accepts binary data
    107108
    108109
     
    122123d.vendors_list()
    123124
     125# Compact invocation also possible:
     126v2 = dict_vendor_data(124, "My test vendor 2")
     127del v2
     128
    124129# New application
    125130a = dict_application_data()
     
    128133my_appl = d.new_obj(DICT_APPLICATION, a, my_vendor)
    129134del a
     135
     136a2 = dict_application_data(99, "My test appl 2")
     137del a2
    130138
    131139# New type (callbacks are not supported yet...)
     
    139147del t
    140148
     149t2 = dict_type_data(AVP_TYPE_UNSIGNED32, "u32 type")
     150del t2
     151
    141152# Constants
    142153c = dict_enumval_data()
     
    150161d.new_obj(DICT_ENUMVAL, c, my_type_os)
    151162del c
     163
     164c2 = dict_enumval_data("enum 23", 23)  # The constructor only accepts unsigned32, for other values, set them afterwards
     165c3 = dict_enumval_data("enum other")
     166c3.os = "other value"
     167del c2
     168del c3
    152169
    153170# AVP
     
    166183my_avp_os = d.new_obj(DICT_AVP, a, my_type_os)
    167184del a
     185
     186a2 = dict_avp_data(235, "no vendor, not mandatory", AVP_TYPE_OCTETSTRING)
     187a3 = dict_avp_data(236, "vendor 12, not mandatory", AVP_TYPE_OCTETSTRING, 12)
     188a4 = dict_avp_data(237, "vendor 12, mandatory", AVP_TYPE_OCTETSTRING, 12, 1)
     189a5 = dict_avp_data(238, "no vendor, mandatory", AVP_TYPE_OCTETSTRING, 0, 1)
     190del a2
     191del a3
     192del a4
     193del a5
     194
    168195
    169196# Command
     
    178205my_ans = d.new_obj(DICT_COMMAND, c, my_appl)
    179206del c
     207
     208c2 = dict_cmd_data(346, "Second-Request", 1) # Default created with PROXIABLE flag.
     209c3 = dict_cmd_data(346, "Second-Answer",  0)
     210del c2
     211del c3
    180212
    181213# Rule
     
    195227del d
    196228
     229r2 = dict_rule_data(my_avp_int, RULE_REQUIRED) # min & max are optional parameters, default to -1
     230r3 = dict_rule_data(my_avp_int, RULE_REQUIRED, 2, 3) # min is 2, max is 3
     231r4 = dict_rule_data(my_avp_int, RULE_FIXED_HEAD) # The r4.rule_order = 1 by default, change afterwards if needed.
     232del r2
     233del r3
     234del r4
    197235
    198236####### Now play with the "real" dictionary
     
    272310## AVP
    273311
    274 # Create empty (as for messages, pass None or a dictionary object as 1st param, and flags as optional 2nd param)
     312# Create empty
    275313blank_avp = avp()
    276314del blank_avp
    277315
     316# Create from dictionary definitions
    278317oh = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host"))                      # Octet String
    279318vi = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Id"))                        # U32
     
    289328vsai.add_child(vi) # call as add_child(vi, 1) to add the new AVP at the beginning, default is at the end
    290329
     330# It is possible to initialize the AVP with a blank value as follow:
     331blank_with_value = avp(None, AVPFL_SET_BLANK_VALUE)
     332# it enables this without doing the setval call:
     333blank_with_value.header().avp_value.u32 = 12
     334
    291335
    292336## Messages
    293337
    294 # Create empty
     338# Create empt (as for avps, pass None or a dictionary object as 1st param, and flags as optional 2nd param)y
    295339a_msg = msg()
    296340a_msg.dump()
     
    358402hex(oh_hdr.avp_flags)
    359403oh_hdr.avp_vendor
    360 oh_hdr.avp_value.os.dump()  # The initial avp value must be set with setval(), but then this accessor is allowed.
     404oh_hdr.avp_value.os.as_str()
     405
    361406
    362407# Get or set the routing data
     
    390435
    391436
    392 
    393 
    394 
    395 
    396 
    397 
    398 
    399 
    400 ######################### old stuff (need update) ######################
    401 
    402 
    403 # Create a new peer_info structure and add the peer to the framework.
    404 mypeer = peer_info()
    405 mypeer.pi_diamid = "nas.testbed.aaa"
    406 mypeer.config.pic_flags.pro4 = 1   # 1 for TCP, for some reason PI_P4_TCP is not defined
    407 fd_peer_add(mypeer, "python", None, None)
    408 del mypeer
    409 
     437# Send a message:
     438mydwr.send()
     439
     440# Optionaly, a callback can be registered when a message is sent, with an optional object.
     441# This callback takes the answer message as parameter and should return None or a message. (cf. fd_msg_send)
     442def send_callback(msg, obj):
     443    print "Received answer:"
     444    msg.dump()
     445    print "Associated data:"
     446    obj
     447    return None
     448
     449mydwr.send(send_callback, some_object)
     450
     451
     452# Set a result code in an answer message.
     453dwa = mydwr.create_answer()
     454dwa.rescode_set()   # This adds the DIAMETER_SUCCESS result code
     455dwa.rescode_set("DIAMETER_LIMITED_SUCCESS" )   # This adds a different result code
     456dwa.rescode_set("DIAMETER_LIMITED_SUCCESS", "Something went not so well" )   # This adds a different result code + specified Error-Message
     457dwa.rescode_set("DIAMETER_INVALID_AVP", None, faulty_avp )   # This adds a Failed-AVP
     458dwa.rescode_set("DIAMETER_SUCCESS", None, None, 1 )   # This adds origin information (see fd_msg_rescode_set's type_id for more info)
     459
     460# Set the origin to local host
     461mydwr.add_origin()  # adds Origin-Host & Origin-Realm
     462mydwr.add_origin(1) # adds Origin-State-Id in addition.
     463
     464
     465############# DISPATCH (aka. server application) ############
     466
     467# As for sessions, only one dispatch handler can be registered in this extension at the moment.
     468# The callback for the handler has the following syntax:
     469def dispatch_cb_model(inmsg, inavp, insession):
     470   print "Callback trigged on message: "
     471   inmsg.dump()
     472   # inavp is None or the AVP that trigged the callback, depending on how it was registered.
     473   if inavp:
     474     print "From the following AVP:"
     475     inavp.dump()
     476   else:
     477     print "No AVP"
     478   # Session is provided only if a Session-Id is in the message
     479   if insession:
     480     print "The session is: ", insession.getsid()
     481   else:
     482     print "No session"
     483   # Now, for the return value.
     484   # This callback must return 3 elements:
     485   # - an integer which is interpreted as an error code (errno.h)
     486   # - a message or None, depending on the next item
     487   # - an enum disp_action value, with the same meaning as in C (see libfreeDiameter.h)
     488   del inmsg
     489   return [ 0, None, DISP_ACT_CONT ]
     490
     491
     492### Example use: rebuild the server-side of test_app.fdx in python
     493
     494# The following block defines the dictionary objects from the test_app.fdx application that we use on the remote peer
     495gdict = cvar.fd_g_config.cnf_dict
     496d_si = gdict.search ( DICT_AVP, AVP_BY_NAME, "Session-Id" )
     497d_oh  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host" )
     498d_or  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Realm" )
     499d_dh  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Host" )
     500d_dr  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Realm" )
     501d_rc  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Result-Code" )
     502d_vnd = gdict.new_obj(DICT_VENDOR,      dict_vendor_data(999999,        "app_test_py vendor") )
     503d_app = gdict.new_obj(DICT_APPLICATION, dict_application_data(0xffffff, "app_test_py appli"), d_vnd)
     504d_req = gdict.new_obj(DICT_COMMAND,     dict_cmd_data(0xfffffe, "Test_py-Request", 1), d_app)
     505d_ans = gdict.new_obj(DICT_COMMAND,     dict_cmd_data(0xfffffe, "Test_py-Answer",  0), d_app)
     506d_avp = gdict.new_obj(DICT_AVP,         dict_avp_data(0xffffff, "app_test_py avp", AVP_TYPE_INTEGER32, 999999 ))
     507gdict.new_obj(DICT_RULE, dict_rule_data(d_si, RULE_FIXED_HEAD, 1, 1), d_req)
     508gdict.new_obj(DICT_RULE, dict_rule_data(d_si, RULE_FIXED_HEAD, 1, 1), d_ans)
     509gdict.new_obj(DICT_RULE, dict_rule_data(d_avp, RULE_REQUIRED, 1, 1), d_req)
     510gdict.new_obj(DICT_RULE, dict_rule_data(d_avp, RULE_REQUIRED, 1, 1), d_ans)
     511gdict.new_obj(DICT_RULE, dict_rule_data(d_oh, RULE_REQUIRED, 1, 1), d_req)
     512gdict.new_obj(DICT_RULE, dict_rule_data(d_oh, RULE_REQUIRED, 1, 1), d_ans)
     513gdict.new_obj(DICT_RULE, dict_rule_data(d_or, RULE_REQUIRED, 1, 1), d_req)
     514gdict.new_obj(DICT_RULE, dict_rule_data(d_or, RULE_REQUIRED, 1, 1), d_ans)
     515gdict.new_obj(DICT_RULE, dict_rule_data(d_dr, RULE_REQUIRED, 1, 1), d_req)
     516gdict.new_obj(DICT_RULE, dict_rule_data(d_dh, RULE_OPTIONAL, 0, 1), d_req)
     517gdict.new_obj(DICT_RULE, dict_rule_data(d_rc, RULE_REQUIRED, 1, 1), d_ans)
     518
     519# Now, create the Test_app server callback:
     520def test_app_cb(inmsg, inavp, insession):
     521   tval = inmsg.search(d_avp).header().avp_value.u32
     522   print "Py ECHO Test message from '%s' with test value %x, replying..." % (inmsg.search(d_oh).header().avp_value.os.as_str(), tval)
     523   answ = inmsg.create_answer()
     524   answ.rescode_set()
     525   answ.add_origin()
     526   ta = avp(d_avp, AVPFL_SET_BLANK_VALUE)
     527   ta.header().avp_value.u32 = tval
     528   answ.add_child(ta)
     529   return [ 0, answ, DISP_ACT_SEND ]
     530
     531# Register the callback for dispatch thread:
     532hdl = disp_hdl(test_app_cb, DISP_HOW_CC, disp_when(d_app, d_req))  # disp_when() takes 0 to 4 arguments as follow: (app=NULL, cmd=NULL, avp=NULL, val=NULL)
     533
     534# Don't forget to register the application in the daemon for CER/CEA capabilities.
     535fd_disp_app_support ( d_app, d_vnd, 1, 0 )
     536
     537
     538###  For the fun, the client part of the test_app:
     539
     540def receive_answer(ans, testval):
     541   try:
     542     tval = ans.search(d_avp).header().avp_value.u32
     543   except:
     544     print "Error in receive_answer: no Test-AVP included"
     545     tval = 0
     546   try:
     547     print "Py RECV %x (expected: %x) Status: %d From: '%s'" % (tval, testval, ans.search(d_rc).header().avp_value.u32, ans.search(d_oh).header().avp_value.os.as_str())
     548   except:
     549     print "Error in receive_answer: Result-Code or Origin-Host are missing"
     550   del ans
     551   return None
     552
     553import random
     554
     555def send_query(destrealm="localdomain"):
     556   qry = msg(d_req)
     557   sess = session()
     558   tv = random.randint(1, 1<<32)
     559   # Session-Id
     560   a = avp(d_si, AVPFL_SET_BLANK_VALUE)
     561   a.header().avp_value.os = sess.getsid()
     562   qry.add_child(a)
     563   # Destination-Realm
     564   a = avp(d_dr, AVPFL_SET_BLANK_VALUE)
     565   a.header().avp_value.os = destrealm
     566   qry.add_child(a)
     567   # Origin-Host, Origin-Realm
     568   qry.add_origin()
     569   # Test-AVP
     570   a = avp(d_avp, AVPFL_SET_BLANK_VALUE)
     571   a.header().avp_value.u32 = tv
     572   qry.add_child(a)
     573   print "Py SEND %x to '%s'" % (tv, destrealm)
     574   qry.send(receive_answer, tv)
     575
     576send_query()
     577
     578
     579############# FIFO queues ############
     580
     581myqueue = fifo()
     582
     583# enqueue any object
     584myqueue.post(3)
     585myqueue.post("blah")
     586myqueue.post( [ 3, 2 ] )
     587
     588# Simple get (blocks when the queue is empty)
     589myqueue.get()
     590
     591# Try get: returns the next object, or None if the queue is empty
     592myqueue.tryget()
     593
     594# timed get: like get, but returns None after x seconds
     595myqueue.timedget(3)
     596
     597# Show the number of items in the queue
     598myqueue.length()
     599
     600del myqueue
     601
     602
     603
     604############# PEERS ############
     605
     606# Get the list of peers defined in the system
     607# (well, we are supposed actually to readlock fd_g_peers_rw before doing this, but it should be fine most of the time)
     608peers = cvar.fd_g_peers.enum_as("struct peer_hdr *")
     609for p in peers:
     610   print "Peer:", p.info.pi_diamid
     611
     612
     613# Create a new peer
     614np = peer_info()
     615np.pi_diamid = "nas.localdomain"
     616np.config.pic_flags.pro4 = 1   # 1 for TCP, for some reason PI_P4_TCP is not defined
     617
     618
     619
     620
     621# Add this peer into the framework.
     622np.add()
     623
     624# It is possible to specify a callback for when the connection completes or fails to this peer.
     625# The prototype is as follow:
     626def add_cb(peer):
     627    if peer:
     628        if peer.runtime.pir_state == STATE_OPEN:
     629           print "Connection to peer '%s' completed" % (peer.pi_diamid)
     630           # can find more information in peer.runtime.*
     631        else:
     632           print "Connection to peer '%s' failed (state:%d)" % (peer.pi_diamid, peer.runtime.pir_state)
     633    else:
     634        print "The peer has been destroyed before it completed the connection."
     635
     636# Then add the peer simply like this:
     637np.add(add_cb)
     638
     639
  • extensions/dbg_interactive/dbg_interactive.i

    r637 r638  
    129129
    130130
     131/* Forward declaration for the peers module */
     132%{
     133static void fd_add_cb(struct peer_info *peer, void *data);
     134%}
     135
    131136/*********************************************************
    132137 Now, create wrappers for (almost) all objects from fD API
  • extensions/dbg_interactive/dictionary.i

    r637 r638  
    242242                fd_log_debug("] '%.*s%s'\n", n, $self->data, n == LEN_MAX ? "..." : "");
    243243        }
    244 }
     244        %cstring_output_allocate_size(char ** outbuffer, size_t * outlen, free(*$1));
     245        void as_str ( char ** outbuffer, size_t * outlen ) {
     246                char * b;
     247                if (!$self->len) {
     248                        *outlen = 0;
     249                        *outbuffer = NULL;
     250                        return;
     251                }
     252                b = malloc($self->len);
     253                if (!b) {
     254                        DI_ERROR_MALLOC;
     255                        return;
     256                }
     257                memcpy(b, $self->data, $self->len);
     258                *outlen = $self->len;
     259                *outbuffer = b;
     260        }
     261}
     262
     263
     264/* Allow constructors with parameters for the dict_*_data */
     265%extend dict_vendor_data {
     266        dict_vendor_data(uint32_t id = 0, char * name = NULL) {
     267                struct dict_vendor_data * d = (struct dict_vendor_data *)calloc(1, sizeof(struct dict_vendor_data));
     268                if (!d) {
     269                        DI_ERROR_MALLOC;
     270                        return NULL;
     271                }
     272                d->vendor_id = id;
     273                if (name) {
     274                        d->vendor_name = strdup(name);
     275                        if (!d->vendor_name) {
     276                                DI_ERROR_MALLOC;
     277                                free(d);
     278                                return NULL;
     279                        }
     280                }
     281                return d;
     282        }
     283}
     284
     285%extend dict_application_data {
     286        dict_application_data(uint32_t id = 0, char * name = NULL) {
     287                struct dict_application_data * d = (struct dict_application_data *)calloc(1, sizeof(struct dict_application_data));
     288                if (!d) {
     289                        DI_ERROR_MALLOC;
     290                        return NULL;
     291                }
     292                d->application_id = id;
     293                if (name) {
     294                        d->application_name = strdup(name);
     295                        if (!d->application_name) {
     296                                DI_ERROR_MALLOC;
     297                                free(d);
     298                                return NULL;
     299                        }
     300                }
     301                return d;
     302        }
     303}
     304
     305%extend dict_type_data {
     306        dict_type_data(enum dict_avp_basetype base = 0, char * name = NULL) {
     307                struct dict_type_data * d = (struct dict_type_data *)calloc(1, sizeof(struct dict_type_data));
     308                if (!d) {
     309                        DI_ERROR_MALLOC;
     310                        return NULL;
     311                }
     312                d->type_base = base;
     313                if (name) {
     314                        d->type_name = strdup(name);
     315                        if (!d->type_name) {
     316                                DI_ERROR_MALLOC;
     317                                free(d);
     318                                return NULL;
     319                        }
     320                }
     321                return d;
     322        }
     323}
     324
     325%extend dict_enumval_data {
     326        dict_enumval_data(char * name = NULL, uint32_t v = 0) {
     327                struct dict_enumval_data * d = (struct dict_enumval_data *)calloc(1, sizeof(struct dict_enumval_data));
     328                if (!d) {
     329                        DI_ERROR_MALLOC;
     330                        return NULL;
     331                }
     332                if (name) {
     333                        d->enum_name = strdup(name);
     334                        if (!d->enum_name) {
     335                                DI_ERROR_MALLOC;
     336                                free(d);
     337                                return NULL;
     338                        }
     339                }
     340                d->enum_value.u32 = v;
     341                return d;
     342        }
     343}
     344
     345%extend dict_avp_data {
     346        dict_avp_data(uint32_t code = 0, char * name = NULL, enum dict_avp_basetype basetype = 0, uint32_t vendor = 0, int mandatory=0) {
     347                struct dict_avp_data * d = (struct dict_avp_data *)calloc(1, sizeof(struct dict_avp_data));
     348                if (!d) {
     349                        DI_ERROR_MALLOC;
     350                        return NULL;
     351                }
     352                if (name) {
     353                        d->avp_name = strdup(name);
     354                        if (!d->avp_name) {
     355                                DI_ERROR_MALLOC;
     356                                free(d);
     357                                return NULL;
     358                        }
     359                }
     360                d->avp_code = code;
     361                d->avp_basetype = basetype;
     362                d->avp_vendor = vendor;
     363                if (vendor) {
     364                        d->avp_flag_val |= AVP_FLAG_VENDOR;
     365                        d->avp_flag_mask |= AVP_FLAG_VENDOR;
     366                }
     367                d->avp_flag_mask |= AVP_FLAG_MANDATORY;
     368                if (mandatory)
     369                        d->avp_flag_val |= AVP_FLAG_MANDATORY;
     370                return d;
     371        }
     372}
     373
     374%extend dict_cmd_data {
     375        dict_cmd_data(uint32_t code = 0, char * name = NULL, int request = 1) {
     376                struct dict_cmd_data * d = (struct dict_cmd_data *)calloc(1, sizeof(struct dict_cmd_data));
     377                if (!d) {
     378                        DI_ERROR_MALLOC;
     379                        return NULL;
     380                }
     381                if (name) {
     382                        d->cmd_name = strdup(name);
     383                        if (!d->cmd_name) {
     384                                DI_ERROR_MALLOC;
     385                                free(d);
     386                                return NULL;
     387                        }
     388                }
     389                d->cmd_code = code;
     390                d->cmd_flag_mask = CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE;
     391                d->cmd_flag_val = CMD_FLAG_PROXIABLE | ( request ? CMD_FLAG_REQUEST : 0 );
     392                return d;
     393        }
     394}
     395
     396%extend dict_rule_data {
     397        dict_rule_data(struct dict_object *avp = NULL, enum rule_position pos = 0, int min = -1, int max = -1 ) {
     398                struct dict_rule_data * d = (struct dict_rule_data *)calloc(1, sizeof(struct dict_rule_data));
     399                if (!d) {
     400                        DI_ERROR_MALLOC;
     401                        return NULL;
     402                }
     403                d->rule_avp = avp;
     404                d->rule_position = pos;
     405                d->rule_order = 1;
     406                d->rule_min = min;
     407                d->rule_max = max;
     408                return d;
     409        }
     410}
     411
  • extensions/dbg_interactive/dispatch.i

    r637 r638  
    3636/* Do not include this directly, use dbg_interactive.i instead */
    3737
     38/****** DISPATCH *********/
     39
     40
     41%{
     42/* store the python callback function here */
     43static PyObject * py_dispatch_cb = NULL;
     44static int        py_dispatch_cb_n = 0;
     45/* call it (will be called from a different thread than the interpreter, when message arrives) */
     46static int call_the_python_dispatch_callback(struct msg **msg, struct avp *avp, struct session *session, enum disp_action *action) {
     47        PyObject *PyMsg, *PyAvp, *PySess;
     48        PyObject *result = NULL;
     49        int ret = 0;
     50       
     51        if (!py_dispatch_cb)
     52                return ENOTSUP;
     53       
     54        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
     55        /* Convert the arguments */
     56        PyMsg  = SWIG_NewPointerObj((void *)*msg,     SWIGTYPE_p_msg,     0 );
     57        PyAvp  = SWIG_NewPointerObj((void *) avp,     SWIGTYPE_p_avp,     0 );
     58        PySess = SWIG_NewPointerObj((void *) session, SWIGTYPE_p_session, 0 );
     59       
     60        /* Call the function */
     61        result = PyEval_CallFunction(py_dispatch_cb, "(OOO)", PyMsg, PyAvp, PySess);
     62       
     63        /* The result is supposedly composed of: [ ret, *msg, *action ] */
     64        if ((result == NULL) || (!PyList_Check(result)) || (PyList_Size(result) != 3)) {
     65                fd_log_debug("Error: The Python callback did not return [ ret, msg, action ].\n");
     66                ret = EINVAL;
     67                goto out;
     68        }
     69       
     70        /* Convert the return values */
     71        if (!SWIG_IsOK(SWIG_AsVal_int(PyList_GetItem(result, 0), &ret))) {
     72                fd_log_debug("Error: Cannot convert the first return value to integer.\n");
     73                ret = EINVAL;
     74                goto out;
     75        }
     76        if (ret) {
     77                TRACE_DEBUG(INFO, "The Python callback returned the error code %d (%s)\n", ret, strerror(ret));
     78                goto out;
     79        }
     80       
     81        if (!SWIG_IsOK(SWIG_ConvertPtr(PyList_GetItem(result, 1), (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) {
     82                fd_log_debug("Error: Cannot convert the second return value to message.\n");
     83                ret = EINVAL;
     84                goto out;
     85        }
     86       
     87        if (!SWIG_IsOK(SWIG_AsVal_int(PyList_GetItem(result, 2), (int *)action))) {
     88                fd_log_debug("Error: Cannot convert the third return value to integer.\n");
     89                ret = EINVAL;
     90                goto out;
     91        }
     92       
     93        TRACE_DEBUG(FULL, "Python callback return: *action = %d\n", *action);
     94out:   
     95        Py_XDECREF(result);
     96       
     97        SWIG_PYTHON_THREAD_END_BLOCK;
     98        return ret;
     99}
     100%}
     101
     102struct disp_hdl {
     103};
     104
     105%nodefaultctor disp_hdl;
     106%extend disp_hdl {
     107        disp_hdl(PyObject * PyCb, enum disp_how how, struct disp_when * when) {
     108                struct disp_hdl * hdl = NULL;
     109                int ret;
     110                if (py_dispatch_cb && (py_dispatch_cb != PyCb)) {
     111                        DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one dispatch callback is supported at the moment in this extension\n.");
     112                        return NULL;
     113                }
     114                py_dispatch_cb = PyCb;
     115                py_dispatch_cb_n += 1;
     116                Py_XINCREF(py_dispatch_cb);
     117               
     118                ret = fd_disp_register ( call_the_python_dispatch_callback, how, when, &hdl );
     119                if (ret != 0) {
     120                        DI_ERROR(ret, NULL, NULL);
     121                        return NULL;
     122                }
     123                return hdl;
     124        }
     125        ~disp_hdl() {
     126                struct disp_hdl * hdl = self;
     127                int ret = fd_disp_unregister(&hdl);
     128                if (ret != 0) {
     129                        DI_ERROR(ret, NULL, NULL);
     130                }
     131                /* Now free the callback */
     132                Py_XDECREF(py_dispatch_cb);
     133                py_dispatch_cb_n -= 1;
     134                if (!py_dispatch_cb_n)
     135                        py_dispatch_cb = NULL;
     136                return;
     137        }
     138}
     139
     140
     141%extend disp_when {
     142        disp_when(struct dict_object * app = NULL, struct dict_object * command = NULL, struct dict_object * avp = NULL, struct dict_object * value = NULL) {
     143                struct disp_when * w = (struct disp_when *)calloc(1, sizeof(struct disp_when));
     144                if (!w) {
     145                        DI_ERROR_MALLOC;
     146                        return NULL;
     147                }
     148                w->app = app;
     149                w->command = command;
     150                w->avp = avp;
     151                w->value = value;
     152                return w;
     153        }
     154}
  • extensions/dbg_interactive/messages.i

    r637 r638  
    3838/****** MESSAGES *********/
    3939
     40%{
     41struct anscb_py_layer {
     42        PyObject * cb;
     43        PyObject * data;
     44};
     45
     46/* If a python callback was provided, it is received in cbdata */
     47static void anscb_python(void *cbdata, struct msg ** msg) {
     48        /* The python callback is received in cbdata */
     49        PyObject * result, *PyMsg;
     50        struct anscb_py_layer * l = cbdata;
     51       
     52        if (!l) {
     53                fd_log_debug("Internal error! Python callback disappeared...\n");
     54                return;
     55        }
     56       
     57        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
     58       
     59        if (!msg || !*msg) {
     60                PyMsg = Py_None;
     61        } else {
     62                PyMsg = SWIG_NewPointerObj((void *)*msg,     SWIGTYPE_p_msg,     0 );
     63        }
     64       
     65        result = PyEval_CallFunction(l->cb, "(OO)", PyMsg, l->data);
     66        Py_XDECREF(l->cb);
     67        Py_XDECREF(l->data);
     68        free(l);
     69       
     70        /* The callback is supposed to return a message or NULL */
     71        if (!SWIG_IsOK(SWIG_ConvertPtr(result, (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) {
     72                fd_log_debug("Error: Cannot convert the return value to message.\n");
     73                *msg = NULL;
     74        }
     75       
     76        Py_XDECREF(result);
     77       
     78        SWIG_PYTHON_THREAD_END_BLOCK;
     79       
     80}
     81%}
     82
    4083struct msg {
    4184};
     
    75118                }
    76119        }
     120       
     121        /* SEND THE MESSAGE */
     122        %delobject send; /* when this has been called, the msg must not be freed anymore */
     123        void send(PyObject * PyCb = NULL, PyObject * data = NULL) {
     124                int ret;
     125                struct msg * m = $self;
     126                struct anscb_py_layer * l = NULL;
     127               
     128                if (PyCb) {
     129                        l = malloc(sizeof(struct anscb_py_layer));
     130                        if (!l) {
     131                                DI_ERROR_MALLOC;
     132                                return;
     133                        }
     134
     135                        Py_XINCREF(PyCb);
     136                        Py_XINCREF(data);
     137                        l->cb = PyCb;
     138                        l->data = data;
     139                }
     140               
     141                ret = fd_msg_send(&m, PyCb ? anscb_python : NULL, l);
     142                if (ret != 0) {
     143                        DI_ERROR(ret, NULL, NULL);
     144                }
     145        }
     146       
     147        /* Create an answer */
    77148        %delobject create_answer; /* when this has been called, the original msg should not be freed anymore */
    78149        struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) {
     
    313384                }
    314385        }
     386       
     387        /* Set the result code */
     388        void rescode_set(char * rescode = "DIAMETER_SUCCESS", char * errormsg = NULL, struct avp * optavp = NULL, int type_id = 0) {
     389                int ret = fd_msg_rescode_set( $self, rescode, errormsg, optavp, type_id );
     390                if (ret) {
     391                        DI_ERROR(ret, NULL, NULL);
     392                }
     393        }
     394       
     395        /* Add the origin */
     396        void add_origin(int osi = 0) {
     397                int ret = fd_msg_add_origin( $self, osi );
     398                if (ret) {
     399                        DI_ERROR(ret, NULL, NULL);
     400                }
     401        }
     402       
    315403}
    316404
  • extensions/dbg_interactive/peers.i

    r637 r638  
    3636/* Do not include this directly, use dbg_interactive.i instead */
    3737
     38/****** PEERS *********/
     39
     40%{
     41static void fd_add_cb(struct peer_info *peer, void *data) {
     42        /* Callback called when the peer connection completes (or fails) */
     43        PyObject *PyPeer, *PyFunc;
     44        PyObject *result = NULL;
     45       
     46        if (!data) {
     47                TRACE_DEBUG(INFO, "Internal error: missing callback\n");
     48                return;
     49        }
     50        PyFunc = data;
     51       
     52        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
     53       
     54        /* Convert the argument */
     55        PyPeer  = SWIG_NewPointerObj((void *)peer,     SWIGTYPE_p_peer_info,     0 );
     56       
     57        /* Call the function */
     58        result = PyEval_CallFunction(PyFunc, "(O)", PyPeer);
     59       
     60        Py_XDECREF(result);
     61        Py_XDECREF(PyFunc);
     62       
     63        SWIG_PYTHON_THREAD_END_BLOCK;
     64        return;
     65}
     66%}
     67
     68%extend peer_info {
     69        /* Wrapper around fd_peer_add to allow calling the python callback */
     70        void add(PyObject * PyCb=NULL) {
     71                int ret;
     72               
     73                if (PyCb) {
     74                        Py_XINCREF(PyCb);
     75                        ret = fd_peer_add ( $self, "dbg_interactive", fd_add_cb, PyCb );
     76                } else {
     77                        ret = fd_peer_add ( $self, "dbg_interactive", NULL, NULL );
     78                }
     79                if (ret != 0) {
     80                        DI_ERROR(ret, NULL, NULL);
     81                }
     82        }
     83
     84        /* Add an endpoint */
     85        void add_endpoint(char * endpoint) {
     86                fd_log_debug("What is the best way in python to pass an endpoint? (ip + port)");
     87        }
     88
     89}
  • extensions/dbg_interactive/queues.i

    r637 r638  
    3636/* Do not include this directly, use dbg_interactive.i instead */
    3737
     38/****** FIFO QUEUES *********/
     39
     40struct fifo {
     41};
     42
     43%extend fifo {
     44        fifo() {
     45                struct fifo * q = NULL;
     46                int ret = fd_fifo_new(&q);
     47                if (ret != 0) {
     48                        DI_ERROR(ret, NULL, NULL);
     49                        return NULL;
     50                }
     51                return q;
     52        }
     53        ~fifo() {
     54                struct fifo *q = self;
     55                fd_fifo_del(&q);
     56        }
     57       
     58        /* Move all elements to another queue */
     59        void move(struct fifo * to) {
     60                int ret = fd_fifo_move($self, to, NULL);
     61                if (ret != 0) {
     62                        DI_ERROR(ret, NULL, NULL);
     63                }
     64        }
     65       
     66        /* Get the length of the queue (nb elements) */
     67        int length() {
     68                int l;
     69                int ret = fd_fifo_length ( $self, &l );
     70                if (ret != 0) {
     71                        DI_ERROR(ret, NULL, NULL);
     72                }
     73                return l;
     74        }
     75
     76        /* Is the threashold function useful here? TODO... */
     77       
     78        /* Post an item */
     79        void post(PyObject * item) {
     80                int ret;
     81                PyObject * i = item;
     82               
     83                Py_XINCREF(i);
     84                ret = fd_fifo_post($self, &i);
     85                if (ret != 0) {
     86                        DI_ERROR(ret, NULL, NULL);
     87                }
     88        }
     89       
     90        /* Get (blocking) */
     91        PyObject * get() {
     92                int ret;
     93                PyObject * i = NULL;
     94               
     95                ret = fd_fifo_get($self, &i);
     96                if (ret != 0) {
     97                        DI_ERROR(ret, NULL, NULL);
     98                }
     99               
     100                return i;
     101        }
     102       
     103        /* TryGet (non-blocking, returns None on empty queue) */
     104        PyObject * tryget() {
     105                int ret;
     106                PyObject * i = NULL;
     107               
     108                ret = fd_fifo_tryget($self, &i);
     109                if (ret == EWOULDBLOCK) {
     110                        Py_XINCREF(Py_None);
     111                        return Py_None;
     112                }
     113                if (ret != 0) {
     114                        DI_ERROR(ret, NULL, NULL);
     115                }
     116               
     117                return i;
     118        }
     119       
     120        /* TimedGet (blocking for a while) */
     121        PyObject * timedget(long seconds) {
     122                int ret;
     123                PyObject * i = NULL;
     124                struct timespec ts;
     125               
     126                clock_gettime(CLOCK_REALTIME, &ts);
     127                ts.tv_sec += seconds;
     128               
     129                ret = fd_fifo_timedget($self, &i, &ts);
     130                if (ret == ETIMEDOUT) {
     131                        Py_XINCREF(Py_None);
     132                        return Py_None;
     133                }
     134                if (ret != 0) {
     135                        DI_ERROR(ret, NULL, NULL);
     136                }
     137               
     138                return i;
     139        }
     140       
     141}               
     142       
     143       
     144       
     145       
  • extensions/dbg_interactive/sessions.i

    r637 r638  
    5959};
    6060
     61%nodefaultctor session_handler;
    6162%extend session_handler {
    62         session_handler() {
    63                 DI_ERROR(EINVAL, PyExc_SyntaxError, "a cleanup callback parameter is required.");
    64                 return NULL;
    65         }
    6663        session_handler(PyObject * PyCb) {
    6764                struct session_handler * hdl = NULL;
     
    9693        }
    9794}
     95
    9896
    9997struct session {
  • include/freeDiameter/libfreeDiameter.h

    r637 r638  
    18771877
    18781878/* Some flags used in the functions bellow */
     1879#define AVPFL_SET_BLANK_VALUE   0x01    /* When creating an AVP, initialize its value to a blank area */
     1880#define AVPFL_MAX               AVPFL_SET_BLANK_VALUE   /* The biggest valid flag value */
     1881       
    18791882#define MSGFL_ALLOC_ETEID       0x01    /* When creating a message, a new end-to-end ID is allocated and set in the message */
    18801883#define MSGFL_ANSW_ERROR        0x02    /* When creating an answer message, set the 'E' bit and use the generic error ABNF instead of command-specific ABNF */
     
    18901893 * PARAMETERS:
    18911894 *  model       : Pointer to a DICT_AVP dictionary object describing the avp to create, or NULL.
    1892  *  flags       : Flags to use in creation (not used yet, should be 0).
     1895 *  flags       : Flags to use in creation (AVPFL_*).
    18931896 *  avp         : Upon success, pointer to the new avp is stored here.
    18941897 *
  • libfreeDiameter/messages.c

    r637 r638  
    140140
    141141/* Macro to validate a MSGFL_ value */
     142#define CHECK_AVPFL(_fl) ( ((_fl) & (- (AVPFL_MAX << 1) )) == 0 )
    142143#define CHECK_MSGFL(_fl) ( ((_fl) & (- (MSGFL_MAX << 1) )) == 0 )
    143144
     
    200201       
    201202        /* Check the parameters */
    202         CHECK_PARAMS(  avp && CHECK_MSGFL(flags)  );
     203        CHECK_PARAMS(  avp && CHECK_AVPFL(flags)  );
    203204       
    204205        if (model) {
     
    223224                new->avp_public.avp_len = GETINITIALSIZE(dictdata.avp_basetype, dictdata.avp_flag_val );
    224225                new->avp_public.avp_vendor  = dictdata.avp_vendor;
     226        }
     227       
     228        if (flags & AVPFL_SET_BLANK_VALUE) {
     229                new->avp_public.avp_value = &new->avp_storage;
    225230        }
    226231       
Note: See TracChangeset for help on using the changeset viewer.