Make the PeerPtr trick work with sync calls as well
[quassel.git] / src / common / signalproxy.cpp
index 1535be7..f4ca5c1 100644 (file)
@@ -34,6 +34,7 @@
 #include "protocol.h"
 #include "syncableobject.h"
 #include "util.h"
+#include "types.h"
 
 using namespace Protocol;
 
@@ -147,7 +148,11 @@ int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void **
                 params << QVariant(argTypes[i], _a[i+1]);
             }
 
-            proxy()->dispatch(RpcCall(signal.signature, params));
+            if (argTypes.size() >= 1 && argTypes[0] == qMetaTypeId<PeerPtr>() && proxy()->proxyMode() == SignalProxy::Server) {
+                Peer *peer = params[0].value<PeerPtr>();
+                proxy()->dispatch(peer, RpcCall(signal.signature, params));
+            } else
+                proxy()->dispatch(RpcCall(signal.signature, params));
         }
         _id -= _slots.count();
     }
@@ -502,30 +507,40 @@ void SignalProxy::dispatch(const T &protoMessage)
 }
 
 
+template<class T>
+void SignalProxy::dispatch(Peer *peer, const T &protoMessage)
+{
+    if (peer && peer->isOpen())
+        peer->dispatch(protoMessage);
+    else
+        QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer));
+}
+
+
 void SignalProxy::handle(Peer *peer, const SyncMessage &syncMessage)
 {
-    if (!_syncSlave.contains(syncMessage.className()) || !_syncSlave[syncMessage.className()].contains(syncMessage.objectName())) {
-        qWarning() << QString("no registered receiver for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className(), syncMessage.slotName(), syncMessage.objectName())
-                   << syncMessage.params();
+    if (!_syncSlave.contains(syncMessage.className) || !_syncSlave[syncMessage.className].contains(syncMessage.objectName)) {
+        qWarning() << QString("no registered receiver for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className, syncMessage.slotName, syncMessage.objectName)
+                   << syncMessage.params;
         return;
     }
 
-    SyncableObject *receiver = _syncSlave[syncMessage.className()][syncMessage.objectName()];
+    SyncableObject *receiver = _syncSlave[syncMessage.className][syncMessage.objectName];
     ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
-    if (!eMeta->slotMap().contains(syncMessage.slotName())) {
-        qWarning() << QString("no matching slot for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className(), syncMessage.slotName(), syncMessage.objectName())
-                   << syncMessage.params();
+    if (!eMeta->slotMap().contains(syncMessage.slotName)) {
+        qWarning() << QString("no matching slot for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className, syncMessage.slotName, syncMessage.objectName)
+                   << syncMessage.params;
         return;
     }
 
-    int slotId = eMeta->slotMap()[syncMessage.slotName()];
+    int slotId = eMeta->slotMap()[syncMessage.slotName];
     if (proxyMode() != eMeta->receiverMode(slotId)) {
         qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed. Wrong ProxyMode!", eMeta->methodName(slotId).constData());
         return;
     }
 
     QVariant returnValue((QVariant::Type)eMeta->returnType(slotId));
-    if (!invokeSlot(receiver, slotId, syncMessage.params(), returnValue)) {
+    if (!invokeSlot(receiver, slotId, syncMessage.params, returnValue, peer)) {
         qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed ", eMeta->methodName(slotId).constData());
         return;
     }
@@ -534,9 +549,9 @@ void SignalProxy::handle(Peer *peer, const SyncMessage &syncMessage)
         int receiverId = eMeta->receiveMap()[slotId];
         QVariantList returnParams;
         if (eMeta->argTypes(receiverId).count() > 1)
-            returnParams << syncMessage.params();
+            returnParams << syncMessage.params;
         returnParams << returnValue;
-        peer->dispatch(SyncMessage(syncMessage.className(), syncMessage.objectName(), eMeta->methodName(receiverId), returnParams));
+        peer->dispatch(SyncMessage(syncMessage.className, syncMessage.objectName, eMeta->methodName(receiverId), returnParams));
     }
 
     // send emit update signal
@@ -546,20 +561,20 @@ void SignalProxy::handle(Peer *peer, const SyncMessage &syncMessage)
 
 void SignalProxy::handle(Peer *peer, const InitRequest &initRequest)
 {
-   if (!_syncSlave.contains(initRequest.className())) {
+   if (!_syncSlave.contains(initRequest.className)) {
         qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Class:"
-                   << initRequest.className();
+                   << initRequest.className;
         return;
     }
 
-    if (!_syncSlave[initRequest.className()].contains(initRequest.objectName())) {
+    if (!_syncSlave[initRequest.className].contains(initRequest.objectName)) {
         qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Object:"
-                   << initRequest.className() << initRequest.objectName();
+                   << initRequest.className << initRequest.objectName;
         return;
     }
 
-    SyncableObject *obj = _syncSlave[initRequest.className()][initRequest.objectName()];
-    peer->dispatch(InitData(initRequest.className(), initRequest.objectName(), initData(obj)));
+    SyncableObject *obj = _syncSlave[initRequest.className][initRequest.objectName];
+    peer->dispatch(InitData(initRequest.className, initRequest.objectName, initData(obj)));
 }
 
 
@@ -567,34 +582,32 @@ void SignalProxy::handle(Peer *peer, const InitData &initData)
 {
     Q_UNUSED(peer)
 
-    if (!_syncSlave.contains(initData.className())) {
+    if (!_syncSlave.contains(initData.className)) {
         qWarning() << "SignalProxy::handleInitData() received initData for unregistered Class:"
-                   << initData.className();
+                   << initData.className;
         return;
     }
 
-    if (!_syncSlave[initData.className()].contains(initData.objectName())) {
+    if (!_syncSlave[initData.className].contains(initData.objectName)) {
         qWarning() << "SignalProxy::handleInitData() received initData for unregistered Object:"
-                   << initData.className() << initData.objectName();
+                   << initData.className << initData.objectName;
         return;
     }
 
-    SyncableObject *obj = _syncSlave[initData.className()][initData.objectName()];
-    setInitData(obj, initData.initData());
+    SyncableObject *obj = _syncSlave[initData.className][initData.objectName];
+    setInitData(obj, initData.initData);
 }
 
 
 void SignalProxy::handle(Peer *peer, const RpcCall &rpcCall)
 {
-    Q_UNUSED(peer)
-
     QObject *receiver;
     int methodId;
-    SlotHash::const_iterator slot = _attachedSlots.constFind(rpcCall.slotName());
-    while (slot != _attachedSlots.constEnd() && slot.key() == rpcCall.slotName()) {
+    SlotHash::const_iterator slot = _attachedSlots.constFind(rpcCall.slotName);
+    while (slot != _attachedSlots.constEnd() && slot.key() == rpcCall.slotName) {
         receiver = (*slot).first;
         methodId = (*slot).second;
-        if (!invokeSlot(receiver, methodId, rpcCall.params())) {
+        if (!invokeSlot(receiver, methodId, rpcCall.params, peer)) {
             ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
             qWarning("SignalProxy::handleSignal(): invokeMethod for \"%s\" failed ", eMeta->methodName(methodId).constData());
         }
@@ -603,7 +616,7 @@ void SignalProxy::handle(Peer *peer, const RpcCall &rpcCall)
 }
 
 
-bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList &params, QVariant &returnValue)
+bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList &params, QVariant &returnValue, Peer *peer)
 {
     ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
     const QList<int> args = eMeta->argTypes(methodId);
@@ -631,7 +644,12 @@ bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList
             qWarning() << "SignalProxy::invokeSlot(): incompatible param types to invoke" << eMeta->methodName(methodId);
             return false;
         }
-        _a[i+1] = const_cast<void *>(params[i].constData());
+        // 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<PeerPtr>()) {
+            QVariant v = QVariant::fromValue<PeerPtr>(peer);
+            _a[1] = const_cast<void*>(v.constData());
+        } else
+            _a[i+1] = const_cast<void *>(params[i].constData());
     }
 
     if (returnValue.type() != QVariant::Invalid)
@@ -652,10 +670,10 @@ bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList
 }
 
 
-bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList &params)
+bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList &params, Peer *peer)
 {
     QVariant ret;
-    return invokeSlot(receiver, methodId, params, ret);
+    return invokeSlot(receiver, methodId, params, ret, peer);
 }
 
 
@@ -723,7 +741,11 @@ void SignalProxy::sync_call__(const SyncableObject *obj, SignalProxy::ProxyMode
         params << QVariant(argTypes[i], va_arg(ap, void *));
     }
 
-    dispatch(SyncMessage(eMeta->metaObject()->className(), obj->objectName(), QByteArray(funcname), params));
+    if (argTypes.size() >= 1 && argTypes[0] == qMetaTypeId<PeerPtr>() && proxyMode() == SignalProxy::Server) {
+        Peer *peer = params[0].value<PeerPtr>();
+        dispatch(peer, SyncMessage(eMeta->metaObject()->className(), obj->objectName(), QByteArray(funcname), params));
+    } else
+        dispatch(SyncMessage(eMeta->metaObject()->className(), obj->objectName(), QByteArray(funcname), params));
 }