Browse code

app_python3: updated to the new mod interface

Daniel-Constantin Mierla authored on 27/09/2018 21:54:04 • Victor Seva committed on 28/09/2018 11:03:26
Showing 1 changed files
... ...
@@ -185,10 +185,9 @@ PyObject *msg_call_function(msgobject *self, PyObject *args)
185 185
 {
186 186
 	int i, rval;
187 187
 	char *fname, *arg1, *arg2;
188
-	sr31_cmd_export_t* fexport;
188
+	ksr_cmd_export_t* fexport;
189 189
 	struct action *act;
190 190
 	struct run_act_ctx ra_ctx;
191
-	unsigned mod_ver;
192 191
 
193 192
 	if (self == NULL) {
194 193
 		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
... ...
@@ -213,7 +212,7 @@ PyObject *msg_call_function(msgobject *self, PyObject *args)
213 212
 	if(!PyArg_ParseTuple(args, "s|ss:call_function", &fname, &arg1, &arg2))
214 213
 		return NULL;
215 214
 
216
-	fexport = find_export_record(fname, i - 1, 0, &mod_ver);
215
+	fexport = find_export_record(fname, i - 1, 0);
217 216
 	if (fexport == NULL) {
218 217
 		PyErr_SetString(PyExc_RuntimeError, "no such function");
219 218
 		Py_INCREF(Py_None);
Browse code

app_python3: first release

- use same symbols names as app_python so these two modules cannot be used together
- use GIL for thread management

AnthonyA authored on 16/02/2018 13:37:33 • Daniel-Constantin Mierla committed on 20/02/2018 09:11:48
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,545 @@
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 "../../core/action.h"
25
+#include "../../core/mem/mem.h"
26
+#include "../../core/sr_module.h"
27
+#include "../../core/dset.h"
28
+#include "../../core/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 == NULL) {
74
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
75
+		Py_INCREF(Py_None);
76
+		return Py_None;
77
+	}
78
+
79
+	if (self->msg == NULL) {
80
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
81
+		Py_INCREF(Py_None);
82
+		return Py_None;
83
+	}
84
+
85
+	if ((self->msg->first_line).type != SIP_REQUEST) {
86
+		PyErr_SetString(PyExc_RuntimeError, "Not a request message - rewrite is not possible.\n");
87
+		Py_INCREF(Py_None);
88
+		return Py_None;
89
+	}
90
+
91
+	if(!PyArg_ParseTuple(args, "s:rewrite_ruri", &nuri.s))
92
+		return NULL;
93
+
94
+	nuri.len = strlen(nuri.s);
95
+
96
+	if(rewrite_uri(self->msg, &nuri)<0) {
97
+		LM_ERR("failed to update r-uri with [%.*s]\n", nuri.len, nuri.s);
98
+	}
99
+
100
+	Py_INCREF(Py_None);
101
+	return Py_None;
102
+}
103
+
104
+static PyObject *msg_set_dst_uri(msgobject *self, PyObject *args)
105
+{
106
+	str ruri;
107
+
108
+	if (self == NULL) {
109
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
110
+		Py_INCREF(Py_None);
111
+		return Py_None;
112
+	}
113
+
114
+	if (self->msg == NULL) {
115
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
116
+		Py_INCREF(Py_None);
117
+		return Py_None;
118
+	}
119
+
120
+	if ((self->msg->first_line).type != SIP_REQUEST) {
121
+		PyErr_SetString(PyExc_RuntimeError, "Not a request message - set destination is not possible.\n");
122
+		Py_INCREF(Py_None);
123
+		return Py_None;
124
+	}
125
+
126
+	if(!PyArg_ParseTuple(args, "s:set_dst_uri", &ruri.s))
127
+		return NULL;
128
+
129
+	ruri.len = strlen(ruri.s);
130
+
131
+	if (set_dst_uri(self->msg, &ruri) < 0) {
132
+		LM_ERR("Error in set_dst_uri\n");
133
+		PyErr_SetString(PyExc_RuntimeError, "Error in set_dst_uri\n");
134
+	}
135
+	/* dst_uri changes, so it makes sense to re-use the current uri for
136
+	 * forking */
137
+	ruri_mark_new(); /* re-use uri for serial forking */
138
+
139
+	Py_INCREF(Py_None);
140
+	return Py_None;
141
+}
142
+
143
+static PyObject *msg_getHeader(msgobject *self, PyObject *args)
144
+{
145
+	struct hdr_field *hf;
146
+	str hname, *hbody;
147
+
148
+	if (self == NULL) {
149
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
150
+		Py_INCREF(Py_None);
151
+		return Py_None;
152
+	}
153
+
154
+	if (self->msg == NULL) {
155
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
156
+		Py_INCREF(Py_None);
157
+		return Py_None;
158
+	}
159
+
160
+	if(!PyArg_ParseTuple(args, "s:getHeader", &hname.s))
161
+		return NULL;
162
+	hname.len = strlen(hname.s);
163
+
164
+	if(parse_headers(self->msg, HDR_EOH_F, 0)<0) {
165
+		LM_ERR("failed to parse msg headers\n");
166
+	}
167
+	hbody = NULL;
168
+	for (hf = self->msg->headers; hf != NULL; hf = hf->next) {
169
+		if (hname.len == hf->name.len &&
170
+				strncasecmp(hname.s, hf->name.s, hname.len) == 0) {
171
+			hbody = &(hf->body);
172
+			break;
173
+		}
174
+	}
175
+
176
+	if (hbody == NULL) {
177
+		Py_INCREF(Py_None);
178
+		return Py_None;
179
+	}
180
+
181
+	return PyUnicode_FromStringAndSize(hbody->s, hbody->len);
182
+}
183
+
184
+PyObject *msg_call_function(msgobject *self, PyObject *args)
185
+{
186
+	int i, rval;
187
+	char *fname, *arg1, *arg2;
188
+	sr31_cmd_export_t* fexport;
189
+	struct action *act;
190
+	struct run_act_ctx ra_ctx;
191
+	unsigned mod_ver;
192
+
193
+	if (self == NULL) {
194
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
195
+		Py_INCREF(Py_None);
196
+		return Py_None;
197
+	}
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 - 1, 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
+	act = mk_action(MODULE2_T, 4 /* number of (type, value) pairs */,
224
+			MODEXP_ST, fexport, /* function */
225
+			NUMBER_ST, 2,       /* parameter number */
226
+			STRING_ST, arg1,    /* param. 1 */
227
+			STRING_ST, arg2     /* param. 2 */
228
+			);
229
+
230
+	if (act == NULL) {
231
+		PyErr_SetString(PyExc_RuntimeError,
232
+				"action structure could not be created");
233
+		Py_INCREF(Py_None);
234
+		return Py_None;
235
+	}
236
+
237
+	if (fexport->fixup != NULL) {
238
+		if (i >= 3) {
239
+			rval = fexport->fixup(&(act->val[3].u.data), 2);
240
+			if (rval < 0) {
241
+				PyErr_SetString(PyExc_RuntimeError, "Error in fixup (2)");
242
+				Py_INCREF(Py_None);
243
+				pkg_free(act);
244
+				return Py_None;
245
+			}
246
+			act->val[3].type = MODFIXUP_ST;
247
+		}
248
+		if (i >= 2) {
249
+			rval = fexport->fixup(&(act->val[2].u.data), 1);
250
+			if (rval < 0) {
251
+				PyErr_SetString(PyExc_RuntimeError, "Error in fixup (1)");
252
+				Py_INCREF(Py_None);
253
+				pkg_free(act);
254
+				return Py_None;
255
+			}
256
+			act->val[2].type = MODFIXUP_ST;
257
+		}
258
+		if (i == 1) {
259
+			rval = fexport->fixup(0, 0);
260
+			if (rval < 0) {
261
+				PyErr_SetString(PyExc_RuntimeError, "Error in fixup (0)");
262
+				Py_INCREF(Py_None);
263
+				pkg_free(act);
264
+				return Py_None;
265
+			}
266
+		}
267
+	}
268
+
269
+	init_run_actions_ctx(&ra_ctx);
270
+	rval = do_action(&ra_ctx, act, self->msg);
271
+
272
+	if ((act->val[3].type == MODFIXUP_ST) && (act->val[3].u.data)) {
273
+		pkg_free(act->val[3].u.data);
274
+	}
275
+
276
+	if ((act->val[2].type == MODFIXUP_ST) && (act->val[2].u.data)) {
277
+		pkg_free(act->val[2].u.data);
278
+	}
279
+
280
+	pkg_free(act);
281
+
282
+	return PyLong_FromLong(rval);
283
+}
284
+
285
+PyDoc_STRVAR(copy_doc,
286
+		"copy() -> msg object\n\
287
+		\n\
288
+		Return a copy (``clone'') of the msg object.");
289
+
290
+static PyMethodDef msg_methods[] = {
291
+	{"copy",          (PyCFunction)msg_copy,          METH_NOARGS,
292
+		copy_doc},
293
+	{"rewrite_ruri",  (PyCFunction)msg_rewrite_ruri,  METH_VARARGS,
294
+		"Rewrite Request-URI."},
295
+	{"set_dst_uri",   (PyCFunction)msg_set_dst_uri,   METH_VARARGS,
296
+		"Set destination URI."},
297
+	{"getHeader",     (PyCFunction)msg_getHeader,     METH_VARARGS,
298
+		"Get SIP header field by name."},
299
+	{"call_function", (PyCFunction)msg_call_function, METH_VARARGS,
300
+		"Invoke function exported by the other module."},
301
+	{NULL, NULL, 0, NULL} /* sentinel */
302
+};
303
+
304
+static PyObject *msg_getType(msgobject *self, PyObject *unused)
305
+{
306
+	const char *rval;
307
+
308
+	if (self == NULL) {
309
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
310
+		Py_INCREF(Py_None);
311
+		return Py_None;
312
+	}
313
+
314
+	if (self->msg == NULL) {
315
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
316
+		Py_INCREF(Py_None);
317
+		return Py_None;
318
+	}
319
+
320
+	switch ((self->msg->first_line).type)
321
+	{
322
+		case SIP_REQUEST:
323
+			rval = "SIP_REQUEST";
324
+			break;
325
+
326
+		case SIP_REPLY:
327
+			rval = "SIP_REPLY";
328
+			break;
329
+
330
+		default:
331
+			rval = "SIP_INVALID";
332
+			break;
333
+	}
334
+
335
+	return PyUnicode_FromString(rval);
336
+}
337
+
338
+static PyObject *msg_getMethod(msgobject *self, PyObject *unused)
339
+{
340
+	str *rval;
341
+
342
+	if (self == NULL) {
343
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
344
+		Py_INCREF(Py_None);
345
+		return Py_None;
346
+	}
347
+
348
+	if (self->msg == NULL) {
349
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
350
+		Py_INCREF(Py_None);
351
+		return Py_None;
352
+	}
353
+
354
+	if ((self->msg->first_line).type != SIP_REQUEST) {
355
+		PyErr_SetString(PyExc_RuntimeError, "Not a request message - no method available.\n");
356
+		Py_INCREF(Py_None);
357
+		return Py_None;
358
+	}
359
+	rval = &((self->msg->first_line).u.request.method);
360
+	return PyUnicode_FromStringAndSize(rval->s, rval->len);
361
+}
362
+
363
+static PyObject *msg_getStatus(msgobject *self, PyObject *unused)
364
+{
365
+	str *rval;
366
+
367
+	if (self == NULL) {
368
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
369
+		Py_INCREF(Py_None);
370
+		return Py_None;
371
+	}
372
+
373
+	if (self->msg == NULL) {
374
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
375
+		Py_INCREF(Py_None);
376
+		return Py_None;
377
+	}
378
+
379
+	if ((self->msg->first_line).type != SIP_REPLY) {
380
+		PyErr_SetString(PyExc_RuntimeError, "Not a non-reply message - no status available.\n");
381
+		Py_INCREF(Py_None);
382
+		return Py_None;
383
+	}
384
+
385
+	rval = &((self->msg->first_line).u.reply.status);
386
+	return PyUnicode_FromStringAndSize(rval->s, rval->len);
387
+}
388
+
389
+static PyObject *msg_getRURI(msgobject *self, PyObject *unused)
390
+{
391
+	str *rval;
392
+
393
+	if (self == NULL) {
394
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
395
+		Py_INCREF(Py_None);
396
+		return Py_None;
397
+	}
398
+
399
+	if (self->msg == NULL) {
400
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
401
+		Py_INCREF(Py_None);
402
+		return Py_None;
403
+	}
404
+
405
+	if ((self->msg->first_line).type != SIP_REQUEST) {
406
+		PyErr_SetString(PyExc_RuntimeError, "Not a request message - RURI is not available.\n");
407
+		Py_INCREF(Py_None);
408
+		return Py_None;
409
+	}
410
+
411
+	rval = &((self->msg->first_line).u.request.uri);
412
+	return PyUnicode_FromStringAndSize(rval->s, rval->len);
413
+}
414
+
415
+static PyObject *msg_get_src_address(msgobject *self, PyObject *unused)
416
+{
417
+	PyObject *src_ip, *src_port, *pyRval;
418
+
419
+	if (self == NULL) {
420
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
421
+		Py_INCREF(Py_None);
422
+		return Py_None;
423
+	}
424
+
425
+	if (self->msg == NULL) {
426
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
427
+		Py_INCREF(Py_None);
428
+		return Py_None;
429
+	}
430
+
431
+	src_ip = PyUnicode_FromString(ip_addr2a(&self->msg->rcv.src_ip));
432
+	if (src_ip == NULL) {
433
+		Py_INCREF(Py_None);
434
+		return Py_None;
435
+	}
436
+
437
+	src_port = PyLong_FromLong(self->msg->rcv.src_port);
438
+	if (src_port == NULL) {
439
+		Py_DECREF(src_ip);
440
+		Py_INCREF(Py_None);
441
+		return Py_None;
442
+	}
443
+
444
+	pyRval = PyTuple_Pack(2, src_ip, src_port);
445
+	Py_DECREF(src_ip);
446
+	Py_DECREF(src_port);
447
+	if (pyRval == NULL) {
448
+		Py_INCREF(Py_None);
449
+		return Py_None;
450
+	}
451
+
452
+	return pyRval;
453
+}
454
+
455
+static PyObject *msg_get_dst_address(msgobject *self, PyObject *unused)
456
+{
457
+	PyObject *dst_ip, *dst_port, *pyRval;
458
+
459
+	if (self == NULL) {
460
+		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
461
+		Py_INCREF(Py_None);
462
+		return Py_None;
463
+	}
464
+
465
+	if (self->msg == NULL) {
466
+		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
467
+		Py_INCREF(Py_None);
468
+		return Py_None;
469
+	}
470
+
471
+	dst_ip = PyUnicode_FromString(ip_addr2a(&self->msg->rcv.dst_ip));
472
+	if (dst_ip == NULL) {
473
+		Py_INCREF(Py_None);
474
+		return Py_None;
475
+	}
476
+
477
+	dst_port = PyLong_FromLong(self->msg->rcv.dst_port);
478
+	if (dst_port == NULL) {
479
+		Py_DECREF(dst_ip);
480
+		Py_INCREF(Py_None);
481
+		return Py_None;
482
+	}
483
+
484
+	pyRval = PyTuple_Pack(2, dst_ip, dst_port);
485
+	Py_DECREF(dst_ip);
486
+	Py_DECREF(dst_port);
487
+	if (pyRval == NULL) {
488
+		Py_INCREF(Py_None);
489
+		return Py_None;
490
+	}
491
+
492
+	return pyRval;
493
+}
494
+
495
+static PyGetSetDef msg_getseters[] = {
496
+	{"Type",		(getter)msg_getType, NULL, NULL,		"Get message type - \"SIP_REQUEST\" or \"SIP_REPLY\"."},
497
+	{"Method",		(getter)msg_getMethod, NULL, NULL,		"Get SIP method name."},
498
+	{"Status",		(getter)msg_getStatus, NULL, NULL,		"Get SIP status code string."},
499
+	{"RURI",		(getter)msg_getRURI, NULL, NULL,		"Get SIP Request-URI."},
500
+	{"src_address",	(getter)msg_get_src_address, NULL, NULL,	"Get (IP, port) tuple representing source address of the message."},
501
+	{"dst_address",	(getter)msg_get_dst_address, NULL, NULL,	"Get (IP, port) tuple representing destination address of the message."},
502
+	{NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
503
+};
504
+
505
+static PyTypeObject MSGtype = {
506
+	PyVarObject_HEAD_INIT(NULL, 0)
507
+	"Router.msg",             /*tp_name*/
508
+	sizeof(msgobject),        /*tp_basicsize*/
509
+	0,                        /*tp_itemsize*/
510
+	/* methods */
511
+	(destructor)msg_dealloc,  /*tp_dealloc*/
512
+	0,                        /*tp_print*/
513
+	0,                        /*tp_getattr*/
514
+	0,                        /*tp_setattr*/
515
+	0,                        /*tp_as_sync*/
516
+	0,                        /*tp_repr*/
517
+	0,                        /*tp_as_number*/
518
+	0,                        /*tp_as_sequence*/
519
+	0,                        /*tp_as_mapping*/
520
+	0,                        /*tp_hash*/
521
+	0,                        /*tp_call*/
522
+	0,                        /*tp_str*/
523
+	0,                        /*tp_getattro*/
524
+	0,                        /*tp_setattro*/
525
+	0,                        /*tp_as_buffer*/
526
+	Py_TPFLAGS_DEFAULT,       /*tp_flags*/
527
+	0,                        /*tp_doc*/
528
+	0,                        /*tp_traverse*/
529
+	0,                        /*tp_clear*/
530
+	0,                        /*tp_richcompare*/
531
+	0,                        /*tp_weaklistoffset*/
532
+	0,                        /*tp_iter*/
533
+	0,                        /*tp_iternext*/
534
+	msg_methods,              /*tp_methods*/
535
+	0,                        /*tp_members*/
536
+	msg_getseters,            /*tp_getset*/
537
+};
538
+
539
+int python_msgobj_init(void)
540
+{
541
+	Py_TYPE(&MSGtype) = &PyType_Type;
542
+	if (PyType_Ready(&MSGtype) < 0)
543
+		return -1;
544
+	return 0;
545
+}