summaryrefslogtreecommitdiff
path: root/usr.sbin/hoststated/relay.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-02-27 13:38:59 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-02-27 13:38:59 +0000
commitc9264b75c20efb4a4120a89f107e9771dd42b1bf (patch)
treea37c32994cb34289a2dc16d2ec5eb31ec258545c /usr.sbin/hoststated/relay.c
parente7c46625ff26167cee75d713d172dc7d865df298 (diff)
in addition to actions on request headers, allow to define relay
actions on response headers (the reply sent by backend HTTP servers). the default and slightly faster relay streaming mode will be used if no actions are defined. for example: response change "Server" to "OpenBSD-hoststated/4.1" ok pyr@
Diffstat (limited to 'usr.sbin/hoststated/relay.c')
-rw-r--r--usr.sbin/hoststated/relay.c75
1 files changed, 61 insertions, 14 deletions
diff --git a/usr.sbin/hoststated/relay.c b/usr.sbin/hoststated/relay.c
index ee7926ba114..d407e8d1047 100644
--- a/usr.sbin/hoststated/relay.c
+++ b/usr.sbin/hoststated/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.13 2007/02/26 16:10:24 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.14 2007/02/27 13:38:58 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -273,6 +273,8 @@ relay_protodebug(struct relay *rlay)
{
struct protocol *proto = rlay->proto;
struct protonode *pn;
+ struct proto_tree *tree;
+ const char *name;
fprintf(stderr, "protocol %d: name %s\n", proto->id, proto->name);
fprintf(stderr, "\tflags: 0x%04x\n", proto->flags);
@@ -287,9 +289,15 @@ relay_protodebug(struct relay *rlay)
fprintf(stderr, "http\n");
break;
}
- RB_FOREACH(pn, proto_tree, &proto->tree) {
+
+ name = "request";
+ tree = &proto->request_tree;
+ show:
+ RB_FOREACH(pn, proto_tree, tree) {
fprintf(stderr, "\t\t");
+ fprintf(stderr, "%s ", name);
+
switch (pn->type) {
case NODE_TYPE_HEADER:
break;
@@ -334,6 +342,11 @@ relay_protodebug(struct relay *rlay)
}
fprintf(stderr, "\n");
}
+ if (tree == &proto->request_tree) {
+ name = "response";
+ tree = &proto->response_tree;
+ goto show;
+ }
}
void
@@ -597,6 +610,7 @@ relay_connected(int fd, short sig, void *arg)
{
struct session *con = (struct session *)arg;
struct relay *rlay = (struct relay *)con->relay;
+ struct protocol *proto = rlay->proto;
evbuffercb outrd = relay_read;
evbuffercb outwr = relay_write;
struct bufferevent *bev;
@@ -609,6 +623,25 @@ relay_connected(int fd, short sig, void *arg)
DPRINTF("relay_connected: session %d: %ssuccessful",
con->id, rlay->proto->lateconnect ? "late connect " : "");
+ switch (rlay->proto->type) {
+ case RELAY_PROTO_HTTP:
+ /* Check the servers's HTTP response */
+ if (!RB_EMPTY(&rlay->proto->response_tree)) {
+ outrd = relay_read_http;
+ if ((con->out.nodes = calloc(proto->response_nodes,
+ sizeof(u_int8_t))) == NULL) {
+ relay_close(con, "failed to allocate nodes");
+ return;
+ }
+ }
+ break;
+ case RELAY_PROTO_TCP:
+ /* Use defaults */
+ break;
+ default:
+ fatalx("relay_input: unknown protocol");
+ }
+
/*
* Relay <-> Server
*/
@@ -639,11 +672,14 @@ relay_input(struct session *con)
switch (rlay->proto->type) {
case RELAY_PROTO_HTTP:
/* Check the client's HTTP request */
- inrd = relay_read_http;
- if ((con->in.nodes = calloc(proto->nodecount,
- sizeof(u_int8_t))) == NULL) {
- relay_close(con, "failed to allocate node buffer");
- return;
+ if (!RB_EMPTY(&rlay->proto->request_tree) ||
+ proto->lateconnect) {
+ inrd = relay_read_http;
+ if ((con->in.nodes = calloc(proto->request_nodes,
+ sizeof(u_int8_t))) == NULL) {
+ relay_close(con, "failed to allocate nodes");
+ return;
+ }
}
break;
case RELAY_PROTO_TCP:
@@ -1038,7 +1074,9 @@ relay_read_http(struct bufferevent *bev, void *arg)
* Identify and handle specific HTTP request methods
*/
if (cre->line == 1) {
- if (strcmp("GET", pk.key) == 0)
+ if (cre->dir == RELAY_DIR_RESPONSE)
+ cre->method = HTTP_METHOD_RESPONSE;
+ else if (strcmp("GET", pk.key) == 0)
cre->method = HTTP_METHOD_GET;
else if (strcmp("HEAD", pk.key) == 0)
cre->method = HTTP_METHOD_HEAD;
@@ -1055,7 +1093,8 @@ relay_read_http(struct bufferevent *bev, void *arg)
else if (strcmp("CONNECT", pk.key) == 0)
cre->method = HTTP_METHOD_CONNECT;
} else if ((cre->method == HTTP_METHOD_POST ||
- cre->method == HTTP_METHOD_PUT) &&
+ cre->method == HTTP_METHOD_PUT ||
+ cre->method == HTTP_METHOD_RESPONSE) &&
strcasecmp("Content-Length", pk.key) == 0) {
/*
* Need to read data from the client after the
@@ -1077,11 +1116,12 @@ relay_read_http(struct bufferevent *bev, void *arg)
cre->chunked = 1;
/* Match the HTTP header */
- if ((pn = RB_FIND(proto_tree, &proto->tree, &pk)) == NULL)
+ if ((pn = RB_FIND(proto_tree, cre->tree, &pk)) == NULL)
goto next;
/* Decode the URL */
- if (pn->flags & PNFLAG_LOOKUP_URL) {
+ if (pn->flags & PNFLAG_LOOKUP_URL &&
+ cre->dir == RELAY_DIR_REQUEST) {
url = strdup(pk.value);
if (url == NULL)
goto next;
@@ -1105,7 +1145,7 @@ relay_read_http(struct bufferevent *bev, void *arg)
continue;
*pkv.value++ = '\0';
if ((pnv = RB_FIND(proto_tree,
- &proto->tree, &pkv)) == NULL)
+ cre->tree, &pkv)) == NULL)
continue;
ret = relay_handle_http(cre, pnv, &pkv, 0);
if (ret == 1)
@@ -1140,7 +1180,7 @@ next:
continue;
}
if (cre->done) {
- RB_FOREACH(pn, proto_tree, &proto->tree) {
+ RB_FOREACH(pn, proto_tree, cre->tree) {
if (cre->nodes[pn->id]) {
cre->nodes[pn->id] = 0;
continue;
@@ -1194,6 +1234,7 @@ next:
break;
case HTTP_METHOD_POST:
case HTTP_METHOD_PUT:
+ case HTTP_METHOD_RESPONSE:
/* HTTP request payload */
if (cre->toread) {
bev->readcb = relay_read_httpcontent;
@@ -1220,7 +1261,8 @@ next:
cre->done = 0;
cre->chunked = 0;
- if (proto->lateconnect && cre->dst->bev == NULL &&
+ if (cre->dir == RELAY_DIR_REQUEST &&
+ proto->lateconnect && cre->dst->bev == NULL &&
relay_connect(con) == -1) {
relay_close(con, "session failed");
return;
@@ -1284,6 +1326,7 @@ void
relay_accept(int fd, short sig, void *arg)
{
struct relay *rlay = (struct relay *)arg;
+ struct protocol *proto = rlay->proto;
struct session *con = NULL;
struct ctl_natlook *cnl = NULL;
socklen_t slen;
@@ -1313,6 +1356,10 @@ relay_accept(int fd, short sig, void *arg)
con->relay = rlay;
con->id = ++relay_conid;
con->outkey = rlay->dstkey;
+ con->in.tree = &proto->request_tree;
+ con->out.tree = &proto->response_tree;
+ con->in.dir = RELAY_DIR_REQUEST;
+ con->out.dir = RELAY_DIR_RESPONSE;
if (gettimeofday(&con->tv_start, NULL))
goto err;
bcopy(&con->tv_start, &con->tv_last, sizeof(con->tv_last));