12b15cb3dSCy Schubert /*
22b15cb3dSCy Schubert  * Copyright 2008-2012 Niels Provos and Nick Mathewson
32b15cb3dSCy Schubert  *
42b15cb3dSCy Schubert  * Redistribution and use in source and binary forms, with or without
52b15cb3dSCy Schubert  * modification, are permitted provided that the following conditions
62b15cb3dSCy Schubert  * are met:
72b15cb3dSCy Schubert  * 1. Redistributions of source code must retain the above copyright
82b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer.
92b15cb3dSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
102b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
112b15cb3dSCy Schubert  *    documentation and/or other materials provided with the distribution.
122b15cb3dSCy Schubert  * 4. The name of the author may not be used to endorse or promote products
132b15cb3dSCy Schubert  *    derived from this software without specific prior written permission.
142b15cb3dSCy Schubert  *
152b15cb3dSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
162b15cb3dSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
172b15cb3dSCy Schubert  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
182b15cb3dSCy Schubert  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
192b15cb3dSCy Schubert  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
202b15cb3dSCy Schubert  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
212b15cb3dSCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
222b15cb3dSCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
232b15cb3dSCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
242b15cb3dSCy Schubert  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252b15cb3dSCy Schubert  *
262b15cb3dSCy Schubert  */
272b15cb3dSCy Schubert 
282b15cb3dSCy Schubert #include <sys/types.h>
292b15cb3dSCy Schubert #include <sys/stat.h>
302b15cb3dSCy Schubert #ifdef _WIN32
312b15cb3dSCy Schubert #include <winsock2.h>
322b15cb3dSCy Schubert #else
332b15cb3dSCy Schubert #include <sys/socket.h>
342b15cb3dSCy Schubert #include <sys/resource.h>
352b15cb3dSCy Schubert #include <sys/time.h>
362b15cb3dSCy Schubert #include <unistd.h>
372b15cb3dSCy Schubert #endif
382b15cb3dSCy Schubert #include <fcntl.h>
392b15cb3dSCy Schubert #include <signal.h>
402b15cb3dSCy Schubert #include <stdlib.h>
412b15cb3dSCy Schubert #include <stdio.h>
422b15cb3dSCy Schubert #include <string.h>
432b15cb3dSCy Schubert #include <errno.h>
442b15cb3dSCy Schubert 
452b15cb3dSCy Schubert #include "event2/event.h"
462b15cb3dSCy Schubert #include "event2/buffer.h"
472b15cb3dSCy Schubert #include "event2/util.h"
482b15cb3dSCy Schubert #include "event2/http.h"
492b15cb3dSCy Schubert #include "event2/thread.h"
502b15cb3dSCy Schubert 
512b15cb3dSCy Schubert static void http_basic_cb(struct evhttp_request *req, void *arg);
522b15cb3dSCy Schubert 
532b15cb3dSCy Schubert static char *content;
542b15cb3dSCy Schubert static size_t content_len = 0;
552b15cb3dSCy Schubert 
562b15cb3dSCy Schubert static void
http_basic_cb(struct evhttp_request * req,void * arg)572b15cb3dSCy Schubert http_basic_cb(struct evhttp_request *req, void *arg)
582b15cb3dSCy Schubert {
592b15cb3dSCy Schubert 	struct evbuffer *evb = evbuffer_new();
602b15cb3dSCy Schubert 
612b15cb3dSCy Schubert 	evbuffer_add(evb, content, content_len);
622b15cb3dSCy Schubert 
632b15cb3dSCy Schubert 	/* allow sending of an empty reply */
642b15cb3dSCy Schubert 	evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
652b15cb3dSCy Schubert 
662b15cb3dSCy Schubert 	evbuffer_free(evb);
672b15cb3dSCy Schubert }
682b15cb3dSCy Schubert 
692b15cb3dSCy Schubert #if LIBEVENT_VERSION_NUMBER >= 0x02000200
702b15cb3dSCy Schubert static void
http_ref_cb(struct evhttp_request * req,void * arg)712b15cb3dSCy Schubert http_ref_cb(struct evhttp_request *req, void *arg)
722b15cb3dSCy Schubert {
732b15cb3dSCy Schubert 	struct evbuffer *evb = evbuffer_new();
742b15cb3dSCy Schubert 
752b15cb3dSCy Schubert 	evbuffer_add_reference(evb, content, content_len, NULL, NULL);
762b15cb3dSCy Schubert 
772b15cb3dSCy Schubert 	/* allow sending of an empty reply */
782b15cb3dSCy Schubert 	evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
792b15cb3dSCy Schubert 
802b15cb3dSCy Schubert 	evbuffer_free(evb);
812b15cb3dSCy Schubert }
822b15cb3dSCy Schubert #endif
832b15cb3dSCy Schubert 
842b15cb3dSCy Schubert int
main(int argc,char ** argv)852b15cb3dSCy Schubert main(int argc, char **argv)
862b15cb3dSCy Schubert {
872b15cb3dSCy Schubert 	struct event_config *cfg = event_config_new();
882b15cb3dSCy Schubert 	struct event_base *base;
892b15cb3dSCy Schubert 	struct evhttp *http;
902b15cb3dSCy Schubert 	int i;
912b15cb3dSCy Schubert 	int c;
922b15cb3dSCy Schubert 	int use_iocp = 0;
93*a466cc55SCy Schubert 	ev_uint16_t port = 8080;
942b15cb3dSCy Schubert 	char *endptr = NULL;
952b15cb3dSCy Schubert 
962b15cb3dSCy Schubert #ifdef _WIN32
972b15cb3dSCy Schubert 	WSADATA WSAData;
982b15cb3dSCy Schubert 	WSAStartup(0x101, &WSAData);
992b15cb3dSCy Schubert #else
1002b15cb3dSCy Schubert 	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1012b15cb3dSCy Schubert 		return (1);
1022b15cb3dSCy Schubert #endif
1032b15cb3dSCy Schubert 
104*a466cc55SCy Schubert 	setbuf(stdout, NULL);
105*a466cc55SCy Schubert 	setbuf(stderr, NULL);
106*a466cc55SCy Schubert 
1072b15cb3dSCy Schubert 	for (i = 1; i < argc; ++i) {
1082b15cb3dSCy Schubert 		if (*argv[i] != '-')
1092b15cb3dSCy Schubert 			continue;
1102b15cb3dSCy Schubert 
1112b15cb3dSCy Schubert 		c = argv[i][1];
1122b15cb3dSCy Schubert 
1132b15cb3dSCy Schubert 		if ((c == 'p' || c == 'l') && i + 1 >= argc) {
1142b15cb3dSCy Schubert 			fprintf(stderr, "-%c requires argument.\n", c);
1152b15cb3dSCy Schubert 			exit(1);
1162b15cb3dSCy Schubert 		}
1172b15cb3dSCy Schubert 
1182b15cb3dSCy Schubert 		switch (c) {
1192b15cb3dSCy Schubert 		case 'p':
1202b15cb3dSCy Schubert 			if (i+1 >= argc || !argv[i+1]) {
1212b15cb3dSCy Schubert 				fprintf(stderr, "Missing port\n");
1222b15cb3dSCy Schubert 				exit(1);
1232b15cb3dSCy Schubert 			}
1242b15cb3dSCy Schubert 			port = (int)strtol(argv[i+1], &endptr, 10);
1252b15cb3dSCy Schubert 			if (*endptr != '\0') {
1262b15cb3dSCy Schubert 				fprintf(stderr, "Bad port\n");
1272b15cb3dSCy Schubert 				exit(1);
1282b15cb3dSCy Schubert 			}
1292b15cb3dSCy Schubert 			break;
1302b15cb3dSCy Schubert 		case 'l':
1312b15cb3dSCy Schubert 			if (i+1 >= argc || !argv[i+1]) {
1322b15cb3dSCy Schubert 				fprintf(stderr, "Missing content length\n");
1332b15cb3dSCy Schubert 				exit(1);
1342b15cb3dSCy Schubert 			}
1352b15cb3dSCy Schubert 			content_len = (size_t)strtol(argv[i+1], &endptr, 10);
1362b15cb3dSCy Schubert 			if (*endptr != '\0' || content_len == 0) {
1372b15cb3dSCy Schubert 				fprintf(stderr, "Bad content length\n");
1382b15cb3dSCy Schubert 				exit(1);
1392b15cb3dSCy Schubert 			}
1402b15cb3dSCy Schubert 			break;
1412b15cb3dSCy Schubert #ifdef _WIN32
1422b15cb3dSCy Schubert 		case 'i':
1432b15cb3dSCy Schubert 			use_iocp = 1;
144*a466cc55SCy Schubert #ifdef EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
1452b15cb3dSCy Schubert 			evthread_use_windows_threads();
146*a466cc55SCy Schubert #endif
1472b15cb3dSCy Schubert 			event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP);
1482b15cb3dSCy Schubert 			break;
1492b15cb3dSCy Schubert #endif
1502b15cb3dSCy Schubert 		default:
1512b15cb3dSCy Schubert 			fprintf(stderr, "Illegal argument \"%c\"\n", c);
1522b15cb3dSCy Schubert 			exit(1);
1532b15cb3dSCy Schubert 		}
1542b15cb3dSCy Schubert 	}
1552b15cb3dSCy Schubert 
1562b15cb3dSCy Schubert 	base = event_base_new_with_config(cfg);
1572b15cb3dSCy Schubert 	if (!base) {
1582b15cb3dSCy Schubert 		fprintf(stderr, "creating event_base failed. Exiting.\n");
1592b15cb3dSCy Schubert 		return 1;
1602b15cb3dSCy Schubert 	}
1612b15cb3dSCy Schubert 
1622b15cb3dSCy Schubert 	http = evhttp_new(base);
1632b15cb3dSCy Schubert 
1642b15cb3dSCy Schubert 	content = malloc(content_len);
1652b15cb3dSCy Schubert 	if (content == NULL) {
1662b15cb3dSCy Schubert 		fprintf(stderr, "Cannot allocate content\n");
1672b15cb3dSCy Schubert 		exit(1);
1682b15cb3dSCy Schubert 	} else {
1692b15cb3dSCy Schubert 		int i = 0;
1702b15cb3dSCy Schubert 		for (i = 0; i < (int)content_len; ++i)
1712b15cb3dSCy Schubert 			content[i] = (i & 255);
1722b15cb3dSCy Schubert 	}
1732b15cb3dSCy Schubert 
1742b15cb3dSCy Schubert 	evhttp_set_cb(http, "/ind", http_basic_cb, NULL);
1752b15cb3dSCy Schubert 	fprintf(stderr, "/ind - basic content (memory copy)\n");
1762b15cb3dSCy Schubert 
1772b15cb3dSCy Schubert 	evhttp_set_cb(http, "/ref", http_ref_cb, NULL);
1782b15cb3dSCy Schubert 	fprintf(stderr, "/ref - basic content (reference)\n");
1792b15cb3dSCy Schubert 
1802b15cb3dSCy Schubert 	fprintf(stderr, "Serving %d bytes on port %d using %s\n",
1812b15cb3dSCy Schubert 	    (int)content_len, port,
1822b15cb3dSCy Schubert 	    use_iocp? "IOCP" : event_base_get_method(base));
1832b15cb3dSCy Schubert 
1842b15cb3dSCy Schubert 	evhttp_bind_socket(http, "0.0.0.0", port);
1852b15cb3dSCy Schubert 
1862b15cb3dSCy Schubert #ifdef _WIN32
1872b15cb3dSCy Schubert 	if (use_iocp) {
1882b15cb3dSCy Schubert 		struct timeval tv={99999999,0};
1892b15cb3dSCy Schubert 		event_base_loopexit(base, &tv);
1902b15cb3dSCy Schubert 	}
1912b15cb3dSCy Schubert #endif
1922b15cb3dSCy Schubert 	event_base_dispatch(base);
1932b15cb3dSCy Schubert 
1942b15cb3dSCy Schubert #ifdef _WIN32
1952b15cb3dSCy Schubert 	WSACleanup();
1962b15cb3dSCy Schubert #endif
1972b15cb3dSCy Schubert 
1982b15cb3dSCy Schubert 	/* NOTREACHED */
1992b15cb3dSCy Schubert 	return (0);
2002b15cb3dSCy Schubert }
201