$search
00001 /* 00002 * http_server - HTTP server 00003 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #include <fcntl.h> 00017 00018 #include "common.h" 00019 #include "eloop.h" 00020 #include "httpread.h" 00021 #include "http_server.h" 00022 00023 #define HTTP_SERVER_TIMEOUT 30 00024 #define HTTP_SERVER_MAX_REQ_LEN 8000 00025 #define HTTP_SERVER_MAX_CONNECTIONS 10 00026 00027 struct http_request { 00028 struct http_request *next; 00029 struct http_server *srv; 00030 int fd; 00031 struct sockaddr_in cli; 00032 struct httpread *hread; 00033 }; 00034 00035 struct http_server { 00036 void (*cb)(void *ctx, struct http_request *req); 00037 void *cb_ctx; 00038 00039 int fd; 00040 int port; 00041 00042 struct http_request *requests; 00043 unsigned int request_count; 00044 }; 00045 00046 00047 static void http_request_cb(struct httpread *handle, void *cookie, 00048 enum httpread_event en) 00049 { 00050 struct http_request *req = cookie; 00051 struct http_server *srv = req->srv; 00052 00053 if (en == HTTPREAD_EVENT_FILE_READY) { 00054 wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received", 00055 inet_ntoa(req->cli.sin_addr), 00056 ntohs(req->cli.sin_port)); 00057 srv->cb(srv->cb_ctx, req); 00058 return; 00059 } 00060 wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received " 00061 "completely", inet_ntoa(req->cli.sin_addr), 00062 ntohs(req->cli.sin_port)); 00063 http_request_deinit(req); 00064 } 00065 00066 00067 static struct http_request * http_request_init(struct http_server *srv, int fd, 00068 struct sockaddr_in *cli) 00069 { 00070 struct http_request *req; 00071 00072 if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) { 00073 wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests"); 00074 return NULL; 00075 } 00076 00077 req = os_zalloc(sizeof(*req)); 00078 if (req == NULL) 00079 return NULL; 00080 00081 req->srv = srv; 00082 req->fd = fd; 00083 req->cli = *cli; 00084 00085 req->hread = httpread_create(req->fd, http_request_cb, req, 00086 HTTP_SERVER_MAX_REQ_LEN, 00087 HTTP_SERVER_TIMEOUT); 00088 if (req->hread == NULL) { 00089 http_request_deinit(req); 00090 return NULL; 00091 } 00092 00093 return req; 00094 } 00095 00096 00097 void http_request_deinit(struct http_request *req) 00098 { 00099 struct http_request *r, *p; 00100 struct http_server *srv; 00101 00102 if (req == NULL) 00103 return; 00104 00105 srv = req->srv; 00106 p = NULL; 00107 r = srv->requests; 00108 while (r) { 00109 if (r == req) { 00110 if (p) 00111 p->next = r->next; 00112 else 00113 srv->requests = r->next; 00114 srv->request_count--; 00115 break; 00116 } 00117 p = r; 00118 r = r->next; 00119 } 00120 00121 httpread_destroy(req->hread); 00122 close(req->fd); 00123 os_free(req); 00124 } 00125 00126 00127 static void http_request_free_all(struct http_request *req) 00128 { 00129 struct http_request *prev; 00130 while (req) { 00131 prev = req; 00132 req = req->next; 00133 http_request_deinit(prev); 00134 } 00135 } 00136 00137 00138 void http_request_send(struct http_request *req, struct wpabuf *resp) 00139 { 00140 int res; 00141 00142 wpa_printf(MSG_DEBUG, "HTTP: Send %lu byte response to %s:%d", 00143 (unsigned long) wpabuf_len(resp), 00144 inet_ntoa(req->cli.sin_addr), 00145 ntohs(req->cli.sin_port)); 00146 00147 res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0); 00148 if (res < 0) { 00149 wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s", 00150 strerror(errno)); 00151 } else if ((size_t) res < wpabuf_len(resp)) { 00152 wpa_printf(MSG_DEBUG, "HTTP: Sent only %d of %lu bytes", 00153 res, (unsigned long) wpabuf_len(resp)); 00154 /* TODO: add eloop handler for sending rest of the data */ 00155 } 00156 00157 wpabuf_free(resp); 00158 } 00159 00160 00161 void http_request_send_and_deinit(struct http_request *req, 00162 struct wpabuf *resp) 00163 { 00164 http_request_send(req, resp); 00165 http_request_deinit(req); 00166 } 00167 00168 00169 enum httpread_hdr_type http_request_get_type(struct http_request *req) 00170 { 00171 return httpread_hdr_type_get(req->hread); 00172 } 00173 00174 00175 char * http_request_get_uri(struct http_request *req) 00176 { 00177 return httpread_uri_get(req->hread); 00178 } 00179 00180 00181 char * http_request_get_hdr(struct http_request *req) 00182 { 00183 return httpread_hdr_get(req->hread); 00184 } 00185 00186 00187 char * http_request_get_data(struct http_request *req) 00188 { 00189 return httpread_data_get(req->hread); 00190 } 00191 00192 00193 char * http_request_get_hdr_line(struct http_request *req, const char *tag) 00194 { 00195 return httpread_hdr_line_get(req->hread, tag); 00196 } 00197 00198 00199 struct sockaddr_in * http_request_get_cli_addr(struct http_request *req) 00200 { 00201 return &req->cli; 00202 } 00203 00204 00205 static void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx) 00206 { 00207 struct sockaddr_in addr; 00208 socklen_t addr_len = sizeof(addr); 00209 struct http_server *srv = eloop_ctx; 00210 int conn; 00211 struct http_request *req; 00212 00213 conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len); 00214 if (conn < 0) { 00215 wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: " 00216 "%s", strerror(errno)); 00217 return; 00218 } 00219 wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d", 00220 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 00221 00222 req = http_request_init(srv, conn, &addr); 00223 if (req == NULL) { 00224 close(conn); 00225 return; 00226 } 00227 00228 req->next = srv->requests; 00229 srv->requests = req; 00230 srv->request_count++; 00231 } 00232 00233 00234 struct http_server * http_server_init(struct in_addr *addr, int port, 00235 void (*cb)(void *ctx, 00236 struct http_request *req), 00237 void *cb_ctx) 00238 { 00239 struct sockaddr_in sin; 00240 struct http_server *srv; 00241 00242 srv = os_zalloc(sizeof(*srv)); 00243 if (srv == NULL) 00244 return NULL; 00245 srv->cb = cb; 00246 srv->cb_ctx = cb_ctx; 00247 00248 srv->fd = socket(AF_INET, SOCK_STREAM, 0); 00249 if (srv->fd < 0) 00250 goto fail; 00251 if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0) 00252 goto fail; 00253 if (port < 0) 00254 srv->port = 49152; 00255 else 00256 srv->port = port; 00257 00258 os_memset(&sin, 0, sizeof(sin)); 00259 sin.sin_family = AF_INET; 00260 sin.sin_addr.s_addr = addr->s_addr; 00261 00262 for (;;) { 00263 sin.sin_port = htons(srv->port); 00264 if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0) 00265 break; 00266 if (errno == EADDRINUSE) { 00267 /* search for unused port */ 00268 if (++srv->port == 65535 || port >= 0) 00269 goto fail; 00270 continue; 00271 } 00272 wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: " 00273 "%s", srv->port, strerror(errno)); 00274 goto fail; 00275 } 00276 if (listen(srv->fd, 10 /* max backlog */) < 0) 00277 goto fail; 00278 if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0) 00279 goto fail; 00280 if (eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb, 00281 srv, NULL)) 00282 goto fail; 00283 00284 wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d", 00285 inet_ntoa(*addr), srv->port); 00286 00287 return srv; 00288 00289 fail: 00290 http_server_deinit(srv); 00291 return NULL; 00292 } 00293 00294 00295 void http_server_deinit(struct http_server *srv) 00296 { 00297 if (srv == NULL) 00298 return; 00299 if (srv->fd >= 0) { 00300 eloop_unregister_sock(srv->fd, EVENT_TYPE_READ); 00301 close(srv->fd); 00302 } 00303 http_request_free_all(srv->requests); 00304 00305 os_free(srv); 00306 } 00307 00308 00309 int http_server_get_port(struct http_server *srv) 00310 { 00311 return srv->port; 00312 }