LCOV - code coverage report
Current view: top level - src/wps - http_server.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 128 142 90.1 %
Date: 2015-09-27 Functions: 16 16 100.0 %

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

Generated by: LCOV version 1.10