Thanks to everybody who reviewed the first patch. This new
version adds error-checking fixes and moves the brigade-splitting
back into send_parsed_content. I also added a nonblocking read
to find_end_sequence.
--Brian
Index: mod_include.h
===================================================================
RCS file: /home/cvspublic/httpd-2.0/modules/filters/mod_include.h,v
retrieving revision 1.21
diff -u -r1.21 mod_include.h
--- mod_include.h 2001/08/27 20:25:42 1.21
+++ mod_include.h 2001/08/29 04:48:12
@@ -138,6 +138,8 @@
int if_nesting_level;
apr_size_t parse_pos;
int bytes_parsed;
+ apr_status_t status;
+ int output_now;
apr_bucket *head_start_bucket;
apr_size_t head_start_index;
Index: mod_include.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/modules/filters/mod_include.c,v
retrieving revision 1.136
diff -u -r1.136 mod_include.c
--- mod_include.c 2001/08/27 20:25:42 1.136
+++ mod_include.c 2001/08/29 04:48:13
@@ -144,7 +144,7 @@
* returns NULL if no match found.
*/
static apr_bucket *find_start_sequence(apr_bucket *dptr, include_ctx_t
*ctx,
- apr_bucket_brigade *bb, int
*do_cleanup)
+ apr_bucket_brigade *bb, int
*do_cleanup)
{
apr_size_t len;
const char *c;
@@ -156,39 +156,56 @@
*do_cleanup = 0;
do {
+ apr_status_t rv;
+ int read_done = 0;
+
if (APR_BUCKET_IS_EOS(dptr)) {
break;
}
- apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
- /* XXX handle retcodes */
- if (len == 0) { /* end of pipe? */
- break;
+
+ if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+ ctx->output_now = 1;
}
- c = buf;
- while (c < buf + len) {
- if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
- apr_bucket *start_bucket;
+ else if (ctx->bytes_parsed > 0) {
+ rv = apr_bucket_read(dptr, &buf, &len, APR_NONBLOCK_READ);
+ read_done = 1;
+ if (APR_STATUS_IS_EAGAIN(rv)) {
+ ctx->output_now = 1;
+ }
+ }
- if (ctx->head_start_index > 0) {
- start_index = ctx->head_start_index;
- start_bucket = ctx->head_start_bucket;
- }
- else {
- start_index = (c - buf);
- start_bucket = dptr;
- }
+ if (ctx->output_now) {
+ apr_size_t start_index;
+ apr_bucket *start_bucket;
+ apr_bucket_brigade *remainder;
+ if (ctx->head_start_index > 0) {
+ start_bucket = ctx->head_start_bucket;
apr_bucket_split(start_bucket, start_index);
- tmp_bkt = APR_BUCKET_NEXT(start_bucket);
- if (ctx->head_start_index > 0) {
- ctx->head_start_index = 0;
- ctx->head_start_bucket = tmp_bkt;
- ctx->parse_pos = 0;
- ctx->state = PRE_HEAD;
- }
-
- return tmp_bkt;
+ start_bucket = APR_BUCKET_NEXT(start_bucket);
+ ctx->head_start_index = 0;
+ ctx->head_start_bucket = start_bucket;
+ ctx->parse_pos = 0;
+ ctx->state = PRE_HEAD;
}
+ else {
+ start_bucket = dptr;
+ }
+ return start_bucket;
+ }
+ if (!read_done) {
+ rv = apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
+ }
+ if (!APR_STATUS_IS_SUCCESS(rv)) {
+ ctx->status = rv;
+ return NULL;
+ }
+
+ if (len == 0) { /* end of pipe? */
+ break;
+ }
+ c = buf;
+ while (c < buf + len) {
if (*c == str[ctx->parse_pos]) {
if (ctx->state == PRE_HEAD) {
ctx->state = PARSE_HEAD;
@@ -256,11 +273,40 @@
const char *str = ENDING_SEQUENCE;
do {
+ apr_status_t rv;
+ int read_done = 0;
+
if (APR_BUCKET_IS_EOS(dptr)) {
break;
+ }
+ if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+ ctx->output_now = 1;
}
- apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
- /* XXX handle retcodes */
+ else if (ctx->bytes_parsed > 0) {
+ rv = apr_bucket_read(dptr, &buf, &len, APR_NONBLOCK_READ);
+ read_done = 1;
+ if (APR_STATUS_IS_EAGAIN(rv)) {
+ ctx->output_now = 1;
+ }
+ }
+
+ if (ctx->output_now) {
+ if (ctx->state == PARSE_DIRECTIVE) {
+ /* gonna start over parsing the directive next time
through */
+ ctx->directive_length = 0;
+ ctx->tag_length = 0;
+ }
+ return dptr;
+ }
+
+ if (!read_done) {
+ rv = apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
+ }
+ if (!APR_STATUS_IS_SUCCESS(rv)) {
+ ctx->status = rv;
+ return NULL;
+ }
+
if (len == 0) { /* end of pipe? */
break;
}
@@ -271,15 +317,6 @@
c = buf;
}
while (c < buf + len) {
- if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
- if (ctx->state == PARSE_DIRECTIVE) {
- /* gonna start over parsing the directive next time
through */
- ctx->directive_length = 0;
- ctx->tag_length = 0;
- }
- return dptr;
- }
-
if (*c == str[ctx->parse_pos]) {
if (ctx->state != PARSE_TAIL) {
ctx->state = PARSE_TAIL;
@@ -2364,6 +2401,9 @@
apr_size_t cleanup_bytes = ctx->parse_pos;
tmp_dptr = find_start_sequence(dptr, ctx, *bb, &do_cleanup);
+ if (!APR_STATUS_IS_SUCCESS(ctx->status)) {
+ return ctx->status;
+ }
/* The few bytes stored in the ssi_tag_brigade turned out
not to
* be a tag after all. This can only happen if the starting
@@ -2401,7 +2441,9 @@
dptr = APR_BRIGADE_SENTINEL(*bb);
}
}
- else if ((tmp_dptr != NULL) && (ctx->bytes_parsed >=
BYTE_COUNT_THRESHOLD)) {
+ else if ((tmp_dptr != NULL) &&
+ (ctx->output_now ||
+ (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD))) {
/* Send the large chunk of pre-tag
bytes... */
tag_and_after = apr_brigade_split(*bb, tmp_dptr);
rv = ap_pass_brigade(f->next, *bb);
@@ -2411,6 +2453,7 @@
*bb = tag_and_after;
dptr = tmp_dptr;
ctx->bytes_parsed = 0;
+ ctx->output_now = 0;
}
else if (tmp_dptr == NULL) { /* There was no possible SSI
tag in the */
dptr = APR_BRIGADE_SENTINEL(*bb); /* remainder of this
brigade... */
@@ -2423,6 +2466,9 @@
(ctx->state == PARSE_TAIL)) &&
(dptr != APR_BRIGADE_SENTINEL(*bb))) {
tmp_dptr = find_end_sequence(dptr, ctx, *bb);
+ if (!APR_STATUS_IS_SUCCESS(ctx->status)) {
+ return ctx->status;
+ }
if (tmp_dptr != NULL) {
dptr = tmp_dptr; /* Adjust bucket pos... */
@@ -2438,11 +2484,13 @@
APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
*bb = tag_and_after;
}
- else if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+ else if (ctx->output_now ||
+ (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD)) {
SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next, rv);
if (rv != APR_SUCCESS) {
return rv;
}
+ ctx->output_now = 0;
}
}
else {
@@ -2715,6 +2763,7 @@
ctx->flags |= FLAG_NO_EXEC;
}
ctx->ssi_tag_brigade = apr_brigade_create(f->c->pool);
+ ctx->status = APR_SUCCESS;
apr_cpystrn(ctx->error_str, conf->default_error_msg,
sizeof(ctx->error_str));
apr_cpystrn(ctx->time_str, conf->default_time_fmt,
sizeof(ctx->time_str));