//TODO: ServiceEvent should be RemoteService and ServiceDescription
void ServiceDiscovery::addedService(const RemoteService& service)
{
        ServiceEvent event(service);
        ServiceConfiguration remoteConfig = service.getConfiguration();

        if(mLocalService && mMode == PUBLISH)
        {
            ServiceConfiguration localConfig = mLocalService->getConfiguration();

            if ( localConfig.getName() == remoteConfig.getName() && localConfig.getType() == remoteConfig.getType())
            {
                LOG_INFO("Service published: %s", service.getName().c_str());
                mPublished = true;
            }
        }

        {
            boost::unique_lock<boost::mutex> lock(mServicesMutex);
            ServiceDescription configuration = service.getConfiguration();
            LOG_INFO("+ %s type: %s", configuration.getName().c_str(), configuration.getType().c_str());
            mServices.push_back( configuration );
        }

        {
            boost::unique_lock<boost::mutex> lock(mAddedComponentMutex);
            ServiceAddedSignal.emit( event );
        }
}
void ServiceDiscovery::removedService(const RemoteService& service)
{
	ServiceEvent event(service);
	ServiceDescription serviceDescription = event.getServiceConfiguration(); 

	boost::unique_lock<boost::mutex> lock(mServicesMutex);
	List<ServiceDescription>::iterator it = mServices.find(serviceDescription);

	if (it != mServices.end())	
	{
		{
			boost::unique_lock<boost::mutex> removalLock(mRemovedComponentMutex);
			ServiceDescription configuration = *it;
			LOG_INFO("- %s type: %s", configuration.getName().c_str(), configuration.getType().c_str());
			ServiceRemovedSignal.emit( event );
		}

		mServices.erase(it);
	}
}
void ServiceManager::addService(Service* service, ServiceDescription& desc) {
	RScopeLock lock(_mutex);
	if (service == NULL)
		return;

	intptr_t svcPtr = (intptr_t)service;
	if (_svc.find(svcPtr) != _svc.end())
		return;

	desc._channelName = service->getChannelName();
	desc._svcName = service->getName();

	assert(desc._channelName.length() > 0);

	_svc[svcPtr] = service;
	_localSvcDesc[svcPtr] = desc;

	// connect service to all nodes the manager is connected to
	std::set<Node>::iterator nodeIter;
	nodeIter = _nodes.begin();
	while(nodeIter != _nodes.end()) {
		((Node)*nodeIter).connect(service);
		nodeIter++;
	}

	// iterate continuous queries and notify other service managers about matches.
	std::map<std::string, ServiceFilter>::iterator filterIter = _remoteQueries.begin();
	while(filterIter != _remoteQueries.end()) {
		if (filterIter->second.matches(desc)) {
			Message* foundMsg = desc.toMessage();
			foundMsg->putMeta("um.rpc.filterId", filterIter->second._uuid);
			foundMsg->putMeta("um.rpc.type", "discovered");
			foundMsg->putMeta("um.rpc.channel", desc.getChannelName());
			foundMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID());
			_svcPub->send(foundMsg);
			delete foundMsg;
		}
		filterIter++;
	}
}
void ServiceManager::removeService(Service* service) {
	RScopeLock lock(_mutex);

	if (service == NULL)
		return;

	intptr_t svcPtr = (intptr_t)service;
	if (_svc.find(svcPtr) == _svc.end())
		return;

	std::set<Node>::iterator nodeIter = _nodes.begin();
	while(nodeIter != _nodes.end()) {
		((Node)*nodeIter).disconnect(service);
		nodeIter++;
	}

	assert(_localSvcDesc.find(svcPtr)!= _localSvcDesc.end());
	ServiceDescription desc = _localSvcDesc[svcPtr];

	// iterate continuous queries and notify other service managers about removals.
	std::map<std::string, ServiceFilter>::iterator filterIter = _remoteQueries.begin();
	while(filterIter != _remoteQueries.end()) {
		if (filterIter->second.matches(desc)) {
			Message* removeMsg = desc.toMessage();
			removeMsg->putMeta("um.rpc.filterId", filterIter->second._uuid);
			removeMsg->putMeta("um.rpc.type", "vanished");
			removeMsg->putMeta("um.rpc.channel", desc.getChannelName());
			removeMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID());
			_svcPub->send(removeMsg);
			delete removeMsg;
		}
		filterIter++;
	}

	_svc.erase(svcPtr);
	_localSvcDesc.erase(svcPtr);

}
std::vector<ServiceDescription> ServiceDiscovery::findServices(const ServicePattern& pattern, const std::string& name_space) const
{
    std::vector<ServiceDescription> result;
    List<ServiceDescription>::const_iterator it;

    boost::unique_lock<boost::mutex> lock(mServicesMutex);

    for (it = mServices.begin(); it != mServices.end(); it++) 
    {
        ServiceDescription description = *it;
        std::string serviceprop = description.getDescription("service");
      
        size_t namespace_begin = serviceprop.find_first_of(":") + 1;
        
        if((name_space == "*" || serviceprop.compare(namespace_begin, name_space.size(), name_space) == 0) 
            && pattern.matchDescription(description) ) 
        {
          result.push_back(description);
        }
    }

    return result;
}
void ServiceDiscovery::updatedService(const RemoteService& service)
{
    ServiceDescription desc = service.getConfiguration();

    boost::unique_lock<boost::mutex> lock(mServicesMutex);

    List<ServiceDescription>::iterator it;

    for(it = mServices.begin(); it != mServices.end(); it++) 
    {
       if( desc.compareWithoutTXT(*it) ) 
       {
           std::vector<std::string> labels = desc.getLabels();

           for(unsigned int i = 0; i < labels.size(); i++) 
           {
               it->setDescription(labels[i], desc.getDescription(labels[i]));
           }

           LOG_INFO("Updated service: %s", service.getName().c_str());
       }
    }
}
void ServiceDiscovery::update(const ServiceDescription& desc) 
{
    if(mLocalService != NULL) 
    {
        std::list<std::string> raw_desc = desc.getRawDescriptions();
        UniqueClientLock lock;
        mLocalService->updateStringList(raw_desc);

        LOG_INFO("Updated local service: %s", mLocalService->getName().c_str());
    } else {
        LOG_FATAL("Service Discovery tries to update a description on a non-started local service.\n");
        throw std::runtime_error("Service Discovery tries to update a description on a non-started local service");
    }
}
Exemple #8
0
void ServiceManager::removeService(Service* service) {
	ScopeLock lock(&_mutex);

  if (service == NULL)
    return;
  
  intptr_t svcPtr = (intptr_t)service;
	if (_svc.find(svcPtr) == _svc.end())
    return;
  
  std::set<Node*>::iterator nodeIter = _nodes.begin();
  while(nodeIter != _nodes.end()) {
    (*nodeIter++)->disconnect(service);
  }
  
  assert(_localSvcDesc.find(svcPtr)!= _localSvcDesc.end());
  ServiceDescription* desc = _localSvcDesc[svcPtr];
  
  // iterate continuous queries and notify other service managers about removals.
  std::map<string, ServiceFilter*>::iterator filterIter = _remoteQueries.begin();
  while(filterIter != _remoteQueries.end()) {
    if (filterIter->second->matches(desc)) {
      Message* removeMsg = desc->toMessage();
      removeMsg->setMeta("filterId", filterIter->second->_uuid);
      removeMsg->setMeta("type", "serviceDiscRemoved");
      removeMsg->setMeta("desc:channel", desc->getChannelName());
      _svcPub->send(removeMsg);
      delete removeMsg;
    }
    filterIter++;
  }

  _svc.erase(svcPtr);
  _localSvcDesc.erase(svcPtr);

}
Exemple #9
0
int main(int argc, char** argv) {
	Node n;
	ServiceManager svcMgr;

	Discovery disc(Discovery::MDNS);
	disc.add(n);

	// set some random properties to query for
	ServiceDescription echoSvcDesc;
	echoSvcDesc.setProperty("host", Host::getHostId());
	echoSvcDesc.setProperty("someString", "this is some random string with 123 numbers inside");
	echoSvcDesc.setProperty("someNumber", "1");

	EchoService* echoSvc = new EchoService();
	svcMgr.addService(echoSvc, echoSvcDesc);

	PingService* pingSvc = new PingService();
	svcMgr.addService(pingSvc);


	n.connect(&svcMgr);
	while(true)
		Thread::sleepMs(1000);
}
bool ServiceDescription::operator==(const ServiceDescription& other) const
{
        if(!compareWithoutTXT(other))
            return false;

	std::vector<std::string> labels = this->getLabels();

        int labelsSize = labels.size();

        for(int i = 0; i < labelsSize; i++)
        {  
		std::string label = labels_[i];

                if(this->getDescription(label) != other.getDescription(label))
                        return false;
        }   
	return true;
}
bool ServiceDescription::compareWithoutTXT(const ServiceDescription& other) const 
{
        if( interfaceIndex_ != other.getInterfaceIndex() && !(interfaceIndex_ == AVAHI_IF_UNSPEC || other.getInterfaceIndex() == AVAHI_IF_UNSPEC))
            return false;

        if(protocol_ != other.getProtocol() && !(protocol_ == AVAHI_PROTO_UNSPEC || other.getProtocol() == AVAHI_PROTO_UNSPEC))
            return false;

        if( getName() != other.getName())
            return false;

        if( getType() != other.getType())
            return false;

        // Compare domains and ignore consider that "" defaults to 'local'
	std::string td1 = (domain_ == "" || domain_ == "local") ? "" : domain_;
	std::string td2 = (other.getDomain() == "" || other.getDomain() == "local") ? "" : other.getDomain();

	if (td1 != td2)
		return false;

        return true;
}
void ServiceManager::receive(Message* msg) {
	RScopeLock lock(_mutex);
	// is this a response for one of our requests?
	if (msg->getMeta().find("um.rpc.respId") != msg->getMeta().end()) {
		std::string respId = msg->getMeta("um.rpc.respId");
		if (_findRequests.find(respId) != _findRequests.end()) {
			// put message into responses and signal waiting thread
			_findResponses[respId] = new Message(*msg);
			_findRequests[respId]->signal();
		}
	}

	// is someone simply asking for a service via find?
	if (msg->getMeta().find("um.rpc.type") != msg->getMeta().end() &&
	        msg->getMeta("um.rpc.type").compare("discover") == 0) {
		ServiceFilter filter(msg);
		std::set<ServiceDescription> foundSvcs = findLocal(filter);

		if (foundSvcs.size() > 0) {
			ServiceDescription svcDesc = (*(foundSvcs.begin()));
			Message* foundMsg = svcDesc.toMessage();
			foundMsg->setReceiver(msg->getMeta("um.rpc.mgrId"));
			foundMsg->putMeta("um.rpc.respId", msg->getMeta("um.rpc.reqId"));
			foundMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID());
//			if (_svcPub->isPublishingTo(msg->getMeta("um.rpc.mgrId"))) {
			_svcPub->send(foundMsg);
			// } else {
			// 	// queue message and send in welcome
			// 	_pendingMessages[msg->getMeta("um.rpc.mgrId")].push_back(std::make_pair(Thread::getTimeStampMs(), foundMsg));
			// }
			delete foundMsg;
		}
	}

	// is this the start of a continuous query?
	if (msg->getMeta().find("um.rpc.type") != msg->getMeta().end() &&
	        msg->getMeta("um.rpc.type").compare("startDiscovery") == 0) {
		ServiceFilter filter(msg);
		_remoteQueries[filter.getUUID()] = filter;

		UM_LOG_INFO("Received query for '%s'", filter._svcName.c_str());

		// do we have such a service?
		std::set<ServiceDescription> foundSvcs = findLocal(filter);
		std::set<ServiceDescription>::iterator svcDescIter = foundSvcs.begin();
		while(svcDescIter != foundSvcs.end()) {
			Message* foundMsg = svcDescIter->toMessage();
			foundMsg->setReceiver(msg->getMeta("um.rpc.mgrId"));
			foundMsg->putMeta("um.rpc.filterId", filter.getUUID());
			foundMsg->putMeta("um.rpc.type", "discovered");
			foundMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID());
			_svcPub->send(foundMsg);
			delete foundMsg;
			svcDescIter++;
		}
	}

	// is this the end of a continuous query?
	if (msg->getMeta().find("um.rpc.type") != msg->getMeta().end() &&
	        msg->getMeta("um.rpc.type").compare("stopDiscovery") == 0) {
		ServiceFilter filter(msg);
		if (_remoteQueries.find(filter.getUUID()) != _remoteQueries.end()) {
			_remoteQueries.erase(filter.getUUID());
		}
	}

	// is this a reply to a continuous service query?
	if (msg->getMeta().find("um.rpc.type") != msg->getMeta().end() &&
	        (msg->getMeta("um.rpc.type").compare("discovered") == 0 ||
	         msg->getMeta("um.rpc.type").compare("vanished") == 0)) {
		// _svcQueries comparator uses filter uuid
		ServiceFilter keyFilter("");
		keyFilter._uuid = msg->getMeta("um.rpc.filterId");
		if (_localQueries.find(keyFilter) != _localQueries.end()) {
			ResultSet<ServiceDescription>* listener = _localQueries[keyFilter];
			assert(msg->getMeta("um.rpc.desc.channel").size() > 0);
			assert(msg->getMeta("um.rpc.mgrId").size() > 0);
			std::string svcChannel = msg->getMeta("um.rpc.desc.channel");
			std::string managerId = msg->getMeta("um.rpc.mgrId");
			if (_remoteSvcDesc.find(managerId) == _remoteSvcDesc.end() || _remoteSvcDesc[managerId].find(svcChannel) == _remoteSvcDesc[managerId].end()) {
				_remoteSvcDesc[managerId][svcChannel] = ServiceDescription(msg);
				_remoteSvcDesc[managerId][svcChannel]._svcManager = this;
			}
			assert(_remoteSvcDesc.find(managerId) != _remoteSvcDesc.end());
			assert(_remoteSvcDesc[managerId].find(svcChannel) != _remoteSvcDesc[managerId].end());
			if (msg->getMeta("um.rpc.type").compare("discovered") == 0) {
				listener->added(_remoteSvcDesc[managerId][svcChannel]);
			} else {
				listener->removed(_remoteSvcDesc[managerId][svcChannel]);
				_remoteSvcDesc[managerId].erase(svcChannel);
			}
		}
	}
}
Exemple #13
0
void ServiceManager::receive(Message* msg) {
  ScopeLock lock(&_mutex);
	// is this a response for one of our requests?
	if (msg->getMeta().find("respId") != msg->getMeta().end()) {
		string respId = msg->getMeta("respId");
		if (_findRequests.find(respId) != _findRequests.end()) {
			_findResponses[respId] = new Message(*msg);
			_findRequests[respId].signal();
		}
	}

	// is someone asking for a service?
	if (msg->getMeta().find("type") != msg->getMeta().end() &&
	        msg->getMeta("type").compare("serviceDisc") == 0) {
		ServiceFilter* filter = new ServiceFilter(msg);
    std::set<ServiceDescription*> foundSvcs = findLocal(filter);
    delete filter;
    
    if (foundSvcs.size() > 0) {
      ServiceDescription* svcDesc = (*(foundSvcs.begin()));
      Message* foundMsg = svcDesc->toMessage();
      foundMsg->setMeta("respId", msg->getMeta("reqId"));
      foundMsg->setMeta("desc:channel", svcDesc->getChannelName());
      _svcPub->send(foundMsg);
      delete foundMsg;
		}
	}
  
  // is this the start of a continuous query?
  if (msg->getMeta().find("type") != msg->getMeta().end() &&
      msg->getMeta("type").compare("serviceDiscStart") == 0) {
		ServiceFilter* filter = new ServiceFilter(msg);
    _remoteQueries[filter->_uuid] = filter;

    // do we have such a service?
    std::set<ServiceDescription*> foundSvcs = findLocal(filter);
    std::set<ServiceDescription*>::iterator svcDescIter = foundSvcs.begin();
		while(svcDescIter != foundSvcs.end()) {
			if (filter->matches(*svcDescIter)) {
				Message* foundMsg = (*svcDescIter)->toMessage();
				foundMsg->setMeta("filterId", filter->_uuid);
				foundMsg->setMeta("type", "serviceDiscFound");
				foundMsg->setMeta("desc:channel", (*svcDescIter)->getChannelName());
				_svcPub->send(foundMsg);
				delete foundMsg;
			}
			svcDescIter++;
		}
  }
  
  // is this the end of a continuous query?
  if (msg->getMeta().find("type") != msg->getMeta().end() &&
      msg->getMeta("type").compare("serviceDiscStop") == 0) {
		ServiceFilter* filter = new ServiceFilter(msg);
    if (_remoteQueries.find(filter->_uuid) != _remoteQueries.end()) {
      delete _remoteQueries[filter->_uuid];
      _remoteQueries.erase(filter->_uuid);
    }
    delete filter;
  }
  
  // is this a reply to a continuous service query?
  if (msg->getMeta().find("type") != msg->getMeta().end() &&
      (msg->getMeta("type").compare("serviceDiscFound") == 0 || 
       msg->getMeta("type").compare("serviceDiscRemoved") == 0)) {
    // _svcQueries comparator uses filter uuid
    ServiceFilter* keyFilter = new ServiceFilter("");
    keyFilter->_uuid = msg->getMeta("filterId");
    if (_localQueries.find(keyFilter) != _localQueries.end()) {
      ResultSet<ServiceDescription>* listener = _localQueries[keyFilter];
      assert(msg->getMeta("desc:channel").size() > 0);
      if (_remoteSvcDesc.find(msg->getMeta("desc:channel")) == _remoteSvcDesc.end())
        _remoteSvcDesc[msg->getMeta("desc:channel")] = shared_ptr<ServiceDescription>(new ServiceDescription(msg));
      if (msg->getMeta("type").compare("serviceDiscFound") == 0) {
        listener->added(_remoteSvcDesc[msg->getMeta("desc:channel")]);
      } else {
        listener->removed(_remoteSvcDesc[msg->getMeta("desc:channel")]);
        _remoteSvcDesc.erase(msg->getMeta("desc:channel"));
      }
    }
    delete keyFilter;
  }
}
bool ServiceDescription::operator==(const ServiceDescription& cmp) const {
	return (m_id == cmp.id());
}