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