static ngx_int_t
ngx_http_spdy_serverpush_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
   
    off_t                       size;
    ngx_buf_t                  *b;
    ngx_chain_t                *cl, *ll, *out, **ln;
    ngx_http_spdy_stream_t     *stream;
    ngx_http_spdy_out_frame_t  *frame;
   
    ngx_output_chain_ctx_t       *ctx;
    ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
    ngx_http_set_ctx(r, ctx, ngx_http_spdy_serverpush_filter_module);
    //ngx_chain_t *myChain=NULL;
    ngx_http_static_handler(r);
    stream =myStream;
    if (stream == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "spdy body filter \"%V?%V\"", &r->uri, &r->args);

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Data in server Push ");

    if (myChain == NULL || r->header_only) {

	ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Ending");
        if (stream->waiting) {
            return NGX_AGAIN;
        }

        r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED;

        return NGX_OK;
    }

    size = 0;
    ln = &out;
    ll = myChain;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "into for ");
    for ( ;; ) {
        b = ll->buf;
//#if 1
	if(b->file)
	{	
		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "file detected push : %d",(b->file_last-b->file_pos));
		ngx_int_t my_size = b->file_last-b->file_pos;
		u_char* my_buf = ngx_pcalloc(r->pool,sizeof(u_char)*my_size);
		ngx_read_file(b->file, my_buf, my_size, 0);
		b->start = my_buf;
		b->pos = my_buf;
		b->last = my_buf+my_size;//+NGX_SPDY_FRAME_HEADER_SIZE;

	}
        if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                          "zero size buf in spdy body filter "
                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
                          b->temporary,
                          b->recycled,
                          b->in_file,
                          b->start,
                          b->pos,
                          b->last,
                          b->file,
                          b->file_pos,
                          b->file_last);

            ngx_debug_point();
            return NGX_ERROR;
        }
//#endif
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "out of for");
        cl = ngx_alloc_chain_link(r->pool);
        if (cl == NULL) {
            return NGX_ERROR;
        }
	
        size += ngx_buf_size(b);
	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Size %d ",size);
        
        cl->buf = b;

        *ln = cl;
        ln = &cl->next;

        if (ll->next == NULL) {
            break;
        }

        ll = ll->next;
    }

    if (size > NGX_SPDY_MAX_FRAME_SIZE) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "FIXME: chain too big in spdy filter: %O", size);
        return NGX_ERROR;
    }
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "ONE ");
    frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
                                                b->last_buf, out, cl);

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "FOUR ");
    if (frame == NULL) {
        return NGX_ERROR;
    }

    ngx_http_spdy_queue_frame(stream->connection, frame);

    stream->waiting++;

    r->main->blocked++;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Data in server Push end sai ram ");
    ngx_http_spdy_serverpush_filter_send(r->connection, stream);
    return ngx_http_next_body_filter(r,in);
}
static ngx_int_t
ngx_http_spdy_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    off_t                       size;
    ngx_buf_t                  *b;
    ngx_chain_t                *cl, *ll, *out, **ln;
    ngx_http_spdy_stream_t     *stream;
    ngx_http_spdy_out_frame_t  *frame;

    stream = r->spdy_stream;

    if (stream == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "spdy body filter \"%V?%V\"", &r->uri, &r->args);

    if (in == NULL || r->header_only) {

        if (stream->waiting) {
            return NGX_AGAIN;
        }

        r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED;

        return NGX_OK;
    }

    size = 0;
    ln = &out;
    ll = in;

    for ( ;; ) {
        b = ll->buf;
#if 1
        if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                          "zero size buf in spdy body filter "
                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
                          b->temporary,
                          b->recycled,
                          b->in_file,
                          b->start,
                          b->pos,
                          b->last,
                          b->file,
                          b->file_pos,
                          b->file_last);

            ngx_debug_point();
            return NGX_ERROR;
        }
