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