//should be done in the object thread void RemoteObject::onMessagePending(const qi::Message &msg) { qiLogDebug() << this << "(" << _service << '/' << _object << ") msg " << msg.address() << " " << msg.buffer().size(); if (msg.object() != _object) { qiLogDebug() << "Passing message " << msg.address() << " to host " ; { boost::mutex::scoped_lock lock(_socketMutex); if(_socket) ObjectHost::onMessage(msg, _socket); return; } } if (msg.type() == qi::Message::Type_Event) { SignalBase* sb = signal(msg.event()); if (sb) { try { // Signal associated with properties have incorrect signature, // Trust MetaObject. //std::string sig = sb->signature(); const MetaSignal* ms = _self.metaObject().signal(msg.event()); qi::Signature sig = ms->parametersSignature(); // Remove top-level tuple //sig = sig.substr(1, sig.length()-2); //TODO: Optimise AnyReference value = msg.value((msg.flags()&Message::TypeFlag_DynamicPayload)? "m":sig, _socket); { GenericFunctionParameters args; if (sig == "m") args = value.content().asTupleValuePtr(); else args = value.asTupleValuePtr(); qiLogDebug() << "Triggering local event listeners with args : " << args.size(); sb->trigger(args); } value.destroy(); } catch (const std::exception& e) { qiLogWarning() << "Deserialize error on event: " << e.what(); } } else { qiLogWarning() << "Event message on unknown signal " << msg.event(); qiLogDebug() << metaObject().signalMap().size(); } return; } if (msg.type() != qi::Message::Type_Reply && msg.type() != qi::Message::Type_Error && msg.type() != qi::Message::Type_Canceled) { qiLogError() << "Message " << msg.address() << " type not handled: " << msg.type(); return; } qi::Promise<AnyReference> promise; { boost::mutex::scoped_lock lock(_promisesMutex); std::map<int, qi::Promise<AnyReference> >::iterator it; it = _promises.find(msg.id()); if (it != _promises.end()) { promise = _promises[msg.id()]; _promises.erase(it); qiLogDebug() << "Handling promise id:" << msg.id(); } else { qiLogError() << "no promise found for req id:" << msg.id() << " obj: " << msg.service() << " func: " << msg.function() << " type: " << Message::typeToString(msg.type()); return; } } switch (msg.type()) { case qi::Message::Type_Canceled: { qiLogDebug() << "Message " << msg.address() << " has been cancelled."; promise.setCanceled(); return; } case qi::Message::Type_Reply: { // Get call signature MetaMethod* mm = metaObject().method(msg.function()); if (!mm) { qiLogError() << "Result for unknown function " << msg.function(); promise.setError("Result for unknown function"); return; } try { qi::AnyReference val = msg.value( (msg.flags() & Message::TypeFlag_DynamicPayload) ? "m" : mm->returnSignature(), _socket); promise.setValue(val); } catch (std::runtime_error &err) { promise.setError(err.what()); } qiLogDebug() << "Message " << msg.address() << " passed to promise"; return; } case qi::Message::Type_Error: { try { static std::string sigerr("m"); qi::AnyReference gvp = msg.value(sigerr, _socket).content(); std::string err = gvp.asString(); qiLogVerbose() << "Received error message" << msg.address() << ":" << err; promise.setError(err); } catch (std::runtime_error &e) { //houston we have an error about the error.. promise.setError(e.what()); } return; } default: //not possible return; } }