Blame _dbus_bindings/server.c

Packit 130fc8
/* Implementation of the _dbus_bindings Server type, a Python wrapper
Packit 130fc8
 * for DBusServer.
Packit 130fc8
 *
Packit 130fc8
 * Copyright (C) 2008 Openismus GmbH <http://openismus.com/>
Packit 130fc8
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
Packit 130fc8
 *
Packit 130fc8
 * Permission is hereby granted, free of charge, to any person
Packit 130fc8
 * obtaining a copy of this software and associated documentation
Packit 130fc8
 * files (the "Software"), to deal in the Software without
Packit 130fc8
 * restriction, including without limitation the rights to use, copy,
Packit 130fc8
 * modify, merge, publish, distribute, sublicense, and/or sell copies
Packit 130fc8
 * of the Software, and to permit persons to whom the Software is
Packit 130fc8
 * furnished to do so, subject to the following conditions:
Packit 130fc8
 *
Packit 130fc8
 * The above copyright notice and this permission notice shall be
Packit 130fc8
 * included in all copies or substantial portions of the Software.
Packit 130fc8
 *
Packit 130fc8
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 130fc8
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 130fc8
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 130fc8
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
Packit 130fc8
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
Packit 130fc8
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Packit 130fc8
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Packit 130fc8
 * DEALINGS IN THE SOFTWARE.
Packit 130fc8
 */
Packit 130fc8
Packit 130fc8
#include "dbus_bindings-internal.h"
Packit 130fc8
Packit 130fc8
/* Server definition ================================================ */
Packit 130fc8
Packit 130fc8
typedef struct {
Packit 130fc8
    PyObject_HEAD
Packit 130fc8
    DBusServer *server;
Packit 130fc8
Packit 130fc8
    /* The Connection subtype for which this Server is a factory */
Packit 130fc8
    PyObject *conn_class;
Packit 130fc8
Packit 130fc8
    /* Weak-references list to make server weakly referenceable */
Packit 130fc8
    PyObject *weaklist;
Packit 130fc8
Packit 130fc8
    PyObject *mainloop;
Packit 130fc8
} Server;
Packit 130fc8
Packit 130fc8
PyDoc_STRVAR(Server_tp_doc,
Packit 130fc8
"A D-Bus server.\n"
Packit 130fc8
"\n"
Packit 130fc8
"::\n"
Packit 130fc8
"\n"
Packit 130fc8
"   Server(address, connection_subtype, mainloop=None, auth_mechanisms=None)\n"
Packit 130fc8
"     -> Server\n"
Packit 130fc8
);
Packit 130fc8
Packit 130fc8
/* D-Bus Server user data slot, containing an owned reference to either
Packit 130fc8
 * the Server, or a weakref to the Server.
Packit 130fc8
 */
Packit 130fc8
static dbus_int32_t _server_python_slot;
Packit 130fc8
Packit 130fc8
/* C API for main-loop hooks ======================================== */
Packit 130fc8
Packit 130fc8
/* Return a borrowed reference to the DBusServer which underlies this
Packit 130fc8
 * Server. */