#endif
        cl = ngx_alloc_chain_link(r->pool);
        if (cl == NULL) {
            return NGX_ERROR;
        }

        size += ngx_buf_size(b);
        cl->buf = b;

        *ln = cl;
        ln = &cl->next;

        if (ll->next == NULL) {
            break;
        }

        ll = ll->next;
    }

    if (size > NGX_SPDY_MAX_FRAME_SIZE) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "FIXME: chain too big in spdy filter: %O", size);
        return NGX_ERROR;
    }

    frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
                                                b->last_buf, out, cl);
    if (frame == NULL) {
        return NGX_ERROR;
    }

    ngx_http_spdy_queue_frame(stream->connection, frame);

    stream->waiting++;

    r->main->blocked++;

    return ngx_http_spdy_filter_send(r->connection, stream);
}
static ngx_chain_t *
ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
{
    off_t                        size, offset;
    size_t                       rest, frame_size;
    ngx_chain_t                 *cl, *out, **ln;
    ngx_http_request_t          *r;
    ngx_http_spdy_stream_t      *stream;
    ngx_http_spdy_loc_conf_t    *slcf;
    ngx_http_spdy_out_frame_t   *frame;
    ngx_http_spdy_connection_t  *sc;
    r = fc->data;
    stream = r->spdy_stream;
#if (NGX_SUPPRESS_WARN)
    size = 0;
#endif
    while (in)
    {
        size = ngx_buf_size(in->buf);
        if (size || in->buf->last_buf)
        {
            break;
        }
        in = in->next;
    }
    if (in == NULL)
    {
        if (stream->queued)
        {
            fc->write->delayed = 1;
        }
        else
        {
            fc->buffered &= ~NGX_SPDY_BUFFERED;
        }
        return NULL;
    }
    sc = stream->connection;
    if (size && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED)
    {
        fc->write->delayed = 1;
        return in;
    }
    if (limit == 0 || limit > (off_t) sc->send_window)
    {
        limit = sc->send_window;
    }
    if (limit > stream->send_window)
    {
        limit = (stream->send_window > 0) ? stream->send_window : 0;
    }
    if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow)
    {
        cl = ngx_alloc_chain_link(r->pool);
        if (cl == NULL)
        {
            return NGX_CHAIN_ERROR;
        }
        cl->buf = in->buf;
        in->buf = cl->buf->shadow;
        offset = ngx_buf_in_memory(in->buf)
                 ? (cl->buf->pos - in->buf->pos)
                 : (cl->buf->file_pos - in->buf->file_pos);
        cl->next = stream->free_bufs;
        stream->free_bufs = cl;
    }
    else
    {
        offset = 0;
    }
#if (NGX_SUPPRESS_WARN)
    cl = NULL;
