summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd
diff options
context:
space:
mode:
authorPierre-Yves Ritschard <pyr@cvs.openbsd.org>2007-01-12 16:43:02 +0000
committerPierre-Yves Ritschard <pyr@cvs.openbsd.org>2007-01-12 16:43:02 +0000
commitc5afe0ba568d248ece5fca0f35c20df84a862bd2 (patch)
tree00fe7910a0ecaeda88215922e4c0772de83ae9b8 /usr.sbin/relayd
parent2bebcfa9da8ac1420312c59ac375bbb6c4880cb0 (diff)
eliminate duplicate tcp read/write code.
ok claudio@, reyk@
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r--usr.sbin/relayd/check_tcp.c130
-rw-r--r--usr.sbin/relayd/parse.y38
-rw-r--r--usr.sbin/relayd/relayd.h12
3 files changed, 144 insertions, 36 deletions
diff --git a/usr.sbin/relayd/check_tcp.c b/usr.sbin/relayd/check_tcp.c
index fc365c18d9d..f5142118c8e 100644
--- a/usr.sbin/relayd/check_tcp.c
+++ b/usr.sbin/relayd/check_tcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_tcp.c,v 1.9 2007/01/11 18:05:08 reyk Exp $ */
+/* $OpenBSD: check_tcp.c,v 1.10 2007/01/12 16:43:01 pyr Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -33,7 +33,9 @@
#include "hoststated.h"
void tcp_write(int, short, void *);
-void tcp_host_up(int s, struct ctl_tcp_event *);
+void tcp_host_up(int, struct ctl_tcp_event *);
+void tcp_send_req(int, short, void *);
+void tcp_read_buf(int, short, void *);
void
check_tcp(struct ctl_tcp_event *cte)
@@ -123,17 +125,127 @@ tcp_host_up(int s, struct ctl_tcp_event *cte)
case CHECK_TCP:
close(s);
hce_notify_done(cte->host, "tcp_host_up: success");
- break;
+ return;
case CHECK_HTTP_CODE:
+ cte->validate_read = NULL;
+ cte->validate_close = check_http_code;
+ break;
case CHECK_HTTP_DIGEST:
- event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, send_http_request,
- &cte->tv_start, &cte->table->timeout, cte);
+ cte->validate_read = NULL;;
+ cte->validate_close = check_http_digest;
break;
case CHECK_SEND_EXPECT:
- event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, start_send_expect,
- &cte->tv_start, &cte->table->timeout, cte);
+ cte->validate_read = check_send_expect;
+ cte->validate_close = check_send_expect;
break;
- default:
- fatalx("tcp_host_up: unhandled check type");
}
+ cte->req = cte->table->sendbuf;
+
+ if (cte->table->sendbuf != NULL) {
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_send_req,
+ &cte->tv_start, &cte->table->timeout, cte);
+ return;
+ }
+
+ log_debug("tcp_host_up: nothing to write");
+ if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
+ fatalx("tcp_host_up: cannot create dynamic buffer");
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf,
+ &cte->tv_start, &cte->table->timeout, cte);
+}
+
+void
+tcp_send_req(int s, short event, void *arg)
+{
+ struct ctl_tcp_event *cte = arg;
+ int bs;
+ int pos;
+ int len;
+
+ if (event == EV_TIMEOUT) {
+ cte->host->up = HOST_DOWN;
+ hce_notify_done(cte->host, "tcp_send_req: timeout");
+ return;
+ }
+ pos = 0;
+ len = strlen(cte->req);
+ do {
+ bs = write(s, cte->req + pos, len);
+ if (bs == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto retry;
+ log_warnx("tcp_send_req: cannot send request");
+ cte->host->up = HOST_DOWN;
+ hce_notify_done(cte->host, "tcp_send_req: write");
+ return;
+ }
+ pos += bs;
+ len -= bs;
+ } while (len > 0);
+
+ log_debug("tcp_send_req: write done");
+ if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
+ fatalx("tcp_send_req: cannot create dynamic buffer");
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf,
+ &cte->tv_start, &cte->table->timeout, cte);
+ return;
+
+ retry:
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_send_req,
+ &cte->tv_start, &cte->table->timeout, cte);
+}
+
+void
+tcp_read_buf(int s, short event, void *arg)
+{
+ ssize_t br;
+ char rbuf[SMALL_READ_BUF_SIZE];
+ struct ctl_tcp_event *cte = arg;
+
+ if (event == EV_TIMEOUT) {
+ cte->host->up = HOST_DOWN;
+ buf_free(cte->buf);
+ hce_notify_done(cte->host, "tcp_read_buf: timeout");
+ return;
+ }
+
+ log_debug("reading");
+ bzero(rbuf, sizeof(rbuf));
+ br = read(s, rbuf, sizeof(rbuf) - 1);
+ if (br == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto retry;
+ cte->host->up = HOST_DOWN;
+ buf_free(cte->buf);
+ hce_notify_done(cte->host, "tcp_read_buf: read failed");
+ return;
+ } else if (br == 0) {
+ cte->host->up = HOST_DOWN;
+ (void)cte->validate_close(cte);
+ close(cte->s);
+ buf_free(cte->buf);
+ if (cte->host->up == HOST_UP)
+ hce_notify_done(cte->host, "check succeeded");
+ else
+ hce_notify_done(cte->host, "check failed");
+ return;
+ }
+ buf_add(cte->buf, rbuf, br);
+ if (cte->validate_read != NULL) {
+ log_debug("calling check");
+ if (cte->validate_read(cte) != 0)
+ goto retry;
+
+ close(cte->s);
+ buf_free(cte->buf);
+ if (cte->host->up == HOST_UP)
+ hce_notify_done(cte->host, "check succeeded");
+ else
+ hce_notify_done(cte->host, "check failed");
+ return;
+ }
+retry:
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf,
+ &cte->tv_start, &cte->table->timeout, cte);
+
}
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index e3428244243..541bb752cd5 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.15 2007/01/09 13:50:11 pyr Exp $ */
+/* $OpenBSD: parse.y,v 1.16 2007/01/12 16:43:01 pyr Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -176,15 +176,12 @@ varset : STRING '=' STRING {
;
sendbuf : NOTHING {
- bzero(table->sendbuf, sizeof(table->sendbuf));
+ table->sendbuf = NULL;
}
| STRING {
- if (strlcpy(table->sendbuf, $1, sizeof(table->sendbuf))
- >= sizeof(table->sendbuf)) {
- yyerror("yyparse: send buffer truncated");
- free($1);
- YYERROR;
- }
+ table->sendbuf = strdup($1);
+ if (table->sendbuf == NULL)
+ fatal("out of memory");
free($1);
}
;
@@ -386,30 +383,25 @@ tableoptsl : host {
| CHECK HTTP STRING CODE number {
table->check = CHECK_HTTP_CODE;
table->retcode = $5;
- if (strlcpy(table->path, $3, sizeof(table->path)) >=
- sizeof(table->path)) {
- yyerror("http path truncated");
- free($3);
- YYERROR;
- }
+ asprintf(&table->sendbuf, "HEAD %s HTTP/1.0\r\n\r\n",
+ $3);
+ free($3);
+ if (table->sendbuf == NULL)
+ fatal("out of memory");
}
| CHECK HTTP STRING DIGEST STRING {
table->check = CHECK_HTTP_DIGEST;
- if (strlcpy(table->path, $3, sizeof(table->path)) >=
- sizeof(table->path)) {
- yyerror("http path truncated");
- free($3);
- free($5);
- YYERROR;
- }
+ asprintf(&table->sendbuf, "GET %s HTTP/1.0\r\n\r\n",
+ $3);
+ free($3);
+ if (table->sendbuf == NULL)
+ fatal("out of memory");
if (strlcpy(table->digest, $5,
sizeof(table->digest)) >= sizeof(table->digest)) {
yyerror("http digest truncated");
- free($3);
free($5);
YYERROR;
}
- free($3);
free($5);
}
| CHECK SEND sendbuf EXPECT STRING {
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index dc801ea20c9..7828e60f8ce 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.14 2007/01/11 18:05:08 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.15 2007/01/12 16:43:01 pyr Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -135,11 +135,14 @@ struct ctl_icmp_event {
struct ctl_tcp_event {
int s;
+ char *req;
struct buf *buf;
struct host *host;
struct table *table;
struct timeval tv_start;
struct event ev;
+ int (*validate_read)(struct ctl_tcp_event *);
+ int (*validate_close)(struct ctl_tcp_event *);
};
struct address {
@@ -191,7 +194,7 @@ struct table {
struct timeval timeout;
char name[TABLE_NAME_SIZE];
char path[MAXPATHLEN];
- char sendbuf[64];
+ char *sendbuf;
char exbuf[64];
char digest[41]; /* length of sha1 digest * 2 */
struct hostlist hosts;
@@ -347,10 +350,11 @@ void check_icmp(struct hoststated *, struct timeval *);
void check_tcp(struct ctl_tcp_event *);
/* check_http.c */
-void send_http_request(int, short, void *);
+int check_http_code(struct ctl_tcp_event *);
+int check_http_digest(struct ctl_tcp_event *);
/* check_send_expect.c */
-void start_send_expect(int, short, void *);
+int check_send_expect(struct ctl_tcp_event *);
/* hoststated.c */
struct host *host_find(struct hoststated *, objid_t);