Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Python bindings for tevent
4 :
5 : Copyright (C) Jelmer Vernooij 2010
6 :
7 : ** NOTE! The following LGPL license applies to the tevent
8 : ** library. This does NOT imply that all of Samba is released
9 : ** under the LGPL
10 :
11 : This library is free software; you can redistribute it and/or
12 : modify it under the terms of the GNU Lesser General Public
13 : License as published by the Free Software Foundation; either
14 : version 3 of the License, or (at your option) any later version.
15 :
16 : This library is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : Lesser General Public License for more details.
20 :
21 : You should have received a copy of the GNU Lesser General Public
22 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include <Python.h>
26 : #include "replace.h"
27 : #include <tevent.h>
28 :
29 : #if PY_MAJOR_VERSION >= 3
30 : #define PyLong_FromLong PyLong_FromLong
31 : #endif
32 :
33 : /* discard signature of 'func' in favour of 'target_sig' */
34 : #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
35 :
36 : void init_tevent(void);
37 :
38 : typedef struct {
39 : PyObject_HEAD
40 : struct tevent_context *ev;
41 : } TeventContext_Object;
42 :
43 : typedef struct {
44 : PyObject_HEAD
45 : struct tevent_queue *queue;
46 : } TeventQueue_Object;
47 :
48 : typedef struct {
49 : PyObject_HEAD
50 : struct tevent_req *req;
51 : } TeventReq_Object;
52 :
53 : typedef struct {
54 : PyObject_HEAD
55 : struct tevent_signal *signal;
56 : } TeventSignal_Object;
57 :
58 : typedef struct {
59 : PyObject_HEAD
60 : struct tevent_timer *timer;
61 : PyObject *callback;
62 : } TeventTimer_Object;
63 :
64 : typedef struct {
65 : PyObject_HEAD
66 : struct tevent_fd *fd;
67 : } TeventFd_Object;
68 :
69 : static PyTypeObject TeventContext_Type;
70 : static PyTypeObject TeventReq_Type;
71 : static PyTypeObject TeventQueue_Type;
72 : static PyTypeObject TeventSignal_Type;
73 : static PyTypeObject TeventTimer_Type;
74 : static PyTypeObject TeventFd_Type;
75 :
76 0 : static int py_context_init(struct tevent_context *ev)
77 : {
78 : /* FIXME */
79 0 : return 0;
80 : }
81 :
82 0 : static struct tevent_fd *py_add_fd(struct tevent_context *ev,
83 : TALLOC_CTX *mem_ctx,
84 : int fd, uint16_t flags,
85 : tevent_fd_handler_t handler,
86 : void *private_data,
87 : const char *handler_name,
88 : const char *location)
89 : {
90 : /* FIXME */
91 0 : return NULL;
92 : }
93 :
94 0 : static void py_set_fd_close_fn(struct tevent_fd *fde,
95 : tevent_fd_close_fn_t close_fn)
96 : {
97 : /* FIXME */
98 0 : }
99 :
100 0 : static uint16_t py_get_fd_flags(struct tevent_fd *fde)
101 : {
102 : /* FIXME */
103 0 : return 0;
104 : }
105 :
106 0 : static void py_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
107 : {
108 : /* FIXME */
109 0 : }
110 :
111 : /* timed_event functions */
112 0 : static struct tevent_timer *py_add_timer(struct tevent_context *ev,
113 : TALLOC_CTX *mem_ctx,
114 : struct timeval next_event,
115 : tevent_timer_handler_t handler,
116 : void *private_data,
117 : const char *handler_name,
118 : const char *location)
119 : {
120 : /* FIXME */
121 0 : return NULL;
122 : }
123 :
124 : /* immediate event functions */
125 0 : static void py_schedule_immediate(struct tevent_immediate *im,
126 : struct tevent_context *ev,
127 : tevent_immediate_handler_t handler,
128 : void *private_data,
129 : const char *handler_name,
130 : const char *location)
131 : {
132 : /* FIXME */
133 0 : }
134 :
135 : /* signal functions */
136 0 : static struct tevent_signal *py_add_signal(struct tevent_context *ev,
137 : TALLOC_CTX *mem_ctx,
138 : int signum, int sa_flags,
139 : tevent_signal_handler_t handler,
140 : void *private_data,
141 : const char *handler_name,
142 : const char *location)
143 : {
144 : /* FIXME */
145 0 : return NULL;
146 : }
147 :
148 : /* loop functions */
149 0 : static int py_loop_once(struct tevent_context *ev, const char *location)
150 : {
151 : /* FIXME */
152 0 : return 0;
153 : }
154 :
155 0 : static int py_loop_wait(struct tevent_context *ev, const char *location)
156 : {
157 : /* FIXME */
158 0 : return 0;
159 : }
160 :
161 : const static struct tevent_ops py_tevent_ops = {
162 : .context_init = py_context_init,
163 : .add_fd = py_add_fd,
164 : .set_fd_close_fn = py_set_fd_close_fn,
165 : .get_fd_flags = py_get_fd_flags,
166 : .set_fd_flags = py_set_fd_flags,
167 : .add_timer = py_add_timer,
168 : .schedule_immediate = py_schedule_immediate,
169 : .add_signal = py_add_signal,
170 : .loop_wait = py_loop_wait,
171 : .loop_once = py_loop_once,
172 : };
173 :
174 0 : static PyObject *py_register_backend(PyObject *self, PyObject *args)
175 : {
176 : PyObject *name, *py_backend;
177 :
178 0 : if (!PyArg_ParseTuple(args, "O", &py_backend))
179 0 : return NULL;
180 :
181 0 : name = PyObject_GetAttrString(py_backend, "name");
182 0 : if (name == NULL) {
183 0 : PyErr_SetNone(PyExc_AttributeError);
184 0 : return NULL;
185 : }
186 :
187 0 : if (!PyUnicode_Check(name)) {
188 0 : PyErr_SetNone(PyExc_TypeError);
189 0 : Py_DECREF(name);
190 0 : return NULL;
191 : }
192 :
193 0 : if (!tevent_register_backend(PyUnicode_AsUTF8(name), &py_tevent_ops)) { /* FIXME: What to do with backend */
194 0 : PyErr_SetNone(PyExc_RuntimeError);
195 0 : Py_DECREF(name);
196 0 : return NULL;
197 : }
198 :
199 0 : Py_DECREF(name);
200 :
201 0 : Py_RETURN_NONE;
202 : }
203 :
204 1 : static PyObject *py_tevent_context_reinitialise(TeventContext_Object *self,
205 : PyObject *Py_UNUSED(ignored))
206 : {
207 1 : int ret = tevent_re_initialise(self->ev);
208 1 : if (ret != 0) {
209 0 : PyErr_SetNone(PyExc_RuntimeError);
210 0 : return NULL;
211 : }
212 1 : Py_RETURN_NONE;
213 : }
214 :
215 0 : static PyObject *py_tevent_queue_stop(TeventQueue_Object *self,
216 : PyObject *Py_UNUSED(ignored))
217 : {
218 0 : tevent_queue_stop(self->queue);
219 0 : Py_RETURN_NONE;
220 : }
221 :
222 0 : static PyObject *py_tevent_queue_start(TeventQueue_Object *self,
223 : PyObject *Py_UNUSED(ignored))
224 : {
225 0 : tevent_queue_start(self->queue);
226 0 : Py_RETURN_NONE;
227 : }
228 :
229 0 : static void py_queue_trigger(struct tevent_req *req, void *private_data)
230 : {
231 0 : PyObject *callback = private_data, *ret;
232 :
233 0 : ret = PyObject_CallFunction(callback, discard_const_p(char, ""));
234 0 : Py_XDECREF(ret);
235 0 : }
236 :
237 0 : static PyObject *py_tevent_queue_add(TeventQueue_Object *self, PyObject *args)
238 : {
239 : TeventContext_Object *py_ev;
240 : TeventReq_Object *py_req;
241 : PyObject *trigger;
242 : bool ret;
243 :
244 0 : if (!PyArg_ParseTuple(args, "O!O!O",
245 : &TeventContext_Type, &py_ev,
246 : &TeventReq_Type, &py_req,
247 : &trigger))
248 0 : return NULL;
249 :
250 0 : Py_INCREF(trigger);
251 :
252 0 : ret = tevent_queue_add(self->queue, py_ev->ev, py_req->req,
253 : py_queue_trigger, trigger);
254 0 : if (!ret) {
255 0 : PyErr_SetString(PyExc_RuntimeError, "queue add failed");
256 0 : Py_DECREF(trigger);
257 0 : return NULL;
258 : }
259 :
260 0 : Py_RETURN_NONE;
261 : }
262 :
263 : static PyMethodDef py_tevent_queue_methods[] = {
264 : { "stop", (PyCFunction)py_tevent_queue_stop,
265 : METH_NOARGS,
266 : "S.stop()" },
267 : { "start", (PyCFunction)py_tevent_queue_start,
268 : METH_NOARGS,
269 : "S.start()" },
270 : { "add", (PyCFunction)py_tevent_queue_add, METH_VARARGS,
271 : "S.add(ctx, req, trigger, baton)" },
272 : {0},
273 : };
274 :
275 0 : static PyObject *py_tevent_context_wakeup_send(PyObject *self, PyObject *args)
276 : {
277 : /* FIXME */
278 :
279 0 : Py_RETURN_NONE;
280 : }
281 :
282 1 : static PyObject *py_tevent_context_loop_wait(TeventContext_Object *self,
283 : PyObject *Py_UNUSED(ignored))
284 : {
285 1 : if (tevent_loop_wait(self->ev) != 0) {
286 0 : PyErr_SetNone(PyExc_RuntimeError);
287 0 : return NULL;
288 : }
289 1 : Py_RETURN_NONE;
290 : }
291 :
292 4 : static PyObject *py_tevent_context_loop_once(TeventContext_Object *self,
293 : PyObject *Py_UNUSED(ignored))
294 : {
295 4 : if (tevent_loop_once(self->ev) != 0) {
296 0 : PyErr_SetNone(PyExc_RuntimeError);
297 0 : return NULL;
298 : }
299 4 : Py_RETURN_NONE;
300 : }
301 :
302 0 : static void py_tevent_signal_handler(struct tevent_context *ev,
303 : struct tevent_signal *se,
304 : int signum,
305 : int count,
306 : void *siginfo,
307 : void *private_data)
308 : {
309 0 : PyObject *callback = (PyObject *)private_data, *ret;
310 :
311 0 : ret = PyObject_CallFunction(callback, discard_const_p(char, "ii"), signum, count);
312 0 : Py_XDECREF(ret);
313 0 : }
314 :
315 1 : static void py_tevent_signal_dealloc(TeventSignal_Object *self)
316 : {
317 1 : talloc_free(self->signal);
318 1 : PyObject_Del(self);
319 1 : }
320 :
321 : static PyTypeObject TeventSignal_Type = {
322 : .tp_name = "tevent.Signal",
323 : .tp_basicsize = sizeof(TeventSignal_Object),
324 : .tp_dealloc = (destructor)py_tevent_signal_dealloc,
325 : .tp_flags = Py_TPFLAGS_DEFAULT,
326 : };
327 :
328 1 : static PyObject *py_tevent_context_add_signal(TeventContext_Object *self, PyObject *args)
329 : {
330 : int signum, sa_flags;
331 : PyObject *handler;
332 : struct tevent_signal *sig;
333 : TeventSignal_Object *ret;
334 :
335 1 : if (!PyArg_ParseTuple(args, "iiO", &signum, &sa_flags, &handler))
336 0 : return NULL;
337 :
338 1 : Py_INCREF(handler);
339 1 : sig = tevent_add_signal(self->ev, NULL, signum, sa_flags,
340 : py_tevent_signal_handler, handler);
341 :
342 1 : ret = PyObject_New(TeventSignal_Object, &TeventSignal_Type);
343 1 : if (ret == NULL) {
344 0 : PyErr_NoMemory();
345 0 : talloc_free(sig);
346 0 : return NULL;
347 : }
348 :
349 1 : ret->signal = sig;
350 :
351 1 : return (PyObject *)ret;
352 : }
353 :
354 4 : static void py_timer_handler(struct tevent_context *ev,
355 : struct tevent_timer *te,
356 : struct timeval current_time,
357 : void *private_data)
358 : {
359 4 : TeventTimer_Object *self = private_data;
360 : PyObject *ret;
361 :
362 4 : ret = PyObject_CallFunction(self->callback, discard_const_p(char, "l"), te);
363 4 : if (ret == NULL) {
364 : /* No Python stack to propagate exception to; just print traceback */
365 0 : PyErr_PrintEx(0);
366 : }
367 4 : Py_XDECREF(ret);
368 4 : }
369 :
370 5 : static void py_tevent_timer_dealloc(TeventTimer_Object *self)
371 : {
372 5 : if (self->timer) {
373 0 : talloc_free(self->timer);
374 : }
375 5 : Py_DECREF(self->callback);
376 5 : PyObject_Del(self);
377 5 : }
378 :
379 0 : static int py_tevent_timer_traverse(TeventTimer_Object *self, visitproc visit, void *arg)
380 : {
381 0 : Py_VISIT(self->callback);
382 0 : return 0;
383 : }
384 :
385 4 : static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self,
386 : PyObject *Py_UNUSED(ignored))
387 : {
388 4 : return PyBool_FromLong(self->timer != NULL);
389 : }
390 :
391 : struct PyGetSetDef py_tevent_timer_getset[] = {
392 : {
393 : .name = discard_const_p(char, "active"),
394 : .get = (getter)py_tevent_timer_get_active,
395 : .doc = discard_const_p(char, "true if the timer is scheduled to run"),
396 : },
397 : {0},
398 : };
399 :
400 : static PyTypeObject TeventTimer_Type = {
401 : .tp_name = "tevent.Timer",
402 : .tp_basicsize = sizeof(TeventTimer_Object),
403 : .tp_dealloc = (destructor)py_tevent_timer_dealloc,
404 : .tp_traverse = (traverseproc)py_tevent_timer_traverse,
405 : .tp_getset = py_tevent_timer_getset,
406 : .tp_flags = Py_TPFLAGS_DEFAULT,
407 : };
408 :
409 : struct TeventTimer_Object_ref {
410 : TeventTimer_Object *obj;
411 : };
412 :
413 5 : static int TeventTimer_Object_ref_destructor(struct TeventTimer_Object_ref *ref)
414 : {
415 5 : ref->obj->timer = NULL;
416 5 : Py_DECREF(ref->obj);
417 5 : return 0;
418 : }
419 :
420 5 : static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self,
421 : struct timeval next_event,
422 : PyObject *callback)
423 : {
424 : /* Ownership notes:
425 : *
426 : * There are 5 pieces in play; two tevent contexts and 3 Python objects:
427 : * - The tevent timer
428 : * - The tevent context
429 : * - The Python context -- "self"
430 : * - The Python timer (TeventTimer_Object) -- "ret"
431 : * - The Python callback function -- "callback"
432 : *
433 : * We only use the Python context for getting the tevent context,
434 : * afterwards it can be destroyed.
435 : *
436 : * The tevent context owns the tevent timer.
437 : *
438 : * The tevent timer holds a reference to the Python timer, so the Python
439 : * timer must always outlive the tevent timer.
440 : * The Python timer has a pointer to the tevent timer; a destructor is
441 : * used to set this to NULL when the tevent timer is deallocated.
442 : *
443 : * The tevent timer can be deallocated in these cases:
444 : * 1) when the context is destroyed
445 : * 2) after the event fires
446 : * Posssibly, API might be added to cancel (free the tevent timer).
447 : *
448 : * The Python timer holds a reference to the callback.
449 : */
450 : TeventTimer_Object *ret;
451 : struct TeventTimer_Object_ref *ref;
452 :
453 5 : ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type);
454 5 : if (ret == NULL) {
455 0 : PyErr_NoMemory();
456 0 : return NULL;
457 : }
458 5 : Py_INCREF(callback);
459 5 : ret->callback = callback;
460 5 : ret->timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler,
461 : ret);
462 5 : if (ret->timer == NULL) {
463 0 : Py_DECREF(ret);
464 0 : PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer");
465 0 : return NULL;
466 : }
467 5 : ref = talloc(ret->timer, struct TeventTimer_Object_ref);
468 5 : if (ref == NULL) {
469 0 : talloc_free(ret->timer);
470 0 : Py_DECREF(ret);
471 0 : PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer");
472 0 : return NULL;
473 : }
474 5 : Py_INCREF(ret);
475 5 : ref->obj = ret;
476 :
477 5 : talloc_set_destructor(ref, TeventTimer_Object_ref_destructor);
478 :
479 5 : return (PyObject *)ret;
480 : }
481 :
482 3 : static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args)
483 : {
484 : struct timeval next_event;
485 : PyObject *callback;
486 : double secs, usecs;
487 3 : if (!PyArg_ParseTuple(args, "dO", &secs, &callback)){
488 0 : return NULL;
489 : }
490 3 : next_event.tv_sec = secs;
491 3 : usecs = (secs - next_event.tv_sec) * 1000000.0;
492 3 : next_event.tv_usec = usecs;
493 3 : return py_tevent_context_add_timer_internal(self, next_event, callback);
494 : }
495 :
496 2 : static PyObject *py_tevent_context_add_timer_offset(TeventContext_Object *self, PyObject *args)
497 : {
498 : struct timeval next_event;
499 : double offset;
500 : int seconds;
501 : PyObject *callback;
502 2 : if (!PyArg_ParseTuple(args, "dO", &offset, &callback))
503 0 : return NULL;
504 :
505 2 : seconds = offset;
506 2 : offset -= seconds;
507 2 : next_event = tevent_timeval_current_ofs(seconds, (int)(offset*1000000));
508 2 : return py_tevent_context_add_timer_internal(self, next_event, callback);
509 : }
510 :
511 0 : static void py_fd_handler(struct tevent_context *ev,
512 : struct tevent_fd *fde,
513 : uint16_t flags,
514 : void *private_data)
515 : {
516 0 : PyObject *callback = private_data, *ret;
517 :
518 0 : ret = PyObject_CallFunction(callback, discard_const_p(char, "i"), flags);
519 0 : Py_XDECREF(ret);
520 0 : }
521 :
522 0 : static void py_tevent_fp_dealloc(TeventFd_Object *self)
523 : {
524 0 : talloc_free(self->fd);
525 0 : PyObject_Del(self);
526 0 : }
527 :
528 : static PyTypeObject TeventFd_Type = {
529 : .tp_name = "tevent.Fd",
530 : .tp_basicsize = sizeof(TeventFd_Object),
531 : .tp_dealloc = (destructor)py_tevent_fp_dealloc,
532 : .tp_flags = Py_TPFLAGS_DEFAULT,
533 : };
534 :
535 0 : static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args)
536 : {
537 : int fd, flags;
538 : PyObject *handler;
539 : struct tevent_fd *tfd;
540 : TeventFd_Object *ret;
541 :
542 0 : if (!PyArg_ParseTuple(args, "iiO", &fd, &flags, &handler))
543 0 : return NULL;
544 :
545 0 : tfd = tevent_add_fd(self->ev, NULL, fd, flags, py_fd_handler, handler);
546 0 : if (tfd == NULL) {
547 0 : PyErr_SetNone(PyExc_RuntimeError);
548 0 : return NULL;
549 : }
550 :
551 0 : ret = PyObject_New(TeventFd_Object, &TeventFd_Type);
552 0 : if (ret == NULL) {
553 0 : talloc_free(tfd);
554 0 : return NULL;
555 : }
556 0 : ret->fd = tfd;
557 :
558 0 : return (PyObject *)ret;
559 : }
560 :
561 : static PyMethodDef py_tevent_context_methods[] = {
562 : { "reinitialise", (PyCFunction)py_tevent_context_reinitialise,
563 : METH_NOARGS,
564 : "S.reinitialise()" },
565 : { "wakeup_send", (PyCFunction)py_tevent_context_wakeup_send,
566 : METH_VARARGS, "S.wakeup_send(wakeup_time) -> req" },
567 : { "loop_wait", (PyCFunction)py_tevent_context_loop_wait,
568 : METH_NOARGS, "S.loop_wait()" },
569 : { "loop_once", (PyCFunction)py_tevent_context_loop_once,
570 : METH_NOARGS, "S.loop_once()" },
571 : { "add_signal", (PyCFunction)py_tevent_context_add_signal,
572 : METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" },
573 : { "add_timer", (PyCFunction)py_tevent_context_add_timer,
574 : METH_VARARGS, "S.add_timer(next_event, handler) -> timer" },
575 : { "add_timer_offset", (PyCFunction)py_tevent_context_add_timer_offset,
576 : METH_VARARGS, "S.add_timer_offset(offset_seconds, handler) -> timer" },
577 : { "add_fd", (PyCFunction)py_tevent_context_add_fd,
578 : METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" },
579 : {0},
580 : };
581 :
582 0 : static PyObject *py_tevent_req_wakeup_recv(PyObject *self,
583 : PyObject *Py_UNUSED(ignored))
584 : {
585 : /* FIXME */
586 0 : Py_RETURN_NONE;
587 : }
588 :
589 0 : static PyObject *py_tevent_req_received(PyObject *self,
590 : PyObject *Py_UNUSED(ignored))
591 : {
592 : /* FIXME */
593 0 : Py_RETURN_NONE;
594 : }
595 :
596 0 : static PyObject *py_tevent_req_is_error(PyObject *self,
597 : PyObject *Py_UNUSED(ignored))
598 : {
599 : /* FIXME */
600 0 : Py_RETURN_NONE;
601 : }
602 :
603 0 : static PyObject *py_tevent_req_poll(PyObject *self,
604 : PyObject *Py_UNUSED(ignored))
605 : {
606 : /* FIXME */
607 0 : Py_RETURN_NONE;
608 : }
609 :
610 0 : static PyObject *py_tevent_req_is_in_progress(PyObject *self,
611 : PyObject *Py_UNUSED(ignored))
612 : {
613 : /* FIXME */
614 0 : Py_RETURN_NONE;
615 : }
616 :
617 : static PyGetSetDef py_tevent_req_getsetters[] = {
618 : {
619 : .name = discard_const_p(char, "in_progress"),
620 : .get = (getter)py_tevent_req_is_in_progress,
621 : .doc = discard_const_p(char, "Whether the request is in progress"),
622 : },
623 : {0}
624 : };
625 :
626 0 : static PyObject *py_tevent_req_post(PyObject *self, PyObject *args)
627 : {
628 : /* FIXME */
629 0 : Py_RETURN_NONE;
630 : }
631 :
632 0 : static PyObject *py_tevent_req_set_error(PyObject *self, PyObject *args)
633 : {
634 : /* FIXME */
635 0 : Py_RETURN_NONE;
636 : }
637 :
638 0 : static PyObject *py_tevent_req_done(PyObject *self,
639 : PyObject *Py_UNUSED(ignored))
640 : {
641 : /* FIXME */
642 0 : Py_RETURN_NONE;
643 : }
644 :
645 0 : static PyObject *py_tevent_req_notify_callback(PyObject *self,
646 : PyObject *Py_UNUSED(ignored))
647 : {
648 : /* FIXME */
649 0 : Py_RETURN_NONE;
650 : }
651 :
652 0 : static PyObject *py_tevent_req_set_endtime(PyObject *self, PyObject *args)
653 : {
654 : /* FIXME */
655 0 : Py_RETURN_NONE;
656 : }
657 :
658 0 : static PyObject *py_tevent_req_cancel(TeventReq_Object *self,
659 : PyObject *Py_UNUSED(ignored))
660 : {
661 0 : if (!tevent_req_cancel(self->req)) {
662 0 : PyErr_SetNone(PyExc_RuntimeError);
663 0 : return NULL;
664 : }
665 0 : Py_RETURN_NONE;
666 : }
667 :
668 : static PyMethodDef py_tevent_req_methods[] = {
669 : { "wakeup_recv", (PyCFunction)py_tevent_req_wakeup_recv,
670 : METH_NOARGS,
671 : "Wakeup received" },
672 : { "received", (PyCFunction)py_tevent_req_received,
673 : METH_NOARGS,
674 : "Receive finished" },
675 : { "is_error", (PyCFunction)py_tevent_req_is_error, METH_NOARGS,
676 : "is_error() -> (error, state)" },
677 : { "poll", (PyCFunction)py_tevent_req_poll, METH_VARARGS,
678 : "poll(ctx)" },
679 : { "post", (PyCFunction)py_tevent_req_post, METH_VARARGS,
680 : "post(ctx) -> req" },
681 : { "set_error", (PyCFunction)py_tevent_req_set_error, METH_VARARGS,
682 : "set_error(error)" },
683 : { "done", (PyCFunction)py_tevent_req_done, METH_NOARGS,
684 : "done()" },
685 : { "notify_callback", (PyCFunction)py_tevent_req_notify_callback,
686 : METH_NOARGS, "notify_callback()" },
687 : { "set_endtime", (PyCFunction)py_tevent_req_set_endtime,
688 : METH_VARARGS, "set_endtime(ctx, endtime)" },
689 : { "cancel", (PyCFunction)py_tevent_req_cancel,
690 : METH_NOARGS, "cancel()" },
691 : {0}
692 : };
693 :
694 0 : static void py_tevent_req_dealloc(TeventReq_Object *self)
695 : {
696 0 : talloc_free(self->req);
697 0 : PyObject_DEL(self);
698 0 : }
699 :
700 : static PyTypeObject TeventReq_Type = {
701 : .tp_name = "tevent.Request",
702 : .tp_basicsize = sizeof(TeventReq_Object),
703 : .tp_methods = py_tevent_req_methods,
704 : .tp_dealloc = (destructor)py_tevent_req_dealloc,
705 : .tp_getset = py_tevent_req_getsetters,
706 : /* FIXME: .tp_new = py_tevent_req_new, */
707 : };
708 :
709 0 : static PyObject *py_tevent_queue_get_length(TeventQueue_Object *self,
710 : PyObject *Py_UNUSED(ignored))
711 : {
712 0 : return PyLong_FromLong(tevent_queue_length(self->queue));
713 : }
714 :
715 : static PyGetSetDef py_tevent_queue_getsetters[] = {
716 : {
717 : .name = discard_const_p(char, "length"),
718 : .get = (getter)py_tevent_queue_get_length,
719 : .doc = discard_const_p(char, "The number of elements in the queue."),
720 : },
721 : {0},
722 : };
723 :
724 0 : static void py_tevent_queue_dealloc(TeventQueue_Object *self)
725 : {
726 0 : talloc_free(self->queue);
727 0 : PyObject_Del(self);
728 0 : }
729 :
730 : static PyTypeObject TeventQueue_Type = {
731 : .tp_name = "tevent.Queue",
732 : .tp_basicsize = sizeof(TeventQueue_Object),
733 : .tp_dealloc = (destructor)py_tevent_queue_dealloc,
734 : .tp_flags = Py_TPFLAGS_DEFAULT,
735 : .tp_getset = py_tevent_queue_getsetters,
736 : .tp_methods = py_tevent_queue_methods,
737 : };
738 :
739 1 : static PyObject *py_tevent_context_signal_support(PyObject *_self,
740 : PyObject *Py_UNUSED(ignored))
741 : {
742 1 : TeventContext_Object *self = (TeventContext_Object *)_self;
743 1 : return PyBool_FromLong(tevent_signal_support(self->ev));
744 : }
745 :
746 : static PyGetSetDef py_tevent_context_getsetters[] = {
747 : {
748 : .name = discard_const_p(char, "signal_support"),
749 : .get = PY_DISCARD_FUNC_SIG(getter,
750 : py_tevent_context_signal_support),
751 : .doc = discard_const_p(char, "if this platform and tevent context support signal handling"),
752 : },
753 : {0}
754 : };
755 :
756 10 : static void py_tevent_context_dealloc(TeventContext_Object *self)
757 : {
758 10 : talloc_free(self->ev);
759 10 : PyObject_Del(self);
760 10 : }
761 :
762 10 : static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
763 : {
764 10 : const char * const kwnames[] = { "name", NULL };
765 10 : char *name = NULL;
766 : struct tevent_context *ev;
767 : TeventContext_Object *ret;
768 :
769 10 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &name))
770 0 : return NULL;
771 :
772 10 : if (name == NULL) {
773 9 : ev = tevent_context_init(NULL);
774 : } else {
775 1 : ev = tevent_context_init_byname(NULL, name);
776 : }
777 :
778 10 : if (ev == NULL) {
779 0 : PyErr_SetNone(PyExc_RuntimeError);
780 0 : return NULL;
781 : }
782 :
783 10 : ret = PyObject_New(TeventContext_Object, type);
784 10 : if (ret == NULL) {
785 0 : PyErr_NoMemory();
786 0 : talloc_free(ev);
787 0 : return NULL;
788 : }
789 :
790 10 : ret->ev = ev;
791 10 : return (PyObject *)ret;
792 : }
793 :
794 : static PyTypeObject TeventContext_Type = {
795 : .tp_name = "tevent.Context",
796 : .tp_new = py_tevent_context_new,
797 : .tp_basicsize = sizeof(TeventContext_Object),
798 : .tp_dealloc = (destructor)py_tevent_context_dealloc,
799 : .tp_methods = py_tevent_context_methods,
800 : .tp_getset = py_tevent_context_getsetters,
801 : .tp_flags = Py_TPFLAGS_DEFAULT,
802 : };
803 :
804 0 : static PyObject *py_set_default_backend(PyObject *self, PyObject *args)
805 : {
806 : char *backend_name;
807 0 : if (!PyArg_ParseTuple(args, "s", &backend_name))
808 0 : return NULL;
809 :
810 0 : tevent_set_default_backend(backend_name);
811 :
812 0 : Py_RETURN_NONE;
813 : }
814 :
815 2 : static PyObject *py_backend_list(PyObject *self,
816 : PyObject *Py_UNUSED(ignored))
817 : {
818 2 : PyObject *ret = NULL;
819 2 : PyObject *string = NULL;
820 : int i, result;
821 2 : const char **backends = NULL;
822 :
823 2 : ret = PyList_New(0);
824 2 : if (ret == NULL) {
825 0 : return NULL;
826 : }
827 :
828 2 : backends = tevent_backend_list(NULL);
829 2 : if (backends == NULL) {
830 0 : PyErr_SetNone(PyExc_RuntimeError);
831 0 : goto err;
832 : }
833 10 : for (i = 0; backends[i]; i++) {
834 8 : string = PyUnicode_FromString(backends[i]);
835 8 : if (!string) {
836 0 : goto err;
837 : }
838 8 : result = PyList_Append(ret, string);
839 8 : if (result) {
840 0 : goto err;
841 : }
842 8 : Py_DECREF(string);
843 8 : string = NULL;
844 : }
845 :
846 2 : talloc_free(backends);
847 :
848 2 : return ret;
849 :
850 0 : err:
851 0 : Py_XDECREF(ret);
852 0 : Py_XDECREF(string);
853 0 : talloc_free(backends);
854 0 : return NULL;
855 : }
856 :
857 : static PyMethodDef tevent_methods[] = {
858 : { "register_backend", (PyCFunction)py_register_backend, METH_VARARGS,
859 : "register_backend(backend)" },
860 : { "set_default_backend", (PyCFunction)py_set_default_backend,
861 : METH_VARARGS, "set_default_backend(backend)" },
862 : { "backend_list", (PyCFunction)py_backend_list,
863 : METH_NOARGS, "backend_list() -> list" },
864 : {0},
865 : };
866 :
867 : #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
868 :
869 : #if PY_MAJOR_VERSION >= 3
870 : static struct PyModuleDef moduledef = {
871 : PyModuleDef_HEAD_INIT,
872 : .m_name = "_tevent",
873 : .m_doc = MODULE_DOC,
874 : .m_size = -1,
875 : .m_methods = tevent_methods,
876 : };
877 : #endif
878 :
879 : PyObject * module_init(void);
880 1 : PyObject * module_init(void)
881 : {
882 : PyObject *m;
883 :
884 1 : if (PyType_Ready(&TeventContext_Type) < 0)
885 0 : return NULL;
886 :
887 1 : if (PyType_Ready(&TeventQueue_Type) < 0)
888 0 : return NULL;
889 :
890 1 : if (PyType_Ready(&TeventReq_Type) < 0)
891 0 : return NULL;
892 :
893 1 : if (PyType_Ready(&TeventSignal_Type) < 0)
894 0 : return NULL;
895 :
896 1 : if (PyType_Ready(&TeventTimer_Type) < 0)
897 0 : return NULL;
898 :
899 1 : if (PyType_Ready(&TeventFd_Type) < 0)
900 0 : return NULL;
901 :
902 : #if PY_MAJOR_VERSION >= 3
903 1 : m = PyModule_Create(&moduledef);
904 : #else
905 : m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC);
906 : #endif
907 1 : if (m == NULL)
908 0 : return NULL;
909 :
910 1 : Py_INCREF(&TeventContext_Type);
911 1 : PyModule_AddObject(m, "Context", (PyObject *)&TeventContext_Type);
912 :
913 1 : Py_INCREF(&TeventQueue_Type);
914 1 : PyModule_AddObject(m, "Queue", (PyObject *)&TeventQueue_Type);
915 :
916 1 : Py_INCREF(&TeventReq_Type);
917 1 : PyModule_AddObject(m, "Request", (PyObject *)&TeventReq_Type);
918 :
919 1 : Py_INCREF(&TeventSignal_Type);
920 1 : PyModule_AddObject(m, "Signal", (PyObject *)&TeventSignal_Type);
921 :
922 1 : Py_INCREF(&TeventTimer_Type);
923 1 : PyModule_AddObject(m, "Timer", (PyObject *)&TeventTimer_Type);
924 :
925 1 : Py_INCREF(&TeventFd_Type);
926 1 : PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type);
927 :
928 1 : PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
929 :
930 1 : return m;
931 : }
932 :
933 : #if PY_MAJOR_VERSION >= 3
934 : PyMODINIT_FUNC PyInit__tevent(void);
935 1 : PyMODINIT_FUNC PyInit__tevent(void)
936 : {
937 1 : return module_init();
938 : }
939 : #else
940 : void init_tevent(void);
941 : void init_tevent(void)
942 : {
943 : module_init();
944 : }
945 : #endif
|