mirror of
https://github.com/apache/httpd.git
synced 2025-08-07 04:02:58 +03:00
mod_ssl: bind buffered data to filter's pending data.
Otherwise they are not considered by ap_filter_input_pending() and pipelining is not detected (MPM event times out). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1844779 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
#include "ssl_private.h"
|
#include "ssl_private.h"
|
||||||
#include "mod_ssl.h"
|
#include "mod_ssl.h"
|
||||||
#include "mod_ssl_openssl.h"
|
#include "mod_ssl_openssl.h"
|
||||||
|
#include "core.h"
|
||||||
#include "apr_date.h"
|
#include "apr_date.h"
|
||||||
|
|
||||||
APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, proxy_post_handshake,
|
APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, proxy_post_handshake,
|
||||||
@@ -320,8 +321,8 @@ static int bio_filter_out_puts(BIO *bio, const char *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int length;
|
apr_bucket *b;
|
||||||
char *value;
|
apr_bucket_brigade *bb;
|
||||||
} char_buffer_t;
|
} char_buffer_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -343,39 +344,70 @@ typedef struct {
|
|||||||
* any of this data and we need to remember the length.
|
* any of this data and we need to remember the length.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void char_buffer_consume(bio_filter_in_ctx_t *inctx, int inl)
|
||||||
|
{
|
||||||
|
apr_bucket *b = inctx->cbuf.b;
|
||||||
|
|
||||||
|
b->data = (char *)b->data + inl;
|
||||||
|
b->length -= inl;
|
||||||
|
|
||||||
|
if (!b->length) {
|
||||||
|
APR_BUCKET_REMOVE(b);
|
||||||
|
APR_BUCKET_INIT(b);
|
||||||
|
}
|
||||||
|
else if (APR_BUCKET_NEXT(b) == b) {
|
||||||
|
/* rollbacks might get us here (inl < 0) */
|
||||||
|
APR_BRIGADE_INSERT_HEAD(inctx->cbuf.bb, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy up to INL bytes from the char_buffer BUFFER into IN. Note
|
/* Copy up to INL bytes from the char_buffer BUFFER into IN. Note
|
||||||
* that due to the strange way this API is designed/used, the
|
* that due to the strange way this API is designed/used, the
|
||||||
* char_buffer object is used to cache a segment of inctx->buffer, and
|
* char_buffer object is used to cache a segment of inctx->buffer, and
|
||||||
* then this function called to copy (part of) that segment to the
|
* then this function called to copy (part of) that segment to the
|
||||||
* beginning of inctx->buffer. So the segments to copy cannot be
|
* beginning of inctx->buffer. So the segments to copy cannot be
|
||||||
* presumed to be non-overlapping, and memmove must be used. */
|
* presumed to be non-overlapping, and memmove must be used. */
|
||||||
static int char_buffer_read(char_buffer_t *buffer, char *in, int inl)
|
static int char_buffer_read(bio_filter_in_ctx_t *inctx, char *in, int inl)
|
||||||
{
|
{
|
||||||
if (!buffer->length) {
|
apr_bucket *b = inctx->cbuf.b;
|
||||||
|
int avail = b ? b->length : 0;
|
||||||
|
|
||||||
|
if (!avail) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer->length > inl) {
|
if (inl > avail) {
|
||||||
/* we have enough to fill the caller's buffer */
|
inl = avail;
|
||||||
memmove(in, buffer->value, inl);
|
|
||||||
buffer->value += inl;
|
|
||||||
buffer->length -= inl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* swallow remainder of the buffer */
|
|
||||||
memmove(in, buffer->value, buffer->length);
|
|
||||||
inl = buffer->length;
|
|
||||||
buffer->value = NULL;
|
|
||||||
buffer->length = 0;
|
|
||||||
}
|
}
|
||||||
|
memmove(in, b->data, inl);
|
||||||
|
char_buffer_consume(inctx, inl);
|
||||||
|
|
||||||
return inl;
|
return inl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int char_buffer_write(char_buffer_t *buffer, char *in, int inl)
|
static int char_buffer_write(bio_filter_in_ctx_t *inctx, char *in, int inl)
|
||||||
{
|
{
|
||||||
buffer->value = in;
|
ap_filter_t *f = inctx->filter_ctx->pInputFilter;
|
||||||
buffer->length = inl;
|
char_buffer_t *buf = &inctx->cbuf;
|
||||||
|
apr_bucket *b = buf->b;
|
||||||
|
|
||||||
|
if (!b) {
|
||||||
|
buf->b = b = apr_bucket_immortal_create("", 0, f->c->bucket_alloc);
|
||||||
|
buf->bb = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AP_DEBUG_ASSERT(APR_BUCKET_NEXT(b) == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
b->data = in;
|
||||||
|
b->length = inl;
|
||||||
|
if (b->length) {
|
||||||
|
/* set this at the top of the filter's pending data */
|
||||||
|
ap_filter_reinstate_brigade(f, buf->bb, NULL);
|
||||||
|
APR_BRIGADE_INSERT_HEAD(buf->bb, b);
|
||||||
|
ap_filter_adopt_brigade(f, buf->bb);
|
||||||
|
}
|
||||||
|
|
||||||
return inl;
|
return inl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,22 +682,16 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
|
|||||||
apr_size_t *len)
|
apr_size_t *len)
|
||||||
{
|
{
|
||||||
apr_size_t wanted = *len;
|
apr_size_t wanted = *len;
|
||||||
apr_size_t bytes = 0;
|
int bytes, rc;
|
||||||
int rc;
|
|
||||||
|
|
||||||
*len = 0;
|
*len = 0;
|
||||||
|
|
||||||
/* If we have something leftover from last time, try that first. */
|
/* If we have something leftover from last time, try that first. */
|
||||||
if ((bytes = char_buffer_read(&inctx->cbuf, buf, wanted))) {
|
if ((bytes = char_buffer_read(inctx, buf, wanted))) {
|
||||||
*len = bytes;
|
*len = bytes;
|
||||||
if (inctx->mode == AP_MODE_SPECULATIVE) {
|
if (inctx->mode == AP_MODE_SPECULATIVE) {
|
||||||
/* We want to rollback this read. */
|
/* We want to rollback this read. */
|
||||||
if (inctx->cbuf.length > 0) {
|
char_buffer_consume(inctx, -bytes);
|
||||||
inctx->cbuf.value -= bytes;
|
|
||||||
inctx->cbuf.length += bytes;
|
|
||||||
} else {
|
|
||||||
char_buffer_write(&inctx->cbuf, buf, (int)bytes);
|
|
||||||
}
|
|
||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
/* This could probably be *len == wanted, but be safe from stray
|
/* This could probably be *len == wanted, but be safe from stray
|
||||||
@@ -711,7 +737,7 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
|
|||||||
*len += rc;
|
*len += rc;
|
||||||
if (inctx->mode == AP_MODE_SPECULATIVE) {
|
if (inctx->mode == AP_MODE_SPECULATIVE) {
|
||||||
/* We want to rollback this read. */
|
/* We want to rollback this read. */
|
||||||
char_buffer_write(&inctx->cbuf, buf, rc);
|
char_buffer_write(inctx, buf, rc);
|
||||||
}
|
}
|
||||||
return inctx->rc;
|
return inctx->rc;
|
||||||
}
|
}
|
||||||
@@ -839,7 +865,7 @@ static apr_status_t ssl_io_input_getline(bio_filter_in_ctx_t *inctx,
|
|||||||
if (status != APR_SUCCESS) {
|
if (status != APR_SUCCESS) {
|
||||||
if (APR_STATUS_IS_EAGAIN(status) && (*len > 0)) {
|
if (APR_STATUS_IS_EAGAIN(status) && (*len > 0)) {
|
||||||
/* Save the part of the line we already got */
|
/* Save the part of the line we already got */
|
||||||
char_buffer_write(&inctx->cbuf, buf, *len);
|
char_buffer_write(inctx, buf, *len);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -863,7 +889,7 @@ static apr_status_t ssl_io_input_getline(bio_filter_in_ctx_t *inctx,
|
|||||||
value = buf + bytes;
|
value = buf + bytes;
|
||||||
length = *len - bytes;
|
length = *len - bytes;
|
||||||
|
|
||||||
char_buffer_write(&inctx->cbuf, value, length);
|
char_buffer_write(inctx, value, length);
|
||||||
|
|
||||||
*len = bytes;
|
*len = bytes;
|
||||||
}
|
}
|
||||||
@@ -1588,17 +1614,18 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f,
|
|||||||
else if (inctx->mode == AP_MODE_GETLINE) {
|
else if (inctx->mode == AP_MODE_GETLINE) {
|
||||||
const char *pos;
|
const char *pos;
|
||||||
|
|
||||||
|
bucket = inctx->cbuf.b;
|
||||||
|
|
||||||
/* Satisfy the read directly out of the buffer if possible;
|
/* Satisfy the read directly out of the buffer if possible;
|
||||||
* invoking ssl_io_input_getline will mean the entire buffer
|
* invoking ssl_io_input_getline will mean the entire buffer
|
||||||
* is copied once (unnecessarily) for each GETLINE call. */
|
* is copied once (unnecessarily) for each GETLINE call. */
|
||||||
if (inctx->cbuf.length
|
if (bucket && bucket->length
|
||||||
&& (pos = memchr(inctx->cbuf.value, APR_ASCII_LF,
|
&& (pos = memchr(bucket->data, APR_ASCII_LF,
|
||||||
inctx->cbuf.length)) != NULL) {
|
bucket->length)) != NULL) {
|
||||||
start = inctx->cbuf.value;
|
start = bucket->data;
|
||||||
len = 1 + pos - start; /* +1 to include LF */
|
len = 1 + pos - start; /* +1 to include LF */
|
||||||
/* Buffer contents now consumed. */
|
/* Buffer contents now consumed. */
|
||||||
inctx->cbuf.value += len;
|
char_buffer_consume(inctx, len);
|
||||||
inctx->cbuf.length -= len;
|
|
||||||
status = APR_SUCCESS;
|
status = APR_SUCCESS;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -2106,7 +2133,7 @@ static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c,
|
|||||||
inctx->f = filter_ctx->pInputFilter;
|
inctx->f = filter_ctx->pInputFilter;
|
||||||
inctx->rc = APR_SUCCESS;
|
inctx->rc = APR_SUCCESS;
|
||||||
inctx->mode = AP_MODE_READBYTES;
|
inctx->mode = AP_MODE_READBYTES;
|
||||||
inctx->cbuf.length = 0;
|
memset(&inctx->cbuf, 0, sizeof(inctx->cbuf));
|
||||||
inctx->bb = apr_brigade_create(c->pool, c->bucket_alloc);
|
inctx->bb = apr_brigade_create(c->pool, c->bucket_alloc);
|
||||||
inctx->block = APR_BLOCK_READ;
|
inctx->block = APR_BLOCK_READ;
|
||||||
inctx->pool = c->pool;
|
inctx->pool = c->pool;
|
||||||
|
Reference in New Issue
Block a user