xref: /freebsd/contrib/libevent/test/bench_http.c (revision b50261e21f39a6c7249a49e7b60aa878c98512a8)
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