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