void ServiceDirectory::updateServiceInfo(const ServiceInfo &svcinfo) { boost::recursive_mutex::scoped_lock lock(mutex); std::map<unsigned int, ServiceInfo>::iterator itService; for (itService = connectedServices.begin(); itService != connectedServices.end(); ++itService) { if (svcinfo.sessionId() == itService->second.sessionId()) { itService->second.setEndpoints(svcinfo.endpoints()); } } itService = connectedServices.find(svcinfo.serviceId()); if (itService != connectedServices.end()) { connectedServices[svcinfo.serviceId()] = svcinfo; return; } // maybe the service registration was pending... itService = pendingServices.find(svcinfo.serviceId()); if (itService != pendingServices.end()) { pendingServices[svcinfo.serviceId()] = svcinfo; return; } std::stringstream ss; ss << "updateServiceInfo: Can't find service #" << svcinfo.serviceId(); qiLogVerbose() << ss.str(); throw std::runtime_error(ss.str()); }
/* * 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(); }