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