X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcommon%2Fsignalproxy.cpp;h=f344603cbdc47b6d16fe9d7bb1ac3e213a7bd34b;hp=d9102fd33c84103f051c9a56be7282346f1ee900;hb=0dbec2cfc937857d66a9645249f876f1e6b3f05e;hpb=695758015a80eb8c158a9ac4c0f1c0b547e70df3 diff --git a/src/common/signalproxy.cpp b/src/common/signalproxy.cpp index d9102fd3..f344603c 100644 --- a/src/common/signalproxy.cpp +++ b/src/common/signalproxy.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2015 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -119,7 +119,7 @@ void SignalProxy::SignalRelay::detachSignal(QObject *sender, int signalId) break; } else { - slotIter++; + ++slotIter; } } } @@ -146,9 +146,9 @@ int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void ** for (int i = 0; i < argTypes.size(); i++) { if (argTypes[i] == 0) { #if QT_VERSION >= 0x050000 - qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(_id).methodSignature().constData()); + qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(signal.signalId).methodSignature().constData()); #else - qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(_id).signature()); + qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(signal.signalId).signature()); #endif qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; return _id; @@ -156,9 +156,11 @@ int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void ** params << QVariant(argTypes[i], _a[i+1]); } - if (argTypes.size() >= 1 && argTypes[0] == qMetaTypeId() && proxy()->proxyMode() == SignalProxy::Server) { - Peer *peer = params[0].value(); - proxy()->dispatch(peer, RpcCall(signal.signature, params)); + if (proxy()->_restrictMessageTarget) { + for (auto peer : proxy()->_restrictedTargets) { + if (peer != nullptr) + proxy()->dispatch(peer, RpcCall(signal.signature, params)); + } } else proxy()->dispatch(RpcCall(signal.signature, params)); } @@ -171,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) { @@ -197,17 +202,19 @@ SignalProxy::~SignalProxy() objIter = classIter->erase(objIter); obj->stopSynchronize(this); } - classIter++; + ++classIter; } _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; } @@ -219,7 +226,6 @@ void SignalProxy::setProxyMode(ProxyMode mode) initClient(); } - void SignalProxy::init() { _heartBeatInterval = 0; @@ -228,6 +234,7 @@ void SignalProxy::init() setHeartBeatInterval(30); setMaxHeartBeatCount(2); _secure = false; + _current = this; updateSecureState(); } @@ -266,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()) { @@ -275,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; } @@ -288,11 +295,16 @@ bool SignalProxy::addPeer(Peer *peer) if (!peer->parent()) peer->setParent(this); - _peers.insert(peer); + if (peer->id() < 0) { + peer->setId(nextPeerId()); + peer->setConnectedSince(QDateTime::currentDateTimeUtc()); + } + + _peerMap[peer->id()] = peer; peer->setSignalProxy(this); - if (_peers.count() == 1) + if (peerCount() == 1) emit connected(); updateSecureState(); @@ -302,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); } } @@ -318,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; } @@ -331,7 +343,7 @@ void SignalProxy::removePeer(Peer *peer) disconnect(peer, 0, this, 0); peer->setSignalProxy(0); - _peers.remove(peer); + _peerMap.remove(peer->id()); emit peerRemoved(peer); if (peer->parent() == this) @@ -339,7 +351,7 @@ void SignalProxy::removePeer(Peer *peer) updateSecureState(); - if (_peers.isEmpty()) + if (_peerMap.isEmpty()) emit disconnected(); } @@ -482,7 +494,7 @@ void SignalProxy::detachSlots(QObject *receiver) slotIter = _attachedSlots.erase(slotIter); } else - slotIter++; + ++slotIter; } } @@ -497,7 +509,7 @@ void SignalProxy::stopSynchronize(SyncableObject *obj) classIter->remove(obj->objectName()); break; } - classIter++; + ++classIter; } obj->stopSynchronize(this); } @@ -506,11 +518,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); } } @@ -518,10 +527,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; } @@ -564,7 +577,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 @@ -587,7 +602,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; } @@ -661,12 +678,8 @@ bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList qWarning() << "SignalProxy::invokeSlot(): incompatible param types to invoke" << eMeta->methodName(methodId); return false; } - // if first arg is a PeerPtr, replace it by the address of the peer originally receiving the RpcCall - if (peer && i == 0 && args[0] == qMetaTypeId()) { - QVariant v = QVariant::fromValue(peer); - _a[1] = const_cast(v.constData()); - } else - _a[i+1] = const_cast(params[i].constData()); + + _a[i+1] = const_cast(params[i].constData()); } if (returnValue.type() != QVariant::Invalid) @@ -677,9 +690,11 @@ bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList : Qt::QueuedConnection; if (type == Qt::DirectConnection) { - return receiver->qt_metacall(QMetaObject::InvokeMetaMethod, methodId, _a) < 0; - } - else { + _sourcePeer = peer; + auto result = receiver->qt_metacall(QMetaObject::InvokeMetaMethod, methodId, _a) < 0; + _sourcePeer = nullptr; + return result; + } else { qWarning() << "Queued Connections are not implemented yet"; // note to self: qmetaobject.cpp:990 ff return false; @@ -758,9 +773,11 @@ void SignalProxy::sync_call__(const SyncableObject *obj, SignalProxy::ProxyMode params << QVariant(argTypes[i], va_arg(ap, void *)); } - if (argTypes.size() >= 1 && argTypes[0] == qMetaTypeId() && proxyMode() == SignalProxy::Server) { - Peer *peer = params[0].value(); - dispatch(peer, SyncMessage(eMeta->metaObject()->className(), obj->objectName(), QByteArray(funcname), params)); + if (_restrictMessageTarget) { + for (auto peer : _restrictedTargets) { + if (peer != nullptr) + dispatch(peer, SyncMessage(eMeta->metaObject()->className(), obj->objectName(), QByteArray(funcname), params)); + } } else dispatch(SyncMessage(eMeta->metaObject()->className(), obj->objectName(), QByteArray(funcname), params)); } @@ -801,8 +818,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(); } @@ -810,6 +827,57 @@ void SignalProxy::updateSecureState() emit secureStateChanged(_secure); } +QVariantList SignalProxy::peerData() { + QVariantList result; + for (auto &&peer : _peerMap.values()) { + QVariantMap data; + 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["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]; +} + +void SignalProxy::restrictTargetPeers(QSet peers, std::function closure) +{ + auto previousRestrictMessageTarget = _restrictMessageTarget; + auto previousRestrictedTargets = _restrictedTargets; + _restrictMessageTarget = true; + _restrictedTargets = peers; + + closure(); + + _restrictMessageTarget = previousRestrictMessageTarget; + _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