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; }
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; }
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); }
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); }
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()); }