1214501Srpaulo/*
2214501Srpaulo * http_server - HTTP server
3214501Srpaulo * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4214501Srpaulo *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7214501Srpaulo */
8214501Srpaulo
9214501Srpaulo#include "includes.h"
10214501Srpaulo#include <fcntl.h>
11214501Srpaulo
12214501Srpaulo#include "common.h"
13214501Srpaulo#include "eloop.h"
14214501Srpaulo#include "httpread.h"
15214501Srpaulo#include "http_server.h"
16214501Srpaulo
17214501Srpaulo#define HTTP_SERVER_TIMEOUT 30
18214501Srpaulo#define HTTP_SERVER_MAX_REQ_LEN 8000
19214501Srpaulo#define HTTP_SERVER_MAX_CONNECTIONS 10
20214501Srpaulo
21214501Srpaulostruct http_request {
22214501Srpaulo	struct http_request *next;
23214501Srpaulo	struct http_server *srv;
24214501Srpaulo	int fd;
25214501Srpaulo	struct sockaddr_in cli;
26214501Srpaulo	struct httpread *hread;
27214501Srpaulo};
28214501Srpaulo
29214501Srpaulostruct http_server {
30214501Srpaulo	void (*cb)(void *ctx, struct http_request *req);
31214501Srpaulo	void *cb_ctx;
32214501Srpaulo
33214501Srpaulo	int fd;
34214501Srpaulo	int port;
35214501Srpaulo
36214501Srpaulo	struct http_request *requests;
37214501Srpaulo	unsigned int request_count;
38214501Srpaulo};
39214501Srpaulo
40214501Srpaulo
41214501Srpaulostatic void http_request_cb(struct httpread *handle, void *cookie,
42214501Srpaulo			    enum httpread_event en)
43214501Srpaulo{
44214501Srpaulo	struct http_request *req = cookie;
45214501Srpaulo	struct http_server *srv = req->srv;
46214501Srpaulo
47214501Srpaulo	if (en == HTTPREAD_EVENT_FILE_READY) {
48214501Srpaulo		wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received",
49214501Srpaulo			   inet_ntoa(req->cli.sin_addr),
50214501Srpaulo			   ntohs(req->cli.sin_port));
51214501Srpaulo		srv->cb(srv->cb_ctx, req);
52214501Srpaulo		return;
53214501Srpaulo	}
54214501Srpaulo	wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received "
55214501Srpaulo		   "completely", inet_ntoa(req->cli.sin_addr),
56214501Srpaulo		   ntohs(req->cli.sin_port));
57214501Srpaulo	http_request_deinit(req);
58214501Srpaulo}
59214501Srpaulo
60214501Srpaulo
61214501Srpaulostatic struct http_request * http_request_init(struct http_server *srv, int fd,
62214501Srpaulo					       struct sockaddr_in *cli)
63214501Srpaulo{
64214501Srpaulo	struct http_request *req;
65214501Srpaulo
66214501Srpaulo	if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) {
67214501Srpaulo		wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests");
68214501Srpaulo		return NULL;
69214501Srpaulo	}
70214501Srpaulo
71214501Srpaulo	req = os_zalloc(sizeof(*req));
72214501Srpaulo	if (req == NULL)
73214501Srpaulo		return NULL;
74214501Srpaulo
75214501Srpaulo	req->srv = srv;
76214501Srpaulo	req->fd = fd;
77214501Srpaulo	req->cli = *cli;
78214501Srpaulo
79214501Srpaulo	req->hread = httpread_create(req->fd, http_request_cb, req,
80214501Srpaulo				     HTTP_SERVER_MAX_REQ_LEN,
81214501Srpaulo				     HTTP_SERVER_TIMEOUT);
82214501Srpaulo	if (req->hread == NULL) {
83214501Srpaulo		http_request_deinit(req);
84214501Srpaulo		return NULL;
85214501Srpaulo	}
86214501Srpaulo
87214501Srpaulo	return req;
88214501Srpaulo}
89214501Srpaulo
90214501Srpaulo
91214501Srpaulovoid http_request_deinit(struct http_request *req)
92214501Srpaulo{
93214501Srpaulo	struct http_request *r, *p;
94214501Srpaulo	struct http_server *srv;
95214501Srpaulo
96214501Srpaulo	if (req == NULL)
97214501Srpaulo		return;
98214501Srpaulo
99214501Srpaulo	srv = req->srv;
100214501Srpaulo	p = NULL;
101214501Srpaulo	r = srv->requests;
102214501Srpaulo	while (r) {
103214501Srpaulo		if (r == req) {
104214501Srpaulo			if (p)
105214501Srpaulo				p->next = r->next;
106214501Srpaulo			else
107214501Srpaulo				srv->requests = r->next;
108214501Srpaulo			srv->request_count--;
109214501Srpaulo			break;
110214501Srpaulo		}
111214501Srpaulo		p = r;
112214501Srpaulo		r = r->next;
113214501Srpaulo	}
114214501Srpaulo
115214501Srpaulo	httpread_destroy(req->hread);
116214501Srpaulo	close(req->fd);
117214501Srpaulo	os_free(req);
118214501Srpaulo}
119214501Srpaulo
120214501Srpaulo
121214501Srpaulostatic void http_request_free_all(struct http_request *req)
122214501Srpaulo{
123214501Srpaulo	struct http_request *prev;
124214501Srpaulo	while (req) {
125214501Srpaulo		prev = req;
126214501Srpaulo		req = req->next;
127214501Srpaulo		http_request_deinit(prev);
128214501Srpaulo	}
129214501Srpaulo}
130214501Srpaulo
131214501Srpaulo
132214501Srpaulovoid http_request_send(struct http_request *req, struct wpabuf *resp)
133214501Srpaulo{
134214501Srpaulo	int res;
135214501Srpaulo
136214501Srpaulo	wpa_printf(MSG_DEBUG, "HTTP: Send %lu byte response to %s:%d",
137214501Srpaulo		   (unsigned long) wpabuf_len(resp),
138214501Srpaulo		   inet_ntoa(req->cli.sin_addr),
139214501Srpaulo		   ntohs(req->cli.sin_port));
140214501Srpaulo
141214501Srpaulo	res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0);
142214501Srpaulo	if (res < 0) {
143214501Srpaulo		wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s",
144214501Srpaulo			   strerror(errno));
145214501Srpaulo	} else if ((size_t) res < wpabuf_len(resp)) {
146214501Srpaulo		wpa_printf(MSG_DEBUG, "HTTP: Sent only %d of %lu bytes",
147214501Srpaulo			   res, (unsigned long) wpabuf_len(resp));
148214501Srpaulo		/* TODO: add eloop handler for sending rest of the data */
149214501Srpaulo	}
150214501Srpaulo
151214501Srpaulo	wpabuf_free(resp);
152214501Srpaulo}
153214501Srpaulo
154214501Srpaulo
155214501Srpaulovoid http_request_send_and_deinit(struct http_request *req,
156214501Srpaulo				  struct wpabuf *resp)
157214501Srpaulo{
158214501Srpaulo	http_request_send(req, resp);
159214501Srpaulo	http_request_deinit(req);
160214501Srpaulo}
161214501Srpaulo
162214501Srpaulo
163214501Srpauloenum httpread_hdr_type http_request_get_type(struct http_request *req)
164214501Srpaulo{
165214501Srpaulo	return httpread_hdr_type_get(req->hread);
166214501Srpaulo}
167214501Srpaulo
168214501Srpaulo
169214501Srpaulochar * http_request_get_uri(struct http_request *req)
170214501Srpaulo{
171214501Srpaulo	return httpread_uri_get(req->hread);
172214501Srpaulo}
173214501Srpaulo
174214501Srpaulo
175214501Srpaulochar * http_request_get_hdr(struct http_request *req)
176214501Srpaulo{
177214501Srpaulo	return httpread_hdr_get(req->hread);
178214501Srpaulo}
179214501Srpaulo
180214501Srpaulo
181214501Srpaulochar * http_request_get_data(struct http_request *req)
182214501Srpaulo{
183214501Srpaulo	return httpread_data_get(req->hread);
184214501Srpaulo}
185214501Srpaulo
186214501Srpaulo
187214501Srpaulochar * http_request_get_hdr_line(struct http_request *req, const char *tag)
188214501Srpaulo{
189214501Srpaulo	return httpread_hdr_line_get(req->hread, tag);
190214501Srpaulo}
191214501Srpaulo
192214501Srpaulo
193214501Srpaulostruct sockaddr_in * http_request_get_cli_addr(struct http_request *req)
194214501Srpaulo{
195214501Srpaulo	return &req->cli;
196214501Srpaulo}
197214501Srpaulo
198214501Srpaulo
199214501Srpaulostatic void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx)
200214501Srpaulo{
201214501Srpaulo	struct sockaddr_in addr;
202214501Srpaulo	socklen_t addr_len = sizeof(addr);
203214501Srpaulo	struct http_server *srv = eloop_ctx;
204214501Srpaulo	int conn;
205214501Srpaulo	struct http_request *req;
206214501Srpaulo
207214501Srpaulo	conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len);
208214501Srpaulo	if (conn < 0) {
209214501Srpaulo		wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: "
210214501Srpaulo			   "%s", strerror(errno));
211214501Srpaulo		return;
212214501Srpaulo	}
213214501Srpaulo	wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d",
214214501Srpaulo		   inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
215214501Srpaulo
216214501Srpaulo	req = http_request_init(srv, conn, &addr);
217214501Srpaulo	if (req == NULL) {
218214501Srpaulo		close(conn);
219214501Srpaulo		return;
220214501Srpaulo	}
221214501Srpaulo
222214501Srpaulo	req->next = srv->requests;
223214501Srpaulo	srv->requests = req;
224214501Srpaulo	srv->request_count++;
225214501Srpaulo}
226214501Srpaulo
227214501Srpaulo
228214501Srpaulostruct http_server * http_server_init(struct in_addr *addr, int port,
229214501Srpaulo				      void (*cb)(void *ctx,
230214501Srpaulo						 struct http_request *req),
231214501Srpaulo				      void *cb_ctx)
232214501Srpaulo{
233214501Srpaulo	struct sockaddr_in sin;
234214501Srpaulo	struct http_server *srv;
235281806Srpaulo	int on = 1;
236214501Srpaulo
237214501Srpaulo	srv = os_zalloc(sizeof(*srv));
238214501Srpaulo	if (srv == NULL)
239214501Srpaulo		return NULL;
240214501Srpaulo	srv->cb = cb;
241214501Srpaulo	srv->cb_ctx = cb_ctx;
242214501Srpaulo
243214501Srpaulo	srv->fd = socket(AF_INET, SOCK_STREAM, 0);
244214501Srpaulo	if (srv->fd < 0)
245214501Srpaulo		goto fail;
246281806Srpaulo
247281806Srpaulo	if (setsockopt(srv->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
248281806Srpaulo	{
249281806Srpaulo		wpa_printf(MSG_DEBUG,
250281806Srpaulo			   "HTTP: setsockopt(SO_REUSEADDR) failed: %s",
251281806Srpaulo			   strerror(errno));
252281806Srpaulo		/* try to continue anyway */
253281806Srpaulo	}
254281806Srpaulo
255214501Srpaulo	if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
256214501Srpaulo		goto fail;
257214501Srpaulo	if (port < 0)
258214501Srpaulo		srv->port = 49152;
259214501Srpaulo	else
260214501Srpaulo		srv->port = port;
261214501Srpaulo
262214501Srpaulo	os_memset(&sin, 0, sizeof(sin));
263214501Srpaulo	sin.sin_family = AF_INET;
264214501Srpaulo	sin.sin_addr.s_addr = addr->s_addr;
265214501Srpaulo
266214501Srpaulo	for (;;) {
267214501Srpaulo		sin.sin_port = htons(srv->port);
268214501Srpaulo		if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0)
269214501Srpaulo			break;
270214501Srpaulo		if (errno == EADDRINUSE) {
271214501Srpaulo			/* search for unused port */
272214501Srpaulo			if (++srv->port == 65535 || port >= 0)
273214501Srpaulo				goto fail;
274214501Srpaulo			continue;
275214501Srpaulo		}
276214501Srpaulo		wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: "
277214501Srpaulo			   "%s", srv->port, strerror(errno));
278214501Srpaulo		goto fail;
279214501Srpaulo	}
280289549Srpaulo	if (listen(srv->fd, 10 /* max backlog */) < 0 ||
281289549Srpaulo	    fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0 ||
282289549Srpaulo	    eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb,
283214501Srpaulo				srv, NULL))
284214501Srpaulo		goto fail;
285214501Srpaulo
286214501Srpaulo	wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d",
287214501Srpaulo		   inet_ntoa(*addr), srv->port);
288214501Srpaulo
289214501Srpaulo	return srv;
290214501Srpaulo
291214501Srpaulofail:
292214501Srpaulo	http_server_deinit(srv);
293214501Srpaulo	return NULL;
294214501Srpaulo}
295214501Srpaulo
296214501Srpaulo
297214501Srpaulovoid http_server_deinit(struct http_server *srv)
298214501Srpaulo{
299214501Srpaulo	if (srv == NULL)
300214501Srpaulo		return;
301214501Srpaulo	if (srv->fd >= 0) {
302214501Srpaulo		eloop_unregister_sock(srv->fd, EVENT_TYPE_READ);
303214501Srpaulo		close(srv->fd);
304214501Srpaulo	}
305214501Srpaulo	http_request_free_all(srv->requests);
306214501Srpaulo
307214501Srpaulo	os_free(srv);
308214501Srpaulo}
309214501Srpaulo
310214501Srpaulo
311214501Srpauloint http_server_get_port(struct http_server *srv)
312214501Srpaulo{
313214501Srpaulo	return srv->port;
314214501Srpaulo}
315