Example #1
0
System_http_session::System_http_session(Move<Unique_file> socket, boost::shared_ptr<const Http::Authentication_context> auth_ctx)
	: Http::Session(STD_MOVE(socket))
	, m_auth_ctx(STD_MOVE(auth_ctx))
	, m_initialized(false), m_decoded_uri(), m_servlet()
{
	POSEIDON_LOG_INFO("System_http_session constructor: remote = ", get_remote_info());
}
Example #2
0
void System_http_session::on_sync_request(Http::Request_headers request_headers, Stream_buffer request_entity){
	POSEIDON_PROFILE_ME;

	initialize_once(request_headers);

	const bool keep_alive = Http::is_keep_alive_enabled(request_headers);

	Http::Response_headers response_headers;
	response_headers.version = 10001;
	response_headers.status_code = Http::status_ok;
	response_headers.reason = "OK";
	response_headers.headers.set(Rcnts::view("Connection"), keep_alive ? "Keep-Alive" : "Close");
	response_headers.headers.set(Rcnts::view("Access-Control-Allow-Origin"), "*");
	response_headers.headers.set(Rcnts::view("Access-Control-Allow-Headers"), "Authorization, Content-Type");
	response_headers.headers.set(Rcnts::view("Access-Control-Allow-Methods"), "OPTIONS, GET, HEAD, POST");

	Json_object request;
	Buffer_istream bis;
	Json_object response;
	Buffer_ostream bos;

	switch(request_headers.verb){
	case Http::verb_options:
		Http::Session::send(STD_MOVE(response_headers));
		break;
	case Http::verb_get:
	case Http::verb_head:
	case Http::verb_post:
		POSEIDON_THROW_ASSERT(m_servlet);
		if(request_headers.verb != Http::verb_post){
			// no parameters
		} else {
			POSEIDON_LOG_DEBUG("Parsing POST entity as JSON Object: ", request_entity);
			bis.set_buffer(STD_MOVE(request_entity));
			request.parse(bis);
			POSEIDON_THROW_UNLESS(bis, Http::Exception, Http::status_bad_request);
		}
		POSEIDON_LOG_DEBUG("System_http_session request: ", request);
		if(request_headers.verb != Http::verb_post){
			m_servlet->handle_get(response);
		} else {
			m_servlet->handle_post(response, STD_MOVE(request));
		}
		POSEIDON_LOG_DEBUG("System_http_session response: ", response);
		response.dump(bos);
		response_headers.headers.set(Rcnts::view("Content-Type"), "application/json");
		Http::Session::send_chunked_header(STD_MOVE(response_headers));
		if(request_headers.verb == Http::verb_head){
			POSEIDON_LOG_DEBUG("The response entity for a HEAD request will be discarded.");
			break;
		}
		Http::Session::send_chunk(STD_MOVE(bos.get_buffer()));
		Http::Session::send_chunked_trailer();
		break;
	default:
		POSEIDON_THROW(Http::Exception, Http::status_method_not_allowed);
	}
}
Example #3
0
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));
	}
}
Example #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;
}
Example #5
0
void System_http_session::on_sync_expect(Http::Request_headers request_headers){
	POSEIDON_PROFILE_ME;

	initialize_once(request_headers);

	Http::Session::on_sync_expect(STD_MOVE(request_headers));
}
Example #6
0
	long ClientWriter::put_request_headers(RequestHeaders request_headers){
		PROFILE_ME;

		StreamBuffer data;

		data.put(get_string_from_verb(request_headers.verb));
		data.put(' ');
		data.put(request_headers.uri);
		if(!request_headers.get_params.empty()){
			data.put('?');
			data.put(url_encoded_from_optional_map(request_headers.get_params));
		}
		char temp[64];
		const unsigned ver_major = request_headers.version / 10000, ver_minor = request_headers.version % 10000;
		unsigned len = (unsigned)std::sprintf(temp, " HTTP/%u.%u\r\n", ver_major, ver_minor);
		data.put(temp, len);

		AUTO_REF(headers, request_headers.headers);
		for(AUTO(it, headers.begin()); it != headers.end(); ++it){
			data.put(it->first.get());
			data.put(": ");
			data.put(it->second);
			data.put("\r\n");
		}
		data.put("\r\n");

		return on_encoded_data_avail(STD_MOVE(data));
	}
