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