Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 310644 Details for
Bug 453518
dbus-python does not have DBusServer APIs
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Patch
0001-Add-wrapper-for-DBusServer.patch (text/plain), 33.09 KB, created by
Peng Huang
on 2008-07-01 07:25:07 UTC
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Peng Huang
Created:
2008-07-01 07:25:07 UTC
Size:
33.09 KB
patch
obsolete
>From 2a95db46a0e69ad0e3a3d04d39988f98f34e0d3b Mon Sep 17 00:00:00 2001 >From: Huang Peng <shawn.p.huang@gmail.com> >Date: Wed, 25 Jun 2008 11:33:44 +0800 >Subject: [PATCH] Add wrapper for DBusServer. > >--- > Makefile.am | 1 + > _dbus_bindings/Makefile.am | 3 + > _dbus_bindings/conn-methods.c | 1 + > _dbus_bindings/dbus_bindings-internal.h | 8 + > _dbus_bindings/mainloop.c | 18 ++ > _dbus_bindings/module.c | 2 + > _dbus_bindings/server-internal.h | 51 ++++ > _dbus_bindings/server-methods.c | 215 ++++++++++++++++++ > _dbus_bindings/server.c | 377 +++++++++++++++++++++++++++++++ > dbus/lowlevel.py | 2 + > dbus/server.py | 71 ++++++ > examples/Makefile.am | 5 +- > examples/example-server-client.py | 18 ++ > examples/example-server.py | 61 +++++ > include/dbus-python.h | 1 + > 15 files changed, 833 insertions(+), 1 deletions(-) > create mode 100644 _dbus_bindings/server-internal.h > create mode 100644 _dbus_bindings/server-methods.c > create mode 100644 _dbus_bindings/server.c > create mode 100644 dbus/server.py > create mode 100644 examples/example-server-client.py > create mode 100644 examples/example-server.py > >diff --git a/Makefile.am b/Makefile.am >index 8f594ad..40ac719 100644 >--- a/Makefile.am >+++ b/Makefile.am >@@ -35,6 +35,7 @@ nobase_python_PYTHON = \ > dbus/mainloop/glib.py \ > dbus/proxies.py \ > dbus/service.py \ >+ dbus/server.py \ > dbus/types.py > > check_py_sources = $(nobase_python_PYTHON) >diff --git a/_dbus_bindings/Makefile.am b/_dbus_bindings/Makefile.am >index c2e59c9..a747e18 100644 >--- a/_dbus_bindings/Makefile.am >+++ b/_dbus_bindings/Makefile.am >@@ -7,6 +7,9 @@ _dbus_bindings_la_SOURCES = \ > abstract.c \ > bus.c \ > bytes.c \ >+ server.c \ >+ server-internal.h \ >+ server-methods.c \ > conn.c \ > conn-internal.h \ > conn-methods.c \ >diff --git a/_dbus_bindings/conn-methods.c b/_dbus_bindings/conn-methods.c >index 6fadc31..81c4514 100644 >--- a/_dbus_bindings/conn-methods.c >+++ b/_dbus_bindings/conn-methods.c >@@ -179,6 +179,7 @@ _filter_message(DBusConnection *conn, DBusMessage *message, void *user_data) > callable = PyList_GET_ITEM(conn_obj->filters, i); > if (callable == user_data) { > Py_INCREF(callable); >+ break; > } > else { > callable = NULL; >diff --git a/_dbus_bindings/dbus_bindings-internal.h b/_dbus_bindings/dbus_bindings-internal.h >index 1dfd6b2..ea3f2aa 100644 >--- a/_dbus_bindings/dbus_bindings-internal.h >+++ b/_dbus_bindings/dbus_bindings-internal.h >@@ -54,6 +54,12 @@ static inline int type##_Check (PyObject *o) \ > return (PyObject_TypeCheck (o, &type##_Type)); \ > } > >+/* server.c */ >+extern PyTypeObject DBusPyServer_Type; >+DEFINE_CHECK(DBusPyServer) >+extern dbus_bool_t dbus_py_init_server_types(void); >+extern dbus_bool_t dbus_py_insert_server_types(PyObject *this_module); >+ > /* conn.c */ > extern PyTypeObject DBusPyConnection_Type; > DEFINE_CHECK(DBusPyConnection) >@@ -138,6 +144,8 @@ extern dbus_bool_t dbus_py_init_pending_call(void); > extern dbus_bool_t dbus_py_insert_pending_call(PyObject *this_module); > > /* mainloop.c */ >+extern dbus_bool_t dbus_py_set_up_server(PyObject *server, >+ PyObject *mainloop); > extern dbus_bool_t dbus_py_set_up_connection(PyObject *conn, > PyObject *mainloop); > extern PyObject *dbus_py_get_default_main_loop(void); >diff --git a/_dbus_bindings/mainloop.c b/_dbus_bindings/mainloop.c >index 3b56ade..c4659fc 100644 >--- a/_dbus_bindings/mainloop.c >+++ b/_dbus_bindings/mainloop.c >@@ -114,6 +114,24 @@ dbus_py_check_mainloop_sanity(PyObject *mainloop) > } > > dbus_bool_t >+dbus_py_set_up_server(PyObject *server, PyObject *mainloop) >+{ >+ if (NativeMainLoop_Check(mainloop)) { >+ /* Native mainloops are allowed to do arbitrary strange things */ >+ NativeMainLoop *nml = (NativeMainLoop *)mainloop; >+ DBusServer *dbs = DBusPyServer_BorrowDBusServer(server); >+ >+ if (!dbs) { >+ return FALSE; >+ } >+ return (nml->set_up_server_cb)(dbs, nml->data); >+ } >+ PyErr_SetString(PyExc_TypeError, >+ "A dbus.mainloop.NativeMainLoop instance is required"); >+ return FALSE; >+} >+ >+dbus_bool_t > dbus_py_set_up_connection(PyObject *conn, PyObject *mainloop) > { > if (NativeMainLoop_Check(mainloop)) { >diff --git a/_dbus_bindings/module.c b/_dbus_bindings/module.c >index ddeb1f0..de5966b 100644 >--- a/_dbus_bindings/module.c >+++ b/_dbus_bindings/module.c >@@ -267,6 +267,7 @@ init_dbus_bindings(void) > if (!dbus_py_init_message_types()) return; > if (!dbus_py_init_pending_call()) return; > if (!dbus_py_init_mainloop()) return; >+ if (!dbus_py_init_server_types()) return; > if (!dbus_py_init_conn_types()) return; > > this_module = Py_InitModule3("_dbus_bindings", module_functions, module_doc); >@@ -282,6 +283,7 @@ init_dbus_bindings(void) > if (!dbus_py_insert_message_types(this_module)) return; > if (!dbus_py_insert_pending_call(this_module)) return; > if (!dbus_py_insert_mainloop_types(this_module)) return; >+ if (!dbus_py_insert_server_types(this_module)) return; > if (!dbus_py_insert_conn_types(this_module)) return; > > if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_NAME", >diff --git a/_dbus_bindings/server-internal.h b/_dbus_bindings/server-internal.h >new file mode 100644 >index 0000000..cde1b1f >--- /dev/null >+++ b/_dbus_bindings/server-internal.h >@@ -0,0 +1,51 @@ >+/* _dbus_bindings internal API. For use within _dbus_bindings only. >+ * >+ * Copyright (C) 2008 Huang Peng <phuang@redhat.com> . >+ * >+ * Permission is hereby granted, free of charge, to any person >+ * obtaining a copy of this software and associated documentation >+ * files (the "Software"), to deal in the Software without >+ * restriction, including without limitation the rights to use, copy, >+ * modify, merge, publish, distribute, sublicense, and/or sell copies >+ * of the Software, and to permit persons to whom the Software is >+ * furnished to do so, subject to the following conditions: >+ * >+ * The above copyright notice and this permission notice shall be >+ * included in all copies or substantial portions of the Software. >+ * >+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND >+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT >+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, >+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, >+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >+ * DEALINGS IN THE SOFTWARE. >+ */ >+ >+#ifndef DBUS_BINDINGS_SERVER_H >+#define DBUS_BINDINGS_SERVER_H >+ >+#include "dbus_bindings-internal.h" >+ >+typedef struct { >+ PyObject_HEAD >+ DBusServer *server; >+ >+ PyObject *new_connection_callback; >+ PyTypeObject *new_connection_type; >+ /* Weak-references list to make Connections weakly referenceable */ >+ PyObject *weaklist; >+ >+ PyObject *mainloop; >+} Server; >+ >+extern struct PyMethodDef DBusPyServer_tp_methods[]; >+extern DBusHandlerResult DBusPyServer_HandleMessage(Server *, >+ PyObject *, >+ PyObject *); >+extern PyObject *DBusPyServer_ExistingFromDBusServer(DBusServer *); >+ >+extern PyObject *DBusPyServer_GetAddress(Server *, PyObject *); >+ >+#endif >diff --git a/_dbus_bindings/server-methods.c b/_dbus_bindings/server-methods.c >new file mode 100644 >index 0000000..1e10d06 >--- /dev/null >+++ b/_dbus_bindings/server-methods.c >@@ -0,0 +1,215 @@ >+/* Implementation of normal Python-accessible methods on the _dbus_bindings >+ * Connection type; separated out to keep the file size manageable. >+ * >+ * Copyright (C) 2008 Huang Peng <phuang@redhat.com> . >+ * >+ * Permission is hereby granted, free of charge, to any person >+ * obtaining a copy of this software and associated documentation >+ * files (the "Software"), to deal in the Software without >+ * restriction, including without limitation the rights to use, copy, >+ * modify, merge, publish, distribute, sublicense, and/or sell copies >+ * of the Software, and to permit persons to whom the Software is >+ * furnished to do so, subject to the following conditions: >+ * >+ * The above copyright notice and this permission notice shall be >+ * included in all copies or substantial portions of the Software. >+ * >+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND >+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT >+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, >+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, >+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >+ * DEALINGS IN THE SOFTWARE. >+ */ >+ >+#include "dbus_bindings-internal.h" >+#include "server-internal.h" >+ >+PyDoc_STRVAR(Server_disconnect__doc__, >+"disconnect()\n\n" >+"Releases the server's address and stops listening for new clients.\n"); >+static PyObject * >+Server_disconnect (Server *self, PyObject *args UNUSED) >+{ >+ TRACE(self); >+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server); >+ Py_BEGIN_ALLOW_THREADS >+ dbus_server_disconnect(self->server); >+ Py_END_ALLOW_THREADS >+ >+ Py_INCREF(Py_None); >+ return Py_None; >+} >+ >+ >+ >+PyDoc_STRVAR(Server_get_address__doc__, >+"get_address() -> String\n\n" >+"Return the address of the server.\n"); >+static PyObject * >+Server_get_address (Server *self, PyObject *args UNUSED) >+{ >+ char *address; >+ PyObject *ret; >+ >+ TRACE(self); >+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server); >+ Py_BEGIN_ALLOW_THREADS >+ address = dbus_server_get_address(self->server); >+ Py_END_ALLOW_THREADS >+ ret = PyString_FromString(address); >+ dbus_free (address); >+ return ret; >+} >+ >+PyDoc_STRVAR(Server_get_id__doc__, >+"get_id() -> String\n\n" >+"Return the id of the server.\n"); >+static PyObject * >+Server_get_id (Server *self, PyObject *args UNUSED) >+{ >+ char *id; >+ PyObject *ret; >+ >+ TRACE(self); >+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server); >+ Py_BEGIN_ALLOW_THREADS >+ id = dbus_server_get_id(self->server); >+ Py_END_ALLOW_THREADS >+ >+ ret = PyString_FromString(id); >+ dbus_free (id); >+ >+ return ret; >+} >+ >+PyDoc_STRVAR(Server_get_is_connected__doc__, >+"get_is_connected() -> bool\n\n" >+"Return True if server is istill listening new connections.\n"); >+static PyObject * >+Server_get_is_connected (Server *self, PyObject *args UNUSED) >+{ >+ PyObject *ret; >+ >+ TRACE(self); >+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server); >+ Py_BEGIN_ALLOW_THREADS >+ if (dbus_server_get_is_connected(self->server)) >+ ret = Py_True; >+ else >+ ret = Py_False; >+ Py_END_ALLOW_THREADS >+ >+ Py_INCREF(ret); >+ >+ return ret; >+} >+ >+ >+PyDoc_STRVAR(Server_set_new_connection_function__doc__, >+"set_new_connection_function()\n\n" >+"Set a function for handling new connections.\n"); >+static PyObject * >+Server_set_new_connection_function (Server *self, PyObject *args) >+{ >+ >+ PyObject *callback; >+ PyTypeObject *conn_type = NULL; >+ >+ if (!PyArg_ParseTuple(args, "O|O:set_new_connection_function", >+ &callback, &conn_type)) { >+ return NULL; >+ } >+ >+ if (callback != Py_None && ! PyCallable_Check (callback)) { >+ PyErr_SetString (PyExc_TypeError, >+ "The first argument must be a callable object"); >+ return NULL; >+ } >+ >+ if (!conn_type || (PyObject *)conn_type == Py_None) { >+ conn_type = &DBusPyConnection_Type; >+ } >+ >+ if (!PyType_IsSubtype (conn_type, &DBusPyConnection_Type)) { >+ PyErr_SetString (PyExc_TypeError, >+ "The second argument must be None or Subclass of _dbus_bindings_.Connection"); >+ return NULL; >+ } >+ >+ TRACE(self); >+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server); >+ Py_BEGIN_ALLOW_THREADS >+ Py_XDECREF (self->new_connection_callback); >+ if (callback != Py_None) { >+ Py_INCREF (callback); >+ self->new_connection_callback = callback; >+ } >+ else >+ self->new_connection_callback = NULL; >+ >+ Py_XDECREF (self->new_connection_type); >+ Py_INCREF (conn_type); >+ self->new_connection_type = conn_type; >+ >+ Py_END_ALLOW_THREADS >+ >+ Py_INCREF (Py_None); >+ return Py_None; >+} >+ >+ >+PyDoc_STRVAR(Server_set_auth_mechanisms__doc__, >+"set_auth_mechanisms (...)\n\n" >+"Set the authentication mechanisms that this server offers to clients.\n"); >+static PyObject * >+Server_set_auth_mechanisms (Server *self, PyObject *args) >+{ >+ >+ int len, i; >+ const char ** _mechanisms = NULL; >+ >+ len = PyTuple_Size (args); >+ >+ if (len > 0) { >+ _mechanisms = (const char **)malloc (sizeof (char *) * (len + 1)); >+ for (i = 0; i < len; i++) { >+ PyObject *mechanism = PyTuple_GetItem (args, i); >+ if (!PyString_Check (mechanism)) { >+ free (_mechanisms); >+ PyErr_SetString(PyExc_TypeError, >+ "arguments must be strings"); >+ return NULL; >+ } >+ _mechanisms[i] = PyString_AS_STRING (mechanism); >+ } >+ _mechanisms[len] = NULL; >+ } >+ >+ TRACE(self); >+ DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server); >+ Py_BEGIN_ALLOW_THREADS >+ dbus_server_set_auth_mechanisms (self->server, _mechanisms); >+ Py_END_ALLOW_THREADS >+ >+ if (_mechanisms != NULL) >+ free (_mechanisms); >+ Py_INCREF (Py_None); >+ return Py_None; >+} >+ >+struct PyMethodDef DBusPyServer_tp_methods[] = { >+#define ENTRY(name, flags) {#name, (PyCFunction)Server_##name, flags, Server_##name##__doc__} >+ ENTRY(disconnect, METH_NOARGS), >+ ENTRY(get_address, METH_NOARGS), >+ ENTRY(get_id, METH_NOARGS), >+ ENTRY(get_is_connected, METH_NOARGS), >+ ENTRY(set_new_connection_function, METH_VARARGS), >+ ENTRY(set_auth_mechanisms, METH_VARARGS), >+ {NULL}, >+#undef ENTRY >+}; >+ >+/* vim:set ft=c cino< sw=4 sts=4 et: */ >diff --git a/_dbus_bindings/server.c b/_dbus_bindings/server.c >new file mode 100644 >index 0000000..3de7e07 >--- /dev/null >+++ b/_dbus_bindings/server.c >@@ -0,0 +1,377 @@ >+/* Implementation of the _dbus_bindings Server type, a Python wrapper >+ * for DBusServer. See also server-methods.c. >+ * >+ * Copyright (C) 2008 Huang Peng <phuang@redhat.com> . >+ * >+ * Permission is hereby granted, free of charge, to any person >+ * obtaining a copy of this software and associated documentation >+ * files (the "Software"), to deal in the Software without >+ * restriction, including without limitation the rights to use, copy, >+ * modify, merge, publish, distribute, sublicense, and/or sell copies >+ * of the Software, and to permit persons to whom the Software is >+ * furnished to do so, subject to the following conditions: >+ * >+ * The above copyright notice and this permission notice shall be >+ * included in all copies or substantial portions of the Software. >+ * >+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND >+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT >+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, >+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, >+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >+ * DEALINGS IN THE SOFTWARE. >+ */ >+ >+#include "dbus_bindings-internal.h" >+#include "server-internal.h" >+ >+/* Server definition ============================================ */ >+ >+PyDoc_STRVAR(Server_tp_doc, >+"A D-Bus server.\n" >+"\n" >+"::\n" >+"\n" >+" Server(address, mainloop=None) -> Server\n" >+); >+ >+/* D-Bus Server user data slot, containing an owned reference to either >+ * the Server, or a weakref to the Server. >+ */ >+static dbus_int32_t _server_python_slot; >+ >+/* C API for main-loop hooks ======================================== */ >+ >+/* Return a borrowed reference to the DBusServer which underlies this >+ * Server. */ >+DBusServer * >+DBusPyServer_BorrowDBusServer(PyObject *self) >+{ >+ DBusServer *dbs; >+ >+ TRACE(self); >+ if (!DBusPyServer_Check(self)) { >+ PyErr_SetString(PyExc_TypeError, "A dbus.Server is required"); >+ return NULL; >+ } >+ dbs = ((Server *)self)->server; >+ if (!dbs) { >+ PyErr_SetString(PyExc_RuntimeError, "Server is in an invalid " >+ "state: no DBusServer"); >+ return NULL; >+ } >+ return dbs; >+} >+ >+/* Internal C API =================================================== */ >+ >+/* Return a new reference to a Python Server or subclass corresponding >+ * to the DBusServer server. For use in callbacks. >+ * >+ * Raises AssertionError if the DBusServer does not have a Server. >+ */ >+PyObject * >+DBusPyServer_ExistingFromDBusServer(DBusServer *server) >+{ >+ PyObject *self, *ref; >+ >+ Py_BEGIN_ALLOW_THREADS >+ ref = (PyObject *)dbus_server_get_data(server, >+ _server_python_slot); >+ Py_END_ALLOW_THREADS >+ if (ref) { >+ DBG("(DBusServer *)%p has weak reference at %p", server, ref); >+ self = PyWeakref_GetObject(ref); /* still a borrowed ref */ >+ if (self && self != Py_None && DBusPyServer_Check(self)) { >+ DBG("(DBusServer *)%p has weak reference at %p pointing to %p", >+ server, ref, self); >+ TRACE(self); >+ Py_INCREF(self); >+ TRACE(self); >+ return self; >+ } >+ } >+ >+ PyErr_SetString(PyExc_AssertionError, >+ "D-Bus server does not have a Server " >+ "instance associated with it"); >+ return NULL; >+} >+ >+/* Return a new reference to a Python Server or subclass (given by cls) >+ * corresponding to the DBusServer server, which must have been newly >+ * created. For use by the Server and Bus constructors. >+ * >+ * Raises AssertionError if the DBusServer already has a Server. >+ */ >+ >+static void >+Server_new_connection_callback (DBusServer *server, DBusConnection *connection, void * data UNUSED) >+{ >+ PyObject *conn = NULL; >+ PyObject *result = NULL; >+ PyObject *args = NULL; >+ Server *self = NULL; >+ >+ self = (Server *)DBusPyServer_ExistingFromDBusServer(server); >+ if (self == NULL) >+ goto error; >+ >+ if (self->new_connection_callback) { >+ conn = DBusPyConnection_NewConsumingDBusConnection(self->new_connection_type, connection, self->mainloop); >+ if (conn == NULL) >+ goto error; >+ dbus_connection_ref (connection); >+ >+ args = Py_BuildValue ("(OO)", self, conn); >+ if (args == NULL) >+ goto error; >+ result = PyObject_Call (self->new_connection_callback, args, NULL); >+ if (result == NULL) >+ goto error; >+ >+ } >+ goto out; >+error: >+ PyErr_Print (); >+out: >+ Py_XDECREF (conn); >+ Py_XDECREF (result); >+ Py_XDECREF (args); >+ Py_XDECREF ((PyObject *)self); >+} >+ >+/* Server type-methods ========================================== */ >+ >+/* "Constructor" (the real constructor is Server_NewFromDBusServer, >+ * to which this delegates). */ >+static PyObject * >+Server_tp_new(PyTypeObject *cls, PyObject *args UNUSED, PyObject *kwargs UNUSED) >+{ >+ PyObject *self; >+ self = cls->tp_alloc (cls, 0); >+ return (PyObject *)self; >+ >+} >+ >+ >+static int >+Server_tp_init(Server *self, PyObject *args, PyObject *kwargs) >+{ >+ PyObject *mainloop = NULL; >+ DBusServer *server = NULL; >+ char *address = NULL; >+ >+ PyObject *ref = NULL; >+ DBusError error; >+ dbus_bool_t ok; >+ >+ static char *argnames[] = {"address", "mainloop", NULL}; >+ >+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", argnames, >+ &address, &mainloop)) { >+ return -1; >+ } >+ >+ if (!mainloop || mainloop == Py_None) { >+ mainloop = dbus_py_get_default_main_loop(); >+ if (!mainloop) { >+ PyErr_SetString (PyExc_Exception, >+ "Can not get default mainloop."); >+ goto err; >+ } >+ } >+ else { >+ Py_INCREF (mainloop); >+ } >+ >+ >+ dbus_error_init(&error); >+ >+ Py_BEGIN_ALLOW_THREADS >+ server = dbus_server_listen(address, &error); >+ Py_END_ALLOW_THREADS >+ >+ if (!server) { >+ DBusPyException_ConsumeError(&error); >+ goto err; >+ } >+ >+ dbus_server_set_new_connection_function (server, Server_new_connection_callback, NULL, NULL); >+ >+ Py_INCREF (mainloop); >+ self->mainloop = mainloop; >+ self->server = server; >+ self->new_connection_callback = NULL; >+ self->new_connection_type = NULL; >+ >+ ref = PyWeakref_NewRef((PyObject *)self, NULL); >+ if (!ref) goto err; >+ DBG("Created weak ref %p to (Server *)%p for (DBusServer *)%p", >+ ref, self, server); >+ >+ Py_BEGIN_ALLOW_THREADS >+ ok = dbus_server_set_data(server, _server_python_slot, >+ (void *)ref, >+ (DBusFreeFunction)dbus_py_take_gil_and_xdecref); >+ Py_END_ALLOW_THREADS >+ >+ if (ok) { >+ DBG("Attached weak ref %p ((Server *)%p) to (DBusServer *)%p", >+ ref, self, server); >+ ref = NULL; /* don't DECREF it - the DBusServer owns it now */ >+ } >+ else { >+ DBG("Failed to attached weak ref %p ((Server *)%p) to " >+ "(DBusServer *)%p - will dispose of it", ref, self, server); >+ PyErr_NoMemory(); >+ goto err; >+ } >+ >+ DBUS_PY_RAISE_VIA_GOTO_IF_FAIL(server, err); >+ self->server = server; >+ /* the DBusPyServer will close it now */ >+ server = NULL; >+ >+ if (!dbus_py_set_up_server((PyObject *)self, mainloop)) { >+ goto err; >+ } >+ >+ Py_DECREF(mainloop); >+ >+ DBG("%s() -> %p", __func__, self); >+ TRACE(self); >+ return 0; >+ >+err: >+ DBG("Failed to construct Server."); >+ Py_XDECREF(mainloop); >+ Py_XDECREF(ref); >+ if (server) { >+ Py_BEGIN_ALLOW_THREADS >+ dbus_server_unref(server); >+ Py_END_ALLOW_THREADS >+ } >+ DBG("%s() fail", __func__); >+ DBG_WHEREAMI; >+ return -1; >+} >+ >+ >+/* Destructor */ >+static void Server_tp_dealloc(Server *self) >+{ >+ DBusServer *server = self->server; >+ PyObject *et, *ev, *etb; >+ >+ /* avoid clobbering any pending exception */ >+ PyErr_Fetch(&et, &ev, &etb); >+ >+ if (self->weaklist) { >+ PyObject_ClearWeakRefs((PyObject *)self); >+ } >+ >+ TRACE(self); >+ DBG("Deallocating Server at %p (DBusServer at %p)", self, server); >+ DBG_WHEREAMI; >+ >+ DBG("Server at %p: deleting callbacks", self); >+ >+ if (server) { >+ /* Might trigger callbacks if we're unlucky... */ >+ DBG("Server at %p has a server, closing it...", self); >+ Py_BEGIN_ALLOW_THREADS >+ Py_END_ALLOW_THREADS >+ } >+ >+ /* make sure to do this last to preserve the invariant that >+ * self->server is always non-NULL for any referenced Server >+ * (until the filters and object paths were freed, we might have been >+ * in a reference cycle!) >+ */ >+ DBG("Server at %p: nulling self->server", self); >+ self->server = server; >+ >+ if (server) { >+ DBG("Server at %p: unreffing server", self); >+ dbus_server_unref(server); >+ } >+ >+ Py_XDECREF (self->mainloop); >+ >+ DBG("Server at %p: freeing self", self); >+ PyErr_Restore(et, ev, etb); >+ (self->ob_type->tp_free)((PyObject *)self); >+} >+ >+/* Server type object =========================================== */ >+ >+PyTypeObject DBusPyServer_Type = { >+ PyObject_HEAD_INIT(NULL) >+ 0, /*ob_size*/ >+ "_dbus_bindings.Server",/*tp_name*/ >+ sizeof(Server), /*tp_basicsize*/ >+ 0, /*tp_itemsize*/ >+ /* methods */ >+ (destructor)Server_tp_dealloc, >+ 0, /*tp_print*/ >+ 0, /*tp_getattr*/ >+ 0, /*tp_setattr*/ >+ 0, /*tp_compare*/ >+ 0, /*tp_repr*/ >+ 0, /*tp_as_number*/ >+ 0, /*tp_as_sequence*/ >+ 0, /*tp_as_mapping*/ >+ 0, /*tp_hash*/ >+ 0, /*tp_call*/ >+ 0, /*tp_str*/ >+ 0, /*tp_getattro*/ >+ 0, /*tp_setattro*/ >+ 0, /*tp_as_buffer*/ >+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_BASETYPE, >+ Server_tp_doc, /*tp_doc*/ >+ 0, /*tp_traverse*/ >+ 0, /*tp_clear*/ >+ 0, /*tp_richcompare*/ >+ offsetof(Server, weaklist), /*tp_weaklistoffset*/ >+ 0, /*tp_iter*/ >+ 0, /*tp_iternext*/ >+ DBusPyServer_tp_methods,/*tp_methods*/ >+ 0, /*tp_members*/ >+ 0, /*tp_getset*/ >+ 0, /*tp_base*/ >+ 0, /*tp_dict*/ >+ 0, /*tp_descr_get*/ >+ 0, /*tp_descr_set*/ >+ 0, /*tp_dictoffset*/ >+ (initproc) Server_tp_init, >+ /*tp_init*/ >+ 0, /*tp_alloc*/ >+ Server_tp_new, /*tp_new*/ >+ 0, /*tp_free*/ >+ 0, /*tp_is_gc*/ >+}; >+ >+dbus_bool_t >+dbus_py_init_server_types(void) >+{ >+ /* Get a slot to store our weakref on DBus Servers */ >+ _server_python_slot = -1; >+ if (!dbus_server_allocate_data_slot(&_server_python_slot)) >+ return FALSE; >+ if (PyType_Ready(&DBusPyServer_Type) < 0) >+ return FALSE; >+ return TRUE; >+} >+ >+dbus_bool_t >+dbus_py_insert_server_types(PyObject *this_module) >+{ >+ if (PyModule_AddObject(this_module, "Server", >+ (PyObject *)&DBusPyServer_Type) < 0) return FALSE; >+ return TRUE; >+} >+ >+/* vim:set ft=c cino< sw=4 sts=4 et: */ >diff --git a/dbus/lowlevel.py b/dbus/lowlevel.py >index eeabcbd..38f763c 100644 >--- a/dbus/lowlevel.py >+++ b/dbus/lowlevel.py >@@ -24,9 +24,11 @@ > > __all__ = ('PendingCall', 'Message', 'MethodCallMessage', > 'MethodReturnMessage', 'ErrorMessage', 'SignalMessage', >+ 'Server', > 'HANDLER_RESULT_HANDLED', 'HANDLER_RESULT_NOT_YET_HANDLED') > > from _dbus_bindings import PendingCall, Message, MethodCallMessage, \ > MethodReturnMessage, ErrorMessage, SignalMessage, \ >+ Server, \ > HANDLER_RESULT_HANDLED, \ > HANDLER_RESULT_NOT_YET_HANDLED >diff --git a/dbus/server.py b/dbus/server.py >new file mode 100644 >index 0000000..d31567a >--- /dev/null >+++ b/dbus/server.py >@@ -0,0 +1,71 @@ >+# Copyright (C) 2008 Huang Peng <phuang@redhat.com> >+# >+# Permission is hereby granted, free of charge, to any person >+# obtaining a copy of this software and associated documentation >+# files (the "Software"), to deal in the Software without >+# restriction, including without limitation the rights to use, copy, >+# modify, merge, publish, distribute, sublicense, and/or sell copies >+# of the Software, and to permit persons to whom the Software is >+# furnished to do so, subject to the following conditions: >+# >+# The above copyright notice and this permission notice shall be >+# included in all copies or substantial portions of the Software. >+# >+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND >+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT >+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, >+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, >+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >+# DEALINGS IN THE SOFTWARE. >+ >+import _dbus_bindings >+import dbus.connection >+import dbus.lowlevel >+ >+class Server (_dbus_bindings.Server): >+ def __init__ (self, address): >+ _dbus_bindings.Server.__init__ (self, address) >+ self._connections = [] >+ self._objects = {} >+ self.set_new_connection_function (self._new_connection_cb, dbus.connection.Connection) >+ >+ def register_object (self, obj, path): >+ if path in self._objects: >+ raise Exception ("%s has been registered", path) >+ self._objects[path] = obj >+ >+ for conn in self._connections: >+ obj.add_to_connection (conn, path) >+ >+ def _new_connection_cb (self, server, new_connection): >+ self._connections.append (new_connection) >+ new_connection.add_message_filter (self._message_filter_cb) >+ >+ # add all objects to the new connection >+ for path, obj in self._objects.items (): >+ obj.add_to_connection (new_connection, path) >+ >+ self.new_connection (server, new_connection) >+ >+ def _message_filter_cb (self, connection, message): >+ if message.get_interface() == "org.freedesktop.DBus.Local" and \ >+ message.get_member() == "Disconnected": >+ # remove all object from this connection >+ for path, obj in self._objects.items (): >+ obj.remove_from_connection (connection, path) >+ >+ self.remove_connection (connection) >+ self._connections.remove (connection) >+ return dbus.lowlevel.HANDLER_RESULT_HANDLED >+ >+ return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED >+ >+ def new_connection (self, server, connection): >+ pass >+ >+ def remove_connection (self, server, connection): >+ pass >+ >+ >diff --git a/examples/Makefile.am b/examples/Makefile.am >index 316b4bb..866aa04 100644 >--- a/examples/Makefile.am >+++ b/examples/Makefile.am >@@ -4,5 +4,8 @@ EXTRA_DIST = \ > example-service.py \ > example-signal-emitter.py \ > example-signal-recipient.py \ >- list-system-services.py >+ list-system-services.py \ >+ example-server.py \ >+ example-server-client.py >+ > # miss out the gconf examples for now - they don't work >diff --git a/examples/example-server-client.py b/examples/example-server-client.py >new file mode 100644 >index 0000000..693fb46 >--- /dev/null >+++ b/examples/example-server-client.py >@@ -0,0 +1,18 @@ >+#!/usr/bin/env python >+import dbus >+import dbus.mainloop.glib >+import dbus.connection >+import gobject >+import time >+ >+def main(): >+ loop = gobject.MainLoop () >+ conn = dbus.connection.Connection ("unix:abstract=/tmp/example-server") >+ obj = conn.get_object ("no.need.name", "/org/freedesktop/ExampleObject") >+ print obj.HelloWorld ("[%s] Hello World" % time.time()) >+ time.sleep (1) >+ print obj.Exit () >+ >+if __name__ == "__main__": >+ dbus.mainloop.glib.DBusGMainLoop (set_as_default=True) >+ main () >diff --git a/examples/example-server.py b/examples/example-server.py >new file mode 100644 >index 0000000..1668426 >--- /dev/null >+++ b/examples/example-server.py >@@ -0,0 +1,61 @@ >+#!/usr/bin/env python >+import dbus >+import dbus.server >+import dbus.lowlevel >+import dbus.service >+import dbus.mainloop.glib >+import sys >+import gobject >+ >+class ExampleObject (dbus.service.Object): >+ SUPPORTS_MULTIPLE_CONNECTIONS = True >+ >+ @dbus.service.method (dbus_interface="org.freedesktop.ExampleObject", in_signature="s", out_signature="s") >+ def HelloWorld (self, message): >+ print message >+ return "Reply : %s" % message >+ >+ @dbus.service.method (dbus_interface="org.freedesktop.ExampleObject", out_signature="s", async_callbacks=("reply_cb", "error_cb")) >+ def Exit (self, reply_cb, error_cb): >+ reply_cb ("Exit") >+ sys.exit () >+ >+ >+class ExampleServer (dbus.server.Server): >+ def __init__ (self): >+ dbus.server.Server.__init__ (self, "unix:abstract=/tmp/example-server") >+ self.register_object (ExampleObject (), "/org/freedesktop/ExampleObject") >+ >+ def new_connection (self, server, connection): >+ connection.add_message_filter (self.message_filter_cb) >+ print "New connection" >+ >+ def remove_connection (self, connection): >+ print "Remove connection" >+ >+ def message_filter_cb (self, connection, message): >+ if message.is_signal (dbus.LOCAL_IFACE, "Disconnected"): >+ print "A connection was closed" >+ return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED >+ >+ print "Got a Message (%s) : " % message.__class__.__name__ >+ print "\t From: %s" % message.get_sender () >+ print "\t To: %s" % message.get_destination () >+ print "\t Interface: %s" % message.get_interface () >+ print "\t Path: %s" % message.get_path () >+ print "\t Member: %s" % message.get_member () >+ print "\t Arguments:" >+ i = 0 >+ for arg in message.get_args_list(): >+ print "\t\t Arg[%d] : %s" % (i, arg) >+ i = i + 1 >+ >+ return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED >+ >+if __name__ == "__main__": >+ dbus.mainloop.glib.DBusGMainLoop (set_as_default = True) >+ loop = gobject.MainLoop () >+ bus = ExampleServer () >+ print "ADDRESS=\"%s\"" % bus.get_address () >+ loop.run () >+ >diff --git a/include/dbus-python.h b/include/dbus-python.h >index ff83e71..b1dd7ff 100644 >--- a/include/dbus-python.h >+++ b/include/dbus-python.h >@@ -46,6 +46,7 @@ typedef void (*_dbus_py_free_func)(void *); > #ifdef INSIDE_DBUS_PYTHON_BINDINGS > > extern DBusConnection *DBusPyConnection_BorrowDBusConnection(PyObject *); >+extern DBusServer *DBusPyServer_BorrowDBusServer(PyObject *); > extern PyObject *DBusPyNativeMainLoop_New4(_dbus_py_conn_setup_func, > _dbus_py_srv_setup_func, > _dbus_py_free_func, >-- >1.5.5.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 453518
: 310644