コード例 #1
0
ファイル: gateway_p.hpp プロジェクト: david781/libqi
 GwTransaction(const Message& msg)
   : content(msg)
   , _destination(TransportSocketPtr())
   , _originalObjectId(msg.object())
   , _originalServiceId(msg.service())
 {
 }
コード例 #2
0
Future<TransportSocketPtr> TransportSocketCache::socket(const ServiceInfo& servInfo, const std::string& protocol)
{
  const std::string& machineId = servInfo.machineId();
  ConnectionAttemptPtr couple = boost::make_shared<ConnectionAttempt>();
  couple->relatedUrls = servInfo.endpoints();
  bool local = machineId == os::getMachineId();
  UrlVector connectionCandidates;

  // If the connection is local, we're mainly interested in localhost endpoint
  if (local)
    connectionCandidates = localhost_only(servInfo.endpoints());

  // If the connection isn't local or if the service doesn't expose local endpoints,
  // try and connect to whatever is available.
  if (connectionCandidates.size() == 0)
    connectionCandidates = servInfo.endpoints();

  couple->endpoint = TransportSocketPtr();
  couple->state = State_Pending;
  {
    // If we already have a pending connection to one of the urls, we return the future in question
    boost::mutex::scoped_lock lock(_socketMutex);

    if (_dying)
      return makeFutureError<TransportSocketPtr>("TransportSocketCache is closed.");

    ConnectionMap::iterator machineIt = _connections.find(machineId);
    if (machineIt != _connections.end())
    {
      // Check if any connection to the machine matches one of our urls
      UrlVector& vurls = couple->relatedUrls;
      for (std::map<Url, ConnectionAttemptPtr>::iterator b = machineIt->second.begin(), e = machineIt->second.end();
           b != e;
           b++)
      {
        UrlVector::iterator uIt = std::find(vurls.begin(), vurls.end(), b->first);
        // We found a matching machineId and URL : return the connected endpoint.
        if (uIt != vurls.end())
          return b->second->promise.future();
      }
    }
    // Otherwise, we keep track of all those URLs and assign them the same promise in our map.
    // They will all track the same connection.
    couple->attemptCount = connectionCandidates.size();
    std::map<Url, ConnectionAttemptPtr>& urlMap = _connections[machineId];
    for (UrlVector::iterator it = connectionCandidates.begin(), end = connectionCandidates.end(); it != end; ++it)
    {
      urlMap[*it] = couple;
      TransportSocketPtr socket = makeTransportSocket(it->protocol());
      _allPendingConnections.push_back(socket);
      Future<void> sockFuture = socket->connect(*it);
      qiLogDebug() << "Inserted [" << machineId << "][" << it->str() << "]";
      sockFuture.connect(&TransportSocketCache::onSocketParallelConnectionAttempt, this, _1, socket, *it, servInfo);
    }
  }
  return couple->promise.future();
}
コード例 #3
0
 qi::TransportSocketPtr ServiceDirectory::_socketOfService(unsigned int id)
 {
   boost::recursive_mutex::scoped_lock lock(mutex);
   std::map<unsigned int, TransportSocketPtr>::iterator it = idxToSocket.find(id);
   if (it == idxToSocket.end())
     return TransportSocketPtr();
   else
     return it->second;
 }
