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 = *