blob: 3ce85c899b014f097c926d370c764be0527aeca1 [file] [log] [blame]
Thierry FOURNIER00a02252018-02-25 20:59:57 +01001/* spoa-server: processing Python
2 *
3 * Copyright 2018 OZON / Thierry Fournier <thierry.fournier@ozon.io>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 */
11
12#include <Python.h>
13
14#include <arpa/inet.h>
15
16#include <errno.h>
17#include <string.h>
18
19#include "spoa.h"
20
21/* Embedding python documentation:
22 *
23 * https://docs.python.org/2/extending/embedding.html
24 * https://docs.python.org/2/extending/extending.html#extending-python-with-c-or-c
25 * https://docs.python.org/2/extending/extending.html#calling-python-functions-from-c
26 */
27
28static PyObject *module_ipaddress;
29static PyObject *ipv4_address;
30static PyObject *ipv6_address;
31static PyObject *spoa_error;
32static PyObject *empty_array;
33static struct worker *worker;
34
35static int ps_python_start_worker(struct worker *w);
36static int ps_python_load_file(struct worker *w, const char *file);
37static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct spoe_kv *args);
38
39static struct ps ps_python_bindings = {
40 .init_worker = ps_python_start_worker,
41 .load_file = ps_python_load_file,
42 .exec_message = ps_python_exec_message,
43 .ext = ".py",
44};
45
46static PyObject *ps_python_register_message(PyObject *self, PyObject *args)
47{
48 const char *name;
49 PyObject *ref;
50
51 if (!PyArg_ParseTuple(args, "sO!", &name, &PyFunction_Type, &ref))
52 return NULL;
53 Py_XINCREF(ref); /* because the function is intenally refrenced */
54
55 ps_register_message(&ps_python_bindings, name, (void *)ref);
56
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +000057 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +010058}
59
60static PyObject *ps_python_set_var_null(PyObject *self, PyObject *args)
61{
62 const char *name;
63 int name_len;
64 int scope;
65
66 if (!PyArg_ParseTuple(args, "s#i", &name, &name_len, &scope))
67 return NULL;
68 if (!set_var_null(worker, name, name_len, scope)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +000069 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +010070 return NULL;
71 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +000072 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +010073}
74
75static PyObject *ps_python_set_var_boolean(PyObject *self, PyObject *args)
76{
77 const char *name;
78 int name_len;
79 int scope;
80 int value;
81
82 if (!PyArg_ParseTuple(args, "s#ii", &name, &name_len, &scope, &value))
83 return NULL;
84 if (!set_var_bool(worker, name, name_len, scope, value)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +000085 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +010086 return NULL;
87 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +000088 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +010089}
90
91static PyObject *ps_python_set_var_int32(PyObject *self, PyObject *args)
92{
93 const char *name;
94 int name_len;
95 int scope;
96 int32_t value;
97
98 if (!PyArg_ParseTuple(args, "s#ii", &name, &name_len, &scope, &value))
99 return NULL;
100 if (!set_var_int32(worker, name, name_len, scope, value)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000101 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100102 return NULL;
103 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000104 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100105}
106
107static PyObject *ps_python_set_var_uint32(PyObject *self, PyObject *args)
108{
109 const char *name;
110 int name_len;
111 int scope;
112 uint32_t value;
113
114 if (!PyArg_ParseTuple(args, "s#iI", &name, &name_len, &scope, &value))
115 return NULL;
116 if (!set_var_uint32(worker, name, name_len, scope, value)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000117 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100118 return NULL;
119 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000120 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100121}
122
123static PyObject *ps_python_set_var_int64(PyObject *self, PyObject *args)
124{
125 const char *name;
126 int name_len;
127 int scope;
128 int64_t value;
129
130 if (!PyArg_ParseTuple(args, "s#il", &name, &name_len, &scope, &value))
131 return NULL;
132 if (!set_var_int64(worker, name, name_len, scope, value)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000133 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100134 return NULL;
135 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000136 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100137}
138
139static PyObject *ps_python_set_var_uint64(PyObject *self, PyObject *args)
140{
141 const char *name;
142 int name_len;
143 int scope;
144 uint64_t value;
145
146 if (!PyArg_ParseTuple(args, "s#ik", &name, &name_len, &scope, &value))
147 return NULL;
148 if (!set_var_uint64(worker, name, name_len, scope, value)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000149 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100150 return NULL;
151 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000152 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100153}
154
155static PyObject *ps_python_set_var_ipv4(PyObject *self, PyObject *args)
156{
157 const char *name;
158 int name_len;
159 int scope;
160 PyObject *ipv4;
161 PyObject *value;
162 struct in_addr ip;
163
164 if (!PyArg_ParseTuple(args, "s#iO", &name, &name_len, &scope, &ipv4))
165 return NULL;
166 if (!PyObject_IsInstance(ipv4, ipv4_address)) {
167 PyErr_Format(spoa_error, "must be 'IPv4Address', not '%s'", ipv4->ob_type->tp_name);
168 return NULL;
169 }
170 /* Execute packed ... I think .. */
171 value = PyObject_GetAttrString(ipv4, "packed");
172 if (value == NULL)
173 return NULL;
174 if (PyString_GET_SIZE(value) != sizeof(ip)) {
Gilchrist Dadaglo77976932020-12-08 14:37:08 +0000175 PyErr_Format(spoa_error, "IPv4 manipulation internal error");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100176 return NULL;
177 }
178 memcpy(&ip, PyString_AS_STRING(value), PyString_GET_SIZE(value));
179 if (!set_var_ipv4(worker, name, name_len, scope, &ip)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000180 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100181 return NULL;
182 }
Gilchrist Dadagloe38c0922020-08-24 19:21:32 +0000183 /* Once we set the IP value in the worker, we don't need it anymore... */
184 Py_XDECREF(value);
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000185 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100186}
187
188static PyObject *ps_python_set_var_ipv6(PyObject *self, PyObject *args)
189{
190 const char *name;
191 int name_len;
192 int scope;
193 PyObject *ipv6;
194 PyObject *value;
195 struct in6_addr ip;
196
197 if (!PyArg_ParseTuple(args, "s#iO", &name, &name_len, &scope, &ipv6))
198 return NULL;
199 if (!PyObject_IsInstance(ipv6, ipv6_address)) {
200 PyErr_Format(spoa_error, "must be 'IPv6Address', not '%s'", ipv6->ob_type->tp_name);
201 return NULL;
202 }
203 /* Execute packed ... I think .. */
204 value = PyObject_GetAttrString(ipv6, "packed");
205 if (value == NULL)
206 return NULL;
207 if (PyString_GET_SIZE(value) != sizeof(ip)) {
Gilchrist Dadaglo77976932020-12-08 14:37:08 +0000208 PyErr_Format(spoa_error, "IPv6 manipulation internal error");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100209 return NULL;
210 }
211 memcpy(&ip, PyString_AS_STRING(value), PyString_GET_SIZE(value));
212 if (!set_var_ipv6(worker, name, name_len, scope, &ip)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000213 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100214 return NULL;
215 }
Gilchrist Dadagloe38c0922020-08-24 19:21:32 +0000216 /* Once we set the IP value in the worker, we don't need it anymore... */
217 Py_XDECREF(value);
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000218 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100219}
220
221static PyObject *ps_python_set_var_str(PyObject *self, PyObject *args)
222{
223 const char *name;
224 int name_len;
225 int scope;
226 const char *value;
227 int value_len;
228
229 if (!PyArg_ParseTuple(args, "s#is#", &name, &name_len, &scope, &value, &value_len))
230 return NULL;
231 if (!set_var_string(worker, name, name_len, scope, value, value_len)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000232 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100233 return NULL;
234 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000235 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100236}
237
238static PyObject *ps_python_set_var_bin(PyObject *self, PyObject *args)
239{
240 const char *name;
241 int name_len;
242 int scope;
243 const char *value;
244 int value_len;
245
246 if (!PyArg_ParseTuple(args, "s#is#", &name, &name_len, &scope, &value, &value_len))
247 return NULL;
248 if (!set_var_bin(worker, name, name_len, scope, value, value_len)) {
Gilchrist Dadaglo16f1f9d2020-12-08 14:37:09 +0000249 PyErr_SetString(spoa_error, "No more memory space available");
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100250 return NULL;
251 }
Gilchrist Dadaglo3f7ece82020-12-08 14:37:07 +0000252 Py_RETURN_NONE;
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100253}
254
255
256static PyMethodDef spoa_methods[] = {
257 {"register_message", ps_python_register_message, METH_VARARGS,
258 "Register binding for SPOA message."},
259 {"set_var_null", ps_python_set_var_null, METH_VARARGS,
260 "Set SPOA NULL variable"},
261 {"set_var_boolean", ps_python_set_var_boolean, METH_VARARGS,
262 "Set SPOA boolean variable"},
263 {"set_var_int32", ps_python_set_var_int32, METH_VARARGS,
264 "Set SPOA int32 variable"},
265 {"set_var_uint32", ps_python_set_var_uint32, METH_VARARGS,
266 "Set SPOA uint32 variable"},
267 {"set_var_int64", ps_python_set_var_int64, METH_VARARGS,
268 "Set SPOA int64 variable"},
269 {"set_var_uint64", ps_python_set_var_uint64, METH_VARARGS,
270 "Set SPOA uint64 variable"},
271 {"set_var_ipv4", ps_python_set_var_ipv4, METH_VARARGS,
272 "Set SPOA ipv4 variable"},
273 {"set_var_ipv6", ps_python_set_var_ipv6, METH_VARARGS,
274 "Set SPOA ipv6 variable"},
275 {"set_var_str", ps_python_set_var_str, METH_VARARGS,
276 "Set SPOA str variable"},
277 {"set_var_bin", ps_python_set_var_bin, METH_VARARGS,
278 "Set SPOA bin variable"},
279 { /* end */ }
280};
281
282static int ps_python_start_worker(struct worker *w)
283{
284 PyObject *m;
285 PyObject *module_name;
286 PyObject *value;
287 int ret;
288
289 Py_SetProgramName("spoa-server");
290 Py_Initialize();
291
292 module_name = PyString_FromString("ipaddress");
293 if (module_name == NULL) {
294 PyErr_Print();
295 return 0;
296 }
297
298 module_ipaddress = PyImport_Import(module_name);
299 Py_DECREF(module_name);
300 if (module_ipaddress == NULL) {
301 PyErr_Print();
302 return 0;
303 }
304
305 ipv4_address = PyObject_GetAttrString(module_ipaddress, "IPv4Address");
306 if (ipv4_address == NULL) {
307 PyErr_Print();
308 return 0;
309 }
310
311 ipv6_address = PyObject_GetAttrString(module_ipaddress, "IPv6Address");
Gilchrist Dadaglo2ded13c2020-08-24 19:21:35 +0000312 if (ipv6_address == NULL) {
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100313 PyErr_Print();
314 return 0;
315 }
316
317 m = Py_InitModule("spoa", spoa_methods);
318 if (m == NULL) {
319 PyErr_Print();
320 return 0;
321 }
322
323 spoa_error = PyErr_NewException("spoa.error", NULL, NULL);
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000324 /* PyModule_AddObject will steal the reference to spoa_error
325 * in case of success only
326 * We need to increment the counters to continue using it
327 * but cleanup in case of failure
328 */
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100329 Py_INCREF(spoa_error);
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000330 ret = PyModule_AddObject(m, "error", spoa_error);
331 if (ret == -1) {
332 Py_DECREF(m);
333 Py_DECREF(spoa_error);
334 PyErr_Print();
335 return 0;
336 }
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100337
338
339 value = PyLong_FromLong(SPOE_SCOPE_PROC);
340 if (value == NULL) {
341 PyErr_Print();
342 return 0;
343 }
344
345 ret = PyModule_AddObject(m, "scope_proc", value);
346 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000347 Py_DECREF(m);
348 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100349 PyErr_Print();
350 return 0;
351 }
352
353 value = PyLong_FromLong(SPOE_SCOPE_SESS);
354 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000355 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100356 PyErr_Print();
357 return 0;
358 }
359
360 ret = PyModule_AddObject(m, "scope_sess", value);
361 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000362 Py_DECREF(m);
363 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100364 PyErr_Print();
365 return 0;
366 }
367
368 value = PyLong_FromLong(SPOE_SCOPE_TXN);
369 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000370 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100371 PyErr_Print();
372 return 0;
373 }
374
375 ret = PyModule_AddObject(m, "scope_txn", value);
376 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000377 Py_DECREF(m);
378 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100379 PyErr_Print();
380 return 0;
381 }
382
383 value = PyLong_FromLong(SPOE_SCOPE_REQ);
384 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000385 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100386 PyErr_Print();
387 return 0;
388 }
389
390 ret = PyModule_AddObject(m, "scope_req", value);
391 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000392 Py_DECREF(m);
393 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100394 PyErr_Print();
395 return 0;
396 }
397
398 value = PyLong_FromLong(SPOE_SCOPE_RES);
399 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000400 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100401 PyErr_Print();
402 return 0;
403 }
404
405 ret = PyModule_AddObject(m, "scope_res", value);
406 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000407 Py_DECREF(m);
408 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100409 PyErr_Print();
410 return 0;
411 }
412
413 empty_array = PyDict_New();
414 if (empty_array == NULL) {
415 PyErr_Print();
416 return 0;
417 }
418
419 worker = w;
420 return 1;
421}
422
423static int ps_python_load_file(struct worker *w, const char *file)
424{
425 FILE *fp;
426 int ret;
427
428 fp = fopen(file, "r");
429 if (fp == NULL) {
430 LOG("python: Cannot read file \"%s\": %s", file, strerror(errno));
431 return 0;
432 }
433
434 ret = PyRun_SimpleFile(fp, file);
435 fclose(fp);
436 if (ret != 0) {
437 PyErr_Print();
438 return 0;
439 }
440
441 return 1;
442}
443
444static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct spoe_kv *args)
445{
446 int i;
447 PyObject *python_ref = ref;
448 PyObject *fkw;
449 PyObject *kw_args;
450 PyObject *result;
451 PyObject *ent;
452 PyObject *key;
453 PyObject *value;
454 PyObject *func;
455 int ret;
456 char ipbuf[64];
457 const char *p;
458 PyObject *ip_dict;
459 PyObject *ip_name;
460 PyObject *ip_value;
461
462 /* Dict containing arguments */
463
464 kw_args = PyList_New(0);
465 if (kw_args == NULL) {
466 PyErr_Print();
467 return 0;
468 }
469
470 for (i = 0; i < nargs; i++) {
471
472 /* New dict containing one argument */
473
474 ent = PyDict_New();
475 if (ent == NULL) {
476 Py_DECREF(kw_args);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100477 PyErr_Print();
478 return 0;
479 }
480
481 /* Create the name entry */
482
483 key = PyString_FromString("name");
484 if (key == NULL) {
485 Py_DECREF(kw_args);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000486 Py_DECREF(ent);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100487 PyErr_Print();
488 return 0;
489 }
490
491 value = PyString_FromStringAndSize(args[i].name.str, args[i].name.len);
492 if (value == NULL) {
493 Py_DECREF(kw_args);
494 Py_DECREF(ent);
495 Py_DECREF(key);
496 PyErr_Print();
497 return 0;
498 }
499
500 ret = PyDict_SetItem(ent, key, value);
501 Py_DECREF(key);
502 Py_DECREF(value);
503 if (ret == -1) {
504 Py_DECREF(kw_args);
505 Py_DECREF(ent);
506 PyErr_Print();
507 return 0;
508 }
509
Gilchrist Dadaglo90fe8902020-12-08 14:37:10 +0000510 /* Create the value entry */
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100511
512 key = PyString_FromString("value");
513 if (key == NULL) {
514 Py_DECREF(kw_args);
515 Py_DECREF(ent);
516 PyErr_Print();
517 return 0;
518 }
519
520 switch (args[i].value.type) {
521 case SPOE_DATA_T_NULL:
522 value = Py_None;
523 break;
524 case SPOE_DATA_T_BOOL:
525 value = PyBool_FromLong(args[i].value.u.boolean);
526 break;
527 case SPOE_DATA_T_INT32:
528 value = PyLong_FromLong(args[i].value.u.sint32);
529 break;
530 case SPOE_DATA_T_UINT32:
531 value = PyLong_FromLong(args[i].value.u.uint32);
532 break;
533 case SPOE_DATA_T_INT64:
534 value = PyLong_FromLong(args[i].value.u.sint64);
535 break;
536 case SPOE_DATA_T_UINT64:
537 value = PyLong_FromUnsignedLong(args[i].value.u.uint64);
538 break;
539 case SPOE_DATA_T_IPV4:
540 case SPOE_DATA_T_IPV6:
541 if (args[i].value.type == SPOE_DATA_T_IPV4)
542 p = inet_ntop(AF_INET, &args[i].value.u.ipv4, ipbuf, 64);
543 else
544 p = inet_ntop(AF_INET6, &args[i].value.u.ipv6, ipbuf, 64);
545 if (!p)
546 strcpy(ipbuf, "0.0.0.0");
547
548 func = PyObject_GetAttrString(module_ipaddress, "ip_address");
549 if (func == NULL) {
550 Py_DECREF(kw_args);
551 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000552 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100553 PyErr_Print();
554 return 0;
555 }
556 ip_dict = PyDict_New();
557 if (ip_dict == NULL) {
558 Py_DECREF(kw_args);
559 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000560 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100561 Py_DECREF(func);
562 PyErr_Print();
563 return 0;
564 }
565 ip_name = PyString_FromString("address");
566 if (ip_name == NULL) {
567 Py_DECREF(kw_args);
568 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000569 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100570 Py_DECREF(func);
571 Py_DECREF(ip_dict);
572 PyErr_Print();
573 return 0;
574 }
575 ip_value = PyUnicode_FromString(ipbuf);
576 if (ip_value == NULL) {
577 Py_DECREF(kw_args);
578 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000579 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100580 Py_DECREF(func);
581 Py_DECREF(ip_dict);
582 Py_DECREF(ip_name);
583 PyErr_Print();
584 return 0;
585 }
586 ret = PyDict_SetItem(ip_dict, ip_name, ip_value);
587 Py_DECREF(ip_name);
588 Py_DECREF(ip_value);
589 if (ret == -1) {
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000590 Py_DECREF(kw_args);
591 Py_DECREF(ent);
592 Py_DECREF(key);
593 Py_DECREF(func);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100594 Py_DECREF(ip_dict);
595 PyErr_Print();
596 return 0;
597 }
598 value = PyObject_Call(func, empty_array, ip_dict);
599 Py_DECREF(func);
600 Py_DECREF(ip_dict);
601 break;
602
603 case SPOE_DATA_T_STR:
604 value = PyString_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
605 break;
606 case SPOE_DATA_T_BIN:
607 value = PyString_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
608 break;
609 default:
610 value = Py_None;
611 break;
612 }
613 if (value == NULL) {
614 Py_DECREF(kw_args);
615 Py_DECREF(ent);
616 Py_DECREF(key);
617 PyErr_Print();
618 return 0;
619 }
620
621 ret = PyDict_SetItem(ent, key, value);
622 Py_DECREF(key);
623 Py_DECREF(value);
624 if (ret == -1) {
625 Py_DECREF(kw_args);
626 Py_DECREF(ent);
627 PyErr_Print();
628 return 0;
629 }
630
631 /* Add dict to the list */
632
633 ret = PyList_Append(kw_args, ent);
634 Py_DECREF(ent);
635 if (ret == -1) {
636 Py_DECREF(kw_args);
637 PyErr_Print();
638 return 0;
639 }
640 }
641
642 /* Dictionnary { args = <list-of-args> } for the function */
643
644 fkw = PyDict_New();
645 if (fkw == NULL) {
646 Py_DECREF(kw_args);
647 PyErr_Print();
648 return 0;
649 }
650
651 key = PyString_FromString("args");
652 if (key == NULL) {
653 Py_DECREF(kw_args);
654 Py_DECREF(fkw);
655 PyErr_Print();
656 return 0;
657 }
658
659 ret = PyDict_SetItem(fkw, key, kw_args);
660 Py_DECREF(kw_args);
661 Py_DECREF(key);
662 if (ret == -1) {
663 Py_DECREF(fkw);
664 PyErr_Print();
665 return 0;
666 }
667
668 result = PyObject_Call(python_ref, empty_array, fkw);
Gilchrist Dadaglod01d2802020-08-24 19:21:31 +0000669 Py_DECREF(fkw);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100670 if (result == NULL) {
671 PyErr_Print();
672 return 0;
673 }
Gilchrist Dadaglod01d2802020-08-24 19:21:31 +0000674 if (result != Py_None) {
675 Py_DECREF(result);
676 }
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100677
678 return 1;
679}
680
681__attribute__((constructor))
682static void __ps_python_init(void)
683{
684 ps_register(&ps_python_bindings);
685}