Packit 130fc8
DBusServer *
Packit 130fc8
DBusPyServer_BorrowDBusServer(PyObject *self)
Packit 130fc8
{
Packit 130fc8
    DBusServer *dbs;
Packit 130fc8
Packit 130fc8
    TRACE(self);
Packit 130fc8
    if (!DBusPyServer_Check(self)) {
Packit 130fc8
        PyErr_SetString(PyExc_TypeError, "A dbus.server.Server is required");
Packit 130fc8
        return NULL;
Packit 130fc8
    }
Packit 130fc8
    dbs = ((Server *)self)->server;
Packit 130fc8
    if (!dbs) {
Packit 130fc8
        PyErr_SetString(PyExc_RuntimeError, "Server is in an invalid "
Packit 130fc8
                        "state: no DBusServer");
Packit 130fc8
        return NULL;
Packit 130fc8
    }
Packit 130fc8
    return dbs;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
/* Internal C API =================================================== */
Packit 130fc8
Packit 130fc8
static dbus_bool_t
Packit 130fc8
DBusPyServer_set_auth_mechanisms(Server *self,
Packit 130fc8
                                 PyObject *auth_mechanisms)
Packit 130fc8
{
Packit 130fc8
    PyObject *fast_seq = NULL, *references = NULL;
Packit 130fc8
    Py_ssize_t length;
Packit 130fc8
    Py_ssize_t i;
Packit 130fc8
    /* a mutable array of constant strings */
Packit 130fc8
    const char **list = NULL;
Packit 130fc8
    dbus_bool_t ret = FALSE;
Packit 130fc8
Packit 130fc8
    fast_seq = PySequence_Fast(auth_mechanisms,
Packit 130fc8
            "Expecting sequence for auth_mechanisms parameter");
Packit 130fc8
Packit 130fc8
    if (!fast_seq)
Packit 130fc8
        return FALSE;
Packit 130fc8
Packit 130fc8
    length = PySequence_Fast_GET_SIZE(fast_seq);
Packit 130fc8
Packit 130fc8
    list = calloc (length + 1, sizeof (char *));
Packit 130fc8
Packit 130fc8
    if (!list) {
Packit 130fc8
        PyErr_NoMemory();
Packit 130fc8
        goto finally;
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    if (!(references = PyTuple_New(length)))
Packit 130fc8
        goto finally;
Packit 130fc8
Packit 130fc8
    for (i = 0; i < length; ++i) {
Packit 130fc8
        PyObject *am, *am_as_bytes;
Packit 130fc8
Packit 130fc8
        am = PySequence_Fast_GET_ITEM(auth_mechanisms, i);
Packit 130fc8
        if (!am)
Packit 130fc8
            goto finally;
Packit 130fc8
Packit 130fc8
        if (PyUnicode_Check(am)) {
Packit 130fc8
            am_as_bytes = PyUnicode_AsUTF8String(am);
Packit 130fc8
            if (!am_as_bytes)
Packit 130fc8
                goto finally;
Packit 130fc8
        }
Packit 130fc8
        else {
Packit 130fc8
            am_as_bytes = am;
Packit 130fc8
            Py_INCREF(am_as_bytes);
Packit 130fc8
        }
Packit 130fc8
        list[i] = PyBytes_AsString(am_as_bytes);
Packit 130fc8
        if (!list[i])
Packit 130fc8
            goto finally;
Packit 130fc8
Packit 130fc8
        PyTuple_SET_ITEM(references, i, am_as_bytes);
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    list[length] = NULL;
Packit 130fc8
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    dbus_server_set_auth_mechanisms(self->server, list);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
Packit 130fc8
    ret = TRUE;
Packit 130fc8
Packit 130fc8
finally:
Packit 130fc8
    if (list)
Packit 130fc8
        free (list);
Packit 130fc8
    Py_CLEAR(fast_seq);
Packit 130fc8
    Py_CLEAR(references);
Packit 130fc8
    return ret;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
/* Return a new reference to a Python Server or subclass corresponding
Packit 130fc8
 * to the DBusServer server. For use in callbacks.
Packit 130fc8
 *
Packit 130fc8
 * Raises AssertionError if the DBusServer does not have a Server.
Packit 130fc8
 */
Packit 130fc8
static PyObject *
Packit 130fc8
DBusPyServer_ExistingFromDBusServer(DBusServer *server)
Packit 130fc8
{
Packit 130fc8
    PyObject *self, *ref;
Packit 130fc8
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    ref = (PyObject *)dbus_server_get_data(server,
Packit 130fc8
                                           _server_python_slot);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
    if (ref) {
Packit 130fc8
        DBG("(DBusServer *)%p has weak reference at %p", server, ref);
Packit 130fc8
        self = PyWeakref_GetObject(ref);   /* still a borrowed ref */
Packit 130fc8
        if (self && self != Py_None && DBusPyServer_Check(self)) {
Packit 130fc8
            DBG("(DBusServer *)%p has weak reference at %p pointing to %p",
Packit 130fc8
                server, ref, self);
Packit 130fc8
            TRACE(self);
Packit 130fc8
            Py_INCREF(self);
Packit 130fc8
            TRACE(self);
Packit 130fc8
            return self;
Packit 130fc8
        }
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    PyErr_SetString(PyExc_AssertionError,
Packit 130fc8
                    "D-Bus server does not have a Server "
Packit 130fc8
                    "instance associated with it");
Packit 130fc8
    return NULL;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
static void
Packit 130fc8
DBusPyServer_new_connection_cb(DBusServer *server,
Packit 130fc8
                               DBusConnection *conn,
Packit 130fc8
                               void *data UNUSED)
Packit 130fc8
{
Packit 130fc8
    PyGILState_STATE gil = PyGILState_Ensure();
Packit 130fc8
    PyObject *self = NULL;
Packit 130fc8
    PyObject *method = NULL;
Packit 130fc8
Packit 130fc8
    self = DBusPyServer_ExistingFromDBusServer(server);
Packit 130fc8
    if (!self) goto out;
Packit 130fc8
    TRACE(self);
Packit 130fc8
Packit 130fc8
    method = PyObject_GetAttrString(self, "_on_new_connection");
Packit 130fc8
    TRACE(method);
Packit 130fc8
Packit 130fc8
    if (method) {
Packit 130fc8
        PyObject *conn_class = ((Server *)self)->conn_class;
Packit 130fc8
        PyObject *wrapper = DBusPyLibDBusConnection_New(conn);
Packit 130fc8
        PyObject *conn_obj;
Packit 130fc8
        PyObject *result;
Packit 130fc8
Packit 130fc8
        if (!wrapper)
Packit 130fc8
            goto out;
Packit 130fc8
Packit 130fc8
        conn_obj = PyObject_CallFunctionObjArgs((PyObject *)conn_class,
Packit 130fc8
                wrapper, ((Server*) self)->mainloop, NULL);
Packit 130fc8
        Py_CLEAR(wrapper);
Packit 130fc8
Packit 130fc8
        if (!conn_obj)
Packit 130fc8
            goto out;
Packit 130fc8
Packit 130fc8
        result = PyObject_CallFunctionObjArgs(method, conn_obj, NULL);
Packit 130fc8
        Py_CLEAR (conn_obj);
Packit 130fc8
Packit 130fc8
        /* discard result if not NULL, and fall through regardless */
Packit 130fc8
        Py_CLEAR(result);
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
out:
Packit 130fc8
    Py_CLEAR(method);
Packit 130fc8
    Py_CLEAR(self);
Packit 130fc8
Packit 130fc8
    if (PyErr_Occurred())
Packit 130fc8
        PyErr_Print();
Packit 130fc8
Packit 130fc8
    PyGILState_Release(gil);
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
/* Return a new reference to a Python Server or subclass (given by cls)
Packit 130fc8
 * corresponding to the DBusServer server, which must have been newly
Packit 130fc8
 * created. For use by the Server constructor.
Packit 130fc8
 *
Packit 130fc8
 * Raises AssertionError if the DBusServer already has a Server.
Packit 130fc8
 *
Packit 130fc8
 * One reference to server is stolen - either the returned DBusPyServer
Packit 130fc8
 * claims it, or it's unreffed.
Packit 130fc8
 */
Packit 130fc8
static PyObject *
Packit 130fc8
DBusPyServer_NewConsumingDBusServer(PyTypeObject *cls,
Packit 130fc8
                                    DBusServer *server,
Packit 130fc8
                                    PyObject *conn_class,
Packit 130fc8
                                    PyObject *mainloop,
Packit 130fc8
                                    PyObject *auth_mechanisms)
Packit 130fc8
{
Packit 130fc8
    Server *self = NULL;
Packit 130fc8
    PyObject *ref;
Packit 130fc8
    dbus_bool_t ok;
Packit 130fc8
Packit 130fc8
    DBG("%s(cls=%p, server=%p, mainloop=%p, auth_mechanisms=%p)",
Packit 130fc8
        __func__, cls, server, mainloop, auth_mechanisms);
Packit 130fc8
    DBUS_PY_RAISE_VIA_NULL_IF_FAIL(server);
Packit 130fc8
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    ref = (PyObject *)dbus_server_get_data(server,
Packit 130fc8
                                           _server_python_slot);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
    if (ref) {
Packit 130fc8
        self = (Server *)PyWeakref_GetObject(ref);
Packit 130fc8
        ref = NULL;
Packit 130fc8
        if (self && (PyObject *)self != Py_None) {
Packit 130fc8
            self = NULL;
Packit 130fc8
            PyErr_SetString(PyExc_AssertionError,
Packit 130fc8
                            "Newly created D-Bus server already has a "
Packit 130fc8
                            "Server instance associated with it");
Packit 130fc8
            DBG("%s() fail - assertion failed, DBusPyServer has a DBusServer already", __func__);
Packit 130fc8
            DBG_WHEREAMI;
Packit 130fc8
            return NULL;
Packit 130fc8
        }
Packit 130fc8
    }
Packit 130fc8
    ref = NULL;
Packit 130fc8
Packit 130fc8
    /* Change mainloop from a borrowed reference to an owned reference */
Packit 130fc8
    if (!mainloop || mainloop == Py_None) {
Packit 130fc8
        mainloop = dbus_py_get_default_main_loop();
Packit 130fc8
Packit 130fc8
        if (!mainloop || mainloop == Py_None) {
Packit 130fc8
            PyErr_SetString(PyExc_RuntimeError,
Packit 130fc8
                            "To run a D-Bus server, you need to either "
Packit 130fc8
                            "pass mainloop=... to the constructor or call "
Packit 130fc8
                            "dbus.set_default_main_loop(...)");
Packit 130fc8
            goto err;
Packit 130fc8
        }
Packit 130fc8
    }
Packit 130fc8
    else {
Packit 130fc8
        Py_INCREF(mainloop);
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    DBG("Constructing Server from DBusServer at %p", server);
Packit 130fc8
Packit 130fc8
    self = (Server *)(cls->tp_alloc(cls, 0));
Packit 130fc8
    if (!self) goto err;
Packit 130fc8
    TRACE(self);
Packit 130fc8
Packit 130fc8
    DBG_WHEREAMI;
Packit 130fc8
Packit 130fc8
    self->server = NULL;
Packit 130fc8
Packit 130fc8
    Py_INCREF(conn_class);
Packit 130fc8
    self->conn_class = conn_class;
Packit 130fc8
Packit 130fc8
    self->mainloop = mainloop;
Packit 130fc8
    mainloop = NULL;    /* don't DECREF it - the DBusServer owns it now */
Packit 130fc8
Packit 130fc8
    ref = PyWeakref_NewRef((PyObject *)self, NULL);
Packit 130fc8
    if (!ref) goto err;
Packit 130fc8
    DBG("Created weak ref %p to (Server *)%p for (DBusServer *)%p",
Packit 130fc8
        ref, self, server);
Packit 130fc8
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    ok = dbus_server_set_data(server, _server_python_slot,
Packit 130fc8
                              (void *)ref,
Packit 130fc8
                              (DBusFreeFunction)dbus_py_take_gil_and_xdecref);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
Packit 130fc8
    if (ok) {
Packit 130fc8
        DBG("Attached weak ref %p ((Server *)%p) to (DBusServer *)%p",
Packit 130fc8
            ref, self, server);
Packit 130fc8
Packit 130fc8
        ref = NULL;     /* don't DECREF it - the DBusServer owns it now */
Packit 130fc8
    }
Packit 130fc8
    else {
Packit 130fc8
        DBG("Failed to attached weak ref %p ((Server *)%p) to "
Packit 130fc8
            "(DBusServer *)%p - will dispose of it", ref, self, server);
Packit 130fc8
        PyErr_NoMemory();
Packit 130fc8
        goto err;
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    DBUS_PY_RAISE_VIA_GOTO_IF_FAIL(server, err);
Packit 130fc8
    self->server = server;
Packit 130fc8
    /* the DBusPyServer will close it now */
Packit 130fc8
    server = NULL;
Packit 130fc8
Packit 130fc8
    if (self->mainloop != Py_None &&
Packit 130fc8
        !dbus_py_set_up_server((PyObject *)self, self->mainloop))
Packit 130fc8
        goto err;
Packit 130fc8
Packit 130fc8
    if (auth_mechanisms && auth_mechanisms != Py_None &&
Packit 130fc8
        !DBusPyServer_set_auth_mechanisms(self, auth_mechanisms))
Packit 130fc8
        goto err;
Packit 130fc8
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    dbus_server_set_new_connection_function(self->server,
Packit 130fc8
                                            DBusPyServer_new_connection_cb,
Packit 130fc8
                                            NULL, NULL);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
Packit 130fc8
    DBG("%s() -> %p", __func__, self);
Packit 130fc8
    TRACE(self);
Packit 130fc8
    return (PyObject *)self;
Packit 130fc8
Packit 130fc8
err:
Packit 130fc8
    DBG("Failed to construct Server from DBusServer at %p", server);
Packit 130fc8
    Py_CLEAR(mainloop);
Packit 130fc8
    Py_CLEAR(self);
Packit 130fc8
    Py_CLEAR(ref);
Packit 130fc8
Packit 130fc8
    if (server) {
Packit 130fc8
        Py_BEGIN_ALLOW_THREADS
Packit 130fc8
        dbus_server_disconnect(server);
Packit 130fc8
        dbus_server_unref(server);
Packit 130fc8
        Py_END_ALLOW_THREADS
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    DBG("%s() fail", __func__);
Packit 130fc8
    DBG_WHEREAMI;
Packit 130fc8
    return NULL;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
/* Server type-methods ============================================== */
Packit 130fc8
Packit 130fc8
static PyObject *
Packit 130fc8
Server_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
Packit 130fc8
{
Packit 130fc8
    DBusServer *server;
Packit 130fc8
    const char *address;
Packit 130fc8
    DBusError error;
Packit 130fc8
    PyObject *self, *conn_class, *mainloop = NULL, *auth_mechanisms = NULL;
Packit 130fc8
    static char *argnames[] = { "address", "connection_class", "mainloop",
Packit 130fc8
        "auth_mechanisms", NULL};
Packit 130fc8
Packit 130fc8
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|OO", argnames,
Packit 130fc8
            &address, &conn_class, &mainloop, &auth_mechanisms)) {
Packit 130fc8
        return NULL;
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    if (!PyType_Check(conn_class) ||
Packit 130fc8
        !PyType_IsSubtype((PyTypeObject *) conn_class, &DBusPyConnection_Type)) {
Packit 130fc8
        /* strictly speaking, it can be any subtype of
Packit 130fc8
         * _dbus_bindings._Connection - but nobody else should be subtyping
Packit 130fc8
         * that, so let's keep this slightly inaccurate message */
Packit 130fc8
        PyErr_SetString(PyExc_TypeError, "connection_class must be "
Packit 130fc8
                "dbus.connection.Connection or a subtype");
Packit 130fc8
        return NULL;
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    dbus_error_init(&error);
Packit 130fc8
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    server = dbus_server_listen(address, &error);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
Packit 130fc8
    if (!server) {
Packit 130fc8
        DBusPyException_ConsumeError(&error);
Packit 130fc8
        return NULL;
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    self = DBusPyServer_NewConsumingDBusServer(cls, server, conn_class,
Packit 130fc8
            mainloop, auth_mechanisms);
Packit 130fc8
    ((Server *)self)->weaklist = NULL;
Packit 130fc8
    TRACE(self);
Packit 130fc8
Packit 130fc8
    return self;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
/* Destructor */
Packit 130fc8
static void Server_tp_dealloc(Server *self)
Packit 130fc8
{
Packit 130fc8
    DBusServer *server = self->server;
Packit 130fc8
    PyObject *et, *ev, *etb;
Packit 130fc8
Packit 130fc8
    /* avoid clobbering any pending exception */
Packit 130fc8
    PyErr_Fetch(&et, &ev, &etb;;
Packit 130fc8
Packit 130fc8
    if (self->weaklist) {
Packit 130fc8
        PyObject_ClearWeakRefs((PyObject *)self);
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    TRACE(self);
Packit 130fc8
    DBG("Deallocating Server at %p (DBusServer at %p)", self, server);
Packit 130fc8
    DBG_WHEREAMI;
Packit 130fc8
Packit 130fc8
    if (server) {
Packit 130fc8
        DBG("Server at %p has a server, disconnecting it...", self);
Packit 130fc8
        Py_BEGIN_ALLOW_THREADS
Packit 130fc8
        dbus_server_disconnect(server);
Packit 130fc8
        Py_END_ALLOW_THREADS
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    Py_CLEAR(self->mainloop);
Packit 130fc8
Packit 130fc8
    /* make sure to do this last to preserve the invariant that
Packit 130fc8
     * self->server is always non-NULL for any referenced Server.
Packit 130fc8
     */
Packit 130fc8
    DBG("Server at %p: nulling self->server", self);
Packit 130fc8
    self->server = NULL;
Packit 130fc8
Packit 130fc8
    if (server) {
Packit 130fc8
        DBG("Server at %p: unreffing server", self);
Packit 130fc8
        dbus_server_unref(server);
Packit 130fc8
    }
Packit 130fc8
Packit 130fc8
    DBG("Server at %p: freeing self", self);
Packit 130fc8
    PyErr_Restore(et, ev, etb);
Packit 130fc8
    (Py_TYPE(self)->tp_free)((PyObject *)self);
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
PyDoc_STRVAR(Server_disconnect__doc__,
Packit 130fc8
"disconnect()\n\n"
Packit 130fc8
"Releases the server's address and stops listening for new clients.\n\n"
Packit 130fc8
"If called more than once, only the first call has an effect.");
Packit 130fc8
static PyObject *
Packit 130fc8
Server_disconnect (Server *self, PyObject *args UNUSED)
Packit 130fc8
{
Packit 130fc8
    TRACE(self);
Packit 130fc8
    if (self->server) {
Packit 130fc8
        Py_BEGIN_ALLOW_THREADS
Packit 130fc8
        dbus_server_disconnect(self->server);
Packit 130fc8
        Py_END_ALLOW_THREADS
Packit 130fc8
    }
Packit 130fc8
    Py_RETURN_NONE;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
PyDoc_STRVAR(Server_get_address__doc__,
Packit 130fc8
"get_address() -> str\n\n"
Packit 130fc8
"Returns the address of the server.");
Packit 130fc8
static PyObject *
Packit 130fc8
Server_get_address(Server *self, PyObject *args UNUSED)
Packit 130fc8
{
Packit 130fc8
    const char *address;
Packit 130fc8
Packit 130fc8
    TRACE(self);
Packit 130fc8
    DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server);
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    address = dbus_server_get_address(self->server);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
Packit 130fc8
    return NATIVESTR_FROMSTR(address);
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
PyDoc_STRVAR(Server_get_id__doc__,
Packit 130fc8
"get_id() -> str\n\n"
Packit 130fc8
"Returns the unique ID of the server.");
Packit 130fc8
static PyObject *
Packit 130fc8
Server_get_id(Server *self, PyObject *args UNUSED)
Packit 130fc8
{
Packit 130fc8
    const char *id;
Packit 130fc8
Packit 130fc8
    TRACE(self);
Packit 130fc8
    DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server);
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    id = dbus_server_get_id(self->server);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
Packit 130fc8
    return NATIVESTR_FROMSTR(id);
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
PyDoc_STRVAR(Server_get_is_connected__doc__,
Packit 130fc8
"get_is_connected() -> bool\n\n"
Packit 130fc8
"Return true if this Server is still listening for new connections.\n");
Packit 130fc8
static PyObject *
Packit 130fc8
Server_get_is_connected (Server *self, PyObject *args UNUSED)
Packit 130fc8
{
Packit 130fc8
    dbus_bool_t ret;
Packit 130fc8
Packit 130fc8
    TRACE(self);
Packit 130fc8
    DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->server);
Packit 130fc8
    Py_BEGIN_ALLOW_THREADS
Packit 130fc8
    ret = dbus_server_get_is_connected(self->server);
Packit 130fc8
    Py_END_ALLOW_THREADS
Packit 130fc8
    return PyBool_FromLong(ret);
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
/* Server type object =============================================== */
Packit 130fc8
Packit 130fc8
struct PyMethodDef DBusPyServer_tp_methods[] = {
Packit 130fc8
#define ENTRY(name, flags) {#name, (PyCFunction)Server_##name, flags, Server_##name##__doc__}
Packit 130fc8
    ENTRY(disconnect,       METH_NOARGS),
Packit 130fc8
    ENTRY(get_address,      METH_NOARGS),
Packit 130fc8
    ENTRY(get_id,           METH_NOARGS),
Packit 130fc8
    ENTRY(get_is_connected, METH_NOARGS),
Packit 130fc8
    {NULL},
Packit 130fc8
#undef ENTRY
Packit 130fc8
};
Packit 130fc8
Packit 130fc8
PyTypeObject DBusPyServer_Type = {
Packit 130fc8
    PyVarObject_HEAD_INIT(NULL, 0)
Packit 130fc8
    "_dbus_bindings._Server",/*tp_name*/
Packit 130fc8
    sizeof(Server),         /*tp_basicsize*/
Packit 130fc8
    0,                      /*tp_itemsize*/
Packit 130fc8
    /* methods */
Packit 130fc8
    (destructor)Server_tp_dealloc,
Packit 130fc8
    0,                      /*tp_print*/
Packit 130fc8
    0,                      /*tp_getattr*/
Packit 130fc8
    0,                      /*tp_setattr*/
Packit 130fc8
    0,                      /*tp_compare*/
Packit 130fc8
    0,                      /*tp_repr*/
Packit 130fc8
    0,                      /*tp_as_number*/
Packit 130fc8
    0,                      /*tp_as_sequence*/
Packit 130fc8
    0,                      /*tp_as_mapping*/
Packit 130fc8
    0,                      /*tp_hash*/
Packit 130fc8
    0,                      /*tp_call*/
Packit 130fc8
    0,                      /*tp_str*/
Packit 130fc8
    0,                      /*tp_getattro*/
Packit 130fc8
    0,                      /*tp_setattro*/
Packit 130fc8
    0,                      /*tp_as_buffer*/
Packit 130fc8
#ifdef PY3
Packit 130fc8
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
Packit 130fc8
#else
Packit 130fc8
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_BASETYPE,
Packit 130fc8
#endif
Packit 130fc8
    Server_tp_doc,          /*tp_doc*/
Packit 130fc8
    0,                      /*tp_traverse*/
Packit 130fc8
    0,                      /*tp_clear*/
Packit 130fc8
    0,                      /*tp_richcompare*/
Packit 130fc8
    offsetof(Server, weaklist),   /*tp_weaklistoffset*/
Packit 130fc8
    0,                      /*tp_iter*/
Packit 130fc8
    0,                      /*tp_iternext*/
Packit 130fc8
    DBusPyServer_tp_methods,/*tp_methods*/
Packit 130fc8
    0,                      /*tp_members*/
Packit 130fc8
    0,                      /*tp_getset*/
Packit 130fc8
    0,                      /*tp_base*/
Packit 130fc8
    0,                      /*tp_dict*/
Packit 130fc8
    0,                      /*tp_descr_get*/
Packit 130fc8
    0,                      /*tp_descr_set*/
Packit 130fc8
    0,                      /*tp_dictoffset*/
Packit 130fc8
    0,                      /*tp_init*/
Packit 130fc8
    0,                      /*tp_alloc*/
Packit 130fc8
    Server_tp_new,          /*tp_new*/
Packit 130fc8
    0,                      /*tp_free*/
Packit 130fc8
    0,                      /*tp_is_gc*/
Packit 130fc8
};
Packit 130fc8
Packit 130fc8
dbus_bool_t
Packit 130fc8
dbus_py_init_server_types(void)
Packit 130fc8
{
Packit 130fc8
    /* Get a slot to store our weakref on DBus Server */
Packit 130fc8
    _server_python_slot = -1;
Packit 130fc8
    if (!dbus_server_allocate_data_slot(&_server_python_slot))
Packit 130fc8
        return FALSE;
Packit 130fc8
Packit 130fc8
    if (PyType_Ready(&DBusPyServer_Type) < 0)
Packit 130fc8
        return FALSE;
Packit 130fc8
Packit 130fc8
    return TRUE;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
dbus_bool_t
Packit 130fc8
dbus_py_insert_server_types(PyObject *this_module)
Packit 130fc8
{
Packit 130fc8
    /* PyModule_AddObject steals a ref */
Packit 130fc8
    Py_INCREF (&DBusPyServer_Type);
Packit 130fc8
    if (PyModule_AddObject(this_module, "_Server",
Packit 130fc8
                           (PyObject *)&DBusPyServer_Type) < 0) return FALSE;
Packit 130fc8
Packit 130fc8
    return TRUE;
Packit 130fc8
}
Packit 130fc8
Packit 130fc8
/* vim:set ft=c cino< sw=4 sts=4 et: */