1*e4f24219SNick Mathewson /* 2*e4f24219SNick Mathewson * Copyright 2009 Niels Provos and Nick Mathewson 3*e4f24219SNick Mathewson * 4*e4f24219SNick Mathewson * Redistribution and use in source and binary forms, with or without 5*e4f24219SNick Mathewson * modification, are permitted provided that the following conditions 6*e4f24219SNick Mathewson * are met: 7*e4f24219SNick Mathewson * 1. Redistributions of source code must retain the above copyright 8*e4f24219SNick Mathewson * notice, this list of conditions and the following disclaimer. 9*e4f24219SNick Mathewson * 2. Redistributions in binary form must reproduce the above copyright 10*e4f24219SNick Mathewson * notice, this list of conditions and the following disclaimer in the 11*e4f24219SNick Mathewson * documentation and/or other materials provided with the distribution. 12*e4f24219SNick Mathewson * 4. The name of the author may not be used to endorse or promote products 13*e4f24219SNick Mathewson * derived from this software without specific prior written permission. 14*e4f24219SNick Mathewson * 15*e4f24219SNick Mathewson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*e4f24219SNick Mathewson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*e4f24219SNick Mathewson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*e4f24219SNick Mathewson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*e4f24219SNick Mathewson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*e4f24219SNick Mathewson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*e4f24219SNick Mathewson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*e4f24219SNick Mathewson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*e4f24219SNick Mathewson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*e4f24219SNick Mathewson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*e4f24219SNick Mathewson * 26*e4f24219SNick Mathewson */ 27*e4f24219SNick Mathewson 28*e4f24219SNick Mathewson #include <sys/types.h> 29*e4f24219SNick Mathewson #include <sys/socket.h> 30*e4f24219SNick Mathewson #include <netinet/in.h> 31*e4f24219SNick Mathewson #include <stdlib.h> 32*e4f24219SNick Mathewson #include <errno.h> 33*e4f24219SNick Mathewson 34*e4f24219SNick Mathewson #include <event2/event.h> 35*e4f24219SNick Mathewson #include <event2/bufferevent.h> 36*e4f24219SNick Mathewson #include <event2/buffer.h> 37*e4f24219SNick Mathewson #include <event2/util.h> 38*e4f24219SNick Mathewson 39*e4f24219SNick Mathewson const char *resource = NULL; 40*e4f24219SNick Mathewson struct event_base *base = NULL; 41*e4f24219SNick Mathewson 42*e4f24219SNick Mathewson int total_n_handled = 0; 43*e4f24219SNick Mathewson int total_n_errors = 0; 44*e4f24219SNick Mathewson int total_n_launched = 0; 45*e4f24219SNick Mathewson size_t total_n_bytes = 0; 46*e4f24219SNick Mathewson struct timeval total_time = {0,0}; 47*e4f24219SNick Mathewson int n_errors = 0; 48*e4f24219SNick Mathewson 49*e4f24219SNick Mathewson const int PARALLELISM = 100; 50*e4f24219SNick Mathewson const int N_REQUESTS = 10000; 51*e4f24219SNick Mathewson 52*e4f24219SNick Mathewson struct request_info { 53*e4f24219SNick Mathewson size_t n_read; 54*e4f24219SNick Mathewson struct timeval started; 55*e4f24219SNick Mathewson }; 56*e4f24219SNick Mathewson 57*e4f24219SNick Mathewson static int launch_request(void); 58*e4f24219SNick Mathewson static void readcb(struct bufferevent *b, void *arg); 59*e4f24219SNick Mathewson static void errorcb(struct bufferevent *b, short what, void *arg); 60*e4f24219SNick Mathewson 61*e4f24219SNick Mathewson static void 62*e4f24219SNick Mathewson readcb(struct bufferevent *b, void *arg) 63*e4f24219SNick Mathewson { 64*e4f24219SNick Mathewson struct request_info *ri = arg; 65*e4f24219SNick Mathewson struct evbuffer *input = bufferevent_get_input(b); 66*e4f24219SNick Mathewson size_t n = evbuffer_get_length(input); 67*e4f24219SNick Mathewson 68*e4f24219SNick Mathewson ri->n_read += n; 69*e4f24219SNick Mathewson evbuffer_drain(input, n); 70*e4f24219SNick Mathewson } 71*e4f24219SNick Mathewson 72*e4f24219SNick Mathewson static void 73*e4f24219SNick Mathewson errorcb(struct bufferevent *b, short what, void *arg) 74*e4f24219SNick Mathewson { 75*e4f24219SNick Mathewson struct request_info *ri = arg; 76*e4f24219SNick Mathewson struct timeval now, diff; 77*e4f24219SNick Mathewson if (what & EVBUFFER_EOF) { 78*e4f24219SNick Mathewson ++total_n_handled; 79*e4f24219SNick Mathewson total_n_bytes += ri->n_read; 80*e4f24219SNick Mathewson gettimeofday(&now, NULL); 81*e4f24219SNick Mathewson evutil_timersub(&now, &ri->started, &diff); 82*e4f24219SNick Mathewson evutil_timeradd(&diff, &total_time, &total_time); 83*e4f24219SNick Mathewson 84*e4f24219SNick Mathewson if (total_n_handled && (total_n_handled%1000)==0) 85*e4f24219SNick Mathewson printf("%d requests done\n",total_n_handled); 86*e4f24219SNick Mathewson 87*e4f24219SNick Mathewson if (total_n_launched < N_REQUESTS) { 88*e4f24219SNick Mathewson if (launch_request() < 0) 89*e4f24219SNick Mathewson perror("Can't launch"); 90*e4f24219SNick Mathewson } 91*e4f24219SNick Mathewson } else { 92*e4f24219SNick Mathewson ++total_n_errors; 93*e4f24219SNick Mathewson perror("Unexpected error"); 94*e4f24219SNick Mathewson } 95*e4f24219SNick Mathewson 96*e4f24219SNick Mathewson bufferevent_setcb(b, NULL, NULL, NULL, NULL); 97*e4f24219SNick Mathewson free(ri); 98*e4f24219SNick Mathewson bufferevent_disable(b, EV_READ|EV_WRITE); 99*e4f24219SNick Mathewson bufferevent_free(b); 100*e4f24219SNick Mathewson } 101*e4f24219SNick Mathewson 102*e4f24219SNick Mathewson static int 103*e4f24219SNick Mathewson launch_request(void) 104*e4f24219SNick Mathewson { 105*e4f24219SNick Mathewson int sock; 106*e4f24219SNick Mathewson struct sockaddr_in sin; 107*e4f24219SNick Mathewson struct bufferevent *b; 108*e4f24219SNick Mathewson 109*e4f24219SNick Mathewson struct request_info *ri; 110*e4f24219SNick Mathewson 111*e4f24219SNick Mathewson ++total_n_launched; 112*e4f24219SNick Mathewson 113*e4f24219SNick Mathewson sin.sin_family = AF_INET; 114*e4f24219SNick Mathewson sin.sin_addr.s_addr = htonl(0x7f000001); 115*e4f24219SNick Mathewson sin.sin_port = htons(8080); 116*e4f24219SNick Mathewson if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 117*e4f24219SNick Mathewson return -1; 118*e4f24219SNick Mathewson if (evutil_make_socket_nonblocking(sock) < 0) 119*e4f24219SNick Mathewson return -1; 120*e4f24219SNick Mathewson if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) { 121*e4f24219SNick Mathewson if (errno != EINTR && errno != EINPROGRESS) { 122*e4f24219SNick Mathewson return -1; 123*e4f24219SNick Mathewson } 124*e4f24219SNick Mathewson } 125*e4f24219SNick Mathewson 126*e4f24219SNick Mathewson ri = malloc(sizeof(*ri)); 127*e4f24219SNick Mathewson ri->n_read = 0; 128*e4f24219SNick Mathewson gettimeofday(&ri->started, NULL); 129*e4f24219SNick Mathewson 130*e4f24219SNick Mathewson b = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE); 131*e4f24219SNick Mathewson 132*e4f24219SNick Mathewson bufferevent_setcb(b, readcb, NULL, errorcb, ri); 133*e4f24219SNick Mathewson bufferevent_enable(b, EV_READ|EV_WRITE); 134*e4f24219SNick Mathewson 135*e4f24219SNick Mathewson evbuffer_add_printf(bufferevent_get_output(b), 136*e4f24219SNick Mathewson "GET %s HTTP/1.0\r\n\r\n", resource); 137*e4f24219SNick Mathewson 138*e4f24219SNick Mathewson return 0; 139*e4f24219SNick Mathewson } 140*e4f24219SNick Mathewson 141*e4f24219SNick Mathewson 142*e4f24219SNick Mathewson int 143*e4f24219SNick Mathewson main(int argc, char **argv) 144*e4f24219SNick Mathewson { 145*e4f24219SNick Mathewson int i; 146*e4f24219SNick Mathewson struct timeval start, end, total; 147*e4f24219SNick Mathewson long long usec; 148*e4f24219SNick Mathewson resource = "/ref"; 149*e4f24219SNick Mathewson 150*e4f24219SNick Mathewson setvbuf(stdout, NULL, _IONBF, 0); 151*e4f24219SNick Mathewson 152*e4f24219SNick Mathewson base = event_base_new(); 153*e4f24219SNick Mathewson 154*e4f24219SNick Mathewson for (i=0; i < PARALLELISM; ++i) { 155*e4f24219SNick Mathewson if (launch_request() < 0) 156*e4f24219SNick Mathewson perror("launch"); 157*e4f24219SNick Mathewson } 158*e4f24219SNick Mathewson 159*e4f24219SNick Mathewson gettimeofday(&start, NULL); 160*e4f24219SNick Mathewson 161*e4f24219SNick Mathewson event_base_dispatch(base); 162*e4f24219SNick Mathewson 163*e4f24219SNick Mathewson gettimeofday(&end, NULL); 164*e4f24219SNick Mathewson evutil_timersub(&end, &start, &total); 165*e4f24219SNick Mathewson usec = total_time.tv_sec * 1000000 + total_time.tv_usec; 166*e4f24219SNick Mathewson 167*e4f24219SNick Mathewson printf("\n%d requests in %d.%06d sec.\n" 168*e4f24219SNick Mathewson "Each took about %d usec.\n" 169*e4f24219SNick Mathewson "%lld bytes read. %d errors.\n", 170*e4f24219SNick Mathewson total_n_handled, 171*e4f24219SNick Mathewson (int)total.tv_sec, total.tv_usec, 172*e4f24219SNick Mathewson (int)(usec / total_n_handled), 173*e4f24219SNick Mathewson (long long)total_n_bytes, n_errors); 174*e4f24219SNick Mathewson 175*e4f24219SNick Mathewson return 0; 176*e4f24219SNick Mathewson } 177