bool SocketAddress::setIntern(Exception& ex,const string& host, UInt16 port,bool resolveHost) { IPAddress ip; Exception ignore; if (ip.set(ignore, host)) { set(ip, port); return true; } HostEntry entry; if (!resolveHost) { if (ignore) ex.set(ignore); return false; } if (!DNS::HostByName(ex, host, entry)) return false; auto& addresses = entry.addresses(); if (addresses.size() > 0) { // if we get both IPv4 and IPv6 addresses, prefer IPv4 for (const IPAddress& address : addresses) { if (address.family() == IPAddress::IPv4) { set(address, port); return true; } } set(addresses.front(), port); return true; } ex.set(Exception::NETADDRESS, "No address found for the host ", host); return false; }
void SocketAddress::init(const std::string& host, Poco::UInt16 port) { IPAddress ip; if (IPAddress::tryParse(host, ip)) { init(ip, port); #if defined(POCO_HAVE_IPv6) std::string::size_type pos = host.rfind('%'); if (std::string::npos != pos) { std::string scope(host, pos + 1); #ifdef _WIN32 ((sockaddr_in6*)addr())->sin6_scope_id = atoi(scope.c_str()); #else if (']' == scope[scope.length() - 1]) { scope.resize(scope.length() - 1); } ((sockaddr_in6*)addr())->sin6_scope_id = if_nametoindex(scope.c_str()); #endif } #endif } else { HostEntry he = DNS::hostByName(host); if (he.addresses().size() > 0) init(he.addresses()[0], port); else throw HostNotFoundException("No address found for host", host); } }
ADD_TEST(DNSTest, HostByName) { Exception ex; HostEntry hostEntry; DNS::HostByName(ex, "aliastest.appinf.com", hostEntry); CHECK(!ex) // different systems report different canonical names, unfortunately. CHECK(hostEntry.name() == "dnstest.appinf.com" || hostEntry.name() == "aliastest.appinf.com"); CHECK(hostEntry.addresses().size() >= 1); CHECK(hostEntry.addresses().front().toString() == "1.2.3.4"); DNS::HostByName(ex, "nohost.appinf.com", hostEntry); CHECK(ex); // must not to find the host }
ADD_TEST(DNSTest, HostByAddress) { Exception ex; HostEntry hostEntry; IPAddress ip; ip.set(ex, "80.122.195.86"); CHECK(!ex) DNS::HostByAddress(ex, ip, hostEntry); CHECK(!ex) CHECK(hostEntry.name() == "mailhost.appinf.com"); CHECK(hostEntry.aliases().empty()); CHECK(hostEntry.addresses().size() >= 1); CHECK(hostEntry.addresses().front().toString() == "80.122.195.86"); ip.set(ex, "10.0.244.253"); CHECK(!ex) DNS::HostByAddress(ex, ip, hostEntry); CHECK(ex) }
void SocketAddress::init(const std::string& host, Poco::UInt16 port) { IPAddress ip; if (IPAddress::tryParse(host, ip)) { init(ip, port); } else { HostEntry he = DNS::hostByName(host); HostEntry::AddressList addresses = he.addresses(); if (addresses.size() > 0) { #if defined(POCO_HAVE_IPv6) // if we get both IPv4 and IPv6 addresses, prefer IPv4 std::sort(addresses.begin(), addresses.end(), AFLT()); #endif init(addresses[0], port); } else throw HostNotFoundException("No address found for host", host); } }
bool DNS::HostByName(Exception& ex, const char* hostname, HostEntry& host) { if (!Net::InitializeNetwork(ex)) return false; struct addrinfo* pAI; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; int rc = getaddrinfo(hostname, NULL, &hints, &pAI); if (rc == 0) { host.set(ex,pAI); freeaddrinfo(pAI); return true; } SetAIError(ex,rc, " (hostname=",hostname,")"); return false; }
// BEWARE blocking method!! bool DNS::HostByAddress(Exception& ex,const IPAddress& address, HostEntry& host) { if (!Net::InitializeNetwork(ex)) return false; SocketAddress sa; sa.set(address, 0); static char fqname[1024]; int rc = getnameinfo(sa.addr(), sa.size(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD); if (rc == 0) { struct addrinfo* pAI; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; rc = getaddrinfo(fqname, NULL, &hints, &pAI); if (rc == 0) { host.set(ex, pAI); freeaddrinfo(pAI); return true; } } SetAIError(ex, rc, " (address=",address.toString(),")"); return false; }
void MulticastPoint::handle_timeout(const boost::system::error_code& error) { if (!error) { //std::cout<<"timeout"<<std::endl; canWarn = true; //Re enable send error warnings KSystem::Time::TimeAbsolute now = KSystem::Time::SystemTime::now(); { //Clean old hosts first std::map<hostid, hostDescription>::iterator t, hit = otherHosts.begin(); KSystem::Time::TimeAbsolute oldest = now - KSystem::Time::TimeAbsolute::milliseconds(cleanupandbeacon * 4); while(hit != otherHosts.end()) { if((*hit).first == Messaging::MessageEntry::HOST_ID_ANY_HOST) //Do not cleanup ANYHOST { ++hit; continue; } if((*hit).second.lastseen < oldest) { //std::cout<<"Cleaning Host:"<<(*hit).first<<std::endl; t = hit++; otherHosts.erase(t); } else hit++; } cleanupLocalSubscriptions(); } { HostSubscriptions *hs = HostSubscriptions::default_instance().New(); hs->set_hostname(boost::asio::ip::host_name()); std::map<hostid, hostDescription>::const_iterator hit = otherHosts.begin(); for(; hit != otherHosts.end(); ++hit) { std::set<size_t>::const_iterator tit = (*hit).second.providesTopics.begin(); for(; tit != (*hit).second.providesTopics.end(); ++tit) { Subscription *s = hs->add_topics(); s->set_host((*hit).first); s->set_topicid(*tit); //std::cout<<"Requesting"<<(*hit).first<<" "<<(*tit)<<std::endl; } } Messaging::MessageEntry m; m.msg.reset(hs); m.topic = Messaging::Topics::Instance().getId("communication"); m.msgclass = Messaging::MessageEntry::STATE; m.timestamp = now.wrapTo<KSystem::Time::TimeStamp>(); m.host = Messaging::MessageEntry::HOST_ID_LOCAL_HOST; //std::cout<<"Beacon"<<std::endl; processOutGoing(m); } { //Internal message, forwarded to localhost, keeps track of known hosts, and this host info. KnownHosts *kn = KnownHosts::default_instance().New(); //Who am I? kn->mutable_localhost()->set_hostid(thishost); kn->mutable_localhost()->set_hostname(boost::asio::ip::host_name()); std::map<hostid, hostDescription>::const_iterator kit = otherHosts.begin(); for(; kit != otherHosts.end(); ++kit) { if((*kit).first == Messaging::MessageEntry::HOST_ID_ANY_HOST) //Do not report ANYHOST continue; HostEntry *e = kn->add_entrylist(); e->set_hostid((*kit).first); e->set_hostname((*kit).second.hostname); } Messaging::MessageEntry m; m.msg.reset(kn); m.topic = Messaging::Topics::Instance().getId("communication"); m.msgclass = Messaging::MessageEntry::STATE; m.timestamp = now.wrapTo<KSystem::Time::TimeStamp>(); m.host = Messaging::MessageEntry::HOST_ID_LOCAL_HOST; publish(m); } dep.cleanOlderThan(KSystem::Time::TimeAbsolute::milliseconds(cleanupandbeacon * 2)); timer_.expires_from_now(boost::posix_time::milliseconds(cleanupandbeacon)); timer_.async_wait( boost::bind(&MulticastPoint::handle_timeout, this, boost::asio::placeholders::error)); } }
void MulticastPoint::handle_timeout(const boost::system::error_code& error) { if (!error) { //std::cout<<"timeout"<<std::endl; canWarn = true; //Re enable send error warnings boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); { //Clean old hosts first std::map<hostid, hostDescription>::iterator t, hit = otherHosts.begin(); boost::posix_time::ptime oldest = now - boost::posix_time::milliseconds(cleanupandbeacon * 4); while(hit != otherHosts.end()) { if((*hit).first == msgentry::HOST_ID_ANY_HOST) //Do not cleanup ANYHOST { ++hit; continue; } if((*hit).second.lastseen < oldest) { //std::cout<<"Cleaning Host:"<<(*hit).first<<std::endl; t = hit++; otherHosts.erase(t); } else hit++; } std::set<size_t> remSub; std::set<size_t>::iterator sit; //Iterate all needed topics remSub = localsubscriptions; for( hit = otherHosts.begin(); hit != otherHosts.end(); hit++) for(sit = (*hit).second.needsTopics.begin(); sit != (*hit).second.needsTopics.end(); ++sit) remSub.erase(*sit); for(sit = remSub.begin(); sit != remSub.end(); ++sit) localsubscriptions.erase(*sit); std::vector<msgentry> newsubscriptions; msgentry kh; kh.msgclass = msgentry::UNSUBSCRIBE_ON_TOPIC; kh.host = msgentry::HOST_ID_LOCAL_HOST; for(sit = remSub.begin(); sit != remSub.end(); ++sit) { kh.topic = (*sit); newsubscriptions.push_back(kh); //std::cout<<"Unsubscribe from:"<<(*sit)<<std::endl; } publish(newsubscriptions); } { HostSubscriptions *hs = HostSubscriptions::default_instance().New(); hs->set_hostname(boost::asio::ip::host_name()); std::map<hostid, hostDescription>::const_iterator hit = otherHosts.begin(); for(; hit != otherHosts.end(); ++hit) { std::set<size_t>::const_iterator tit = (*hit).second.providesTopics.begin(); for(; tit != (*hit).second.providesTopics.end(); ++tit) { Subscription *s = hs->add_topics(); s->set_host((*hit).first); s->set_topicid(*tit); //std::cout<<"Requesting"<<(*hit).first<<" "<<(*tit)<<std::endl; } } msgentry m; m.msg.reset(hs); m.topic = Topics::Instance().getId("communication"); m.msgclass = msgentry::STATE; m.timestamp = now; m.host = msgentry::HOST_ID_LOCAL_HOST; //std::cout<<"Beacon"<<std::endl; processOutGoing(m); } { //Internal message, forwarded to localhost, keeps track of known hosts, and this host info. KnownHosts *kn = KnownHosts::default_instance().New(); //Who am I? kn->mutable_localhost()->set_hostid(thishost); kn->mutable_localhost()->set_hostname(boost::asio::ip::host_name()); std::map<hostid, hostDescription>::const_iterator kit = otherHosts.begin(); for(; kit != otherHosts.end(); ++kit) { if((*kit).first == msgentry::HOST_ID_ANY_HOST) //Do not report ANYHOST continue; HostEntry *e = kn->add_entrylist(); e->set_hostid((*kit).first); e->set_hostname((*kit).second.hostname); } msgentry m; m.msg.reset(kn); m.topic = Topics::Instance().getId("communication"); m.msgclass = msgentry::STATE; m.timestamp = now; m.host = msgentry::HOST_ID_LOCAL_HOST; publish(m); } dep.cleanOlderThan(boost::posix_time::milliseconds(cleanupandbeacon * 2)); timer_.expires_from_now(boost::posix_time::milliseconds(cleanupandbeacon)); timer_.async_wait( boost::bind(&MulticastPoint::handle_timeout, this, boost::asio::placeholders::error)); } }