void Server::onMessageReady(const qi::Message &msg, TransportSocketPtr socket) { qi::BoundAnyObject obj; // qiLogDebug() << "Server Recv (" << msg.type() << "):" << msg.address(); { boost::mutex::scoped_lock sl(_boundObjectsMutex); BoundAnyObjectMap::iterator it; it = _boundObjects.find(msg.service()); if (it == _boundObjects.end()) { // The message could be addressed to a bound object, inside a // remoteobject host, or to a remoteobject, using the same socket. qiLogVerbose() << "No service for " << msg.address(); if (msg.object() > Message::GenericObject_Main || msg.type() == Message::Type_Reply || msg.type() == Message::Type_Event || msg.type() == Message::Type_Error || msg.type() == Message::Type_Canceled) return; // ... but only if the object id is >main qi::Message retval(Message::Type_Error, msg.address()); std::stringstream ss; ss << "can't find service, address: " << msg.address(); retval.setError(ss.str()); socket->send(retval); qiLogError() << "Can't find service: " << msg.service() << " on " << msg.address(); return; } obj = it->second; } // We were called from the thread pool: synchronous call is ok //qi::getEventLoop()->post(boost::bind<void>(&BoundObject::onMessage, obj, msg, socket)); obj->onMessage(msg, socket); }
void MessageDispatcher::sent(const qi::Message& msg) { //store Call id, we can use them later to notify the client //if the call did not succeed. (network disconnection, message lost) if (msg.type() == qi::Message::Type_Call) { boost::mutex::scoped_lock l(_messageSentMutex); MessageSentMap::iterator it = _messageSent.find(msg.id()); if (it != _messageSent.end()) { qiLogInfo() << "Message ID conflict. A message with the same Id is already in flight" << msg.id(); return; } _messageSent[msg.id()] = msg.address(); } return; }
void MessageDispatcher::dispatch(const qi::Message& msg) { //remove the address from the messageSent map if (msg.type() == qi::Message::Type_Reply) { boost::mutex::scoped_lock sl(_messageSentMutex); MessageSentMap::iterator it; it = _messageSent.find(msg.id()); if (it != _messageSent.end()) _messageSent.erase(it); else qiLogDebug() << "Message " << msg.id() << " is not in the messageSent map"; } { boost::shared_ptr<OnMessageSignal> sig[2]; bool hit = false; { boost::recursive_mutex::scoped_lock sl(_signalMapMutex); SignalMap::iterator it; it = _signalMap.find(Target(msg.service(), msg.object())); if (it != _signalMap.end()) { hit = true; sig[0] = it->second; } it = _signalMap.find(Target(msg.service(), ALL_OBJECTS)); if (it != _signalMap.end()) { hit = true; sig[1] = it->second; } } if (sig[0]) (*sig[0])(msg); if (sig[1]) (*sig[1])(msg); if (!hit) // FIXME: that should probably never happen, raise log level qiLogDebug() << "No listener for service " << msg.service(); } }
//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; } }