2 * http_server - HTTP server
3 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
21 #include "http_server.h"
23 #define HTTP_SERVER_TIMEOUT 30
24 #define HTTP_SERVER_MAX_REQ_LEN 8000
25 #define HTTP_SERVER_MAX_CONNECTIONS 10
28 struct http_request
*next
;
29 struct http_server
*srv
;
31 struct sockaddr_in cli
;
32 struct httpread
*hread
;
36 void (*cb
)(void *ctx
, struct http_request
*req
);
42 struct http_request
*requests
;
43 unsigned int request_count
;
47 static void http_request_cb(struct httpread
*handle
, void *cookie
,
48 enum httpread_event en
)
50 struct http_request
*req
= cookie
;
51 struct http_server
*srv
= req
->srv
;
53 if (en
== HTTPREAD_EVENT_FILE_READY
) {
54 wpa_printf(MSG_DEBUG
, "HTTP: Request from %s:%d received",
55 inet_ntoa(req
->cli
.sin_addr
),
56 ntohs(req
->cli
.sin_port
));
57 srv
->cb(srv
->cb_ctx
, req
);
60 wpa_printf(MSG_DEBUG
, "HTTP: Request from %s:%d could not be received "
61 "completely", inet_ntoa(req
->cli
.sin_addr
),
62 ntohs(req
->cli
.sin_port
));
63 http_request_deinit(req
);
67 static struct http_request
* http_request_init(struct http_server
*srv
, int fd
,
68 struct sockaddr_in
*cli
)
70 struct http_request
*req
;
72 if (srv
->request_count
>= HTTP_SERVER_MAX_CONNECTIONS
) {
73 wpa_printf(MSG_DEBUG
, "HTTP: Too many concurrent requests");
77 req
= os_zalloc(sizeof(*req
));
85 req
->hread
= httpread_create(req
->fd
, http_request_cb
, req
,
86 HTTP_SERVER_MAX_REQ_LEN
,
88 if (req
->hread
== NULL
) {
89 http_request_deinit(req
);
97 void http_request_deinit(struct http_request
*req
)
99 struct http_request
*r
, *p
;
100 struct http_server
*srv
;
113 srv
->requests
= r
->next
;
114 srv
->request_count
--;
121 httpread_destroy(req
->hread
);
127 static void http_request_free_all(struct http_request
*req
)
129 struct http_request
*prev
;
133 http_request_deinit(prev
);
138 void http_request_send(struct http_request
*req
, struct wpabuf
*resp
)
142 wpa_printf(MSG_DEBUG
, "HTTP: Send %lu byte response to %s:%d",
143 (unsigned long) wpabuf_len(resp
),
144 inet_ntoa(req
->cli
.sin_addr
),
145 ntohs(req
->cli
.sin_port
));
147 res
= send(req
->fd
, wpabuf_head(resp
), wpabuf_len(resp
), 0);
149 wpa_printf(MSG_DEBUG
, "HTTP: Send failed: %s",
151 } else if ((size_t) res
< wpabuf_len(resp
)) {
152 wpa_printf(MSG_DEBUG
, "HTTP: Sent only %d of %lu bytes",
153 res
, (unsigned long) wpabuf_len(resp
));
154 /* TODO: add eloop handler for sending rest of the data */
161 void http_request_send_and_deinit(struct http_request
*req
,
164 http_request_send(req
, resp
);
165 http_request_deinit(req
);
169 enum httpread_hdr_type
http_request_get_type(struct http_request
*req
)
171 return httpread_hdr_type_get(req
->hread
);
175 char * http_request_get_uri(struct http_request
*req
)
177 return httpread_uri_get(req
->hread
);
181 char * http_request_get_hdr(struct http_request
*req
)
183 return httpread_hdr_get(req
->hread
);
187 char * http_request_get_data(struct http_request
*req
)
189 return httpread_data_get(req
->hread
);
193 char * http_request_get_hdr_line(struct http_request
*req
, const char *tag
)
195 return httpread_hdr_line_get(req
->hread
, tag
);
199 struct sockaddr_in
* http_request_get_cli_addr(struct http_request
*req
)
205 static void http_server_cb(int sd
, void *eloop_ctx
, void *sock_ctx
)
207 struct sockaddr_in addr
;
208 socklen_t addr_len
= sizeof(addr
);
209 struct http_server
*srv
= eloop_ctx
;
211 struct http_request
*req
;
213 conn
= accept(srv
->fd
, (struct sockaddr
*) &addr
, &addr_len
);
215 wpa_printf(MSG_DEBUG
, "HTTP: Failed to accept new connection: "
216 "%s", strerror(errno
));
219 wpa_printf(MSG_DEBUG
, "HTTP: Connection from %s:%d",
220 inet_ntoa(addr
.sin_addr
), ntohs(addr
.sin_port
));
222 req
= http_request_init(srv
, conn
, &addr
);
228 req
->next
= srv
->requests
;
230 srv
->request_count
++;
234 struct http_server
* http_server_init(struct in_addr
*addr
, int port
,
235 void (*cb
)(void *ctx
,
236 struct http_request
*req
),
239 struct sockaddr_in sin
;
240 struct http_server
*srv
;
242 srv
= os_zalloc(sizeof(*srv
));
246 srv
->cb_ctx
= cb_ctx
;
248 srv
->fd
= socket(AF_INET
, SOCK_STREAM
, 0);
251 if (fcntl(srv
->fd
, F_SETFL
, O_NONBLOCK
) < 0)
258 os_memset(&sin
, 0, sizeof(sin
));
259 sin
.sin_family
= AF_INET
;
260 sin
.sin_addr
.s_addr
= addr
->s_addr
;
263 sin
.sin_port
= htons(srv
->port
);
264 if (bind(srv
->fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == 0)
266 if (errno
== EADDRINUSE
) {
267 /* search for unused port */
268 if (++srv
->port
== 65535 || port
>= 0)
272 wpa_printf(MSG_DEBUG
, "HTTP: Failed to bind server port %d: "
273 "%s", srv
->port
, strerror(errno
));
276 if (listen(srv
->fd
, 10 /* max backlog */) < 0)
278 if (fcntl(srv
->fd
, F_SETFL
, O_NONBLOCK
) < 0)
280 if (eloop_register_sock(srv
->fd
, EVENT_TYPE_READ
, http_server_cb
,
284 wpa_printf(MSG_DEBUG
, "HTTP: Started server on %s:%d",
285 inet_ntoa(*addr
), srv
->port
);
290 http_server_deinit(srv
);
295 void http_server_deinit(struct http_server
*srv
)
300 eloop_unregister_sock(srv
->fd
, EVENT_TYPE_READ
);
303 http_request_free_all(srv
->requests
);
309 int http_server_get_port(struct http_server
*srv
)