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