aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2014-07-14 14:57:33 +0200
committerReyk Floeter <reyk@esdenera.com>2014-07-14 14:57:33 +0200
commit96f89aa8441368158f5b347b90c13e1acbfdd149 (patch)
tree65f30950345c8e285e8713f64cac68a78db76762
parent7c427faee432c049aec99ee716dc5c2c0af41f48 (diff)
downloadhttpd-96f89aa8441368158f5b347b90c13e1acbfdd149.tar.gz
httpd-96f89aa8441368158f5b347b90c13e1acbfdd149.zip
sync
-rw-r--r--config.c2
-rw-r--r--http.h11
-rw-r--r--httpd.c2
-rw-r--r--httpd.conf.54
-rw-r--r--httpd.h11
-rw-r--r--parse.y2
-rw-r--r--server.c22
-rw-r--r--server_file.c50
-rw-r--r--server_http.c117
9 files changed, 166 insertions, 55 deletions
diff --git a/config.c b/config.c
index 01a8e5e..230ec35 100644
--- a/config.c
+++ b/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.1 2014/07/12 23:34:54 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.2 2014/07/13 14:17:37 reyk Exp $ */
/*
* Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
diff --git a/http.h b/http.h
index d9cf13e..af2627f 100644
--- a/http.h
+++ b/http.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: http.h,v 1.1 2014/07/12 23:34:54 reyk Exp $ */
+/* $OpenBSD: http.h,v 1.3 2014/07/13 15:11:23 reyk Exp $ */
/*
* Copyright (c) 2012 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -16,8 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _HTTPD_HTTP_H
-#define _HTTPD_HTTP_H
+#ifndef _HTTP_H
+#define _HTTP_H
enum httpmethod {
HTTP_METHOD_NONE = 0,
@@ -140,10 +140,13 @@ struct http_mediatype {
/* Used during runtime */
struct http_descriptor {
struct kv http_pathquery;
+ struct kv http_matchquery;
#define http_path http_pathquery.kv_key
#define http_query http_pathquery.kv_value
#define http_rescode http_pathquery.kv_key
#define http_resmesg http_pathquery.kv_value
+#define query_key http_matchquery.kv_key
+#define query_val http_matchquery.kv_value
char *http_version;
enum httpmethod http_method;
@@ -154,4 +157,4 @@ struct http_descriptor {
struct kv *http_lastheader;
};
-#endif /* _HTTPD_HTTP_H */
+#endif /* _HTTP_H */
diff --git a/httpd.c b/httpd.c
index 7db7288..f8f0323 100644
--- a/httpd.c
+++ b/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.1 2014/07/12 23:34:54 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.2 2014/07/13 14:17:37 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
diff --git a/httpd.conf.5 b/httpd.conf.5
index 2e99949..a6f90a6 100644
--- a/httpd.conf.5
+++ b/httpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.conf.5,v 1.1 2014/07/12 23:34:54 reyk Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.2 2014/07/13 14:17:37 reyk Exp $
.\"
.\" Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: July 12 2014 $
+.Dd $Mdocdate: July 13 2014 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
diff --git a/httpd.h b/httpd.h
index f4ba745..3834e80 100644
--- a/httpd.h
+++ b/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.1 2014/07/12 23:34:54 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.3 2014/07/14 00:19:48 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -68,7 +68,8 @@ enum httpchunk {
TOREAD_UNLIMITED = -1,
TOREAD_HTTP_HEADER = -2,
TOREAD_HTTP_CHUNK_LENGTH = -3,
- TOREAD_HTTP_CHUNK_TRAILER = -4
+ TOREAD_HTTP_CHUNK_TRAILER = -4,
+ TOREAD_HTTP_NONE = -5
};
#if DEBUG > 1
@@ -264,6 +265,7 @@ struct client {
struct bufferevent *clt_file;
off_t clt_toread;
+ int clt_persist;
int clt_line;
size_t clt_headerlen;
int clt_done;
@@ -394,11 +396,14 @@ void server_read_httpchunks(struct bufferevent *, void *);
int server_writeheader_kv(struct client *, struct kv *);
int server_writeheader_http(struct client *);
int server_writeresponse_http(struct client *);
+int server_response_http(struct client *, u_int, struct media_type *,
+ size_t);
void server_reset_http(struct client *);
void server_close_http(struct client *);
+int server_response(struct httpd *, struct client *);
/* server_file.c */
-int server_response(struct httpd *, struct client *);
+int server_file(struct httpd *, struct client *);
/* httpd.c */
void event_again(struct event *, int, short,
diff --git a/parse.y b/parse.y
index 43e00c9..ec2be91 100644
--- a/parse.y
+++ b/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.1 2014/07/12 23:34:54 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.2 2014/07/13 14:17:37 reyk Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
diff --git a/server.c b/server.c
index 4106d92..b72d556 100644
--- a/server.c
+++ b/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.1 2014/07/12 23:34:54 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.5 2014/07/14 00:19:48 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -326,6 +326,11 @@ void
server_write(struct bufferevent *bev, void *arg)
{
struct client *clt = arg;
+ struct evbuffer *dst = EVBUFFER_OUTPUT(bev);
+
+ if (EVBUFFER_LENGTH(dst) == 0 &&
+ clt->clt_toread == TOREAD_HTTP_NONE)
+ goto done;
getmonotime(&clt->clt_tv_last);
@@ -384,6 +389,7 @@ void
server_error(struct bufferevent *bev, short error, void *arg)
{
struct client *clt = arg;
+ struct evbuffer *dst;
if (error & EVBUFFER_TIMEOUT) {
server_close(clt, "buffer event timeout");
@@ -398,8 +404,20 @@ server_error(struct bufferevent *bev, short error, void *arg)
clt->clt_done = 1;
+ if (bev != clt->clt_bev) {
+ dst = EVBUFFER_OUTPUT(clt->clt_bev);
+ if (EVBUFFER_LENGTH(dst))
+ return;
+ } else
+ return;
+
+ if (clt->clt_persist) {
+ server_reset_http(clt);
+ bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
+ return;
+ } else
+ server_close(clt, "done");
return;
-// server_close(con, "done");
}
server_close(clt, "buffer event error");
return;
diff --git a/server_file.c b/server_file.c
index ff3f565..e8db8a7 100644
--- a/server_file.c
+++ b/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.3 2014/07/13 15:07:50 reyk Exp $ */
+/* $OpenBSD: server_file.c,v 1.4 2014/07/14 00:19:48 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -47,20 +47,16 @@
#include "http.h"
int
-server_response(struct httpd *env, struct client *clt)
+server_file(struct httpd *env, struct client *clt)
{
struct http_descriptor *desc = clt->clt_desc;
struct server *srv = clt->clt_server;
- struct kv *ct, *cl;
struct media_type *media;
const char *errstr = NULL;
- int fd = -1;
+ int fd = -1, ret;
char path[MAXPATHLEN];
struct stat st;
- if (desc->http_path == NULL)
- goto fail;
-
/*
* XXX This is not ready XXX
* XXX Don't expect anything from this code yet,
@@ -91,40 +87,20 @@ server_response(struct httpd *env, struct client *clt)
if ((fd = open(path, O_RDONLY)) == -1 || fstat(fd, &st) == -1)
goto fail;
- kv_purge(&desc->http_headers);
-
- /* Add error codes */
- if (kv_setkey(&desc->http_pathquery, "200") == -1 ||
- kv_set(&desc->http_pathquery, "%s",
- server_httperror_byid(200)) == -1)
- goto fail;
-
- /* Add headers */
- if (kv_add(&desc->http_headers, "Server", HTTPD_SERVERNAME) == NULL ||
- kv_add(&desc->http_headers, "Connection", "close") == NULL ||
- (ct = kv_add(&desc->http_headers, "Content-Type", NULL)) == NULL ||
- (cl = kv_add(&desc->http_headers, "Content-Length", NULL)) == NULL)
- goto fail;
-
- /* Set content type */
media = media_find(env->sc_mediatypes, path);
- if (kv_set(ct, "%s/%s",
- media == NULL ? "application" : media->media_type,
- media == NULL ? "octet-stream" : media->media_subtype) == -1)
- goto fail;
-
- /* Set content length */
- if (kv_set(cl, "%ld", st.st_size) == -1)
- goto fail;
-
- if (server_writeresponse_http(clt) == -1 ||
- server_bufferevent_print(clt, "\r\n") == -1 ||
- server_writeheader_http(clt) == -1 ||
- server_bufferevent_print(clt, "\r\n") == -1)
+ ret = server_response_http(clt, 200, media, st.st_size);
+ switch (ret) {
+ case -1:
goto fail;
+ case 0:
+ /* Connection is already finished */
+ close(fd);
+ return (0);
+ default:
+ break;
+ }
clt->clt_fd = fd;
- clt->clt_persist = 0;
if (clt->clt_file != NULL)
bufferevent_free(clt->clt_file);
clt->clt_file = bufferevent_new(clt->clt_fd, server_read,
diff --git a/server_http.c b/server_http.c
index 674e92b..ad2add8 100644
--- a/server_http.c
+++ b/server_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_http.c,v 1.3 2014/07/13 09:46:19 beck Exp $ */
+/* $OpenBSD: server_http.c,v 1.7 2014/07/14 09:03:08 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -321,9 +321,8 @@ server_read_http(struct bufferevent *bev, void *arg)
if (clt->clt_toread <= 0) {
if (server_response(env, clt) == -1)
return;
+ clt->clt_done = 0;
}
-
- server_reset_http(clt);
}
if (clt->clt_done) {
server_close(clt, "done");
@@ -513,6 +512,12 @@ server_reset_http(struct client *clt)
clt->clt_headerlen = 0;
clt->clt_line = 0;
clt->clt_done = 0;
+ clt->clt_toread = TOREAD_HTTP_HEADER;
+ clt->clt_bev->readcb = server_read_http;
+ if (clt->clt_fd != -1) {
+ close(clt->clt_fd);
+ clt->clt_fd = -1;
+ }
}
void
@@ -609,6 +614,111 @@ server_close_http(struct client *clt)
}
int
+server_response(struct httpd *httpd, struct client *clt)
+{
+ struct http_descriptor *desc = clt->clt_desc;
+ struct kv *kv, key;
+ int ret;
+
+ if (desc->http_path == NULL)
+ goto fail;
+
+ if (strcmp(desc->http_version, "HTTP/1.1") == 0) {
+ /* Host header is mandatory */
+ key.kv_key = "Host";
+ if ((kv = kv_find(&desc->http_headers, &key)) == NULL)
+ goto fail;
+
+ /* Is the connection persistent? */
+ key.kv_key = "Connection";
+ if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
+ strcasecmp("close", kv->kv_value) == 0)
+ clt->clt_persist = 0;
+ else
+ clt->clt_persist++;
+ } else {
+ /* Is the connection persistent? */
+ key.kv_key = "Connection";
+ if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
+ strcasecmp("keep-alive", kv->kv_value) == 0)
+ clt->clt_persist++;
+ else
+ clt->clt_persist = 0;
+ }
+
+ if ((ret = server_file(httpd, clt)) == -1)
+ return (-1);
+
+ return (ret);
+ fail:
+ server_abort_http(clt, 400, "bad request");
+ return (-1);
+}
+
+int
+server_response_http(struct client *clt, u_int code,
+ struct media_type *media, size_t size)
+{
+ struct http_descriptor *desc = clt->clt_desc;
+ const char *error;
+ struct kv *ct, *cl;
+
+ if (desc == NULL || (error = server_httperror_byid(code)) == NULL)
+ return (-1);
+
+ kv_purge(&desc->http_headers);
+
+ /* Add error codes */
+ if (kv_setkey(&desc->http_pathquery, "%lu", code) == -1 ||
+ kv_set(&desc->http_pathquery, "%s", error) == -1)
+ return (-1);
+
+ /* Add headers */
+ if (kv_add(&desc->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
+ return (-1);
+
+ /* Is it a persistent connection? */
+ if (clt->clt_persist) {
+ if (kv_add(&desc->http_headers,
+ "Connection", "keep-alive") == NULL)
+ return (-1);
+ } else if (kv_add(&desc->http_headers, "Connection", "close") == NULL)
+ return (-1);
+
+ /* Set media type */
+ if ((ct = kv_add(&desc->http_headers, "Content-Type", NULL)) == NULL ||
+ kv_set(ct, "%s/%s",
+ media == NULL ? "application" : media->media_type,
+ media == NULL ? "octet-stream" : media->media_subtype) == -1)
+ return (-1);
+
+ /* Set content length, if specified */
+ if (size && ((cl =
+ kv_add(&desc->http_headers, "Content-Length", NULL)) == NULL ||
+ kv_set(cl, "%ld", size) == -1))
+ return (-1);
+
+ /* Write completed header */
+ if (server_writeresponse_http(clt) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1 ||
+ server_writeheader_http(clt) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1)
+ return (-1);
+
+ if (desc->http_method == HTTP_METHOD_HEAD) {
+ bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
+ if (clt->clt_persist)
+ clt->clt_toread = TOREAD_HTTP_HEADER;
+ else
+ clt->clt_toread = TOREAD_HTTP_NONE;
+ clt->clt_done = 0;
+ return (0);
+ }
+
+ return (1);
+}
+
+int
server_writeresponse_http(struct client *clt)
{
struct http_descriptor *desc = (struct http_descriptor *)clt->clt_desc;
@@ -642,7 +752,6 @@ server_writeheader_kv(struct client *clt, struct kv *hdr)
key = hdr->kv_key;
ptr = hdr->kv_value;
- DPRINTF("%s: ptr %s", __func__, ptr);
if (server_bufferevent_print(clt, key) == -1 ||
(ptr != NULL &&
(server_bufferevent_print(clt, ": ") == -1 ||