uhttpd: various changes

- remove unused variables
	- simply ignore command line args which belong to not enabled features
	- resolve peer address at accept() time, should solve (#11850)
	- remove floating point operations where possible

SVN-Revision: 32704
This commit is contained in:
Jo-Philipp Wich 2012-07-13 17:10:56 +00:00
parent abc3d9493b
commit 00f1b1d62a
8 changed files with 127 additions and 140 deletions

View File

@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=uhttpd
PKG_RELEASE:=39
PKG_RELEASE:=40
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_CONFIG_DEPENDS := \

View File

@ -201,9 +201,10 @@ static bool uh_cgi_socket_cb(struct client *cl)
{
/* write status */
ensure_out(uh_http_sendf(cl, NULL,
"HTTP/%.1f %03d %s\r\n"
"%s %03d %s\r\n"
"Connection: close\r\n",
req->version, res->statuscode, res->statusmsg));
http_versions[req->version],
res->statuscode, res->statusmsg));
/* add Content-Type if no Location or Content-Type */
if (!uh_cgi_header_lookup(res, "Location") &&
@ -214,7 +215,7 @@ static bool uh_cgi_socket_cb(struct client *cl)
}
/* if request was HTTP 1.1 we'll respond chunked */
if ((req->version > 1.0) &&
if ((req->version > UH_HTTP_VER_1_0) &&
!uh_cgi_header_lookup(res, "Transfer-Encoding"))
{
ensure_out(uh_http_send(cl, NULL,
@ -260,10 +261,11 @@ static bool uh_cgi_socket_cb(struct client *cl)
*/
ensure_out(uh_http_sendf(cl, NULL,
"HTTP/%.1f 200 OK\r\n"
"%s 200 OK\r\n"
"Content-Type: text/plain\r\n"
"%s\r\n",
req->version, (req->version > 1.0)
http_versions[req->version],
(req->version > UH_HTTP_VER_1_0)
? "Transfer-Encoding: chunked\r\n" : ""
));
@ -427,26 +429,10 @@ bool uh_cgi_request(struct client *cl, struct path_info *pi,
}
/* http version */
if (req->version > 1.0)
setenv("SERVER_PROTOCOL", "HTTP/1.1", 1);
else
setenv("SERVER_PROTOCOL", "HTTP/1.0", 1);
setenv("SERVER_PROTOCOL", http_versions[req->version], 1);
/* request method */
switch (req->method)
{
case UH_HTTP_MSG_GET:
setenv("REQUEST_METHOD", "GET", 1);
break;
case UH_HTTP_MSG_HEAD:
setenv("REQUEST_METHOD", "HEAD", 1);
break;
case UH_HTTP_MSG_POST:
setenv("REQUEST_METHOD", "POST", 1);
break;
}
setenv("REQUEST_METHOD", http_methods[req->method], 1);
/* request url */
setenv("REQUEST_URI", req->url, 1);

View File

@ -113,16 +113,16 @@ static int uh_file_response_ok_hdrs(struct client *cl, struct stat *s)
static int uh_file_response_200(struct client *cl, struct stat *s)
{
ensure_ret(uh_http_sendf(cl, NULL, "HTTP/%.1f 200 OK\r\n",
cl->request.version));
ensure_ret(uh_http_sendf(cl, NULL, "%s 200 OK\r\n",
http_versions[cl->request.version]));
return uh_file_response_ok_hdrs(cl, s);
}
static int uh_file_response_304(struct client *cl, struct stat *s)
{
ensure_ret(uh_http_sendf(cl, NULL, "HTTP/%.1f 304 Not Modified\r\n",
cl->request.version));
ensure_ret(uh_http_sendf(cl, NULL, "%s 304 Not Modified\r\n",
http_versions[cl->request.version]));
return uh_file_response_ok_hdrs(cl, s);
}
@ -130,8 +130,9 @@ static int uh_file_response_304(struct client *cl, struct stat *s)
static int uh_file_response_412(struct client *cl)
{
return uh_http_sendf(cl, NULL,
"HTTP/%.1f 412 Precondition Failed\r\n"
"Connection: close\r\n", cl->request.version);
"%s 412 Precondition Failed\r\n"
"Connection: close\r\n",
http_versions[cl->request.version]);
}
static int uh_file_if_match(struct client *cl, struct stat *s, int *ok)

View File

@ -66,7 +66,7 @@ static int uh_lua_recv(lua_State *L)
return 1;
}
static int uh_lua_send_common(lua_State *L, int chunked)
static int uh_lua_send_common(lua_State *L, bool chunked)
{
size_t length;
@ -112,12 +112,12 @@ out:
static int uh_lua_send(lua_State *L)
{
return uh_lua_send_common(L, 0);
return uh_lua_send_common(L, false);
}
static int uh_lua_sendc(lua_State *L)
{
return uh_lua_send_common(L, 1);
return uh_lua_send_common(L, true);
}
static int uh_lua_str2str(lua_State *L, int (*xlate_func) (char *, int, const char *, int))
@ -414,21 +414,7 @@ bool uh_lua_request(struct client *cl, lua_State *L)
lua_newtable(L);
/* request method */
switch(req->method)
{
case UH_HTTP_MSG_GET:
lua_pushstring(L, "GET");
break;
case UH_HTTP_MSG_HEAD:
lua_pushstring(L, "HEAD");
break;
case UH_HTTP_MSG_POST:
lua_pushstring(L, "POST");
break;
}
lua_pushstring(L, http_methods[req->method]);
lua_setfield(L, -2, "REQUEST_METHOD");
/* request url */
@ -462,14 +448,10 @@ bool uh_lua_request(struct client *cl, lua_State *L)
}
/* http protcol version */
lua_pushnumber(L, floor(req->version * 10) / 10);
lua_pushnumber(L, 0.9 + (req->version / 10.0));
lua_setfield(L, -2, "HTTP_VERSION");
if (req->version > 1.0)
lua_pushstring(L, "HTTP/1.1");
else
lua_pushstring(L, "HTTP/1.0");
lua_pushstring(L, http_versions[req->version]);
lua_setfield(L, -2, "SERVER_PROTOCOL");
@ -529,12 +511,13 @@ bool uh_lua_request(struct client *cl, lua_State *L)
if (! err_str)
err_str = "Unknown error";
printf("HTTP/%.1f 500 Internal Server Error\r\n"
printf("%s 500 Internal Server Error\r\n"
"Connection: close\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: %i\r\n\r\n"
"Lua raised a runtime error:\n %s\n",
req->version, 31 + strlen(err_str), err_str);
http_versions[req->version],
31 + strlen(err_str), err_str);
break;

View File

@ -334,7 +334,7 @@ int uh_http_sendf(struct client *cl, struct http_request *req,
len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
if ((req != NULL) && (req->version > 1.0))
if ((req != NULL) && (req->version > UH_HTTP_VER_1_0))
ensure_ret(uh_http_sendc(cl, buffer, len));
else if (len > 0)
ensure_ret(uh_tcp_send(cl, buffer, len));
@ -348,7 +348,7 @@ int uh_http_send(struct client *cl, struct http_request *req,
if (len < 0)
len = strlen(buf);
if ((req != NULL) && (req->version > 1.0))
if ((req != NULL) && (req->version > UH_HTTP_VER_1_0))
ensure_ret(uh_http_sendc(cl, buf, len));
else if (len > 0)
ensure_ret(uh_tcp_send(cl, buf, len));
@ -865,13 +865,13 @@ int uh_auth_check(struct client *cl, struct http_request *req,
/* 401 */
uh_http_sendf(cl, NULL,
"HTTP/%.1f 401 Authorization Required\r\n"
"WWW-Authenticate: Basic realm=\"%s\"\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 23\r\n\r\n"
"Authorization Required\n",
req->version, cl->server->conf->realm
);
"%s 401 Authorization Required\r\n"
"WWW-Authenticate: Basic realm=\"%s\"\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 23\r\n\r\n"
"Authorization Required\n",
http_versions[req->version],
cl->server->conf->realm);
return 0;
}
@ -922,7 +922,8 @@ struct listener * uh_listener_lookup(int sock)
}
struct client * uh_client_add(int sock, struct listener *serv)
struct client * uh_client_add(int sock, struct listener *serv,
struct sockaddr_in6 *peer)
{
struct client *new = NULL;
socklen_t sl;
@ -930,6 +931,7 @@ struct client * uh_client_add(int sock, struct listener *serv)
if ((new = (struct client *)malloc(sizeof(struct client))) != NULL)
{
memset(new, 0, sizeof(struct client));
memcpy(&new->peeraddr, peer, sizeof(new->peeraddr));
new->fd.fd = sock;
new->server = serv;
@ -937,14 +939,8 @@ struct client * uh_client_add(int sock, struct listener *serv)
new->rpipe.fd = -1;
new->wpipe.fd = -1;
/* get remote endpoint addr */
sl = sizeof(struct sockaddr_in6);
memset(&(new->peeraddr), 0, sl);
getpeername(sock, (struct sockaddr *) &(new->peeraddr), &sl);
/* get local endpoint addr */
sl = sizeof(struct sockaddr_in6);
memset(&(new->servaddr), 0, sl);
getsockname(sock, (struct sockaddr *) &(new->servaddr), &sl);
new->next = uh_clients;
@ -988,7 +984,7 @@ void uh_client_remove(struct client *cl)
for (cur = uh_clients; cur; prv = cur, cur = cur->next)
{
if ((cur == cl) || (!cl && cur->dead))
if (cur == cl)
{
if (prv)
prv->next = cur->next;

View File

@ -115,7 +115,9 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url);
struct listener * uh_listener_add(int sock, struct config *conf);
struct listener * uh_listener_lookup(int sock);
struct client * uh_client_add(int sock, struct listener *serv);
struct client * uh_client_add(int sock, struct listener *serv,
struct sockaddr_in6 *peer);
struct client * uh_client_lookup(int sock);
#define uh_client_error(cl, code, status, ...) do { \

View File

@ -35,6 +35,9 @@
#endif
const char * http_methods[] = { "GET", "POST", "HEAD", };
const char * http_versions[] = { "HTTP/0.9", "HTTP/1.0", "HTTP/1.1", };
static int run = 1;
static void uh_sigterm(int sig)
@ -123,10 +126,9 @@ static void uh_config_parse(struct config *conf)
static void uh_listener_cb(struct uloop_fd *u, unsigned int events);
static int uh_socket_bind(fd_set *serv_fds, int *max_fd,
const char *host, const char *port,
struct addrinfo *hints, int do_tls,
struct config *conf)
static int uh_socket_bind(const char *host, const char *port,
struct addrinfo *hints, int do_tls,
struct config *conf)
{
int sock = -1;
int yes = 1;
@ -213,11 +215,8 @@ static int uh_socket_bind(fd_set *serv_fds, int *max_fd,
l->tls = do_tls ? conf->tls : NULL;
#endif
/* add socket to server fd set */
FD_SET(sock, serv_fds);
/* add socket to uloop */
fd_cloexec(sock);
*max_fd = max(*max_fd, sock);
uh_ufd_add(&l->fd, uh_listener_cb, ULOOP_READ);
bound++;
@ -268,29 +267,18 @@ static struct http_request * uh_http_header_parse(struct client *cl,
/* check method */
if (strcmp(method, "GET") && strcmp(method, "HEAD") && strcmp(method, "POST"))
if (method && !strcmp(method, "GET"))
req->method = UH_HTTP_MSG_GET;
else if (method && !strcmp(method, "POST"))
req->method = UH_HTTP_MSG_POST;
else if (method && !strcmp(method, "HEAD"))
req->method = UH_HTTP_MSG_HEAD;
else
{
/* invalid method */
uh_http_response(cl, 405, "Method Not Allowed");
return NULL;
}
else
{
switch(method[0])
{
case 'G':
req->method = UH_HTTP_MSG_GET;
break;
case 'H':
req->method = UH_HTTP_MSG_HEAD;
break;
case 'P':
req->method = UH_HTTP_MSG_POST;
break;
}
}
/* check path */
if (!path || !strlen(path))
@ -305,22 +293,21 @@ static struct http_request * uh_http_header_parse(struct client *cl,
}
/* check version */
if ((version == NULL) || (strcmp(version, "HTTP/0.9") &&
strcmp(version, "HTTP/1.0") && strcmp(version, "HTTP/1.1")))
if (version && !strcmp(version, "HTTP/0.9"))
req->version = UH_HTTP_VER_0_9;
else if (version && !strcmp(version, "HTTP/1.0"))
req->version = UH_HTTP_VER_1_0;
else if (version && !strcmp(version, "HTTP/1.1"))
req->version = UH_HTTP_VER_1_1;
else
{
/* unsupported version */
uh_http_response(cl, 400, "Bad Request");
return NULL;
}
else
{
req->version = strtof(&version[5], NULL);
}
D("SRV: %s %s HTTP/%.1f\n",
(req->method == UH_HTTP_MSG_POST) ? "POST" :
(req->method == UH_HTTP_MSG_GET) ? "GET" : "HEAD",
req->url, req->version);
D("SRV: %s %s %s\n",
http_methods[req->method], req->url, http_versions[req->version]);
/* process header fields */
for (i = (int)(headers - buffer); i < buflen; i++)
@ -522,6 +509,9 @@ static void uh_listener_cb(struct uloop_fd *u, unsigned int events)
struct client *cl;
struct config *conf;
struct sockaddr_in6 sa;
socklen_t sl = sizeof(sa);
serv = container_of(u, struct listener, fd);
conf = serv->conf;
@ -530,12 +520,12 @@ static void uh_listener_cb(struct uloop_fd *u, unsigned int events)
return;
/* handle new connections */
if ((new_fd = accept(u->fd, NULL, 0)) != -1)
if ((new_fd = accept(u->fd, (struct sockaddr *)&sa, &sl)) != -1)
{
D("SRV: Server(%d) accept => Client(%d)\n", u->fd, new_fd);
/* add to global client list */
if ((cl = uh_client_add(new_fd, serv)) != NULL)
if ((cl = uh_client_add(new_fd, serv, &sa)) != NULL)
{
/* add client socket to global fdset */
uh_ufd_add(&cl->fd, uh_socket_cb, ULOOP_READ);
@ -785,16 +775,13 @@ static inline int uh_inittls(struct config *conf)
int main (int argc, char **argv)
{
/* master file descriptor list */
fd_set serv_fds;
/* working structs */
struct addrinfo hints;
struct sigaction sa;
struct config conf;
/* maximum file descriptor number */
int cur_fd, max_fd = 0;
int cur_fd = 0;
#ifdef HAVE_TLS
int tls = 0;
@ -806,16 +793,14 @@ int main (int argc, char **argv)
/* args */
int opt;
char bind[128];
char addr[128];
char *port = NULL;
#ifdef HAVE_LUA
#if defined(HAVE_LUA) || defined(HAVE_TLS) || defined(HAVE_UBUS)
/* library handle */
void *lib;
#endif
FD_ZERO(&serv_fds);
/* handle SIGPIPE, SIGINT, SIGTERM */
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
@ -835,7 +820,6 @@ int main (int argc, char **argv)
/* parse args */
memset(&conf, 0, sizeof(conf));
memset(bind, 0, sizeof(bind));
uloop_init();
@ -847,14 +831,16 @@ int main (int argc, char **argv)
/* [addr:]port */
case 'p':
case 's':
memset(addr, 0, sizeof(addr));
if ((port = strrchr(optarg, ':')) != NULL)
{
if ((optarg[0] == '[') && (port > optarg) && (port[-1] == ']'))
memcpy(bind, optarg + 1,
min(sizeof(bind), (int)(port - optarg) - 2));
memcpy(addr, optarg + 1,
min(sizeof(addr), (int)(port - optarg) - 2));
else
memcpy(bind, optarg,
min(sizeof(bind), (int)(port - optarg)));
memcpy(addr, optarg,
min(sizeof(addr), (int)(port - optarg)));
port++;
}
@ -880,11 +866,8 @@ int main (int argc, char **argv)
#endif
/* bind sockets */
bound += uh_socket_bind(&serv_fds, &max_fd,
bind[0] ? bind : NULL,
port, &hints, (opt == 's'), &conf);
memset(bind, 0, sizeof(bind));
bound += uh_socket_bind(addr[0] ? addr : NULL, port, &hints,
(opt == 's'), &conf);
break;
#ifdef HAVE_TLS
@ -919,6 +902,13 @@ int main (int argc, char **argv)
}
break;
#else
case 'C':
case 'K':
fprintf(stderr,
"Notice: TLS support not compiled, ignoring -%c\n",
opt);
break;
#endif
/* docroot */
@ -991,6 +981,13 @@ int main (int argc, char **argv)
exit(1);
}
break;
#else
case 'x':
case 'i':
fprintf(stderr,
"Notice: CGI support not compiled, ignoring -%c\n",
opt);
break;
#endif
#ifdef HAVE_LUA
@ -1003,6 +1000,13 @@ int main (int argc, char **argv)
case 'L':
conf.lua_handler = optarg;
break;
#else
case 'l':
case 'L':
fprintf(stderr,
"Notice: Lua support not compiled, ignoring -%c\n",
opt);
break;
#endif
#ifdef HAVE_UBUS
@ -1015,6 +1019,13 @@ int main (int argc, char **argv)
case 'U':
conf.ubus_socket = optarg;
break;
#else
case 'u':
case 'U':
fprintf(stderr,
"Notice: UBUS support not compiled, ignoring -%c\n",
opt);
break;
#endif
#if defined(HAVE_CGI) || defined(HAVE_LUA)

View File

@ -63,15 +63,8 @@
#define UH_LIMIT_MSGHEAD 4096
#define UH_LIMIT_HEADERS 64
#define UH_LIMIT_CLIENTS 64
#define UH_HTTP_MSG_GET 0
#define UH_HTTP_MSG_HEAD 1
#define UH_HTTP_MSG_POST 2
#define UH_SOCK_CLIENT 0
#define UH_SOCK_SERVER 1
struct listener;
struct client;
@ -128,9 +121,25 @@ struct config {
#endif
};
enum http_method {
UH_HTTP_MSG_GET,
UH_HTTP_MSG_POST,
UH_HTTP_MSG_HEAD,
};
extern const char *http_methods[];
enum http_version {
UH_HTTP_VER_0_9,
UH_HTTP_VER_1_0,
UH_HTTP_VER_1_1,
};
extern const char *http_versions[];
struct http_request {
int method;
float version;
enum http_method method;
enum http_version version;
int redirect_status;
char *url;
char *headers[UH_LIMIT_HEADERS];
@ -167,7 +176,6 @@ struct client {
bool (*cb)(struct client *);
void *priv;
bool dispatched;
bool dead;
struct {
char buf[UH_LIMIT_MSGHEAD];
char *ptr;