int main() { local_process(20); exit(EXIT_SUCCESS); }
void HttpProxy::handle_async( boost::system::error_code const & ec, Size const & bytes_transferred) { LOG_SECTION(); LOG_DEBUG("[handle_async] (id = %u, status = %s, ec = %s, bytes_transferred = %s)" %id_ % state_str[state_] % ec.message() % bytes_transferred.to_string()); if (watch_state_ == broken) { on_finish(); delete this; return; } if (ec) { if (state_ == receiving_request_head) { error_code ec1; response_.clear_data(); bool block = !get_non_block(ec1); if (block) set_non_block(true, ec1); boost::asio::read(*this, response_.data(), boost::asio::transfer_at_least(4096), ec1); if (block) set_non_block(false, ec1); LOG_DATA(framework::logger::Debug, ("receiving_request_head", response_.data().data())); } on_error(ec); switch (state_) { case receiving_request_head: case transferring_request_data: case sending_response_head: case transferring_response_data: on_finish(); state_ = exiting; if (watch_state_ == watching) { error_code ec1; HttpSocket::cancel(ec1); } else { delete this; } break; case local_processing: if (is_local() && !response_.head().content_length.is_initialized() && bytes_transferred.is_size_t()) { response_.head().content_length.reset(bytes_transferred.get_size_t()); } case preparing: case connectting: case sending_request_head: case receiving_response_head: state_ = sending_response_head; response_error(ec, boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; default: assert(0); break; } return; } switch (state_) { case stopped: state_ = receiving_request_head; response_.head() = HttpResponseHead(); async_read(request_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case receiving_request_head: state_ = preparing; if (watch_state_ == watch_stopped && request_.head().content_length.get_value_or(0) == 0) { watch_state_ = watching; async_read_some(boost::asio::null_buffers(), boost::bind(&HttpProxy::handle_watch, this, _1)); } on_receive_request_head( request_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case preparing: if (bytes_transferred.get_bool()) { if (!http_to_server_) http_to_server_ = new HttpSocket(get_io_service()); state_ = connectting; http_to_server_->async_connect(request_.head().host.get(), boost::bind(&HttpProxy::handle_async, this, _1, Size())); } else { state_ = transferring_request_data; transfer_request_data( boost::bind(&HttpProxy::handle_async, this, _1, _2)); } break; case connectting: state_ = sending_request_head; http_to_server_->async_write(request_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case sending_request_head: state_ = transferring_request_data; transfer_request_data( boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case transferring_request_data: if (is_local()) { on_receive_request_data(transfer_buf_); transfer_buf_.consume(transfer_buf_.size()); } state_ = local_processing; if (watch_state_ == watch_stopped) { watch_state_ = watching; async_read_some(boost::asio::null_buffers(), boost::bind(&HttpProxy::handle_watch, this, _1)); } response_.head().connection = request_.head().connection; local_process( boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case local_processing: if (is_local()) { state_ = receiving_response_head; on_receive_response_head(response_.head()); if (!response_.head().content_length.is_initialized()) { if (bytes_transferred.is_size_t()) response_.head().content_length.reset(bytes_transferred.get_size_t()); else response_.head().connection.reset(http_field::Connection()); } if (!response_.head().connection.is_initialized()) { response_.head().connection.reset(http_field::Connection()); } handle_async(ec, Size()); } else { state_ = receiving_response_head; http_to_server_->async_read(response_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); } break; case receiving_response_head: if (!is_local()) { on_receive_response_head(response_.head()); if (!response_.head().connection.is_initialized()) { response_.head().connection.reset(http_field::Connection()); } if (response_.head().err_msg.empty()) response_.head().err_msg = "OK"; } state_ = sending_response_head; async_write(response_.head(), boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case sending_response_head: state_ = transferring_response_data; transfer_response_data( boost::bind(&HttpProxy::handle_async, this, _1, _2)); break; case transferring_response_data: on_finish(); if (!response_.head().connection || response_.head().connection.get() == http_field::Connection::close) { state_ = exiting; if (watch_state_ != watching) { delete this; } else { error_code ec; shutdown(boost::asio::socket_base::shutdown_send, ec); boost::asio::ip::tcp::socket::cancel(ec); } } else { state_ = stopped; if (watch_state_ != watching) { // restart watch_state_ = watch_stopped; handle_async(ec, Size()); } else { error_code ec; boost::asio::ip::tcp::socket::cancel(ec); } } break; default: assert(0); break; } }