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