コード例 #1
0
ファイル: AsyncTasker.hpp プロジェクト: 5guo/AirSim
    void execute(std::function<void()> func, unsigned int iterations = 1)
    {
        if (iterations < 1)
            return;

        if (iterations == 1)
        {
            threads_.push([=](int i) {
                unused(i);
                try {
                    func();
                }
                catch (std::exception& e) {
                    error_handler_(e);
                };
            });
        }
        else {
            threads_.push([=](int i) {
                unused(i);
                try {
                    for (unsigned int itr = 0; itr < iterations; ++itr) {
                        func();
                    }
                }
                catch (std::exception& e) {
                    // if task failed we shouldn't try additional iterations.
                    error_handler_(e);
                };
            });
        }
    }
コード例 #2
0
ファイル: reader_internal.cpp プロジェクト: saltstar/smartnix
bool TraceBufferReader::ReadChunks(const void* buffer, size_t buffer_size) {
    fbl::unique_ptr<BufferHeaderReader> header;
    auto error = BufferHeaderReader::Create(buffer, buffer_size, &header);
    if (error != "") {
        error_handler_(error);
        return false;
    }

    CallChunkConsumerIfNonEmpty(header->GetDurableBuffer(buffer),
                                header->durable_data_end());

    // There's only two buffers, thus the earlier one is not the current one.
    // It's important to process them in chronological order on the off
    // chance that the earlier buffer provides a stringref or threadref
    // referenced by the later buffer.
    int later_buffer = header->GetBufferNumber(header->wrapped_count());
    int earlier_buffer = 0;
    if (header->wrapped_count() > 0)
        earlier_buffer = header->GetBufferNumber(header->wrapped_count() - 1);

    if (earlier_buffer != later_buffer) {
        CallChunkConsumerIfNonEmpty(header->GetRollingBuffer(buffer,
                                                             earlier_buffer),
                                    header->rolling_data_end(earlier_buffer));
    }

    CallChunkConsumerIfNonEmpty(header->GetRollingBuffer(buffer,
                                                         later_buffer),
                                header->rolling_data_end(later_buffer));

    return true;
}
コード例 #3
0
ファイル: Connection.cpp プロジェクト: blytkerchan/arachnida
	void Connection::onError_()
	{
		boost::recursive_mutex::scoped_lock sentinel(error_handler_lock_);
		if (error_handler_)
		{
			error_handler_();
		}
		else
		{ /* no-op */ }
	}
コード例 #4
0
ファイル: cinatra.hpp プロジェクト: chenfengyuan/cinatra
		void run()
		{
			HTTPServer s(num_threads_);
			s.set_request_handler([this](const Request& req, Response& res)
			{
				for (auto router : routers_)
				{
					if (router.handle(req, res))
					{
						LOG_DBG << "Route " << req.path();
						return true;
					}
				}

				LOG_DBG << "Request handler not found in dynamic router";
				return false;
			})
				.set_error_handler([this](int code, const std::string& msg, const Request& req, Response& res)
			{
				LOG_DBG << "Handle error:" << code << " " << msg << "with path " << req.path();
				if (error_handler_
					&& error_handler_(code,msg,req,res))
				{
					return true;
				}

				LOG_DBG << "In defaule error handler";
				std::string html;
				auto s = status_header(code);
				html = "<html><head><title>" + s.second + "</title></head>";
				html += "<body>";
				html += "<h1>" + boost::lexical_cast<std::string>(s.first) + " " + s.second + " " + "</h1>";
				if (!msg.empty())
				{
					html += "<br> <h2>Message: " + msg + "</h2>";
				}
				html += "</body></html>";

				res.set_status_code(s.first);

				res.write(html);

				return true;
			})
				.public_dir(public_dir_)
				.listen(listen_addr_, listen_port_)
				.run();
		}
コード例 #5
0
ファイル: connection.hpp プロジェクト: chenfengyuan/cinatra
		void response_5xx(const std::string& msg, const boost::asio::yield_context& yield)
		{
			Request req;
			Response res;
			error_handler_(500, msg, req, res);
			boost::system::error_code ignored_ec;
			boost::asio::async_write(socket_,
				boost::asio::buffer(res.get_header_str()),
				yield[ignored_ec]);
			boost::asio::async_write(socket_,
				res.buffer_,
				boost::asio::transfer_exactly(res.buffer_.size()),
				yield[ignored_ec]);

			shutdown();
		}
コード例 #6
0
ファイル: cinatra.hpp プロジェクト: whuthj/cinatra
		void run()
		{
			HTTPServer s(num_threads_);

			s.set_request_handler([this](Request& req, Response& res)
			{
				return Invoke<sizeof...(Aspect)>(res, &Cinatra::dispatch, this, req, res);
			})
				.set_error_handler([this](int code, const std::string& msg, Request& req, Response& res)
			{
				LOG_DBG << "Handle error:" << code << " " << msg << " with path " << req.path();
				if (error_handler_
					&& error_handler_(code,msg,req,res))
				{
					return true;
				}

				LOG_DBG << "In defaule error handler";
				std::string html;
				auto s = status_header(code);
				html = "<html><head><title>" + s.second + "</title></head>";
				html += "<body>";
				html += "<h1>" + boost::lexical_cast<std::string>(s.first) + " " + s.second + " " + "</h1>";
				if (!msg.empty())
				{
					html += "<br> <h2>Message: " + msg + "</h2>";
				}
				html += "</body></html>";

				res.set_status_code(s.first);

				res.write(html);

				return true;
			})
				.static_dir(static_dir_)
#ifdef CINATRA_ENABLE_HTTPS
				.https_config(config_)
#endif // CINATRA_ENABLE_HTTPS
				.listen(listen_addr_, listen_port_)
				.run();
		}