#endif
    slcf = ngx_http_get_module_loc_conf(r, ngx_http_spdy_module);
    frame_size = (limit <= (off_t) slcf->chunk_size) ? (size_t) limit
                 : slcf->chunk_size;
    for (;;)
    {
        ln = &out;
        rest = frame_size;
        while ((off_t) rest >= size)
        {
            if (offset)
            {
                cl = ngx_http_spdy_filter_get_shadow(stream, in->buf,
                                                     offset, size);
                if (cl == NULL)
                {
                    return NGX_CHAIN_ERROR;
                }
                offset = 0;
            }
            else
            {
                cl = ngx_alloc_chain_link(r->pool);
                if (cl == NULL)
                {
                    return NGX_CHAIN_ERROR;
                }
                cl->buf = in->buf;
            }
            *ln = cl;
            ln = &cl->next;
            rest -= (size_t) size;
            in = in->next;
            if (in == NULL)
            {
                frame_size -= rest;
                rest = 0;
                break;
            }
            size = ngx_buf_size(in->buf);
        }
        if (rest)
        {
            cl = ngx_http_spdy_filter_get_shadow(stream, in->buf,
                                                 offset, rest);
            if (cl == NULL)
            {
                return NGX_CHAIN_ERROR;
            }
            cl->buf->flush = 0;
            cl->buf->last_buf = 0;
            *ln = cl;
            offset += rest;
            size -= rest;
        }
        frame = ngx_http_spdy_filter_get_data_frame(stream, frame_size,
                out, cl);
        if (frame == NULL)
        {
            return NGX_CHAIN_ERROR;
        }
        ngx_http_spdy_queue_frame(sc, frame);
        sc->send_window -= frame_size;
        stream->send_window -= frame_size;
        stream->queued++;
        if (in == NULL)
        {
            break;
        }
        limit -= frame_size;
        if (limit == 0)
        {
            break;
        }
        if (limit < (off_t) slcf->chunk_size)
        {
            frame_size = (size_t) limit;
        }
    }
    if (offset)
    {
        cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, offset, size);
        if (cl == NULL)
        {
            return NGX_CHAIN_ERROR;
        }
        in->buf = cl->buf;
        ngx_free_chain(r->pool, cl);
    }
    if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR)
    {
        return NGX_CHAIN_ERROR;
    }
    if (in && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED)
    {
        fc->write->delayed = 1;
    }
    return in;
}
Пример #4
0
static ngx_int_t
ngx_http_spdy_v3_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    off_t                       total, size;
    ngx_buf_t                  *b;
    ngx_chain_t                *cl, *tl, *ll, *out, **ln;
    ngx_http_spdy_stream_t     *stream;
    ngx_http_spdy_srv_conf_t   *sscf;
    ngx_http_spdy_out_frame_t  *frame;

    total = 0;
    size = 0;
    out = NULL;
    stream = r->spdy_stream;

    if (stream == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "spdy body filter \"%V?%V\"", &r->uri, &r->args);

    if (in == NULL || r->header_only) {

        if (stream->pending && (stream->send_window_size > 0)) {
            goto output;
        }

        if (stream->waiting) {
            return NGX_AGAIN;
        }

        if (!stream->pending) {
            r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
        }

        return NGX_OK;
    }

    ln = &out;
    ll = in;

    for ( ;; ) {
        b = ll->buf;
#if 1
        if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                          "zero size buf in spdy body filter "
                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
                          b->temporary,
                          b->recycled,
                          b->in_file,
                          b->start,
                          b->pos,
                          b->last,
                          b->file,
                          b->file_pos,
                          b->file_last);

            ngx_debug_point();
            return NGX_ERROR;
        }
#endif
        cl = ngx_alloc_chain_link(r->pool);
        if (cl == NULL) {
            return NGX_ERROR;
        }

        cl->next = NULL;

        size += ngx_buf_size(b);
        cl->buf = b;

        *ln = cl;
        ln = &cl->next;

        if (ll->next == NULL) {
            break;
        }

        ll = ll->next;
    }

output:

    total = size;
    if (stream->pending) {
        for (tl = stream->pending; ;tl = tl->next) {

            total += ngx_buf_size(tl->buf);
            if (tl->next == NULL) {
                break;
            }
        }
        tl->next = out;
    } else {
        stream->pending = out;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "spdy id=%ui, send_window_size=%i, total=%O",
                   stream->id, stream->send_window_size, total);

    if (stream->send_window_size == 0) {

        ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
                      "zero send windows size");

        r->connection->buffered |= NGX_SPDY_WRITE_BUFFERED;
        return NGX_AGAIN;
    } else if (total > stream->send_window_size) {
        out = ngx_http_spdy_split_chain(stream, stream->send_window_size);
        if (out == NULL) {
            return NGX_ERROR;
        }

        r->connection->buffered |= NGX_SPDY_WRITE_BUFFERED;
        stream->send_window_size = 0;
    } else {
        out = stream->pending;
        stream->pending = NULL;
        stream->send_window_size -= total;
    }

    size = 0;
    cl = out;
    for (;;) {

        size += ngx_buf_size(cl->buf);

        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "spdy, cl=%p, cl->buf=%p, size=%uz, fin:%d",
                       cl, cl->buf, ngx_buf_size(cl->buf), cl->buf->last_buf);

        if (cl->next == NULL) {
            b = cl->buf;
            break;
        }

        cl = cl->next;
    }

    frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
                                                b->last_buf, out, cl);
    if (frame == NULL) {
        return NGX_ERROR;
    }

    ngx_http_spdy_queue_frame(stream->connection, frame);

    stream->waiting++;

    r->main->blocked++;

    sscf = ngx_http_get_module_srv_conf(stream->connection->http_connection->conf_ctx,
                                        ngx_http_spdy_module);
    if (!sscf->flow_control) {
        stream->send_window_size = NGX_SPDY_TMP_WINDOW_SIZE;
    }

    return ngx_http_spdy_filter_send(r->connection, stream);
}