Example #1
0
int main() {
    local_process(20);
    exit(EXIT_SUCCESS);
}
Example #2
0
        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;
            }
        }