From 720c14e513bba2c96fd407d06b2b9afd59feb651 Mon Sep 17 00:00:00 2001 From: reyk Date: Wed, 6 Aug 2014 09:36:31 +0000 Subject: [PATCH] Adjust the read/write watermarks according to the TCP send buffer. This fixes sending of large files. Previously, httpd was reading the input file too quickly and could run out of memory when filling the input buffer. Found by jsg@ OK florian@ --- usr.sbin/httpd/httpd.h | 3 ++- usr.sbin/httpd/server.c | 14 +++++++++++++- usr.sbin/httpd/server_file.c | 6 +++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h index 0983ce22500..449c10fc59c 100644 --- a/usr.sbin/httpd/httpd.h +++ b/usr.sbin/httpd/httpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.h,v 1.47 2014/08/06 02:04:42 jsing Exp $ */ +/* $OpenBSD: httpd.h,v 1.48 2014/08/06 09:36:31 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -273,6 +273,7 @@ struct client { struct evbuffer *clt_output; struct event clt_ev; void *clt_desc; + int clt_sndbufsiz; int clt_fd; struct ressl *clt_ressl_ctx; diff --git a/usr.sbin/httpd/server.c b/usr.sbin/httpd/server.c index e3727aed1b9..b9d3c757f3f 100644 --- a/usr.sbin/httpd/server.c +++ b/usr.sbin/httpd/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.31 2014/08/06 04:39:50 jsg Exp $ */ +/* $OpenBSD: server.c,v 1.32 2014/08/06 09:36:31 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -631,6 +631,7 @@ server_input(struct client *clt) struct server_config *srv_conf = clt->clt_srv_conf; evbuffercb inrd = server_read; evbuffercb inwr = server_write; + socklen_t slen; if (server_httpdesc_init(clt) == -1) { server_close(clt, "failed to allocate http descriptor"); @@ -640,6 +641,13 @@ server_input(struct client *clt) clt->clt_toread = TOREAD_HTTP_HEADER; inrd = server_read_http; + slen = sizeof(clt->clt_sndbufsiz); + if (getsockopt(clt->clt_s, SOL_SOCKET, SO_SNDBUF, + &clt->clt_sndbufsiz, &slen) == -1) { + server_close(clt, "failed to get send buffer size"); + return; + } + /* * Client <-> Server */ @@ -657,6 +665,10 @@ server_input(struct client *clt) server_ssl_writecb, clt->clt_bev); } + /* Adjust write watermark to the socket buffer output size */ + bufferevent_setwatermark(clt->clt_bev, EV_WRITE, + clt->clt_sndbufsiz, 0); + bufferevent_settimeout(clt->clt_bev, srv_conf->timeout.tv_sec, srv_conf->timeout.tv_sec); bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE); diff --git a/usr.sbin/httpd/server_file.c b/usr.sbin/httpd/server_file.c index 4989f195663..5b72aaf4683 100644 --- a/usr.sbin/httpd/server_file.c +++ b/usr.sbin/httpd/server_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_file.c,v 1.29 2014/08/04 17:43:20 reyk Exp $ */ +/* $OpenBSD: server_file.c,v 1.30 2014/08/06 09:36:31 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -201,6 +201,10 @@ server_file(struct httpd *env, struct client *clt) goto fail; } + /* Adjust read watermark to the socket output buffer size */ + bufferevent_setwatermark(clt->clt_srvbev, EV_READ, 0, + clt->clt_sndbufsiz); + bufferevent_settimeout(clt->clt_srvbev, srv_conf->timeout.tv_sec, srv_conf->timeout.tv_sec); bufferevent_enable(clt->clt_srvbev, EV_READ); -- 2.20.1