static void
ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
    ngx_uint_t from_upstream)
{
    size_t                     size;
    ssize_t                    n;
    ngx_buf_t                 *b;
    ngx_uint_t                 do_write;
    ngx_connection_t          *c, *downstream, *upstream, *dst, *src;
    ngx_http_upstream_t       *u;
    ngx_http_core_loc_conf_t  *clcf;
    c = r->connection;
    u = r->upstream;
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   "http upstream process upgraded, fu:%ui", from_upstream);
    downstream = c;
    upstream = u->peer.connection;
    if (downstream->write->timedout) {
        c->timedout = 1;
        ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
        return;
    }
    if (upstream->read->timedout || upstream->write->timedout) {
        ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
        ngx_http_upstream_finalize_request(r, u, 0);
        return;
    }
    if (from_upstream) {
        src = upstream;
        dst = downstream;
        b = &u->buffer;
    } else {
        src = downstream;
        dst = upstream;
        b = &u->from_client;
        if (r->header_in->last > r->header_in->pos) {
            b = r->header_in;
            b->end = b->last;
            do_write = 1;
        }
        if (b->start == NULL) {
            b->start = ngx_palloc(r->pool, u->conf->buffer_size);
            if (b->start == NULL) {
                ngx_http_upstream_finalize_request(r, u, 0);
                return;
            }
            b->pos = b->start;
            b->last = b->start;
            b->end = b->start + u->conf->buffer_size;
            b->temporary = 1;
            b->tag = u->output.tag;
        }
    }
    for ( ;; ) {
        if (do_write) {
            size = b->last - b->pos;
            if (size && dst->write->ready) {
                n = dst->send(dst, b->pos, size);
                if (n == NGX_ERROR) {
                    ngx_http_upstream_finalize_request(r, u, 0);
                    return;
                }
                if (n > 0) {
                    b->pos += n;
                    if (b->pos == b->last) {
                        b->pos = b->start;
                        b->last = b->start;
                    }
                }
            }
        }
        size = b->end - b->last;
        if (size && src->read->ready) {
            n = src->recv(src, b->last, size);
            if (n == NGX_AGAIN || n == 0) {
                break;
            }
            if (n > 0) {
                do_write = 1;
                b->last += n;
                continue;
            }
            if (n == NGX_ERROR) {
                src->read->eof = 1;
            }
        }
        break;
    }
    if ((upstream->read->eof && u->buffer.pos == u->buffer.last)
        || (downstream->read->eof && u->from_client.pos == u->from_client.last)
        || (downstream->read->eof && upstream->read->eof))
    {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
                       "http upstream upgraded done");
        ngx_http_upstream_finalize_request(r, u, 0);
        return;
    }
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
        != NGX_OK)
    {
        ngx_http_upstream_finalize_request(r, u, 0);
        return;
    }
    if (upstream->write->active && !upstream->write->ready) {
        ngx_add_timer(upstream->write, u->conf->send_timeout);
    } else if (upstream->write->timer_set) {
        ngx_del_timer(upstream->write);
    }
    if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
        ngx_http_upstream_finalize_request(r, u, 0);
        return;
    }
    if (upstream->read->active && !upstream->read->ready) {
        ngx_add_timer(upstream->read, u->conf->read_timeout);
    } else if (upstream->read->timer_set) {
        ngx_del_timer(upstream->read);
    }
    if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
        != NGX_OK)
    {
        ngx_http_upstream_finalize_request(r, u, 0);
        return;
    }
    if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) {
        ngx_http_upstream_finalize_request(r, u, 0);
        return;
    }
    if (downstream->write->active && !downstream->write->ready) {
        ngx_add_timer(downstream->write, clcf->send_timeout);
    } else if (downstream->write->timer_set) {
        ngx_del_timer(downstream->write);
    }
}
['static void\nngx_http_upstream_process_upgraded(ngx_http_request_t *r,\n    ngx_uint_t from_upstream)\n{\n    size_t                     size;\n    ssize_t                    n;\n    ngx_buf_t                 *b;\n    ngx_uint_t                 do_write;\n    ngx_connection_t          *c, *downstream, *upstream, *dst, *src;\n    ngx_http_upstream_t       *u;\n    ngx_http_core_loc_conf_t  *clcf;\n    c = r->connection;\n    u = r->upstream;\n    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,\n                   "http upstream process upgraded, fu:%ui", from_upstream);\n    downstream = c;\n    upstream = u->peer.connection;\n    if (downstream->write->timedout) {\n        c->timedout = 1;\n        ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");\n        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);\n        return;\n    }\n    if (upstream->read->timedout || upstream->write->timedout) {\n        ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");\n        ngx_http_upstream_finalize_request(r, u, 0);\n        return;\n    }\n    if (from_upstream) {\n        src = upstream;\n        dst = downstream;\n        b = &u->buffer;\n    } else {\n        src = downstream;\n        dst = upstream;\n        b = &u->from_client;\n        if (r->header_in->last > r->header_in->pos) {\n            b = r->header_in;\n            b->end = b->last;\n            do_write = 1;\n        }\n        if (b->start == NULL) {\n            b->start = ngx_palloc(r->pool, u->conf->buffer_size);\n            if (b->start == NULL) {\n                ngx_http_upstream_finalize_request(r, u, 0);\n                return;\n            }\n            b->pos = b->start;\n            b->last = b->start;\n            b->end = b->start + u->conf->buffer_size;\n            b->temporary = 1;\n            b->tag = u->output.tag;\n        }\n    }\n    for ( ;; ) {\n        if (do_write) {\n            size = b->last - b->pos;\n            if (size && dst->write->ready) {\n                n = dst->send(dst, b->pos, size);\n                if (n == NGX_ERROR) {\n                    ngx_http_upstream_finalize_request(r, u, 0);\n                    return;\n                }\n                if (n > 0) {\n                    b->pos += n;\n                    if (b->pos == b->last) {\n                        b->pos = b->start;\n                        b->last = b->start;\n                    }\n                }\n            }\n        }\n        size = b->end - b->last;\n        if (size && src->read->ready) {\n            n = src->recv(src, b->last, size);\n            if (n == NGX_AGAIN || n == 0) {\n                break;\n            }\n            if (n > 0) {\n                do_write = 1;\n                b->last += n;\n                continue;\n            }\n            if (n == NGX_ERROR) {\n                src->read->eof = 1;\n            }\n        }\n        break;\n    }\n    if ((upstream->read->eof && u->buffer.pos == u->buffer.last)\n        || (downstream->read->eof && u->from_client.pos == u->from_client.last)\n        || (downstream->read->eof && upstream->read->eof))\n    {\n        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,\n                       "http upstream upgraded done");\n        ngx_http_upstream_finalize_request(r, u, 0);\n        return;\n    }\n    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);\n    if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)\n        != NGX_OK)\n    {\n        ngx_http_upstream_finalize_request(r, u, 0);\n        return;\n    }\n    if (upstream->write->active && !upstream->write->ready) {\n        ngx_add_timer(upstream->write, u->conf->send_timeout);\n    } else if (upstream->write->timer_set) {\n        ngx_del_timer(upstream->write);\n    }\n    if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {\n        ngx_http_upstream_finalize_request(r, u, 0);\n        return;\n    }\n    if (upstream->read->active && !upstream->read->ready) {\n        ngx_add_timer(upstream->read, u->conf->read_timeout);\n    } else if (upstream->read->timer_set) {\n        ngx_del_timer(upstream->read);\n    }\n    if (ngx_handle_write_event(downstream->write, clcf->send_lowat)\n        != NGX_OK)\n    {\n        ngx_http_upstream_finalize_request(r, u, 0);\n        return;\n    }\n    if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) {\n        ngx_http_upstream_finalize_request(r, u, 0);\n        return;\n    }\n    if (downstream->write->active && !downstream->write->ready) {\n        ngx_add_timer(downstream->write, clcf->send_timeout);\n    } else if (downstream->write->timer_set) {\n        ngx_del_timer(downstream->write);\n    }\n}']