X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcommon%2Fsignalproxy.cpp;h=9d3c04ddac6279729f7751307b681c569aaa7eab;hp=8499e1ada965b2e94895d41f21bd780b1b7cff35;hb=a65f42197839da536975b3e2858eedcef420035f;hpb=2c4e055125a3e3ab7a2bd0d9c0ea33415f6ce7cc diff --git a/src/common/signalproxy.cpp b/src/common/signalproxy.cpp index 8499e1ad..9d3c04dd 100644 --- a/src/common/signalproxy.cpp +++ b/src/common/signalproxy.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2016 by the Quassel Project * + * Copyright (C) 2005-2019 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -173,6 +173,9 @@ int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void ** // ================================================== // SignalProxy // ================================================== + +thread_local SignalProxy *SignalProxy::_current{nullptr}; + SignalProxy::SignalProxy(QObject *parent) : QObject(parent) { @@ -204,12 +207,14 @@ SignalProxy::~SignalProxy() _syncSlave.clear(); removeAllPeers(); + + _current = nullptr; } void SignalProxy::setProxyMode(ProxyMode mode) { - if (_peers.count()) { + if (!_peerMap.empty()) { qWarning() << Q_FUNC_INFO << "Cannot change proxy mode while connected"; return; } @@ -221,7 +226,6 @@ void SignalProxy::setProxyMode(ProxyMode mode) initClient(); } - void SignalProxy::init() { _heartBeatInterval = 0; @@ -230,6 +234,7 @@ void SignalProxy::init() setHeartBeatInterval(30); setMaxHeartBeatCount(2); _secure = false; + _current = this; updateSecureState(); } @@ -268,7 +273,7 @@ bool SignalProxy::addPeer(Peer *peer) if (!peer) return false; - if (_peers.contains(peer)) + if (_peerMap.values().contains(peer)) return true; if (!peer->isOpen()) { @@ -277,7 +282,7 @@ bool SignalProxy::addPeer(Peer *peer) } if (proxyMode() == Client) { - if (!_peers.isEmpty()) { + if (!_peerMap.isEmpty()) { qWarning("SignalProxy: only one peer allowed in client mode!"); return false; } @@ -290,17 +295,16 @@ bool SignalProxy::addPeer(Peer *peer) if (!peer->parent()) peer->setParent(this); - if (peer->_id < 0) { - peer->_id = nextPeerId(); - peer->_connectedSince = QDateTime::currentDateTimeUtc(); + if (peer->id() < 0) { + peer->setId(nextPeerId()); + peer->setConnectedSince(QDateTime::currentDateTimeUtc()); } - _peers.insert(peer); - _peerMap[peer->_id] = peer; + _peerMap[peer->id()] = peer; peer->setSignalProxy(this); - if (_peers.count() == 1) + if (peerCount() == 1) emit connected(); updateSecureState(); @@ -310,10 +314,10 @@ bool SignalProxy::addPeer(Peer *peer) void SignalProxy::removeAllPeers() { - Q_ASSERT(proxyMode() == Server || _peers.count() <= 1); + Q_ASSERT(proxyMode() == Server || peerCount() <= 1); // wee need to copy that list since we modify it in the loop - QSet peers = _peers; - foreach(Peer *peer, peers) { + QList peers = _peerMap.values(); + for (auto peer : peers) { removePeer(peer); } } @@ -326,12 +330,12 @@ void SignalProxy::removePeer(Peer *peer) return; } - if (_peers.isEmpty()) { + if (_peerMap.isEmpty()) { qWarning() << "SignalProxy::removePeer(): No peers in use!"; return; } - if (!_peers.contains(peer)) { + if (!_peerMap.values().contains(peer)) { qWarning() << "SignalProxy: unknown Peer" << peer; return; } @@ -339,8 +343,7 @@ void SignalProxy::removePeer(Peer *peer) disconnect(peer, 0, this, 0); peer->setSignalProxy(0); - _peerMap.remove(peer->_id); - _peers.remove(peer); + _peerMap.remove(peer->id()); emit peerRemoved(peer); if (peer->parent() == this) @@ -348,7 +351,7 @@ void SignalProxy::removePeer(Peer *peer) updateSecureState(); - if (_peers.isEmpty()) + if (_peerMap.isEmpty()) emit disconnected(); } @@ -472,8 +475,11 @@ void SignalProxy::synchronize(SyncableObject *obj) void SignalProxy::detachObject(QObject *obj) { - detachSignals(obj); - detachSlots(obj); + // Don't try to connect SignalProxy from itself on shutdown + if (obj != this) { + detachSignals(obj); + detachSlots(obj); + } } @@ -515,11 +521,8 @@ void SignalProxy::stopSynchronize(SyncableObject *obj) template void SignalProxy::dispatch(const T &protoMessage) { - foreach (Peer *peer, _peers) { - if (peer->isOpen()) - peer->dispatch(protoMessage); - else - QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer)); + for (auto&& peer : _peerMap.values()) { + dispatch(peer, protoMessage); } } @@ -527,10 +530,14 @@ void SignalProxy::dispatch(const T &protoMessage) template void SignalProxy::dispatch(Peer *peer, const T &protoMessage) { + _targetPeer = peer; + if (peer && peer->isOpen()) peer->dispatch(protoMessage); else QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer)); + + _targetPeer = nullptr; } @@ -573,7 +580,9 @@ void SignalProxy::handle(Peer *peer, const SyncMessage &syncMessage) if (eMeta->argTypes(receiverId).count() > 1) returnParams << syncMessage.params; returnParams << returnValue; + _targetPeer = peer; peer->dispatch(SyncMessage(syncMessage.className, syncMessage.objectName, eMeta->methodName(receiverId), returnParams)); + _targetPeer = nullptr; } // send emit update signal @@ -596,7 +605,9 @@ void SignalProxy::handle(Peer *peer, const InitRequest &initRequest) } SyncableObject *obj = _syncSlave[initRequest.className][initRequest.objectName]; + _targetPeer = peer; peer->dispatch(InitData(initRequest.className, initRequest.objectName, initData(obj))); + _targetPeer = nullptr; } @@ -810,8 +821,8 @@ void SignalProxy::updateSecureState() { bool wasSecure = _secure; - _secure = !_peers.isEmpty(); - foreach (const Peer *peer, _peers) { + _secure = !_peerMap.isEmpty(); + for (auto peer : _peerMap.values()) { _secure &= peer->isSecure(); } @@ -821,21 +832,28 @@ void SignalProxy::updateSecureState() QVariantList SignalProxy::peerData() { QVariantList result; - for (auto peer : _peers) { + for (auto &&peer : _peerMap.values()) { QVariantMap data; - data["id"] = peer->_id; - data["clientVersion"] = peer->_clientVersion; - data["clientVersionDate"] = peer->_buildDate; + data["id"] = peer->id(); + data["clientVersion"] = peer->clientVersion(); + // We explicitly rename this, as, due to the Debian reproducability changes, buildDate isn’t actually the build + // date anymore, but on newer clients the date of the last git commit + data["clientVersionDate"] = peer->buildDate(); data["remoteAddress"] = peer->address(); - data["connectedSince"] = peer->_connectedSince; + data["connectedSince"] = peer->connectedSince(); data["secure"] = peer->isSecure(); + data["features"] = static_cast(peer->features().toLegacyFeatures()); + data["featureList"] = peer->features().toStringList(); result << data; } return result; } Peer *SignalProxy::peerById(int peerId) { - return _peerMap[peerId]; + // We use ::value() here instead of the [] operator because the latter has the side-effect + // of automatically inserting a null value with the passed key into the map. See + // https://doc.qt.io/qt-5/qhash.html#operator-5b-5d and https://doc.qt.io/qt-5/qhash.html#value. + return _peerMap.value(peerId); } void SignalProxy::restrictTargetPeers(QSet peers, std::function closure) @@ -851,6 +869,22 @@ void SignalProxy::restrictTargetPeers(QSet peers, std::function c _restrictedTargets = previousRestrictedTargets; } +Peer *SignalProxy::sourcePeer() { + return _sourcePeer; +} + +void SignalProxy::setSourcePeer(Peer *sourcePeer) { + _sourcePeer = sourcePeer; +} + +Peer *SignalProxy::targetPeer() { + return _targetPeer; +} + +void SignalProxy::setTargetPeer(Peer *targetPeer) { + _targetPeer = targetPeer; +} + // ================================================== // ExtendedMetaObject // ==================================================