blob: 7eadef605ae119e93b3005c0bb9c8bb6ae98ac07 [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;
Gilchrist Dadaglo690ba742020-12-08 14:37:13 +000032static PyObject *empty_tuple;
Thierry FOURNIER00a02252018-02-25 20:59:57 +010033static 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) {
Gilchrist Dadaglob7299492020-12-08 14:37:12 +0000307 Py_DECREF(module_ipaddress);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100308 PyErr_Print();
309 return 0;
310 }
311
312 ipv6_address = PyObject_GetAttrString(module_ipaddress, "IPv6Address");
Gilchrist Dadaglo2ded13c2020-08-24 19:21:35 +0000313 if (ipv6_address == NULL) {
Gilchrist Dadaglob7299492020-12-08 14:37:12 +0000314 Py_DECREF(ipv4_address);
315 Py_DECREF(module_ipaddress);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100316 PyErr_Print();
317 return 0;
318 }
319
320 m = Py_InitModule("spoa", spoa_methods);
321 if (m == NULL) {
Gilchrist Dadaglob7299492020-12-08 14:37:12 +0000322 Py_DECREF(ipv4_address);
323 Py_DECREF(ipv6_address);
324 Py_DECREF(module_ipaddress);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100325 PyErr_Print();
326 return 0;
327 }
328
329 spoa_error = PyErr_NewException("spoa.error", NULL, NULL);
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000330 /* PyModule_AddObject will steal the reference to spoa_error
331 * in case of success only
332 * We need to increment the counters to continue using it
333 * but cleanup in case of failure
334 */
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100335 Py_INCREF(spoa_error);
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000336 ret = PyModule_AddObject(m, "error", spoa_error);
337 if (ret == -1) {
338 Py_DECREF(m);
339 Py_DECREF(spoa_error);
340 PyErr_Print();
341 return 0;
342 }
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100343
344
345 value = PyLong_FromLong(SPOE_SCOPE_PROC);
346 if (value == NULL) {
347 PyErr_Print();
348 return 0;
349 }
350
351 ret = PyModule_AddObject(m, "scope_proc", value);
352 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000353 Py_DECREF(m);
354 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100355 PyErr_Print();
356 return 0;
357 }
358
359 value = PyLong_FromLong(SPOE_SCOPE_SESS);
360 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000361 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100362 PyErr_Print();
363 return 0;
364 }
365
366 ret = PyModule_AddObject(m, "scope_sess", value);
367 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000368 Py_DECREF(m);
369 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100370 PyErr_Print();
371 return 0;
372 }
373
374 value = PyLong_FromLong(SPOE_SCOPE_TXN);
375 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000376 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100377 PyErr_Print();
378 return 0;
379 }
380
381 ret = PyModule_AddObject(m, "scope_txn", value);
382 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000383 Py_DECREF(m);
384 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100385 PyErr_Print();
386 return 0;
387 }
388
389 value = PyLong_FromLong(SPOE_SCOPE_REQ);
390 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000391 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100392 PyErr_Print();
393 return 0;
394 }
395
396 ret = PyModule_AddObject(m, "scope_req", value);
397 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000398 Py_DECREF(m);
399 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100400 PyErr_Print();
401 return 0;
402 }
403
404 value = PyLong_FromLong(SPOE_SCOPE_RES);
405 if (value == NULL) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000406 Py_DECREF(m);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100407 PyErr_Print();
408 return 0;
409 }
410
411 ret = PyModule_AddObject(m, "scope_res", value);
412 if (ret == -1) {
Gilchrist Dadaglo137fcba2020-12-08 14:37:11 +0000413 Py_DECREF(m);
414 Py_DECREF(value);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100415 PyErr_Print();
416 return 0;
417 }
418
Gilchrist Dadaglo690ba742020-12-08 14:37:13 +0000419 empty_tuple = PyTuple_New(0);
420 if (empty_tuple == NULL) {
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100421 PyErr_Print();
422 return 0;
423 }
424
425 worker = w;
426 return 1;
427}
428
429static int ps_python_load_file(struct worker *w, const char *file)
430{
431 FILE *fp;
432 int ret;
433
434 fp = fopen(file, "r");
435 if (fp == NULL) {
436 LOG("python: Cannot read file \"%s\": %s", file, strerror(errno));
437 return 0;
438 }
439
440 ret = PyRun_SimpleFile(fp, file);
441 fclose(fp);
442 if (ret != 0) {
443 PyErr_Print();
444 return 0;
445 }
446
447 return 1;
448}
449
450static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct spoe_kv *args)
451{
452 int i;
453 PyObject *python_ref = ref;
454 PyObject *fkw;
455 PyObject *kw_args;
456 PyObject *result;
457 PyObject *ent;
458 PyObject *key;
459 PyObject *value;
460 PyObject *func;
461 int ret;
462 char ipbuf[64];
463 const char *p;
464 PyObject *ip_dict;
465 PyObject *ip_name;
466 PyObject *ip_value;
467
468 /* Dict containing arguments */
469
470 kw_args = PyList_New(0);
471 if (kw_args == NULL) {
472 PyErr_Print();
473 return 0;
474 }
475
476 for (i = 0; i < nargs; i++) {
477
478 /* New dict containing one argument */
479
480 ent = PyDict_New();
481 if (ent == NULL) {
482 Py_DECREF(kw_args);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100483 PyErr_Print();
484 return 0;
485 }
486
487 /* Create the name entry */
488
489 key = PyString_FromString("name");
490 if (key == NULL) {
491 Py_DECREF(kw_args);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000492 Py_DECREF(ent);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100493 PyErr_Print();
494 return 0;
495 }
496
497 value = PyString_FromStringAndSize(args[i].name.str, args[i].name.len);
498 if (value == NULL) {
499 Py_DECREF(kw_args);
500 Py_DECREF(ent);
501 Py_DECREF(key);
502 PyErr_Print();
503 return 0;
504 }
505
506 ret = PyDict_SetItem(ent, key, value);
507 Py_DECREF(key);
508 Py_DECREF(value);
509 if (ret == -1) {
510 Py_DECREF(kw_args);
511 Py_DECREF(ent);
512 PyErr_Print();
513 return 0;
514 }
515
Gilchrist Dadaglo90fe8902020-12-08 14:37:10 +0000516 /* Create the value entry */
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100517
518 key = PyString_FromString("value");
519 if (key == NULL) {
520 Py_DECREF(kw_args);
521 Py_DECREF(ent);
522 PyErr_Print();
523 return 0;
524 }
525
526 switch (args[i].value.type) {
527 case SPOE_DATA_T_NULL:
Gilchrist Dadaglo8b6aabe2020-12-08 14:37:14 +0000528 Py_INCREF(Py_None);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100529 value = Py_None;
530 break;
531 case SPOE_DATA_T_BOOL:
532 value = PyBool_FromLong(args[i].value.u.boolean);
533 break;
534 case SPOE_DATA_T_INT32:
535 value = PyLong_FromLong(args[i].value.u.sint32);
536 break;
537 case SPOE_DATA_T_UINT32:
538 value = PyLong_FromLong(args[i].value.u.uint32);
539 break;
540 case SPOE_DATA_T_INT64:
541 value = PyLong_FromLong(args[i].value.u.sint64);
542 break;
543 case SPOE_DATA_T_UINT64:
544 value = PyLong_FromUnsignedLong(args[i].value.u.uint64);
545 break;
546 case SPOE_DATA_T_IPV4:
547 case SPOE_DATA_T_IPV6:
548 if (args[i].value.type == SPOE_DATA_T_IPV4)
549 p = inet_ntop(AF_INET, &args[i].value.u.ipv4, ipbuf, 64);
550 else
551 p = inet_ntop(AF_INET6, &args[i].value.u.ipv6, ipbuf, 64);
552 if (!p)
553 strcpy(ipbuf, "0.0.0.0");
554
555 func = PyObject_GetAttrString(module_ipaddress, "ip_address");
556 if (func == NULL) {
557 Py_DECREF(kw_args);
558 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000559 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100560 PyErr_Print();
561 return 0;
562 }
563 ip_dict = PyDict_New();
564 if (ip_dict == NULL) {
565 Py_DECREF(kw_args);
566 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000567 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100568 Py_DECREF(func);
569 PyErr_Print();
570 return 0;
571 }
572 ip_name = PyString_FromString("address");
573 if (ip_name == NULL) {
574 Py_DECREF(kw_args);
575 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000576 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100577 Py_DECREF(func);
578 Py_DECREF(ip_dict);
579 PyErr_Print();
580 return 0;
581 }
582 ip_value = PyUnicode_FromString(ipbuf);
583 if (ip_value == NULL) {
584 Py_DECREF(kw_args);
585 Py_DECREF(ent);
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000586 Py_DECREF(key);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100587 Py_DECREF(func);
588 Py_DECREF(ip_dict);
589 Py_DECREF(ip_name);
590 PyErr_Print();
591 return 0;
592 }
593 ret = PyDict_SetItem(ip_dict, ip_name, ip_value);
594 Py_DECREF(ip_name);
595 Py_DECREF(ip_value);
596 if (ret == -1) {
Gilchrist Dadaglo10cd77a2020-08-24 19:21:34 +0000597 Py_DECREF(kw_args);
598 Py_DECREF(ent);
599 Py_DECREF(key);
600 Py_DECREF(func);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100601 Py_DECREF(ip_dict);
602 PyErr_Print();
603 return 0;
604 }
Gilchrist Dadaglo690ba742020-12-08 14:37:13 +0000605 value = PyObject_Call(func, empty_tuple, ip_dict);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100606 Py_DECREF(func);
607 Py_DECREF(ip_dict);
608 break;
609
610 case SPOE_DATA_T_STR:
611 value = PyString_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
612 break;
613 case SPOE_DATA_T_BIN:
614 value = PyString_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
615 break;
616 default:
Gilchrist Dadaglo8b6aabe2020-12-08 14:37:14 +0000617 Py_INCREF(Py_None);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100618 value = Py_None;
619 break;
620 }
621 if (value == NULL) {
622 Py_DECREF(kw_args);
623 Py_DECREF(ent);
624 Py_DECREF(key);
625 PyErr_Print();
626 return 0;
627 }
628
629 ret = PyDict_SetItem(ent, key, value);
630 Py_DECREF(key);
631 Py_DECREF(value);
632 if (ret == -1) {
633 Py_DECREF(kw_args);
634 Py_DECREF(ent);
635 PyErr_Print();
636 return 0;
637 }
638
639 /* Add dict to the list */
640
641 ret = PyList_Append(kw_args, ent);
642 Py_DECREF(ent);
643 if (ret == -1) {
644 Py_DECREF(kw_args);
645 PyErr_Print();
646 return 0;
647 }
648 }
649
650 /* Dictionnary { args = <list-of-args> } for the function */
651
652 fkw = PyDict_New();
653 if (fkw == NULL) {
654 Py_DECREF(kw_args);
655 PyErr_Print();
656 return 0;
657 }
658
659 key = PyString_FromString("args");
660 if (key == NULL) {
661 Py_DECREF(kw_args);
662 Py_DECREF(fkw);
663 PyErr_Print();
664 return 0;
665 }
666
667 ret = PyDict_SetItem(fkw, key, kw_args);
668 Py_DECREF(kw_args);
669 Py_DECREF(key);
670 if (ret == -1) {
671 Py_DECREF(fkw);
672 PyErr_Print();
673 return 0;
674 }
675
Gilchrist Dadaglo690ba742020-12-08 14:37:13 +0000676 result = PyObject_Call(python_ref, empty_tuple, fkw);
Gilchrist Dadaglod01d2802020-08-24 19:21:31 +0000677 Py_DECREF(fkw);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100678 if (result == NULL) {
679 PyErr_Print();
680 return 0;
681 }
Gilchrist Dadaglo8b6aabe2020-12-08 14:37:14 +0000682 Py_DECREF(result);
Thierry FOURNIER00a02252018-02-25 20:59:57 +0100683
684 return 1;
685}
686
687__attribute__((constructor))
688static void __ps_python_init(void)
689{
690 ps_register(&ps_python_bindings);
691}