3b54ade33d0f55094ee66849f6fda70e20cf44b7
[sip-router] / modules / app_python / python_msgobj.c
1 /* $Id$
2  *
3  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
4  *
5  * This file is part of SIP-Router, a free SIP server.
6  *
7  * SIP-Router is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * SIP-Router is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21 */
22
23 #include "../../action.h"
24 #include "../../mem/mem.h"
25 #include "../../sr_module.h"
26 #include "../../parser/msg_parser.h"
27
28 #include <Python.h>
29 #include "structmember.h"
30
31 #ifndef Py_TYPE
32 #define Py_TYPE(ob)               (((PyObject*)(ob))->ob_type)
33 #endif
34
35 typedef struct {
36     PyObject_HEAD
37     struct sip_msg *msg;
38 } msgobject;
39
40 static PyTypeObject MSGtype;
41
42 #define is_msgobject(v)         ((v)->ob_type == &MSGtype)
43
44 msgobject *
45 newmsgobject(struct sip_msg *msg)
46 {
47     msgobject *msgp;
48
49     msgp = PyObject_New(msgobject, &MSGtype);
50     if (msgp == NULL)
51         return NULL;
52
53     msgp->msg = msg;
54     return msgp;
55 }
56
57 void
58 msg_invalidate(msgobject *self)
59 {
60
61     self->msg = NULL;
62 }
63
64 static void
65 msg_dealloc(msgobject *msgp)
66 {
67
68     PyObject_Del(msgp);
69 }
70
71 static PyObject *
72 msg_copy(msgobject *self)
73 {
74     msgobject *msgp;
75
76     if ((msgp = newmsgobject(self->msg)) == NULL)
77         return NULL;
78
79     return (PyObject *)msgp;
80 }
81
82 static PyObject *
83 msg_rewrite_ruri(msgobject *self, PyObject *args)
84 {
85     char *ruri;
86     struct action act;
87     struct run_act_ctx ra_ctx;
88
89     if (self->msg == NULL) {
90         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
91         Py_INCREF(Py_None);
92         return Py_None;
93     }
94
95     if ((self->msg->first_line).type != SIP_REQUEST) {
96         PyErr_SetString(PyExc_RuntimeError, "Not a request message - "
97           "rewrite is not possible.\n");
98         Py_INCREF(Py_None);
99         return Py_None;
100     }
101
102     if(!PyArg_ParseTuple(args, "s:rewrite_ruri", &ruri))
103         return NULL;
104
105     memset(&act, '\0', sizeof(act));
106
107     act.type = SET_URI_T;
108     act.val[0].type = STR_ST;
109     act.val[0].u.str.s = ruri;
110     act.val[0].u.str.len = strlen(ruri);
111
112     init_run_actions_ctx(&ra_ctx);
113     if (do_action(&ra_ctx, &act, self->msg) < 0) {
114         LM_ERR("Error in do_action\n");
115         PyErr_SetString(PyExc_RuntimeError, "Error in do_action\n");
116     }
117
118     Py_INCREF(Py_None);
119     return Py_None;
120 }
121
122 static PyObject *
123 msg_set_dst_uri(msgobject *self, PyObject *args)
124 {
125     str ruri;
126
127     if (self->msg == NULL) {
128         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
129         Py_INCREF(Py_None);
130         return Py_None;
131     }
132
133     if ((self->msg->first_line).type != SIP_REQUEST) {
134         PyErr_SetString(PyExc_RuntimeError, "Not a request message - "
135           "set destination is not possible.\n");
136         Py_INCREF(Py_None);
137         return Py_None;
138     }
139
140     if(!PyArg_ParseTuple(args, "s:set_dst_uri", &ruri.s))
141         return NULL;
142
143     ruri.len = strlen(ruri.s);
144
145     if (set_dst_uri(self->msg, &ruri) < 0) {
146         LM_ERR("Error in set_dst_uri\n");
147         PyErr_SetString(PyExc_RuntimeError, "Error in set_dst_uri\n");
148     }
149
150     Py_INCREF(Py_None);
151     return Py_None;
152 }
153
154 static PyObject *
155 msg_getHeader(msgobject *self, PyObject *args)
156 {
157     struct hdr_field *hf;
158     str hname, *hbody;
159
160     if (self->msg == NULL) {
161         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
162         Py_INCREF(Py_None);
163         return Py_None;
164     }
165
166     if(!PyArg_ParseTuple(args, "s:getHeader", &hname.s))
167         return NULL;
168     hname.len = strlen(hname.s);
169
170     parse_headers(self->msg, ~0, 0);
171     hbody = NULL;
172     for (hf = self->msg->headers; hf != NULL; hf = hf->next) {
173         if (hname.len == hf->name.len &&
174           strncasecmp(hname.s, hf->name.s, hname.len) == 0) {
175             hbody = &(hf->body);
176             break;
177         }
178     }
179
180     if (hbody == NULL) {
181         Py_INCREF(Py_None);
182         return Py_None;
183     }
184
185     return PyString_FromStringAndSize(hbody->s, hbody->len);
186 }
187
188 static PyObject *
189 msg_call_function(msgobject *self, PyObject *args)
190 {
191     int i, rval;
192     char *fname, *arg1, *arg2;
193     union cmd_export_u* fexport;
194     struct action *act;
195     action_u_t elems[MAX_ACTIONS];
196     struct run_act_ctx ra_ctx;
197     unsigned mod_ver;
198
199     if (self->msg == NULL) {
200         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
201         Py_INCREF(Py_None);
202         return Py_None;
203     }
204
205     i = PySequence_Size(args);
206     if (i < 1 || i > 3) {
207         PyErr_SetString(PyExc_RuntimeError, "call_function() should " \
208           "have from 1 to 3 arguments");
209         Py_INCREF(Py_None);
210         return Py_None;
211     }
212
213     if(!PyArg_ParseTuple(args, "s|ss:call_function", &fname, &arg1, &arg2))
214         return NULL;
215
216     fexport = find_export_record(fname, i - 2, 0, &mod_ver);
217     if (fexport == NULL) {
218         PyErr_SetString(PyExc_RuntimeError, "no such function");
219         Py_INCREF(Py_None);
220         return Py_None;
221     }
222
223     elems[0].type = MODEXP_ST;
224     elems[0].u.data = fexport;
225     elems[1].type = STRING_ST;
226     elems[1].u.data = arg1;
227     elems[2].type = STRING_ST;
228     elems[2].u.data = arg2;
229     act = mk_action(MODULE_T, 3, elems, 0);
230
231     if (act == NULL) {
232         PyErr_SetString(PyExc_RuntimeError,
233           "action structure could not be created");
234         Py_INCREF(Py_None);
235         return Py_None;
236     }
237
238     if (fexport->v1.fixup != NULL) {
239         if (i >= 3) {
240             rval = fexport->v1.fixup(&(act->val[2].u.data), 2);
241             if (rval < 0) {
242                 PyErr_SetString(PyExc_RuntimeError, "Error in fixup (2)");
243                 Py_INCREF(Py_None);
244                 return Py_None;
245             }
246             act->val[2].type = MODFIXUP_ST;
247         }
248         if (i >= 2) {
249             rval = fexport->v1.fixup(&(act->val[1].u.data), 1);
250             if (rval < 0) {
251                 PyErr_SetString(PyExc_RuntimeError, "Error in fixup (1)");
252                 Py_INCREF(Py_None);
253                 return Py_None;
254             }
255             act->val[1].type = MODFIXUP_ST;
256         }
257         if (i == 1) {
258             rval = fexport->v1.fixup(0, 0);
259             if (rval < 0) {
260                 PyErr_SetString(PyExc_RuntimeError, "Error in fixup (0)");
261                 Py_INCREF(Py_None);
262                 return Py_None;
263             }
264         }
265     }
266
267     init_run_actions_ctx(&ra_ctx);
268     rval = do_action(&ra_ctx, act, self->msg);
269
270     if ((act->val[2].type == MODFIXUP_ST) && (act->val[2].u.data)) {
271        pkg_free(act->val[2].u.data);
272     }
273
274     if ((act->val[1].type == MODFIXUP_ST) && (act->val[1].u.data)) {
275         pkg_free(act->val[1].u.data);
276     }
277
278     pkg_free(act);
279
280     return PyInt_FromLong(rval);
281 }
282
283 PyDoc_STRVAR(copy_doc,
284 "copy() -> msg object\n\
285 \n\
286 Return a copy (``clone'') of the msg object.");
287
288 static PyMethodDef msg_methods[] = {
289     {"copy",          (PyCFunction)msg_copy,          METH_NOARGS,  copy_doc},
290     {"rewrite_ruri",  (PyCFunction)msg_rewrite_ruri,  METH_VARARGS,
291       "Rewrite Request-URI."},
292     {"set_dst_uri",   (PyCFunction)msg_set_dst_uri,   METH_VARARGS,
293       "Set destination URI."},
294     {"getHeader",     (PyCFunction)msg_getHeader,     METH_VARARGS,
295       "Get SIP header field by name."},
296     {"call_function", (PyCFunction)msg_call_function, METH_VARARGS,
297       "Invoke function exported by the other module."},
298     {NULL, NULL, 0, NULL}                              /* sentinel */
299 };
300
301 static PyObject *
302 msg_getType(msgobject *self, PyObject *unused)
303 {
304     const char *rval;
305
306     if (self->msg == NULL) {
307         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
308         Py_INCREF(Py_None);
309         return Py_None;
310     }
311
312     switch ((self->msg->first_line).type) {
313     case SIP_REQUEST:
314        rval = "SIP_REQUEST";
315        break;
316
317     case SIP_REPLY:
318        rval = "SIP_REPLY";
319        break;
320
321     default:
322        /* Shouldn't happen */
323        abort();
324     }
325     return PyString_FromString(rval);
326 }
327
328 static PyObject *
329 msg_getMethod(msgobject *self, PyObject *unused)
330 {
331     str *rval;
332
333     if (self->msg == NULL) {
334         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
335         Py_INCREF(Py_None);
336         return Py_None;
337     }
338
339     if ((self->msg->first_line).type != SIP_REQUEST) {
340         PyErr_SetString(PyExc_RuntimeError, "Not a request message - "
341           "no method available.\n");
342         Py_INCREF(Py_None);
343         return Py_None;
344     }
345     rval = &((self->msg->first_line).u.request.method);
346     return PyString_FromStringAndSize(rval->s, rval->len);
347 }
348
349 static PyObject *
350 msg_getStatus(msgobject *self, PyObject *unused)
351 {
352     str *rval;
353
354     if (self->msg == NULL) {
355         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
356         Py_INCREF(Py_None);
357         return Py_None;
358     }
359
360     if ((self->msg->first_line).type != SIP_REPLY) {
361         PyErr_SetString(PyExc_RuntimeError, "Not a non-reply message - "
362           "no status available.\n");
363         Py_INCREF(Py_None);
364         return Py_None;
365     }
366
367     rval = &((self->msg->first_line).u.reply.status);
368     return PyString_FromStringAndSize(rval->s, rval->len);
369 }
370
371 static PyObject *
372 msg_getRURI(msgobject *self, PyObject *unused)
373 {
374     str *rval;
375
376     if (self->msg == NULL) {
377         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
378         Py_INCREF(Py_None);
379         return Py_None;
380     }
381
382     if ((self->msg->first_line).type != SIP_REQUEST) {
383         PyErr_SetString(PyExc_RuntimeError, "Not a request message - "
384           "RURI is not available.\n");
385         Py_INCREF(Py_None);
386         return Py_None;
387     }
388
389     rval = &((self->msg->first_line).u.request.uri);
390     return PyString_FromStringAndSize(rval->s, rval->len);
391 }
392
393 static PyObject *
394 msg_get_src_address(msgobject *self, PyObject *unused)
395 {
396     PyObject *src_ip, *src_port, *pyRval;
397
398     if (self->msg == NULL) {
399         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
400         Py_INCREF(Py_None);
401         return Py_None;
402     }
403
404     src_ip = PyString_FromString(ip_addr2a(&self->msg->rcv.src_ip));
405     if (src_ip == NULL) {
406         Py_INCREF(Py_None);
407         return Py_None;
408     }
409
410     src_port = PyInt_FromLong(self->msg->rcv.src_port);
411     if (src_port == NULL) {
412         Py_DECREF(src_ip);
413         Py_INCREF(Py_None);
414         return Py_None;
415     }
416
417     pyRval = PyTuple_Pack(2, src_ip, src_port);
418     Py_DECREF(src_ip);
419     Py_DECREF(src_port);
420     if (pyRval == NULL) {
421         Py_INCREF(Py_None);
422         return Py_None;
423     }
424
425     return pyRval;
426 }
427
428 static PyObject *
429 msg_get_dst_address(msgobject *self, PyObject *unused)
430 {
431     PyObject *dst_ip, *dst_port, *pyRval;
432
433     if (self->msg == NULL) {
434         PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
435         Py_INCREF(Py_None);
436         return Py_None;
437     }
438
439     dst_ip = PyString_FromString(ip_addr2a(&self->msg->rcv.dst_ip));
440     if (dst_ip == NULL) {
441         Py_INCREF(Py_None);
442         return Py_None;
443     }
444
445     dst_port = PyInt_FromLong(self->msg->rcv.dst_port);
446     if (dst_port == NULL) {
447         Py_DECREF(dst_ip);
448         Py_INCREF(Py_None);
449         return Py_None;
450     }
451
452     pyRval = PyTuple_Pack(2, dst_ip, dst_port);
453     Py_DECREF(dst_ip);
454     Py_DECREF(dst_port);
455     if (pyRval == NULL) {
456         Py_INCREF(Py_None);
457         return Py_None;
458     }
459
460     return pyRval;
461 }
462
463 static PyGetSetDef msg_getseters[] = {
464     {"Type",
465      (getter)msg_getType, NULL, NULL,
466      "Get message type - \"SIP_REQUEST\" or \"SIP_REPLY\"."},
467     {"Method",
468      (getter)msg_getMethod, NULL, NULL,
469      "Get SIP method name."},
470     {"Status",
471      (getter)msg_getStatus, NULL, NULL,
472      "Get SIP status code string."},
473     {"RURI",
474      (getter)msg_getRURI, NULL, NULL,
475      "Get SIP Request-URI."},
476     {"src_address",
477      (getter)msg_get_src_address, NULL, NULL,
478      "Get (IP, port) tuple representing source address of the message."},
479     {"dst_address",
480      (getter)msg_get_dst_address, NULL, NULL,
481      "Get (IP, port) tuple representing destination address of the message."},
482     {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
483 };
484
485 static PyTypeObject MSGtype = {
486 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6
487     PyVarObject_HEAD_INIT(NULL, 0)
488 #else
489     PyObject_HEAD_INIT(NULL)
490     0,                        /*ob_size*/
491 #endif
492     "Router.msg",             /*tp_name*/
493     sizeof(msgobject),        /*tp_size*/
494     0,                        /*tp_itemsize*/
495     /* methods */
496     (destructor)msg_dealloc,  /*tp_dealloc*/
497     0,                        /*tp_print*/
498     0,                        /*tp_getattr*/
499     0,                        /*tp_setattr*/
500     0,                        /*tp_compare*/
501     0,                        /*tp_repr*/
502     0,                        /*tp_as_number*/
503     0,                        /*tp_as_sequence*/
504     0,                        /*tp_as_mapping*/
505     0,                        /*tp_hash*/
506     0,                        /*tp_call*/
507     0,                        /*tp_str*/
508     0,                        /*tp_getattro*/
509     0,                        /*tp_setattro*/
510     0,                        /*tp_as_buffer*/
511     Py_TPFLAGS_DEFAULT,       /*tp_flags*/
512     0,                        /*tp_doc*/
513     0,                        /*tp_traverse*/
514     0,                        /*tp_clear*/
515     0,                        /*tp_richcompare*/
516     0,                        /*tp_weaklistoffset*/
517     0,                        /*tp_iter*/
518     0,                        /*tp_iternext*/
519     msg_methods,              /*tp_methods*/
520     0,                        /*tp_members*/
521     msg_getseters,            /*tp_getset*/
522 };
523
524 int
525 python_msgobj_init(void)
526 {
527
528     Py_TYPE(&MSGtype) = &PyType_Type;
529     if (PyType_Ready(&MSGtype) < 0)
530         return -1;
531     return 0;
532 }