On Fri, 2018-01-05 at 00:12 +0100, Alexander Bluhm wrote:
> On Wed, Dec 13, 2017 at 07:42:03AM +0100, Claudio Jeker wrote:
> > On Wed, Dec 13, 2017 at 12:25:39AM +0000, Rivo Nurges wrote:
> > > If you http PUT a "big" file through relayd, server<>relay read
> > > side
> > > will eventually get a EVBUFFER_TIMEOUT. Nothing comes back from
> > > the
> > > server until the PUT is done. I disabled server read timeouts for
> > > PUT
> > > requests.
> >
> > I have seen something similar and came to the conclusion that the
> > timeout
> > handling of relayd is not correct. As long as traffic is flowing
> > the
> > timeout should be reset (at least that is what every other
> > implementation
> > does). This is not really happening in relayd. I have seen this on
> > GET
> > requests that are huge (timeout hits in the middle of the transimit
> > and
> > kills the session).
>
> I have commited more regression tests that check the timeout with
> unidirectional traffic flow. I could not find an error. In theory
> when we have an idle timeout in one direction, relayd checks wheter
> there is trafic flowing in the other direction. The tests set the
> timeout to 2 seconds and send 5 bytes while sleeping one second
> between each byte. The timeout does not trigger.
>
> So it seems that you encounter some corner case. I need more
> information.
>
> - Do you use http or https?
> - Do you use persistent connections?
> - Do you use chunked encoding?
> - Does it only occur with http or also with plain tcp?
> - Does disabling socket splicing help?
> - Does it happen when the connect to the server is slow?
>
> While testing I saw that with socket splicing the timeout is handled
> twice. We get an wakeup from the idle splicing and from libevent
> timeout. I think it is sufficient to only use the idle splicing
> if it is available.
>
> Does this diff help?
>
> bluhm
>
> Index: relay.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
> retrieving revision 1.237
> diff -u -p -r1.237 relay.c
> --- relay.c 27 Dec 2017 15:53:30 -0000 1.237
> +++ relay.c 4 Jan 2018 22:44:20 -0000
> @@ -733,16 +733,21 @@ relay_connected(int fd, short sig, void
> if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->tls !=
> NULL))
> relay_tls_connected(out);
>
> - bufferevent_settimeout(bev,
> - rlay->rl_conf.timeout.tv_sec, rlay-
> >rl_conf.timeout.tv_sec);
> bufferevent_setwatermark(bev, EV_WRITE,
> RELAY_MIN_PREFETCHED * proto->tcpbufsiz, 0);
> bufferevent_enable(bev, EV_READ|EV_WRITE);
> if (con->se_in.bev)
> bufferevent_enable(con->se_in.bev, EV_READ);
>
> - if (relay_splice(&con->se_out) == -1)
> + switch (relay_splice(&con->se_out)) {
> + case 0:
> + bufferevent_settimeout(bev,
> + rlay->rl_conf.timeout.tv_sec, rlay-
> >rl_conf.timeout.tv_sec);
> + break;
> + case -1:
> relay_close(con, strerror(errno));
> + break;
> + }
> }
>
> void
> @@ -784,14 +789,19 @@ relay_input(struct rsession *con)
> if ((rlay->rl_conf.flags & F_TLS) && con->se_in.tls != NULL)
> relay_tls_connected(&con->se_in);
>
> - bufferevent_settimeout(con->se_in.bev,
> - rlay->rl_conf.timeout.tv_sec, rlay-
> >rl_conf.timeout.tv_sec);
> bufferevent_setwatermark(con->se_in.bev, EV_WRITE,
> RELAY_MIN_PREFETCHED * proto->tcpbufsiz, 0);
> bufferevent_enable(con->se_in.bev, EV_READ|EV_WRITE);
>
> - if (relay_splice(&con->se_in) == -1)
> + switch (relay_splice(&con->se_in)) {
> + case 0:
> + bufferevent_settimeout(con->se_in.bev,
> + rlay->rl_conf.timeout.tv_sec, rlay-
> >rl_conf.timeout.tv_sec);
> + break;
> + case -1:
> relay_close(con, strerror(errno));
> + break;
> + }
> }
>
> void