Example #1
0
  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);
  }
Example #2
0
 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;
 }
Example #3
0
  //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;
    }
  }