Example #7
0
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"));
	}
}
Example #8
0
int file_put_contents_nothrow(const char *path, StreamBuffer contents, bool append){
	try {
		file_put_contents(path, STD_MOVE(contents), append);
		return 0;
	} catch(SystemException &e){
		return e.code();
	}
}
Example #9
0
	long ClientWriter::put_chunked_header(RequestHeaders request_headers){
		PROFILE_ME;

		StreamBuffer data;

		data.put(get_string_from_verb(request_headers.verb));
		data.put(' ');
		data.put(request_headers.uri);
		if(!request_headers.get_params.empty()){
			data.put('?');
			data.put(url_encoded_from_optional_map(request_headers.get_params));
		}
		char temp[64];
		const unsigned ver_major = request_headers.version / 10000, ver_minor = request_headers.version % 10000;
		unsigned len = (unsigned)std::sprintf(temp, " HTTP/%u.%u\r\n", ver_major, ver_minor);
		data.put(temp, len);

		AUTO_REF(headers, request_headers.headers);
		if(!headers.has("Content-Type")){
			headers.set(sslit("Content-Type"), "application/x-www-form-urlencoded; charset=utf-8");
		}

		AUTO(transfer_encoding, headers.get("Transfer-Encoding"));
		AUTO(pos, transfer_encoding.find(';'));
		if(pos != std::string::npos){
			transfer_encoding.erase(pos);
		}
		transfer_encoding = to_lower_case(trim(STD_MOVE(transfer_encoding)));

		if(transfer_encoding.empty() || (transfer_encoding == STR_IDENTITY)){
			headers.set(sslit("Transfer-Encoding"), STR_CHUNKED);
		} else {
			headers.set(sslit("Transfer-Encoding"), STD_MOVE(transfer_encoding));
		}

		for(AUTO(it, headers.begin()); it != headers.end(); ++it){
			data.put(it->first.get());
			data.put(": ");
			data.put(it->second);
			data.put("\r\n");
		}
		data.put("\r\n");

		return on_encoded_data_avail(STD_MOVE(data));
	}
Example #10
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;
}
Example #11
0
	long ClientWriter::put_chunked_trailer(OptionalMap headers){
		PROFILE_ME;

		StreamBuffer data;

		data.put("0\r\n");
		for(AUTO(it, headers.begin()); it != headers.end(); ++it){
			data.put(it->first.get());
			data.put(": ");
			data.put(it->second);
			data.put("\r\n");
		}
		data.put("\r\n");

		return on_encoded_data_avail(STD_MOVE(data));
	}
Example #12
0
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);
}
Example #13
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));
	}
Example #14
0
	bool LowLevelClient::send_chunked_trailer(OptionalMap headers){
		PROFILE_ME;

		return ClientWriter::put_chunked_trailer(STD_MOVE(headers));
	}
Example #15
0
	bool LowLevelClient::send_chunk(StreamBuffer entity){
		PROFILE_ME;

		return ClientWriter::put_chunk(STD_MOVE(entity));
	}
Example #16
0
	bool LowLevelClient::send_chunked_header(RequestHeaders request_headers){
		PROFILE_ME;

		return ClientWriter::put_chunked_header(STD_MOVE(request_headers));
	}
Example #17
0
	bool LowLevelClient::send(RequestHeaders request_headers, StreamBuffer entity){
		PROFILE_ME;

		return ClientWriter::put_request(STD_MOVE(request_headers), STD_MOVE(entity));
	}
Example #18
0
	bool LowLevelClient::send_entity(StreamBuffer data){
		PROFILE_ME;

		return ClientWriter::put_entity(STD_MOVE(data));
	}
Example #19
0
	long LowLevelClient::on_encoded_data_avail(StreamBuffer encoded){
		PROFILE_ME;

		return TcpClientBase::send(STD_MOVE(encoded));
	}
Example #20
0
void Ssl_server_factory::create_ssl_filter(boost::scoped_ptr<Ssl_filter> &ssl_filter, int fd){
	Unique_ssl ssl;
	POSEIDON_THROW_UNLESS(ssl.reset(::SSL_new(m_ssl_ctx.get())), Exception, Rcnts::view("::SSL_new() failed"));
	ssl_filter.reset(new Ssl_filter(STD_MOVE(ssl), Ssl_filter::to_accept, fd));
}
Example #21
0
	void LowLevelClient::on_response_entity(boost::uint64_t entity_offset, bool is_chunked, StreamBuffer entity){
		PROFILE_ME;

		on_low_level_response_entity(entity_offset, is_chunked, STD_MOVE(entity));
	}
