bool ConditionVariable::timed_wait(Mutex::UniqueLock &lock, unsigned long long ms){ assert(lock.m_locked); ::timespec tp; if(::clock_gettime(CLOCK_MONOTONIC, &tp) != 0){ const int err = errno; LOG_POSEIDON_ERROR("::clock_gettime() failed with error code ", err); DEBUG_THROW(SystemException, err); } tp.tv_sec += static_cast<std::time_t>(ms / 1000); tp.tv_nsec += static_cast<long>(ms % 1000 * 1000000); if(tp.tv_nsec >= 1000000000){ ++tp.tv_sec; tp.tv_nsec -= 1000000000; } const int err = ::pthread_cond_timedwait(&(m_impl->cond), reinterpret_cast< ::pthread_mutex_t *>(lock.m_owner->m_impl.get()), &tp); if(err != 0){ if(err == ETIMEDOUT){ return false; } LOG_POSEIDON_ERROR("::pthread_cond_timedwait() failed with error code ", err); DEBUG_THROW(SystemException, err); } return true; }
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")); }
DynamicLinkLibrary::RawProc DynamicLinkLibrary::RawRequireProcAddress(const char *pszName){ if(!x_hDll){ DEBUG_THROW(Exception, ERROR_INVALID_HANDLE, "No shared library opened"_rcs); } const auto pfnRet = ::GetProcAddress(reinterpret_cast<HINSTANCE>(x_hDll.Get()), pszName); if(!pfnRet){ DEBUG_THROW(SystemError, "GetProcAddress"_rcs); } return pfnRet; }
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; }
DynamicLinkLibrary::RawProc DynamicLinkLibrary::RawGetProcAddress(const char *pszName){ if(!x_hDll){ DEBUG_THROW(Exception, ERROR_INVALID_HANDLE, "No shared library opened"_rcs); } return ::GetProcAddress(reinterpret_cast<HINSTANCE>(x_hDll.Get()), pszName); }
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")); }
void file_put_contents(const char *path, StreamBuffer contents, bool append){ const UniqueFile file(::open(path, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC))); if(!file){ DEBUG_THROW(SystemException); } for(;;){ char write_buf[4096]; const std::size_t bytes_to_write = contents.get(write_buf, sizeof(write_buf)); if(bytes_to_write == 0){ break; } if(::write(file.get(), write_buf, bytes_to_write) < static_cast< ::ssize_t>(bytes_to_write)){ DEBUG_THROW(SystemException); } } }
SslFilterBase::SslFilterBase(Move<UniqueSsl> ssl, int fd) : m_ssl(STD_MOVE(ssl)), m_fd(fd) , m_established(false) { if(!::SSL_set_fd(m_ssl.get(), fd)){ DEBUG_THROW(Exception, sslit("::SSL_set_fd() failed")); } }
int SockAddr::getFamily() const { const AUTO(p, reinterpret_cast<const ::sockaddr *>(m_data)); if(m_size < sizeof(p->sa_family)){ LOG_POSEIDON_ERROR("Invalid SockAddr: size = ", m_size); DEBUG_THROW(Exception, sslit("Invalid SockAddr")); } return p->sa_family; }
std::size_t CsvParser::seek(std::size_t row){ if((row != static_cast<std::size_t>(-1)) && (row >= m_data.size())){ DEBUG_THROW(Exception, sslit("Row index is out of range")); } const AUTO(oldRow, m_row); m_row = row; return oldRow; }
SockAddr::SockAddr(const void *data, unsigned size){ if(size > sizeof(m_data)){ LOG_POSEIDON_ERROR("SockAddr size too large: ", size); DEBUG_THROW(Exception, sslit("SockAddr size too large")); } m_size = size; std::memcpy(m_data, data, size); }
SocketServerBase::SocketServerBase(UniqueFile socket) : m_socket(STD_MOVE(socket)), m_local_info(get_local_ip_port_from_fd(m_socket.get())) { const int flags = ::fcntl(m_socket.get(), F_GETFL); if(flags == -1){ const int code = errno; LOG_POSEIDON_ERROR("Could not get fcntl flags on socket."); DEBUG_THROW(SystemException, code); } if(::fcntl(m_socket.get(), F_SETFL, flags | O_NONBLOCK) != 0){ const int code = errno; LOG_POSEIDON_ERROR("Could not set fcntl flags on socket."); DEBUG_THROW(SystemException, code); } LOG_POSEIDON_INFO("Created socket server, local = ", m_local_info); }
void DynamicLinkLibrary::Open(const wchar_t *pwszPath){ UniqueHandle<X_LibraryFreer> hDll; if(!hDll.Reset(reinterpret_cast<X_LibraryFreer::Handle>(::LoadLibraryW(pwszPath)))){ DEBUG_THROW(SystemError, "LoadLibraryW"_rcs); } x_hDll = std::move(hDll); }
void file_get_contents(StreamBuffer &contents, const char *path){ const UniqueFile file(::open(path, O_RDONLY)); if(!file){ DEBUG_THROW(SystemException); } StreamBuffer temp; for(;;){ char read_buf[4096]; const ::ssize_t bytes_read = ::read(file.get(), read_buf, sizeof(read_buf)); if(bytes_read < 0){ DEBUG_THROW(SystemException); } else if(bytes_read == 0){ break; } temp.put(read_buf, static_cast<std::size_t>(bytes_read)); } contents.splice(temp); }
To operator()(From value) { DEBUG_THROW("generic"); To result; std::stringstream sstr; if(!(sstr << value && sstr >> result)) { throw bad_lexical_cast(); } else { return result;
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")); }
void TcpClientBase::realConnect(bool useSsl){ if(::connect(m_socket.get(), static_cast<const ::sockaddr *>(SockAddr::getData()), SockAddr::getSize()) != 0){ if(errno != EINPROGRESS){ DEBUG_THROW(SystemException); } } if(useSsl){ LOG_POSEIDON_INFO("Initiating SSL handshake..."); AUTO(ssl, g_clientSslFactory.createSsl()); boost::scoped_ptr<SslFilterBase> filter(new SslFilter(STD_MOVE(ssl), getFd())); initSsl(STD_MOVE(filter)); } }
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; }
SockAddr getSockAddrFromIpPort(const IpPort &addr){ ::sockaddr_in sin; if(::inet_pton(AF_INET, addr.ip.get(), &sin.sin_addr) == 1){ sin.sin_family = AF_INET; storeBe(sin.sin_port, addr.port); return SockAddr(&sin, sizeof(sin)); } ::sockaddr_in6 sin6; if(::inet_pton(AF_INET6, addr.ip.get(), &sin6.sin6_addr) == 1){ sin6.sin6_family = AF_INET6; storeBe(sin6.sin6_port, addr.port); return SockAddr(&sin6, sizeof(sin6)); } LOG_POSEIDON_ERROR("Unknown address format: ", addr.ip); DEBUG_THROW(Exception, sslit("Unknown address format")); }
long ClientWriter::put_chunk(StreamBuffer entity){ PROFILE_ME; if(entity.empty()){ LOG_POSEIDON_ERROR("You are not allowed to send an empty chunk"); DEBUG_THROW(BasicException, sslit("You are not allowed to send an empty chunk")); } StreamBuffer chunk; char temp[64]; unsigned len = (unsigned)std::sprintf(temp, "%llx\r\n", (unsigned long long)entity.size()); chunk.put(temp, len); chunk.splice(entity); chunk.put("\r\n"); return on_encoded_data_avail(STD_MOVE(chunk)); }
[[noreturn]] IntrusivePtr<FuncT> operator()(const FuncT & /* vFunc */) const { DEBUG_THROW(Exception, ERROR_ACCESS_DENIED, "DummyFunctorCopier::operator()()"_rcs); }
void CsvParser::load(const char *file){ LOG_POSEIDON_DEBUG("Loading CSV file: ", file); StreamBuffer buffer; fileGetContents(buffer, file); buffer.put('\n'); std::vector<OptionalMap> data; std::vector<std::vector<std::string> > rows; { std::vector<std::string> row; std::string token; bool first = true; bool inQuote = false; do { char ch = buffer.get(); if(ch == '\r'){ if(buffer.peek() == '\n'){ buffer.get(); } ch = '\n'; } if(first){ first = false; if(ch == '\"'){ inQuote = true; continue; } } if(ch == '\"'){ if(inQuote){ if(buffer.peek() == '\"'){ buffer.get(); token.push_back('\"'); } else { inQuote = false; } continue; } } if(!inQuote){ if((ch == ',') || (ch == '\n')){ std::string trimmed; const std::size_t begin = token.find_first_not_of(" \t\r\n"); if(begin != std::string::npos){ const std::size_t end = token.find_last_not_of(" \t\r\n") + 1; trimmed = token.substr(begin, end - begin); } row.push_back(STD_MOVE(trimmed)); token.clear(); first = true; if(ch == '\n'){ rows.push_back(STD_MOVE(row)); row.clear(); } continue; } } token.push_back(ch); } while(!buffer.empty()); } if(rows.empty() || rows.front().empty()){ LOG_POSEIDON_ERROR("The first line of a CSV file may not be empty."); DEBUG_THROW(Exception, sslit("Bad CSV header")); } const std::size_t columnCount = rows.front().size(); std::vector<SharedNts> keys(columnCount); for(std::size_t i = 0; i < columnCount; ++i){ AUTO_REF(key, rows.front().at(i)); for(std::size_t j = 0; j < i; ++j){ if(keys.at(j) == key){ LOG_POSEIDON_ERROR("Duplicate key: ", key); DEBUG_THROW(Exception, sslit("Duplicate key")); } } keys.at(i).assign(key.c_str()); } for(std::size_t i = 1; i < rows.size(); ++i){ rows.at(i - 1).swap(rows.at(i)); } rows.pop_back(); { std::size_t line = 1; std::size_t i = 0; while(i < rows.size()){ AUTO_REF(row, rows.at(i)); ++line; if((row.size() == 1) && row.front().empty()){ for(std::size_t j = i + 1; j < rows.size(); ++j){ rows.at(j - 1).swap(rows.at(j)); } rows.pop_back(); continue; } if(row.size() != columnCount){ LOG_POSEIDON_ERROR("There are ", row.size(), " column(s) on line ", line, " but there are ", columnCount, " in the header"); DEBUG_THROW(Exception, sslit("Inconsistent CSV column numbers")); } ++i; } } const std::size_t rowCount = rows.size(); data.resize(rowCount); for(std::size_t i = 0; i < rowCount; ++i){ AUTO_REF(row, rows.at(i)); AUTO_REF(map, data.at(i)); for(std::size_t j = 0; j < columnCount; ++j){ map.create(keys.at(j))->second.swap(row.at(j)); } } LOG_POSEIDON_DEBUG("Done loading CSV file: ", file); m_data.swap(data); m_row = static_cast<std::size_t>(-1); }