From 035d0863169ed32409a20f64a48de768442ddadc Mon Sep 17 00:00:00 2001 From: petter Date: Wed, 19 Nov 2008 14:13:57 +0000 Subject: [PATCH] Added support for setting read timeouts for backend requests (first_byte_timeout and between_bytes_timeout), in addition to make the connect_timeout available for the bereq object in vcl_miss and vcl_fetch. first_byte_timeout is a read timeout from the connection to the backend is created to when the first byte arrives. It can be set as a parameter to varnish, as a field in the backend declaration or as bereq.first_byte_timeout in vcl_miss and vcl_pass. between_bytes_timeout is a read timeout between each read from the backend. It can be set as a parameter to varnish, as a field in the backend declaration or as bereq.between_bytes_timeout in vcl_miss and vcl_pass. The time unit for these timeout values are seconds. NOTE: The connect_timeout previously used milliseconds as time unit, so beware. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3406 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 7 +++ varnish-cache/bin/varnishd/cache_backend.c | 2 +- varnish-cache/bin/varnishd/cache_backend.h | 2 + .../bin/varnishd/cache_backend_cfg.c | 2 + varnish-cache/bin/varnishd/cache_center.c | 2 + varnish-cache/bin/varnishd/cache_fetch.c | 7 ++- varnish-cache/bin/varnishd/cache_session.c | 38 ++++++++++++++ varnish-cache/bin/varnishd/cache_vrt.c | 42 ++++++++++++++++ varnish-cache/bin/varnishd/heritage.h | 6 ++- varnish-cache/bin/varnishd/mgt_param.c | 50 +++++++++++++++++-- .../bin/varnishtest/tests/b00020.vtc | 34 +++++++++++++ .../bin/varnishtest/tests/b00021.vtc | 37 ++++++++++++++ .../bin/varnishtest/tests/b00022.vtc | 39 +++++++++++++++ .../bin/varnishtest/tests/b00023.vtc | 31 ++++++++++++ .../bin/varnishtest/tests/b00024.vtc | 34 +++++++++++++ .../bin/varnishtest/tests/b00025.vtc | 36 +++++++++++++ .../bin/varnishtest/tests/b00026.vtc | 50 +++++++++++++++++++ varnish-cache/include/libvarnish.h | 1 + varnish-cache/include/vrt.h | 2 + varnish-cache/include/vrt_obj.h | 6 +++ varnish-cache/lib/libvarnish/tcp.c | 12 +++++ varnish-cache/lib/libvcl/vcc_backend.c | 16 ++++++ varnish-cache/lib/libvcl/vcc_fixed_token.c | 15 ++++-- varnish-cache/lib/libvcl/vcc_gen_obj.tcl | 15 ++++++ varnish-cache/lib/libvcl/vcc_obj.c | 15 ++++++ 25 files changed, 491 insertions(+), 10 deletions(-) create mode 100644 varnish-cache/bin/varnishtest/tests/b00020.vtc create mode 100644 varnish-cache/bin/varnishtest/tests/b00021.vtc create mode 100644 varnish-cache/bin/varnishtest/tests/b00022.vtc create mode 100644 varnish-cache/bin/varnishtest/tests/b00023.vtc create mode 100644 varnish-cache/bin/varnishtest/tests/b00024.vtc create mode 100644 varnish-cache/bin/varnishtest/tests/b00025.vtc create mode 100644 varnish-cache/bin/varnishtest/tests/b00026.vtc diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 03581566..aa286541 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -337,6 +337,11 @@ struct sess { double t_resp; double t_end; + /* Timeouts */ + double connect_timeout; + double first_byte_timeout; + double between_bytes_timeout; + /* Acceptable grace period */ double grace; @@ -538,6 +543,8 @@ struct sess *SES_New(const struct sockaddr *addr, unsigned len); void SES_Delete(struct sess *sp); void SES_RefSrcAddr(struct sess *sp); void SES_Charge(struct sess *sp); +void SES_ResetBackendTimeouts(struct sess *sp); +void SES_InheritBackendTimeouts(struct sess *sp); /* cache_shmlog.c */ void VSL_Init(void); diff --git a/varnish-cache/bin/varnishd/cache_backend.c b/varnish-cache/bin/varnishd/cache_backend.c index 8dfa41bd..ee6eb207 100644 --- a/varnish-cache/bin/varnishd/cache_backend.c +++ b/varnish-cache/bin/varnishd/cache_backend.c @@ -95,7 +95,7 @@ VBE_TryConnect(const struct sess *sp, int pf, const struct sockaddr *sa, if (s < 0) return (s); - tmo = params->connect_timeout; + tmo = (int)(sp->connect_timeout * 1000); if (bp->connect_timeout > 10e-3) tmo = (int)(bp->connect_timeout * 1000); diff --git a/varnish-cache/bin/varnishd/cache_backend.h b/varnish-cache/bin/varnishd/cache_backend.h index a52551de..0cf52188 100644 --- a/varnish-cache/bin/varnishd/cache_backend.h +++ b/varnish-cache/bin/varnishd/cache_backend.h @@ -104,6 +104,8 @@ struct backend { char *ident; char *vcl_name; double connect_timeout; + double first_byte_timeout; + double between_bytes_timeout; uint32_t hash; diff --git a/varnish-cache/bin/varnishd/cache_backend_cfg.c b/varnish-cache/bin/varnishd/cache_backend_cfg.c index 1c1013c0..50a557b0 100644 --- a/varnish-cache/bin/varnishd/cache_backend_cfg.c +++ b/varnish-cache/bin/varnishd/cache_backend_cfg.c @@ -222,6 +222,8 @@ VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb) REPLACE(b->hosthdr, vb->hosthdr); b->connect_timeout = vb->connect_timeout; + b->first_byte_timeout = vb->first_byte_timeout; + b->between_bytes_timeout = vb->between_bytes_timeout; b->max_conn = vb->max_connections; /* diff --git a/varnish-cache/bin/varnishd/cache_center.c b/varnish-cache/bin/varnishd/cache_center.c index f40a78f2..ffcdc6f0 100644 --- a/varnish-cache/bin/varnishd/cache_center.c +++ b/varnish-cache/bin/varnishd/cache_center.c @@ -845,6 +845,8 @@ cnt_recv(struct sess *sp) CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); AZ(sp->obj); + SES_ResetBackendTimeouts(sp); + /* By default we use the first backend */ AZ(sp->director); sp->director = sp->vcl->director[0]; diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index f44489c9..3da90a4e 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -336,6 +336,8 @@ Fetch(struct sess *sp) if (sp->vbe == NULL) return (__LINE__); vc = sp->vbe; + /* Inherit the backend timeouts from the selected backend */ + SES_InheritBackendTimeouts(sp); /* * Now that we know our backend, we can set a default Host: @@ -369,8 +371,11 @@ Fetch(struct sess *sp) VSL_stats->backend_req++; HTC_Init(htc, bereq->ws, vc->fd); - do + TCP_set_read_timeout(vc->fd, sp->first_byte_timeout); + do { i = HTC_Rx(htc); + TCP_set_read_timeout(vc->fd, sp->between_bytes_timeout); + } while (i == 0); if (i < 0) { diff --git a/varnish-cache/bin/varnishd/cache_session.c b/varnish-cache/bin/varnishd/cache_session.c index a57d803a..fa7e741d 100644 --- a/varnish-cache/bin/varnishd/cache_session.c +++ b/varnish-cache/bin/varnishd/cache_session.c @@ -58,6 +58,7 @@ #include "shmlog.h" #include "cache.h" +#include "cache_backend.h" /*--------------------------------------------------------------------*/ @@ -316,6 +317,8 @@ SES_New(const struct sockaddr *addr, unsigned len) sp->http = &sm->http[0]; sp->http0 = &sm->http[1]; + SES_ResetBackendTimeouts(sp); + return (sp); } @@ -367,3 +370,38 @@ SES_Init() Lck_New(&stat_mtx); Lck_New(&ses_mem_mtx); } + +void +SES_ResetBackendTimeouts(struct sess *sp) +{ + sp->connect_timeout = params->connect_timeout; + sp->first_byte_timeout = params->first_byte_timeout; + sp->between_bytes_timeout = params->between_bytes_timeout; +} + +void +SES_InheritBackendTimeouts(struct sess *sp) +{ + struct backend *be = NULL; + + AN(sp); + AN(sp->vbe); + AN(sp->vbe->backend); + + be = sp->vbe->backend; + /* + * We only inherit the backend's timeout if the session timeout + * has not already been set in the VCL, as the order of precedence + * is parameter < backend definition < VCL. + */ + if (be->connect_timeout > 1e-3 && + sp->connect_timeout == params->connect_timeout) + sp->connect_timeout = be->connect_timeout; + if (be->first_byte_timeout > 1e-3 && + sp->first_byte_timeout == params->first_byte_timeout) + sp->first_byte_timeout = be->first_byte_timeout; + if (be->between_bytes_timeout > 1e-3 + && sp->between_bytes_timeout == params->between_bytes_timeout) + sp->between_bytes_timeout = be->between_bytes_timeout; +} + diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index c99c0e28..61ba299a 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -299,6 +299,48 @@ VRT_r_resp_status(const struct sess *sp) return (atoi(sp->http->hd[HTTP_HDR_STATUS].b)); } +void +VRT_l_bereq_connect_timeout(struct sess *sp, double num) +{ + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + sp->connect_timeout = (num > 0 ? num : 0); +} + +double +VRT_r_bereq_connect_timeout(struct sess *sp) +{ + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + return sp->connect_timeout; +} + +void +VRT_l_bereq_first_byte_timeout(struct sess *sp, double num) +{ + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + sp->first_byte_timeout = (num > 0 ? num : 0); +} + +double +VRT_r_bereq_first_byte_timeout(struct sess *sp) +{ + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + return sp->first_byte_timeout; +} + +void +VRT_l_bereq_between_bytes_timeout(struct sess *sp, double num) +{ + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + sp->between_bytes_timeout = (num > 0 ? num : 0); +} + +double +VRT_r_bereq_between_bytes_timeout(struct sess *sp) +{ + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + return sp->between_bytes_timeout; +} + /*--------------------------------------------------------------------*/ void diff --git a/varnish-cache/bin/varnishd/heritage.h b/varnish-cache/bin/varnishd/heritage.h index fd7dada8..a044964b 100644 --- a/varnish-cache/bin/varnishd/heritage.h +++ b/varnish-cache/bin/varnishd/heritage.h @@ -154,7 +154,11 @@ struct params { unsigned cache_vbe_conns; /* Default connection_timeout */ - unsigned connect_timeout; + double connect_timeout; + + /* Read timeouts for backend */ + double first_byte_timeout; + double between_bytes_timeout; /* How long to linger on sessions */ unsigned session_linger; diff --git a/varnish-cache/bin/varnishd/mgt_param.c b/varnish-cache/bin/varnishd/mgt_param.c index 202bf4d3..d952e774 100644 --- a/varnish-cache/bin/varnishd/mgt_param.c +++ b/varnish-cache/bin/varnishd/mgt_param.c @@ -97,6 +97,24 @@ tweak_generic_timeout(struct cli *cli, volatile unsigned *dst, const char *arg) cli_out(cli, "%u", *dst); } +static void +tweak_generic_timeout_double(struct cli *cli, volatile double *dst, const char *arg) +{ + double u; + + if (arg != NULL) { + u = strtod(arg, NULL); + if (u < 0) { + cli_out(cli, "Timeout must be greater or equal to zero\n"); + cli_result(cli, CLIS_PARAM); + return; + } + *dst = u; + } else + cli_out(cli, "%f", *dst); +} + + /*--------------------------------------------------------------------*/ static void @@ -108,7 +126,14 @@ tweak_timeout(struct cli *cli, const struct parspec *par, const char *arg) tweak_generic_timeout(cli, dest, arg); } +static void +tweak_timeout_double(struct cli *cli, const struct parspec *par, const char *arg) +{ + volatile double *dest; + dest = par->priv; + tweak_generic_timeout_double(cli, dest, arg); +} /*--------------------------------------------------------------------*/ static void @@ -746,14 +771,31 @@ static const struct parspec parspec[] = { "Cache vbe_conn's or rely on malloc, that's the question.", EXPERIMENTAL, "off", "bool" }, - { "connect_timeout", tweak_uint, + { "connect_timeout", tweak_timeout_double, &master.connect_timeout,0, UINT_MAX, "Default connection timeout for backend connections. " "We only try to connect to the backend for this many " - "milliseconds before giving up. " - "VCL can override this default value for each backend.", + "seconds before giving up. " + "VCL can override this default value for each backend. " + "This does not apply to pipe. ", + 0, + "0.4", "s" }, + { "first_byte_timeout", tweak_timeout_double, + &master.first_byte_timeout,0, UINT_MAX, + "Default timeout for receiving first byte from backend. " + "We only wait for this many seconds for the first " + "byte before giving up. A value of 0 means it will never time out. " + "VCL can override this default value for each backend request.", + 0, + "60", "s" }, + { "between_bytes_timeout", tweak_timeout_double, + &master.between_bytes_timeout,0, UINT_MAX, + "Default timeout between bytes when receiving data from backend. " + "We only wait for this many seconds between bytes " + "before giving up. A value of 0 means it will never time out. " + "VCL can override this default value for each backend request.", 0, - "400", "ms" }, + "60", "s" }, { "accept_fd_holdoff", tweak_timeout, &master.accept_fd_holdoff, 0, 3600*1000, "If we run out of file descriptors, the accept thread will " diff --git a/varnish-cache/bin/varnishtest/tests/b00020.vtc b/varnish-cache/bin/varnishtest/tests/b00020.vtc new file mode 100644 index 00000000..c05d752b --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/b00020.vtc @@ -0,0 +1,34 @@ +# $Id: b00019.vtc 3300 2008-10-15 09:52:15Z tfheen $ + +test "Check the between_bytes_timeout behaves from parameters" + +server s1 { + rxreq + send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" + delay 1.5 + send "Baba\n" +} -start + +varnish v1 -vcl+backend {} -start +varnish v1 -cliok "param.set between_bytes_timeout 1" + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run + +server s1 { + rxreq + send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" + delay 0.5 + send "Baba\n" + delay 0.5 + send "Baba\n" +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/varnish-cache/bin/varnishtest/tests/b00021.vtc b/varnish-cache/bin/varnishtest/tests/b00021.vtc new file mode 100644 index 00000000..1387d4b7 --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/b00021.vtc @@ -0,0 +1,37 @@ +# $Id: b00019.vtc 3300 2008-10-15 09:52:15Z tfheen $ + +test "Check the between_bytes_timeout behaves from vcl" + +server s1 { + rxreq + send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" + delay 1.5 + send "Baba\n" +} -start + +varnish v1 -vcl+backend { + sub vcl_miss { + set bereq.between_bytes_timeout = 1s; + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run + +server s1 { + rxreq + send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" + delay 0.5 + send "Baba\n" + delay 0.5 + send "Baba\n" +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/varnish-cache/bin/varnishtest/tests/b00022.vtc b/varnish-cache/bin/varnishtest/tests/b00022.vtc new file mode 100644 index 00000000..c5db44c2 --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/b00022.vtc @@ -0,0 +1,39 @@ +# $Id: b00019.vtc 3300 2008-10-15 09:52:15Z tfheen $ + +test "Check the between_bytes_timeout behaves from backend definition" + +server s1 { + rxreq + send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" + delay 1.5 + send "Baba\n" +} -start + +varnish v1 -vcl { + backend b1 { + .host = "127.0.0.1"; + .port = "9080"; + .between_bytes_timeout = 1s; + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run + +server s1 { + rxreq + send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" + delay 0.5 + send "Baba\n" + delay 0.5 + send "Baba\n" +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/varnish-cache/bin/varnishtest/tests/b00023.vtc b/varnish-cache/bin/varnishtest/tests/b00023.vtc new file mode 100644 index 00000000..907edfdb --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/b00023.vtc @@ -0,0 +1,31 @@ +# $Id: b00019.vtc 3300 2008-10-15 09:52:15Z tfheen $ + +test "Check that the first_byte_timeout works from parameters" + +server s1 { + rxreq + delay 1.5 + txresp +} -start + +varnish v1 -vcl+backend {} -start +varnish v1 -cliok "param.set first_byte_timeout 1" + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run + + +server s1 { + rxreq + delay 0.5 + txresp +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/varnish-cache/bin/varnishtest/tests/b00024.vtc b/varnish-cache/bin/varnishtest/tests/b00024.vtc new file mode 100644 index 00000000..6896ba86 --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/b00024.vtc @@ -0,0 +1,34 @@ +# $Id: b00019.vtc 3300 2008-10-15 09:52:15Z tfheen $ + +test "Check that the first_byte_timeout works from vcl" + +server s1 { + rxreq + delay 1.5 + txresp +} -start + +varnish v1 -vcl+backend { + sub vcl_miss { + set bereq.first_byte_timeout = 1s; + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run + + +server s1 { + rxreq + delay 0.5 + txresp +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/varnish-cache/bin/varnishtest/tests/b00025.vtc b/varnish-cache/bin/varnishtest/tests/b00025.vtc new file mode 100644 index 00000000..10e70c94 --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/b00025.vtc @@ -0,0 +1,36 @@ +# $Id: b00019.vtc 3300 2008-10-15 09:52:15Z tfheen $ + +test "Check that the first_byte_timeout works from backend definition" + +server s1 { + rxreq + delay 1.5 + txresp +} -start + +varnish v1 -vcl { + backend b1 { + .host = "127.0.0.1"; + .port = "9080"; + .first_byte_timeout = 1s; + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run + + +server s1 { + rxreq + delay 0.5 + txresp +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/varnish-cache/bin/varnishtest/tests/b00026.vtc b/varnish-cache/bin/varnishtest/tests/b00026.vtc new file mode 100644 index 00000000..78be372c --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/b00026.vtc @@ -0,0 +1,50 @@ +# $Id: b00019.vtc 3300 2008-10-15 09:52:15Z tfheen $ + +test "Check the precedence for timeouts" + +server s1 -listen 127.0.0.1:9080 { + rxreq + expect req.url == "from_backend" + delay 1; + txresp +} -start +server s2 -listen 127.0.0.1:9180 { + rxreq + expect req.url == "from_vcl" + delay 1.5; + txresp +} -start + +varnish v1 -vcl { + backend b1 { + .host = "127.0.0.1"; + .port = "9080"; + .first_byte_timeout = 2s; + } + backend b2 { + .host = "127.0.0.1"; + .port = "9180"; + .first_byte_timeout = 1s; + } + + sub vcl_recv { + if (req.url == "from_backend") { + set req.backend = b1; + pass; + } + set req.backend = b2; + } + sub vcl_miss { + set bereq.first_byte_timeout = 2s; + } +} -start +varnish v1 -cliok "param.set first_byte_timeout 0.5" + +client c1 { + txreq -url "from_backend" + rxresp + expect resp.status == 200 + txreq -url "from_vcl" + rxresp + expect resp.status == 200 +} -run diff --git a/varnish-cache/include/libvarnish.h b/varnish-cache/include/libvarnish.h index 277cc534..7ef22d1b 100644 --- a/varnish-cache/include/libvarnish.h +++ b/varnish-cache/include/libvarnish.h @@ -65,6 +65,7 @@ void TCP_name(const struct sockaddr *addr, unsigned l, char *abuf, int TCP_connect(int s, const struct sockaddr *name, socklen_t namelen, int msec); void TCP_close(int *s); +void TCP_set_read_timeout(int socket, double seconds); #endif /* from libvarnish/time.c */ diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 051d6148..df612d07 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -69,6 +69,8 @@ struct vrt_backend { const unsigned char *ipv6_sockaddr; double connect_timeout; + double first_byte_timeout; + double between_bytes_timeout; unsigned max_connections; struct vrt_backend_probe probe; }; diff --git a/varnish-cache/include/vrt_obj.h b/varnish-cache/include/vrt_obj.h index e11b4eb8..44c17380 100644 --- a/varnish-cache/include/vrt_obj.h +++ b/varnish-cache/include/vrt_obj.h @@ -28,6 +28,12 @@ const char * VRT_r_bereq_url(const struct sess *); void VRT_l_bereq_url(const struct sess *, const char *, ...); const char * VRT_r_bereq_proto(const struct sess *); void VRT_l_bereq_proto(const struct sess *, const char *, ...); +double VRT_r_bereq_connect_timeout(struct sess *); +void VRT_l_bereq_connect_timeout(struct sess *, double); +double VRT_r_bereq_first_byte_timeout(struct sess *); +void VRT_l_bereq_first_byte_timeout(struct sess *, double); +double VRT_r_bereq_between_bytes_timeout(struct sess *); +void VRT_l_bereq_between_bytes_timeout(struct sess *, double); const char * VRT_r_obj_proto(const struct sess *); void VRT_l_obj_proto(const struct sess *, const char *, ...); int VRT_r_obj_status(const struct sess *); diff --git a/varnish-cache/lib/libvarnish/tcp.c b/varnish-cache/lib/libvarnish/tcp.c index 427c469e..35d63df1 100644 --- a/varnish-cache/lib/libvarnish/tcp.c +++ b/varnish-cache/lib/libvarnish/tcp.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "config.h" #ifndef HAVE_STRLCPY @@ -210,3 +211,14 @@ TCP_close(int *s) errno == ENOTCONN); *s = -1; } + +void +TCP_set_read_timeout(int s, double seconds) +{ + struct timeval timeout; + timeout.tv_sec = floor(seconds); + timeout.tv_usec = 1e6 * (seconds - timeout.tv_sec); +#ifdef SO_RCVTIMEO_WORKS + AZ(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout)); +#endif +} diff --git a/varnish-cache/lib/libvcl/vcc_backend.c b/varnish-cache/lib/libvcl/vcc_backend.c index c86b41ce..d1c63206 100644 --- a/varnish-cache/lib/libvcl/vcc_backend.c +++ b/varnish-cache/lib/libvcl/vcc_backend.c @@ -473,6 +473,8 @@ vcc_ParseHostDef(struct tokenlist *tl, int *nbh, const struct token *name, "?port", "?host_header", "?connect_timeout", + "?first_byte_timeout", + "?between_bytes_timeout", "?probe", "?max_connections", NULL); @@ -537,6 +539,20 @@ vcc_ParseHostDef(struct tokenlist *tl, int *nbh, const struct token *name, Fb(tl, 0, ",\n"); ExpectErr(tl, ';'); vcc_NextToken(tl); + } else if (vcc_IdIs(t_field, "first_byte_timeout")) { + Fb(tl, 0, "\t.first_byte_timeout = "); + vcc_TimeVal(tl); + ERRCHK(tl); + Fb(tl, 0, ",\n"); + ExpectErr(tl, ';'); + vcc_NextToken(tl); + } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { + Fb(tl, 0, "\t.between_bytes_timeout = "); + vcc_TimeVal(tl); + ERRCHK(tl); + Fb(tl, 0, ",\n"); + ExpectErr(tl, ';'); + vcc_NextToken(tl); } else if (vcc_IdIs(t_field, "max_connections")) { u = vcc_UintVal(tl); vcc_NextToken(tl); diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index dfcf7368..a94c7fcd 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -243,6 +243,8 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, "\tconst unsigned char\t\t*ipv4_sockaddr;\n"); vsb_cat(sb, "\tconst unsigned char\t\t*ipv6_sockaddr;\n"); vsb_cat(sb, "\n\tdouble\t\t\t\tconnect_timeout;\n"); + vsb_cat(sb, "\tdouble\t\t\t\tfirst_byte_timeout;\n"); + vsb_cat(sb, "\tdouble\t\t\t\tbetween_bytes_timeout;\n"); vsb_cat(sb, "\tunsigned\t\t\tmax_connections;\n"); vsb_cat(sb, "\tstruct vrt_backend_probe\tprobe;\n"); vsb_cat(sb, "};\n\n/*\n * A director with a predictable reply\n"); @@ -335,9 +337,16 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, " const char *, ...);\nconst char * VRT_r_bereq_proto(c"); vsb_cat(sb, "onst struct sess *);\nvoid VRT_l_bereq_proto(const str"); vsb_cat(sb, "uct sess *, const char *, ...);\n"); - vsb_cat(sb, "const char * VRT_r_obj_proto(const struct sess *);\n"); - vsb_cat(sb, "void VRT_l_obj_proto(const struct sess *, const char *"); - vsb_cat(sb, ", ...);\nint VRT_r_obj_status(const struct sess *);\n"); + vsb_cat(sb, "double VRT_r_bereq_connect_timeout(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_bereq_connect_timeout(struct sess *, double"); + vsb_cat(sb, ");\ndouble VRT_r_bereq_first_byte_timeout(struct sess "); + vsb_cat(sb, "*);\nvoid VRT_l_bereq_first_byte_timeout(struct sess *"); + vsb_cat(sb, ", double);\ndouble VRT_r_bereq_between_bytes_timeout(s"); + vsb_cat(sb, "truct sess *);\nvoid VRT_l_bereq_between_bytes_timeout"); + vsb_cat(sb, "(struct sess *, double);\nconst char * VRT_r_obj_proto"); + vsb_cat(sb, "(const struct sess *);\nvoid VRT_l_obj_proto(const str"); + vsb_cat(sb, "uct sess *, const char *, ...);\n"); + vsb_cat(sb, "int VRT_r_obj_status(const struct sess *);\n"); vsb_cat(sb, "void VRT_l_obj_status(const struct sess *, int);\n"); vsb_cat(sb, "const char * VRT_r_obj_response(const struct sess *);\n"); vsb_cat(sb, "void VRT_l_obj_response(const struct sess *, const cha"); diff --git a/varnish-cache/lib/libvcl/vcc_gen_obj.tcl b/varnish-cache/lib/libvcl/vcc_gen_obj.tcl index 28e76c4e..405ca02b 100755 --- a/varnish-cache/lib/libvcl/vcc_gen_obj.tcl +++ b/varnish-cache/lib/libvcl/vcc_gen_obj.tcl @@ -127,6 +127,21 @@ set spobj { { pipe pass miss fetch } "const struct sess *" } + { bereq.connect_timeout + RW TIME + { pass miss } + "struct sess *" + } + { bereq.first_byte_timeout + RW TIME + { pass miss } + "struct sess *" + } + { bereq.between_bytes_timeout + RW TIME + { pass miss } + "struct sess *" + } # The (possibly) cached object { obj.proto diff --git a/varnish-cache/lib/libvcl/vcc_obj.c b/varnish-cache/lib/libvcl/vcc_obj.c index 37f14364..a7f98211 100644 --- a/varnish-cache/lib/libvcl/vcc_obj.c +++ b/varnish-cache/lib/libvcl/vcc_obj.c @@ -108,6 +108,21 @@ struct var vcc_vars[] = { V_RW, "HDR_BEREQ", VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_MISS | VCL_MET_FETCH }, + { "bereq.connect_timeout", TIME, 21, + "VRT_r_bereq_connect_timeout(sp)", "VRT_l_bereq_connect_timeout(sp, ", + V_RW, 0, + VCL_MET_PASS | VCL_MET_MISS + }, + { "bereq.first_byte_timeout", TIME, 24, + "VRT_r_bereq_first_byte_timeout(sp)", "VRT_l_bereq_first_byte_timeout(sp, ", + V_RW, 0, + VCL_MET_PASS | VCL_MET_MISS + }, + { "bereq.between_bytes_timeout", TIME, 27, + "VRT_r_bereq_between_bytes_timeout(sp)", "VRT_l_bereq_between_bytes_timeout(sp, ", + V_RW, 0, + VCL_MET_PASS | VCL_MET_MISS + }, { "obj.proto", STRING, 9, "VRT_r_obj_proto(sp)", "VRT_l_obj_proto(sp, ", V_RW, 0, -- 2.39.5