Ejemplo n.º 1
0
  void SessionPrivate::addSdSocketToCache(Future<void> f, const qi::Url& url,
                                          qi::Promise<void> p)
  {
    qiLogDebug() << "addSocketToCache processing";
    if (f.hasError())
    {
      qiLogDebug() << "addSdSocketToCache: connect reported failure";
      _serviceHandler.removeService("ServiceDirectory");
      p.setError(f.error());
      return;
    }

    // Allow the SD process to use the existing socket to talk to our services
    _serverObject.registerSocket(_sdClient.socket());

    /* Allow reusing the SD socket for communicating with services.
     * To do this, we must add it to our socket cache, and for this we need
     * to know the sd machineId
     */
     std::string mid;
     try
     {
       mid = _sdClient.machineId();
     }
     catch (const std::exception& e)
     { // Provide a nice message for backward compatibility
       qiLogVerbose() << e.what();
       qiLogWarning() << "Failed to obtain machineId, connection to service directory will not be reused for other services.";
       p.setValue(0);
       return;
     }
     TransportSocketPtr s = _sdClient.socket();
     qiLogVerbose() << "Inserting sd to cache for " << mid <<" " << url.str() << std::endl;
     _socketsCache.insert(mid, s->remoteEndpoint(), s);
     p.setValue(0);
  }
Ejemplo n.º 2
0
/*
 * Corner case to manage (TODO):
 *
 * You are connecting to machineId foo, you are machineId bar. foo and bar are
 * on different sub-networks with the same netmask. They sadly got the same IP
 * on their subnet: 192.168.1.42. When trying to connect to foo from bar, we
 * will try to connect its endpoints, basically:
 *   - tcp://1.2.3.4:1333 (public IP)
 *   - tcp://192.168.1.42:1333 (subnet public IP)
 * If bar is listening on port 1333, we may connect to it instead of foo (our
 * real target).
 */
void TransportSocketCache::onSocketParallelConnectionAttempt(Future<void> fut,
                                                             MessageSocketPtr socket,
                                                             Url url,
                                                             const ServiceInfo& info)
{
  boost::mutex::scoped_lock lock(_socketMutex);

  if (_dying)
  {
    qiLogDebug() << "ConnectionAttempt: TransportSocketCache is closed";
    if (!fut.hasError())
    {
      _allPendingConnections.remove(socket);
      socket->disconnect();
    }
    return;
  }

  ConnectionMap::iterator machineIt = _connections.find(info.machineId());
  std::map<Url, ConnectionAttemptPtr>::iterator urlIt;
  if (machineIt != _connections.end())
    urlIt = machineIt->second.find(url);

  if (machineIt == _connections.end() || urlIt == machineIt->second.end())
  {
    // The socket was disconnected at some point, and we removed it from our map:
    // return early.
    _allPendingConnections.remove(socket);
    socket->disconnect();
    return;
  }

  ConnectionAttemptPtr attempt = urlIt->second;
  attempt->attemptCount--;
  if (attempt->state != State_Pending)
  {
    qiLogDebug() << "Already connected: reject socket " << socket.get() << " endpoint " << url.str();
    _allPendingConnections.remove(socket);
    socket->disconnect();
    checkClear(attempt, info.machineId());
    return;
  }
  if (fut.hasError())
  {
    // Failing to connect to some of the endpoint is expected.
    qiLogDebug() << "Could not connect to service #" << info.serviceId() << " through url " << url.str();
    _allPendingConnections.remove(socket);
    // It's a critical error if we've exhausted all available endpoints.
    if (attempt->attemptCount == 0)
    {
      std::stringstream err;
      err << "Could not connect to service #" << info.serviceId() << ": no endpoint replied.";
      qiLogError() << err.str();
      attempt->promise.setError(err.str());
      attempt->state = State_Error;
      checkClear(attempt, info.machineId());
    }
    return;
  }
  qi::SignalLink disconnectionTracking = socket->disconnected.connect(
        &TransportSocketCache::onSocketDisconnected, this, url, info)
      .setCallType(MetaCallType_Direct);
  attempt->state = State_Connected;
  attempt->endpoint = socket;
  attempt->promise.setValue(socket);
  attempt->disconnectionTracking = disconnectionTracking;
  qiLogDebug() << "Connected to service #" << info.serviceId() << " through url " << url.str() << " and socket "
               << socket.get();
}