Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVladimir Homutov <vl@nginx.com>2021-09-22 10:20:00 +0300
committerVladimir Homutov <vl@nginx.com>2021-09-22 10:20:00 +0300
commite56ba23158b8466d108fd4d571bd7d9a88f2a473 (patch)
tree100e8c1244711933931875c1cdca5f1615ad3f3a /src
parentadbd28b7a9843ebce895f9903f19c5a740d61db4 (diff)
Stream: added half-close support.
The "proxy_half_close" directive enables handling of TCP half close. If enabled, connection to proxied server is kept open until both read ends get EOF. Write end shutdown is properly transmitted via proxy.
Diffstat (limited to 'src')
-rw-r--r--src/stream/ngx_stream_proxy_module.c36
-rw-r--r--src/stream/ngx_stream_upstream.h1
2 files changed, 37 insertions, 0 deletions
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
index 1275cf225..934e7d8f2 100644
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -31,6 +31,7 @@ typedef struct {
ngx_uint_t next_upstream_tries;
ngx_flag_t next_upstream;
ngx_flag_t proxy_protocol;
+ ngx_flag_t half_close;
ngx_stream_upstream_local_t *local;
ngx_flag_t socket_keepalive;
@@ -245,6 +246,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol),
NULL },
+ { ngx_string("proxy_half_close"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_proxy_srv_conf_t, half_close),
+ NULL },
+
#if (NGX_STREAM_SSL)
{ ngx_string("proxy_ssl"),
@@ -1755,6 +1763,24 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
}
if (dst) {
+
+ if (dst->type == SOCK_STREAM && pscf->half_close
+ && src->read->eof && !u->half_closed && !dst->buffered)
+ {
+ if (ngx_shutdown_socket(dst->fd, NGX_WRITE_SHUTDOWN) == -1) {
+ ngx_connection_error(c, ngx_socket_errno,
+ ngx_shutdown_socket_n " failed");
+
+ ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ u->half_closed = 1;
+ ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
+ "stream proxy %s socket shutdown",
+ from_upstream ? "client" : "upstream");
+ }
+
if (ngx_handle_write_event(dst->write, 0) != NGX_OK) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
@@ -1833,6 +1859,13 @@ ngx_stream_proxy_test_finalize(ngx_stream_session_t *s,
return NGX_DECLINED;
}
+ if (pscf->half_close) {
+ /* avoid closing live connections until both read ends get EOF */
+ if (!(c->read->eof && pc->read->eof && !c->buffered && !pc->buffered)) {
+ return NGX_DECLINED;
+ }
+ }
+
handler = c->log->handler;
c->log->handler = NULL;
@@ -2052,6 +2085,7 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
conf->proxy_protocol = NGX_CONF_UNSET;
conf->local = NGX_CONF_UNSET_PTR;
conf->socket_keepalive = NGX_CONF_UNSET;
+ conf->half_close = NGX_CONF_UNSET;
#if (NGX_STREAM_SSL)
conf->ssl_enable = NGX_CONF_UNSET;
@@ -2110,6 +2144,8 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->socket_keepalive,
prev->socket_keepalive, 0);
+ ngx_conf_merge_value(conf->half_close, prev->half_close, 0);
+
#if (NGX_STREAM_SSL)
ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0);
diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h
index 9857e0b75..f5617794f 100644
--- a/src/stream/ngx_stream_upstream.h
+++ b/src/stream/ngx_stream_upstream.h
@@ -142,6 +142,7 @@ typedef struct {
ngx_stream_upstream_state_t *state;
unsigned connected:1;
unsigned proxy_protocol:1;
+ unsigned half_closed:1;
} ngx_stream_upstream_t;