1*eabc0478Schristos /* $NetBSD: bench_http.c,v 1.6 2024/08/18 20:47:23 christos Exp $ */ 28585484eSchristos 38585484eSchristos /* 48585484eSchristos * Copyright 2008-2012 Niels Provos and Nick Mathewson 58585484eSchristos * 68585484eSchristos * Redistribution and use in source and binary forms, with or without 78585484eSchristos * modification, are permitted provided that the following conditions 88585484eSchristos * are met: 98585484eSchristos * 1. Redistributions of source code must retain the above copyright 108585484eSchristos * notice, this list of conditions and the following disclaimer. 118585484eSchristos * 2. Redistributions in binary form must reproduce the above copyright 128585484eSchristos * notice, this list of conditions and the following disclaimer in the 138585484eSchristos * documentation and/or other materials provided with the distribution. 148585484eSchristos * 4. The name of the author may not be used to endorse or promote products 158585484eSchristos * derived from this software without specific prior written permission. 168585484eSchristos * 178585484eSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 188585484eSchristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 198585484eSchristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 208585484eSchristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 218585484eSchristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 228585484eSchristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 238585484eSchristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 248585484eSchristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258585484eSchristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 268585484eSchristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278585484eSchristos * 288585484eSchristos */ 298585484eSchristos 308585484eSchristos #include <sys/types.h> 318585484eSchristos #include <sys/stat.h> 328585484eSchristos #ifdef _WIN32 338585484eSchristos #include <winsock2.h> 348585484eSchristos #else 358585484eSchristos #include <sys/socket.h> 368585484eSchristos #include <sys/resource.h> 378585484eSchristos #include <sys/time.h> 388585484eSchristos #include <unistd.h> 398585484eSchristos #endif 408585484eSchristos #include <fcntl.h> 418585484eSchristos #include <signal.h> 428585484eSchristos #include <stdlib.h> 438585484eSchristos #include <stdio.h> 448585484eSchristos #include <string.h> 458585484eSchristos #include <errno.h> 468585484eSchristos 478585484eSchristos #include "event2/event.h" 488585484eSchristos #include "event2/buffer.h" 498585484eSchristos #include "event2/util.h" 508585484eSchristos #include "event2/http.h" 518585484eSchristos #include "event2/thread.h" 528585484eSchristos 538585484eSchristos static void http_basic_cb(struct evhttp_request *req, void *arg); 548585484eSchristos 558585484eSchristos static char *content; 568585484eSchristos static size_t content_len = 0; 578585484eSchristos 588585484eSchristos static void 598585484eSchristos http_basic_cb(struct evhttp_request *req, void *arg) 608585484eSchristos { 618585484eSchristos struct evbuffer *evb = evbuffer_new(); 628585484eSchristos 638585484eSchristos evbuffer_add(evb, content, content_len); 648585484eSchristos 658585484eSchristos /* allow sending of an empty reply */ 668585484eSchristos evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); 678585484eSchristos 688585484eSchristos evbuffer_free(evb); 698585484eSchristos } 708585484eSchristos 718585484eSchristos #if LIBEVENT_VERSION_NUMBER >= 0x02000200 728585484eSchristos static void 738585484eSchristos http_ref_cb(struct evhttp_request *req, void *arg) 748585484eSchristos { 758585484eSchristos struct evbuffer *evb = evbuffer_new(); 768585484eSchristos 778585484eSchristos evbuffer_add_reference(evb, content, content_len, NULL, NULL); 788585484eSchristos 798585484eSchristos /* allow sending of an empty reply */ 808585484eSchristos evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); 818585484eSchristos 828585484eSchristos evbuffer_free(evb); 838585484eSchristos } 848585484eSchristos #endif 858585484eSchristos 868585484eSchristos int 878585484eSchristos main(int argc, char **argv) 888585484eSchristos { 898585484eSchristos struct event_config *cfg = event_config_new(); 908585484eSchristos struct event_base *base; 918585484eSchristos struct evhttp *http; 928585484eSchristos int i; 938585484eSchristos int c; 948585484eSchristos int use_iocp = 0; 95*eabc0478Schristos ev_uint16_t port = 8080; 968585484eSchristos char *endptr = NULL; 978585484eSchristos 988585484eSchristos #ifdef _WIN32 998585484eSchristos WSADATA WSAData; 1008585484eSchristos WSAStartup(0x101, &WSAData); 1018585484eSchristos #else 1028585484eSchristos if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) 1038585484eSchristos return (1); 1048585484eSchristos #endif 1058585484eSchristos 106*eabc0478Schristos setbuf(stdout, NULL); 107*eabc0478Schristos setbuf(stderr, NULL); 108*eabc0478Schristos 1098585484eSchristos for (i = 1; i < argc; ++i) { 1108585484eSchristos if (*argv[i] != '-') 1118585484eSchristos continue; 1128585484eSchristos 1138585484eSchristos c = argv[i][1]; 1148585484eSchristos 1158585484eSchristos if ((c == 'p' || c == 'l') && i + 1 >= argc) { 1168585484eSchristos fprintf(stderr, "-%c requires argument.\n", c); 1178585484eSchristos exit(1); 1188585484eSchristos } 1198585484eSchristos 1208585484eSchristos switch (c) { 1218585484eSchristos case 'p': 1228585484eSchristos if (i+1 >= argc || !argv[i+1]) { 1238585484eSchristos fprintf(stderr, "Missing port\n"); 1248585484eSchristos exit(1); 1258585484eSchristos } 1268585484eSchristos port = (int)strtol(argv[i+1], &endptr, 10); 1278585484eSchristos if (*endptr != '\0') { 1288585484eSchristos fprintf(stderr, "Bad port\n"); 1298585484eSchristos exit(1); 1308585484eSchristos } 1318585484eSchristos break; 1328585484eSchristos case 'l': 1338585484eSchristos if (i+1 >= argc || !argv[i+1]) { 1348585484eSchristos fprintf(stderr, "Missing content length\n"); 1358585484eSchristos exit(1); 1368585484eSchristos } 1378585484eSchristos content_len = (size_t)strtol(argv[i+1], &endptr, 10); 1388585484eSchristos if (*endptr != '\0' || content_len == 0) { 1398585484eSchristos fprintf(stderr, "Bad content length\n"); 1408585484eSchristos exit(1); 1418585484eSchristos } 1428585484eSchristos break; 1438585484eSchristos #ifdef _WIN32 1448585484eSchristos case 'i': 1458585484eSchristos use_iocp = 1; 146*eabc0478Schristos #ifdef EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1478585484eSchristos evthread_use_windows_threads(); 148*eabc0478Schristos #endif 1498585484eSchristos event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP); 1508585484eSchristos break; 1518585484eSchristos #endif 1528585484eSchristos default: 1538585484eSchristos fprintf(stderr, "Illegal argument \"%c\"\n", c); 1548585484eSchristos exit(1); 1558585484eSchristos } 1568585484eSchristos } 1578585484eSchristos 1588585484eSchristos base = event_base_new_with_config(cfg); 1598585484eSchristos if (!base) { 1608585484eSchristos fprintf(stderr, "creating event_base failed. Exiting.\n"); 1618585484eSchristos return 1; 1628585484eSchristos } 1638585484eSchristos 1648585484eSchristos http = evhttp_new(base); 1658585484eSchristos 1668585484eSchristos content = malloc(content_len); 1678585484eSchristos if (content == NULL) { 1688585484eSchristos fprintf(stderr, "Cannot allocate content\n"); 1698585484eSchristos exit(1); 1708585484eSchristos } else { 1718585484eSchristos int i = 0; 1728585484eSchristos for (i = 0; i < (int)content_len; ++i) 1738585484eSchristos content[i] = (i & 255); 1748585484eSchristos } 1758585484eSchristos 1768585484eSchristos evhttp_set_cb(http, "/ind", http_basic_cb, NULL); 1778585484eSchristos fprintf(stderr, "/ind - basic content (memory copy)\n"); 1788585484eSchristos 1798585484eSchristos evhttp_set_cb(http, "/ref", http_ref_cb, NULL); 1808585484eSchristos fprintf(stderr, "/ref - basic content (reference)\n"); 1818585484eSchristos 1828585484eSchristos fprintf(stderr, "Serving %d bytes on port %d using %s\n", 1838585484eSchristos (int)content_len, port, 1848585484eSchristos use_iocp? "IOCP" : event_base_get_method(base)); 1858585484eSchristos 1868585484eSchristos evhttp_bind_socket(http, "0.0.0.0", port); 1878585484eSchristos 188b8ecfcfeSchristos #ifdef _WIN32 1898585484eSchristos if (use_iocp) { 1908585484eSchristos struct timeval tv={99999999,0}; 1918585484eSchristos event_base_loopexit(base, &tv); 1928585484eSchristos } 193b8ecfcfeSchristos #endif 1948585484eSchristos event_base_dispatch(base); 1958585484eSchristos 196b8ecfcfeSchristos #ifdef _WIN32 197b8ecfcfeSchristos WSACleanup(); 198b8ecfcfeSchristos #endif 199b8ecfcfeSchristos 2008585484eSchristos /* NOTREACHED */ 2018585484eSchristos return (0); 2028585484eSchristos } 203