/* Implementation of Bus, a subtype of Connection.
*
* Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
*
* 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 "conn-internal.h"
PyObject *
DBusPyConnection_NewForBus(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
{
PyObject *first = NULL, *mainloop = NULL;
DBusConnection *conn;
DBusError error;
Connection *self;
static char *argnames[] = {"address_or_type", "mainloop", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", argnames,
&first, &mainloop)) {
return NULL;
}
dbus_error_init(&error);
if (first &&
#ifdef PY3
PyUnicode_Check(first)
#else
PyBytes_Check(first)
#endif
)
{
dbus_bool_t ret;
/* It's a custom address. First connect to it, then register. */
self = (Connection *)(DBusPyConnection_Type.tp_new)(cls, args, kwargs);
if (!self) return NULL;
TRACE(self);
Py_BEGIN_ALLOW_THREADS
ret = dbus_bus_register(self->conn, &error);
Py_END_ALLOW_THREADS
if (!ret) {
DBusPyException_ConsumeError(&error);
Py_CLEAR(self);
return NULL;
}
return (PyObject *)self;
}
else if (!first || INTORLONG_CHECK(first))
{
long type;
PyObject *libdbusconn;
PyObject *new_args;
PyObject *new_kwargs;
/* If the first argument isn't a string, it must be an integer
representing one of the well-known bus types. The default is
DBUS_BUS_SESSION. */
if (first) {
/* on Python 2 this accepts either int or long */
type = PyLong_AsLong(first);
if (type == -1 && PyErr_Occurred())
return NULL;
if (type != DBUS_BUS_SESSION && type != DBUS_BUS_SYSTEM
&& type != DBUS_BUS_STARTER) {
PyErr_Format(PyExc_ValueError, "Unknown bus type %ld", type);
return NULL;
}
}
else {
type = DBUS_BUS_SESSION;
}
Py_BEGIN_ALLOW_THREADS
conn = dbus_bus_get_private(type, &error);
Py_END_ALLOW_THREADS
if (!conn) {
DBusPyException_ConsumeError(&error);
return NULL;
}
libdbusconn = DBusPyLibDBusConnection_New (conn);
dbus_connection_unref (conn);
if (!libdbusconn)
return NULL;
new_args = PyTuple_Pack(2, libdbusconn, mainloop ? mainloop : Py_None);
Py_CLEAR(libdbusconn);
if (!new_args) {
return NULL;
}
new_kwargs = PyDict_New();
if (!new_kwargs) {
Py_CLEAR(new_args);
return NULL;
}
self = (Connection *)(DBusPyConnection_Type.tp_new)(cls, new_args,
new_kwargs);
Py_CLEAR(new_args);
Py_CLEAR(new_kwargs);
return (PyObject *)self; /* whether NULL or not */
}
else {
PyErr_SetString(PyExc_TypeError, "A string address or an integer "
"bus type is required");
return NULL;
}
}
PyObject *
DBusPyConnection_GetUniqueName(Connection *self, PyObject *args UNUSED)
{
const char *name;
TRACE(self);
DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
Py_BEGIN_ALLOW_THREADS
name = dbus_bus_get_unique_name(self->conn);
Py_END_ALLOW_THREADS
if (!name) {
return DBusPyException_SetString("This connection has no unique name "
"yet");
}
return NATIVESTR_FROMSTR(name);
}
PyObject *
DBusPyConnection_SetUniqueName(Connection *self, PyObject *args)
{
const char *old_name, *new_name;
if (!PyArg_ParseTuple(args, "s:set_unique_name", &new_name)) {
return NULL;
}
TRACE(self);
DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
/* libdbus will assert if we try to set a unique name when there's
* already one, so we need to make sure that can't happen.
* (Thanks, libdbus.)
*
* The things that can set the unique name are:
* - this function - but we don't release the GIL, so only one instance of
* this function can run
* - dbus_bus_get - but this is only called in a __new__ or __new__-like
* function, so the new connection isn't available to other code yet
* and this function can't be called on it
* - dbus_bus_register - same as dbus_bus_get
*
* Code outside dbus-python shouldn't be setting the unique name, because
* we're using a private connection; we have to trust the authors
* of mainloop bindings not to do silly things like that.
*/
old_name = dbus_bus_get_unique_name(self->conn);
if (old_name != NULL) {
PyErr_Format(PyExc_ValueError, "This connection already has a "
"unique name: '%s'", old_name);
return NULL;
}
dbus_bus_set_unique_name(self->conn, new_name);
Py_RETURN_NONE;
}
/* vim:set ft=c cino< sw=4 sts=4 et: */