Return-Path: X-Original-To: apmail-httpd-cvs-archive@www.apache.org Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 040D118DE8 for ; Wed, 30 Dec 2015 16:13:57 +0000 (UTC) Received: (qmail 71109 invoked by uid 500); 30 Dec 2015 16:13:56 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 71032 invoked by uid 500); 30 Dec 2015 16:13:56 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 71023 invoked by uid 99); 30 Dec 2015 16:13:56 -0000 Received: from Unknown (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Dec 2015 16:13:56 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 47B901A02A4 for ; Wed, 30 Dec 2015 16:13:56 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.247 X-Spam-Level: * X-Spam-Status: No, score=1.247 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.554, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-eu-west.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id WNh7omK3kIKT for ; Wed, 30 Dec 2015 16:13:48 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-eu-west.apache.org (ASF Mail Server at mx1-eu-west.apache.org) with ESMTP id 775B5203A3 for ; Wed, 30 Dec 2015 16:13:47 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 9C2EFE0428 for ; Wed, 30 Dec 2015 16:13:46 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 9A1213A019A for ; Wed, 30 Dec 2015 16:13:46 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1722370 - in /httpd/test/mod_h2/trunk: ./ conf/ mh2fuzz/ Date: Wed, 30 Dec 2015 16:13:46 -0000 To: cvs@httpd.apache.org From: icing@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20151230161346.9A1213A019A@svn01-us-west.apache.org> 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 LogLevel http2:info - - ThreadsPerChild 64 - MaxRequestWorkers 768 - - # 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 - = 2.4.19> - H2Timeout 5 - H2KeepAliveTimeout 5 - 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 + +#include +#include +#include +#include + +#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 = *