コード例 #4
0
ファイル: gwobjecthost.cpp プロジェクト: dmerejkowsky/libqi
void GwObjectHost::assignClientMessageObjectsGwIds(const Signature& signature, Message& msg, TransportSocketPtr sender)
{
  // if there's no chance of any object being in the call we're done.
  if (!hasObjectsSomewhere(signature))
    return;

  AnyReference callParameters = msg.value(signature, sender);

  // re-serialize the arguments so that the objects can receive a GW-specific objectId
  // ObjectHost uses a static int for its objectId so we're OK instantiating multiple
  // ones.
  Message forward;
  MockObjectHost host(Message::Service_Server);

  forward.setFlags(msg.flags());
  forward.setValue(callParameters, signature, &host, sender.get());
  msg.setBuffer(forward.buffer());

  // The message will store all the objects it serializes in the host.
  const ObjectHost::ObjectMap& objects = host.objects();
  std::map<GwObjectId, MetaObject> newObjectsMetaObjects;
  std::map<GwObjectId, std::pair<TransportSocketPtr, ObjectAddress> > newObjectsOrigin;
  std::map<ObjectAddress, GwObjectId> newHostObjectBank;
  for (ObjectHost::ObjectMap::const_iterator it = objects.begin(), end = objects.end(); it != end; ++it)
  {
    GwObjectId oid = it->first;
    ServiceBoundObject* sbo = static_cast<ServiceBoundObject*>(it->second.get());
    RemoteObject* ro = static_cast<RemoteObject*>(sbo->object().asGenericObject()->value);
    ObjectAddress addr;
    addr.service = ro->service();
    addr.object = ro->object();
    ro->setTransportSocket(TransportSocketPtr());

    newObjectsMetaObjects[oid] = ro->metaObject();
    newObjectsOrigin[oid] = std::make_pair(sender, addr);
    newHostObjectBank[addr] = oid;
    // We set an empty transportsocket.
    // Otherwise when we destroy `passed` below, the remoteobject
    // will attempt to send back home a `terminate` message, which we don't want.
    // By setting a null socket the object will stay alive on the remote end.

    qiLogDebug() << "Message " << msg.address() << ", Object connection: {" << addr.service << "," << addr.object
                 << "} <=> {0," << oid << "}";
  }
  {
    boost::upgrade_lock<boost::shared_mutex> lock(_mutex);
    boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock);
    _objectsMetaObjects.insert(newObjectsMetaObjects.begin(), newObjectsMetaObjects.end());
    _objectsOrigin.insert(newObjectsOrigin.begin(), newObjectsOrigin.end());
    _hostObjectBank[sender].insert(newHostObjectBank.begin(), newHostObjectBank.end());
  }
  callParameters.destroy();
}
コード例 #5
0
ファイル: gwobjecthost.cpp プロジェクト: dmerejkowsky/libqi
void GwObjectHost::harvestServiceOriginatingObjects(Message& msg, TransportSocketPtr sender)
{
  Signature signature;
  {
    boost::upgrade_lock<boost::shared_mutex> lock(_mutex);
    MetaObject* metaObject = NULL;
    const Signature& (MetaMethod::*signatureGetter)() const = NULL;
    if (msg.type() == Message::Type_Reply || msg.type() == Message::Type_Error)
    {
      std::map<ServiceId, std::map<ObjectId, MetaObject> >::iterator sit = _servicesMetaObjects.find(msg.service());
      if (msg.function() == Message::BoundObjectFunction_MetaObject &&
          sit->second.find(msg.object()) == sit->second.end())
      {
        boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock);
        _servicesMetaObjects[msg.service()][Message::GenericObject_Main] = extractReturnedMetaObject(msg, sender);
        return;
      }
      metaObject = &_servicesMetaObjects[msg.service()][msg.object()];
      signatureGetter = &MetaMethod::returnSignature;
    }
    else if (msg.type() == Message::Type_Call || msg.type() == Message::Type_Post)
    {
      // if a service does a CALL, he does so on a user-supplied object.
      std::map<GwObjectId, MetaObject>::iterator mit = _objectsMetaObjects.find(msg.object());
      assert(mit != _objectsMetaObjects.end());
      metaObject = &mit->second;
      signatureGetter = &MetaMethod::parametersSignature;
    }
    const MetaMethod* method = metaObject->method(msg.function());
    if (!method)
      return;
    signature = (method->*signatureGetter)();
  }
  if (!hasObjectsSomewhere(signature))
  {
    // no object can be here
    return;
  }

  AnyReference passed = msg.value(signature, sender);
  StreamContext filler;
  MockObjectHost host(Message::Service_Server);
  Message dummy;

  // we don't want to pollute the original message and potentially change valid id
  // of contained objects, so we do it in an unrelated message.
  dummy.setValue(passed, signature, &host, &filler);

  const ObjectHost::ObjectMap& objects = host.objects();
  std::map<ObjectId, MetaObject> newServicesMetaObject;
  for (ObjectHost::ObjectMap::const_iterator it = objects.begin(), end = objects.end(); it != end; ++it)
  {
    ServiceBoundObject* sbo = static_cast<ServiceBoundObject*>(it->second.get());
    RemoteObject* ro = static_cast<RemoteObject*>(sbo->object().asGenericObject()->value);

    // We set an empty transportsocket.
    // Otherwise when we destroy `passed` below, the remoteobject
    // will attempt to send back home a `terminate` message, which we don't want.
    // By setting a null socket the object will stay alive on the remote end.
    ro->setTransportSocket(TransportSocketPtr());
    newServicesMetaObject[ro->object()] = ro->metaObject();
  }
  {
    boost::upgrade_lock<boost::shared_mutex> lock(_mutex);
    boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock);
    _servicesMetaObjects[msg.service()].insert(newServicesMetaObject.begin(), newServicesMetaObject.end());
  }
  passed.destroy();
}