source: trunk/src/dbus/qdbusconnection.cpp@ 637

Last change on this file since 637 was 561, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 36.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtDBus module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <qdebug.h>
43#include <qcoreapplication.h>
44#include <qstringlist.h>
45
46#include "qdbusconnection.h"
47#include "qdbusconnectioninterface.h"
48#include "qdbuserror.h"
49#include "qdbusmessage.h"
50#include "qdbusmessage_p.h"
51#include "qdbusconnection_p.h"
52#include "qdbusinterface_p.h"
53#include "qdbusutil_p.h"
54
55#include "qdbusthreaddebug_p.h"
56
57QT_BEGIN_NAMESPACE
58
59class QDBusConnectionManager
60{
61public:
62 QDBusConnectionManager() {}
63 ~QDBusConnectionManager();
64
65 QDBusConnectionPrivate *connection(const QString &name) const;
66 void removeConnection(const QString &name);
67 void setConnection(const QString &name, QDBusConnectionPrivate *c);
68
69 QDBusConnectionPrivate *sender() const;
70 void setSender(const QDBusConnectionPrivate *s);
71
72 mutable QMutex mutex;
73private:
74 QHash<QString, QDBusConnectionPrivate *> connectionHash;
75
76 mutable QMutex senderMutex;
77 QString senderName; // internal; will probably change
78};
79
80Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
81
82QDBusConnectionPrivate *QDBusConnectionManager::sender() const
83{
84 QMutexLocker locker(&senderMutex);
85 return connection(senderName);
86}
87
88void QDBusConnectionManager::setSender(const QDBusConnectionPrivate *s)
89{
90 QMutexLocker locker(&senderMutex);
91 senderName = (s ? s->name : QString());
92}
93
94QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
95{
96 return connectionHash.value(name, 0);
97}
98
99void QDBusConnectionManager::removeConnection(const QString &name)
100{
101 QDBusConnectionPrivate *d = 0;
102 d = connectionHash.take(name);
103 if (d && !d->ref.deref())
104 d->deleteYourself();
105
106 // Static objects may be keeping the connection open.
107 // However, it is harmless to have outstanding references to a connection that is
108 // closing as long as those references will be soon dropped without being used.
109
110 // ### Output a warning if connections are being used after they have been removed.
111}
112
113QDBusConnectionManager::~QDBusConnectionManager()
114{
115 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
116 it != connectionHash.constEnd(); ++it) {
117 QDBusConnectionPrivate *d = it.value();
118 if (!d->ref.deref())
119 d->deleteYourself();
120 else
121 d->closeConnection();
122 }
123 connectionHash.clear();
124}
125
126QDBUS_EXPORT void qDBusBindToApplication();
127void qDBusBindToApplication()
128{
129}
130
131void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
132{
133 connectionHash[name] = c;
134 c->name = name;
135}
136
137/*!
138 \fn QDBusConnection &QDBusConnection::sessionBus()
139 \relates QDBusConnection
140
141 Returns a QDBusConnection object opened with the session bus. The object reference returned
142 by this function is valid until the QCoreApplication's destructor is run, when the
143 connection will be closed and the object, deleted.
144*/
145/*!
146 \fn QDBusConnection &QDBusConnection::systemBus()
147 \relates QDBusConnection
148
149 Returns a QDBusConnection object opened with the system bus. The object reference returned
150 by this function is valid until the QCoreApplication's destructor is run, when the
151 connection will be closed and the object, deleted.
152*/
153
154/*!
155 \class QDBusConnection
156 \inmodule QtDBus
157 \since 4.2
158
159 \brief The QDBusConnection class represents a connection to the D-Bus bus daemon.
160
161 This class is the initial point in a D-Bus session. Using it, you
162 can get access to remote objects, interfaces; connect remote
163 signals to your object's slots; register objects, etc.
164
165 D-Bus connections are created using the connectToBus() function,
166 which opens a connection to the server daemon and does the initial
167 handshaking, associating that connection with a name. Further
168 attempts to connect using the same name will return the same
169 connection.
170
171 The connection is then torn down using the disconnectFromBus()
172 function.
173
174 As a convenience for the two most common connection types, the
175 sessionBus() and systemBus() functions return open connections to
176 the session server daemon and the system server daemon,
177 respectively. Those connections are opened when first used and are
178 closed when the QCoreApplication destructor is run.
179
180 D-Bus also supports peer-to-peer connections, without the need for
181 a bus server daemon. Using this facility, two applications can
182 talk to each other and exchange messages. This can be achieved by
183 passing an address to connectToBus() function, which was opened by
184 another D-Bus application using QDBusServer.
185*/
186
187/*!
188 \enum QDBusConnection::BusType
189 Specifies the type of the bus connection. The valid bus types are:
190
191 \value SessionBus the session bus, associated with the running desktop session
192 \value SystemBus the system bus, used to communicate with system-wide processes
193 \value ActivationBus the activation bus, the "alias" for the bus that started the
194 service
195
196 On the Session Bus, one can find other applications by the same user that are sharing the same
197 desktop session (hence the name). On the System Bus, however, processes shared for the whole
198 system are usually found.
199*/
200
201/*!
202 \enum QDBusConnection::RegisterOption
203 Specifies the options for registering objects with the connection. The possible values are:
204
205 \value ExportAdaptors export the contents of adaptors found in this object
206
207 \value ExportScriptableSlots export this object's scriptable slots
208 \value ExportScriptableSignals export this object's scriptable signals
209 \value ExportScriptableProperties export this object's scriptable properties
210 \value ExportScriptableContents shorthand form for ExportScriptableSlots |
211 ExportScriptableSignals |
212 ExportScriptableProperties
213
214 \value ExportNonScriptableSlots export this object's non-scriptable slots
215 \value ExportNonScriptableSignals export this object's non-scriptable signals
216 \value ExportNonScriptableProperties export this object's non-scriptable properties
217 \value ExportNonScriptableContents shorthand form for ExportNonScriptableSlots |
218 ExportNonScriptableSignals |
219 ExportNonScriptableProperties
220
221 \value ExportAllSlots export all of this object's slots
222 \value ExportAllSignals export all of this object's signals
223 \value ExportAllProperties export all of this object's properties
224 \value ExportAllContents export all of this object's contents
225
226 \value ExportChildObjects export this object's child objects
227
228 \sa registerObject(), QDBusAbstractAdaptor, {usingadaptors.html}{Using adaptors}
229*/
230
231/*!
232 \enum QDBusConnection::UnregisterMode
233 The mode for unregistering an object path:
234
235 \value UnregisterNode unregister this node only: do not unregister child objects
236 \value UnregisterTree unregister this node and all its sub-tree
237
238 Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode
239 will unregister the child objects too.
240*/
241
242/*!
243 Creates a QDBusConnection object attached to the connection with name \a name.
244
245 This does not open the connection. You have to call connectToBus() to open it.
246*/
247QDBusConnection::QDBusConnection(const QString &name)
248{
249 if (name.isEmpty()) {
250 d = 0;
251 } else {
252 QMutexLocker locker(&_q_manager()->mutex);
253 d = _q_manager()->connection(name);
254 if (d)
255 d->ref.ref();
256 }
257}
258
259/*!
260 Creates a copy of the \a other connection.
261*/
262QDBusConnection::QDBusConnection(const QDBusConnection &other)
263{
264 d = other.d;
265 if (d)
266 d->ref.ref();
267}
268
269/*!
270 \internal
271 Creates a connection object with the given \a dd as private object.
272*/
273QDBusConnection::QDBusConnection(QDBusConnectionPrivate *dd)
274{
275 d = dd;
276 if (d)
277 d->ref.ref();
278}
279
280/*!
281 Disposes of this object. This does not close the connection: you
282 have to call disconnectFromBus() to do that.
283*/
284QDBusConnection::~QDBusConnection()
285{
286 if (d && !d->ref.deref())
287 d->deleteYourself();
288}
289
290/*!
291 Creates a copy of the connection \a other in this object. Note
292 that the connection this object referenced before the copy, is not
293 spontaneously disconnected.
294
295 \sa disconnectFromBus()
296*/
297QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
298{
299 if (other.d)
300 other.d->ref.ref();
301 if (d && !d->ref.deref())
302 d->deleteYourself();
303 d = other.d;
304 return *this;
305}
306
307/*!
308 Opens a connection of type \a type to one of the known busses and
309 associate with it the connection name \a name. Returns a
310 QDBusConnection object associated with that connection.
311*/
312QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
313{
314// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
315// "Cannot create connection without a Q[Core]Application instance");
316 if (!qdbus_loadLibDBus()) {
317 QDBusConnectionPrivate *d = 0;
318 return QDBusConnection(d);
319 }
320
321 QMutexLocker locker(&_q_manager()->mutex);
322
323 QDBusConnectionPrivate *d = _q_manager()->connection(name);
324 if (d || name.isEmpty())
325 return QDBusConnection(d);
326
327 d = new QDBusConnectionPrivate;
328 DBusConnection *c = 0;
329 QDBusErrorInternal error;
330 switch (type) {
331 case SystemBus:
332 c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error);
333 break;
334 case SessionBus:
335 c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error);
336 break;
337 case ActivationBus:
338 c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error);
339 break;
340 }
341 d->setConnection(c, error); //setConnection does the error handling for us
342
343 _q_manager()->setConnection(name, d);
344
345 QDBusConnection retval(d);
346
347 // create the bus service
348 // will lock in QDBusConnectionPrivate::connectRelay()
349 d->setBusService(retval);
350
351 return retval;
352}
353
354/*!
355 Opens a peer-to-peer connection on address \a address and associate with it the
356 connection name \a name. Returns a QDBusConnection object associated with that connection.
357*/
358QDBusConnection QDBusConnection::connectToBus(const QString &address,
359 const QString &name)
360{
361// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
362// "Cannot create connection without a Q[Core]Application instance");
363 if (!qdbus_loadLibDBus()){
364 QDBusConnectionPrivate *d = 0;
365 return QDBusConnection(d);
366 }
367
368 QMutexLocker locker(&_q_manager()->mutex);
369
370 QDBusConnectionPrivate *d = _q_manager()->connection(name);
371 if (d || name.isEmpty())
372 return QDBusConnection(d);
373
374 d = new QDBusConnectionPrivate;
375 // setConnection does the error handling for us
376 QDBusErrorInternal error;