00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <tqapplication.h>
00026 #include <tqevent.h>
00027 #include <tqmetaobject.h>
00028 #include <tqsocketnotifier.h>
00029 #include <tqtimer.h>
00030
00031 #include "tqdbusconnection_p.h"
00032 #include "tqdbusmessage.h"
00033
00034 Atomic::Atomic(int value) : m_value(value)
00035 {
00036 }
00037
00038 void Atomic::ref()
00039 {
00040 m_value++;
00041 }
00042
00043 bool Atomic::deref()
00044 {
00045 m_value--;
00046 return m_value > 0;
00047 }
00048
00049 int TQT_DBusConnectionPrivate::messageMetaType = 0;
00050
00051 static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
00052 {
00053 Q_ASSERT(timeout);
00054 Q_ASSERT(data);
00055
00056
00057
00058 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00059
00060 if (!dbus_timeout_get_enabled(timeout))
00061 return true;
00062
00063 if (!tqApp) {
00064 d->pendingTimeouts.append(timeout);
00065 return true;
00066 }
00067 int timerId = d->startTimer(dbus_timeout_get_interval(timeout));
00068 if (!timerId)
00069 return false;
00070
00071 d->timeouts[timerId] = timeout;
00072 return true;
00073 }
00074
00075 static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data)
00076 {
00077 Q_ASSERT(timeout);
00078 Q_ASSERT(data);
00079
00080
00081
00082 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00083 for (TQValueList<DBusTimeout*>::iterator it = d->pendingTimeouts.begin();
00084 it != d->pendingTimeouts.end();) {
00085 if ((*it) == timeout) {
00086 it = d->pendingTimeouts.erase(it);
00087 }
00088 else
00089 ++it;
00090 }
00091
00092 TQT_DBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin();
00093 while (it != d->timeouts.end()) {
00094 if (it.data() == timeout) {
00095 d->killTimer(it.key());
00096 TQT_DBusConnectionPrivate::TimeoutHash::iterator copyIt = it;
00097 ++it;
00098 d->timeouts.erase(copyIt);
00099 } else {
00100 ++it;
00101 }
00102 }
00103 }
00104
00105 static void qDBusToggleTimeout(DBusTimeout *timeout, void *data)
00106 {
00107 Q_ASSERT(timeout);
00108 Q_ASSERT(data);
00109
00110
00111
00112 qDBusRemoveTimeout(timeout, data);
00113 qDBusAddTimeout(timeout, data);
00114 }
00115
00116 static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data)
00117 {
00118 Q_ASSERT(watch);
00119 Q_ASSERT(data);
00120
00121 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00122
00123 int flags = dbus_watch_get_flags(watch);
00124 int fd = dbus_watch_get_unix_fd(watch);
00125
00126 TQT_DBusConnectionPrivate::Watcher watcher;
00127 if (flags & DBUS_WATCH_READABLE) {
00128 bool enabled = dbus_watch_get_enabled(watch);
00129
00130 watcher.watch = watch;
00131 if (tqApp) {
00132 watcher.read = new TQSocketNotifier(fd, TQSocketNotifier::Read, d);
00133 if (!enabled) watcher.read->setEnabled(false);
00134 d->connect(watcher.read, TQT_SIGNAL(activated(int)), TQT_SLOT(socketRead(int)));
00135 }
00136 }
00137 if (flags & DBUS_WATCH_WRITABLE) {
00138 bool enabled = dbus_watch_get_enabled(watch);
00139
00140 watcher.watch = watch;
00141 if (tqApp) {
00142 watcher.write = new TQSocketNotifier(fd, TQSocketNotifier::Write, d);
00143 if (!enabled) watcher.write->setEnabled(false);
00144 d->connect(watcher.write, TQT_SIGNAL(activated(int)), TQT_SLOT(socketWrite(int)));
00145 }
00146 }
00147
00148 TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
00149 if (it == d->watchers.end())
00150 {
00151 it = d->watchers.insert(fd, TQT_DBusConnectionPrivate::WatcherList());
00152 }
00153 it.data().append(watcher);
00154
00155 return true;
00156 }
00157
00158 static void qDBusRemoveWatch(DBusWatch *watch, void *data)
00159 {
00160 Q_ASSERT(watch);
00161 Q_ASSERT(data);
00162
00163
00164
00165 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00166 int fd = dbus_watch_get_unix_fd(watch);
00167
00168 TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
00169 if (it != d->watchers.end())
00170 {
00171 TQT_DBusConnectionPrivate::WatcherList& list = *it;
00172 for (TQT_DBusConnectionPrivate::WatcherList::iterator wit = list.begin();
00173 wit != list.end(); ++wit)
00174 {
00175 if ((*wit).watch == watch)
00176 {
00177
00178
00179
00180 d->removedWatches.append(*wit);
00181 if ((*wit).read)
00182 {
00183 (*wit).read->disconnect(d);
00184 (*wit).read = 0;
00185 }
00186 if ((*wit).write)
00187 {
00188 (*wit).write->disconnect(d);
00189 (*wit).write = 0;
00190 }
00191 (*wit).watch = 0;
00192 }
00193 }
00194 }
00195
00196 if (d->removedWatches.count() > 0)
00197 TQTimer::singleShot(0, d, TQT_SLOT(purgeRemovedWatches()));
00198 }
00199
00200 static void qDBusToggleWatch(DBusWatch *watch, void *data)
00201 {
00202 Q_ASSERT(watch);
00203 Q_ASSERT(data);
00204
00205
00206
00207 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00208 int fd = dbus_watch_get_unix_fd(watch);
00209
00210 TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
00211 if (it != d->watchers.end()) {
00212 TQT_DBusConnectionPrivate::WatcherList& list = *it;
00213 for (TQT_DBusConnectionPrivate::WatcherList::iterator wit = list.begin(); wit != list.end();
00214 ++wit)
00215 {
00216 if ((*wit).watch == watch) {
00217 bool enabled = dbus_watch_get_enabled(watch);
00218 int flags = dbus_watch_get_flags(watch);
00219
00220
00221
00222
00223
00224 if (flags & DBUS_WATCH_READABLE && (*wit).read)
00225 (*wit).read->setEnabled(enabled);
00226 if (flags & DBUS_WATCH_WRITABLE && (*wit).write)
00227 (*wit).write->setEnabled(enabled);
00228 return;
00229 }
00230 }
00231 }
00232 }
00233
00234 static void qDBusNewConnection(DBusServer *server, DBusConnection *c, void *data)
00235 {
00236 Q_ASSERT(data); Q_ASSERT(server); Q_ASSERT(c);
00237
00238 tqDebug("SERVER: GOT A NEW CONNECTION");
00239 }
00240
00241 static DBusHandlerResult qDBusSignalFilter(DBusConnection *connection,
00242 DBusMessage *message, void *data)
00243 {
00244 Q_ASSERT(data);
00245 Q_UNUSED(connection);
00246
00247 TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00248 if (d->mode == TQT_DBusConnectionPrivate::InvalidMode)
00249 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00250
00251 int msgType = dbus_message_get_type(message);
00252 bool handled = false;
00253
00254
00255
00256
00257 if (msgType == DBUS_MESSAGE_TYPE_SIGNAL) {
00258 handled = d->handleSignal(message);
00259 } else if (msgType == DBUS_MESSAGE_TYPE_METHOD_CALL) {
00260 handled = d->handleObjectCall(message);
00261 }
00262
00263 return handled ? DBUS_HANDLER_RESULT_HANDLED :
00264 DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00265 }
00266
00267 int TQT_DBusConnectionPrivate::registerMessageMetaType()
00268 {
00269
00270 int tp = 0;
00271 return tp;
00272 }
00273
00274 TQT_DBusConnectionPrivate::TQT_DBusConnectionPrivate(TQObject *parent)
00275 : TQObject(parent), ref(1), mode(InvalidMode), connection(0), server(0),
00276 dispatcher(0), inDispatch(false)
00277 {
00278 static const int msgType = registerMessageMetaType();
00279 Q_UNUSED(msgType);
00280
00281 dbus_error_init(&error);
00282
00283 dispatcher = new TQTimer(this);
00284 TQObject::connect(dispatcher, TQT_SIGNAL(timeout()), this, TQT_SLOT(dispatch()));
00285
00286 m_resultEmissionQueueTimer = new TQTimer(this);
00287 TQObject::connect(m_resultEmissionQueueTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(transmitResultEmissionQueue()));
00288 m_messageEmissionQueueTimer = new TQTimer(this);
00289 TQObject::connect(m_messageEmissionQueueTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(transmitMessageEmissionQueue()));
00290 }
00291
00292 TQT_DBusConnectionPrivate::~TQT_DBusConnectionPrivate()
00293 {
00294 for (PendingCallMap::iterator it = pendingCalls.begin(); it != pendingCalls.end();)
00295 {
00296 PendingCallMap::iterator copyIt = it;
00297 ++it;
00298 dbus_pending_call_cancel(copyIt.key());
00299 dbus_pending_call_unref(copyIt.key());
00300 delete copyIt.data();
00301 pendingCalls.erase(copyIt);
00302 }
00303
00304 if (dbus_error_is_set(&error))
00305 dbus_error_free(&error);
00306
00307 closeConnection();
00308 }
00309
00310 void TQT_DBusConnectionPrivate::closeConnection()
00311 {
00312 ConnectionMode oldMode = mode;
00313 mode = InvalidMode;
00314 if (oldMode == ServerMode) {
00315 if (server) {
00316 dbus_server_disconnect(server);
00317 dbus_server_unref(server);
00318 server = 0;
00319 }
00320 } else if (oldMode == ClientMode) {
00321 if (connection) {
00322
00323 #if 0
00324 dbus_connection_close(connection);
00325
00326 while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
00327 #endif
00328 dbus_connection_unref(connection);
00329 connection = 0;
00330 }
00331 }
00332 }
00333
00334 bool TQT_DBusConnectionPrivate::handleError()
00335 {
00336 lastError = TQT_DBusError(&error);
00337 if (dbus_error_is_set(&error))
00338 dbus_error_free(&error);
00339 return lastError.isValid();
00340 }
00341
00342 void TQT_DBusConnectionPrivate::emitPendingCallReply(const TQT_DBusMessage& message)
00343 {
00344 emit dbusPendingCallReply(message);
00345 }
00346
00347 void TQT_DBusConnectionPrivate::bindToApplication()
00348 {
00349
00350
00351 WatcherHash oldWatchers = watchers;
00352 watchers.clear();
00353
00354 for (WatcherHash::const_iterator it = oldWatchers.begin(); it != oldWatchers.end(); ++it)
00355 {
00356 const WatcherList& list = *it;
00357 for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit)
00358 {
00359 if (!(*wit).read && !(*wit).write) {
00360 qDBusAddWatch((*wit).watch, this);
00361 }
00362 }
00363 }
00364
00365
00366 while (!pendingTimeouts.isEmpty()) {
00367 qDBusAddTimeout(pendingTimeouts.first(), this);
00368 pendingTimeouts.pop_front();
00369 }
00370 }
00371
00372 void TQT_DBusConnectionPrivate::socketRead(int fd)
00373 {
00374
00375 WatcherHash::const_iterator it = watchers.find(fd);
00376 if (it != watchers.end()) {
00377 const WatcherList& list = *it;
00378 for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) {
00379 if ((*wit).read && (*wit).read->isEnabled()) {
00380 if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_READABLE))
00381 tqDebug("OUT OF MEM");
00382 }
00383 }
00384 }
00385 if (mode == ClientMode)
00386 scheduleDispatch();
00387 }
00388
00389 void TQT_DBusConnectionPrivate::socketWrite(int fd)
00390 {
00391
00392 WatcherHash::const_iterator it = watchers.find(fd);
00393 if (it != watchers.end()) {
00394 const WatcherList& list = *it;
00395 for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) {
00396 if ((*wit).write && (*wit).write->isEnabled()) {
00397 if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_WRITABLE))
00398 tqDebug("OUT OF MEM");
00399 }
00400 }
00401 }
00402 }
00403
00404 void TQT_DBusConnectionPrivate::objectDestroyed(TQObject* object)
00405 {
00406
00407 for (PendingCallMap::iterator it = pendingCalls.begin(); it != pendingCalls.end();)
00408 {
00409 TQObject* receiver = (TQObject*) it.data()->receiver;
00410 if (receiver == object || receiver == 0)
00411 {
00412 PendingCallMap::iterator copyIt = it;
00413 ++it;
00414
00415 dbus_pending_call_cancel(copyIt.key());
00416 dbus_pending_call_unref(copyIt.key());
00417 delete copyIt.data();
00418 pendingCalls.erase(copyIt);
00419 }
00420 else
00421 ++it;
00422 }
00423 }
00424
00425 void TQT_DBusConnectionPrivate::purgeRemovedWatches()
00426 {
00427 if (removedWatches.isEmpty()) return;
00428
00429 WatcherList::iterator listIt = removedWatches.begin();
00430 for (; listIt != removedWatches.end(); ++listIt)
00431 {
00432 delete (*listIt).read;
00433 delete (*listIt).write;
00434 }
00435 removedWatches.clear();
00436
00437 uint count = 0;
00438 WatcherHash::iterator it = watchers.begin();
00439 while (it != watchers.end())
00440 {
00441 WatcherList& list = *it;
00442 listIt = list.begin();
00443 while (listIt != list.end())
00444 {
00445 if (!((*listIt).read) && !((*listIt).write))
00446 {
00447 listIt = list.erase(listIt);
00448 ++count;
00449 }
00450 }
00451
00452 if (list.isEmpty())
00453 {
00454 WatcherHash::iterator copyIt = it;
00455 ++it;
00456 watchers.erase(copyIt);
00457 }
00458 else
00459 ++it;
00460 }
00461 }
00462
00463 void TQT_DBusConnectionPrivate::scheduleDispatch()
00464 {
00465 dispatcher->start(0);
00466 }
00467
00468 void TQT_DBusConnectionPrivate::dispatch()
00469 {
00470
00471 if (inDispatch) {
00472 printf("[dbus-1-tqt] WARNING: Attempt to call dispatch() recursively was silently ignored to prevent lockup!\n\r"); fflush(stdout);
00473 return;
00474 }
00475 inDispatch = true;
00476
00477 if (mode == ClientMode)
00478 {
00479 if (dbus_connection_dispatch(connection) != DBUS_DISPATCH_DATA_REMAINS)
00480 {
00481
00482 dispatcher->stop();
00483 }
00484 }
00485
00486 inDispatch = false;
00487 }
00488
00489 void TQT_DBusConnectionPrivate::transmitMessageEmissionQueue()
00490 {
00491 TQT_DBusConnectionPrivate::PendingMessagesForEmit::iterator pmfe;
00492 pmfe = pendingMessages.begin();
00493 while (pmfe != pendingMessages.end()) {
00494 TQT_DBusMessage msg = *pmfe;
00495 pmfe = pendingMessages.remove(pmfe);
00496 dbusSignal(msg);
00497 }
00498 }
00499
00500 bool TQT_DBusConnectionPrivate::handleObjectCall(DBusMessage *message)
00501 {
00502 TQT_DBusMessage msg = TQT_DBusMessage::fromDBusMessage(message);
00503
00504 ObjectMap::iterator it = registeredObjects.find(msg.path());
00505 if (it == registeredObjects.end())
00506 return false;
00507
00508 return it.data()->handleMethodCall(msg);
00509 }
00510
00511 bool TQT_DBusConnectionPrivate::handleSignal(DBusMessage *message)
00512 {
00513 TQT_DBusMessage msg = TQT_DBusMessage::fromDBusMessage(message);
00514
00515
00516
00517
00518
00519
00520
00521
00522 pendingMessages.append(msg);
00523 if (!m_messageEmissionQueueTimer->isActive()) m_messageEmissionQueueTimer->start(0, TRUE);
00524
00525 return true;
00526 }
00527
00528 static dbus_int32_t server_slot = -1;
00529
00530 void TQT_DBusConnectionPrivate::setServer(DBusServer *s)
00531 {
00532 if (!server) {
00533 handleError();
00534 return;
00535 }
00536
00537 server = s;
00538 mode = ServerMode;
00539
00540 dbus_server_allocate_data_slot(&server_slot);
00541 if (server_slot < 0)
00542 return;
00543
00544 dbus_server_set_watch_functions(server, qDBusAddWatch, qDBusRemoveWatch,
00545 qDBusToggleWatch, this, 0);
00546 dbus_server_set_timeout_functions(server, qDBusAddTimeout, qDBusRemoveTimeout,
00547 qDBusToggleTimeout, this, 0);
00548 dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0);
00549
00550 dbus_server_set_data(server, server_slot, this, 0);
00551 }
00552
00553 void TQT_DBusConnectionPrivate::setConnection(DBusConnection *dbc)
00554 {
00555 if (!dbc) {
00556 handleError();
00557 return;
00558 }
00559
00560 connection = dbc;
00561 mode = ClientMode;
00562
00563 dbus_connection_set_exit_on_disconnect(connection, false);
00564 dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
00565 qDBusToggleWatch, this, 0);
00566 dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout,
00567 qDBusToggleTimeout, this, 0);
00568
00569
00570
00571 dbus_bus_add_match(connection, "type='signal'", &error);
00572 if (handleError()) {
00573 closeConnection();
00574 return;
00575 }
00576
00577 const char *service = dbus_bus_get_unique_name(connection);
00578 if (service) {
00579 TQCString filter;
00580 filter += "destination='";
00581 filter += service;
00582 filter += "\'";
00583
00584 dbus_bus_add_match(connection, filter.data(), &error);
00585 if (handleError()) {
00586 closeConnection();
00587 return;
00588 }
00589 } else {
00590 tqWarning("TQT_DBusConnectionPrivate::SetConnection: Unable to get unique name");
00591 }
00592
00593 dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0);
00594
00595
00596 }
00597
00598 static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
00599 {
00600
00601 TQT_DBusConnectionPrivate* d = reinterpret_cast<TQT_DBusConnectionPrivate*>(user_data);
00602 TQT_DBusConnectionPrivate::PendingCallMap::iterator it = d->pendingCalls.find(pending);
00603
00604 DBusMessage *dbusReply = dbus_pending_call_steal_reply(pending);
00605
00606 dbus_set_error_from_message(&d->error, dbusReply);
00607 d->handleError();
00608
00609 if (it != d->pendingCalls.end())
00610 {
00611 TQT_DBusMessage reply = TQT_DBusMessage::fromDBusMessage(dbusReply);
00612
00613 TQT_DBusResultInfo dbusResult;
00614 dbusResult.message = reply;
00615 dbusResult.receiver = it.data()->receiver;
00616 dbusResult.method = it.data()->method.data();
00617 d->m_resultEmissionQueue.append(dbusResult);
00618 d->newMethodInResultEmissionQueue();
00619 }
00620
00621 dbus_message_unref(dbusReply);
00622 dbus_pending_call_unref(pending);
00623 delete it.data();
00624
00625 d->pendingCalls.erase(it);
00626 }
00627
00628 int TQT_DBusConnectionPrivate::sendWithReplyAsync(const TQT_DBusMessage &message, TQObject *receiver,
00629 const char *method)
00630 {
00631 if (!receiver || !method)
00632 return 0;
00633
00634 if (!TQObject::connect(receiver, TQT_SIGNAL(destroyed(TQObject*)),
00635 this, TQT_SLOT(objectDestroyed(TQObject*))))
00636 return false;
00637
00638 DBusMessage *msg = message.toDBusMessage();
00639 if (!msg)
00640 return 0;
00641
00642 int msg_serial = 0;
00643 DBusPendingCall *pending = 0;
00644 if (dbus_connection_send_with_reply(connection, msg, &pending, message.timeout())) {
00645 TQT_DBusPendingCall *pcall = new TQT_DBusPendingCall;
00646 pcall->receiver = receiver;
00647 pcall->method = method;
00648 pcall->pending = pending;
00649 pendingCalls.insert(pcall->pending, pcall);
00650
00651 dbus_pending_call_set_notify(pending, qDBusResultReceived, this, 0);
00652
00653 msg_serial = dbus_message_get_serial(msg);
00654 }
00655
00656 dbus_message_unref(msg);
00657 return msg_serial;
00658 }
00659
00660 void TQT_DBusConnectionPrivate::flush()
00661 {
00662 if (!connection) return;
00663
00664 dbus_connection_flush(connection);
00665 }
00666
00667 void TQT_DBusConnectionPrivate::newMethodInResultEmissionQueue()
00668 {
00669 if (!m_resultEmissionQueueTimer->isActive()) m_resultEmissionQueueTimer->start(0, TRUE);
00670 }
00671
00672 void TQT_DBusConnectionPrivate::transmitResultEmissionQueue()
00673 {
00674 if (!m_resultEmissionQueue.isEmpty()) {
00675 TQT_DBusResultInfoList::Iterator it;
00676 it = m_resultEmissionQueue.begin();
00677 while (it != m_resultEmissionQueue.end()) {
00678 TQT_DBusResultInfo dbusResult = (*it);
00679 m_resultEmissionQueue.remove(it);
00680 it = m_resultEmissionQueue.begin();
00681
00682 TQObject::connect(this, TQT_SIGNAL(dbusPendingCallReply(const TQT_DBusMessage&)), dbusResult.receiver, dbusResult.method.data());
00683 emitPendingCallReply(dbusResult.message);
00684 TQObject::disconnect(this, TQT_SIGNAL(dbusPendingCallReply(const TQT_DBusMessage&)), dbusResult.receiver, dbusResult.method.data());
00685 }
00686 }
00687 }
00688
00689 #include "tqdbusconnection_p.moc"