Navigation


source: freeDiameter/extensions/dbg_interactive/messages.i @ 649:5e5d8152c229

Last change on this file since 649:5e5d8152c229 was 649:5e5d8152c229, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 2 years ago

Implemented fd_msg_send_timeout to close #10. Not tested yet.

File size: 14.1 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2010, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36/* Do not include this directly, use dbg_interactive.i instead */
37
38/****** MESSAGES *********/
39
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        if (l->cb) {
58       
59                SWIG_PYTHON_THREAD_BEGIN_BLOCK;
60
61                if (!msg || !*msg) {
62                        PyMsg = Py_None;
63                } else {
64                        PyMsg = SWIG_NewPointerObj((void *)*msg,     SWIGTYPE_p_msg,     0 );
65                }
66
67                result = PyEval_CallFunction(l->cb, "(OO)", PyMsg, l->data);
68                Py_XDECREF(l->cb);
69                Py_XDECREF(l->data);
70                free(l);
71
72                /* The callback is supposed to return a message or NULL */
73                if (!SWIG_IsOK(SWIG_ConvertPtr(result, (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) {
74                        fd_log_debug("Error: Cannot convert the return value to message.\n");
75                        *msg = NULL;
76                }
77
78                Py_XDECREF(result);
79
80                SWIG_PYTHON_THREAD_END_BLOCK;
81               
82        }
83        /* else */
84                /* Only the timeout was specified, without a callback */
85                /* in this case, just delete the message */
86                /* it actually happens automatically when we do nothing. */
87}
88%}
89
90struct msg {
91};
92
93%extend msg {
94        msg(struct dict_object * model=NULL, int flags = MSGFL_ALLOC_ETEID) {
95                struct msg * m = NULL;
96                int ret = fd_msg_new( model, flags, &m);
97                if (ret != 0) {
98                        DI_ERROR(ret, NULL, NULL);
99                }
100                return m;
101        }
102        /* construct also from a binary buffer */
103        msg(char * STRING, size_t LENGTH) {
104                int ret;
105                struct msg * m = NULL;
106                /* First, copy the string */
107                unsigned char * buf = malloc(LENGTH);
108                if (buf == NULL) {
109                        DI_ERROR_MALLOC;
110                        return NULL;
111                }
112                memcpy(buf, STRING, LENGTH);
113                ret = fd_msg_parse_buffer(&buf, LENGTH, &m);
114                if (ret != 0) {
115                        DI_ERROR(ret, NULL, NULL);
116                        free(buf);
117                        return NULL;
118                }
119                return m;
120        }
121        ~msg() {
122                int ret = fd_msg_free($self);
123                if (ret != 0) {
124                        DI_ERROR(ret, NULL, NULL);
125                }
126        }
127       
128        /* SEND THE MESSAGE */
129        %delobject send; /* when this has been called, the msg must not be freed anymore */
130        void send(PyObject * PyCb = NULL, PyObject * data = NULL, unsigned int timeout = 0) {
131                int ret;
132                struct msg * m = $self;
133                struct anscb_py_layer * l = NULL;
134               
135                if (PyCb || timeout) {
136                        l = malloc(sizeof(struct anscb_py_layer));
137                        if (!l) {
138                                DI_ERROR_MALLOC;
139                                return;
140                        }
141
142                        Py_XINCREF(PyCb);
143                        Py_XINCREF(data);
144                        l->cb = PyCb;
145                        l->data = data;
146                }
147               
148                if (timeout) {
149                        struct timespec ts;
150                        (void) clock_gettime(CLOCK_REALTIME, &ts);
151                        ts.tv_sec += timeout;
152                        ret = fd_msg_send_timeout(&m, anscb_python, l, &ts);
153                } else {
154                        ret = fd_msg_send(&m, PyCb ? anscb_python : NULL, l);
155                }
156                if (ret != 0) {
157                        DI_ERROR(ret, NULL, NULL);
158                }
159        }
160       
161        /* Create an answer */
162        %delobject create_answer; /* when this has been called, the original msg should not be freed anymore */
163        struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) {
164                /* if dict is not provided, attempt to get it from the request model */
165                struct dictionary * d = dict;
166                struct msg * m = $self;
167                int ret;
168                if (!d) {
169                        struct dict_object * mo = NULL;
170                        ret = fd_msg_model($self, &mo);
171                        if (ret != 0) {
172                                DI_ERROR(ret, NULL, "Error retrieving query model.");
173                                return NULL;
174                        }
175                        if (mo == NULL) {
176                                /* use the fD dictionary by default */
177                                d = fd_g_config->cnf_dict;
178                        } else {
179                                ret = fd_dict_getdict ( mo, &d );
180                                if (ret != 0) {
181                                        DI_ERROR(ret, NULL, "Error retrieving query's dictionary.");
182                                        return NULL;
183                                }
184                        }
185                }
186                ret = fd_msg_new_answer_from_req(d, &m, flags);
187                if (ret != 0) {
188                        DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
189                        return NULL;
190                }
191               
192                return m;
193        }
194        /* Return the first child AVP if any */
195        struct avp * first_child() {
196                struct avp * a = NULL;
197                int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
198                if (ret != 0) {
199                        DI_ERROR(ret, NULL, NULL);
200                }
201                return a;
202        }
203       
204        /* Enumerable list of children AVP */
205        %newobject children;
206        PyObject * children() {
207                struct avp * a = NULL;
208                PyObject * rl;
209                int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
210                if (ret != 0) {
211                        DI_ERROR(ret, NULL, NULL);
212                        return NULL;
213                }
214                SWIG_PYTHON_THREAD_BEGIN_BLOCK;
215                rl = PyList_New(0);
216                while (a) {
217                        PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* do not own the AVPs */ ));
218                        ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL);
219                        if (ret != 0) {
220                                DI_ERROR(ret, NULL, NULL);
221                                return NULL;
222                        }
223                }
224                Py_XINCREF(rl);
225                SWIG_PYTHON_THREAD_END_BLOCK;
226                return rl;
227        }
228       
229        /* Add a new AVP */
230        void add_child(struct avp *DISOWN, int begin = 0) {
231                int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN);
232                if (ret != 0) {
233                        DI_ERROR(ret, NULL, NULL);
234                }
235        }
236       
237        /* Search an AVP */
238        struct avp * search(struct dict_object * what) {
239                struct avp * a = NULL;
240                int ret = fd_msg_search_avp($self, what, &a);
241                if (ret != 0) {
242                        DI_ERROR(ret, NULL, NULL);
243                        return NULL;
244                }
245                return a;
246        }
247       
248        /* Dump */
249        void dump (int tree = 1) {
250                if (tree)
251                        fd_msg_dump_walk(0, $self);
252                else
253                        fd_msg_dump_one(0, $self);
254        }
255       
256        /* Model */
257        struct dict_object * model() {
258                struct dict_object * m = NULL;
259                int ret = fd_msg_model($self, &m);
260                if (ret != 0) {
261                        DI_ERROR(ret, NULL, NULL);
262                        return NULL;
263                }
264                return m;
265        }
266       
267        /* Header */
268        struct msg_hdr * header() {
269                struct msg_hdr * h = NULL;
270                int ret = fd_msg_hdr($self, &h);
271                if (ret != 0) {
272                        DI_ERROR(ret, NULL, NULL);
273                        return NULL;
274                }
275                return h;
276        }
277       
278        /* Get query if message is an answer */
279        struct msg * get_query() {
280                struct msg * q = NULL;
281                int ret = fd_msg_answ_getq($self, &q);
282                if (ret != 0) {
283                        DI_ERROR(ret, NULL, NULL);
284                        return NULL;
285                }
286                return q;
287        }
288       
289        /* Get / Set routing data */
290        struct rt_data * get_rtd() {
291                struct rt_data * r = NULL;
292                int ret = fd_msg_rt_get($self, &r);
293                if (ret != 0) {
294                        DI_ERROR(ret, NULL, NULL);
295                        return NULL;
296                }
297                return r;
298        }
299        void set_rtd(struct rt_data *DISOWN) {
300                struct rt_data * r = DISOWN;
301                int ret = fd_msg_rt_associate($self, &r);
302                if (ret != 0) {
303                        DI_ERROR(ret, NULL, NULL);
304                }
305                return;
306        }
307       
308        /* Is routable? */
309        PyObject * is_routable() {
310                PyObject * r;
311                if (fd_msg_is_routable($self))
312                        r = Py_True;
313                else
314                        r = Py_False;
315                Py_XINCREF(r);
316                return r;
317        }
318       
319        /* Is request? (shortcut) */
320        PyObject * is_request() {
321                PyObject * r;
322                int ret;
323                struct msg_hdr * h;
324               
325                ret = fd_msg_hdr($self, &h);
326                if (ret != 0) {
327                        DI_ERROR(ret, NULL, NULL);
328                }
329                if (h->msg_flags & CMD_FLAG_REQUEST)
330                        r = Py_True;
331                else
332                        r = Py_False;
333                Py_XINCREF(r);
334                return r;
335        }
336       
337        /* Get the source */
338        char *source() {
339                char * s = NULL;
340                int ret = fd_msg_source_get($self, &s);
341                if (ret != 0) {
342                        DI_ERROR(ret, NULL, NULL);
343                        return NULL;
344                }
345                return s;
346        }
347       
348        /* Get the session */
349        %newobject get_session; /* it may be created or not, it is harmless because we only reclaim in ~session */
350        struct session *get_session(struct dictionary * dict = NULL) {
351                struct session *s = NULL;
352                struct dictionary * d = dict;
353                int ret = 0;
354                if (d == NULL)
355                        d = fd_g_config->cnf_dict; /* default: use daemon's */
356                ret = fd_msg_sess_get(d, $self, &s, NULL);
357                if (ret != 0) {
358                        DI_ERROR(ret, NULL, NULL);
359                        return NULL;
360                }
361                return s;
362        }
363       
364        /* Bufferize */
365        %cstring_output_allocate_size(char ** outbuffer, size_t * outlen, free(*$1));
366        void bufferize ( char ** outbuffer, size_t * outlen ) {
367                int ret = fd_msg_bufferize ( $self, (void *)outbuffer, outlen );
368                if (ret != 0) {
369                        DI_ERROR(ret, NULL, NULL);
370                }
371        }
372       
373        /* Dictionary parsing */
374        %newobject parse_dict;
375        struct fd_pei * parse_dict(struct dictionary * dict=NULL) {
376                int ret;
377                struct fd_pei pei, *e = NULL;
378                struct dictionary * d = dict;
379                memset(&pei, 0, sizeof(struct fd_pei));
380                if (d == NULL)
381                        d = fd_g_config->cnf_dict; /* default: use daemon's */
382               
383                ret = fd_msg_parse_dict ( $self, d, &pei );
384                if (ret != 0) {
385                        e = malloc(sizeof(struct fd_pei));
386                        if (!e) {
387                                DI_ERROR_MALLOC;
388                                return NULL;
389                        }
390                        memcpy(e, &pei, sizeof(struct fd_pei));
391                }
392                return e; /* returns NULL when everything went OK */
393        }
394       
395        /* Rules parsing */
396        %newobject parse_rules;
397        struct fd_pei * parse_rules(struct dictionary * dict=NULL) {
398                int ret;
399                struct fd_pei pei, *e = NULL;
400                struct dictionary * d = dict;
401                memset(&pei, 0, sizeof(struct fd_pei));
402                if (d == NULL)
403                        d = fd_g_config->cnf_dict; /* default: use daemon's */
404               
405                ret = fd_msg_parse_rules ( $self, d, &pei );
406                if (ret != 0) {
407                        e = malloc(sizeof(struct fd_pei));
408                        if (!e) {
409                                DI_ERROR_MALLOC;
410                                return NULL;
411                        }
412                        memcpy(e, &pei, sizeof(struct fd_pei));
413                }
414                return e; /* returns NULL when everything went OK */
415        }
416       
417        /* Update the length info in header */
418        void update_length() {
419                int ret = fd_msg_update_length ( $self );
420                if (ret) {
421                        DI_ERROR(ret, NULL, NULL);
422                }
423        }
424       
425        /* Set the result code */
426        void rescode_set(char * rescode = "DIAMETER_SUCCESS", char * errormsg = NULL, struct avp * optavp = NULL, int type_id = 0) {
427                int ret = fd_msg_rescode_set( $self, rescode, errormsg, optavp, type_id );
428                if (ret) {
429                        DI_ERROR(ret, NULL, NULL);
430                }
431        }
432       
433        /* Add the origin */
434        void add_origin(int osi = 0) {
435                int ret = fd_msg_add_origin( $self, osi );
436                if (ret) {
437                        DI_ERROR(ret, NULL, NULL);
438                }
439        }
440       
441}
442
443struct avp {
444};
445
446%extend avp {
447        avp(struct dict_object * model = NULL, int flags = 0) {
448                struct avp * a = NULL;
449                int ret = fd_msg_avp_new( model, flags, &a);
450                if (ret != 0) {
451                        DI_ERROR(ret, NULL, NULL);
452                }
453                return a;
454        }
455        ~avp() {
456                int ret = fd_msg_free($self);
457                if (ret != 0) {
458                        DI_ERROR(ret, NULL, NULL);
459                }
460        }
461       
462        /* Return the first child AVP if any */
463        struct avp * first_child() {
464                struct avp * a = NULL;
465                int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
466                if (ret != 0) {
467                        DI_ERROR(ret, NULL, NULL);
468                }
469                return a;
470        }
471       
472        /* Enumerable list of children AVP */
473        %newobject children;
474        PyObject * children() {
475                struct avp * a = NULL;
476                PyObject * rl;
477                int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
478                if (ret != 0) {
479                        DI_ERROR(ret, NULL, NULL);
480                        return NULL;
481                }
482                SWIG_PYTHON_THREAD_BEGIN_BLOCK;
483                rl = PyList_New(0);
484                while (a) {
485                        PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* the AVPs are not owned */ ));
486                        ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL);
487                        if (ret != 0) {
488                                DI_ERROR(ret, NULL, NULL);
489                                return NULL;
490                        }
491                }
492                Py_XINCREF(rl);
493                SWIG_PYTHON_THREAD_END_BLOCK;
494                return rl;
495        }
496       
497        /* Add a new AVP */
498        void add_next(struct avp *avp) {
499                int ret = fd_msg_avp_add ( $self, MSG_BRW_NEXT, avp);
500                if (ret != 0) {
501                        DI_ERROR(ret, NULL, NULL);
502                }
503        }
504        void add_prev(struct avp *avp) {
505                int ret = fd_msg_avp_add ( $self, MSG_BRW_PREV, avp);
506                if (ret != 0) {
507                        DI_ERROR(ret, NULL, NULL);
508                }
509        }
510        void add_child(struct avp *DISOWN, int begin = 0) {
511                int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN);
512                if (ret != 0) {
513                        DI_ERROR(ret, NULL, NULL);
514                }
515        }
516       
517        /* Get the next AVP at the same level */
518        struct avp * get_next() {
519                struct avp * a = NULL;
520                int ret = fd_msg_browse($self, MSG_BRW_NEXT, &a, NULL);
521                if (ret != 0) {
522                        DI_ERROR(ret, NULL, NULL);
523                }
524                return a;
525        }
526       
527        /* Dump */
528        void dump (int tree = 1) {
529                if (tree)
530                        fd_msg_dump_walk(0, $self);
531                else
532                        fd_msg_dump_one(0, $self);
533        }
534       
535        /* Model */
536        struct dict_object * model() {
537                struct dict_object * m = NULL;
538                int ret = fd_msg_model($self, &m);
539                if (ret != 0) {
540                        DI_ERROR(ret, NULL, NULL);
541                        return NULL;
542                }
543                return m;
544        }
545       
546        /* Header */
547        struct avp_hdr * header() {
548                struct avp_hdr * h = NULL;
549                int ret = fd_msg_avp_hdr($self, &h);
550                if (ret != 0) {
551                        DI_ERROR(ret, NULL, NULL);
552                        return NULL;
553                }
554                return h;
555        }
556       
557        /* set value */
558        void setval(union avp_value * val) {
559                int ret = fd_msg_avp_setvalue ( $self, val );
560                if (ret != 0) {
561                        DI_ERROR(ret, NULL, NULL);
562                }
563        }
564       
565        /* Update the length info in header */
566        void update_length() {
567                int ret = fd_msg_update_length ( $self );
568                if (ret) {
569                        DI_ERROR(ret, NULL, NULL);
570                }
571        }
572}
Note: See TracBrowser for help on using the repository browser.