Ejemplo n.º 1
0
/**
 * Start a query for a service.
 *
 * Remember service filter and send query to all connected ServiceManagers.
 */
void ServiceManager::startQuery(const ServiceFilter& filter, ResultSet<ServiceDescription>* listener) {
	RScopeLock lock(_mutex);
	_localQueries[filter] = listener;
	Message* queryMsg = filter.toMessage();
	queryMsg->putMeta("um.rpc.type", "startDiscovery");
	queryMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID());

	_svcPub->send(queryMsg);
	UM_LOG_INFO("Sending new query to %d ServiceManagers", _svcPub->waitForSubscribers(0));
	delete queryMsg;
}
Ejemplo n.º 2
0
ServiceDescription ServiceManager::find(const ServiceFilter& svcFilter, int timeout) {
	if(_svcPub->waitForSubscribers(1, timeout) < 1) {
		// there is no other ServiceManager yet
		UM_LOG_INFO("Failed to find another ServiceManager");
		return ServiceDescription();
	}

	Message* findMsg = svcFilter.toMessage();
	std::string reqId = UUID::getUUID();
	findMsg->putMeta("um.rpc.type", "discover");
	findMsg->putMeta("um.rpc.reqId", reqId.c_str());
	findMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID());
//	Thread::sleepMs(1000);
	if(_findRequests.find(reqId) != _findRequests.end())
		UM_LOG_WARN("Find request %s already received", reqId.c_str());
	_findRequests[reqId] = new Monitor();

	_svcPub->send(findMsg);
	delete findMsg;

	RScopeLock lock(_mutex);
	_findRequests[reqId]->wait(_mutex, timeout);
	delete _findRequests[reqId];
	_findRequests.erase(reqId);

	if (_findResponses.find(reqId) == _findResponses.end()) {
		UM_LOG_INFO("Failed to find %s", svcFilter.getServiceName().c_str());
		return ServiceDescription();
	}

	// TODO: Remove other replies as they come in!

	Message* foundMsg = _findResponses[reqId];
	assert(foundMsg != NULL);
	ServiceDescription svcDesc(foundMsg);
	svcDesc._svcManager = this;
	_findResponses.erase(reqId);
	delete foundMsg;
	return svcDesc;

}
Ejemplo n.º 3
0
/**
 * Find local service matching filter.
 */
