18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * http_server - HTTP server 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h> 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "httpread.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "http_server.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define HTTP_SERVER_TIMEOUT 30 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define HTTP_SERVER_MAX_REQ_LEN 8000 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define HTTP_SERVER_MAX_CONNECTIONS 10 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct http_request { 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *next; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_server *srv; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int fd; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in cli; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct httpread *hread; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct http_server { 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*cb)(void *ctx, struct http_request *req); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int fd; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int port; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *requests; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int request_count; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_request_cb(struct httpread *handle, void *cookie, 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum httpread_event en) 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req = cookie; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_server *srv = req->srv; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (en == HTTPREAD_EVENT_FILE_READY) { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received", 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(req->cli.sin_addr), 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ntohs(req->cli.sin_port)); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->cb(srv->cb_ctx, req); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received " 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "completely", inet_ntoa(req->cli.sin_addr), 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ntohs(req->cli.sin_port)); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct http_request * http_request_init(struct http_server *srv, int fd, 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) { 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests"); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = os_zalloc(sizeof(*req)); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->srv = srv; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->fd = fd; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->cli = *cli; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->hread = httpread_create(req->fd, http_request_cb, req, 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HTTP_SERVER_MAX_REQ_LEN, 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HTTP_SERVER_TIMEOUT); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->hread == NULL) { 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid http_request_deinit(struct http_request *req) 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *r, *p; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_server *srv; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv = req->srv; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p = NULL; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = srv->requests; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (r) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (r == req) { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->next = r->next; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->requests = r->next; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->request_count--; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p = r; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = r->next; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt httpread_destroy(req->hread); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(req->fd); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(req); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_request_free_all(struct http_request *req) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *prev; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (req) { 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = req; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = req->next; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(prev); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid http_request_send(struct http_request *req, struct wpabuf *resp) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Send %lu byte response to %s:%d", 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(resp), 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(req->cli.sin_addr), 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ntohs(req->cli.sin_port)); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s", 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(errno)); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if ((size_t) res < wpabuf_len(resp)) { 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Sent only %d of %lu bytes", 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res, (unsigned long) wpabuf_len(resp)); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add eloop handler for sending rest of the data */ 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid http_request_send_and_deinit(struct http_request *req, 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send(req, resp); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtenum httpread_hdr_type http_request_get_type(struct http_request *req) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return httpread_hdr_type_get(req->hread); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * http_request_get_uri(struct http_request *req) 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return httpread_uri_get(req->hread); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * http_request_get_hdr(struct http_request *req) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return httpread_hdr_get(req->hread); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * http_request_get_data(struct http_request *req) 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return httpread_data_get(req->hread); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * http_request_get_hdr_line(struct http_request *req, const char *tag) 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return httpread_hdr_line_get(req->hread, tag); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct sockaddr_in * http_request_get_cli_addr(struct http_request *req) 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &req->cli; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx) 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in addr; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t addr_len = sizeof(addr); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_server *srv = eloop_ctx; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int conn; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn < 0) { 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: " 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s", strerror(errno)); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d", 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = http_request_init(srv, conn, &addr); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(conn); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->next = srv->requests; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->requests = req; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->request_count++; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct http_server * http_server_init(struct in_addr *addr, int port, 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*cb)(void *ctx, 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req), 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in sin; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_server *srv; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv = os_zalloc(sizeof(*srv)); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (srv == NULL) 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->cb = cb; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->cb_ctx = cb_ctx; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->fd = socket(AF_INET, SOCK_STREAM, 0); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (srv->fd < 0) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (port < 0) 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->port = 49152; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv->port = port; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sin, 0, sizeof(sin)); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sin.sin_family = AF_INET; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sin.sin_addr.s_addr = addr->s_addr; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sin.sin_port = htons(srv->port); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0) 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno == EADDRINUSE) { 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* search for unused port */ 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (++srv->port == 65535 || port >= 0) 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: " 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s", srv->port, strerror(errno)); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (listen(srv->fd, 10 /* max backlog */) < 0) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0) 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb, 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srv, NULL)) 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d", 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(*addr), srv->port); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return srv; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_server_deinit(srv); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid http_server_deinit(struct http_server *srv) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (srv == NULL) 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (srv->fd >= 0) { 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_sock(srv->fd, EVENT_TYPE_READ); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(srv->fd); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_free_all(srv->requests); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(srv); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint http_server_get_port(struct http_server *srv) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return srv->port; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 313