aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2014-09-09 15:19:10 +0200
committerReyk Floeter <reyk@esdenera.com>2014-09-09 15:19:10 +0200
commit58771b3259adedefc391e9bb3da319e7502ab66f (patch)
treead63b6173fee881f2e213a3a0fe22ddb68353f69
parent9de7466f7739b04f4e0f598d21becda0b146928d (diff)
downloadhttpd-58771b3259adedefc391e9bb3da319e7502ab66f.tar.gz
httpd-58771b3259adedefc391e9bb3da319e7502ab66f.zip
sync
-rw-r--r--config.c71
-rw-r--r--http.h44
-rw-r--r--httpd.c46
-rw-r--r--httpd.conf.57
-rw-r--r--httpd.h14
-rw-r--r--parse.y82
-rw-r--r--server.c58
-rw-r--r--server_fcgi.c181
-rw-r--r--server_file.c10
-rw-r--r--server_http.c123
10 files changed, 475 insertions, 161 deletions
diff --git a/config.c b/config.c
index 7ab53b5..e545571 100644
--- a/config.c
+++ b/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.21 2014/08/06 18:21:14 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.22 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -176,8 +176,9 @@ config_setserver(struct httpd *env, struct server *srv)
if ((what & CONFIG_SERVERS) == 0 || id == privsep_process)
continue;
- DPRINTF("%s: sending server %s to %s fd %d", __func__,
- srv->srv_conf.name, ps->ps_title[id], srv->srv_s);
+ DPRINTF("%s: sending server \"%s[%u]\" to %s fd %d", __func__,
+ srv->srv_conf.name, srv->srv_conf.id,
+ ps->ps_title[id], srv->srv_s);
memcpy(&s, &srv->srv_conf, sizeof(s));
@@ -223,7 +224,7 @@ config_getserver_config(struct httpd *env, struct server *srv,
#ifdef DEBUG
struct privsep *ps = env->sc_ps;
#endif
- struct server_config *srv_conf;
+ struct server_config *srv_conf, *parent;
u_int8_t *p = imsg->data;
u_int f;
@@ -233,18 +234,28 @@ config_getserver_config(struct httpd *env, struct server *srv,
IMSG_SIZE_CHECK(imsg, srv_conf);
memcpy(srv_conf, p, sizeof(*srv_conf));
+ /* Reset these variables to avoid free'ing invalid pointers */
+ serverconfig_reset(srv_conf);
+
+ TAILQ_FOREACH(parent, &srv->srv_hosts, entry) {
+ if (strcmp(parent->name, srv_conf->name) == 0)
+ break;
+ }
+ if (parent == NULL)
+ parent = &srv->srv_conf;
+
if (srv_conf->flags & SRVFLAG_LOCATION) {
/* Inherit configuration from the parent */
f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
- (void)strlcpy(srv_conf->index, srv->srv_conf.index,
+ srv_conf->flags |= parent->flags & f;
+ (void)strlcpy(srv_conf->index, parent->index,
sizeof(srv_conf->index));
}
f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX;
if ((srv_conf->flags & f) == 0)
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_SOCKET|SRVFLAG_FCGI;
if ((srv_conf->flags & f) == SRVFLAG_FCGI) {
@@ -255,59 +266,60 @@ config_getserver_config(struct httpd *env, struct server *srv,
f = SRVFLAG_ROOT;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
- (void)strlcpy(srv_conf->root, srv->srv_conf.root,
+ srv_conf->flags |= parent->flags & f;
+ (void)strlcpy(srv_conf->root, parent->root,
sizeof(srv_conf->root));
}
f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI;
if ((srv_conf->flags & f) == 0)
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_LOG|SRVFLAG_NO_LOG;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
- srv_conf->logformat = srv->srv_conf.logformat;
+ srv_conf->flags |= parent->flags & f;
+ srv_conf->logformat = parent->logformat;
}
f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG;
if ((srv_conf->flags & f) == 0)
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_SSL;
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
f = SRVFLAG_ACCESS_LOG;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
(void)strlcpy(srv_conf->accesslog,
- srv->srv_conf.accesslog,
+ parent->accesslog,
sizeof(srv_conf->accesslog));
}
f = SRVFLAG_ERROR_LOG;
if ((srv_conf->flags & f) == 0) {
- srv_conf->flags |= srv->srv_conf.flags & f;
+ srv_conf->flags |= parent->flags & f;
(void)strlcpy(srv_conf->errorlog,
- srv->srv_conf.errorlog,
+ parent->errorlog,
sizeof(srv_conf->errorlog));
}
- memcpy(&srv_conf->timeout, &srv->srv_conf.timeout,
+ memcpy(&srv_conf->timeout, &parent->timeout,
sizeof(srv_conf->timeout));
- srv_conf->maxrequests = srv->srv_conf.maxrequests;
- srv_conf->maxrequestbody = srv->srv_conf.maxrequestbody;
+ srv_conf->maxrequests = parent->maxrequests;
+ srv_conf->maxrequestbody = parent->maxrequestbody;
DPRINTF("%s: %s %d location \"%s\", "
- "parent \"%s\", flags: %s",
+ "parent \"%s[%u]\", flags: %s",
__func__, ps->ps_title[privsep_process], ps->ps_instance,
- srv_conf->location, srv->srv_conf.name,
+ srv_conf->location, parent->name, parent->id,
printb_flags(srv_conf->flags, SRVFLAG_BITS));
} else {
/* Add a new "virtual" server */
- DPRINTF("%s: %s %d server \"%s\", parent \"%s\", flags: %s",
- __func__, ps->ps_title[privsep_process], ps->ps_instance,
- srv_conf->name, srv->srv_conf.name,
+ DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", "
+ "flags: %s", __func__,
+ ps->ps_title[privsep_process], ps->ps_instance,
+ srv_conf->name, srv_conf->id, parent->name, parent->id,
printb_flags(srv_conf->flags, SRVFLAG_BITS));
}
@@ -331,6 +343,9 @@ config_getserver(struct httpd *env, struct imsg *imsg)
memcpy(&srv_conf, p, sizeof(srv_conf));
s = sizeof(srv_conf);
+ /* Reset these variables to avoid free'ing invalid pointers */
+ serverconfig_reset(&srv_conf);
+
if ((u_int)(IMSG_DATA_SIZE(imsg) - s) <
(srv_conf.ssl_cert_len + srv_conf.ssl_key_len)) {
log_debug("%s: invalid message length", __func__);
@@ -364,9 +379,9 @@ config_getserver(struct httpd *env, struct imsg *imsg)
TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry);
TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry);
- DPRINTF("%s: %s %d configuration \"%s\", flags: %s", __func__,
+ DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__,
ps->ps_title[privsep_process], ps->ps_instance,
- srv->srv_conf.name,
+ srv->srv_conf.name, srv->srv_conf.id,
printb_flags(srv->srv_conf.flags, SRVFLAG_BITS));
if (srv->srv_conf.ssl_cert_len != 0) {
diff --git a/http.h b/http.h
index 43ac089..7e67a5c 100644
--- a/http.h
+++ b/http.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: http.h,v 1.7 2014/08/14 09:12:26 doug Exp $ */
+/* $OpenBSD: http.h,v 1.8 2014/09/05 15:06:05 reyk Exp $ */
/*
* Copyright (c) 2012 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -44,6 +44,32 @@ enum httpmethod {
HTTP_METHOD_LOCK,
HTTP_METHOD_UNLOCK,
+ /* WebDAV Versioning Extension, RFC 3253 */
+ HTTP_METHOD_VERSION_CONTROL,
+ HTTP_METHOD_REPORT,
+ HTTP_METHOD_CHECKOUT,
+ HTTP_METHOD_CHECKIN,
+ HTTP_METHOD_UNCHECKOUT,
+ HTTP_METHOD_MKWORKSPACE,
+ HTTP_METHOD_UPDATE,
+ HTTP_METHOD_LABEL,
+ HTTP_METHOD_MERGE,
+ HTTP_METHOD_BASELINE_CONTROL,
+ HTTP_METHOD_MKACTIVITY,
+
+ /* WebDAV Ordered Collections, RFC 3648 */
+ HTTP_METHOD_ORDERPATCH,
+
+ /* WebDAV Access Control, RFC 3744 */
+ HTTP_METHOD_ACL,
+
+ /* WebDAV Redirect Reference Resources, RFC 4437 */
+ HTTP_METHOD_MKREDIRECTREF,
+ HTTP_METHOD_UPDATEREDIRECTREF,
+
+ /* WebDAV Search, RFC 5323 */
+ HTTP_METHOD_SEARCH,
+
/* PATCH, RFC 5789 */
HTTP_METHOD_PATCH,
@@ -71,6 +97,22 @@ struct http_method {
{ HTTP_METHOD_MOVE, "MOVE" }, \
{ HTTP_METHOD_LOCK, "LOCK" }, \
{ HTTP_METHOD_UNLOCK, "UNLOCK" }, \
+ { HTTP_METHOD_VERSION_CONTROL, "VERSION-CONTROL" }, \
+ { HTTP_METHOD_REPORT, "REPORT" }, \
+ { HTTP_METHOD_CHECKOUT, "CHECKOUT" }, \
+ { HTTP_METHOD_CHECKIN, "CHECKIN" }, \
+ { HTTP_METHOD_UNCHECKOUT, "UNCHECKOUT" }, \
+ { HTTP_METHOD_MKWORKSPACE, "MKWORKSPACE" }, \
+ { HTTP_METHOD_UPDATE, "UPDATE" }, \
+ { HTTP_METHOD_LABEL, "LABEL" }, \
+ { HTTP_METHOD_MERGE, "MERGE" }, \
+ { HTTP_METHOD_BASELINE_CONTROL, "BASELINE-CONTROL" }, \
+ { HTTP_METHOD_MKACTIVITY, "MKACTIVITY" }, \
+ { HTTP_METHOD_ORDERPATCH, "ORDERPATCH" }, \
+ { HTTP_METHOD_ACL, "ACL" }, \
+ { HTTP_METHOD_MKREDIRECTREF, "MKREDIRECTREF" }, \
+ { HTTP_METHOD_UPDATEREDIRECTREF, "UPDATEREDIRECTREF" }, \
+ { HTTP_METHOD_SEARCH, "SEARCH" }, \
{ HTTP_METHOD_PATCH, "PATCH" }, \
{ HTTP_METHOD_NONE, NULL } \
}
diff --git a/httpd.c b/httpd.c
index 4b631ec..9284eb7 100644
--- a/httpd.c
+++ b/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.19 2014/08/13 16:04:28 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.21 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -289,10 +289,20 @@ parent_configure(struct httpd *env)
fatal("send media");
}
+ /* First send the servers... */
TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
+ if (srv->srv_conf.flags & SRVFLAG_LOCATION)
+ continue;
if (config_setserver(env, srv) == -1)
fatal("send server");
}
+ /* ...and now send the locations */
+ TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
+ if ((srv->srv_conf.flags & SRVFLAG_LOCATION) == 0)
+ continue;
+ if (config_setserver(env, srv) == -1)
+ fatal("send location");
+ }
/* The servers need to reload their config. */
env->sc_reload = env->sc_prefork_server + 1;
@@ -631,6 +641,40 @@ socket_rlimit(int maxfd)
}
char *
+evbuffer_getline(struct evbuffer *evb)
+{
+ u_int8_t *ptr = EVBUFFER_DATA(evb);
+ size_t len = EVBUFFER_LENGTH(evb);
+ char *str;
+ u_int i;
+
+ /* Safe version of evbuffer_readline() */
+ if ((str = get_string(ptr, len)) == NULL)
+ return (NULL);
+
+ for (i = 0; str[i] != '\0'; i++) {
+ if (str[i] == '\r' || str[i] == '\n')
+ break;
+ }
+
+ if (i == len) {
+ free(str);
+ return (NULL);
+ }
+
+ str[i] = '\0';
+
+ if ((i + 1) < len) {
+ if (ptr[i] == '\r' && ptr[i + 1] == '\n')
+ i++;
+ }
+
+ evbuffer_drain(evb, ++i);
+
+ return (str);
+}
+
+char *
get_string(u_int8_t *ptr, size_t len)
{
size_t i;
diff --git a/httpd.conf.5 b/httpd.conf.5
index 788d0a9..6d267d6 100644
--- a/httpd.conf.5
+++ b/httpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.conf.5,v 1.33 2014/08/25 14:27:54 reyk Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.34 2014/09/01 12:22:38 jmc 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: August 25 2014 $
+.Dd $Mdocdate: September 1 2014 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
@@ -385,8 +385,7 @@ server "intranet.example.com" {
}
.Ed
.Pp
-The syntax of the types section is also compatible with the format used by
-.Xr nginx 8 ,
+The syntax of the types section is also compatible with the format used by nginx,
so it is possible to include its
.Pa mime.types
file directly:
diff --git a/httpd.h b/httpd.h
index 6f1b48d..5c197cf 100644
--- a/httpd.h
+++ b/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.54 2014/08/21 19:23:10 chrisz Exp $ */
+/* $OpenBSD: httpd.h,v 1.58 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -276,7 +276,8 @@ struct client {
size_t clt_buflen;
struct evbuffer *clt_output;
struct event clt_ev;
- void *clt_desc;
+ void *clt_descreq;
+ void *clt_descresp;
int clt_sndbufsiz;
int clt_fd;
@@ -294,6 +295,8 @@ struct client {
int clt_fcgi_toread;
int clt_fcgi_padding_len;
int clt_fcgi_type;
+ int clt_fcgi_chunked;
+ int clt_fcgi_end;
struct evbuffer *clt_srvevb;
struct evbuffer *clt_log;
@@ -463,6 +466,8 @@ pid_t server(struct privsep *, struct privsep_proc *);
int server_ssl_load_keypair(struct server *);
int server_privinit(struct server *);
void server_purge(struct server *);
+void serverconfig_free(struct server_config *);
+void serverconfig_reset(struct server_config *);
int server_socket_af(struct sockaddr_storage *, in_port_t);
in_port_t
server_socket_getport(struct sockaddr_storage *);
@@ -477,6 +482,8 @@ void server_sendlog(struct server_config *, int, const char *, ...)
void server_close(struct client *, const char *);
void server_dump(struct client *, const void *, size_t);
int server_client_cmp(struct client *, struct client *);
+int server_bufferevent_printf(struct client *, const char *, ...)
+ __attribute__((__format__ (printf, 2, 3)));
int server_bufferevent_print(struct client *, const char *);
int server_bufferevent_write_buffer(struct client *,
struct evbuffer *);
@@ -508,7 +515,7 @@ const char
void server_read_httpcontent(struct bufferevent *, void *);
void server_read_httpchunks(struct bufferevent *, void *);
int server_writeheader_http(struct client *clt, struct kv *, void *);
-int server_headers(struct client *,
+int server_headers(struct client *, void *,
int (*)(struct client *, struct kv *, void *), void *);
int server_writeresponse_http(struct client *);
int server_response_http(struct client *, u_int, struct media_type *,
@@ -542,6 +549,7 @@ void imsg_event_add(struct imsgev *);
int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
pid_t, int, void *, u_int16_t);
void socket_rlimit(int);
+char *evbuffer_getline(struct evbuffer *);
char *get_string(u_int8_t *, size_t);
void *get_data(u_int8_t *, size_t);
int sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
diff --git a/parse.y b/parse.y
index 44cf90c..9ad7732 100644
--- a/parse.y
+++ b/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.36 2014/08/25 14:27:54 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.38 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -199,15 +199,6 @@ server : SERVER STRING {
YYACCEPT;
}
- TAILQ_FOREACH(s, conf->sc_servers, srv_entry)
- if (!strcmp(s->srv_conf.name, $2))
- break;
- if (s != NULL) {
- yyerror("server %s defined twice", $2);
- free($2);
- YYERROR;
- }
-
if ((s = calloc(1, sizeof (*s))) == NULL)
fatal("out of memory");
@@ -253,18 +244,49 @@ server : SERVER STRING {
srv_conf = &srv->srv_conf;
SPLAY_INIT(&srv->srv_clients);
- TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
} '{' optnl serveropts_l '}' {
+ struct server *s = NULL;
+
+ TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
+ if ((s->srv_conf.flags &
+ SRVFLAG_LOCATION) == 0 &&
+ strcmp(s->srv_conf.name,
+ srv->srv_conf.name) == 0 &&
+ s->srv_conf.port == srv->srv_conf.port &&
+ sockaddr_cmp(
+ (struct sockaddr *)&s->srv_conf.ss,
+ (struct sockaddr *)&srv->srv_conf.ss,
+ s->srv_conf.prefixlen) == 0)
+ break;
+ }
+ if (s != NULL) {
+ yyerror("server \"%s\" defined twice",
+ srv->srv_conf.name);
+ serverconfig_free(srv_conf);
+ free(srv);
+ YYABORT;
+ }
+
if (srv->srv_conf.ss.ss_family == AF_UNSPEC) {
yyerror("listen address not specified");
- free($2);
+ serverconfig_free(srv_conf);
+ free(srv);
YYERROR;
}
+
if (server_ssl_load_keypair(srv) == -1) {
yyerror("failed to load public/private keys "
"for server %s", srv->srv_conf.name);
+ serverconfig_free(srv_conf);
+ free(srv);
YYERROR;
}
+
+ DPRINTF("adding server \"%s[%u]\"",
+ srv->srv_conf.name, srv->srv_conf.id);
+
+ TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
+
srv = NULL;
srv_conf = NULL;
}
@@ -368,17 +390,6 @@ serveroptsl : LISTEN ON STRING optssl port {
YYACCEPT;
}
- TAILQ_FOREACH(s, conf->sc_servers, srv_entry)
- if (strcmp(s->srv_conf.name,
- srv->srv_conf.name) == 0 &&
- strcmp(s->srv_conf.location, $2) == 0)
- break;
- if (s != NULL) {
- yyerror("location %s defined twice", $2);
- free($2);
- YYERROR;
- }
-
if ((s = calloc(1, sizeof (*s))) == NULL)
fatal("out of memory");
@@ -417,12 +428,35 @@ serveroptsl : LISTEN ON STRING optssl port {
srv = s;
srv_conf = &srv->srv_conf;
SPLAY_INIT(&srv->srv_clients);
- TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
} '{' optnl serveropts_l '}' {
+ struct server *s = NULL;
+
+ TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
+ if ((s->srv_conf.flags & SRVFLAG_LOCATION) &&
+ s->srv_conf.id == srv_conf->id &&
+ strcmp(s->srv_conf.location,
+ srv_conf->location) == 0)
+ break;
+ }
+ if (s != NULL) {
+ yyerror("location \"%s\" defined twice",
+ srv->srv_conf.location);
+ serverconfig_free(srv_conf);
+ free(srv);
+ YYABORT;
+ }
+
+ DPRINTF("adding location \"%s\" for \"%s[%u]\"",
+ srv->srv_conf.location,
+ srv->srv_conf.name, srv->srv_conf.id);
+
+ TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
+
srv = parentsrv;
srv_conf = &parentsrv->srv_conf;
parentsrv = NULL;
}
+ | include
;
fastcgi : NO FCGI {
diff --git a/server.c b/server.c
index 56f363f..e756abb 100644
--- a/server.c
+++ b/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.39 2014/08/06 18:38:11 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.42 2014/09/05 10:04:20 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -285,8 +285,7 @@ server_purge(struct server *srv)
/* It might point to our own "default" entry */
if (srv_conf != &srv->srv_conf) {
- free(srv_conf->ssl_cert);
- free(srv_conf->ssl_key);
+ serverconfig_free(srv_conf);
free(srv_conf);
}
}
@@ -297,6 +296,22 @@ server_purge(struct server *srv)
free(srv);
}
+void
+serverconfig_free(struct server_config *srv_conf)
+{
+ free(srv_conf->ssl_cert_file);
+ free(srv_conf->ssl_cert);
+ free(srv_conf->ssl_key_file);
+ free(srv_conf->ssl_key);
+}
+
+void
+serverconfig_reset(struct server_config *srv_conf)
+{
+ srv_conf->ssl_cert_file = srv_conf->ssl_cert =
+ srv_conf->ssl_key_file = srv_conf->ssl_key = NULL;
+}
+
struct server *
server_byaddr(struct sockaddr *addr, in_port_t port)
{
@@ -750,22 +765,31 @@ 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");
return;
}
- if (error & EVBUFFER_ERROR && errno == EFBIG) {
- bufferevent_enable(bev, EV_READ);
- return;
- }
if (error & (EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF)) {
bufferevent_disable(bev, EV_READ|EV_WRITE);
clt->clt_done = 1;
+
+ dst = EVBUFFER_OUTPUT(clt->clt_bev);
+ if (EVBUFFER_LENGTH(dst)) {
+ /* Finish writing all data first */
+ bufferevent_enable(clt->clt_bev, EV_WRITE);
+ return;
+ }
+
server_close(clt, "done");
return;
}
+ if (error & EVBUFFER_ERROR && errno == EFBIG) {
+ bufferevent_enable(bev, EV_READ);
+ return;
+ }
server_close(clt, "buffer event error");
return;
}
@@ -1112,6 +1136,26 @@ server_bufferevent_add(struct event *ev, int timeout)
}
int
+server_bufferevent_printf(struct client *clt, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+ char *str;
+
+ va_start(ap, fmt);
+ ret = vasprintf(&str, fmt, ap);
+ va_end(ap);
+
+ if (ret == -1)
+ return (ret);
+
+ ret = server_bufferevent_print(clt, str);
+ free(str);
+
+ return (ret);
+}
+
+int
server_bufferevent_print(struct client *clt, const char *str)
{
if (clt->clt_bev == NULL)
diff --git a/server_fcgi.c b/server_fcgi.c
index 6eb668e..c51d4b5 100644
--- a/server_fcgi.c
+++ b/server_fcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_fcgi.c,v 1.34 2014/08/21 19:23:10 chrisz Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.38 2014/09/02 16:20:41 reyk Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -87,16 +87,17 @@ struct server_fcgi_param {
int server_fcgi_header(struct client *, u_int);
void server_fcgi_read(struct bufferevent *, void *);
int server_fcgi_writeheader(struct client *, struct kv *, void *);
+int server_fcgi_writechunk(struct client *);
+int server_fcgi_getheaders(struct client *);
int fcgi_add_param(struct server_fcgi_param *, const char *, const char *,
struct client *);
-int get_status(struct evbuffer *);
int
server_fcgi(struct httpd *env, struct client *clt)
{
struct server_fcgi_param param;
struct server_config *srv_conf = clt->clt_srv_conf;
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
struct fcgi_record_header *h;
struct fcgi_begin_request_body *begin;
char hbuf[MAXHOSTNAMELEN];
@@ -249,7 +250,7 @@ server_fcgi(struct httpd *env, struct client *clt)
}
/* Add HTTP_* headers */
- if (server_headers(clt, server_fcgi_writeheader, &param) == -1) {
+ if (server_headers(clt, desc, server_fcgi_writeheader, &param) == -1) {
errstr = "failed to encode param";
goto fail;
}
@@ -347,11 +348,14 @@ server_fcgi(struct httpd *env, struct client *clt)
fcgi_add_stdin(clt, NULL);
}
- /*
- * persist is not supported yet because we don't get the
- * Content-Length from slowcgi and don't support chunked encoding.
- */
- clt->clt_persist = 0;
+ if (strcmp(desc->http_version, "HTTP/1.1") == 0) {
+ clt->clt_fcgi_chunked = 1;
+ } else {
+ /* HTTP/1.0 does not support chunked encoding */
+ clt->clt_fcgi_chunked = 0;
+ clt->clt_persist = 0;
+ }
+ clt->clt_fcgi_end = 0;
clt->clt_done = 0;
free(script);
@@ -454,12 +458,13 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
char *ptr;
do {
- len = bufferevent_read(bev, &buf, clt->clt_fcgi_toread);
+ len = bufferevent_read(bev, buf, clt->clt_fcgi_toread);
/* XXX error handling */
- evbuffer_add(clt->clt_srvevb, &buf, len);
+ evbuffer_add(clt->clt_srvevb, buf, len);
clt->clt_fcgi_toread -= len;
- DPRINTF("%s: len: %lu toread: %d state: %d", __func__, len,
- clt->clt_fcgi_toread, clt->clt_fcgi_state);
+ DPRINTF("%s: len: %lu toread: %d state: %d type: %d",
+ __func__, len, clt->clt_fcgi_toread,
+ clt->clt_fcgi_state, clt->clt_fcgi_type);
if (clt->clt_fcgi_toread != 0)
return;
@@ -488,9 +493,10 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
/* fallthrough if content_len == 0 */
case FCGI_READ_CONTENT:
- if (clt->clt_fcgi_type == FCGI_STDERR &&
- EVBUFFER_LENGTH(clt->clt_srvevb) > 0) {
- if ((ptr = get_string(
+ switch (clt->clt_fcgi_type) {
+ case FCGI_STDERR:
+ if (EVBUFFER_LENGTH(clt->clt_srvevb) > 0 &&
+ (ptr = get_string(
EVBUFFER_DATA(clt->clt_srvevb),
EVBUFFER_LENGTH(clt->clt_srvevb)))
!= NULL) {
@@ -498,14 +504,27 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
IMSG_LOG_ERROR, "%s", ptr);
free(ptr);
}
- }
- if (clt->clt_fcgi_type == FCGI_STDOUT &&
- EVBUFFER_LENGTH(clt->clt_srvevb) > 0) {
- if (++clt->clt_chunk == 1)
- server_fcgi_header(clt,
- get_status(clt->clt_srvevb));
- server_bufferevent_write_buffer(clt,
- clt->clt_srvevb);
+ break;
+ case FCGI_STDOUT:
+ if (++clt->clt_chunk == 1) {
+ if (server_fcgi_header(clt,
+ server_fcgi_getheaders(clt))
+ == -1) {
+ server_abort_http(clt, 500,
+ "malformed fcgi headers");
+ return;
+ }
+ if (!EVBUFFER_LENGTH(clt->clt_srvevb))
+ break;
+ }
+ /* FALLTHROUGH */
+ case FCGI_END_REQUEST:
+ if (server_fcgi_writechunk(clt) == -1) {
+ server_abort_http(clt, 500,
+ "encoding error");
+ return;
+ }
+ break;
}
evbuffer_drain(clt->clt_srvevb,
EVBUFFER_LENGTH(clt->clt_srvevb));
@@ -533,9 +552,11 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
int
server_fcgi_header(struct client *clt, u_int code)
{
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
+ struct http_descriptor *resp = clt->clt_descresp;
const char *error;
char tmbuf[32];
+ struct kv *kv, key;
if (desc == NULL || (error = server_httperror_byid(code)) == NULL)
return (-1);
@@ -543,34 +564,49 @@ server_fcgi_header(struct client *clt, u_int code)
if (server_log_http(clt, code, 0) == -1)
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)
+ if (kv_setkey(&resp->http_pathquery, "%lu", code) == -1 ||
+ kv_set(&resp->http_pathquery, "%s", error) == -1)
return (-1);
/* Add headers */
- if (kv_add(&desc->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
+ if (kv_add(&resp->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
return (-1);
+ /* Set chunked encoding */
+ if (clt->clt_fcgi_chunked) {
+ /* XXX Should we keep and handle Content-Length instead? */
+ key.kv_key = "Content-Length";
+ if ((kv = kv_find(&resp->http_headers, &key)) != NULL)
+ kv_delete(&resp->http_headers, kv);
+
+ /*
+ * XXX What if the FastCGI added some kind of Transfer-Encoding?
+ * XXX like gzip, deflate or even "chunked"?
+ */
+ if (kv_add(&resp->http_headers,
+ "Transfer-Encoding", "chunked") == NULL)
+ return (-1);
+ }
+
/* Is it a persistent connection? */
if (clt->clt_persist) {
- if (kv_add(&desc->http_headers,
+ if (kv_add(&resp->http_headers,
"Connection", "keep-alive") == NULL)
return (-1);
- } else if (kv_add(&desc->http_headers, "Connection", "close") == NULL)
+ } else if (kv_add(&resp->http_headers, "Connection", "close") == NULL)
return (-1);
/* Date header is mandatory and should be added as late as possible */
if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 ||
- kv_add(&desc->http_headers, "Date", tmbuf) == NULL)
+ kv_add(&resp->http_headers, "Date", tmbuf) == NULL)
return (-1);
/* Write initial header (fcgi might append more) */
if (server_writeresponse_http(clt) == -1 ||
server_bufferevent_print(clt, "\r\n") == -1 ||
- server_headers(clt, server_writeheader_http, NULL) == -1)
+ server_headers(clt, resp, server_writeheader_http, NULL) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1)
return (-1);
return (0);
@@ -618,26 +654,65 @@ server_fcgi_writeheader(struct client *clt, struct kv *hdr, void *arg)
}
int
-get_status(struct evbuffer *bev)
+server_fcgi_writechunk(struct client *clt)
{
- int code;
- char *statusline, *tok;
- const char *errstr;
-
- /* XXX This is a hack. We need to parse the response header. */
- code = 200;
- if (strncmp(EVBUFFER_DATA(bev), "Status: ", strlen("Status: ")) == 0) {
- statusline = get_string(EVBUFFER_DATA(bev),
- EVBUFFER_LENGTH(bev));
- if (strtok(statusline, " ") != NULL) {
- if ((tok = strtok(NULL, " ")) != NULL) {
- code = (int) strtonum(tok, 100, 600, &errstr);
- if (errstr != NULL || server_httperror_byid(
- code) == NULL)
- code = 200;
- }
+ struct evbuffer *evb = clt->clt_srvevb;
+ size_t len;
+
+ if (clt->clt_fcgi_type == FCGI_END_REQUEST) {
+ len = 0;
+ } else
+ len = EVBUFFER_LENGTH(evb);
+
+ /* If len is 0, make sure to write the end marker only once */
+ if (len == 0 && clt->clt_fcgi_end++)
+ return (0);
+
+ if (clt->clt_fcgi_chunked) {
+ if (server_bufferevent_printf(clt, "%zx\r\n", len) == -1 ||
+ server_bufferevent_write_chunk(clt, evb, len) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1)
+ return (-1);
+ } else
+ return (server_bufferevent_write_buffer(clt, evb));
+
+ return (0);
+}
+
+int
+server_fcgi_getheaders(struct client *clt)
+{
+ struct http_descriptor *resp = clt->clt_descresp;
+ struct evbuffer *evb = clt->clt_srvevb;
+ int code = 200;
+ char *line, *key, *value;
+ const char *errstr;
+
+ while ((line = evbuffer_getline(evb)) != NULL && *line != '\0') {
+ key = line;
+
+ if ((value = strchr(key, ':')) == NULL)
+ break;
+ if (*value == ':') {
+ *value++ = '\0';
+ value += strspn(value, " \t");
+ } else {
+ *value++ = '\0';
}
- free(statusline);
+
+ DPRINTF("%s: %s: %s", __func__, key, value);
+
+ if (strcasecmp("Status", key) == 0) {
+ value[strcspn(value, " \t")] = '\0';
+ code = (int)strtonum(value, 100, 600, &errstr);
+ if (errstr != NULL || server_httperror_byid(
+ code) == NULL)
+ code = 200;
+ } else {
+ (void)kv_add(&resp->http_headers, key, value);
+ }
+ free(line);
}
- return code;
+
+ return (code);
}
diff --git a/server_file.c b/server_file.c
index 28b17c7..e8a487e 100644
--- a/server_file.c
+++ b/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.34 2014/08/21 19:23:10 chrisz Exp $ */
+/* $OpenBSD: server_file.c,v 1.35 2014/08/29 13:01:46 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -56,7 +56,7 @@ int
server_file_access(struct httpd *env, struct client *clt,
char *path, size_t len)
{
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
struct server_config *srv_conf = clt->clt_srv_conf;
struct stat st;
char *newpath;
@@ -150,7 +150,7 @@ server_file_access(struct httpd *env, struct client *clt,
int
server_file(struct httpd *env, struct client *clt)
{
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
struct server_config *srv_conf = clt->clt_srv_conf;
char path[MAXPATHLEN];
const char *errstr = NULL;
@@ -187,7 +187,7 @@ server_file(struct httpd *env, struct client *clt)
int
server_file_method(struct client *clt)
{
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
switch (desc->http_method) {
case HTTP_METHOD_GET:
@@ -272,7 +272,7 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
{
char path[MAXPATHLEN];
char tmstr[21];
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
struct server_config *srv_conf = clt->clt_srv_conf;
struct dirent **namelist, *dp;
int namesize, i, ret, fd = -1, namewidth, skip;
diff --git a/server_http.c b/server_http.c
index af996a5..6ba5c15 100644
--- a/server_http.c
+++ b/server_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_http.c,v 1.45 2014/08/21 19:23:10 chrisz Exp $ */
+/* $OpenBSD: server_http.c,v 1.48 2014/09/05 15:06:05 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -86,9 +86,15 @@ server_httpdesc_init(struct client *clt)
if ((desc = calloc(1, sizeof(*desc))) == NULL)
return (-1);
+ RB_INIT(&desc->http_headers);
+ clt->clt_descreq = desc;
+ if ((desc = calloc(1, sizeof(*desc))) == NULL) {
+ /* req will be cleaned up later */
+ return (-1);
+ }
RB_INIT(&desc->http_headers);
- clt->clt_desc = desc;
+ clt->clt_descresp = desc;
return (0);
}
@@ -96,6 +102,8 @@ server_httpdesc_init(struct client *clt)
void
server_httpdesc_free(struct http_descriptor *desc)
{
+ if (desc == NULL)
+ return;
if (desc->http_path != NULL) {
free(desc->http_path);
desc->http_path = NULL;
@@ -118,6 +126,8 @@ server_httpdesc_free(struct http_descriptor *desc)
}
kv_purge(&desc->http_headers);
desc->http_lastheader = NULL;
+ desc->http_method = 0;
+ desc->http_chunked = 0;
}
void
@@ -125,7 +135,7 @@ server_read_http(struct bufferevent *bev, void *arg)
{
struct client *clt = arg;
struct server_config *srv_conf = clt->clt_srv_conf;
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
struct evbuffer *src = EVBUFFER_INPUT(bev);
char *line = NULL, *key, *value;
const char *errstr;
@@ -304,11 +314,36 @@ server_read_http(struct bufferevent *bev, void *arg)
case HTTP_METHOD_GET:
case HTTP_METHOD_HEAD:
case HTTP_METHOD_OPTIONS:
+ /* WebDAV methods */
+ case HTTP_METHOD_COPY:
clt->clt_toread = 0;
break;
case HTTP_METHOD_POST:
case HTTP_METHOD_PUT:
case HTTP_METHOD_RESPONSE:
+ /* WebDAV methods */
+ case HTTP_METHOD_PROPFIND:
+ case HTTP_METHOD_PROPPATCH:
+ case HTTP_METHOD_MKCOL:
+ case HTTP_METHOD_LOCK:
+ case HTTP_METHOD_UNLOCK:
+ case HTTP_METHOD_VERSION_CONTROL:
+ case HTTP_METHOD_REPORT:
+ case HTTP_METHOD_CHECKOUT:
+ case HTTP_METHOD_CHECKIN:
+ case HTTP_METHOD_UNCHECKOUT:
+ case HTTP_METHOD_MKWORKSPACE:
+ case HTTP_METHOD_UPDATE:
+ case HTTP_METHOD_LABEL:
+ case HTTP_METHOD_MERGE:
+ case HTTP_METHOD_BASELINE_CONTROL:
+ case HTTP_METHOD_MKACTIVITY:
+ case HTTP_METHOD_ORDERPATCH:
+ case HTTP_METHOD_ACL:
+ case HTTP_METHOD_MKREDIRECTREF:
+ case HTTP_METHOD_UPDATEREDIRECTREF:
+ case HTTP_METHOD_SEARCH:
+ case HTTP_METHOD_PATCH:
/* HTTP request payload */
if (clt->clt_toread > 0)
bev->readcb = server_read_httpcontent;
@@ -320,10 +355,8 @@ server_read_http(struct bufferevent *bev, void *arg)
}
break;
default:
- /* HTTP handler */
- clt->clt_toread = TOREAD_HTTP_HEADER;
- bev->readcb = server_read_http;
- break;
+ server_abort_http(clt, 405, "method not allowed");
+ return;
}
if (desc->http_chunked) {
/* Chunked transfer encoding */
@@ -518,12 +551,10 @@ server_read_httpchunks(struct bufferevent *bev, void *arg)
void
server_reset_http(struct client *clt)
{
- struct http_descriptor *desc = clt->clt_desc;
struct server *srv = clt->clt_srv;
-
- server_httpdesc_free(desc);
- desc->http_method = 0;
- desc->http_chunked = 0;
+
+ server_httpdesc_free(clt->clt_descreq);
+ server_httpdesc_free(clt->clt_descresp);
clt->clt_headerlen = 0;
clt->clt_line = 0;
clt->clt_done = 0;
@@ -670,12 +701,17 @@ server_abort_http(struct client *clt, u_int code, const char *msg)
void
server_close_http(struct client *clt)
{
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc;
- if (desc == NULL)
- return;
+ desc = clt->clt_descreq;
+ server_httpdesc_free(desc);
+ free(desc);
+ clt->clt_descreq = NULL;
+
+ desc = clt->clt_descresp;
server_httpdesc_free(desc);
free(desc);
+ clt->clt_descresp = NULL;
}
int
@@ -683,7 +719,8 @@ server_response(struct httpd *httpd, struct client *clt)
{
char path[MAXPATHLEN];
char hostname[MAXHOSTNAMELEN];
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
+ struct http_descriptor *resp = clt->clt_descresp;
struct server *srv = clt->clt_srv;
struct server_config *srv_conf = &srv->srv_conf;
struct kv *kv, key, *host;
@@ -733,6 +770,12 @@ server_response(struct httpd *httpd, struct client *clt)
if (host != NULL) {
/* XXX maybe better to turn srv_hosts into a tree */
TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
+#ifdef DEBUG
+ if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
+ DPRINTF("%s: virtual host \"%s\" host \"%s\"",
+ __func__, srv_conf->name, host->kv_value);
+ }
+#endif
if ((srv_conf->flags & SRVFLAG_LOCATION) == 0 &&
fnmatch(srv_conf->name, host->kv_value,
FNM_CASEFOLD) == 0) {
@@ -760,6 +803,11 @@ server_response(struct httpd *httpd, struct client *clt)
if ((desc->http_host = strdup(hostname)) == NULL)
goto fail;
+ /* Now fill in the mandatory parts of the response descriptor */
+ resp->http_method = desc->http_method;
+ if ((resp->http_version = strdup(desc->http_version)) == NULL)
+ goto fail;
+
/* Now search for the location */
srv_conf = server_getlocation(clt, desc->http_path);
@@ -777,6 +825,12 @@ server_getlocation(struct client *clt, const char *path)
/* Now search for the location */
TAILQ_FOREACH(location, &srv->srv_hosts, entry) {
+#ifdef DEBUG
+ if (location->flags & SRVFLAG_LOCATION) {
+ DPRINTF("%s: location \"%s\" path \"%s\"",
+ __func__, location->location, path);
+ }
+#endif
if ((location->flags & SRVFLAG_LOCATION) &&
location->id == srv_conf->id &&
fnmatch(location->location, path, FNM_CASEFOLD) == 0) {
@@ -793,7 +847,8 @@ int
server_response_http(struct client *clt, u_int code,
struct media_type *media, size_t size, time_t mtime)
{
- struct http_descriptor *desc = clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descreq;
+ struct http_descriptor *resp = clt->clt_descresp;
const char *error;
struct kv *ct, *cl;
char tmbuf[32];
@@ -804,27 +859,25 @@ server_response_http(struct client *clt, u_int code,
if (server_log_http(clt, code, size) == -1)
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)
+ if (kv_setkey(&resp->http_pathquery, "%lu", code) == -1 ||
+ kv_set(&resp->http_pathquery, "%s", error) == -1)
return (-1);
/* Add headers */
- if (kv_add(&desc->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
+ if (kv_add(&resp->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
return (-1);
/* Is it a persistent connection? */
if (clt->clt_persist) {
- if (kv_add(&desc->http_headers,
+ if (kv_add(&resp->http_headers,
"Connection", "keep-alive") == NULL)
return (-1);
- } else if (kv_add(&desc->http_headers, "Connection", "close") == NULL)
+ } else if (kv_add(&resp->http_headers, "Connection", "close") == NULL)
return (-1);
/* Set media type */
- if ((ct = kv_add(&desc->http_headers, "Content-Type", NULL)) == NULL ||
+ if ((ct = kv_add(&resp->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)
@@ -832,28 +885,28 @@ server_response_http(struct client *clt, u_int code,
/* Set content length, if specified */
if ((cl =
- kv_add(&desc->http_headers, "Content-Length", NULL)) == NULL ||
+ kv_add(&resp->http_headers, "Content-Length", NULL)) == NULL ||
kv_set(cl, "%ld", size) == -1)
return (-1);
/* Set last modification time */
if (server_http_time(mtime, tmbuf, sizeof(tmbuf)) <= 0 ||
- kv_add(&desc->http_headers, "Last-Modified", tmbuf) == NULL)
+ kv_add(&resp->http_headers, "Last-Modified", tmbuf) == NULL)
return (-1);
/* Date header is mandatory and should be added as late as possible */
if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 ||
- kv_add(&desc->http_headers, "Date", tmbuf) == NULL)
+ kv_add(&resp->http_headers, "Date", tmbuf) == NULL)
return (-1);
/* Write completed header */
if (server_writeresponse_http(clt) == -1 ||
server_bufferevent_print(clt, "\r\n") == -1 ||
- server_headers(clt, server_writeheader_http, NULL) == -1 ||
+ server_headers(clt, resp, server_writeheader_http, NULL) == -1 ||
server_bufferevent_print(clt, "\r\n") == -1)
return (-1);
- if (size == 0 || desc->http_method == HTTP_METHOD_HEAD) {
+ if (size == 0 || resp->http_method == HTTP_METHOD_HEAD) {
bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
if (clt->clt_persist)
clt->clt_toread = TOREAD_HTTP_HEADER;
@@ -869,7 +922,7 @@ server_response_http(struct client *clt, u_int code,
int
server_writeresponse_http(struct client *clt)
{
- struct http_descriptor *desc = (struct http_descriptor *)clt->clt_desc;
+ struct http_descriptor *desc = clt->clt_descresp;
DPRINTF("version: %s rescode: %s resmsg: %s", desc->http_version,
desc->http_rescode, desc->http_resmesg);
@@ -913,11 +966,11 @@ server_writeheader_http(struct client *clt, struct kv *hdr, void *arg)
}
int
-server_headers(struct client *clt,
+server_headers(struct client *clt, void *descp,
int (*hdr_cb)(struct client *, struct kv *, void *), void *arg)
{
struct kv *hdr, *kv;
- struct http_descriptor *desc = (struct http_descriptor *)clt->clt_desc;
+ struct http_descriptor *desc = descp;
RB_FOREACH(hdr, kvtree, &desc->http_headers) {
if ((hdr_cb)(clt, hdr, arg) == -1)
@@ -951,7 +1004,7 @@ server_httpmethod_byname(const char *name)
const char *
server_httpmethod_byid(u_int id)
{
- const char *name = NULL;
+ const char *name = "<UNKNOWN>";
int i;
for (i = 0; http_methods[i].method_name != NULL; i++) {
@@ -1015,7 +1068,7 @@ server_log_http(struct client *clt, u_int code, size_t len)
return (-1);
if ((srv_conf->flags & SRVFLAG_LOG) == 0)
return (0);
- if ((desc = clt->clt_desc) == NULL)
+ if ((desc = clt->clt_descreq) == NULL)
return (-1);
if ((t = time(NULL)) == -1)