| 1 | [[PageOutline(2-4)]] |
| 2 | == Embedded Python interpreter == |
| 3 | |
| 4 | 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. |
| 5 | |
| 6 | 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. |
| 7 | |
| 8 | === Configuration === |
| 9 | |
| 10 | {{{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). |
| 11 | |
| 12 | |
| 13 | === Usage === |
| 14 | |
| 15 | 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: |
| 16 | {{{ |
| 17 | #!python |
| 18 | # Load / create the dictionary objects |
| 19 | gdict = cvar.fd_g_config.cnf_dict |
| 20 | d_si = gdict.search ( DICT_AVP, AVP_BY_NAME, "Session-Id" ) |
| 21 | d_oh = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host" ) |
| 22 | d_or = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Realm" ) |
| 23 | d_dh = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Host" ) |
| 24 | d_dr = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Realm" ) |
| 25 | d_rc = gdict.search ( DICT_AVP, AVP_BY_NAME, "Result-Code" ) |
| 26 | d_vnd = gdict.new_obj(DICT_VENDOR, dict_vendor_data(999999, "app_test_py vendor") ) |
| 27 | d_app = gdict.new_obj(DICT_APPLICATION, dict_application_data(0xffffff, "app_test_py appli"), d_vnd) |
| 28 | d_req = gdict.new_obj(DICT_COMMAND, dict_cmd_data(0xfffffe, "Test_py-Request", 1), d_app) |
| 29 | d_ans = gdict.new_obj(DICT_COMMAND, dict_cmd_data(0xfffffe, "Test_py-Answer", 0), d_app) |
| 30 | d_avp = gdict.new_obj(DICT_AVP, dict_avp_data(0xffffff, "app_test_py avp", AVP_TYPE_INTEGER32, 999999 )) |
| 31 | # (skip rules in the example) |
| 32 | |
| 33 | ###### Server part: |
| 34 | def test_app_cb(inmsg, inavp, insession): |
| 35 | tval = inmsg.search(d_avp).header().avp_value.u32 |
| 36 | print "Py ECHO Test message from '%s' with test value %x, replying..." % (inmsg.search(d_oh).header().avp_value.os.as_str(), tval) |
| 37 | answ = inmsg.create_answer() |
| 38 | answ.rescode_set() |
| 39 | answ.add_origin() |
| 40 | ta = avp(d_avp, AVPFL_SET_BLANK_VALUE) |
| 41 | ta.header().avp_value.u32 = tval |
| 42 | answ.add_child(ta) |
| 43 | return [ 0, answ, DISP_ACT_SEND ] |
| 44 | |
| 45 | # Register the callback for dispatch thread: |
| 46 | hdl = disp_hdl(test_app_cb, DISP_HOW_CC, disp_when(d_app, d_req)) |
| 47 | |
| 48 | # Don't forget to register the application in the daemon for CER/CEA capabilities. |
| 49 | fd_disp_app_support ( d_app, d_vnd, 1, 0 ) |
| 50 | |
| 51 | ###### Client part: |
| 52 | def receive_answer(ans, testval): |
| 53 | tval = ans.search(d_avp).header().avp_value.u32 |
| 54 | 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()) |
| 55 | del ans |
| 56 | return None |
| 57 | |
| 58 | import random |
| 59 | def send_query(destrealm="localdomain"): |
| 60 | qry = msg(d_req) |
| 61 | sess = session() |
| 62 | tv = random.randint(1, 1<<32) |
| 63 | # Session-Id |
| 64 | a = avp(d_si, AVPFL_SET_BLANK_VALUE) |
| 65 | a.header().avp_value.os = sess.getsid() |
| 66 | qry.add_child(a) |
| 67 | # Destination-Realm |
| 68 | a = avp(d_dr, AVPFL_SET_BLANK_VALUE) |
| 69 | a.header().avp_value.os = destrealm |
| 70 | qry.add_child(a) |
| 71 | # Origin-Host, Origin-Realm |
| 72 | qry.add_origin() |
| 73 | # Test-AVP |
| 74 | a = avp(d_avp, AVPFL_SET_BLANK_VALUE) |
| 75 | a.header().avp_value.u32 = tv |
| 76 | qry.add_child(a) |
| 77 | print "Py SEND %x to '%s'" % (tv, destrealm) |
| 78 | qry.send(receive_answer, tv) |
| 79 | |
| 80 | send_query() |
| 81 | }}} |
| 82 | |
| 83 | This is a simplified version without error checking, but it should give a good idea of the simplicity of use of the python interface. |
| 84 | |
| 85 | === Output === |
| 86 | |
| 87 | This application does not produce any particular output -- well, all depends on what is done in python. |
| 88 | |
| 89 | === Troubleshooting === |
| 90 | |
| 91 | |
| 92 | |
| 93 | |
| 94 | |