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