Ejemplo n.º 1
0
void RTPSubscriber::init(const Options* config) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t min=16384;		//minimum rtp port
	uint16_t max=65534;		//maximum rtp port
	uint16_t portbase=strTo<uint16_t>(config->getKVPs()["sub.rtp.portbase"]);
	_multicastIP=config->getKVPs()["sub.rtp.multicast"];
	if(config->getKVPs().count("pub.rtp.multicast") && !config->getKVPs().count("pub.rtp.portbase")) {
		UM_LOG_ERR("%s: error RTPSubscriber.init(): you need to specify a valid multicast portbase (0 < portbase < 65535) when using multicast", SHORT_UUID(_uuid).c_str());
		return;
	}
	if(config->getKVPs().count("sub.rtp.portbase") && (portbase==0 || portbase==65535)) {
		UM_LOG_ERR("%s: error RTPSubscriber.init(): you need to specify a valid portbase (0 < portbase < 65535)", SHORT_UUID(_uuid).c_str());
		return;
	}

	_helper=new RTPHelpers();		//this starts the re_main() mainloop
	if(config->getKVPs().count("sub.rtp.portbase")) {
		min=portbase;
		max=portbase+1;
	}
	struct libre::sa ip;
	libre::sa_init(&ip, AF_INET);
	libre::sa_set_in(&ip, INADDR_ANY, 0);
	if((status=RTPHelpers::call(boost::bind(libre::rtp_listen, &_rtp_socket, static_cast<int>(IPPROTO_UDP), &ip, min, max, false, rtp_recv, (void (*)(const libre::sa*, libre::rtcp_msg*, void*)) NULL, this)))) {
		UM_LOG_ERR("%s: error %d in libre::rtp_listen()", SHORT_UUID(_uuid).c_str(), status);
		delete _helper;
		return;
	}
	_port=libre::sa_port(libre::rtp_local(_rtp_socket));
	libre::udp_sockbuf_set((libre::udp_sock*)libre::rtp_sock(_rtp_socket), 8192*1024);		//try to set something large

	if(config->getKVPs().count("sub.rtp.multicast")) {
		struct libre::sa maddr;
		libre::sa_init(&maddr, AF_INET);
		if((status=libre::sa_set_str(&maddr, _multicastIP.c_str(), _port)))
			UM_LOG_WARN("%s: error %d in libre::sa_set_str(%s:%u): %s", SHORT_UUID(_uuid).c_str(), status, _multicastIP.c_str(), _port, strerror(status));
		else {
			//test for multicast support
			status=libre::udp_multicast_join((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr);
			status|=libre::udp_multicast_leave((libre::udp_sock*)libre::rtp_sock(_rtp_socket), &maddr);
			if(status)
				UM_LOG_ERR("%s: system not supporting multicast, using unicast", SHORT_UUID(_uuid).c_str());
			else
				_multicast=true;
		}
	}

	_initDone=true;
}
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
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.º 4
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.º 5
0
void Message::uncompress() {
	if (!isCompressed())
		return;

	std::string errorStr = "Unsupported compression";
	size_t actualSize;
	std::string comprType;

	std::string comprIdent = _meta["um.compressed"];
	size_t colon = comprIdent.find_first_of(':');
	if (colon == std::string::npos) {
		errorStr = "No colon found in um.compressed meta field";
		goto DECOMPRESS_ERROR;
	}

	actualSize = strTo<size_t>(comprIdent.substr(0, colon));
	comprType = comprIdent.substr(colon + 1);

	_meta["um.compressRatio"] = toStr((double)_size / (double)actualSize);
//    std::cout << _size << " vs " << actualSize << std::endl;

	if (false) {}
#ifdef BUILD_WITH_COMPRESSION_MINIZ
	else if (comprType == "miniz") {
		int cmp_status;
		uint8_t *pUncmp;

		pUncmp = (mz_uint8 *)malloc((size_t)actualSize);
		cmp_status = mz_uncompress(pUncmp, (mz_ulong*)&actualSize, (const unsigned char *)_data.get(), _size);

		if (cmp_status != MZ_OK) {
			errorStr = mz_error(cmp_status);
			goto DECOMPRESS_ERROR;
		}

		_size = actualSize;
		_data = SharedPtr<char>((char*)pUncmp);
		_meta.erase("um.compressed");
		return;
	}
#endif
#ifdef BUILD_WITH_COMPRESSION_FASTLZ
	else if (comprType == "fastlz") {
		void* uncompressed = malloc((size_t)actualSize);

		// returns the size of the decompressed block.
		actualSize = fastlz_decompress(_data.get(), _size, uncompressed, actualSize);

		// If error occurs, e.g. the compressed data is corrupted or the output buffer is not large enough, then 0
		if (actualSize == 0) {
			errorStr = "fastlz_decompress returned 0";
			goto DECOMPRESS_ERROR;
		}

		_size = actualSize;
		_data = SharedPtr<char>((char*)uncompressed);
		_meta.erase("um.compressed");
		return;
	}

#endif
#ifdef BUILD_WITH_COMPRESSION_LZ4
	else if (comprType == "lz4") {
#ifdef LZ4_FRAME
		LZ4F_errorCode_t n;
		LZ4F_decompressionContext_t ctx;

		void* uncompressed = malloc((size_t)actualSize);

		n = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
		if (LZ4F_isError(n)) {
			errorStr = LZ4F_getErrorName(n);
			goto DECOMPRESS_ERROR;
		}

		n = LZ4F_decompress(ctx, uncompressed, &actualSize, _data.get(), &_size, NULL);
		if (LZ4F_isError(n)) {
			errorStr = LZ4F_getErrorName(n);
			goto DECOMPRESS_ERROR;
		}

		_size = actualSize;
		_data = SharedPtr<char>((char*)uncompressed);
		_meta.erase("um.compressed");

		LZ4F_freeDecompressionContext(ctx);
#else
		char* uncompressed = (char*)malloc((size_t)actualSize);
		int n = LZ4_decompress_fast(_data.get(), uncompressed, actualSize);
		if (n < 0) {
			errorStr = "Decompression failed";
			goto DECOMPRESS_ERROR;
		}

		_size = actualSize;
		_data = SharedPtr<char>((char*)uncompressed);
		_meta.erase("um.compressed");

#endif
		return;
	}
#endif

DECOMPRESS_ERROR:
	UM_LOG_WARN("Could not decompress message: %s", errorStr.c_str());

}