Hi,
benno@ triggered a crash in with previous relayd splicing diff, so
here is the fixed version for -current.
bluhm
Index: usr.sbin/relayd/relay.c
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.160
diff -u -p -r1.160 relay.c
--- usr.sbin/relayd/relay.c 18 Dec 2012 15:58:25 - 1.160
+++ usr.sbin/relayd/relay.c 28 Dec 2012 21:29:39 -
@@ -70,9 +70,6 @@ void relay_input(struct rsession *);
u_int32_t relay_hash_addr(struct sockaddr_storage *, u_int32_t);
-int relay_splice(struct ctl_relay_event *);
-int relay_splicelen(struct ctl_relay_event *);
-
SSL_CTX*relay_ssl_ctx_create(struct relay *);
voidrelay_ssl_transaction(struct rsession *,
struct ctl_relay_event *);
@@ -643,6 +640,7 @@ relay_connected(int fd, short sig, void
case RELAY_PROTO_HTTP:
/* Check the servers's HTTP response */
if (!RB_EMPTY(rlay-rl_proto-response_tree)) {
+ con-se_out.toread = TOREAD_HTTP_HEADER;
outrd = relay_read_http;
if ((con-se_out.nodes = calloc(proto-response_nodes,
sizeof(u_int8_t))) == NULL) {
@@ -699,6 +697,7 @@ relay_input(struct rsession *con)
/* Check the client's HTTP request */
if (!RB_EMPTY(rlay-rl_proto-request_tree) ||
proto-lateconnect) {
+ con-se_in.toread = TOREAD_HTTP_HEADER;
inrd = relay_read_http;
if ((con-se_in.nodes = calloc(proto-request_nodes,
sizeof(u_int8_t))) == NULL) {
@@ -741,10 +740,19 @@ relay_write(struct bufferevent *bev, voi
{
struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
struct rsession *con = cre-con;
+
if (gettimeofday(con-se_tv_last, NULL) == -1)
- con-se_done = 1;
+ goto fail;
if (con-se_done)
- relay_close(con, last write (done));
+ goto done;
+ if (relay_splice(cre-dst) == -1)
+ goto fail;
+ return;
+ done:
+ relay_close(con, last write (done));
+ return;
+ fail:
+ relay_close(con, strerror(errno));
}
void
@@ -822,11 +830,31 @@ relay_splice(struct ctl_relay_event *cre
(proto-tcpflags TCPFLAG_NSPLICE))
return (0);
- if (cre-bev-readcb != relay_read)
+ if (cre-splicelen = 0)
return (0);
+ /* still not connected */
+ if (cre-bev == NULL || cre-dst-bev == NULL)
+ return (0);
+
+ if (! (cre-toread == TOREAD_UNLIMITED || cre-toread 0)) {
+ DPRINTF(%s: session %d: splice dir %d, nothing to read %lld,
+ __func__, con-se_id, cre-dir, cre-toread);
+ return (0);
+ }
+
+ /* do not splice before buffers have not been completely fushed */
+ if (EVBUFFER_LENGTH(cre-bev-input) ||
+ EVBUFFER_LENGTH(cre-dst-bev-output)) {
+ DPRINTF(%s: session %d: splice dir %d, dirty buffer,
+ __func__, con-se_id, cre-dir);
+ bufferevent_disable(cre-bev, EV_READ);
+ return (2);
+ }
+
bzero(sp, sizeof(sp));
sp.sp_fd = cre-dst-s;
+ sp.sp_max = cre-toread 0 ? cre-toread : 0;
sp.sp_idle = rlay-rl_conf.timeout;
if (setsockopt(cre-s, SOL_SOCKET, SO_SPLICE, sp, sizeof(sp)) == -1) {
log_debug(%s: session %d: splice dir %d failed: %s,
@@ -834,8 +862,11 @@ relay_splice(struct ctl_relay_event *cre
return (-1);
}
cre-splicelen = 0;
- DPRINTF(%s: session %d: splice dir %d successful,
- __func__, con-se_id, cre-dir);
+ bufferevent_enable(cre-bev, EV_READ);
+
+ DPRINTF(%s: session %d: splice dir %d, maximum %lld, successful,
+ __func__, con-se_id, cre-dir, cre-toread);
+
return (1);
}
@@ -846,12 +877,19 @@ relay_splicelen(struct ctl_relay_event *
off_tlen;
socklen_toptlen;
+ if (cre-splicelen 0)
+ return (0);
+
optlen = sizeof(len);
if (getsockopt(cre-s, SOL_SOCKET, SO_SPLICE, len, optlen) == -1) {
log_debug(%s: session %d: splice dir %d get length failed: %s,
__func__, con-se_id, cre-dir, strerror(errno));
return (-1);
}
+
+ DPRINTF(%s: session %d: splice dir %d, length %lld,
+ __func__, con-se_id, cre-dir, len);
+
if (len cre-splicelen) {
cre-splicelen = len;
return (1);
@@ -859,6 +897,20 @@ relay_splicelen(struct ctl_relay_event *
return (0);
}
+int
+relay_spliceadjust(struct ctl_relay_event