1*2b15cb3dSCy Schubert /* 2*2b15cb3dSCy Schubert * Copyright 2008-2012 Niels Provos and Nick Mathewson 3*2b15cb3dSCy Schubert * 4*2b15cb3dSCy Schubert * Redistribution and use in source and binary forms, with or without 5*2b15cb3dSCy Schubert * modification, are permitted provided that the following conditions 6*2b15cb3dSCy Schubert * are met: 7*2b15cb3dSCy Schubert * 1. Redistributions of source code must retain the above copyright 8*2b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer. 9*2b15cb3dSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 10*2b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer in the 11*2b15cb3dSCy Schubert * documentation and/or other materials provided with the distribution. 12*2b15cb3dSCy Schubert * 4. The name of the author may not be used to endorse or promote products 13*2b15cb3dSCy Schubert * derived from this software without specific prior written permission. 14*2b15cb3dSCy Schubert * 15*2b15cb3dSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*2b15cb3dSCy Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*2b15cb3dSCy Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*2b15cb3dSCy Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*2b15cb3dSCy Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*2b15cb3dSCy Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*2b15cb3dSCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*2b15cb3dSCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*2b15cb3dSCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*2b15cb3dSCy Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*2b15cb3dSCy Schubert * 26*2b15cb3dSCy Schubert */ 27*2b15cb3dSCy Schubert 28*2b15cb3dSCy Schubert #include <sys/types.h> 29*2b15cb3dSCy Schubert #include <sys/stat.h> 30*2b15cb3dSCy Schubert #ifdef _WIN32 31*2b15cb3dSCy Schubert #include <winsock2.h> 32*2b15cb3dSCy Schubert #else 33*2b15cb3dSCy Schubert #include <sys/socket.h> 34*2b15cb3dSCy Schubert #include <sys/resource.h> 35*2b15cb3dSCy Schubert #include <sys/time.h> 36*2b15cb3dSCy Schubert #include <unistd.h> 37*2b15cb3dSCy Schubert #endif 38*2b15cb3dSCy Schubert #include <fcntl.h> 39*2b15cb3dSCy Schubert #include <signal.h> 40*2b15cb3dSCy Schubert #include <stdlib.h> 41*2b15cb3dSCy Schubert #include <stdio.h> 42*2b15cb3dSCy Schubert #include <string.h> 43*2b15cb3dSCy Schubert #include <errno.h> 44*2b15cb3dSCy Schubert 45*2b15cb3dSCy Schubert #include "event2/event.h" 46*2b15cb3dSCy Schubert #include "event2/buffer.h" 47*2b15cb3dSCy Schubert #include "event2/util.h" 48*2b15cb3dSCy Schubert #include "event2/http.h" 49*2b15cb3dSCy Schubert #include "event2/thread.h" 50*2b15cb3dSCy Schubert 51*2b15cb3dSCy Schubert static void http_basic_cb(struct evhttp_request *req, void *arg); 52*2b15cb3dSCy Schubert 53*2b15cb3dSCy Schubert static char *content; 54*2b15cb3dSCy Schubert static size_t content_len = 0; 55*2b15cb3dSCy Schubert 56*2b15cb3dSCy Schubert static void 57*2b15cb3dSCy Schubert http_basic_cb(struct evhttp_request *req, void *arg) 58*2b15cb3dSCy Schubert { 59*2b15cb3dSCy Schubert struct evbuffer *evb = evbuffer_new(); 60*2b15cb3dSCy Schubert 61*2b15cb3dSCy Schubert evbuffer_add(evb, content, content_len); 62*2b15cb3dSCy Schubert 63*2b15cb3dSCy Schubert /* allow sending of an empty reply */ 64*2b15cb3dSCy Schubert evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); 65*2b15cb3dSCy Schubert 66*2b15cb3dSCy Schubert evbuffer_free(evb); 67*2b15cb3dSCy Schubert } 68*2b15cb3dSCy Schubert 69*2b15cb3dSCy Schubert #if LIBEVENT_VERSION_NUMBER >= 0x02000200 70*2b15cb3dSCy Schubert static void 71*2b15cb3dSCy Schubert http_ref_cb(struct evhttp_request *req, void *arg) 72*2b15cb3dSCy Schubert { 73*2b15cb3dSCy Schubert struct evbuffer *evb = evbuffer_new(); 74*2b15cb3dSCy Schubert 75*2b15cb3dSCy Schubert evbuffer_add_reference(evb, content, content_len, NULL, NULL); 76*2b15cb3dSCy Schubert 77*2b15cb3dSCy Schubert /* allow sending of an empty reply */ 78*2b15cb3dSCy Schubert evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); 79*2b15cb3dSCy Schubert 80*2b15cb3dSCy Schubert evbuffer_free(evb); 81*2b15cb3dSCy Schubert } 82*2b15cb3dSCy Schubert #endif 83*2b15cb3dSCy Schubert 84*2b15cb3dSCy Schubert int 85*2b15cb3dSCy Schubert main(int argc, char **argv) 86*2b15cb3dSCy Schubert { 87*2b15cb3dSCy Schubert struct event_config *cfg = event_config_new(); 88*2b15cb3dSCy Schubert struct event_base *base; 89*2b15cb3dSCy Schubert struct evhttp *http; 90*2b15cb3dSCy Schubert int i; 91*2b15cb3dSCy Schubert int c; 92*2b15cb3dSCy Schubert int use_iocp = 0; 93*2b15cb3dSCy Schubert unsigned short port = 8080; 94*2b15cb3dSCy Schubert char *endptr = NULL; 95*2b15cb3dSCy Schubert 96*2b15cb3dSCy Schubert #ifdef _WIN32 97*2b15cb3dSCy Schubert WSADATA WSAData; 98*2b15cb3dSCy Schubert WSAStartup(0x101, &WSAData); 99*2b15cb3dSCy Schubert #else 100*2b15cb3dSCy Schubert if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) 101*2b15cb3dSCy Schubert return (1); 102*2b15cb3dSCy Schubert #endif 103*2b15cb3dSCy Schubert 104*2b15cb3dSCy Schubert for (i = 1; i < argc; ++i) { 105*2b15cb3dSCy Schubert if (*argv[i] != '-') 106*2b15cb3dSCy Schubert continue; 107*2b15cb3dSCy Schubert 108*2b15cb3dSCy Schubert c = argv[i][1]; 109*2b15cb3dSCy Schubert 110*2b15cb3dSCy Schubert if ((c == 'p' || c == 'l') && i + 1 >= argc) { 111*2b15cb3dSCy Schubert fprintf(stderr, "-%c requires argument.\n", c); 112*2b15cb3dSCy Schubert exit(1); 113*2b15cb3dSCy Schubert } 114*2b15cb3dSCy Schubert 115*2b15cb3dSCy Schubert switch (c) { 116*2b15cb3dSCy Schubert case 'p': 117*2b15cb3dSCy Schubert if (i+1 >= argc || !argv[i+1]) { 118*2b15cb3dSCy Schubert fprintf(stderr, "Missing port\n"); 119*2b15cb3dSCy Schubert exit(1); 120*2b15cb3dSCy Schubert } 121*2b15cb3dSCy Schubert port = (int)strtol(argv[i+1], &endptr, 10); 122*2b15cb3dSCy Schubert if (*endptr != '\0') { 123*2b15cb3dSCy Schubert fprintf(stderr, "Bad port\n"); 124*2b15cb3dSCy Schubert exit(1); 125*2b15cb3dSCy Schubert } 126*2b15cb3dSCy Schubert break; 127*2b15cb3dSCy Schubert case 'l': 128*2b15cb3dSCy Schubert if (i+1 >= argc || !argv[i+1]) { 129*2b15cb3dSCy Schubert fprintf(stderr, "Missing content length\n"); 130*2b15cb3dSCy Schubert exit(1); 131*2b15cb3dSCy Schubert } 132*2b15cb3dSCy Schubert content_len = (size_t)strtol(argv[i+1], &endptr, 10); 133*2b15cb3dSCy Schubert if (*endptr != '\0' || content_len == 0) { 134*2b15cb3dSCy Schubert fprintf(stderr, "Bad content length\n"); 135*2b15cb3dSCy Schubert exit(1); 136*2b15cb3dSCy Schubert } 137*2b15cb3dSCy Schubert break; 138*2b15cb3dSCy Schubert #ifdef _WIN32 139*2b15cb3dSCy Schubert case 'i': 140*2b15cb3dSCy Schubert use_iocp = 1; 141*2b15cb3dSCy Schubert evthread_use_windows_threads(); 142*2b15cb3dSCy Schubert event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP); 143*2b15cb3dSCy Schubert break; 144*2b15cb3dSCy Schubert #endif 145*2b15cb3dSCy Schubert default: 146*2b15cb3dSCy Schubert fprintf(stderr, "Illegal argument \"%c\"\n", c); 147*2b15cb3dSCy Schubert exit(1); 148*2b15cb3dSCy Schubert } 149*2b15cb3dSCy Schubert } 150*2b15cb3dSCy Schubert 151*2b15cb3dSCy Schubert base = event_base_new_with_config(cfg); 152*2b15cb3dSCy Schubert if (!base) { 153*2b15cb3dSCy Schubert fprintf(stderr, "creating event_base failed. Exiting.\n"); 154*2b15cb3dSCy Schubert return 1; 155*2b15cb3dSCy Schubert } 156*2b15cb3dSCy Schubert 157*2b15cb3dSCy Schubert http = evhttp_new(base); 158*2b15cb3dSCy Schubert 159*2b15cb3dSCy Schubert content = malloc(content_len); 160*2b15cb3dSCy Schubert if (content == NULL) { 161*2b15cb3dSCy Schubert fprintf(stderr, "Cannot allocate content\n"); 162*2b15cb3dSCy Schubert exit(1); 163*2b15cb3dSCy Schubert } else { 164*2b15cb3dSCy Schubert int i = 0; 165*2b15cb3dSCy Schubert for (i = 0; i < (int)content_len; ++i) 166*2b15cb3dSCy Schubert content[i] = (i & 255); 167*2b15cb3dSCy Schubert } 168*2b15cb3dSCy Schubert 169*2b15cb3dSCy Schubert evhttp_set_cb(http, "/ind", http_basic_cb, NULL); 170*2b15cb3dSCy Schubert fprintf(stderr, "/ind - basic content (memory copy)\n"); 171*2b15cb3dSCy Schubert 172*2b15cb3dSCy Schubert evhttp_set_cb(http, "/ref", http_ref_cb, NULL); 173*2b15cb3dSCy Schubert fprintf(stderr, "/ref - basic content (reference)\n"); 174*2b15cb3dSCy Schubert 175*2b15cb3dSCy Schubert fprintf(stderr, "Serving %d bytes on port %d using %s\n", 176*2b15cb3dSCy Schubert (int)content_len, port, 177*2b15cb3dSCy Schubert use_iocp? "IOCP" : event_base_get_method(base)); 178*2b15cb3dSCy Schubert 179*2b15cb3dSCy Schubert evhttp_bind_socket(http, "0.0.0.0", port); 180*2b15cb3dSCy Schubert 181*2b15cb3dSCy Schubert #ifdef _WIN32 182*2b15cb3dSCy Schubert if (use_iocp) { 183*2b15cb3dSCy Schubert struct timeval tv={99999999,0}; 184*2b15cb3dSCy Schubert event_base_loopexit(base, &tv); 185*2b15cb3dSCy Schubert } 186*2b15cb3dSCy Schubert #endif 187*2b15cb3dSCy Schubert event_base_dispatch(base); 188*2b15cb3dSCy Schubert 189*2b15cb3dSCy Schubert #ifdef _WIN32 190*2b15cb3dSCy Schubert WSACleanup(); 191*2b15cb3dSCy Schubert #endif 192*2b15cb3dSCy Schubert 193*2b15cb3dSCy Schubert /* NOTREACHED */ 194*2b15cb3dSCy Schubert return (0); 195*2b15cb3dSCy Schubert } 196