Mercurial > hg > freeDiameter
view extensions/dbg_interactive/messages.i @ 1562:6219359a36a9 default tip
Merge latest changes from proposed branch
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Mon, 21 Jun 2021 19:08:18 +0800 |
parents | c38bb8b69c43 |
children |
line wrap: on
line source
/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis <sdecugis@freediameter.net> * * * * Copyright (c) 2013, WIDE Project and NICT * * All rights reserved. * * * * Redistribution and use of this software in source and binary forms, with or without modification, are * * permitted provided that the following conditions are met: * * * * * Redistributions of source code must retain the above * * copyright notice, this list of conditions and the * * following disclaimer. * * * * * Redistributions in binary form must reproduce the above * * copyright notice, this list of conditions and the * * following disclaimer in the documentation and/or other * * materials provided with the distribution. * * * * * Neither the name of the WIDE Project or NICT nor the * * names of its contributors may be used to endorse or * * promote products derived from this software without * * specific prior written permission of WIDE Project and * * NICT. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *********************************************************************************************************/ /* Do not include this directly, use dbg_interactive.i instead */ /****** MESSAGES *********/ %{ struct anscb_py_layer { PyObject * cb; PyObject * expcb; PyObject * data; }; /* If a python callback was provided, it is received in cbdata */ static void anscb_python(void *cbdata, struct msg ** msg) { /* The python callback is received in cbdata */ PyObject * result, *PyMsg; struct anscb_py_layer * l = cbdata; if (!l) { fd_log_debug("Internal error! Python callback disappeared..."); return; } if (l->cb) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (!msg || !*msg) { PyMsg = Py_None; } else { PyMsg = SWIG_NewPointerObj((void *)*msg, SWIGTYPE_p_msg, 0 ); } result = PyObject_CallFunction(l->cb, "(OO)", PyMsg, l->data); Py_XDECREF(l->cb); Py_XDECREF(l->expcb); Py_XDECREF(l->data); free(l); /* The callback is supposed to return a message or NULL */ if (!SWIG_IsOK(SWIG_ConvertPtr(result, (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) { fd_log_debug("Error: Cannot convert the return value to message."); *msg = NULL; } Py_XDECREF(result); SWIG_PYTHON_THREAD_END_BLOCK; } /* else */ /* Only the timeout was specified, without a callback */ /* in this case, just delete the message */ /* it actually happens automatically when we do nothing. */ } static void expcb_python(void *cbdata, DiamId_t sentto, size_t senttolen, struct msg ** msg) { /* The python callback is received in cbdata */ PyObject * result, *PyMsg; struct anscb_py_layer * l = cbdata; if (!l) { fd_log_debug("Internal error! Python callback disappeared..."); return; } SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (!msg || !*msg) { PyMsg = Py_None; } else { PyMsg = SWIG_NewPointerObj((void *)*msg, SWIGTYPE_p_msg, 0 ); } result = PyObject_CallFunction(l->expcb, "(Os#O)", PyMsg, sentto, senttolen, l->data); Py_XDECREF(l->cb); Py_XDECREF(l->expcb); Py_XDECREF(l->data); free(l); /* The callback is supposed to return a message or NULL */ if (!SWIG_IsOK(SWIG_ConvertPtr(result, (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) { fd_log_debug("Error: Cannot convert the return value to message."); *msg = NULL; } Py_XDECREF(result); SWIG_PYTHON_THREAD_END_BLOCK; } %} struct msg { }; %extend msg { msg(struct dict_object * model=NULL, int flags = MSGFL_ALLOC_ETEID) { struct msg * m = NULL; int ret = fd_msg_new( model, flags, &m); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } return m; } /* construct also from a binary buffer */ msg(char * STRING, size_t LENGTH) { int ret; struct msg * m = NULL; /* First, copy the string */ unsigned char * buf = malloc(LENGTH); if (buf == NULL) { DI_ERROR_MALLOC; return NULL; } memcpy(buf, STRING, LENGTH); ret = fd_msg_parse_buffer(&buf, LENGTH, &m); if (ret != 0) { DI_ERROR(ret, NULL, NULL); free(buf); return NULL; } return m; } ~msg() { int ret = fd_msg_free($self); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* SEND THE MESSAGE */ %delobject send; /* when this has been called, the msg must not be freed anymore */ void send(PyObject * PyCb = NULL, PyObject * data = NULL, PyObject * PyExpCb = NULL, unsigned int timeout = 0) { int ret; struct msg * m = $self; struct anscb_py_layer * l = NULL; if (PyCb || timeout) { l = malloc(sizeof(struct anscb_py_layer)); if (!l) { DI_ERROR_MALLOC; return; } Py_XINCREF(PyCb); Py_XINCREF(data); Py_XINCREF(PyExpCb); l->expcb = PyExpCb; l->cb = PyCb; l->data = data; } if (timeout) { struct timespec ts; (void) clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += timeout; ret = fd_msg_send_timeout(&m, anscb_python, l, expcb_python, &ts); } else { ret = fd_msg_send(&m, PyCb ? anscb_python : NULL, l); } if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* Create an answer */ %delobject create_answer; /* when this has been called, the original msg should not be freed anymore */ struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) { /* if dict is not provided, attempt to get it from the request model */ struct dictionary * d = dict; struct msg * m = $self; int ret; if (!d) { struct dict_object * mo = NULL; ret = fd_msg_model($self, &mo); if (ret != 0) { DI_ERROR(ret, NULL, "Error retrieving query model."); return NULL; } if (mo == NULL) { /* use the fD dictionary by default */ d = fd_g_config->cnf_dict; } else { ret = fd_dict_getdict ( mo, &d ); if (ret != 0) { DI_ERROR(ret, NULL, "Error retrieving query's dictionary."); return NULL; } } } ret = fd_msg_new_answer_from_req(d, &m, flags); if (ret != 0) { DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter."); return NULL; } return m; } /* Return the first child AVP if any */ struct avp * first_child() { struct avp * a = NULL; int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } return a; } /* Enumerable list of children AVP */ %newobject children; PyObject * children() { struct avp * a = NULL; PyObject * rl; int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } SWIG_PYTHON_THREAD_BEGIN_BLOCK; rl = PyList_New(0); while (a) { PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* do not own the AVPs */ )); ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } } Py_XINCREF(rl); SWIG_PYTHON_THREAD_END_BLOCK; return rl; } /* Add a new AVP */ void add_child(struct avp *DISOWN, int begin = 0) { int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* Search an AVP */ struct avp * search(struct dict_object * what) { struct avp * a = NULL; int ret = fd_msg_search_avp($self, what, &a); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return a; } /* Dump */ void dump (int tree = 1) { char * buf = NULL; size_t len; printf("%s", fd_msg_dump_treeview(&buf, &len, NULL, $self, NULL, 0, tree)); free(buf); } /* Model */ struct dict_object * model() { struct dict_object * m = NULL; int ret = fd_msg_model($self, &m); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return m; } /* Header */ struct msg_hdr * header() { struct msg_hdr * h = NULL; int ret = fd_msg_hdr($self, &h); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return h; } /* Get query if message is an answer */ struct msg * get_query() { struct msg * q = NULL; int ret = fd_msg_answ_getq($self, &q); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return q; } /* Get / Set routing data */ struct rt_data * get_rtd() { struct rt_data * r = NULL; int ret = fd_msg_rt_get($self, &r); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return r; } void set_rtd(struct rt_data *DISOWN) { struct rt_data * r = DISOWN; int ret = fd_msg_rt_associate($self, r); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } return; } /* Is routable? */ PyObject * is_routable() { PyObject * r; if (fd_msg_is_routable($self)) r = Py_True; else r = Py_False; Py_XINCREF(r); return r; } /* Is request? (shortcut) */ PyObject * is_request() { PyObject * r; int ret; struct msg_hdr * h; ret = fd_msg_hdr($self, &h); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } if (h->msg_flags & CMD_FLAG_REQUEST) r = Py_True; else r = Py_False; Py_XINCREF(r); return r; } /* Get the source */ %cstring_output_allocate_size(char ** outid, size_t * outlen, /* do not free */); void source(char ** outid, size_t * outlen) { int ret = fd_msg_source_get($self, outid, outlen); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return; } return; } /* Get the session */ %newobject get_session; /* it may be created or not, it is harmless because we only reclaim in ~session */ struct session *get_session(struct dictionary * dict = NULL) { struct session *s = NULL; struct dictionary * d = dict; int ret = 0; if (d == NULL) d = fd_g_config->cnf_dict; /* default: use daemon's */ ret = fd_msg_sess_get(d, $self, &s, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return s; } /* Bufferize */ %cstring_output_allocate_size(char ** outbuffer, size_t * outlen, free(*$1)); void bufferize ( char ** outbuffer, size_t * outlen ) { int ret = fd_msg_bufferize ( $self, (void *)outbuffer, outlen ); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* Dictionary parsing */ %newobject parse_dict; struct fd_pei * parse_dict(struct dictionary * dict=NULL) { int ret; struct fd_pei pei, *e = NULL; struct dictionary * d = dict; memset(&pei, 0, sizeof(struct fd_pei)); if (d == NULL) d = fd_g_config->cnf_dict; /* default: use daemon's */ ret = fd_msg_parse_dict ( $self, d, &pei ); if (ret != 0) { e = malloc(sizeof(struct fd_pei)); if (!e) { DI_ERROR_MALLOC; return NULL; } memcpy(e, &pei, sizeof(struct fd_pei)); } return e; /* returns NULL when everything went OK */ } /* Rules parsing */ %newobject parse_rules; struct fd_pei * parse_rules(struct dictionary * dict=NULL) { int ret; struct fd_pei pei, *e = NULL; struct dictionary * d = dict; memset(&pei, 0, sizeof(struct fd_pei)); if (d == NULL) d = fd_g_config->cnf_dict; /* default: use daemon's */ ret = fd_msg_parse_rules ( $self, d, &pei ); if (ret != 0) { e = malloc(sizeof(struct fd_pei)); if (!e) { DI_ERROR_MALLOC; return NULL; } memcpy(e, &pei, sizeof(struct fd_pei)); } return e; /* returns NULL when everything went OK */ } /* Update the length info in header */ void update_length() { int ret = fd_msg_update_length ( $self ); if (ret) { DI_ERROR(ret, NULL, NULL); } } /* Set the result code */ void rescode_set(char * rescode = "DIAMETER_SUCCESS", char * errormsg = NULL, struct avp * optavp = NULL, int type_id = 0) { int ret = fd_msg_rescode_set( $self, rescode, errormsg, optavp, type_id ); if (ret) { DI_ERROR(ret, NULL, NULL); } } /* Add the origin */ void add_origin(int osi = 0) { int ret = fd_msg_add_origin( $self, osi ); if (ret) { DI_ERROR(ret, NULL, NULL); } } } struct avp { }; %extend avp { avp(struct dict_object * model = NULL, int flags = 0) { struct avp * a = NULL; int ret = fd_msg_avp_new( model, flags, &a); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } return a; } ~avp() { int ret = fd_msg_free($self); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* Return the first child AVP if any */ struct avp * first_child() { struct avp * a = NULL; int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } return a; } /* Enumerable list of children AVP */ %newobject children; PyObject * children() { struct avp * a = NULL; PyObject * rl; int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } SWIG_PYTHON_THREAD_BEGIN_BLOCK; rl = PyList_New(0); while (a) { PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* the AVPs are not owned */ )); ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } } Py_XINCREF(rl); SWIG_PYTHON_THREAD_END_BLOCK; return rl; } /* Add a new AVP */ void add_next(struct avp *avp) { int ret = fd_msg_avp_add ( $self, MSG_BRW_NEXT, avp); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } void add_prev(struct avp *avp) { int ret = fd_msg_avp_add ( $self, MSG_BRW_PREV, avp); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } void add_child(struct avp *DISOWN, int begin = 0) { int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* Get the next AVP at the same level */ struct avp * get_next() { struct avp * a = NULL; int ret = fd_msg_browse($self, MSG_BRW_NEXT, &a, NULL); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } return a; } /* Dump */ void dump (int tree = 1) { char * buf = NULL; size_t len; printf("%s", fd_msg_dump_treeview(&buf, &len, NULL, $self, NULL, 0, tree)); free(buf); } /* Model */ struct dict_object * model() { struct dict_object * m = NULL; int ret = fd_msg_model($self, &m); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return m; } /* Header */ struct avp_hdr * header() { struct avp_hdr * h = NULL; int ret = fd_msg_avp_hdr($self, &h); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } return h; } /* set value */ void setval(union avp_value * val) { int ret = fd_msg_avp_setvalue ( $self, val ); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } } /* Update the length info in header */ void update_length() { int ret = fd_msg_update_length ( $self ); if (ret) { DI_ERROR(ret, NULL, NULL); } } }