Example #22
0
	ProtocolException(const char *file, std::size_t line, std::string what, int code)
		: Exception(file, line, STD_MOVE(what)), m_code(code)
	{
	}
Example #23
0
	Exception(const char *file, std::size_t line, std::string what)
		: std::runtime_error(STD_MOVE(what)), m_file(file), m_line(line)
	{
	}
Example #24
0
	long ClientWriter::put_request(RequestHeaders request_headers, StreamBuffer entity){
		PROFILE_ME;

		StreamBuffer data;

		data.put(get_string_from_verb(request_headers.verb));
		data.put(' ');
		data.put(request_headers.uri);
		if(!request_headers.get_params.empty()){
			data.put('?');
			data.put(url_encoded_from_optional_map(request_headers.get_params));
		}
		char temp[64];
		const unsigned ver_major = request_headers.version / 10000, ver_minor = request_headers.version % 10000;
		unsigned len = (unsigned)std::sprintf(temp, " HTTP/%u.%u\r\n", ver_major, ver_minor);
		data.put(temp, len);

		AUTO_REF(headers, request_headers.headers);
		if(entity.empty()){
			headers.erase("Content-Type");
			headers.erase("Transfer-Encoding");

			if((request_headers.verb == V_POST) || (request_headers.verb == V_PUT)){
				headers.set(sslit("Content-Length"), STR_0);
			} else {
				headers.erase("Content-Length");
			}
		} else {
			if(!headers.has("Content-Type")){
				headers.set(sslit("Content-Type"), "application/x-www-form-urlencoded; charset=utf-8");
			}

			AUTO(transfer_encoding, headers.get("Transfer-Encoding"));
			AUTO(pos, transfer_encoding.find(';'));
			if(pos != std::string::npos){
				transfer_encoding.erase(pos);
			}
			transfer_encoding = to_lower_case(trim(STD_MOVE(transfer_encoding)));

			if(transfer_encoding.empty() || (transfer_encoding == STR_IDENTITY)){
				headers.set(sslit("Content-Length"), boost::lexical_cast<std::string>(entity.size()));
			} else {
				// 只有一个 chunk。
				StreamBuffer chunk;
				len = (unsigned)std::sprintf(temp, "%llx\r\n", (unsigned long long)entity.size());
				chunk.put(temp, len);
				chunk.splice(entity);
				chunk.put("\r\n0\r\n\r\n");
				entity.swap(chunk);
			}
		}
		for(AUTO(it, headers.begin()); it != headers.end(); ++it){
			data.put(it->first.get());
			data.put(": ");
			data.put(it->second);
			data.put("\r\n");
		}
		data.put("\r\n");

		data.splice(entity);

		return on_encoded_data_avail(STD_MOVE(data));
	}
Example #25
0
		SystemSession(UniqueFile socket, boost::shared_ptr<const Http::AuthInfo> authInfo, std::string prefix)
			: Http::Session(STD_MOVE(socket))
			, m_authInfo(STD_MOVE(authInfo)), m_prefix(STD_MOVE(prefix))
		{
		}
Example #26
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);
}
Example #27
0
void EpollDaemon::registerServer(boost::weak_ptr<const SocketServerBase> server){
	const Mutex::UniqueLock lock(g_serverMutex);
	g_servers.push_back(STD_MOVE(server));
}
Example #28
0
	bool LowLevelClient::on_response_end(boost::uint64_t content_length, bool is_chunked, OptionalMap headers){
		PROFILE_ME;

		return on_low_level_response_end(content_length, is_chunked, STD_MOVE(headers));
	}
Example #29
0
// SslFactoryBase
SslFactoryBase::SslFactoryBase(UniqueSslCtx ssl_ctx)
	: m_ssl_ctx(STD_MOVE(ssl_ctx))
{
}
Example #30
0
	long ClientWriter::put_entity(StreamBuffer data){
		PROFILE_ME;

		return on_encoded_data_avail(STD_MOVE(data));
	}