Branch data Line data Source code
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 : :
41 : 58 : static void http_request_cb(struct httpread *handle, void *cookie,
42 : : enum httpread_event en)
43 : : {
44 : 58 : struct http_request *req = cookie;
45 : 58 : struct http_server *srv = req->srv;
46 : :
47 [ + - ]: 58 : if (en == HTTPREAD_EVENT_FILE_READY) {
48 : 58 : wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received",
49 : : inet_ntoa(req->cli.sin_addr),
50 : 58 : ntohs(req->cli.sin_port));
51 : 58 : srv->cb(srv->cb_ctx, req);
52 : 58 : return;
53 : : }
54 : 0 : wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received "
55 : : "completely", inet_ntoa(req->cli.sin_addr),
56 : 0 : ntohs(req->cli.sin_port));
57 : 0 : http_request_deinit(req);
58 : : }
59 : :
60 : :
61 : 58 : 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 [ - + ]: 58 : if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) {
67 : 0 : wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests");
68 : 0 : return NULL;
69 : : }
70 : :
71 : 58 : req = os_zalloc(sizeof(*req));
72 [ - + ]: 58 : if (req == NULL)
73 : 0 : return NULL;
74 : :
75 : 58 : req->srv = srv;
76 : 58 : req->fd = fd;
77 : 58 : req->cli = *cli;
78 : :
79 : 58 : req->hread = httpread_create(req->fd, http_request_cb, req,
80 : : HTTP_SERVER_MAX_REQ_LEN,
81 : : HTTP_SERVER_TIMEOUT);
82 [ - + ]: 58 : if (req->hread == NULL) {
83 : 0 : http_request_deinit(req);
84 : 0 : return NULL;
85 : : }
86 : :
87 : 58 : return req;
88 : : }
89 : :
90 : :
91 : 58 : void http_request_deinit(struct http_request *req)
92 : : {
93 : : struct http_request *r, *p;
94 : : struct http_server *srv;
95 : :
96 [ - + ]: 58 : if (req == NULL)
97 : 58 : return;
98 : :
99 : 58 : srv = req->srv;
100 : 58 : p = NULL;
101 : 58 : r = srv->requests;
102 [ + - ]: 59 : while (r) {
103 [ + + ]: 59 : if (r == req) {
104 [ + + ]: 58 : if (p)
105 : 1 : p->next = r->next;
106 : : else
107 : 57 : srv->requests = r->next;
108 : 58 : srv->request_count--;
109 : 58 : break;
110 : : }
111 : 1 : p = r;
112 : 1 : r = r->next;
113 : : }
114 : :
115 : 58 : httpread_destroy(req->hread);
116 : 58 : close(req->fd);
117 : 58 : os_free(req);
118 : : }
119 : :
120 : :
121 : 6 : static void http_request_free_all(struct http_request *req)
122 : : {
123 : : struct http_request *prev;
124 [ - + ]: 6 : while (req) {
125 : 0 : prev = req;
126 : 0 : req = req->next;
127 : 0 : http_request_deinit(prev);
128 : : }
129 : 6 : }
130 : :
131 : :
132 : 58 : void http_request_send(struct http_request *req, struct wpabuf *resp)
133 : : {
134 : : int res;
135 : :
136 : 58 : 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 : 58 : ntohs(req->cli.sin_port));
140 : :
141 : 58 : res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0);
142 [ - + ]: 58 : if (res < 0) {
143 : 0 : wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s",
144 : 0 : strerror(errno));
145 [ - + ]: 58 : } else if ((size_t) res < wpabuf_len(resp)) {
146 : 0 : 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 : 58 : wpabuf_free(resp);
152 : 58 : }
153 : :
154 : :
155 : 58 : void http_request_send_and_deinit(struct http_request *req,
156 : : struct wpabuf *resp)
157 : : {
158 : 58 : http_request_send(req, resp);
159 : 58 : http_request_deinit(req);
160 : 58 : }
161 : :
162 : :
163 : 58 : enum httpread_hdr_type http_request_get_type(struct http_request *req)
164 : : {
165 : 58 : return httpread_hdr_type_get(req->hread);
166 : : }
167 : :
168 : :
169 : 77 : char * http_request_get_uri(struct http_request *req)
170 : : {
171 : 77 : return httpread_uri_get(req->hread);
172 : : }
173 : :
174 : :
175 : 4 : char * http_request_get_hdr(struct http_request *req)
176 : : {
177 : 4 : return httpread_hdr_get(req->hread);
178 : : }
179 : :
180 : :
181 : 69 : char * http_request_get_data(struct http_request *req)
182 : : {
183 : 69 : return httpread_data_get(req->hread);
184 : : }
185 : :
186 : :
187 : 31 : char * http_request_get_hdr_line(struct http_request *req, const char *tag)
188 : : {
189 : 31 : return httpread_hdr_line_get(req->hread, tag);
190 : : }
191 : :
192 : :
193 : 58 : struct sockaddr_in * http_request_get_cli_addr(struct http_request *req)
194 : : {
195 : 58 : return &req->cli;
196 : : }
197 : :
198 : :
199 : 58 : static void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx)
200 : : {
201 : : struct sockaddr_in addr;
202 : 58 : socklen_t addr_len = sizeof(addr);
203 : 58 : struct http_server *srv = eloop_ctx;
204 : : int conn;
205 : : struct http_request *req;
206 : :
207 : 58 : conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len);
208 [ - + ]: 58 : if (conn < 0) {
209 : 0 : wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: "
210 : 0 : "%s", strerror(errno));
211 : 0 : return;
212 : : }
213 : 58 : wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d",
214 : 58 : inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
215 : :
216 : 58 : req = http_request_init(srv, conn, &addr);
217 [ - + ]: 58 : if (req == NULL) {
218 : 0 : close(conn);
219 : 0 : return;
220 : : }
221 : :
222 : 58 : req->next = srv->requests;
223 : 58 : srv->requests = req;
224 : 58 : srv->request_count++;
225 : : }
226 : :
227 : :
228 : 6 : 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 : 6 : int on = 1;
236 : :
237 : 6 : srv = os_zalloc(sizeof(*srv));
238 [ - + ]: 6 : if (srv == NULL)
239 : 0 : return NULL;
240 : 6 : srv->cb = cb;
241 : 6 : srv->cb_ctx = cb_ctx;
242 : :
243 : 6 : srv->fd = socket(AF_INET, SOCK_STREAM, 0);
244 [ - + ]: 6 : if (srv->fd < 0)
245 : 0 : goto fail;
246 : :
247 : 6 : setsockopt(srv->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
248 : :
249 [ - + ]: 6 : if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
250 : 0 : goto fail;
251 [ + - ]: 6 : if (port < 0)
252 : 6 : srv->port = 49152;
253 : : else
254 : 0 : srv->port = port;
255 : :
256 : 6 : os_memset(&sin, 0, sizeof(sin));
257 : 6 : sin.sin_family = AF_INET;
258 : 6 : sin.sin_addr.s_addr = addr->s_addr;
259 : :
260 : : for (;;) {
261 : 8 : sin.sin_port = htons(srv->port);
262 [ + + ]: 8 : if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0)
263 : 6 : break;
264 [ + - ]: 2 : if (errno == EADDRINUSE) {
265 : : /* search for unused port */
266 [ + - ][ + - ]: 2 : if (++srv->port == 65535 || port >= 0)
267 : : goto fail;
268 : 2 : continue;
269 : : }
270 : 0 : wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: "
271 : 0 : "%s", srv->port, strerror(errno));
272 : 0 : goto fail;
273 : 2 : }
274 [ - + ]: 6 : if (listen(srv->fd, 10 /* max backlog */) < 0)
275 : 0 : goto fail;
276 [ - + ]: 6 : if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
277 : 0 : goto fail;
278 [ - + ]: 6 : if (eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb,
279 : : srv, NULL))
280 : 0 : goto fail;
281 : :
282 : 6 : wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d",
283 : : inet_ntoa(*addr), srv->port);
284 : :
285 : 6 : return srv;
286 : :
287 : : fail:
288 : 0 : http_server_deinit(srv);
289 : 6 : return NULL;
290 : : }
291 : :
292 : :
293 : 6 : void http_server_deinit(struct http_server *srv)
294 : : {
295 [ - + ]: 6 : if (srv == NULL)
296 : 6 : return;
297 [ + - ]: 6 : if (srv->fd >= 0) {
298 : 6 : eloop_unregister_sock(srv->fd, EVENT_TYPE_READ);
299 : 6 : close(srv->fd);
300 : : }
301 : 6 : http_request_free_all(srv->requests);
302 : :
303 : 6 : os_free(srv);
304 : : }
305 : :
306 : :
307 : 6 : int http_server_get_port(struct http_server *srv)
308 : : {
309 : 6 : return srv->port;
310 : : }
|