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;
}
Exemple #2
0
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"));
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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);
}
Exemple #6
0
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"));
}
Exemple #7
0
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"));
	}
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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);
}
Exemple #13
0
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);
}
Exemple #14
0
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);
}
Exemple #15
0
	To operator()(From value)
	{
		DEBUG_THROW("generic");

		To result;
		std::stringstream sstr;

		if(!(sstr << value && sstr >> result)) {
			throw bad_lexical_cast();
		} else {
			return result;
Exemple #16
0
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));
	}
}
Exemple #18
0
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;
}
Exemple #19
0
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"));
}
Exemple #20
0
	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));
	}
Exemple #21
0
 [[noreturn]]
 IntrusivePtr<FuncT> operator()(const FuncT & /* vFunc */) const {
     DEBUG_THROW(Exception, ERROR_ACCESS_DENIED, "DummyFunctorCopier::operator()()"_rcs);
 }
Exemple #22
0
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);
}