Beispiel #1
0
void* PBDeserializer::deserialize(const std::string& type, Message* msg) {
	const std::string data(msg->data(), msg->size());

	if (type.length() == 0) {
		return NULL;
	}

	if (_deserializers.find(type) != _deserializers.end()) {
		// we have an explicit deserializer type registered
		MessageLite* pbObj = _deserializers[type]->New();
		if(!pbObj->ParseFromString(data)) {
			UM_LOG_ERR("Could not parse %s from serialized data", type.c_str());
		}
		return pbObj;
	} else {
		// we only now the type by its description -> receive will have to use the protobuf message API!
		const google::protobuf::Message* deserializer = PBSerializer::getProto(type);
		if (deserializer != NULL) {
			google::protobuf::Message* pbObj = deserializer->New();
			if(!pbObj->ParseFromString(data)) {
				UM_LOG_ERR("Could not parse %s from serialized data", type.c_str());
			}
			// make sure we do not try to cast it to the actual object in receive
			msg->putMeta("um.s11n.type", "google::protobuf::Message");
			return pbObj;
		} else {
			UM_LOG_ERR("received type %s, but no deserializer is known", type.c_str());
		}
	}
	return NULL;
}
void DirectoryListingClient::receive(void* object, Message* msg) {
	ServiceStub::receive(object, msg);

	if (msg->getMeta().find("operation") != msg->getMeta().end()) {
		ScopeLock lock(_mutex);
		string op = msg->getMeta("operation");
		DirectoryEntry* dirEntry = new DirectoryEntry(*(DirectoryEntry*)object);
		string key = dirEntry->path() + ":" + dirEntry->name();
		if (op.compare("added") == 0) {
			if (_knownEntries.find(key) == _knownEntries.end())
				_knownEntries[key] = shared_ptr<DirectoryEntry>(dirEntry);
			if (_listener != NULL)
				_listener->added(_knownEntries[key]);
		} else if (op.compare("modified") == 0) {
			if (_knownEntries.find(key) != _knownEntries.end()) {
				if (_listener != NULL)
					_listener->changed(_knownEntries[key]);
			} else {
				UM_LOG_ERR("Unknown directory entry reported as modified");
			}
		} else if (op.compare("removed") == 0) {
			if (_knownEntries.find(key) != _knownEntries.end()) {
				if (_listener != NULL)
					_listener->removed(_knownEntries[key]);
			} else {
				UM_LOG_ERR("Unknown directory entry reported as removed");
			}
		}
	}
}
Beispiel #3
0
void RTPPublisher::init(const Options* config) {
	RScopeLock lock(_mutex);
	int status;
	uint16_t min = 16384;		//minimum rtp port
	uint16_t max = 65534;		//maximum rtp port

	std::map<std::string, std::string> options = config->getKVPs();

	uint16_t portbase   = (options.find("pub.rtp.portbase") !=  options.end() ? strTo<uint16_t>(options["pub.rtp.portbase"]) : 0);
	_timestampIncrement = (options.find("pub.rtp.timestampIncrement") !=  options.end() ? strTo<uint32_t>(options["pub.rtp.timestampIncrement"]) : 0);
	_payloadType        = (options.find("pub.rtp.payloadType") !=  options.end() ? strTo<uint8_t>(options["pub.rtp.payloadType"]) : 96); //dynamic [RFC3551]

	if (options.find("pub.rtp.portbase") != options.end()) { // user did specify portbase
		if((portbase > 0 && portbase < 65534)) {
			min=portbase;
			max=portbase+1;
		} else {
			UM_LOG_ERR("%s: error RTPPublisher.init(): you need to specify a valid portbase (0 < portbase < 65535)", SHORT_UUID(_uuid).c_str());
		}
	}

	if (_timestampIncrement == 0) {
		UM_LOG_ERR("%s: error RTPPublisher.init(): you need to specify a valid timestampIncrement (timestampIncrement > 0)", SHORT_UUID(_uuid).c_str());
		return;
	}

	_rtpThread = RTPThread::getInstance();			// this starts the re_main() mainloop...


	struct libre::sa ip;
	libre::sa_init(&ip, AF_INET);
	libre::sa_set_in(&ip, INADDR_ANY, 0);
	//we always have to specify a rtp_recv() handler (so specify an empty function)
	status = _rtpThread->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));
	if (status) {
		UM_LOG_ERR("%s: error %d in libre::rtp_listen(): %s", SHORT_UUID(_uuid).c_str(), status, strerror(status));
		return;
	}

	_port           = libre::sa_port(libre::rtp_local(_rtp_socket));
	_timestamp      = libre::rand_u32();
	_sequenceNumber = _rtp_socket->enc.seq;

	libre::udp_sockbuf_set((libre::udp_sock*)libre::rtp_sock(_rtp_socket), 8192*1024);		//try to set something large

	_initDone = true;
}
Beispiel #4
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;
}
DirectoryEntryContent* DirectoryListingService::get(DirectoryEntry* req) {
	DirectoryEntryContent* rep = new DirectoryEntryContent();

	if (_knownEntries.find(req->name()) == _knownEntries.end()) {
		UM_LOG_ERR("Request for unkown file '%s'", req->name().c_str());
		return rep;
	}

	struct stat fileStat;
	if (stat((_dir + '/' +  req->name()).c_str(), &fileStat) != 0) {
		UM_LOG_ERR("Error with stat on '%s': %s", req->name().c_str(), strerror(errno));
		return rep;
	}
	char* buffer = readFileIntoBuffer(req->name().c_str(), fileStat.st_size);
	rep->set_content(buffer, fileStat.st_size);
	rep->set_md5(md5(buffer, fileStat.st_size));
	free(buffer);
	return rep;
}
Beispiel #6
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);
		}

	}
}
Beispiel #7
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()));
}
void DirectoryListingService::updateEntries() {
	ScopeLock lock(_mutex);

	// stat directory for modification date
	struct stat dirStat;
	if (stat(_dir.c_str(), &dirStat) != 0) {
		UM_LOG_ERR("Error with stat on directory '%s': %s", _dir.c_str(), strerror(errno));
		return;
	}

	if ((unsigned)dirStat.st_mtime >= (unsigned)_lastChecked) {
		// there are changes in the directory
		set<string> currEntries;

#ifndef WIN32
		DIR *dp;
		dp = opendir(_dir.c_str());
		if (dp == NULL) {
			UM_LOG_ERR("Error opening directory '%s': %s", _dir.c_str(), strerror(errno));
			return;
		}
		// iterate all entries and see what changed
		struct dirent* entry;
		while((entry = readdir(dp))) {
			string dname = entry->d_name;
#else
		WIN32_FIND_DATA ffd;
		HANDLE hFind = INVALID_HANDLE_VALUE;
		TCHAR szDir[MAX_PATH];
		StringCchCopy(szDir, MAX_PATH, _dir.c_str());
		StringCchCat(szDir, MAX_PATH, TEXT("\\*"));

		hFind = FindFirstFile(szDir, &ffd);
		do {
			string dname = ffd.cFileName;
#endif

			// see if the file was changed
			char* filename;
			asprintf(&filename, "%s/%s", _dir.c_str(), dname.c_str());

			struct stat fileStat;
			if (stat(filename, &fileStat) != 0) {
				UM_LOG_ERR("Error with stat on directory entry '%s': %s", filename, strerror(errno));
				free(filename);
				continue;
			}

			if (fileStat.st_mode & S_IFDIR) {
				// ignore directories
				free(filename);
				continue;
			}

			// are we interested in such a file?
			if (!filter(dname)) {
				free(filename);
				continue;
			}
			currEntries.insert(dname);

			if (_knownEntries.find(dname) != _knownEntries.end()) {
				// we have seen this entry before
				struct stat oldStat = _knownEntries[dname];
				if (oldStat.st_mtime < fileStat.st_mtime) {
					notifyModifiedFile(dname, fileStat);
				}
			} else {
				// we have not yet seen this entry
				notifyNewFile(dname, fileStat);
			}

			free(filename);
			_knownEntries[dname] = fileStat; // gets copied on insertion
#ifndef WIN32
		}
		closedir(dp);
#else
		}
		while (FindNextFile(hFind, &ffd) != 0);
		FindClose(hFind);
#endif
		// are there any known entries we have not seen this time around?
		map<string, struct stat>::iterator fileIter = _knownEntries.begin();
		while(fileIter != _knownEntries.end()) {
			if (currEntries.find(fileIter->first) == currEntries.end()) {
				// we used to know this file
				notifyRemovedFile(fileIter->first, fileIter->second);
				_knownEntries.erase(fileIter->first);
			}
			fileIter++;
		}
		// remember when we last checked the directory for modifications
#ifndef WIN32
		time(&_lastChecked);
#else
		// TODO: this will fail with subsecond updates to the directory
		_lastChecked = dirStat.st_mtime + 1;
#endif
	}