You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2015/12/30 17:13:46 UTC
svn commit: r1722370 - in /httpd/test/mod_h2/trunk: ./ conf/ mh2fuzz/
Author: icing
Date: Wed Dec 30 16:13:45 2015
New Revision: 1722370
URL: http://svn.apache.org/viewvc?rev=1722370&view=rev
Log:
implemented first fuzzer 'random-close' for randomly aborting connections
Added:
httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.c
httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.h
httpd/test/mod_h2/trunk/sessionlife (with props)
Modified:
httpd/test/mod_h2/trunk/Makefile.am
httpd/test/mod_h2/trunk/conf/httpd.conf
httpd/test/mod_h2/trunk/mh2fuzz/Makefile.am
httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.c
httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.h
httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.c
httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.h
httpd/test/mod_h2/trunk/mh2fuzz/h2c_stream.c
httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.c
httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.h
httpd/test/mod_h2/trunk/mh2fuzz/mh2f_main.c
Modified: httpd/test/mod_h2/trunk/Makefile.am
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/Makefile.am?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/Makefile.am (original)
+++ httpd/test/mod_h2/trunk/Makefile.am Wed Dec 30 16:13:45 2015
@@ -56,6 +56,7 @@ TEST_DEP = @TEST_DEP@
PHP_FPM = @PHP_FPM@
PHP_FPM_PID = gen/php-fpm/php-fpm.pid
+MH2FUZZ = mh2fuzz/mh2fuzz
.PHONY: clean test loadtest start stop restart install-client install-nghttp2
@@ -169,6 +170,10 @@ h2cload: \
$(H2LOAD) -i $(GEN)/load-h2c-urls-1.txt -n 200000 -t 7 -m $(MAX_STREAMS) -c 8
$(H2LOAD) -i $(GEN)/load-h2c-urls-1.txt -n 200000 -t 8 -m $(MAX_STREAMS) -c 8
+fuzz: $(MH2FUZZ)
+ @for i in 0 1 2 3 4 5 6 7 8 9; do echo "fuzz $$i..."; $(MH2FUZZ) -q -t 4 -c 75 -m 10 -n 100000 -f random-close10 http://$(HTTP_AUTH)/ ; done
+
+
################################################################################
# Switch mpm modules
#
Modified: httpd/test/mod_h2/trunk/conf/httpd.conf
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/conf/httpd.conf?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/conf/httpd.conf (original)
+++ httpd/test/mod_h2/trunk/conf/httpd.conf Wed Dec 30 16:13:45 2015
@@ -72,11 +72,6 @@ MaxKeepAliveRequests 0
<IfModule http2_module>
LogLevel http2:info
- <IfModule mpm_event_module>
- ThreadsPerChild 64
- MaxRequestWorkers 768
- </IfModule>
-
# max parallel streams per session, default 100
#H2MaxSessionStreams
# max initial window size upstream (per stream), default 64k
@@ -107,10 +102,6 @@ MaxKeepAliveRequests 0
H2PushPriority image/png after 32
H2PushPriority application/javascript interleaved
</IfVersion>
- <IfVersion >= 2.4.19>
- H2Timeout 5
- H2KeepAliveTimeout 5
- </IfVersion>
</IfModule>
Modified: httpd/test/mod_h2/trunk/mh2fuzz/Makefile.am
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/Makefile.am?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/Makefile.am (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/Makefile.am Wed Dec 30 16:13:45 2015
@@ -24,6 +24,7 @@ bin_PROGRAMS = mh2fuzz
mh2fuzz_SOURCES = \
mh2f_main.c \
+ mh2f_fuzzer.c \
h2c_conn.c \
h2c_feed.c \
h2c_request.c \
Modified: httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.c
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.c?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.c (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.c Wed Dec 30 16:13:45 2015
@@ -27,15 +27,34 @@ static long cid;
static apr_size_t BUF_SIZE = 16 * 1024;
+static apr_status_t on_read(h2c_conn *c, const char *data, apr_size_t len)
+{
+ if (c->obs && c->obs->on_read) {
+ return c->obs->on_read(c, data, len, c->obs->ctx);
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t on_write(h2c_conn *c)
+{
+ if (c->obs && c->obs->on_write) {
+ return c->obs->on_write(c, c->obs->ctx);
+ }
+ return APR_SUCCESS;
+}
+
static apr_status_t read_plain(h2c_conn *c)
{
char buffer[16*1024];
apr_size_t len = H2_DIM(buffer);
apr_status_t status;
+ if (!c->socket) {
+ return APR_EOF;
+ }
status = apr_socket_recv(c->socket, buffer, &len);
if (len > 0) {
- apr_status_t s2 = h2c_conn_on_read(c, buffer, len);
+ apr_status_t s2 = on_read(c, buffer, len);
if (status == APR_SUCCESS) {
status = s2;
}
@@ -46,6 +65,10 @@ static apr_status_t read_plain(h2c_conn
static apr_status_t write_plain(h2c_conn *c)
{
apr_status_t status = APR_SUCCESS;
+
+ if (!c->socket) {
+ return APR_EOF;
+ }
if (c->buf_len > 0) {
apr_size_t len = c->buf_len;
status = apr_socket_send(c->socket, c->buffer + c->buf_head, &len);
@@ -111,8 +134,12 @@ apr_status_t h2c_conn_create(h2c_conn **
void h2c_conn_destroy(h2c_conn *c)
{
+ if (c->socket) {
+ apr_socket_close(c->socket);
+ c->socket = NULL;
+ }
if (c->pool) {
- apr_pool_destroy(c->pool);
+ /* apr_pool_destroy(c->pool);*/
}
}
@@ -128,57 +155,58 @@ void h2c_conn_want_io(h2c_conn *c, int f
c->pfd->reqevents = pf;
}
-apr_status_t h2c_conn_on_connect(h2c_conn *c)
+h2c_conn_obs *h2c_conn_obs_get(h2c_conn *c)
{
- if (c->on_connect) {
- return c->on_connect(c, c->cb_ctx);
- }
- return APR_SUCCESS;
+ return c->obs;
}
-apr_status_t h2c_conn_on_read(h2c_conn *c, const char *data, apr_size_t len)
+void h2c_conn_obs_set(h2c_conn *c, h2c_conn_obs *obs)
{
- if (c->on_read) {
- return c->on_read(c, data, len, c->cb_ctx);
+ if (obs->setup) {
+ c->obs = obs->setup(c, obs->ctx);
+ }
+ else {
+ c->obs = obs;
}
- return APR_SUCCESS;
}
-apr_status_t h2c_conn_on_write(h2c_conn *c)
+void h2c_conn_verbose_set(h2c_conn *c, int verbose)
{
- if (c->on_write) {
- return c->on_write(c, c->cb_ctx);
- }
- return APR_SUCCESS;
+ c->verbose = verbose;
}
-void h2c_conn_set_callback(h2c_conn *c,
- h2c_conn_on_connect_cb *on_connect,
- h2c_conn_on_read_cb *on_read,
- h2c_conn_on_write_cb *on_write,
- h2c_conn_before_close *before_close,
- void *ctx)
-{
- c->on_connect = on_connect;
- c->on_read = on_read;
- c->on_write = on_write;
- c->before_close = before_close;
- c->cb_ctx = ctx;
+apr_status_t h2c_conn_connect(h2c_conn *c)
+{
+ apr_status_t status;
+
+ if (c->verbose > 0) {
+ printf("connecting to %s (%s)...", c->addr->hostname, c->ip_addr);
+ }
+
+ status = apr_socket_connect(c->socket, c->addr);
+ if (status != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(status)) {
+ return status;
+ }
+
+ if (c->verbose > 0) {
+ printf("done.\n");
+ }
+
+ apr_socket_opt_set(c->socket, APR_SO_NONBLOCK, 1);
+ if (c->obs && c->obs->on_connect) {
+ return c->obs->on_connect(c, c->obs->ctx);
+ }
+ return APR_SUCCESS;
}
apr_status_t h2c_conn_read(h2c_conn *c)
{
- if (!c->socket) {
- return APR_EOF;
- }
return c->read(c);
}
apr_status_t h2c_conn_write(h2c_conn *c)
{
- if (!c->socket) {
- return APR_EOF;
- }
+ on_write(c);
return c->write(c);
}
@@ -187,8 +215,8 @@ apr_status_t h2c_conn_close(h2c_conn *c)
apr_status_t status = APR_SUCCESS;
if (c->socket) {
- if (c->before_close) {
- c->before_close(c, c->cb_ctx);
+ if (c->obs && c->obs->before_close) {
+ c->obs->before_close(c, c->obs->ctx);
}
status = apr_socket_close(c->socket);
c->socket = NULL;
Modified: httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.h
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.h?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.h (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/h2c_conn.h Wed Dec 30 16:13:45 2015
@@ -18,13 +18,24 @@
struct apr_pollfd_t;
typedef struct h2c_conn h2c_conn;
+typedef struct h2c_conn_obs h2c_conn_obs;
+typedef h2c_conn_obs *h2c_conn_obs_setup(h2c_conn *c, void *ctx);
typedef apr_status_t h2c_conn_on_connect_cb(h2c_conn *c, void *ctx);
typedef apr_status_t h2c_conn_on_read_cb(h2c_conn *c, const char *data, apr_size_t len, void *ctx);
typedef apr_status_t h2c_conn_on_write_cb(h2c_conn *c, void *ctx);
typedef apr_status_t h2c_conn_before_close(h2c_conn *c, void *ctx);
typedef apr_status_t h2c_conn_action(h2c_conn *c);
+struct h2c_conn_obs {
+ void *ctx;
+ h2c_conn_obs_setup *setup;
+ h2c_conn_on_connect_cb *on_connect;
+ h2c_conn_on_read_cb *on_read;
+ h2c_conn_on_write_cb *on_write;
+ h2c_conn_before_close *before_close;
+};
+
#define H2C_CONN_READ 0x01
#define H2C_CONN_WRITE 0x04
@@ -46,30 +57,24 @@ struct h2c_conn {
apr_size_t buf_head;
apr_size_t buf_len;
- void *cb_ctx;
- h2c_conn_on_connect_cb *on_connect;
- h2c_conn_on_read_cb *on_read;
- h2c_conn_on_write_cb *on_write;
- h2c_conn_before_close *before_close;
+ h2c_conn_obs *obs;
+ int verbose;
};
apr_status_t h2c_conn_create(h2c_conn **pc, apr_pool_t *parent, apr_uri_t *uri);
void h2c_conn_destroy(h2c_conn *c);
-void h2c_conn_set_callback(h2c_conn *c,
- h2c_conn_on_connect_cb *on_connect,
- h2c_conn_on_read_cb *on_read,
- h2c_conn_on_write_cb *on_write,
- h2c_conn_before_close *before_close,
- void *ctx);
+h2c_conn_obs *h2c_conn_obs_get(h2c_conn *c);
+void h2c_conn_obs_set(h2c_conn *c, h2c_conn_obs *obs);
apr_status_t h2c_conn_on_connect(h2c_conn *c);
-apr_status_t h2c_conn_on_read(h2c_conn *c, const char *data, apr_size_t len);
-apr_status_t h2c_conn_on_write(h2c_conn *c);
void h2c_conn_want_io(h2c_conn *c, int flags);
+void h2c_conn_verbose_set(h2c_conn *c, int verbose);
+
+apr_status_t h2c_conn_connect(h2c_conn *c);
apr_status_t h2c_conn_read(h2c_conn *c);
apr_status_t h2c_conn_write(h2c_conn *c);
Modified: httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.c
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.c?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.c (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.c Wed Dec 30 16:13:45 2015
@@ -34,26 +34,32 @@ apr_status_t h2c_session_create(h2c_sess
{
apr_pool_t *p;
apr_status_t status;
+ h2c_conn_obs *obs;
h2c_session *s;
s = apr_pcalloc(c->pool, sizeof(h2c_session));
s->c = c;
- s->state = H2C_SESSION_ST_INIT;
s->output = stdout;
s->window_bits_default = 30;
s->window_bits_connection = 30;
s->max_streams = max_streams;
+
+ obs = apr_pcalloc(c->pool, sizeof(*obs));
+ obs->ctx = s;
+ obs->on_connect = on_conn_connect;
+ obs->on_read = on_conn_read;
+ obs->on_write = on_conn_write;
+ obs->before_close = on_conn_close;
+ h2c_conn_obs_set(c, obs);
- h2c_conn_set_callback(c, on_conn_connect, on_conn_read, on_conn_write,
- on_conn_close, s);
*ps = s;
return APR_SUCCESS;
}
-apr_status_t h2c_session_close(h2c_session *s)
+static apr_status_t h2c_session_close(h2c_session *s)
{
if (!s->closed) {
if (!s->goaway_recvd) {
@@ -66,9 +72,14 @@ apr_status_t h2c_session_close(h2c_sessi
return APR_SUCCESS;
}
-void h2c_session_verbose_set(h2c_session *s, int verbose)
+void h2c_session_output_set(h2c_session *s, FILE *output)
+{
+ s->output = output;
+}
+
+void h2c_session_feed_set(h2c_session *s, h2c_feed *feed)
{
- s->verbose = verbose;
+ s->feed = feed;
}
static ssize_t raw_send(nghttp2_session *session, const uint8_t *data,
@@ -82,7 +93,7 @@ static ssize_t raw_send(nghttp2_session
return h2c_conn_wbuf_append(s->c, (const char*)data, length);
}
-static void log_frame(h2c_session *s, const char *msg, const nghttp2_frame *frame)
+static void log_frame(h2c_session *s, const char *msg, const nghttp2_frame *frame, FILE *f)
{
char scratch[128];
size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
@@ -90,45 +101,45 @@ static void log_frame(h2c_session *s, co
switch (frame->hd.type) {
case NGHTTP2_DATA:
- fprintf(stderr, "%ld: %s DATA[length=%d, flags=%d, stream=%d, padlen=%d]\n",
+ fprintf(f, "%ld: %s DATA[length=%d, flags=%d, stream=%d, padlen=%d]\n",
s->c->id, msg, (int)frame->hd.length, frame->hd.flags,
frame->hd.stream_id, (int)frame->data.padlen);
break;
case NGHTTP2_HEADERS:
- fprintf(stderr, "%ld: %s HEADERS[length=%d, hend=%d, stream=%d, eos=%d]\n",
+ fprintf(f, "%ld: %s HEADERS[length=%d, hend=%d, stream=%d, eos=%d]\n",
s->c->id, msg, (int)frame->hd.length,
!!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
frame->hd.stream_id,
!!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM));
break;
case NGHTTP2_PRIORITY:
- fprintf(stderr, "%ld: %s PRIORITY[length=%d, flags=%d, stream=%d]\n",
+ fprintf(f, "%ld: %s PRIORITY[length=%d, flags=%d, stream=%d]\n",
s->c->id, msg, (int)frame->hd.length,
frame->hd.flags, frame->hd.stream_id);
break;
case NGHTTP2_RST_STREAM:
- fprintf(stderr, "%ld: %s RST_STREAM[length=%d, flags=%d, stream=%d]\n",
+ fprintf(f, "%ld: %s RST_STREAM[length=%d, flags=%d, stream=%d]\n",
s->c->id, msg, (int)frame->hd.length,
frame->hd.flags, frame->hd.stream_id);
break;
case NGHTTP2_SETTINGS:
if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
- fprintf(stderr, "%ld: %s SETTINGS[ack=1, stream=%d]\n",
+ fprintf(f, "%ld: %s SETTINGS[ack=1, stream=%d]\n",
s->c->id, msg, frame->hd.stream_id);
return;
}
- fprintf(stderr, "%ld: %s SETTINGS[length=%d, stream=%d]\n",
+ fprintf(f, "%ld: %s SETTINGS[length=%d, stream=%d]\n",
s->c->id, msg, (int)frame->hd.length, frame->hd.stream_id);
break;
case NGHTTP2_PUSH_PROMISE:
- fprintf(stderr, "%ld: %s PUSH_PROMISE[length=%d, hend=%d, stream=%d]\n",
+ fprintf(f, "%ld: %s PUSH_PROMISE[length=%d, hend=%d, stream=%d]\n",
s->c->id, msg, (int)frame->hd.length,
!!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
frame->hd.stream_id);
break;
case NGHTTP2_PING:
- fprintf(stderr, "%ld: %s PING[length=%d, ack=%d, stream=%d]\n",
+ fprintf(f, "%ld: %s PING[length=%d, ack=%d, stream=%d]\n",
s->c->id, msg, (int)frame->hd.length,
frame->hd.flags&NGHTTP2_FLAG_ACK,
frame->hd.stream_id);
@@ -142,11 +153,11 @@ static void log_frame(h2c_session *s, co
s->c->id, msg, frame->goaway.error_code, scratch);
break;
case NGHTTP2_WINDOW_UPDATE:
- fprintf(stderr, "%ld: %s WINDOW_UPDATE[length=%d, stream=%d]\n",
+ fprintf(f, "%ld: %s WINDOW_UPDATE[length=%d, stream=%d]\n",
s->c->id, msg, (int)frame->hd.length, frame->hd.stream_id);
break;
default:
- fprintf(stderr, "%ld: %s type=%d[length=%d, flags=%d, stream=%d]\n",
+ fprintf(f, "%ld: %s type=%d[length=%d, flags=%d, stream=%d]\n",
s->c->id, msg, frame->hd.type, (int)frame->hd.length,
frame->hd.flags, frame->hd.stream_id);
break;
@@ -158,8 +169,8 @@ static int on_frame_recv(nghttp2_session
{
h2c_session *s = user_data;
- if (s->verbose > 0) {
- log_frame(s, "recv", frame);
+ if (s->c->verbose > 0) {
+ log_frame(s, "recv", frame, stderr);
}
switch (frame->hd.type) {
case NGHTTP2_GOAWAY:
@@ -177,8 +188,8 @@ static int before_frame_send(nghttp2_ses
{
h2c_session *s = user_data;
- if (s->verbose > 0) {
- log_frame(s, "send", frame);
+ if (s->c->verbose > 0) {
+ log_frame(s, "send", frame, stderr);
}
return 0;
}
@@ -207,14 +218,11 @@ static int on_stream_close(nghttp2_sessi
h2c_session *s = user_data;
h2c_stream *stream;
- if (s->verbose > 0) {
+ if (s->c->verbose > 0) {
fprintf(stderr, "closed STREAM[%d]\n", stream_id);
}
--s->open_streams;
- if (!s->closed && s->open_streams <= 0) {
- s->state = H2C_SESSION_ST_IDLE;
- }
stream = nghttp2_session_get_stream_user_data(ngh2, stream_id);
if (!stream) {
@@ -249,15 +257,17 @@ static apr_status_t check_io_sense(h2c_s
{
int io_sense = 0;
- if (s->feed && s->max_streams > s->open_streams) {
+ if (status == APR_SUCCESS && s->feed && s->max_streams > s->open_streams) {
+ apr_status_t s2;
h2c_request *r;
- status = h2c_feed_next(&r, s->feed, s);
- if (status == APR_SUCCESS) {
+ s2 = h2c_feed_next(&r, s->feed, s);
+ if (s2 == APR_SUCCESS) {
status = h2c_session_submit(s, r, NULL);
}
- else if (APR_STATUS_IS_EOF(status) && s->state == H2C_SESSION_ST_IDLE) {
+ else if (APR_STATUS_IS_EOF(s2) && s->open_streams == 0) {
h2c_session_close(s);
+ status = APR_EOF;
}
}
@@ -335,8 +345,6 @@ static apr_status_t on_conn_connect(h2c_
rv = nghttp2_submit_window_update(s->ngh2, NGHTTP2_FLAG_NONE, 0, add_conn_window);
}
- s->state = H2C_SESSION_ST_IDLE;
-
h2c_conn_want_io(c, H2C_CONN_READ|H2C_CONN_WRITE);
return rv? APR_EGENERAL : APR_SUCCESS;
}
@@ -377,7 +385,6 @@ apr_status_t h2c_session_submit(h2c_sess
return APR_EGENERAL;
}
- s->state = H2C_SESSION_ST_BUSY;
s->max_stream_sent = H2_MAX(s->max_stream_sent, stream_id);
++s->open_streams;
stream->id = stream_id;
@@ -388,12 +395,3 @@ apr_status_t h2c_session_submit(h2c_sess
return check_io_sense(s, APR_SUCCESS);
}
-void h2c_session_output_set(h2c_session *s, FILE *output)
-{
- s->output = output;
-}
-
-void h2c_session_feed_set(h2c_session *s, h2c_feed *feed)
-{
- s->feed = feed;
-}
Modified: httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.h
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.h?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.h (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/h2c_session.h Wed Dec 30 16:13:45 2015
@@ -25,23 +25,12 @@ struct nghttp2_session;
typedef struct h2c_session h2c_session;
-typedef enum {
- H2C_SESSION_ST_INIT, /* send initial SETTINGS, etc. */
- H2C_SESSION_ST_IDLE, /* nothing submitted */
- H2C_SESSION_ST_BUSY, /* read/write without stop */
- H2C_SESSION_ST_BUSY_READ, /* waiting for data from server */
- H2C_SESSION_ST_KEEPALIVE, /* IDLE passed, hanging around */
- H2C_SESSION_ST_CLOSING, /* shutting down */
-} h2c_session_state;
-
struct h2c_session {
struct h2c_conn *c;
struct nghttp2_session *ngh2;
- h2c_session_state state;
unsigned int closed : 1;
unsigned int goaway_recvd : 1;
- int verbose;
int max_stream_recv;
int max_stream_sent;
@@ -52,27 +41,19 @@ struct h2c_session {
int window_bits_default;
int window_bits_connection;
- FILE *output;
-
struct h2c_feed *feed;
+ FILE *output;
};
apr_status_t h2c_session_create(h2c_session **psession, struct h2c_conn *c,
int max_streams);
-apr_status_t h2c_session_add_request(h2c_session *session, struct h2c_request *r);
-
-apr_status_t h2c_session_close(h2c_session *session);
+void h2c_session_feed_set(h2c_session *s, struct h2c_feed *feed);
+void h2c_session_output_set(h2c_session *s, FILE *output);
-void h2c_session_verbose_set(h2c_session *s, int verbose);
+apr_status_t h2c_session_add_request(h2c_session *session, struct h2c_request *r);
-apr_status_t h2c_session_on_read(h2c_session *s, const uint8_t *data, size_t len);
-apr_status_t h2c_session_on_write(h2c_session *session);
-
apr_status_t h2c_session_submit(h2c_session *s, struct h2c_request *r, int *pid);
-void h2c_session_feed_set(h2c_session *s, struct h2c_feed *feed);
-void h2c_session_output_set(h2c_session *s, FILE *output);
-
#endif /* h2c_session_h */
Modified: httpd/test/mod_h2/trunk/mh2fuzz/h2c_stream.c
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/h2c_stream.c?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/h2c_stream.c (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/h2c_stream.c Wed Dec 30 16:13:45 2015
@@ -71,7 +71,7 @@ apr_status_t h2c_stream_close(h2c_stream
{
if (!stream->closed) {
stream->closed = 1;
- if (stream->s->verbose >= 0) {
+ if (stream->s->c->verbose >= 0) {
fprintf(stderr, "%5ld:%05d %s %s -> %d %ld\n",
stream->s->c->id, stream->id,
stream->r->method, stream->r->path,
Modified: httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.c
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.c?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.c (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.c Wed Dec 30 16:13:45 2015
@@ -26,20 +26,22 @@
static int nid;
apr_status_t h2c_worker_create(h2c_worker **pw, apr_pool_t *p, apr_uri_t *uri,
- h2c_feed *feed, int num_conns, int max_streams, int verbose)
+ h2c_feed *feed, h2c_conn_obs *conn_fuzzer,
+ int num_conns, int max_streams, int verbose)
{
h2c_worker *w;
w = apr_pcalloc(p, sizeof(*w));
- w->id = nid++;
- w->p = p;
- w->uri = uri;
- w->feed = feed;
+ w->id = nid++;
+ w->p = p;
+ w->uri = uri;
+ w->feed = feed;
+ w->conn_fuzzer = conn_fuzzer;
w->max_streams = max_streams;
- w->verbose = verbose;
+ w->verbose = verbose;
- w->num_conns = num_conns;
+ w->num_conns = num_conns;
w->connections = apr_pcalloc(w->p, sizeof(h2c_conn*)*w->num_conns);
*pw = w;
@@ -79,8 +81,7 @@ apr_status_t h2c_worker_run(h2c_worker *
fprintf(stderr, "error %d creating conn %s\n", status, w->uri->hostname);
return status;
}
-
- w->connections[i] = conn;
+ h2c_conn_verbose_set(conn, w->verbose);
status = apr_pollset_add(pollset, conn->pfd);
if (status != APR_SUCCESS) {
@@ -97,28 +98,23 @@ apr_status_t h2c_worker_run(h2c_worker *
h2c_session_feed_set(session, w->feed);
h2c_session_output_set(session, NULL);
- h2c_session_verbose_set(session, w->verbose);
- if (w->verbose > 0) {
- printf("connecting to %s (%s %d)...", conn->addr->hostname, conn->ip_addr, w->uri->port);
+ if (w->conn_fuzzer) {
+ h2c_conn_obs_set(conn, w->conn_fuzzer);
}
- status = apr_socket_connect(conn->socket, conn->addr);
- if (status != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(status)) {
- fprintf(stderr, "error %d connecting to %s\n", status, conn->addr->hostname);
- return status;
+ status = h2c_conn_connect(conn);
+ if (status != APR_SUCCESS) {
+ if (!APR_STATUS_IS_EOF(status)) {
+ fprintf(stderr, "error %d connecting to %s\n", status, conn->addr->hostname);
+ }
+ h2c_conn_destroy(conn);
}
-
- if (w->verbose > 0) {
- printf("done.\n");
+ else {
+ ++live_conns;
+ w->connections[i] = conn;
}
-
- apr_socket_opt_set(conn->socket, APR_SO_NONBLOCK, 1);
-
- ++live_conns;
- h2c_conn_on_connect(conn);
}
-
while (live_conns > 0) {
apr_int32_t numdesc;
const apr_pollfd_t *pdesc;
@@ -130,7 +126,7 @@ apr_status_t h2c_worker_run(h2c_worker *
if (status != APR_SUCCESS) {
if (APR_STATUS_IS_TIMEUP(status)) {
fprintf(stderr, "timeup polling\n");
- continue;
+ break;
}
else if (APR_STATUS_IS_EINTR(status)) {
continue;
@@ -149,7 +145,6 @@ apr_status_t h2c_worker_run(h2c_worker *
}
if (pfd->rtnevents & APR_POLLOUT) {
op = "writing";
- h2c_conn_on_write(c);
status = h2c_conn_write(c);
}
if (pfd->rtnevents & APR_POLLHUP) {
@@ -162,8 +157,8 @@ apr_status_t h2c_worker_run(h2c_worker *
}
if (status != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(status)) {
- if (status != APR_EOF) {
- fprintf(stderr, "error %d %s\n", status, op);
+ if (!APR_STATUS_IS_EOF(status)) {
+ fprintf(stderr, "closing %ld, status %d %s\n", c->id, status, op);
}
h2c_conn_close(c);
}
@@ -174,12 +169,20 @@ apr_status_t h2c_worker_run(h2c_worker *
conn_destroy(w, c);
}
else if (pfd->reqevents != c->pfd->reqevents) {
- /* change in events this connection waits for */
+ /* change in events this connection waits for
+ * TODO: is there a better way to do this? */
apr_pollset_remove(pollset, pfd);
apr_pollset_add(pollset, c->pfd);
}
}
}
+ for (i = 0; i < w->num_conns; ++i) {
+ h2c_conn *c = w->connections[i];
+ if (c) {
+ conn_destroy(w, c);
+ }
+ }
+
return APR_SUCCESS;
}
\ No newline at end of file
Modified: httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.h
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.h?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.h (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/h2c_worker.h Wed Dec 30 16:13:45 2015
@@ -17,6 +17,7 @@
#define h2c_worker_h
struct h2c_conn;
+struct h2c_conn_obs;
struct h2c_feed;
typedef struct h2c_worker h2c_worker;
@@ -25,7 +26,8 @@ struct h2c_worker {
int id;
apr_pool_t *p;
apr_uri_t *uri;
- h2c_feed *feed;
+ struct h2c_feed *feed;
+ struct h2c_conn_obs *conn_fuzzer;
int num_conns;
struct h2c_conn **connections;
@@ -34,8 +36,8 @@ struct h2c_worker {
};
apr_status_t h2c_worker_create(h2c_worker **pw, apr_pool_t *p, apr_uri_t *uri,
- struct h2c_feed *feed, int num_conns,
- int max_streams, int verbose);
+ struct h2c_feed *feed, struct h2c_conn_obs *conn_fuzzer,
+ int num_conns, int max_streams, int verbose);
apr_status_t h2c_worker_run(h2c_worker *w);
Added: httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.c
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.c?rev=1722370&view=auto
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.c (added)
+++ httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.c Wed Dec 30 16:13:45 2015
@@ -0,0 +1,127 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+
+#include <apr.h>
+#include <apr_strings.h>
+#include <apr_poll.h>
+#include <apr_uri.h>
+
+#include "h2c_conn.h"
+#include "mh2f_fuzzer.h"
+
+typedef struct fuzzer_rc {
+ const char *name;
+ h2c_conn_obs obs;
+ h2c_conn_obs *prev;
+ int fail_pc;
+} fuzzer_rc;
+
+static h2c_conn_obs *rc_setup(h2c_conn *c, void *ctx)
+{
+ fuzzer_rc *fnew, *f = ctx;
+
+ fnew = apr_pcalloc(c->pool, sizeof(*fnew));
+
+ memcpy(fnew, f, sizeof(*fnew));
+ fnew->obs.ctx = fnew;
+
+ if (f->prev && f->prev->setup) {
+ fnew->prev = f->prev->setup(c, f->prev->ctx);
+ }
+ else {
+ fnew->prev = h2c_conn_obs_get(c);
+ }
+
+ return &fnew->obs;
+}
+
+static apr_status_t rc_pipe(h2c_conn *c, fuzzer_rc *f, apr_status_t status)
+{
+ if (status == APR_SUCCESS && (rand() % 100 <= f->fail_pc)) {
+ if (c->verbose > 0) {
+ fprintf(stderr, "random-close(%d): closing conn %ld\n", f->fail_pc, c->id);
+ }
+ h2c_conn_close(c);
+ return APR_EOF;
+ }
+ return status;
+}
+
+static apr_status_t rc_on_connect(h2c_conn *c, void *ctx)
+{
+ fuzzer_rc *f = ctx;
+ return rc_pipe(c, f, (f->prev && f->prev->on_connect)?
+ f->prev->on_connect(c, f->prev->ctx) : APR_SUCCESS);
+}
+
+static apr_status_t rc_on_read(h2c_conn *c, const char *data, apr_size_t len, void *ctx)
+{
+ fuzzer_rc *f = ctx;
+ return rc_pipe(c, f, (f->prev && f->prev->on_read)?
+ f->prev->on_read(c, data, len, f->prev->ctx) : APR_SUCCESS);
+}
+
+static apr_status_t rc_on_write(h2c_conn *c, void *ctx)
+{
+ fuzzer_rc *f = ctx;
+ return rc_pipe(c, f, (f->prev && f->prev->on_write)?
+ f->prev->on_write(c, f->prev->ctx) : APR_SUCCESS);
+}
+
+static apr_status_t rc_before_close(h2c_conn *c, void *ctx)
+{
+ fuzzer_rc *f = ctx;
+ return ((f->prev && f->prev->before_close)?
+ f->prev->before_close(c, f->prev->ctx) : APR_SUCCESS);
+}
+
+static h2c_conn_obs *rc_create(const char *name, apr_pool_t *p, h2c_conn_obs *prev)
+{
+ fuzzer_rc *f;
+ size_t prelen = sizeof("random-close")-1;
+
+ f = apr_pcalloc(p, sizeof(*f));
+
+ f->name = apr_pstrdup(p, name);
+ f->fail_pc = 5;
+
+ f->obs.ctx = f;
+ f->obs.setup = rc_setup;
+ f->obs.on_connect = rc_on_connect;
+ f->obs.on_read = rc_on_read;
+ f->obs.on_write = rc_on_write;
+ f->obs.before_close = rc_before_close;
+ f->prev = prev;
+
+ if (strlen(f->name) > prelen) {
+ int n = (int)apr_atoi64(f->name+prelen);
+ if (n > 0) {
+ f->fail_pc = n;
+ }
+ }
+ return &f->obs;
+}
+
+#define HAS_PREFIX(lit,cs) (!strncmp((lit), (cs), sizeof(lit)-1))
+
+struct h2c_conn_obs *mh2f_conn_fuzzer_create(const char *name, apr_pool_t *p, h2c_conn_obs *prev)
+{
+ if (HAS_PREFIX("random-close", name)) {
+ return rc_create(name, p, prev);
+ }
+ return NULL;
+}
Added: httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.h
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.h?rev=1722370&view=auto
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.h (added)
+++ httpd/test/mod_h2/trunk/mh2fuzz/mh2f_fuzzer.h Wed Dec 30 16:13:45 2015
@@ -0,0 +1,24 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef mh2f_fuzzer_h
+#define mh2f_fuzzer_h
+
+struct h2c_conn_obs;
+
+struct h2c_conn_obs *mh2f_conn_fuzzer_create(const char *name, apr_pool_t *p,
+ struct h2c_conn_obs *prev);
+
+#endif /* mh2f_fuzzer_h */
Modified: httpd/test/mod_h2/trunk/mh2fuzz/mh2f_main.c
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/mh2fuzz/mh2f_main.c?rev=1722370&r1=1722369&r2=1722370&view=diff
==============================================================================
--- httpd/test/mod_h2/trunk/mh2fuzz/mh2f_main.c (original)
+++ httpd/test/mod_h2/trunk/mh2fuzz/mh2f_main.c Wed Dec 30 16:13:45 2015
@@ -27,6 +27,7 @@
#include "h2c_worker.h"
#include "mh2f_version.h"
+#include "mh2f_fuzzer.h"
#include "mh2f_main.h"
static int usage(const char *cmd, const char *msg)
@@ -43,8 +44,14 @@ static int usage(const char *cmd, const
return 2;
}
+static apr_thread_t *worker_create(apr_pool_t *parent, apr_uri_t *uri,
+ h2c_feed *feed, h2c_conn_obs *conn_fuzzer,
+ int num_conns, int max_streams, int verbose,
+ apr_threadattr_t *attr);
+
static struct option long_options[] = {
{ "connections", required_argument, NULL, 'c'},
+ { "fuzzer", required_argument, NULL, 'f'},
{"max-concurrent-streams", required_argument, NULL, 'm'},
{ "quiet", no_argument, NULL, 'q'},
{ "requests", required_argument, NULL, 'n'},
@@ -54,10 +61,6 @@ static struct option long_options[] = {
{ NULL, 0, NULL, 0}
};
-static apr_thread_t *worker_create(apr_pool_t *parent, apr_uri_t *uri,
- h2c_feed *feed, apr_threadattr_t *attr,
- int num_conns, int max_streams, int verbose);
-
int main(int argc, char **argv)
{
apr_pool_t *pool;
@@ -77,6 +80,7 @@ int main(int argc, char **argv)
h2c_conn *conn;
h2c_session *session;
h2c_request *r;
+ h2c_conn_obs *conn_fuzzer = NULL;
apr_thread_t **threads;
apr_threadattr_t *thread_attr;
@@ -84,7 +88,7 @@ int main(int argc, char **argv)
apr_pool_create_core(&pool);
while (1) {
- c = getopt_long(argc, argv, "c:m:n:qt:vV",
+ c = getopt_long(argc, argv, "c:f:m:n:qt:vV",
long_options, &option_index);
if (c == -1) {
@@ -94,6 +98,13 @@ int main(int argc, char **argv)
case 'c':
connections = (int)apr_atoi64(optarg);
break;
+ case 'f':
+ conn_fuzzer = mh2f_conn_fuzzer_create(optarg, pool, conn_fuzzer);
+ if (!conn_fuzzer) {
+ fprintf(stderr, "unknown fuzzer '%s'\n", optarg);
+ return usage(argv[0], NULL);
+ }
+ break;
case 'm':
if (!apr_strnatcasecmp("auto", optarg)) {
max_streams = -1;
@@ -183,8 +194,9 @@ int main(int argc, char **argv)
--repeats_rem;
h2c_feed_repeat_create(&feed, pool, r, n);
- threads[i] = worker_create(pool, &uri, feed, thread_attr,
- num_conns, max_streams, verbose);
+ threads[i] = worker_create(pool, &uri, feed, conn_fuzzer,
+ num_conns, max_streams, verbose,
+ thread_attr);
}
@@ -208,8 +220,9 @@ static void* APR_THREAD_FUNC execute(apr
}
static apr_thread_t *worker_create(apr_pool_t *parent, apr_uri_t *uri,
- h2c_feed *feed, apr_threadattr_t *attr,
- int num_conns, int max_streams, int verbose)
+ h2c_feed *feed, h2c_conn_obs *conn_fuzzer,
+ int num_conns, int max_streams, int verbose,
+ apr_threadattr_t *attr)
{
apr_allocator_t *allocator;
apr_pool_t *pool;
@@ -221,7 +234,8 @@ static apr_thread_t *worker_create(apr_p
apr_pool_create_ex(&pool, parent, NULL, allocator);
apr_allocator_owner_set(allocator, pool);
- status = h2c_worker_create(&w, pool, uri, feed, num_conns, max_streams, verbose);
+ status = h2c_worker_create(&w, pool, uri, feed, conn_fuzzer,
+ num_conns, max_streams, verbose);
if (status != APR_SUCCESS) {
fprintf(stderr, "error %d creating worker\n", status);
return NULL;
Added: httpd/test/mod_h2/trunk/sessionlife
URL: http://svn.apache.org/viewvc/httpd/test/mod_h2/trunk/sessionlife?rev=1722370&view=auto
==============================================================================
--- httpd/test/mod_h2/trunk/sessionlife (added)
+++ httpd/test/mod_h2/trunk/sessionlife Wed Dec 30 16:13:45 2015
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+LOG="$1"
+
+TMP="${TMP:-/tmp}"
+TMPOPENED="$TMP/$$.opened"
+TMPCLOSED="$TMP/$$.closed"
+TMPRELEASED="$TMP/$$.released"
+
+fgrep "started on " "$LOG" | while read line; do
+ stream=${line##*h2_session(};
+ stream=${stream%%)*}
+ echo $stream
+done | sort -n > "$TMPOPENED"
+
+fgrep "sent FRAME[GOAWAY" "$LOG" | while read line; do
+ stream=${line##*h2_session(};
+ stream=${stream%%)*}
+ echo $stream
+done | sort -n > "$TMPCLOSED"
+
+fgrep "release_join -> destroy" "$LOG" | while read line; do
+ stream=${line##*h2_mplx(};
+ stream=${stream%%)*}
+ echo $stream
+done | sort -n > "$TMPRELEASED"
+
+nopened=$(cat "$TMPOPENED" | wc -l | tr -d ' ')
+ngoaway=$(cat "$TMPCLOSED" | wc -l | tr -d ' ')
+nreleased=$(cat "$TMPRELEASED" | wc -l | tr -d ' ')
+
+echo "($nopened/$ngoaway/$nreleased) sessions (open/goaway/release)"
+if test $nopened != $ngoaway; then
+ echo "started <> goaway sessions:"
+ diff "$TMPOPENED" "$TMPCLOSED"
+fi
+if test $nopened != $nreleased; then
+ echo "started <> released sessions:"
+ diff "$TMPOPENED" "$TMPRELEASED"
+fi
+
+rm -f "$TMP/$$.*"
\ No newline at end of file
Propchange: httpd/test/mod_h2/trunk/sessionlife
------------------------------------------------------------------------------
svn:executable = *