1  /*
2   * http_server - HTTP server
3   * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4   *
5   * This software may be distributed under the terms of the BSD license.
6   * See README for more details.
7   */
8  
9  #include "includes.h"
10  #include <fcntl.h>
11  
12  #include "common.h"
13  #include "eloop.h"
14  #include "httpread.h"
15  #include "http_server.h"
16  
17  #define HTTP_SERVER_TIMEOUT 30
18  #define HTTP_SERVER_MAX_REQ_LEN 8000
19  #define HTTP_SERVER_MAX_CONNECTIONS 10
20  
21  struct http_request {
22  	struct http_request *next;
23  	struct http_server *srv;
24  	int fd;
25  	struct sockaddr_in cli;
26  	struct httpread *hread;
27  };
28  
29  struct http_server {
30  	void (*cb)(void *ctx, struct http_request *req);
31  	void *cb_ctx;
32  
33  	int fd;
34  	int port;
35  
36  	struct http_request *requests;
37  	unsigned int request_count;
38  };
39  
40  
http_request_cb(struct httpread * handle,void * cookie,enum httpread_event en)41  static void http_request_cb(struct httpread *handle, void *cookie,
42  			    enum httpread_event en)
43  {
44  	struct http_request *req = cookie;
45  	struct http_server *srv = req->srv;
46  
47  	if (en == HTTPREAD_EVENT_FILE_READY) {
48  		wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received",
49  			   inet_ntoa(req->cli.sin_addr),
50  			   ntohs(req->cli.sin_port));
51  		srv->cb(srv->cb_ctx, req);
52  		return;
53  	}
54  	wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received "
55  		   "completely", inet_ntoa(req->cli.sin_addr),
56  		   ntohs(req->cli.sin_port));
57  	http_request_deinit(req);
58  }
59  
60  
http_request_init(struct http_server * srv,int fd,struct sockaddr_in * cli)61  static struct http_request * http_request_init(struct http_server *srv, int fd,
62  					       struct sockaddr_in *cli)
63  {
64  	struct http_request *req;
65  
66  	if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) {
67  		wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests");
68  		return NULL;
69  	}
70  
71  	req = os_zalloc(sizeof(*req));
72  	if (req == NULL)
73  		return NULL;
74  
75  	req->srv = srv;
76  	req->fd = fd;
77  	req->cli = *cli;
78  
79  	req->hread = httpread_create(req->fd, http_request_cb, req,
80  				     HTTP_SERVER_MAX_REQ_LEN,
81  				     HTTP_SERVER_TIMEOUT);
82  	if (req->hread == NULL) {
83  		http_request_deinit(req);
84  		return NULL;
85  	}
86  
87  	return req;
88  }
89  
90  
http_request_deinit(struct http_request * req)91  void http_request_deinit(struct http_request *req)
92  {
93  	struct http_request *r, *p;
94  	struct http_server *srv;
95  
96  	if (req == NULL)
97  		return;
98  
99  	srv = req->srv;
100  	p = NULL;
101  	r = srv->requests;
102  	while (r) {
103  		if (r == req) {
104  			if (p)
105  				p->next = r->next;
106  			else
107  				srv->requests = r->next;
108  			srv->request_count--;
109  			break;
110  		}
111  		p = r;
112  		r = r->next;
113  	}
114  
115  	httpread_destroy(req->hread);
116  	close(req->fd);
117  	os_free(req);
118  }
119  
120  
http_request_free_all(struct http_request * req)121  static void http_request_free_all(struct http_request *req)
122  {
123  	struct http_request *prev;
124  	while (req) {
125  		prev = req;
126  		req = req->next;
127  		http_request_deinit(prev);
128  	}
129  }
130  
131  
http_request_send(struct http_request * req,struct wpabuf * resp)132  void http_request_send(struct http_request *req, struct wpabuf *resp)
133  {
134  	int res;
135  
136  	wpa_printf(MSG_DEBUG, "HTTP: Send %lu byte response to %s:%d",
137  		   (unsigned long) wpabuf_len(resp),
138  		   inet_ntoa(req->cli.sin_addr),
139  		   ntohs(req->cli.sin_port));
140  
141  	res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0);
142  	if (res < 0) {
143  		wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s",
144  			   strerror(errno));
145  	} else if ((size_t) res < wpabuf_len(resp)) {
146  		wpa_printf(MSG_DEBUG, "HTTP: Sent only %d of %lu bytes",
147  			   res, (unsigned long) wpabuf_len(resp));
148  		/* TODO: add eloop handler for sending rest of the data */
149  	}
150  
151  	wpabuf_free(resp);
152  }
153  
154  
http_request_send_and_deinit(struct http_request * req,struct wpabuf * resp)155  void http_request_send_and_deinit(struct http_request *req,
156  				  struct wpabuf *resp)
157  {
158  	http_request_send(req, resp);
159  	http_request_deinit(req);
160  }
161  
162  
http_request_get_type(struct http_request * req)163  enum httpread_hdr_type http_request_get_type(struct http_request *req)
164  {
165  	return httpread_hdr_type_get(req->hread);
166  }
167  
168  
http_request_get_uri(struct http_request * req)169  char * http_request_get_uri(struct http_request *req)
170  {
171  	return httpread_uri_get(req->hread);
172  }
173  
174  
http_request_get_hdr(struct http_request * req)175  char * http_request_get_hdr(struct http_request *req)
176  {
177  	return httpread_hdr_get(req->hread);
178  }
179  
180  
http_request_get_data(struct http_request * req)181  char * http_request_get_data(struct http_request *req)
182  {
183  	return httpread_data_get(req->hread);
184  }
185  
186  
http_request_get_hdr_line(struct http_request * req,const char * tag)187  char * http_request_get_hdr_line(struct http_request *req, const char *tag)
188  {
189  	return httpread_hdr_line_get(req->hread, tag);
190  }
191  
192  
http_request_get_cli_addr(struct http_request * req)193  struct sockaddr_in * http_request_get_cli_addr(struct http_request *req)
194  {
195  	return &req->cli;
196  }
197  
198  
http_server_cb(int sd,void * eloop_ctx,void * sock_ctx)199  static void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx)
200  {
201  	struct sockaddr_in addr;
202  	socklen_t addr_len = sizeof(addr);
203  	struct http_server *srv = eloop_ctx;
204  	int conn;
205  	struct http_request *req;
206  
207  	conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len);
208  	if (conn < 0) {
209  		wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: "
210  			   "%s", strerror(errno));
211  		return;
212  	}
213  	wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d",
214  		   inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
215  
216  	req = http_request_init(srv, conn, &addr);
217  	if (req == NULL) {
218  		close(conn);
219  		return;
220  	}
221  
222  	req->next = srv->requests;
223  	srv->requests = req;
224  	srv->request_count++;
225  }
226  
227  
http_server_init(struct in_addr * addr,int port,void (* cb)(void * ctx,struct http_request * req),void * cb_ctx)228  struct http_server * http_server_init(struct in_addr *addr, int port,
229  				      void (*cb)(void *ctx,
230  						 struct http_request *req),
231  				      void *cb_ctx)
232  {
233  	struct sockaddr_in sin;
234  	struct http_server *srv;
235  	int on = 1;
236  
237  	srv = os_zalloc(sizeof(*srv));
238  	if (srv == NULL)
239  		return NULL;
240  	srv->cb = cb;
241  	srv->cb_ctx = cb_ctx;
242  
243  	srv->fd = socket(AF_INET, SOCK_STREAM, 0);
244  	if (srv->fd < 0)
245  		goto fail;
246  
247  	if (setsockopt(srv->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
248  	{
249  		wpa_printf(MSG_DEBUG,
250  			   "HTTP: setsockopt(SO_REUSEADDR) failed: %s",
251  			   strerror(errno));
252  		/* try to continue anyway */
253  	}
254  
255  	if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
256  		goto fail;
257  	if (port < 0)
258  		srv->port = 49152;
259  	else
260  		srv->port = port;
261  
262  	os_memset(&sin, 0, sizeof(sin));
263  	sin.sin_family = AF_INET;
264  	sin.sin_addr.s_addr = addr->s_addr;
265  
266  	for (;;) {
267  		sin.sin_port = htons(srv->port);
268  		if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0)
269  			break;
270  		if (errno == EADDRINUSE) {
271  			/* search for unused port */
272  			if (++srv->port == 65535 || port >= 0)
273  				goto fail;
274  			continue;
275  		}
276  		wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: "
277  			   "%s", srv->port, strerror(errno));
278  		goto fail;
279  	}
280  	if (listen(srv->fd, 10 /* max backlog */) < 0 ||
281  	    fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0 ||
282  	    eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb,
283  				srv, NULL))
284  		goto fail;
285  
286  	wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d",
287  		   inet_ntoa(*addr), srv->port);
288  
289  	return srv;
290  
291  fail:
292  	http_server_deinit(srv);
293  	return NULL;
294  }
295  
296  
http_server_deinit(struct http_server * srv)297  void http_server_deinit(struct http_server *srv)
298  {
299  	if (srv == NULL)
300  		return;
301  	if (srv->fd >= 0) {
302  		eloop_unregister_sock(srv->fd, EVENT_TYPE_READ);
303  		close(srv->fd);
304  	}
305  	http_request_free_all(srv->requests);
306  
307  	os_free(srv);
308  }
309  
310  
http_server_get_port(struct http_server * srv)311  int http_server_get_port(struct http_server *srv)
312  {
313  	return srv->port;
314  }
315