File: | build/temp.linux-x86_64-3.8/../../dbus_bindings/server.c |
Warning: | line 123, column 27 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Implementation of the _dbus_bindings Server type, a Python wrapper | |||
2 | * for DBusServer. | |||
3 | * | |||
4 | * Copyright (C) 2008 Openismus GmbH <http://openismus.com/> | |||
5 | * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> | |||
6 | * | |||
7 | * SPDX-License-Identifier: MIT | |||
8 | * | |||
9 | * Permission is hereby granted, free of charge, to any person | |||
10 | * obtaining a copy of this software and associated documentation | |||
11 | * files (the "Software"), to deal in the Software without | |||
12 | * restriction, including without limitation the rights to use, copy, | |||
13 | * modify, merge, publish, distribute, sublicense, and/or sell copies | |||
14 | * of the Software, and to permit persons to whom the Software is | |||
15 | * furnished to do so, subject to the following conditions: | |||
16 | * | |||
17 | * The above copyright notice and this permission notice shall be | |||
18 | * included in all copies or substantial portions of the Software. | |||
19 | * | |||
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |||
24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |||
25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
27 | * DEALINGS IN THE SOFTWARE. | |||
28 | */ | |||
29 | ||||
30 | #include "dbus_bindings-internal.h" | |||
31 | ||||
32 | /* Server definition ================================================ */ | |||
33 | ||||
34 | typedef struct { | |||
35 | PyObject_HEADPyObject ob_base; | |||
36 | DBusServer *server; | |||
37 | ||||
38 | /* The Connection subtype for which this Server is a factory */ | |||
39 | PyObject *conn_class; | |||
40 | ||||
41 | /* Weak-references list to make server weakly referenceable */ | |||
42 | PyObject *weaklist; | |||
43 | ||||
44 | PyObject *mainloop; | |||
45 | } Server; | |||
46 | ||||
47 | PyDoc_STRVAR(Server_tp_doc,static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n" | |||
48 | "A D-Bus server.\n"static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n" | |||
49 | "\n"static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n" | |||
50 | "::\n"static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n" | |||
51 | "\n"static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n" | |||
52 | " Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n"static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n" | |||
53 | " -> Server\n"static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n" | |||
54 | )static const char Server_tp_doc[] = "A D-Bus server.\n""\n""::\n" "\n"" Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n" " -> Server\n"; | |||
55 | ||||
56 | /* D-Bus Server user data slot, containing an owned reference to either | |||
57 | * the Server, or a weakref to the Server. | |||
58 | */ | |||
59 | static dbus_int32_t _server_python_slot; | |||
60 | ||||
61 | /* C API for main-loop hooks ======================================== */ | |||
62 | ||||
63 | /* Return a borrowed reference to the DBusServer which underlies this | |||
64 | * Server. */ | |||
65 | DBusServer * | |||
66 | DBusPyServer_BorrowDBusServer(PyObject *self) | |||
67 | { | |||
68 | DBusServer *dbs; | |||
69 | ||||
70 | TRACE(self)do {} while (0); | |||
71 | if (!DBusPyServer_Check(self)) { | |||
72 | PyErr_SetString(PyExc_TypeError, "A dbus.server.Server is required"); | |||
73 | return NULL((void*)0); | |||
74 | } | |||
75 | dbs = ((Server *)self)->server; | |||
76 | if (!dbs) { | |||
77 | PyErr_SetString(PyExc_RuntimeError, "Server is in an invalid " | |||
78 | "state: no DBusServer"); | |||
79 | return NULL((void*)0); | |||
80 | } | |||
81 | return dbs; | |||
82 | } | |||
83 | ||||
84 | /* Internal C API =================================================== */ | |||
85 | ||||
86 | static dbus_bool_t | |||
87 | DBusPyServer_set_auth_mechanisms(Server *self, | |||
88 | PyObject *auth_mechanisms) | |||
89 | { | |||
90 | PyObject *fast_seq = NULL((void*)0), *references = NULL((void*)0); | |||
91 | Py_ssize_t length; | |||
92 | Py_ssize_t i; | |||
93 | /* a mutable array of constant strings */ | |||
94 | const char **list = NULL((void*)0); | |||
95 | dbus_bool_t ret = FALSE0; | |||
96 | ||||
97 | fast_seq = PySequence_Fast(auth_mechanisms, | |||
98 | "Expecting sequence for auth_mechanisms parameter"); | |||
99 | ||||
100 | if (!fast_seq) | |||
101 | return FALSE0; | |||
102 | ||||
103 | length = PySequence_Fast_GET_SIZE(fast_seq)(((((((PyObject*)(fast_seq))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? ((((PyVarObject*)(fast_seq))-> ob_size)) : (((PyVarObject*)(((PyTupleObject *)(fast_seq))))-> ob_size)); | |||
104 | ||||
105 | list = calloc (length + 1, sizeof (char *)); | |||
106 | ||||
107 | if (!list) { | |||
108 | PyErr_NoMemory(); | |||
109 | goto finally; | |||
110 | } | |||
111 | ||||
112 | if (!(references = PyTuple_New(length))) | |||
113 | goto finally; | |||
114 | ||||
115 | for (i = 0; i < length; ++i) { | |||
116 | PyObject *am, *am_as_bytes; | |||
117 | ||||
118 | am = PySequence_Fast_GET_ITEM(auth_mechanisms, i)(((((((PyObject*)(auth_mechanisms))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(auth_mechanisms ))->ob_item[i]) : (((PyTupleObject *)(auth_mechanisms))-> ob_item[i])); | |||
119 | if (!am) | |||
120 | goto finally; | |||
121 | ||||
122 | if (PyUnicode_Check(am)((((((PyObject*)(am))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
123 | am_as_bytes = PyUnicode_AsUTF8String(am); | |||
| ||||
124 | if (!am_as_bytes) | |||
125 | goto finally; | |||
126 | } | |||
127 | else { | |||
128 | am_as_bytes = am; | |||
129 | Py_INCREF(am_as_bytes)_Py_INCREF(((PyObject*)(am_as_bytes))); | |||
130 | } | |||
131 | list[i] = PyBytes_AsString(am_as_bytes); | |||
132 | if (!list[i]) | |||
133 | goto finally; | |||
134 | ||||
135 | PyTuple_SET_ITEM(references, i, am_as_bytes)PyTuple_SetItem(references, i, am_as_bytes); | |||
136 | } | |||
137 | ||||
138 | list[length] = NULL((void*)0); | |||
139 | ||||
140 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
141 | dbus_server_set_auth_mechanisms(self->server, list); | |||
142 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
143 | ||||
144 | ret = TRUE1; | |||
145 | ||||
146 | finally: | |||
147 | if (list) | |||
148 | free (list); | |||
149 | Py_CLEAR(fast_seq)do { PyObject *_py_tmp = ((PyObject*)(fast_seq)); if (_py_tmp != ((void*)0)) { (fast_seq) = ((void*)0); _Py_DECREF(((PyObject *)(_py_tmp))); } } while (0); | |||
150 | Py_CLEAR(references)do { PyObject *_py_tmp = ((PyObject*)(references)); if (_py_tmp != ((void*)0)) { (references) = ((void*)0); _Py_DECREF(((PyObject *)(_py_tmp))); } } while (0); | |||
151 | return ret; | |||
152 | } | |||
153 | ||||
154 | /* Return a new reference to a Python Server or subclass corresponding | |||
155 | * to the DBusServer server. For use in callbacks. | |||
156 | * | |||
157 | * Raises AssertionError if the DBusServer does not have a Server. | |||
158 | */ | |||
159 | static PyObject * | |||
160 | DBusPyServer_ExistingFromDBusServer(DBusServer *server) | |||
161 | { | |||
162 | PyObject *self, *ref; | |||
163 | ||||
164 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
165 | ref = (PyObject *)dbus_server_get_data(server, | |||
166 | _server_python_slot); | |||
167 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
168 | if (ref) { | |||
169 | DBG("(DBusServer *)%p has weak reference at %p", server, ref)do {} while (0); | |||
170 | self = PyWeakref_GetObject(ref); /* still a borrowed ref */ | |||
171 | if (self && self != Py_None(&_Py_NoneStruct) && DBusPyServer_Check(self)) { | |||
172 | DBG("(DBusServer *)%p has weak reference at %p pointing to %p",do {} while (0) | |||
173 | server, ref, self)do {} while (0); | |||
174 | TRACE(self)do {} while (0); | |||
175 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
176 | TRACE(self)do {} while (0); | |||
177 | return self; | |||
178 | } | |||
179 | } | |||
180 | ||||
181 | PyErr_SetString(PyExc_AssertionError, | |||
182 | "D-Bus server does not have a Server " | |||
183 | "instance associated with it"); | |||
184 | return NULL((void*)0); | |||
185 | } | |||
186 | ||||
187 | static void | |||
188 | DBusPyServer_new_connection_cb(DBusServer *server, | |||
189 | DBusConnection *conn, | |||
190 | void *data UNUSED__attribute__((__unused__))) | |||
191 | { | |||
192 | PyGILState_STATE gil = PyGILState_Ensure(); | |||
193 | PyObject *self = NULL((void*)0); | |||
194 | PyObject *method = NULL((void*)0); | |||
195 | ||||
196 | self = DBusPyServer_ExistingFromDBusServer(server); | |||
197 | if (!self) goto out; | |||
198 | TRACE(self)do {} while (0); | |||
199 | ||||
200 | method = PyObject_GetAttrString(self, "_on_new_connection"); | |||
201 | TRACE(method)do {} while (0); | |||
202 | ||||
203 | if (method) { | |||
204 | PyObject *conn_class = ((Server *)self)->conn_class; | |||
205 | PyObject *wrapper = DBusPyLibDBusConnection_New(conn); | |||
206 | PyObject *conn_obj; | |||
207 | PyObject *result; | |||
208 | ||||
209 | if (!wrapper) | |||
210 | goto out; | |||
211 | ||||
212 | conn_obj = PyObject_CallFunctionObjArgs((PyObject *)conn_class, | |||
213 | wrapper, ((Server*) self)->mainloop, NULL((void*)0)); | |||
214 | Py_CLEAR(wrapper)do { PyObject *_py_tmp = ((PyObject*)(wrapper)); if (_py_tmp != ((void*)0)) { (wrapper) = ((void*)0); _Py_DECREF(((PyObject* )(_py_tmp))); } } while (0); | |||
215 | ||||
216 | if (!conn_obj) | |||
217 | goto out; | |||
218 | ||||
219 | result = PyObject_CallFunctionObjArgs(method, conn_obj, NULL((void*)0)); | |||
220 | Py_CLEAR (conn_obj)do { PyObject *_py_tmp = ((PyObject*)(conn_obj)); if (_py_tmp != ((void*)0)) { (conn_obj) = ((void*)0); _Py_DECREF(((PyObject *)(_py_tmp))); } } while (0); | |||
221 | ||||
222 | /* discard result if not NULL, and fall through regardless */ | |||
223 | Py_CLEAR(result)do { PyObject *_py_tmp = ((PyObject*)(result)); if (_py_tmp != ((void*)0)) { (result) = ((void*)0); _Py_DECREF(((PyObject*) (_py_tmp))); } } while (0); | |||
224 | } | |||
225 | ||||
226 | out: | |||
227 | Py_CLEAR(method)do { PyObject *_py_tmp = ((PyObject*)(method)); if (_py_tmp != ((void*)0)) { (method) = ((void*)0); _Py_DECREF(((PyObject*) (_py_tmp))); } } while (0); | |||
228 | Py_CLEAR(self)do { PyObject *_py_tmp = ((PyObject*)(self)); if (_py_tmp != ( (void*)0)) { (self) = ((void*)0); _Py_DECREF(((PyObject*)(_py_tmp ))); } } while (0); | |||
229 | ||||
230 | if (PyErr_Occurred()) | |||
231 | PyErr_Print(); | |||
232 | ||||
233 | PyGILState_Release(gil); | |||
234 | } | |||
235 | ||||
236 | /* Return a new reference to a Python Server or subclass (given by cls) | |||
237 | * corresponding to the DBusServer server, which must have been newly | |||
238 | * created. For use by the Server constructor. | |||
239 | * | |||
240 | * Raises AssertionError if the DBusServer already has a Server. | |||
241 | * | |||
242 | * One reference to server is stolen - either the returned DBusPyServer | |||
243 | * claims it, or it's unreffed. | |||
244 | */ | |||
245 | static PyObject * | |||
246 | DBusPyServer_NewConsumingDBusServer(PyTypeObject *cls, | |||
247 | DBusServer *server, | |||
248 | PyObject *conn_class, | |||
249 | PyObject *mainloop, | |||
250 | PyObject *auth_mechanisms) | |||
251 | { | |||
252 | Server *self = NULL((void*)0); | |||
253 | PyObject *ref; | |||
254 | dbus_bool_t ok; | |||
255 | ||||
256 | DBG("%s(cls=%p, server=%p, mainloop=%p, auth_mechanisms=%p)",do {} while (0) | |||
257 | __func__, cls, server, mainloop, auth_mechanisms)do {} while (0); | |||
258 | DBUS_PY_RAISE_VIA_NULL_IF_FAIL(server)do { if (!(server)) { _dbus_py_assertion_failed("server"); return ((void*)0); } } while (0); | |||
259 | ||||
260 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
261 | ref = (PyObject *)dbus_server_get_data(server, | |||
262 | _server_python_slot); | |||
263 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
264 | if (ref) { | |||
265 | self = (Server *)PyWeakref_GetObject(ref); | |||
266 | ref = NULL((void*)0); | |||
267 | if (self && (PyObject *)self != Py_None(&_Py_NoneStruct)) { | |||
268 | self = NULL((void*)0); | |||
269 | PyErr_SetString(PyExc_AssertionError, | |||
270 | "Newly created D-Bus server already has a " | |||
271 | "Server instance associated with it"); | |||
272 | DBG("%s() fail - assertion failed, DBusPyServer has a DBusServer already", __func__)do {} while (0); | |||
273 | DBG_WHEREAMIdo {} while (0); | |||
274 | return NULL((void*)0); | |||
275 | } | |||
276 | } | |||
277 | ref = NULL((void*)0); | |||
278 | ||||
279 | /* Change mainloop from a borrowed reference to an owned reference */ | |||
280 | if (!mainloop || mainloop == Py_None(&_Py_NoneStruct)) { | |||
281 | mainloop = dbus_py_get_default_main_loop(); | |||
282 | ||||
283 | if (!mainloop || mainloop == Py_None(&_Py_NoneStruct)) { | |||
284 | PyErr_SetString(PyExc_RuntimeError, | |||
285 | "To run a D-Bus server, you need to either " | |||
286 | "pass mainloop=... to the constructor or call " | |||
287 | "dbus.set_default_main_loop(...)"); | |||
288 | goto err; | |||
289 | } | |||
290 | } | |||
291 | else { | |||
292 | Py_INCREF(mainloop)_Py_INCREF(((PyObject*)(mainloop))); | |||
293 | } | |||
294 | ||||
295 | DBG("Constructing Server from DBusServer at %p", server)do {} while (0); | |||
296 | ||||
297 | self = (Server *)(cls->tp_alloc(cls, 0)); | |||
298 | if (!self) goto err; | |||
299 | TRACE(self)do {} while (0); | |||
300 | ||||
301 | DBG_WHEREAMIdo {} while (0); | |||
302 | ||||
303 | self->server = NULL((void*)0); | |||
304 | ||||
305 | Py_INCREF(conn_class)_Py_INCREF(((PyObject*)(conn_class))); | |||
306 | self->conn_class = conn_class; | |||
307 | ||||
308 | self->mainloop = mainloop; | |||
309 | mainloop = NULL((void*)0); /* don't DECREF it - the DBusServer owns it now */ | |||
310 | ||||
311 | ref = PyWeakref_NewRef((PyObject *)self, NULL((void*)0)); | |||
312 | if (!ref) goto err; | |||
313 | DBG("Created weak ref %p to (Server *)%p for (DBusServer *)%p",do {} while (0) | |||
314 | ref, self, server)do {} while (0); | |||
315 | ||||
316 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
317 | ok = dbus_server_set_data(server, _server_python_slot, | |||
318 | (void *)ref, | |||
319 | (DBusFreeFunction)dbus_py_take_gil_and_xdecref); | |||
320 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
321 | ||||
322 | if (ok) { | |||
323 | DBG("Attached weak ref %p ((Server *)%p) to (DBusServer *)%p",do {} while (0) | |||
324 | ref, self, server)do {} while (0); | |||
325 | ||||
326 | ref = NULL((void*)0); /* don't DECREF it - the DBusServer owns it now */ | |||
327 | } | |||
328 | else { | |||
329 | DBG("Failed to attached weak ref %p ((Server *)%p) to "do {} while (0) | |||
330 | "(DBusServer *)%p - will dispose of it", ref, self, server)do {} while (0); | |||
331 | PyErr_NoMemory(); | |||
332 | goto err; | |||
333 | } | |||
334 | ||||
335 | DBUS_PY_RAISE_VIA_GOTO_IF_FAIL(server, err)do { if (!(server)) { _dbus_py_assertion_failed("server"); goto err; } } while (0); | |||
336 | self->server = server; | |||
337 | /* the DBusPyServer will close it now */ | |||
338 | server = NULL((void*)0); | |||
339 | ||||
340 | if (self->mainloop != Py_None(&_Py_NoneStruct) && | |||
341 | !dbus_py_set_up_server((PyObject *)self, self->mainloop)) | |||
342 | goto err; | |||
343 | ||||
344 | if (auth_mechanisms && auth_mechanisms != Py_None(&_Py_NoneStruct) && | |||
345 | !DBusPyServer_set_auth_mechanisms(self, auth_mechanisms)) | |||
346 | goto err; | |||
347 | ||||
348 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
349 | dbus_server_set_new_connection_function(self->server, | |||
350 | DBusPyServer_new_connection_cb, | |||
351 | NULL((void*)0), NULL((void*)0)); | |||
352 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
353 | ||||
354 | DBG("%s() -> %p", __func__, self)do {} while (0); | |||
355 | TRACE(self)do {} while (0); | |||
356 | return (PyObject *)self; | |||
357 | ||||
358 | err: | |||
359 | DBG("Failed to construct Server from DBusServer at %p", server)do {} while (0); | |||
360 | Py_CLEAR(mainloop)do { PyObject *_py_tmp = ((PyObject*)(mainloop)); if (_py_tmp != ((void*)0)) { (mainloop) = ((void*)0); _Py_DECREF(((PyObject *)(_py_tmp))); } } while (0); | |||
361 | Py_CLEAR(self)do { PyObject *_py_tmp = ((PyObject*)(self)); if (_py_tmp != ( (void*)0)) { (self) = ((void*)0); _Py_DECREF(((PyObject*)(_py_tmp ))); } } while (0); | |||
362 | Py_CLEAR(ref)do { PyObject *_py_tmp = ((PyObject*)(ref)); if (_py_tmp != ( (void*)0)) { (ref) = ((void*)0); _Py_DECREF(((PyObject*)(_py_tmp ))); } } while (0); | |||
363 | ||||
364 | if (server) { | |||
365 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
366 | dbus_server_disconnect(server); | |||
367 | dbus_server_unref(server); | |||
368 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
369 | } | |||
370 | ||||
371 | DBG("%s() fail", __func__)do {} while (0); | |||
372 | DBG_WHEREAMIdo {} while (0); | |||
373 | return NULL((void*)0); | |||
374 | } | |||
375 | ||||
376 | /* Server type-methods ============================================== */ | |||
377 | ||||
378 | static PyObject * | |||
379 | Server_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) | |||
380 | { | |||
381 | DBusServer *server; | |||
382 | const char *address; | |||
383 | DBusError error; | |||
384 | PyObject *self, *conn_class, *mainloop = NULL((void*)0), *auth_mechanisms = NULL((void*)0); | |||
385 | static char *argnames[] = { "address", "connection_class", "mainloop", | |||
386 | "auth_mechanisms", NULL((void*)0)}; | |||
387 | ||||
388 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, kwargs, "sO|OO", argnames, | |||
| ||||
389 | &address, &conn_class, &mainloop, &auth_mechanisms)) { | |||
390 | return NULL((void*)0); | |||
391 | } | |||
392 | ||||
393 | if (!PyType_Check(conn_class)((((((PyObject*)(conn_class))->ob_type))->tp_flags & ((1UL << 31))) != 0) || | |||
394 | !PyType_IsSubtype((PyTypeObject *) conn_class, &DBusPyConnection_Type)) { | |||
395 | /* strictly speaking, it can be any subtype of | |||
396 | * _dbus_bindings._Connection - but nobody else should be subtyping | |||
397 | * that, so let's keep this slightly inaccurate message */ | |||
398 | PyErr_SetString(PyExc_TypeError, "connection_class must be " | |||
399 | "dbus.connection.Connection or a subtype"); | |||
400 | return NULL((void*)0); | |||
401 | } | |||
402 | ||||
403 | dbus_error_init(&error); | |||
404 | ||||
405 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
406 | server = dbus_server_listen(address, &error); | |||
407 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
408 | ||||
409 | if (!server) { | |||
410 | DBusPyException_ConsumeError(&error); | |||
411 | return NULL((void*)0); | |||
412 | } | |||
413 | ||||
414 | self = DBusPyServer_NewConsumingDBusServer(cls, server, conn_class, | |||
415 | mainloop, auth_mechanisms); | |||
416 | ||||
417 | if (!self) { | |||
418 | return NULL((void*)0); | |||
419 | } | |||
420 | ||||
421 | ((Server *)self)->weaklist = NULL((void*)0); | |||
422 | TRACE(self)do {} while (0); | |||
423 | ||||
424 | return self; | |||
425 | } | |||
426 | ||||
427 | /* Destructor */ | |||
428 | static void Server_tp_dealloc(Server *self) | |||
429 | { | |||
430 | DBusServer *server = self->server; | |||
431 | PyObject *et, *ev, *etb; | |||
432 | ||||
433 | /* avoid clobbering any pending exception */ | |||
434 | PyErr_Fetch(&et, &ev, &etb); | |||
435 | ||||
436 | if (self->weaklist) { | |||
437 | PyObject_ClearWeakRefs((PyObject *)self); | |||
438 | } | |||
439 | ||||
440 | TRACE(self)do {} while (0); | |||
441 | DBG("Deallocating Server at %p (DBusServer at %p)", self, server)do {} while (0); | |||
442 | DBG_WHEREAMIdo {} while (0); | |||
443 | ||||
444 | if (server) { | |||
445 | DBG("Server at %p has a server, disconnecting it...", self)do {} while (0); | |||
446 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
447 | dbus_server_disconnect(server); | |||
448 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
449 | } | |||
450 | ||||
451 | Py_CLEAR(self->mainloop)do { PyObject *_py_tmp = ((PyObject*)(self->mainloop)); if (_py_tmp != ((void*)0)) { (self->mainloop) = ((void*)0); _Py_DECREF (((PyObject*)(_py_tmp))); } } while (0); | |||
452 | ||||
453 | /* make sure to do this last to preserve the invariant that | |||
454 | * self->server is always non-NULL for any referenced Server. | |||
455 | */ | |||
456 | DBG("Server at %p: nulling self->server", self)do {} while (0); | |||
457 | self->server = NULL((void*)0); | |||
458 | ||||
459 | if (server) { | |||
460 | DBG("Server at %p: unreffing server", self)do {} while (0); | |||
461 | dbus_server_unref(server); | |||
462 | } | |||
463 | ||||
464 | DBG("Server at %p: freeing self", self)do {} while (0); | |||
465 | PyErr_Restore(et, ev, etb); | |||
466 | (Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free)((PyObject *)self); | |||
467 | } | |||
468 | ||||
469 | PyDoc_STRVAR(Server_disconnect__doc__,static const char Server_disconnect__doc__[] = "disconnect()\n\n" "Releases the server's address and stops listening for new clients.\n\n" "If called more than once, only the first call has an effect." | |||
470 | "disconnect()\n\n"static const char Server_disconnect__doc__[] = "disconnect()\n\n" "Releases the server's address and stops listening for new clients.\n\n" "If called more than once, only the first call has an effect." | |||
471 | "Releases the server's address and stops listening for new clients.\n\n"static const char Server_disconnect__doc__[] = "disconnect()\n\n" "Releases the server's address and stops listening for new clients.\n\n" "If called more than once, only the first call has an effect." | |||
472 | "If called more than once, only the first call has an effect.")static const char Server_disconnect__doc__[] = "disconnect()\n\n" "Releases the server's address and stops listening for new clients.\n\n" "If called more than once, only the first call has an effect."; | |||
473 | static PyObject * | |||
474 | Server_disconnect (Server *self, PyObject *args UNUSED__attribute__((__unused__))) | |||
475 | { | |||
476 | TRACE(self)do {} while (0); | |||
477 | if (self->server) { | |||
478 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
479 | dbus_server_disconnect(self->server); | |||
480 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
481 | } | |||
482 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
483 | } | |||
484 | ||||
485 | PyDoc_STRVAR(Server_get_address__doc__,static const char Server_get_address__doc__[] = "get_address() -> str\n\n" "Returns the address of the server." | |||
486 | "get_address() -> str\n\n"static const char Server_get_address__doc__[] = "get_address() -> str\n\n" "Returns the address of the server." | |||
487 | "Returns the address of the server.")static const char Server_get_address__doc__[] = "get_address() -> str\n\n" "Returns the address of the server."; | |||
488 | static PyObject * | |||
489 | Server_get_address(Server *self, PyObject *args UNUSED__attribute__((__unused__))) | |||
490 | { | |||
491 | const char *address; | |||
492 | ||||
493 | TRACE(self)do {} while (0); | |||
494 | DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server)do { if (!(self->server)) { _dbus_py_assertion_failed("self->server" ); return ((void*)0); } } while (0); | |||
495 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
496 | address = dbus_server_get_address(self->server); | |||
497 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
498 | ||||
499 | return PyUnicode_FromString(address); | |||
500 | } | |||
501 | ||||
502 | PyDoc_STRVAR(Server_get_id__doc__,static const char Server_get_id__doc__[] = "get_id() -> str\n\n" "Returns the unique ID of the server." | |||
503 | "get_id() -> str\n\n"static const char Server_get_id__doc__[] = "get_id() -> str\n\n" "Returns the unique ID of the server." | |||
504 | "Returns the unique ID of the server.")static const char Server_get_id__doc__[] = "get_id() -> str\n\n" "Returns the unique ID of the server."; | |||
505 | static PyObject * | |||
506 | Server_get_id(Server *self, PyObject *args UNUSED__attribute__((__unused__))) | |||
507 | { | |||
508 | const char *id; | |||
509 | ||||
510 | TRACE(self)do {} while (0); | |||
511 | DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server)do { if (!(self->server)) { _dbus_py_assertion_failed("self->server" ); return ((void*)0); } } while (0); | |||
512 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
513 | id = dbus_server_get_id(self->server); | |||
514 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
515 | ||||
516 | return PyUnicode_FromString(id); | |||
517 | } | |||
518 | ||||
519 | PyDoc_STRVAR(Server_get_is_connected__doc__,static const char Server_get_is_connected__doc__[] = "get_is_connected() -> bool\n\n" "Return true if this Server is still listening for new connections.\n" | |||
520 | "get_is_connected() -> bool\n\n"static const char Server_get_is_connected__doc__[] = "get_is_connected() -> bool\n\n" "Return true if this Server is still listening for new connections.\n" | |||
521 | "Return true if this Server is still listening for new connections.\n")static const char Server_get_is_connected__doc__[] = "get_is_connected() -> bool\n\n" "Return true if this Server is still listening for new connections.\n"; | |||
522 | static PyObject * | |||
523 | Server_get_is_connected (Server *self, PyObject *args UNUSED__attribute__((__unused__))) | |||
524 | { | |||
525 | dbus_bool_t ret; | |||
526 | ||||
527 | TRACE(self)do {} while (0); | |||
528 | DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server)do { if (!(self->server)) { _dbus_py_assertion_failed("self->server" ); return ((void*)0); } } while (0); | |||
529 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
530 | ret = dbus_server_get_is_connected(self->server); | |||
531 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
532 | return PyBool_FromLong(ret); | |||
533 | } | |||
534 | ||||
535 | /* Server type object =============================================== */ | |||
536 | ||||
537 | struct PyMethodDef DBusPyServer_tp_methods[] = { | |||
538 | #define ENTRY(name, flags) {#name, (PyCFunction) (void (*)(void))Server_##name, flags, Server_##name##__doc__} | |||
539 | ENTRY(disconnect, METH_NOARGS0x0004), | |||
540 | ENTRY(get_address, METH_NOARGS0x0004), | |||
541 | ENTRY(get_id, METH_NOARGS0x0004), | |||
542 | ENTRY(get_is_connected, METH_NOARGS0x0004), | |||
543 | {NULL((void*)0)}, | |||
544 | #undef ENTRY | |||
545 | }; | |||
546 | ||||
547 | PyTypeObject DBusPyServer_Type = { | |||
548 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | |||
549 | "_dbus_bindings._Server",/*tp_name*/ | |||
550 | sizeof(Server), /*tp_basicsize*/ | |||
551 | 0, /*tp_itemsize*/ | |||
552 | /* methods */ | |||
553 | (destructor)Server_tp_dealloc, | |||
554 | 0, /*tp_print*/ | |||
555 | 0, /*tp_getattr*/ | |||
556 | 0, /*tp_setattr*/ | |||
557 | 0, /*tp_compare*/ | |||
558 | 0, /*tp_repr*/ | |||
559 | 0, /*tp_as_number*/ | |||
560 | 0, /*tp_as_sequence*/ | |||
561 | 0, /*tp_as_mapping*/ | |||
562 | 0, /*tp_hash*/ | |||
563 | 0, /*tp_call*/ | |||
564 | 0, /*tp_str*/ | |||
565 | 0, /*tp_getattro*/ | |||
566 | 0, /*tp_setattro*/ | |||
567 | 0, /*tp_as_buffer*/ | |||
568 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0) | Py_TPFLAGS_BASETYPE(1UL << 10), | |||
569 | Server_tp_doc, /*tp_doc*/ | |||
570 | 0, /*tp_traverse*/ | |||
571 | 0, /*tp_clear*/ | |||
572 | 0, /*tp_richcompare*/ | |||
573 | offsetof(Server, weaklist)__builtin_offsetof(Server, weaklist), /*tp_weaklistoffset*/ | |||
574 | 0, /*tp_iter*/ | |||
575 | 0, /*tp_iternext*/ | |||
576 | DBusPyServer_tp_methods,/*tp_methods*/ | |||
577 | 0, /*tp_members*/ | |||
578 | 0, /*tp_getset*/ | |||
579 | 0, /*tp_base*/ | |||
580 | 0, /*tp_dict*/ | |||
581 | 0, /*tp_descr_get*/ | |||
582 | 0, /*tp_descr_set*/ | |||
583 | 0, /*tp_dictoffset*/ | |||
584 | 0, /*tp_init*/ | |||
585 | 0, /*tp_alloc*/ | |||
586 | Server_tp_new, /*tp_new*/ | |||
587 | 0, /*tp_free*/ | |||
588 | 0, /*tp_is_gc*/ | |||
589 | }; | |||
590 | ||||
591 | dbus_bool_t | |||
592 | dbus_py_init_server_types(void) | |||
593 | { | |||
594 | /* Get a slot to store our weakref on DBus Server */ | |||
595 | _server_python_slot = -1; | |||
596 | if (!dbus_server_allocate_data_slot(&_server_python_slot)) | |||
597 | return FALSE0; | |||
598 | ||||
599 | if (PyType_Ready(&DBusPyServer_Type) < 0) | |||
600 | return FALSE0; | |||
601 | ||||
602 | return TRUE1; | |||
603 | } | |||
604 | ||||
605 | dbus_bool_t | |||
606 | dbus_py_insert_server_types(PyObject *this_module) | |||
607 | { | |||
608 | /* PyModule_AddObject steals a ref */ | |||
609 | Py_INCREF (&DBusPyServer_Type)_Py_INCREF(((PyObject*)(&DBusPyServer_Type))); | |||
610 | if (PyModule_AddObject(this_module, "_Server", | |||
611 | (PyObject *)&DBusPyServer_Type) < 0) return FALSE0; | |||
612 | ||||
613 | return TRUE1; | |||
614 | } | |||
615 | ||||
616 | /* vim:set ft=c cino< sw=4 sts=4 et: */ |
1 | #ifndef PyUnicode_AsUTF8String |
2 | struct _object; |
3 | typedef struct _object PyObject; |
4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
5 | PyObject* PyUnicode_AsUTF8String(PyObject *unicode) { |
6 | return clang_analyzer_PyObject_New_Reference(); |
7 | } |
8 | #else |
9 | #warning "API PyUnicode_AsUTF8String is defined as a macro." |
10 | #endif |