Use enum for HTTP stati and improve data structures
This commit is contained in:
parent
89d7bbb9c3
commit
6996e702e8
1 changed files with 90 additions and 67 deletions
157
quark.c
157
quark.c
|
@ -30,18 +30,32 @@ char *argv0;
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
static char *status[] = {
|
enum stati {
|
||||||
[200] = "OK",
|
S_OK = 200,
|
||||||
[206] = "Partial Content",
|
S_PARTIAL_CONTENT = 206,
|
||||||
[301] = "Moved Permanently",
|
S_MOVED_PERMANENTLY = 301,
|
||||||
[400] = "Bad Request",
|
S_BAD_REQUEST = 400,
|
||||||
[403] = "Forbidden",
|
S_FORBIDDEN = 403,
|
||||||
[404] = "Not Found",
|
S_NOT_FOUND = 404,
|
||||||
[405] = "Method Not Allowed",
|
S_METHOD_NOT_ALLOWED = 405,
|
||||||
[408] = "Request Time-out",
|
S_REQUEST_TIMEOUT = 408,
|
||||||
[431] = "Request Header Fields Too Large",
|
S_REQUEST_TOO_LARGE = 431,
|
||||||
[500] = "Internal Server Error",
|
S_INTERNAL_SERVER_ERROR = 500,
|
||||||
[505] = "HTTP Version not supported",
|
S_VERSION_NOT_SUPPORTED = 505,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *statistr[] = {
|
||||||
|
[S_OK] = "OK",
|
||||||
|
[S_PARTIAL_CONTENT] = "Partial Content",
|
||||||
|
[S_MOVED_PERMANENTLY] = "Moved Permanently",
|
||||||
|
[S_BAD_REQUEST] = "Bad Request",
|
||||||
|
[S_FORBIDDEN] = "Forbidden",
|
||||||
|
[S_NOT_FOUND] = "Not Found",
|
||||||
|
[S_METHOD_NOT_ALLOWED] = "Method Not Allowed",
|
||||||
|
[S_REQUEST_TIMEOUT] = "Request Time-out",
|
||||||
|
[S_REQUEST_TOO_LARGE] = "Request Header Fields Too Large",
|
||||||
|
[S_INTERNAL_SERVER_ERROR] = "Internal Server Error",
|
||||||
|
[S_VERSION_NOT_SUPPORTED] = "HTTP Version not supported",
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,7 +75,7 @@ timestamp(time_t t)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sendstatus(int code, int fd, ...)
|
sendstatus(enum stati code, int fd, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
@ -70,13 +84,13 @@ sendstatus(int code, int fd, ...)
|
||||||
long lower, upper, size;
|
long lower, upper, size;
|
||||||
|
|
||||||
buflen = snprintf(buf, 4096, "HTTP/1.1 %d %s\r\n", code,
|
buflen = snprintf(buf, 4096, "HTTP/1.1 %d %s\r\n", code,
|
||||||
status[code]);
|
statistr[code]);
|
||||||
|
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen, "Date: %s\r\n",
|
buflen += snprintf(buf + buflen, 4096 - buflen, "Date: %s\r\n",
|
||||||
timestamp(0));
|
timestamp(0));
|
||||||
va_start(ap, fd);
|
va_start(ap, fd);
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 200: /* arg-list: mime, size */
|
case S_OK: /* arg-list: mime, size */
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen,
|
buflen += snprintf(buf + buflen, 4096 - buflen,
|
||||||
"Content-Type: %s\r\n",
|
"Content-Type: %s\r\n",
|
||||||
va_arg(ap, char *));
|
va_arg(ap, char *));
|
||||||
|
@ -86,7 +100,7 @@ sendstatus(int code, int fd, ...)
|
||||||
size);
|
size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 206: /* arg-list: mime, lower, upper, size */
|
case S_PARTIAL_CONTENT: /* arg-list: mime, lower, upper, size */
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen,
|
buflen += snprintf(buf + buflen, 4096 - buflen,
|
||||||
"Content-Type: %s\r\n",
|
"Content-Type: %s\r\n",
|
||||||
va_arg(ap, char *));
|
va_arg(ap, char *));
|
||||||
|
@ -100,7 +114,7 @@ sendstatus(int code, int fd, ...)
|
||||||
"Content-Length: %ld\r\n",
|
"Content-Length: %ld\r\n",
|
||||||
(upper - lower) + 1);
|
(upper - lower) + 1);
|
||||||
break;
|
break;
|
||||||
case 301: /* arg-list: host, url */
|
case S_MOVED_PERMANENTLY: /* arg-list: host, url */
|
||||||
if (!strcmp(port, "80")) {
|
if (!strcmp(port, "80")) {
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen,
|
buflen += snprintf(buf + buflen, 4096 - buflen,
|
||||||
"Location: http://%s%s\r\n",
|
"Location: http://%s%s\r\n",
|
||||||
|
@ -113,32 +127,34 @@ sendstatus(int code, int fd, ...)
|
||||||
va_arg(ap, char *));
|
va_arg(ap, char *));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 405: /* arg-list: none */
|
case S_METHOD_NOT_ALLOWED: /* arg-list: none */
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen,
|
buflen += snprintf(buf + buflen, 4096 - buflen,
|
||||||
"Allow: GET\r\n");
|
"Allow: GET\r\n");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen,
|
buflen += snprintf(buf + buflen, 4096 - buflen,
|
||||||
"Connection: close\r\n");
|
"Connection: close\r\n");
|
||||||
|
|
||||||
if (code != 200 && code != 206) {
|
if (code != S_OK && code != S_PARTIAL_CONTENT) {
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen,
|
buflen += snprintf(buf + buflen, 4096 - buflen,
|
||||||
"Content-Type: text/html\r\n");
|
"Content-Type: text/html\r\n");
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen,
|
buflen += snprintf(buf + buflen, 4096 - buflen,
|
||||||
"\r\n<!DOCTYPE html>\r\n<html>\r\n"
|
"\r\n<!DOCTYPE html>\r\n<html>\r\n"
|
||||||
"\t<head><title>%d %s</title></head>"
|
"\t<head><title>%d %s</title></head>"
|
||||||
"\r\n\t<body><h1>%d %s</h1></body>\r\n"
|
"\r\n\t<body><h1>%d %s</h1></body>\r\n"
|
||||||
"</html>\r\n", code, status[code],
|
"</html>\r\n", code, statistr[code],
|
||||||
code, status[code]);
|
code, statistr[code]);
|
||||||
} else {
|
} else {
|
||||||
buflen += snprintf(buf + buflen, 4096 - buflen, "\r\n");
|
buflen += snprintf(buf + buflen, 4096 - buflen, "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (written = 0; buflen > 0; written += ret, buflen -= ret) {
|
for (written = 0; buflen > 0; written += ret, buflen -= ret) {
|
||||||
if ((ret = write(fd, buf + written, buflen)) < 0) {
|
if ((ret = write(fd, buf + written, buflen)) < 0) {
|
||||||
code = 408;
|
code = S_REQUEST_TIMEOUT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,9 +213,9 @@ listdir(char *dir, int fd)
|
||||||
int dirlen, ret, i;
|
int dirlen, ret, i;
|
||||||
|
|
||||||
if ((dirlen = scandir(dir, &e, NULL, alphasort)) < 0) {
|
if ((dirlen = scandir(dir, &e, NULL, alphasort)) < 0) {
|
||||||
return sendstatus(403, fd);
|
return sendstatus(S_FORBIDDEN, fd);
|
||||||
}
|
}
|
||||||
if ((ret = sendstatus(200, fd, "text/html", (long)-1)) != 200) {
|
if ((ret = sendstatus(S_OK, fd, "text/html", (long)-1)) != S_OK) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if ((buflen = snprintf(buf, sizeof(buf), "<!DOCTYPE html>\r\n"
|
if ((buflen = snprintf(buf, sizeof(buf), "<!DOCTYPE html>\r\n"
|
||||||
|
@ -207,12 +223,12 @@ listdir(char *dir, int fd)
|
||||||
"</title></head>\r\n<body>\r\n"
|
"</title></head>\r\n<body>\r\n"
|
||||||
"<a href=\"..\">..</a><br />\r\n",
|
"<a href=\"..\">..</a><br />\r\n",
|
||||||
dir)) >= sizeof(buf)) {
|
dir)) >= sizeof(buf)) {
|
||||||
return 500;
|
return S_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
written = 0;
|
written = 0;
|
||||||
while (buflen > 0) {
|
while (buflen > 0) {
|
||||||
if ((bread = write(fd, buf + written, buflen)) < 0) {
|
if ((bread = write(fd, buf + written, buflen)) < 0) {
|
||||||
return 408;
|
return S_REQUEST_TIMEOUT;
|
||||||
}
|
}
|
||||||
written += bread;
|
written += bread;
|
||||||
buflen -= bread;
|
buflen -= bread;
|
||||||
|
@ -225,12 +241,12 @@ listdir(char *dir, int fd)
|
||||||
if ((buflen = snprintf(buf, sizeof(buf), "<a href=\"%s"
|
if ((buflen = snprintf(buf, sizeof(buf), "<a href=\"%s"
|
||||||
"\">%s</a><br />\r\n", e[i]->d_name,
|
"\">%s</a><br />\r\n", e[i]->d_name,
|
||||||
e[i]->d_name)) >= sizeof(buf)) {
|
e[i]->d_name)) >= sizeof(buf)) {
|
||||||
return 500;
|
return S_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
written = 0;
|
written = 0;
|
||||||
while (buflen > 0) {
|
while (buflen > 0) {
|
||||||
if ((bread = write(fd, buf + written, buflen)) < 0) {
|
if ((bread = write(fd, buf + written, buflen)) < 0) {
|
||||||
return 408;
|
return S_REQUEST_TIMEOUT;
|
||||||
}
|
}
|
||||||
written += bread;
|
written += bread;
|
||||||
buflen -= bread;
|
buflen -= bread;
|
||||||
|
@ -239,18 +255,18 @@ listdir(char *dir, int fd)
|
||||||
|
|
||||||
if ((buflen = snprintf(buf, sizeof(buf), "\r\n</body></html>\r\n"))
|
if ((buflen = snprintf(buf, sizeof(buf), "\r\n</body></html>\r\n"))
|
||||||
>= sizeof(buf)) {
|
>= sizeof(buf)) {
|
||||||
return 500;
|
return S_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
written = 0;
|
written = 0;
|
||||||
while (buflen > 0) {
|
while (buflen > 0) {
|
||||||
if ((bread = write(fd, buf + written, buflen)) < 0) {
|
if ((bread = write(fd, buf + written, buflen)) < 0) {
|
||||||
return 408;
|
return S_REQUEST_TIMEOUT;
|
||||||
}
|
}
|
||||||
written += bread;
|
written += bread;
|
||||||
buflen -= bread;
|
buflen -= bread;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 200;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -271,7 +287,7 @@ handle(int infd, char **url)
|
||||||
/* get request header */
|
/* get request header */
|
||||||
for (reqlen = 0; ;) {
|
for (reqlen = 0; ;) {
|
||||||
if ((off = read(infd, req + reqlen, MAXREQLEN - reqlen)) < 0) {
|
if ((off = read(infd, req + reqlen, MAXREQLEN - reqlen)) < 0) {
|
||||||
return sendstatus(408, infd);
|
return sendstatus(S_REQUEST_TIMEOUT, infd);
|
||||||
} else if (off == 0) {
|
} else if (off == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -280,49 +296,49 @@ handle(int infd, char **url)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (reqlen == MAXREQLEN) {
|
if (reqlen == MAXREQLEN) {
|
||||||
return sendstatus(431, infd);
|
return sendstatus(S_REQUEST_TOO_LARGE, infd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reqlen < 2) {
|
if (reqlen < 2) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
reqlen -= 2; /* remove last \r\n */
|
reqlen -= 2; /* remove last \r\n */
|
||||||
req[reqlen] = '\0'; /* make it safe */
|
req[reqlen] = '\0'; /* make it safe */
|
||||||
|
|
||||||
/* parse request line */
|
/* parse request line */
|
||||||
if (reqlen < 3) {
|
if (reqlen < 3) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
} else if (strncmp(req, "GET", sizeof("GET") - 1)) {
|
} else if (strncmp(req, "GET", sizeof("GET") - 1)) {
|
||||||
return sendstatus(405, infd);
|
return sendstatus(S_METHOD_NOT_ALLOWED, infd);
|
||||||
} else if (req[3] != ' ') {
|
} else if (req[3] != ' ') {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
for (p = req + sizeof("GET ") - 1; *p && *p != ' '; p++)
|
for (p = req + sizeof("GET ") - 1; *p && *p != ' '; p++)
|
||||||
;
|
;
|
||||||
if (!*p) {
|
if (!*p) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
if (snprintf(urlenc, sizeof(urlenc), "%s",
|
if (snprintf(urlenc, sizeof(urlenc), "%s",
|
||||||
req + sizeof("GET ") - 1) >= sizeof(urlenc)) {
|
req + sizeof("GET ") - 1) >= sizeof(urlenc)) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
*url = urldecnorm;
|
*url = urldecnorm;
|
||||||
if (!strlen(urlenc)) {
|
if (!strlen(urlenc)) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
p += sizeof(" ") - 1;
|
p += sizeof(" ") - 1;
|
||||||
if (strncmp(p, "HTTP/", sizeof("HTTP/") - 1)) {
|
if (strncmp(p, "HTTP/", sizeof("HTTP/") - 1)) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
p += sizeof("HTTP/") - 1;
|
p += sizeof("HTTP/") - 1;
|
||||||
if (strncmp(p, "1.0", sizeof("1.0") - 1) &&
|
if (strncmp(p, "1.0", sizeof("1.0") - 1) &&
|
||||||
strncmp(p, "1.1", sizeof("1.1") - 1)) {
|
strncmp(p, "1.1", sizeof("1.1") - 1)) {
|
||||||
return sendstatus(505, infd);
|
return sendstatus(S_VERSION_NOT_SUPPORTED, infd);
|
||||||
}
|
}
|
||||||
p += sizeof("1.*") - 1;
|
p += sizeof("1.*") - 1;
|
||||||
if (strncmp(p, "\r\n", sizeof("\r\n") - 1)) {
|
if (strncmp(p, "\r\n", sizeof("\r\n") - 1)) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
p += sizeof("\r\n") - 1;
|
p += sizeof("\r\n") - 1;
|
||||||
|
|
||||||
|
@ -336,7 +352,8 @@ handle(int infd, char **url)
|
||||||
}
|
}
|
||||||
if (snprintf(reqhost, sizeof(reqhost), "%s", p) >=
|
if (snprintf(reqhost, sizeof(reqhost), "%s", p) >=
|
||||||
sizeof(reqhost)) {
|
sizeof(reqhost)) {
|
||||||
return sendstatus(500, infd);
|
return sendstatus(S_INTERNAL_SERVER_ERROR,
|
||||||
|
infd);
|
||||||
}
|
}
|
||||||
} else if (!strncmp(p, "Range:", sizeof("Range:") - 1)) {
|
} else if (!strncmp(p, "Range:", sizeof("Range:") - 1)) {
|
||||||
p += sizeof("Range:") - 1;
|
p += sizeof("Range:") - 1;
|
||||||
|
@ -345,7 +362,8 @@ handle(int infd, char **url)
|
||||||
}
|
}
|
||||||
if (snprintf(range, sizeof(range), "%s", p) >=
|
if (snprintf(range, sizeof(range), "%s", p) >=
|
||||||
sizeof(range)) {
|
sizeof(range)) {
|
||||||
return sendstatus(500, infd);
|
return sendstatus(S_INTERNAL_SERVER_ERROR,
|
||||||
|
infd);
|
||||||
}
|
}
|
||||||
} else if (!strncmp(p, "If-Modified-Since:",
|
} else if (!strncmp(p, "If-Modified-Since:",
|
||||||
sizeof("If-Modified-Since:") - 1)) {
|
sizeof("If-Modified-Since:") - 1)) {
|
||||||
|
@ -355,7 +373,8 @@ handle(int infd, char **url)
|
||||||
}
|
}
|
||||||
if (snprintf(modsince, sizeof(modsince), "%s", p) >=
|
if (snprintf(modsince, sizeof(modsince), "%s", p) >=
|
||||||
sizeof(modsince)) {
|
sizeof(modsince)) {
|
||||||
return sendstatus(500, infd);
|
return sendstatus(S_INTERNAL_SERVER_ERROR,
|
||||||
|
infd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,17 +384,18 @@ handle(int infd, char **url)
|
||||||
decode(urlenc, urldec);
|
decode(urlenc, urldec);
|
||||||
if (!realpath(urldec, urldecnorm)) {
|
if (!realpath(urldec, urldecnorm)) {
|
||||||
/* todo: break up the cases */
|
/* todo: break up the cases */
|
||||||
return sendstatus((errno == EACCES) ? 403 : 404, infd);
|
return sendstatus((errno == EACCES) ? S_FORBIDDEN :
|
||||||
|
S_NOT_FOUND, infd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hidden path? */
|
/* hidden path? */
|
||||||
if (urldecnorm[0] == '.' || strstr(urldecnorm, "/.")) {
|
if (urldecnorm[0] == '.' || strstr(urldecnorm, "/.")) {
|
||||||
return sendstatus(403, infd);
|
return sendstatus(S_FORBIDDEN, infd);
|
||||||
}
|
}
|
||||||
/* check if file or directory */
|
/* check if file or directory */
|
||||||
if (stat(urldecnorm, &st) < 0) {
|
if (stat(urldecnorm, &st) < 0) {
|
||||||
/* todo: break up the cases */
|
/* todo: break up the cases */
|
||||||
return sendstatus(404, infd);
|
return sendstatus(S_NOT_FOUND, infd);
|
||||||
}
|
}
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
/* add / at the end, was removed by realpath */
|
/* add / at the end, was removed by realpath */
|
||||||
|
@ -394,12 +414,12 @@ handle(int infd, char **url)
|
||||||
if (snprintf(urldecnormind, sizeof(urldecnormind),
|
if (snprintf(urldecnormind, sizeof(urldecnormind),
|
||||||
"%s/%s", urldecnorm, docindex) >=
|
"%s/%s", urldecnorm, docindex) >=
|
||||||
sizeof(urldecnorm)) {
|
sizeof(urldecnorm)) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
if (stat(urldecnormind, &st) < 0) {
|
if (stat(urldecnormind, &st) < 0) {
|
||||||
/* no index, serve dir */
|
/* no index, serve dir */
|
||||||
if (!listdirs) {
|
if (!listdirs) {
|
||||||
return sendstatus(403, infd);
|
return sendstatus(S_FORBIDDEN, infd);
|
||||||
}
|
}
|
||||||
return listdir(urldecnorm, infd);
|
return listdir(urldecnorm, infd);
|
||||||
}
|
}
|
||||||
|
@ -410,7 +430,7 @@ handle(int infd, char **url)
|
||||||
}
|
}
|
||||||
if (needredirect) {
|
if (needredirect) {
|
||||||
encode(urldecnorm, urlenc);
|
encode(urldecnorm, urlenc);
|
||||||
return sendstatus(301, infd, urlenc,
|
return sendstatus(S_MOVED_PERMANENTLY, infd, urlenc,
|
||||||
reqhost[0] ? reqhost : host);
|
reqhost[0] ? reqhost : host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,11 +439,11 @@ handle(int infd, char **url)
|
||||||
upper = LONG_MAX;
|
upper = LONG_MAX;
|
||||||
if (range[0]) {
|
if (range[0]) {
|
||||||
if (strncmp(range, "bytes=", sizeof("bytes=") - 1)) {
|
if (strncmp(range, "bytes=", sizeof("bytes=") - 1)) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
p = range + sizeof("bytes=") - 1;
|
p = range + sizeof("bytes=") - 1;
|
||||||
if (!(q = strchr(p, '-'))) {
|
if (!(q = strchr(p, '-'))) {
|
||||||
return sendstatus(400, infd);
|
return sendstatus(S_BAD_REQUEST, infd);
|
||||||
}
|
}
|
||||||
*(q++) = '\0';
|
*(q++) = '\0';
|
||||||
if (p[0]) {
|
if (p[0]) {
|
||||||
|
@ -436,7 +456,7 @@ handle(int infd, char **url)
|
||||||
|
|
||||||
/* serve file */
|
/* serve file */
|
||||||
if (!(fp = fopen(urldecnorm, "r"))) {
|
if (!(fp = fopen(urldecnorm, "r"))) {
|
||||||
return sendstatus(403, infd);
|
return sendstatus(S_FORBIDDEN, infd);
|
||||||
}
|
}
|
||||||
mime = "text/plain";
|
mime = "text/plain";
|
||||||
if ((p = strrchr(urldecnorm, '.'))) {
|
if ((p = strrchr(urldecnorm, '.'))) {
|
||||||
|
@ -448,22 +468,22 @@ handle(int infd, char **url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fseek(fp, 0, SEEK_END) || (fsize = ftell(fp)) < 0) {
|
if (fseek(fp, 0, SEEK_END) || (fsize = ftell(fp)) < 0) {
|
||||||
return sendstatus(500, infd);
|
return sendstatus(S_INTERNAL_SERVER_ERROR, infd);
|
||||||
}
|
}
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
if (fsize && upper > fsize) {
|
if (fsize && upper > fsize) {
|
||||||
upper = fsize - 1;
|
upper = fsize - 1;
|
||||||
}
|
}
|
||||||
if (fseek(fp, lower, SEEK_SET)) {
|
if (fseek(fp, lower, SEEK_SET)) {
|
||||||
return sendstatus(500, infd);
|
return sendstatus(S_INTERNAL_SERVER_ERROR, infd);
|
||||||
}
|
}
|
||||||
if (!range[0]) {
|
if (!range[0]) {
|
||||||
if ((ret = sendstatus(200, infd, mime, (long)fsize)) != 200) {
|
if ((ret = sendstatus(S_OK, infd, mime, (long)fsize)) != S_OK) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((ret = sendstatus(206, infd, mime, lower,
|
if ((ret = sendstatus(S_PARTIAL_CONTENT, infd, mime, lower,
|
||||||
upper, fsize)) != 206) {
|
upper, fsize)) != S_PARTIAL_CONTENT) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -472,20 +492,20 @@ handle(int infd, char **url)
|
||||||
fp))) {
|
fp))) {
|
||||||
remaining -= buflen;
|
remaining -= buflen;
|
||||||
if (buflen < 0) {
|
if (buflen < 0) {
|
||||||
return 500;
|
return S_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
p = buf;
|
p = buf;
|
||||||
while (buflen > 0) {
|
while (buflen > 0) {
|
||||||
written = write(infd, p, buflen);
|
written = write(infd, p, buflen);
|
||||||
if (written <= 0) {
|
if (written <= 0) {
|
||||||
return 408;
|
return S_REQUEST_TIMEOUT;
|
||||||
}
|
}
|
||||||
buflen -= written;
|
buflen -= written;
|
||||||
p += written;
|
p += written;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 200;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -496,11 +516,13 @@ serve(int insock)
|
||||||
pid_t p;
|
pid_t p;
|
||||||
socklen_t in_sa_len;
|
socklen_t in_sa_len;
|
||||||
time_t t;
|
time_t t;
|
||||||
int infd, status;
|
enum stati status;
|
||||||
|
int infd;
|
||||||
char inip4[INET_ADDRSTRLEN], inip6[INET6_ADDRSTRLEN], *url = "",
|
char inip4[INET_ADDRSTRLEN], inip6[INET6_ADDRSTRLEN], *url = "",
|
||||||
tstmp[25];
|
tstmp[25];
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
/* accept incoming connections */
|
||||||
in_sa_len = sizeof(in_sa);
|
in_sa_len = sizeof(in_sa);
|
||||||
if ((infd = accept(insock, (struct sockaddr *)&in_sa,
|
if ((infd = accept(insock, (struct sockaddr *)&in_sa,
|
||||||
&in_sa_len)) < 0) {
|
&in_sa_len)) < 0) {
|
||||||
|
@ -517,7 +539,7 @@ serve(int insock)
|
||||||
case 0:
|
case 0:
|
||||||
close(insock);
|
close(insock);
|
||||||
|
|
||||||
/* timeouts */
|
/* set connection timeout */
|
||||||
tv.tv_sec = 30;
|
tv.tv_sec = 30;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
if (setsockopt(infd, SOL_SOCKET, SO_RCVTIMEO, &tv,
|
if (setsockopt(infd, SOL_SOCKET, SO_RCVTIMEO, &tv,
|
||||||
|
@ -531,7 +553,7 @@ serve(int insock)
|
||||||
|
|
||||||
status = handle(infd, &url);
|
status = handle(infd, &url);
|
||||||
|
|
||||||
/* log */
|
/* write output to log */
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
strftime(tstmp, sizeof(tstmp), "%Y-%m-%dT%H:%M:%S",
|
strftime(tstmp, sizeof(tstmp), "%Y-%m-%dT%H:%M:%S",
|
||||||
gmtime(&t));
|
gmtime(&t));
|
||||||
|
@ -548,10 +570,11 @@ serve(int insock)
|
||||||
printf("%s\t%s\t%d\t%s\n", tstmp, inip6, status, url);
|
printf("%s\t%s\t%d\t%s\n", tstmp, inip6, status, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clean up and finish */
|
||||||
shutdown(infd, SHUT_RD);
|
shutdown(infd, SHUT_RD);
|
||||||
shutdown(infd, SHUT_WR);
|
shutdown(infd, SHUT_WR);
|
||||||
close(infd);
|
close(infd);
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(0);
|
||||||
default:
|
default:
|
||||||
close(infd);
|
close(infd);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue