← Commit list

b41c28e70a

Stefan Eissing
Stefan Eissing
2026-07-21
SUCCESS Duration: 176s

Subject

lib: client writer tweaks

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/cw-out.c+8 -37
@@ -97,7 +97,6 @@ static void cw_out_buf_free(struct cw_out_buf *cwbuf)
struct cw_out_ctx {
struct Curl_cwriter super;
struct cw_out_buf *buf;
- BIT(paused);
BIT(errored);
};
@@ -171,8 +170,7 @@ static void cw_get_writefunc(struct Curl_easy *data, cw_out_type otype,
}
}
-static CURLcode cw_out_cb_write(struct cw_out_ctx *ctx,
- struct Curl_easy *data,
+static CURLcode cw_out_cb_write(struct Curl_easy *data,
curl_write_callback wcb,
void *wcb_data,
cw_out_type otype,
@@ -200,7 +198,7 @@ static CURLcode cw_out_cb_write(struct cw_out_ctx *ctx,
failf(data, "Write callback asked for PAUSE when not supported");
return CURLE_WRITE_ERROR;
}
- ctx->paused = TRUE;
+ data->req.writer.paused = TRUE;
CURL_TRC_WRITE(data, "[OUT] PAUSE requested by client");
result = Curl_xfer_pause_recv(data, TRUE);
return result ? result : CURLE_AGAIN;
@@ -245,18 +243,18 @@ static CURLcode cw_out_ptr_flush(struct cw_out_ctx *ctx,
*pconsumed = 0;
if(otype == CW_OUT_BODY_0LEN) {
DEBUGASSERT(!blen);
- return cw_out_cb_write(ctx, data, wcb, wcb_data, otype,
+ return cw_out_cb_write(data, wcb, wcb_data, otype,
buf, blen, &nwritten);
}
else {
- while(blen && !ctx->paused) {
+ while(blen && !data->req.writer.paused) {
if(!flush_all && blen < min_write)
break;
wlen = max_write ? CURLMIN(blen, max_write) : blen;
if(otype == CW_OUT_BODY)
result = Curl_pgrs_deliver_check(data, wlen);
if(!result)
- result = cw_out_cb_write(ctx, data, wcb, wcb_data, otype,
+ result = cw_out_cb_write(data, wcb, wcb_data, otype,
buf, wlen, &nwritten);
if(result)
return result;
@@ -314,7 +312,7 @@ static CURLcode cw_out_flush_chain(struct cw_out_ctx *ctx,
if(!cwbuf)
return CURLE_OK;
- if(ctx->paused)
+ if(data->req.writer.paused)
return CURLE_OK;
/* write the end of the chain until it blocks or gets empty */
@@ -327,7 +325,7 @@ static CURLcode cw_out_flush_chain(struct cw_out_ctx *ctx,
return result;
if(*plast) {
/* could not write last, paused again? */
- DEBUGASSERT(ctx->paused);
+ DEBUGASSERT(data->req.writer.paused);
return CURLE_OK;
}
}
@@ -457,7 +455,7 @@ static CURLcode cw_out_do_flush(struct Curl_easy *data,
if(ctx->errored)
return CURLE_WRITE_ERROR;
- if(ctx->paused)
+ if(data->req.writer.paused)
return CURLE_OK; /* not doing it */
result = cw_out_flush_chain(ctx, data, &ctx->buf, flush_all);
@@ -486,33 +484,6 @@ const struct Curl_cwtype Curl_cwt_out = {
sizeof(struct cw_out_ctx)
};
-bool Curl_cw_out_is_paused(struct Curl_easy *data)
-{
- struct Curl_cwriter *cw_out;
- struct cw_out_ctx *ctx;
-
- cw_out = Curl_cwriter_get_by_type(data, &Curl_cwt_out);
- if(!cw_out)
- return FALSE;
-
- ctx = (struct cw_out_ctx *)cw_out;
- return (bool)ctx->paused;
-}
-
-CURLcode Curl_cw_out_unpause(struct Curl_easy *data)
-{
- struct Curl_cwriter *cw_out;
- CURLcode result = CURLE_OK;
-
- cw_out = Curl_cwriter_get_by_type(data, &Curl_cwt_out);
- if(cw_out) {
- struct cw_out_ctx *ctx = (struct cw_out_ctx *)cw_out;
- CURL_TRC_WRITE(data, "[OUT] unpause");
- ctx->paused = FALSE;
- }
- return result;
-}
-
CURLcode Curl_cw_out_done(struct Curl_easy *data)
{
struct Curl_cwriter *cw_out;
lib/cw-out.h+0 -10
@@ -34,16 +34,6 @@ struct Curl_easy;
*/
extern const struct Curl_cwtype Curl_cwt_out;
-/**
- * Return TRUE iff 'cw-out' client write has paused data.
- */
-bool Curl_cw_out_is_paused(struct Curl_easy *data);
-
-/**
- * Flush any buffered date to the client, chunk collation still applies.
- */
-CURLcode Curl_cw_out_unpause(struct Curl_easy *data);
-
/**
* Mark EndOfStream reached and flush ALL data to the client.
*/
lib/cw-pause.c+2 -4
@@ -100,7 +100,6 @@ static CURLcode cw_pause_flush(struct Curl_easy *data,
struct Curl_cwriter *cw_pause)
{
struct cw_pause_ctx *ctx = (struct cw_pause_ctx *)cw_pause;
- bool decoding = Curl_cwriter_is_content_decoding(data);
CURLcode result = CURLE_OK;
/* write the end of the chain until it blocks or gets empty */
@@ -112,7 +111,7 @@ static CURLcode cw_pause_flush(struct Curl_easy *data,
while((*plast)->next) /* got to last in list */
plast = &(*plast)->next;
if(Curl_bufq_peek(&(*plast)->b, &buf, &blen)) {
- wlen = (decoding && ((*plast)->type & CLIENTWRITE_BODY)) ?
+ wlen = ((*plast)->type & CLIENTWRITE_BODY) ?
CURLMIN(blen, CW_PAUSE_DEC_WRITE_CHUNK) : blen;
result = Curl_cwriter_write(data, cw_pause->next, (*plast)->type,
(const char *)buf, wlen);
@@ -151,7 +150,6 @@ static CURLcode cw_pause_write(struct Curl_easy *data,
struct cw_pause_ctx *ctx = writer->ctx;
CURLcode result = CURLE_OK;
size_t wlen = 0;
- bool decoding = Curl_cwriter_is_content_decoding(data);
if(ctx->buf && !Curl_cwriter_is_paused(data)) {
result = cw_pause_flush(data, writer);
@@ -164,7 +162,7 @@ static CURLcode cw_pause_write(struct Curl_easy *data,
DEBUGASSERT(!ctx->buf);
/* content decoding might blow up size considerably, write smaller
* chunks to make pausing need buffer less. */
- wlen = (decoding && (type & CLIENTWRITE_BODY)) ?
+ wlen = (type & CLIENTWRITE_BODY) ?
CURLMIN(blen, CW_PAUSE_DEC_WRITE_CHUNK) : blen;
if(wlen < blen)
wtype &= ~CLIENTWRITE_EOS;
lib/request.h+8 -2
@@ -101,10 +101,16 @@ struct SingleRequest {
/* Client Writer stack, handles transfer- and content-encodings, protocol
* checks, pausing by client callbacks. */
- struct Curl_cwriter *writer_stack;
+ struct {
+ struct Curl_cwriter *stack;
+ BIT(paused);
+ } writer;
/* Client Reader stack, handles transfer- and content-encodings, protocol
* checks, pausing by client callbacks. */
- struct Curl_creader *reader_stack;
+ struct {
+ struct Curl_creader *stack;
+ BIT(paused);
+ } reader;
struct bufq sendbuf; /* data which needs to be send to the server */
size_t sendbuf_hds_len; /* amount of header bytes in sendbuf */
time_t timeofdoc;
lib/sendf.c+75 -100
@@ -46,24 +46,24 @@
static void cl_reset_writer(struct Curl_easy *data)
{
- struct Curl_cwriter *writer = data->req.writer_stack;
+ struct Curl_cwriter *writer = data->req.writer.stack;
while(writer) {
- data->req.writer_stack = writer->next;
+ data->req.writer.stack = writer->next;
writer->cwt->do_close(data, writer);
curlx_free(writer);
- writer = data->req.writer_stack;
+ writer = data->req.writer.stack;
}
}
static void cl_reset_reader(struct Curl_easy *data)
{
- struct Curl_creader *reader = data->req.reader_stack;
+ struct Curl_creader *reader = data->req.reader.stack;
data->req.reader_started = FALSE;
while(reader) {
- data->req.reader_stack = reader->next;
+ data->req.reader.stack = reader->next;
reader->crt->do_close(data, reader);
curlx_free(reader);
- reader = data->req.reader_stack;
+ reader = data->req.reader.stack;
}
}
@@ -95,7 +95,7 @@ void Curl_client_reset(struct Curl_easy *data)
CURLcode Curl_client_start(struct Curl_easy *data)
{
if(data->req.rewind_read) {
- struct Curl_creader *r = data->req.reader_stack;
+ struct Curl_creader *r = data->req.reader.stack;
CURLcode result = CURLE_OK;
CURL_TRC_READ(data, "client start, rewind readers");
@@ -124,25 +124,6 @@ void Curl_creader_set_rewind(struct Curl_easy *data, bool enable)
data->req.rewind_read = !!enable;
}
-/* Write data using an unencoding writer stack. */
-CURLcode Curl_cwriter_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes)
-{
- if(!writer)
- return CURLE_WRITE_ERROR;
- return writer->cwt->do_write(data, writer, type, buf, nbytes);
-}
-
-CURLcode Curl_cwriter_flush(struct Curl_easy *data,
- struct Curl_cwriter *writer)
-{
- if(!writer) {
- return CURLE_WRITE_ERROR;
- }
- return writer->cwt->do_flush(data, writer);
-}
-
CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
@@ -340,47 +321,39 @@ static const struct Curl_cwtype cw_raw = {
sizeof(struct Curl_cwriter)
};
+static void cwriter_add(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
+{
+ struct Curl_cwriter **anchor = &data->req.writer.stack;
+
+ /* Insert the writer as first in its phase.
+ * Skip existing writers of lower phases. */
+ while(*anchor && (*anchor)->phase < writer->phase)
+ anchor = &((*anchor)->next);
+ writer->next = *anchor;
+ *anchor = writer;
+}
+
static CURLcode do_init_writer_stack(struct Curl_easy *data)
{
struct Curl_cwriter *writer;
CURLcode result;
- DEBUGASSERT(!data->req.writer_stack);
- result = Curl_cwriter_create(&data->req.writer_stack,
+ DEBUGASSERT(!data->req.writer.stack);
+ result = Curl_cwriter_create(&data->req.writer.stack,
data, &Curl_cwt_out, CURL_CW_CLIENT);
if(result)
return result;
- /* This places the "pause" writer behind the "download" writer that
- * is added below. Meaning the "download" can do checks on content length
- * and other things *before* write outs are buffered for paused transfers. */
- result = Curl_cwriter_create(&writer, data, &Curl_cwt_pause,
- CURL_CW_PROTOCOL);
- if(!result) {
- result = Curl_cwriter_add(data, writer);
- if(result)
- Curl_cwriter_free(data, writer);
- }
- if(result)
- return result;
-
result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL);
- if(!result) {
- result = Curl_cwriter_add(data, writer);
- if(result)
- Curl_cwriter_free(data, writer);
- }
if(result)
return result;
+ cwriter_add(data, writer);
result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW);
- if(!result) {
- result = Curl_cwriter_add(data, writer);
- if(result)
- Curl_cwriter_free(data, writer);
- }
if(result)
return result;
+ cwriter_add(data, writer);
return result;
}
@@ -405,14 +378,14 @@ CURLcode Curl_client_write(struct Curl_easy *data, int type, const char *buf,
DEBUGASSERT(!(type & CLIENTWRITE_INFO) ||
((type & ~(CLIENTWRITE_INFO | CLIENTWRITE_EOS)) == 0));
- if(!data->req.writer_stack) {
+ if(!data->req.writer.stack) {
result = do_init_writer_stack(data);
if(result)
return result;
- DEBUGASSERT(data->req.writer_stack);
+ DEBUGASSERT(data->req.writer.stack);
}
- result = Curl_cwriter_write(data, data->req.writer_stack, type, buf, len);
+ result = Curl_cwriter_write(data, data->req.writer.stack, type, buf, len);
CURL_TRC_WRITE(data, "client_write(type=%x, len=%zu) -> %d",
(unsigned int)type, len, (int)result);
return result;
@@ -422,14 +395,14 @@ CURLcode Curl_client_flush(struct Curl_easy *data)
{
CURLcode result;
- if(!data->req.writer_stack) {
+ if(!data->req.writer.stack) {
result = do_init_writer_stack(data);
if(result)
return result;
- DEBUGASSERT(data->req.writer_stack);
+ DEBUGASSERT(data->req.writer.stack);
}
- result = Curl_cwriter_flush(data, data->req.writer_stack);
+ result = Curl_cwriter_flush(data, data->req.writer.stack);
CURL_TRC_WRITE(data, "client_flush() -> %d", (int)result);
return result;
}
@@ -476,18 +449,33 @@ size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase)
struct Curl_cwriter *w;
size_t n = 0;
- for(w = data->req.writer_stack; w; w = w->next) {
+ for(w = data->req.writer.stack; w; w = w->next) {
if(w->phase == phase)
++n;
}
return n;
}
+static CURLcode cwriter_ensure_pause_writer(struct Curl_easy *data)
+{
+ struct Curl_cwriter *writer =
+ Curl_cwriter_get_by_type(data, &Curl_cwt_pause);
+ CURLcode result = CURLE_OK;
+
+ if(!writer) {
+ result = Curl_cwriter_create(&writer, data, &Curl_cwt_pause,
+ CURL_CW_BEFORE_DECODE);
+ if(!result)
+ cwriter_add(data, writer);
+ }
+ return result;
+}
+
CURLcode Curl_cwriter_add(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
CURLcode result;
- struct Curl_cwriter **anchor = &data->req.writer_stack;
+ struct Curl_cwriter **anchor = &data->req.writer.stack;
if(!*anchor) {
result = do_init_writer_stack(data);
@@ -495,12 +483,16 @@ CURLcode Curl_cwriter_add(struct Curl_easy *data,
return result;
}
- /* Insert the writer as first in its phase.
- * Skip existing writers of lower phases. */
- while(*anchor && (*anchor)->phase < writer->phase)
- anchor = &((*anchor)->next);
- writer->next = *anchor;
- *anchor = writer;
+ if(writer->phase == CURL_CW_CONTENT_DECODE) {
+ /* On adding a content decoder, add the pause writer. Do this
+ * BEFORE the given writer as any failure will make the
+ * caller destroy the writer again. */
+ result = cwriter_ensure_pause_writer(data);
+ if(result)
+ return result;
+ }
+
+ cwriter_add(data, writer);
return CURLE_OK;
}
@@ -508,7 +500,7 @@ struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
const char *name)
{
struct Curl_cwriter *writer;
- for(writer = data->req.writer_stack; writer; writer = writer->next) {
+ for(writer = data->req.writer.stack; writer; writer = writer->next) {
if(!strcmp(name, writer->cwt->name))
return writer;
}
@@ -519,34 +511,17 @@ struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
const struct Curl_cwtype *cwt)
{
struct Curl_cwriter *writer;
- for(writer = data->req.writer_stack; writer; writer = writer->next) {
+ for(writer = data->req.writer.stack; writer; writer = writer->next) {
if(writer->cwt == cwt)
return writer;
}
return NULL;
}
-bool Curl_cwriter_is_content_decoding(struct Curl_easy *data)
-{
- struct Curl_cwriter *writer;
- for(writer = data->req.writer_stack; writer; writer = writer->next) {
- if(writer->phase == CURL_CW_CONTENT_DECODE)
- return TRUE;
- }
- return FALSE;
-}
-
-bool Curl_cwriter_is_paused(struct Curl_easy *data)
-{
- return Curl_cw_out_is_paused(data);
-}
-
CURLcode Curl_cwriter_unpause(struct Curl_easy *data)
{
- CURLcode result = Curl_cw_out_unpause(data);
- if(!result)
- result = Curl_cwriter_flush(data, data->req.writer_stack);
- return result;
+ data->req.writer.paused = FALSE;
+ return Curl_cwriter_flush(data, data->req.writer.stack);
}
CURLcode Curl_creader_read(struct Curl_easy *data,
@@ -1141,9 +1116,9 @@ static CURLcode do_init_reader_stack(struct Curl_easy *data,
DEBUGASSERT(r);
DEBUGASSERT(r->crt);
DEBUGASSERT(r->phase == CURL_CR_CLIENT);
- DEBUGASSERT(!data->req.reader_stack);
+ DEBUGASSERT(!data->req.reader.stack);
- data->req.reader_stack = r;
+ data->req.reader.stack = r;
clen = r->crt->total_length(data, r);
/* if we do not have 0 length init, and crlf conversion is wanted,
* add the reader for it */
@@ -1184,7 +1159,7 @@ CURLcode Curl_creader_add(struct Curl_easy *data,
struct Curl_creader *reader)
{
CURLcode result;
- struct Curl_creader **anchor = &data->req.reader_stack;
+ struct Curl_creader **anchor = &data->req.reader.stack;
if(!*anchor) {
result = Curl_creader_set_fread(data, data->state.infilesize);
@@ -1227,11 +1202,11 @@ CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
DEBUGASSERT(eos);
*nread = 0;
- if(!data->req.reader_stack) {
+ if(!data->req.reader.stack) {
result = Curl_creader_set_fread(data, data->state.infilesize);
if(result)
return result;
- DEBUGASSERT(data->req.reader_stack);
+ DEBUGASSERT(data->req.reader.stack);
}
if(!data->req.reader_started) {
Curl_rlimit_start(&data->progress.ul.rlimit, Curl_pgrs_now(data), -1);
@@ -1248,7 +1223,7 @@ CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
if(ul_avail < (curl_off_t)blen)
blen = (size_t)ul_avail;
}
- result = Curl_creader_read(data, data->req.reader_stack, buf, blen,
+ result = Curl_creader_read(data, data->req.reader.stack, buf, blen,
nread, eos);
out:
@@ -1259,7 +1234,7 @@ out:
bool Curl_creader_needs_rewind(struct Curl_easy *data)
{
- struct Curl_creader *reader = data->req.reader_stack;
+ struct Curl_creader *reader = data->req.reader.stack;
while(reader) {
if(reader->crt->needs_rewind(data, reader)) {
CURL_TRC_READ(data, "client reader needs rewind before next request");
@@ -1445,13 +1420,13 @@ out:
curl_off_t Curl_creader_total_length(struct Curl_easy *data)
{
- struct Curl_creader *r = data->req.reader_stack;
+ struct Curl_creader *r = data->req.reader.stack;
return r ? r->crt->total_length(data, r) : -1;
}
curl_off_t Curl_creader_client_length(struct Curl_easy *data)
{
- struct Curl_creader *r = data->req.reader_stack;
+ struct Curl_creader *r = data->req.reader.stack;
while(r && r->phase != CURL_CR_CLIENT)
r = r->next;
return r ? r->crt->total_length(data, r) : -1;
@@ -1459,7 +1434,7 @@ curl_off_t Curl_creader_client_length(struct Curl_easy *data)
CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset)
{
- struct Curl_creader *r = data->req.reader_stack;
+ struct Curl_creader *r = data->req.reader.stack;
while(r && r->phase != CURL_CR_CLIENT)
r = r->next;
return r ? r->crt->resume_from(data, r, offset) : CURLE_READ_ERROR;
@@ -1467,7 +1442,7 @@ CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset)
CURLcode Curl_creader_unpause(struct Curl_easy *data)
{
- struct Curl_creader *reader = data->req.reader_stack;
+ struct Curl_creader *reader = data->req.reader.stack;
CURLcode result = CURLE_OK;
while(reader) {
@@ -1482,7 +1457,7 @@ CURLcode Curl_creader_unpause(struct Curl_easy *data)
bool Curl_creader_is_paused(struct Curl_easy *data)
{
- struct Curl_creader *reader = data->req.reader_stack;
+ struct Curl_creader *reader = data->req.reader.stack;
while(reader) {
if(reader->crt->is_paused(data, reader))
@@ -1494,7 +1469,7 @@ bool Curl_creader_is_paused(struct Curl_easy *data)
void Curl_creader_done(struct Curl_easy *data, int premature)
{
- struct Curl_creader *reader = data->req.reader_stack;
+ struct Curl_creader *reader = data->req.reader.stack;
while(reader) {
reader->crt->done(data, reader, premature);
reader = reader->next;
@@ -1505,7 +1480,7 @@ struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data,
const struct Curl_crtype *crt)
{
struct Curl_creader *r;
- for(r = data->req.reader_stack; r; r = r->next) {
+ for(r = data->req.reader.stack; r; r = r->next) {
if(r->crt == crt)
return r;
}
lib/sendf.h+10 -14
@@ -24,6 +24,7 @@
*
***************************************************************************/
#include "curl_setup.h"
+#include "cw-out.h"
/**
* Type of data that is being written to the client (application)
@@ -104,6 +105,7 @@ typedef enum {
CURL_CW_RAW, /* raw data written, before any decoding */
CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
+ CURL_CW_BEFORE_DECODE, /* after protocol, but before content decoding */
CURL_CW_CONTENT_DECODE, /* remove content-encodings */
CURL_CW_CLIENT /* data written to client */
} Curl_cwriter_phase;
@@ -176,22 +178,16 @@ struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
const char *name);
-/**
- * Convenience method for calling `writer->do_write()` that
- * checks for NULL writer.
- */
-CURLcode Curl_cwriter_write(struct Curl_easy *data,
- struct Curl_cwriter *writer, int type,
- const char *buf, size_t nbytes);
-CURLcode Curl_cwriter_flush(struct Curl_easy *data,
- struct Curl_cwriter *writer);
+/* Convenience method for calling `writer->do_write()` that
+ * checks for NULL writer. */
+#define Curl_cwriter_write(d, w, t, b, n) \
+ ((w) ? (w)->cwt->do_write((d), (w), (t), (b), (n)) : CURLE_WRITE_ERROR)
-/**
- * Return TRUE iff client writer is paused.
- */
-bool Curl_cwriter_is_paused(struct Curl_easy *data);
+#define Curl_cwriter_flush(d, w) \
+ ((w) ? (w)->cwt->do_flush((d), (w)) : CURLE_WRITE_ERROR)
-bool Curl_cwriter_is_content_decoding(struct Curl_easy *data);
+/* TRUE if client writer is paused. */
+#define Curl_cwriter_is_paused(d) ((bool)(d)->req.writer.paused)
/**
* Unpause client writer and flush any buffered date to the client.
tests/http/scorecard.py+34 -6
@@ -40,6 +40,7 @@ from testenv import (
Dante,
Env,
ExecResult,
+ H2oServer,
Httpd,
NghttpxQuic,
RunProfile,
@@ -776,17 +777,19 @@ def run_score(args, protocol):
uploads = None
requests = args.requests
- test_httpd = protocol != 'h3'
- test_caddy = protocol == 'h3'
- if args.caddy or args.httpd:
- test_caddy = args.caddy
- test_httpd = args.httpd
-
rv = 0
env = Env()
env.setup()
env.test_timeout = None
+ test_httpd = protocol != 'h3'
+ test_h2o = protocol == 'h3' and env.have_h2o()
+ test_caddy = protocol == 'h3' and not test_h2o
+ if args.caddy or args.httpd or args.h2o:
+ test_caddy = args.caddy
+ test_httpd = args.httpd
+ test_h2o = args.h2o
+
sockd = None
socks_args = None
if args.socks4 and args.socks5:
@@ -803,6 +806,7 @@ def run_score(args, protocol):
httpd = None
nghttpx = None
caddy = None
+ h2o = None
try:
cards = []
@@ -859,6 +863,26 @@ def run_score(args, protocol):
card.setup_resources(server_docs, downloads)
cards.append(card)
+ if test_h2o:
+ h2o = H2oServer(env=env)
+ h2o.clear_logs()
+ assert h2o.initial_start()
+ server_descr = f'H2o/{env.h2o_version()}'
+ server_port = h2o.port
+ server_docs = h2o.docs_dir
+ card = ScoreRunner(env=env,
+ protocol=protocol,
+ server_descr=server_descr,
+ server_port=server_port,
+ verbose=args.verbose, curl_verbose=args.curl_verbose,
+ download_parallel=args.download_parallel,
+ upload_parallel=args.upload_parallel,
+ with_flame=args.flame,
+ socks_args=socks_args,
+ limit_rate=args.limit_rate)
+ card.setup_resources(server_docs, downloads)
+ cards.append(card)
+
if test_caddy and env.caddy:
backend = ''
if uploads and httpd is None:
@@ -921,6 +945,8 @@ def run_score(args, protocol):
caddy.stop()
if nghttpx:
nghttpx.stop(wait_dead=False)
+ if h2o:
+ h2o.stop()
if httpd:
httpd.stop()
if sockd:
@@ -951,6 +977,8 @@ def main():
default=1, help="how many sample runs to make")
parser.add_argument("--httpd", action='store_true', default=False,
help="evaluate httpd server only")
+ parser.add_argument("--h2o", action='store_true', default=False,
+ help="evaluate h2o server only")
parser.add_argument("--caddy", action='store_true', default=False,
help="evaluate caddy server only")
parser.add_argument("--curl-verbose", action='store_true',
tests/http/testenv/__init__.py+1 -0
@@ -38,6 +38,7 @@ from .client import LocalClient
from .dante import Dante
from .dnsd import Dnsd
from .env import Env
+from .h2o import H2oServer, H2oProxy
from .httpd import Httpd
from .nghttpx import Nghttpx, NghttpxFwd, NghttpxQuic
from .sshd import Sshd