|
Packit |
284210 |
|
|
Packit |
284210 |
#include <apr_bucket_nginx.h>
|
|
Packit |
284210 |
|
|
Packit |
284210 |
static apr_status_t nginx_bucket_read(apr_bucket *b, const char **str,
|
|
Packit |
284210 |
apr_size_t *len, apr_read_type_e block);
|
|
Packit |
284210 |
static void nginx_bucket_destroy(void *data);
|
|
Packit |
284210 |
|
|
Packit |
284210 |
static const apr_bucket_type_t apr_bucket_type_nginx = {
|
|
Packit |
284210 |
"NGINX", 5, APR_BUCKET_DATA,
|
|
Packit |
284210 |
nginx_bucket_destroy,
|
|
Packit |
284210 |
nginx_bucket_read,
|
|
Packit |
284210 |
apr_bucket_setaside_noop,
|
|
Packit |
284210 |
apr_bucket_shared_split,
|
|
Packit |
284210 |
apr_bucket_shared_copy
|
|
Packit |
284210 |
};
|
|
Packit |
284210 |
|
|
Packit |
284210 |
|
|
Packit |
284210 |
typedef struct apr_bucket_nginx {
|
|
Packit |
284210 |
apr_bucket_refcount refcount;
|
|
Packit |
284210 |
ngx_buf_t *buf;
|
|
Packit |
284210 |
} apr_bucket_nginx;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
/* ngx_buf_t to apr_bucket */
|
|
Packit |
284210 |
apr_bucket * apr_bucket_nginx_create(ngx_buf_t *buf,
|
|
Packit |
284210 |
apr_pool_t *p,
|
|
Packit |
284210 |
apr_bucket_alloc_t *list)
|
|
Packit |
284210 |
{
|
|
Packit |
284210 |
|
|
Packit |
284210 |
apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
|
|
Packit |
284210 |
|
|
Packit |
284210 |
APR_BUCKET_INIT(b); /* link */
|
|
Packit |
284210 |
b->free = apr_bucket_free;
|
|
Packit |
284210 |
b->list = list;
|
|
Packit |
284210 |
return apr_bucket_nginx_make(b, buf, p);
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
apr_bucket * apr_bucket_nginx_make(apr_bucket *b, ngx_buf_t *buf,
|
|
Packit |
284210 |
apr_pool_t *pool)
|
|
Packit |
284210 |
{
|
|
Packit |
284210 |
apr_bucket_nginx *n;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
n = apr_bucket_alloc(sizeof(*n), b->list);
|
|
Packit |
284210 |
|
|
Packit |
284210 |
n->buf = buf;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
b = apr_bucket_shared_make(b, n, 0, ngx_buf_size(buf));
|
|
Packit |
284210 |
b->type = &apr_bucket_type_nginx;
|
|
Packit |
284210 |
return b;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
static apr_status_t nginx_bucket_read(apr_bucket *b, const char **str,
|
|
Packit |
284210 |
apr_size_t *len, apr_read_type_e block)
|
|
Packit |
284210 |
{
|
|
Packit |
284210 |
apr_bucket_nginx *n = b->data;
|
|
Packit |
284210 |
ngx_buf_t *buf = n->buf;
|
|
Packit |
284210 |
u_char *data;
|
|
Packit |
284210 |
ssize_t size;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (buf->pos == NULL && ngx_buf_size(buf) != 0) {
|
|
Packit |
284210 |
data = apr_bucket_alloc(ngx_buf_size(buf), b->list);
|
|
Packit |
284210 |
if (data == NULL) {
|
|
Packit |
284210 |
return APR_EGENERAL;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
size = ngx_read_file(buf->file, data, ngx_buf_size(buf), buf->file_pos);
|
|
Packit |
284210 |
if (size != ngx_buf_size(buf)) {
|
|
Packit |
284210 |
apr_bucket_free(data);
|
|
Packit |
284210 |
return APR_EGENERAL;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
buf->pos = data;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
*str = (char *)buf->pos + b->start;
|
|
Packit |
284210 |
*len = b->length;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
return APR_SUCCESS;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
|
|
Packit |
284210 |
static void nginx_bucket_destroy(void *data)
|
|
Packit |
284210 |
{
|
|
Packit |
284210 |
apr_bucket_nginx *n = data;
|
|
Packit |
284210 |
ngx_buf_t *buf = n->buf;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (apr_bucket_shared_destroy(n)) {
|
|
Packit |
284210 |
if (!ngx_buf_in_memory(buf) && buf->pos != NULL) {
|
|
Packit |
284210 |
apr_bucket_free(buf->pos);
|
|
Packit |
284210 |
buf->pos = NULL;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
apr_bucket_free(n);
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
ngx_buf_t * apr_bucket_to_ngx_buf(apr_bucket *e, ngx_pool_t *pool) {
|
|
Packit |
284210 |
ngx_buf_t *buf, *b;
|
|
Packit |
284210 |
apr_bucket_nginx *n;
|
|
Packit |
284210 |
ngx_uint_t len;
|
|
Packit |
284210 |
u_char *data;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (e->type->is_metadata) {
|
|
Packit |
284210 |
return NULL;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (e->type == &apr_bucket_type_nginx) {
|
|
Packit |
284210 |
n = e->data;
|
|
Packit |
284210 |
b = n->buf;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
/* whole buf */
|
|
Packit |
284210 |
if (e->length == (apr_size_t)ngx_buf_size(b)) {
|
|
Packit |
284210 |
b->last_buf = 0;
|
|
Packit |
284210 |
return b;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
buf = ngx_palloc(pool, sizeof(ngx_buf_t));
|
|
Packit |
284210 |
if (buf == NULL) {
|
|
Packit |
284210 |
return NULL;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
ngx_memcpy(buf, b, sizeof(ngx_buf_t));
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (ngx_buf_in_memory(buf)) {
|
|
Packit |
284210 |
buf->start = buf->pos = buf->pos + e->start;
|
|
Packit |
284210 |
buf->end = buf->last = buf->pos + e->length;
|
|
Packit |
284210 |
} else {
|
|
Packit |
284210 |
buf->pos = NULL;
|
|
Packit |
284210 |
buf->file_pos += e->start;
|
|
Packit |
284210 |
buf->file_last = buf->file_pos + e->length;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
buf->last_buf = 0;
|
|
Packit |
284210 |
return buf;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (apr_bucket_read(e, (const char **)&data,
|
|
Packit |
284210 |
&len, APR_BLOCK_READ) != APR_SUCCESS) {
|
|
Packit |
284210 |
return NULL;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
buf = ngx_calloc_buf(pool);
|
|
Packit |
284210 |
if (buf == NULL) {
|
|
Packit |
284210 |
return NULL;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (e->type == &apr_bucket_type_pool) {
|
|
Packit |
284210 |
buf->start = data;
|
|
Packit |
284210 |
} else if (len != 0) {
|
|
Packit |
284210 |
buf->start = ngx_palloc(pool, len);
|
|
Packit |
284210 |
ngx_memcpy(buf->start, data, len);
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
buf->pos = buf->start;
|
|
Packit |
284210 |
buf->end = buf->last = buf->start + len;
|
|
Packit |
284210 |
buf->temporary = 1;
|
|
Packit |
284210 |
return buf;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
ngx_int_t
|
|
Packit |
284210 |
move_chain_to_brigade(ngx_chain_t *chain, apr_bucket_brigade *bb, ngx_pool_t *pool, ngx_int_t last_buf) {
|
|
Packit |
284210 |
apr_bucket *e;
|
|
Packit |
284210 |
ngx_chain_t *cl;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
while (chain) {
|
|
Packit |
284210 |
e = ngx_buf_to_apr_bucket(chain->buf, bb->p, bb->bucket_alloc);
|
|
Packit |
284210 |
if (e == NULL) {
|
|
Packit |
284210 |
return NGX_ERROR;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
APR_BRIGADE_INSERT_TAIL(bb, e);
|
|
Packit |
284210 |
if (chain->buf->last_buf) {
|
|
Packit |
284210 |
e = apr_bucket_eos_create(bb->bucket_alloc);
|
|
Packit |
284210 |
APR_BRIGADE_INSERT_TAIL(bb, e);
|
|
Packit |
284210 |
chain->buf->last_buf = 0;
|
|
Packit |
284210 |
return NGX_OK;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
cl = chain;
|
|
Packit |
284210 |
chain = chain->next;
|
|
Packit |
284210 |
ngx_free_chain(pool, cl);
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (last_buf) {
|
|
Packit |
284210 |
e = apr_bucket_eos_create(bb->bucket_alloc);
|
|
Packit |
284210 |
APR_BRIGADE_INSERT_TAIL(bb, e);
|
|
Packit |
284210 |
return NGX_OK;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
return NGX_AGAIN;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
ngx_int_t
|
|
Packit |
284210 |
move_brigade_to_chain(apr_bucket_brigade *bb, ngx_chain_t **ll, ngx_pool_t *pool) {
|
|
Packit |
284210 |
apr_bucket *e;
|
|
Packit |
284210 |
ngx_buf_t *buf;
|
|
Packit |
284210 |
ngx_chain_t *cl;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
cl = NULL;
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (APR_BRIGADE_EMPTY(bb)) {
|
|
Packit |
284210 |
*ll = NULL;
|
|
Packit |
284210 |
return NGX_OK;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
for (e = APR_BRIGADE_FIRST(bb);
|
|
Packit |
284210 |
e != APR_BRIGADE_SENTINEL(bb);
|
|
Packit |
284210 |
e = APR_BUCKET_NEXT(e)) {
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (APR_BUCKET_IS_EOS(e)) {
|
|
Packit |
284210 |
if (cl == NULL) {
|
|
Packit |
284210 |
cl = ngx_alloc_chain_link(pool);
|
|
Packit |
284210 |
if (cl == NULL) {
|
|
Packit |
284210 |
break;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
cl->buf = ngx_calloc_buf(pool);
|
|
Packit |
284210 |
if (cl->buf == NULL) {
|
|
Packit |
284210 |
break;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
cl->buf->last_buf = 1;
|
|
Packit |
284210 |
*ll = cl;
|
|
Packit |
284210 |
} else {
|
|
Packit |
284210 |
cl->buf->last_buf = 1;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
apr_brigade_cleanup(bb);
|
|
Packit |
284210 |
return NGX_OK;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
if (APR_BUCKET_IS_METADATA(e)) {
|
|
Packit |
284210 |
continue;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
buf = apr_bucket_to_ngx_buf(e, pool);
|
|
Packit |
284210 |
if (buf == NULL) {
|
|
Packit |
284210 |
break;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
cl = ngx_alloc_chain_link(pool);
|
|
Packit |
284210 |
if (cl == NULL) {
|
|
Packit |
284210 |
break;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
cl->buf = buf;
|
|
Packit |
284210 |
cl->next = NULL;
|
|
Packit |
284210 |
*ll = cl;
|
|
Packit |
284210 |
ll = &cl->next;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|
|
Packit |
284210 |
apr_brigade_cleanup(bb);
|
|
Packit |
284210 |
/* no eos or error */
|
|
Packit |
284210 |
return NGX_ERROR;
|
|
Packit |
284210 |
}
|
|
Packit |
284210 |
|