コード例 #7
0
ファイル: connection.hpp プロジェクト: chenfengyuan/cinatra
		void do_work(const boost::asio::yield_context& yield)
		{
			//FIXME: 拆分成多个子函数..
			for (;;)
			{
				try
				{
					std::array<char, 8192> buffer;
					RequestParser parser;

					std::size_t total_size = 0;
					for (;;)
					{
						std::size_t n = socket_.async_read_some(boost::asio::buffer(buffer), yield);
						total_size += n;
						if (total_size > 2 * 1024 * 1024)
						{
							throw std::runtime_error("Request toooooooo large");
						}
						auto ret = parser.parse(buffer.data(), buffer.data() + n);
						if (ret == RequestParser::good)
						{
							break;
						}
						if (ret == RequestParser::bad)
						{
							throw std::runtime_error("HTTP Parser error");
						}
					}

					/*
					如果是http1.0,规则是这样的:
					如果request里面的connection是keep-alive,那就说明浏览器想要长连接,服务器如果也同意长连接,
					那么返回的response的connection也应该有keep-alive通知浏览器,如果不想长链接,response里面就不应该有keep-alive;
					如果是1.1的,规则是这样的:
					如果request里面的connection是close,那就说明浏览器不希望长连接,如果没有close,就是默认保持长链接,
					本来是跟keep-alive没关系,但是如果浏览器发了keep-alive,那你返回的时候也应该返回keep-alive;
					惯例是根据有没有close判断是否长链接,但是如果没有close但是有keep-alive,你response也得加keep-alive;
					如果没有close也没有keep-alive
					那就是长链接但是不用返回keep-alive
					*/

					Request req = parser.get_request();
					Response res;
					LOG_DBG << "New request,path:" << req.path();

					auto self = shared_from_this();
					res.direct_write_func_ = 
						[&yield, self, this]
					(const char* data, std::size_t len)->bool
					{
						boost::system::error_code ec;
						boost::asio::async_write(socket_, boost::asio::buffer(data, len), yield[ec]);
						if (ec)
						{
							// TODO: log ec.message().
							std::cout << "direct_write_func error" << ec.message() << std::endl;
							return false;
						}
						return true;
					};

					// 是否已经处理了这个request.
					bool found = false;

					bool keep_alive{};
					bool close_connection{};
					if (parser.check_version(1, 0))
					{
						// HTTP/1.0
						LOG_DBG << "http/1.0";
						if (req.header().val_ncase_equal("Connetion", "Keep-Alive"))
						{
							LOG_DBG << "Keep-Alive";
							keep_alive = true;
							close_connection = false;
						}
						else
						{
							keep_alive = false;
							close_connection = true;
						}

						res.set_version(1, 0);
					}
					else if (parser.check_version(1, 1))
					{
						// HTTP/1.1
						LOG_DBG << "http/1.1";
						if (req.header().val_ncase_equal("Connetion", "close"))
						{
							keep_alive = false;
							close_connection = true;
						}
						else if (req.header().val_ncase_equal("Connetion", "Keep-Alive"))
						{
							keep_alive = true;
							close_connection = false;
						}
						else
						{
							keep_alive = false;
							close_connection = false;
						}

						if (req.header().get_count("host") == 0)
						{
							found = error_handler_(400,"", req, res);
						}

						res.set_version(1, 1);
					}
					else
					{
						LOG_DBG << "Unsupported http version";
						found = error_handler_(400, "Unsupported HTTP version.", req, res);
					}

					if (!found && request_handler_)
					{
						found = request_handler_(req, res);
					}
					if (!found && response_file(req, keep_alive, yield))
					{
						continue;
					}

					//如果都没有找到,404
					if (!found)
					{
						LOG_DBG << "404 Not found";
						error_handler_(404, "", req, res);
					}

					if (keep_alive)
					{
						res.header.add("Connetion", "Keep-Alive");
					}

					//用户没有指定Content-Type,默认设置成text/html
					if (res.header.get_count("Content-Type") == 0)
					{
						res.header.add("Content-Type", "text/html");
					}

					if (!res.is_complete_)
					{
						res.end();
					}

					if (!res.is_chunked_encoding_)
					{
						// 如果是chunked编码数据应该都发完了.
						std::string header_str = res.get_header_str();
						boost::asio::async_write(socket_, boost::asio::buffer(header_str), yield);
						boost::asio::async_write(socket_, res.buffer_, 
							boost::asio::transfer_exactly(res.buffer_.size()), yield);
					}

					if (close_connection)
					{
						shutdown();
					}
				}
				catch (boost::system::system_error& e)
				{
					//网络通信异常,关socket.
					if (e.code() == boost::asio::error::eof)
					{
						LOG_DBG << "Socket shutdown";
					}
					else
					{
						LOG_DBG << "Network exception: " << e.code().message();
					}
					boost::system::error_code ignored_ec;
					socket_.close(ignored_ec);
					return;
				}
				catch (std::exception& e)
				{
					LOG_ERR << "Error occurs,response 500: " << e.what();
					response_5xx(e.what(), yield);
				}
				catch (...)
				{
					response_5xx("", yield);
				}
			}
		}