[[PageOutline(2-4)]] = Embedded Python interpreter = This {{{dbg_interactive.fdx}}} extension gives access to the freeDiameter framework through a Python interface layer. It can be used both to run pre-existing scripts or through an interactive console directly for quick tests / monitoring of the daemon's state. A warning anyway: this python layer should not be used for any purpose other than quick prototyping and/or debug. The memory management and the efficiency are bellow the level of the framework itself -- although still pretty usable. == Configuration == {{{dbg_interactive_xml.fdx}}} extension does not use a configuration file. It is possible however to specify a file associated with the extension in the main {{freeDiameter.conf}} file. In that case, this file should be a python script, that will be executed by the embedded python interpreter. If no such file is provided, the interpreter is run interactively (as long as the daemon is run with a usable console). == Usage == The list of all usable functions is given in [source:freeDiameter/doc/dbg_interactive.py.sample dbg_interactive.py.sample]. Here is a brief example of how to re-create the [wiki:test_app.fdx] client and server function from python: {{{ #!python # Load / create the dictionary objects gdict = cvar.fd_g_config.cnf_dict d_si = gdict.search ( DICT_AVP, AVP_BY_NAME, "Session-Id" ) d_oh = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host" ) d_or = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Realm" ) d_dh = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Host" ) d_dr = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Realm" ) d_rc = gdict.search ( DICT_AVP, AVP_BY_NAME, "Result-Code" ) d_vnd = gdict.new_obj(DICT_VENDOR, dict_vendor_data(999999, "app_test_py vendor") ) d_app = gdict.new_obj(DICT_APPLICATION, dict_application_data(0xffffff, "app_test_py appli"), d_vnd) d_req = gdict.new_obj(DICT_COMMAND, dict_cmd_data(0xfffffe, "Test_py-Request", 1), d_app) d_ans = gdict.new_obj(DICT_COMMAND, dict_cmd_data(0xfffffe, "Test_py-Answer", 0), d_app) d_avp = gdict.new_obj(DICT_AVP, dict_avp_data(0xffffff, "app_test_py avp", AVP_TYPE_INTEGER32, 999999 )) # (skip rules in the example) ###### Server part: def test_app_cb(inmsg, inavp, insession): tval = inmsg.search(d_avp).header().avp_value.u32 print "Py ECHO Test message from '%s' with test value %x, replying..." % (inmsg.search(d_oh).header().avp_value.os.as_str(), tval) answ = inmsg.create_answer() answ.rescode_set() answ.add_origin() ta = avp(d_avp, AVPFL_SET_BLANK_VALUE) ta.header().avp_value.u32 = tval answ.add_child(ta) return [ 0, answ, DISP_ACT_SEND ] # Register the callback for dispatch thread: hdl = disp_hdl(test_app_cb, DISP_HOW_CC, disp_when(d_app, d_req)) # Don't forget to register the application in the daemon for CER/CEA capabilities. fd_disp_app_support ( d_app, d_vnd, 1, 0 ) ###### Client part: def receive_answer(ans, testval): tval = ans.search(d_avp).header().avp_value.u32 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()) del ans return None import random def send_query(destrealm="localdomain"): qry = msg(d_req) sess = session() tv = random.randint(1, 1<<32) # Session-Id a = avp(d_si, AVPFL_SET_BLANK_VALUE) a.header().avp_value.os = sess.getsid() qry.add_child(a) # Destination-Realm a = avp(d_dr, AVPFL_SET_BLANK_VALUE) a.header().avp_value.os = destrealm qry.add_child(a) # Origin-Host, Origin-Realm qry.add_origin() # Test-AVP a = avp(d_avp, AVPFL_SET_BLANK_VALUE) a.header().avp_value.u32 = tv qry.add_child(a) print "Py SEND %x to '%s'" % (tv, destrealm) qry.send(receive_answer, tv) send_query() }}} This is a simplified version without error checking, but it should give a good idea of the simplicity of use of the python interface. == Output == This application does not produce any particular output -- well, all depends on what is done in python. == Troubleshooting ==