1275970Scy/* 2275970Scy * Copyright 2008-2012 Niels Provos and Nick Mathewson 3275970Scy * 4275970Scy * Redistribution and use in source and binary forms, with or without 5275970Scy * modification, are permitted provided that the following conditions 6275970Scy * are met: 7275970Scy * 1. Redistributions of source code must retain the above copyright 8275970Scy * notice, this list of conditions and the following disclaimer. 9275970Scy * 2. Redistributions in binary form must reproduce the above copyright 10275970Scy * notice, this list of conditions and the following disclaimer in the 11275970Scy * documentation and/or other materials provided with the distribution. 12275970Scy * 4. The name of the author may not be used to endorse or promote products 13275970Scy * derived from this software without specific prior written permission. 14275970Scy * 15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25275970Scy * 26275970Scy */ 27275970Scy 28275970Scy#include <sys/types.h> 29275970Scy#include <sys/stat.h> 30275970Scy#ifdef _WIN32 31275970Scy#include <winsock2.h> 32275970Scy#else 33275970Scy#include <sys/socket.h> 34275970Scy#include <sys/resource.h> 35275970Scy#include <sys/time.h> 36275970Scy#include <unistd.h> 37275970Scy#endif 38275970Scy#include <fcntl.h> 39275970Scy#include <signal.h> 40275970Scy#include <stdlib.h> 41275970Scy#include <stdio.h> 42275970Scy#include <string.h> 43275970Scy#include <errno.h> 44275970Scy 45275970Scy#include "event2/event.h" 46275970Scy#include "event2/buffer.h" 47275970Scy#include "event2/util.h" 48275970Scy#include "event2/http.h" 49275970Scy#include "event2/thread.h" 50275970Scy 51275970Scystatic void http_basic_cb(struct evhttp_request *req, void *arg); 52275970Scy 53275970Scystatic char *content; 54275970Scystatic size_t content_len = 0; 55275970Scy 56275970Scystatic void 57275970Scyhttp_basic_cb(struct evhttp_request *req, void *arg) 58275970Scy{ 59275970Scy struct evbuffer *evb = evbuffer_new(); 60275970Scy 61275970Scy evbuffer_add(evb, content, content_len); 62275970Scy 63275970Scy /* allow sending of an empty reply */ 64275970Scy evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); 65275970Scy 66275970Scy evbuffer_free(evb); 67275970Scy} 68275970Scy 69275970Scy#if LIBEVENT_VERSION_NUMBER >= 0x02000200 70275970Scystatic void 71275970Scyhttp_ref_cb(struct evhttp_request *req, void *arg) 72275970Scy{ 73275970Scy struct evbuffer *evb = evbuffer_new(); 74275970Scy 75275970Scy evbuffer_add_reference(evb, content, content_len, NULL, NULL); 76275970Scy 77275970Scy /* allow sending of an empty reply */ 78275970Scy evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); 79275970Scy 80275970Scy evbuffer_free(evb); 81275970Scy} 82275970Scy#endif 83275970Scy 84275970Scyint 85275970Scymain(int argc, char **argv) 86275970Scy{ 87275970Scy struct event_config *cfg = event_config_new(); 88275970Scy struct event_base *base; 89275970Scy struct evhttp *http; 90275970Scy int i; 91275970Scy int c; 92275970Scy int use_iocp = 0; 93275970Scy unsigned short port = 8080; 94275970Scy char *endptr = NULL; 95275970Scy 96275970Scy#ifdef _WIN32 97275970Scy WSADATA WSAData; 98275970Scy WSAStartup(0x101, &WSAData); 99275970Scy#else 100275970Scy if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) 101275970Scy return (1); 102275970Scy#endif 103275970Scy 104275970Scy for (i = 1; i < argc; ++i) { 105275970Scy if (*argv[i] != '-') 106275970Scy continue; 107275970Scy 108275970Scy c = argv[i][1]; 109275970Scy 110275970Scy if ((c == 'p' || c == 'l') && i + 1 >= argc) { 111275970Scy fprintf(stderr, "-%c requires argument.\n", c); 112275970Scy exit(1); 113275970Scy } 114275970Scy 115275970Scy switch (c) { 116275970Scy case 'p': 117275970Scy if (i+1 >= argc || !argv[i+1]) { 118275970Scy fprintf(stderr, "Missing port\n"); 119275970Scy exit(1); 120275970Scy } 121275970Scy port = (int)strtol(argv[i+1], &endptr, 10); 122275970Scy if (*endptr != '\0') { 123275970Scy fprintf(stderr, "Bad port\n"); 124275970Scy exit(1); 125275970Scy } 126275970Scy break; 127275970Scy case 'l': 128275970Scy if (i+1 >= argc || !argv[i+1]) { 129275970Scy fprintf(stderr, "Missing content length\n"); 130275970Scy exit(1); 131275970Scy } 132275970Scy content_len = (size_t)strtol(argv[i+1], &endptr, 10); 133275970Scy if (*endptr != '\0' || content_len == 0) { 134275970Scy fprintf(stderr, "Bad content length\n"); 135275970Scy exit(1); 136275970Scy } 137275970Scy break; 138275970Scy#ifdef _WIN32 139275970Scy case 'i': 140275970Scy use_iocp = 1; 141275970Scy evthread_use_windows_threads(); 142275970Scy event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP); 143275970Scy break; 144275970Scy#endif 145275970Scy default: 146275970Scy fprintf(stderr, "Illegal argument \"%c\"\n", c); 147275970Scy exit(1); 148275970Scy } 149275970Scy } 150275970Scy 151275970Scy base = event_base_new_with_config(cfg); 152275970Scy if (!base) { 153275970Scy fprintf(stderr, "creating event_base failed. Exiting.\n"); 154275970Scy return 1; 155275970Scy } 156275970Scy 157275970Scy http = evhttp_new(base); 158275970Scy 159275970Scy content = malloc(content_len); 160275970Scy if (content == NULL) { 161275970Scy fprintf(stderr, "Cannot allocate content\n"); 162275970Scy exit(1); 163275970Scy } else { 164275970Scy int i = 0; 165275970Scy for (i = 0; i < (int)content_len; ++i) 166275970Scy content[i] = (i & 255); 167275970Scy } 168275970Scy 169275970Scy evhttp_set_cb(http, "/ind", http_basic_cb, NULL); 170275970Scy fprintf(stderr, "/ind - basic content (memory copy)\n"); 171275970Scy 172275970Scy evhttp_set_cb(http, "/ref", http_ref_cb, NULL); 173275970Scy fprintf(stderr, "/ref - basic content (reference)\n"); 174275970Scy 175275970Scy fprintf(stderr, "Serving %d bytes on port %d using %s\n", 176275970Scy (int)content_len, port, 177275970Scy use_iocp? "IOCP" : event_base_get_method(base)); 178275970Scy 179275970Scy evhttp_bind_socket(http, "0.0.0.0", port); 180275970Scy 181275970Scy#ifdef _WIN32 182275970Scy if (use_iocp) { 183275970Scy struct timeval tv={99999999,0}; 184275970Scy event_base_loopexit(base, &tv); 185275970Scy } 186275970Scy#endif 187275970Scy event_base_dispatch(base); 188275970Scy 189275970Scy#ifdef _WIN32 190275970Scy WSACleanup(); 191275970Scy#endif 192275970Scy 193275970Scy /* NOTREACHED */ 194275970Scy return (0); 195275970Scy} 196