std::set<ServiceDescription> ServiceManager::findLocal(const ServiceFilter& svcFilter) {
	std::set<ServiceDescription> foundSvcs;
	std::map<intptr_t, ServiceDescription>::iterator svcDescIter = _localSvcDesc.begin();
	while(svcDescIter != _localSvcDesc.end()) {
		if (svcFilter.matches(svcDescIter->second)) {
			foundSvcs.insert(svcDescIter->second);
			UM_LOG_INFO("we have a match for %s", svcFilter.getServiceName().c_str());
		}
		svcDescIter++;
	}
	return foundSvcs;
}
Ejemplo n.º 4
0
void RTPSubscriber::removed(const PublisherStub& pub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t port=pub.getPort();
	std::string ip=node.getIP();

	// TODO: This fails for publishers added via different nodes
	if (_pubs.find(pub.getUUID()) != _pubs.end())
		_pubs.erase(pub.getUUID());

	if (_domainPubs.count(pub.getDomain()) == 0)
		return;

	std::multimap<std::string, std::string>::iterator domIter = _domainPubs.find(pub.getDomain());

	while(domIter != _domainPubs.end()) {
		if (domIter->second == pub.getUUID()) {
			_domainPubs.erase(domIter++);
		} else {
			domIter++;
		}
	}

	if (_domainPubs.count(pub.getDomain()) == 0) {
		UM_LOG_INFO("%s unsubscribing from %s (%s:%d)", SHORT_UUID(_uuid).c_str(), pub.getChannelName().c_str(), ip.c_str(), port);

		if(_multicast && _pubs.size()==0) {
			UM_LOG_INFO("%s: last publisher vanished and we are using multicast, leaving multicast group %s:%d now", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);

			struct libre::sa maddr;
			libre::sa_init(&maddr, AF_INET);
			if((status=libre::sa_set_str(&maddr, _multicastIP.c_str(), _port)))
				UM_LOG_ERR("%s: error %d in libre::sa_set_str(%s:%u): %s, not leaving multicast group", SHORT_UUID(_uuid).c_str(), status, _multicastIP.c_str(), _port, strerror(status));
			else if(libre::udp_multicast_join((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr))
				UM_LOG_ERR("%s: system not supporting multicast, not leaving multicast group (%s:%d)", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);
		}

	}
}
Ejemplo n.º 5
0
void RTPSubscriber::added(const PublisherStub& pub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t port=pub.getPort();
	std::string ip=node.getIP();

	if(_domainPubs.count(pub.getDomain()) == 0) {
		UM_LOG_INFO("%s: subscribing to %s (%s:%d)", SHORT_UUID(_uuid).c_str(), pub.getChannelName().c_str(), ip.c_str(), port);

		if(_multicast && _pubs.size()==0) {
			UM_LOG_INFO("%s: first publisher found and we are using multicast, joining multicast group %s:%d now", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);

			struct libre::sa maddr;
			libre::sa_init(&maddr, AF_INET);
			if((status=libre::sa_set_str(&maddr, _multicastIP.c_str(), _port)))
				UM_LOG_ERR("%s: error %d in libre::sa_set_str(%s:%u): %s, ignoring publisher", SHORT_UUID(_uuid).c_str(), status, _multicastIP.c_str(), _port, strerror(status));
			else if(libre::udp_multicast_join((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr))
				UM_LOG_ERR("%s: system not supporting multicast, ignoring publisher (%s:%d)", SHORT_UUID(_uuid).c_str(), _multicastIP.c_str(), _port);
		}
	}
	_pubs[pub.getUUID()] = pub;
	_domainPubs.insert(std::make_pair(pub.getDomain(), pub.getUUID()));
}
Ejemplo n.º 6
0
void RTPPublisher::send(Message* msg) {
	RScopeLock lock(_mutex);
	int status = 0;
	uint32_t timestamp = 0;
	uint8_t payloadType = _payloadType;
	uint16_t sequenceNumber = strTo<uint16_t>(msg->getMeta("um.sequenceNumber"));		//only for internal use by umundo-bridge
	bool marker = strTo<bool>(msg->getMeta("um.marker"));
	if (!msg->getMeta("um.sequenceNumber").size())
		sequenceNumber = _sequenceNumber++;

	if (!msg->getMeta("um.marker").size())
		marker = false;

	std::string timestampIncrement = msg->getMeta("um.timestampIncrement");

	if (!timestampIncrement.size())
		timestampIncrement = _mandatoryMeta["um.timestampIncrement"];

	if (msg->getMeta("um.timestamp").size())	{					//mainly for internal use by umundo-bridge
		timestamp = strTo<uint32_t>(msg->getMeta("um.timestamp"));
	} else {
		if (timestampIncrement.size()) {
			timestamp = (_timestamp += strTo<uint32_t>(timestampIncrement));
		}	else {
			timestamp = (_timestamp += _timestampIncrement);
		}
	}
	if (msg->getMeta("um.payloadType").size())							//mainly for internal use by umundo-bridge
		payloadType = strTo<uint8_t>(msg->getMeta("um.payloadType"));

	//allocate buffer
	libre::mbuf *mb = libre::mbuf_alloc(libre::RTP_HEADER_SIZE + msg->size());
	//make room for rtp header
	libre::mbuf_set_end(mb, libre::RTP_HEADER_SIZE);
	libre::mbuf_skip_to_end(mb);
	//write data
	libre::mbuf_write_mem(mb, (const uint8_t*)msg->data(), msg->size());
	//send data
	typedef std::map<std::string, struct libre::sa>::iterator it_type;
	for(it_type iterator = _destinations.begin(); iterator !=  _destinations.end(); iterator++) {
		//reset buffer pos to start of data
		libre::mbuf_set_pos(mb, libre::RTP_HEADER_SIZE);
		if (sequenceNumber)
			_rtp_socket->enc.seq = sequenceNumber;
		if ((status = libre::rtp_send(_rtp_socket, &iterator->second, marker, payloadType, timestamp, mb)))
			UM_LOG_INFO("%s: error in libre::rtp_send() for destination '%s': %s", SHORT_UUID(_uuid).c_str(), iterator->first.c_str(), strerror(status));
	}
	//cleanup
	libre::mem_deref(mb);
}
Ejemplo n.º 7
0
void RTPPublisher::removed(const SubscriberStub& sub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;
	std::string ip = sub.getIP();
	uint16_t port = sub.getPort();
	if (!ip.length())		//only use separate subscriber ip (for multicast support etc.), if specified
		ip = node.getIP();

	// do we now about this sub via this node?
	bool subscriptionFound = false;
	std::pair<_domainSubs_t::iterator, _domainSubs_t::iterator> subIter = _domainSubs.equal_range(sub.getUUID());
	while(subIter.first !=  subIter.second) {
		if (subIter.first->second.first.getUUID() ==  node.getUUID()) {
			subscriptionFound = true;
			break;
		}
		subIter.first++;
	}
	if (!subscriptionFound)
		return;

	UM_LOG_INFO("%s: lost a %s subscriber (%s:%u) for channel %s", SHORT_UUID(_uuid).c_str(), sub.isMulticast() ? "multicast" : "unicast", ip.c_str(), port, _channelName.c_str());

	struct libre::sa addr;
	libre::sa_init(&addr, AF_INET);
	if ((status = libre::sa_set_str(&addr, ip.c_str(), port)))
		UM_LOG_WARN("%s: error %d in libre::sa_set_str(%s:%u): %s", SHORT_UUID(_uuid).c_str(), status, ip.c_str(), port, strerror(status));
	else
		_destinations.erase(ip+":"+toStr(port));

	if (_domainSubs.count(sub.getUUID()) ==  1) { // about to vanish
		if (_greeter !=  NULL) {
			Publisher pub(Publisher(StaticPtrCast<PublisherImpl>(shared_from_this())));
			_greeter->farewell(pub, sub);
		}
		_subs.erase(sub.getUUID());
	}

	_domainSubs.erase(subIter.first);
	UMUNDO_SIGNAL(_pubLock);
}
Ejemplo n.º 8
0
void RTPPublisher::added(const SubscriberStub& sub, const NodeStub& node) {
	RScopeLock lock(_mutex);
	int status;

	std::string ip = sub.getIP();
	uint16_t port = sub.getPort();
	if (!ip.length())		//only use separate subscriber ip (for multicast support etc.), if specified
		ip = node.getIP();

	// do we already now about this sub via this node?
	std::pair<_domainSubs_t::iterator, _domainSubs_t::iterator> subIter = _domainSubs.equal_range(sub.getUUID());
	while(subIter.first !=  subIter.second) {
		if (subIter.first->second.first.getUUID() ==  node.getUUID())
			return; // we already know about this sub from this node
		subIter.first++;
	}

	UM_LOG_INFO("%s: received a new %s subscriber (%s:%u) for channel %s", SHORT_UUID(_uuid).c_str(), sub.isMulticast() ? "multicast" : "unicast", ip.c_str(), port, _channelName.c_str());

	struct libre::sa addr;
	libre::sa_init(&addr, AF_INET);
	status = libre::sa_set_str(&addr, ip.c_str(), port);

	if (status) {
		UM_LOG_WARN("%s: error %d in libre::sa_set_str(%s:%u): %s", SHORT_UUID(_uuid).c_str(), status, ip.c_str(), port, strerror(status));
	} else {
		_destinations[ip + ":" + toStr(port)] = addr;
	}

	_subs[sub.getUUID()] = sub;
	_domainSubs.insert(std::make_pair(sub.getUUID(), std::make_pair(node, sub)));

	if (_greeter !=  NULL && _domainSubs.count(sub.getUUID()) ==  1) {
		// only perform greeting for first occurence of subscriber
		Publisher pub(StaticPtrCast<PublisherImpl>(shared_from_this()));
		_greeter->welcome(pub, sub);
	}

	UMUNDO_SIGNAL(_pubLock);
}
Ejemplo n.º 9
0
/**
 * Another ServiceManager was added.
 *
 * Send all local continuous queries.
 */
void ServiceManager::welcome(Publisher& pub, const SubscriberStub& subStub) {
	RScopeLock lock(_mutex);
	UM_LOG_INFO("found remote ServiceManager - sending %d queries", _localQueries.size());
	std::map<ServiceFilter, ResultSet<ServiceDescription>*>::iterator queryIter = _localQueries.begin();
	while (queryIter != _localQueries.end()) {
		Message* queryMsg = queryIter->first.toMessage();
		queryMsg->putMeta("um.rpc.type", "startDiscovery");
		queryMsg->putMeta("um.sub", subStub.getUUID());
		queryMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID());
		_svcPub->send(queryMsg);
		delete queryMsg;
		queryIter++;
	}
	if (_pendingMessages.find(subStub.getUUID()) != _pendingMessages.end()) {
		std::list<std::pair<uint64_t, Message*> >::iterator msgIter = _pendingMessages[subStub.getUUID()].begin();
		while(msgIter != _pendingMessages[subStub.getUUID()].end()) {
			_svcPub->send(msgIter->second);
			delete msgIter->second;
		}
		_pendingMessages.erase(subStub.getUUID());
	}
}
Ejemplo n.º 10
0
/**
 * A ServiceManager was removed.
 */
void ServiceManager::farewell(Publisher& pub, const SubscriberStub& subStub) {
	RScopeLock lock(_mutex);
	UM_LOG_INFO("removed remote ServiceManager - notifying", _localQueries.size());

	// did this publisher responded to our queries before?
	if (_remoteSvcDesc.find(subStub.getUUID()) != _remoteSvcDesc.end()) {

		// check all local queries if the remote services matched and notify about removal
		std::map<ServiceFilter, ResultSet<ServiceDescription>*>::iterator queryIter = _localQueries.begin();
		while(queryIter != _localQueries.end()) {

			std::map<std::string, ServiceDescription>::iterator remoteSvcIter = _remoteSvcDesc[subStub.getUUID()].begin();
			while(remoteSvcIter != _remoteSvcDesc[subStub.getUUID()].end()) {
				if (queryIter->first.matches(remoteSvcIter->second)) {
					queryIter->second->removed(remoteSvcIter->second);
				}
				remoteSvcIter++;
			}
			queryIter++;
		}
	}
	_remoteSvcDesc.erase(subStub.getUUID());
}
Ejemplo n.º 11
0
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);
			}
		}
	}
}