diff options
author | Pierre-Yves Ritschard <pyr@cvs.openbsd.org> | 2007-01-12 16:43:02 +0000 |
---|---|---|
committer | Pierre-Yves Ritschard <pyr@cvs.openbsd.org> | 2007-01-12 16:43:02 +0000 |
commit | c5afe0ba568d248ece5fca0f35c20df84a862bd2 (patch) | |
tree | 00fe7910a0ecaeda88215922e4c0772de83ae9b8 /usr.sbin/relayd | |
parent | 2bebcfa9da8ac1420312c59ac375bbb6c4880cb0 (diff) |
eliminate duplicate tcp read/write code.
ok claudio@, reyk@
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r-- | usr.sbin/relayd/check_tcp.c | 130 | ||||
-rw-r--r-- | usr.sbin/relayd/parse.y | 38 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 12 |
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); |