IpPort getIpPortFromSockAddr(const SockAddr &sa){ const int family = sa.getFamily(); if(family == AF_INET){ if(sa.getSize() < sizeof(::sockaddr_in)){ LOG_POSEIDON_WARNING("Invalid IPv4 SockAddr: size = ", sa.getSize()); DEBUG_THROW(Exception, sslit("Invalid IPv4 SockAddr")); } char ip[INET_ADDRSTRLEN]; const char *const str = ::inet_ntop(AF_INET, &static_cast<const ::sockaddr_in *>(sa.getData())->sin_addr, ip, sizeof(ip)); if(!str){ DEBUG_THROW(SystemException); } return IpPort(SharedNts(str), loadBe(static_cast<const ::sockaddr_in *>(sa.getData())->sin_port)); } else if(family == AF_INET6){ if(sa.getSize() < sizeof(::sockaddr_in6)){ LOG_POSEIDON_WARNING("Invalid IPv6 SockAddr: size = ", sa.getSize()); DEBUG_THROW(Exception, sslit("Invalid IPv6 SockAddr")); } char ip[INET6_ADDRSTRLEN]; const char *const str = ::inet_ntop(AF_INET6, &static_cast<const ::sockaddr_in6 *>(sa.getData())->sin6_addr, ip, sizeof(ip)); if(!str){ DEBUG_THROW(SystemException); } return IpPort(SharedNts(str), loadBe(static_cast<const ::sockaddr_in6 *>(sa.getData())->sin6_port)); } LOG_POSEIDON_WARNING("Unknown IP protocol ", family); DEBUG_THROW(Exception, sslit("Unknown IP protocol")); }
boost::shared_ptr<const JobPromise> DnsDaemon::enqueue_for_looking_up(boost::shared_ptr<SockAddr> sock_addr, std::string host, unsigned port){ PROFILE_ME; AUTO(promise, boost::make_shared<JobPromise>()); const AUTO(param, new DnsCallbackParam(STD_MOVE(sock_addr), host, port, promise)); atomic_add(g_pending_callback_count, 1, ATOMIC_RELAXED); // noexcept try { ::sigevent sev; sev.sigev_notify = SIGEV_THREAD; sev.sigev_value.sival_ptr = param; sev.sigev_notify_function = &dns_callback; sev.sigev_notify_attributes = NULLPTR; AUTO(pcb, &(param->cb)); const int gai_code = ::getaddrinfo_a(GAI_NOWAIT, &pcb, 1, &sev); // noexcept if(gai_code != 0){ LOG_POSEIDON_WARNING("DNS failure: gai_code = ", gai_code, ", err_msg = ", ::gai_strerror(gai_code)); DEBUG_THROW(Exception, sslit("DNS failure")); } } catch(...){ atomic_sub(g_pending_callback_count, 1, ATOMIC_RELAXED); // noexcept delete param; throw; } return promise; }
bool SockAddr::isPrivate() const { const int family = getFamily(); if(family == AF_INET){ const AUTO_REF(ip, reinterpret_cast<const unsigned char (&)[4]>( static_cast<const ::sockaddr_in *>(getData())->sin_addr)); if(ip[0] == 0){ // 0.0.0.0/8: 当前网络地址 return true; } else if(ip[0] == 10){ // 10.0.0.0/8: A 类私有地址 return true; } else if(ip[0] == 127){ // 127.0.0.0/8: 回环地址 return true; } else if((ip[0] == 172) && ((ip[1] & 0xF0) == 16)){ // 172.16.0.0/12: B 类私有地址 return true; } else if((ip[0] == 169) && (ip[1] == 254)){ // 169.254.0.0/16: 链路本地地址 return true; } else if((ip[0] == 192) && (ip[1] == 168)){ // 192.168.0.0/16: C 类私有地址 return true; } else if(ip[0] >= 224){ // D 类、E 类地址和广播地址 return true; } return false; } else if(family == AF_INET6){ static const unsigned char ZEROES[16] = { }; const AUTO_REF(ip, reinterpret_cast<const unsigned char (&)[16]>( static_cast<const ::sockaddr_in6 *>(getData())->sin6_addr)); if(std::memcmp(ip, ZEROES, 15) == 0){ if(ip[15] == 0){ // ::/128: 未指定的地址 return true; } if(ip[15] == 1){ // ::1/128: 回环地址 return true; } } else if((std::memcmp(ip, ZEROES, 10) == 0) && (ip[10] == 0xFF) && (ip[11] == 0xFF)){ // IPv4 翻译地址 if(ip[12] == 0){ // 0.0.0.0/8: 当前网络地址 return true; } else if(ip[12] == 10){ // 10.0.0.0/8: A 类私有地址 return true; } else if(ip[12] == 127){ // 127.0.0.0/8: 回环地址 return true; } else if((ip[12] == 172) && ((ip[13] & 0xF0) == 16)){ // 172.16.0.0/12: B 类私有地址 return true; } else if((ip[12] == 169) && (ip[13] == 254)){ // 169.254.0.0/16: 链路本地地址 return true; } else if((ip[12] == 192) && (ip[13] == 168)){ // 192.168.0.0/16: C 类私有地址 return true; } else if(ip[12] >= 224){ // D 类、E 类地址和广播地址 return true; } } else if((ip[0] == 0x01) && (std::memcmp(ip + 1, ZEROES, 7) == 0)){ // 100::/64 黑洞地址 return true; } else if(ip[0] >= 0xFC){ // 私有地址、链路本地地址和广播地址 return true; } return false; } LOG_POSEIDON_WARNING("Unknown IP protocol ", family); DEBUG_THROW(Exception, sslit("Unknown IP protocol")); }
const std::string &CsvParser::getRaw(const char *key) const { const AUTO_REF(map, m_data.at(m_row)); const AUTO(it, map.find(key)); if(it == map.end()){ LOG_POSEIDON_WARNING("Column not found: ", key); return EMPTY_STRING; } return it->second; }
bool SockAddr::isIpv6() const { const int family = getFamily(); if(family == AF_INET){ return false; } else if(family == AF_INET6){ return true; } LOG_POSEIDON_WARNING("Unknown IP protocol ", family); DEBUG_THROW(Exception, sslit("Unknown IP protocol")); }
bool isValidUtf8String(const std::string &str){ PROFILE_ME; boost::uint32_t codePoint; for(AUTO(it, str.begin()); it != str.end(); ++it){ codePoint = static_cast<unsigned char>(*it); if((codePoint & 0x80) == 0){ continue; } const AUTO(bytes, (unsigned)__builtin_clz((~codePoint | 1) & 0xFF) - (sizeof(unsigned) - 1) * CHAR_BIT); if(bytes - 2 > 2){ // 2, 3, 4 LOG_POSEIDON_WARNING("Invalid UTF-8 leading byte: bytes = ", bytes); return false; } codePoint &= (0xFFu >> bytes); for(unsigned i = 1; i < bytes; ++i){ ++it; if(it == str.end()){ LOG_POSEIDON_WARNING("String is truncated."); return false; } const unsigned trailing = static_cast<unsigned char>(*it); if((trailing & 0xC0u) != 0x80u){ LOG_POSEIDON_WARNING("Invalid UTF-8 trailing byte: trailing = 0x", std::hex, std::setw(2), std::setfill('0'), trailing); return false; } } if(codePoint > 0x10FFFFu){ LOG_POSEIDON_WARNING("Invalid UTF-8 code point: codePoint = 0x", std::hex, std::setw(6), std::setfill('0'), codePoint); return false; } if(codePoint - 0xD800u < 0x800u){ LOG_POSEIDON_WARNING("UTF-8 code point is reserved for UTF-16: codePoint = 0x", std::hex, std::setw(4), std::setfill('0'), codePoint); return false; } } return true; }
bool TcpServerBase::poll() const { UniqueFile client(::accept(get_fd(), NULLPTR, NULLPTR)); if(!client){ if(errno != EAGAIN){ DEBUG_THROW(SystemException); } return false; } AUTO(session, on_client_connect(STD_MOVE(client))); if(!session){ LOG_POSEIDON_WARNING("on_client_connect() returns a null pointer."); DEBUG_THROW(Exception, sslit("Null client pointer")); } if(m_ssl_factory){ AUTO(ssl, m_ssl_factory->create_ssl()); boost::scoped_ptr<SslFilterBase> filter(new SslFilter(STD_MOVE(ssl), session->get_fd())); session->init_ssl(STD_MOVE(filter)); } session->set_timeout(EpollDaemon::get_tcp_request_timeout()); EpollDaemon::add_session(session); LOG_POSEIDON_INFO("Accepted TCP connection from ", session->get_remote_info()); return true; }