Mercurial > hg > nginx
comparison src/stream/ngx_stream_proxy_module.c @ 7929:bfad703459b4
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.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Wed, 22 Sep 2021 10:20:00 +0300 |
parents | 419c066cb710 |
children | c7e25324be11 b4c7853b0488 |
comparison
equal
deleted
inserted
replaced
7928:97cf8284fd19 | 7929:bfad703459b4 |
---|---|
29 ngx_uint_t requests; | 29 ngx_uint_t requests; |
30 ngx_uint_t responses; | 30 ngx_uint_t responses; |
31 ngx_uint_t next_upstream_tries; | 31 ngx_uint_t next_upstream_tries; |
32 ngx_flag_t next_upstream; | 32 ngx_flag_t next_upstream; |
33 ngx_flag_t proxy_protocol; | 33 ngx_flag_t proxy_protocol; |
34 ngx_flag_t half_close; | |
34 ngx_stream_upstream_local_t *local; | 35 ngx_stream_upstream_local_t *local; |
35 ngx_flag_t socket_keepalive; | 36 ngx_flag_t socket_keepalive; |
36 | 37 |
37 #if (NGX_STREAM_SSL) | 38 #if (NGX_STREAM_SSL) |
38 ngx_flag_t ssl_enable; | 39 ngx_flag_t ssl_enable; |
243 ngx_conf_set_flag_slot, | 244 ngx_conf_set_flag_slot, |
244 NGX_STREAM_SRV_CONF_OFFSET, | 245 NGX_STREAM_SRV_CONF_OFFSET, |
245 offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol), | 246 offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol), |
246 NULL }, | 247 NULL }, |
247 | 248 |
249 { ngx_string("proxy_half_close"), | |
250 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, | |
251 ngx_conf_set_flag_slot, | |
252 NGX_STREAM_SRV_CONF_OFFSET, | |
253 offsetof(ngx_stream_proxy_srv_conf_t, half_close), | |
254 NULL }, | |
255 | |
248 #if (NGX_STREAM_SSL) | 256 #if (NGX_STREAM_SSL) |
249 | 257 |
250 { ngx_string("proxy_ssl"), | 258 { ngx_string("proxy_ssl"), |
251 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, | 259 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, |
252 ngx_conf_set_flag_slot, | 260 ngx_conf_set_flag_slot, |
1753 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); | 1761 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); |
1754 return; | 1762 return; |
1755 } | 1763 } |
1756 | 1764 |
1757 if (dst) { | 1765 if (dst) { |
1766 | |
1767 if (dst->type == SOCK_STREAM && pscf->half_close | |
1768 && src->read->eof && !u->half_closed && !dst->buffered) | |
1769 { | |
1770 if (ngx_shutdown_socket(dst->fd, NGX_WRITE_SHUTDOWN) == -1) { | |
1771 ngx_connection_error(c, ngx_socket_errno, | |
1772 ngx_shutdown_socket_n " failed"); | |
1773 | |
1774 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); | |
1775 return; | |
1776 } | |
1777 | |
1778 u->half_closed = 1; | |
1779 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, | |
1780 "stream proxy %s socket shutdown", | |
1781 from_upstream ? "client" : "upstream"); | |
1782 } | |
1783 | |
1758 if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { | 1784 if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { |
1759 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); | 1785 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); |
1760 return; | 1786 return; |
1761 } | 1787 } |
1762 | 1788 |
1829 || (!c->read->eof && !pc->read->eof) | 1855 || (!c->read->eof && !pc->read->eof) |
1830 || (!c->read->eof && c->buffered) | 1856 || (!c->read->eof && c->buffered) |
1831 || (!pc->read->eof && pc->buffered)) | 1857 || (!pc->read->eof && pc->buffered)) |
1832 { | 1858 { |
1833 return NGX_DECLINED; | 1859 return NGX_DECLINED; |
1860 } | |
1861 | |
1862 if (pscf->half_close) { | |
1863 /* avoid closing live connections until both read ends get EOF */ | |
1864 if (!(c->read->eof && pc->read->eof && !c->buffered && !pc->buffered)) { | |
1865 return NGX_DECLINED; | |
1866 } | |
1834 } | 1867 } |
1835 | 1868 |
1836 handler = c->log->handler; | 1869 handler = c->log->handler; |
1837 c->log->handler = NULL; | 1870 c->log->handler = NULL; |
1838 | 1871 |
2050 conf->next_upstream_tries = NGX_CONF_UNSET_UINT; | 2083 conf->next_upstream_tries = NGX_CONF_UNSET_UINT; |
2051 conf->next_upstream = NGX_CONF_UNSET; | 2084 conf->next_upstream = NGX_CONF_UNSET; |
2052 conf->proxy_protocol = NGX_CONF_UNSET; | 2085 conf->proxy_protocol = NGX_CONF_UNSET; |
2053 conf->local = NGX_CONF_UNSET_PTR; | 2086 conf->local = NGX_CONF_UNSET_PTR; |
2054 conf->socket_keepalive = NGX_CONF_UNSET; | 2087 conf->socket_keepalive = NGX_CONF_UNSET; |
2088 conf->half_close = NGX_CONF_UNSET; | |
2055 | 2089 |
2056 #if (NGX_STREAM_SSL) | 2090 #if (NGX_STREAM_SSL) |
2057 conf->ssl_enable = NGX_CONF_UNSET; | 2091 conf->ssl_enable = NGX_CONF_UNSET; |
2058 conf->ssl_session_reuse = NGX_CONF_UNSET; | 2092 conf->ssl_session_reuse = NGX_CONF_UNSET; |
2059 conf->ssl_name = NGX_CONF_UNSET_PTR; | 2093 conf->ssl_name = NGX_CONF_UNSET_PTR; |
2108 ngx_conf_merge_ptr_value(conf->local, prev->local, NULL); | 2142 ngx_conf_merge_ptr_value(conf->local, prev->local, NULL); |
2109 | 2143 |
2110 ngx_conf_merge_value(conf->socket_keepalive, | 2144 ngx_conf_merge_value(conf->socket_keepalive, |
2111 prev->socket_keepalive, 0); | 2145 prev->socket_keepalive, 0); |
2112 | 2146 |
2147 ngx_conf_merge_value(conf->half_close, prev->half_close, 0); | |
2148 | |
2113 #if (NGX_STREAM_SSL) | 2149 #if (NGX_STREAM_SSL) |
2114 | 2150 |
2115 ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0); | 2151 ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0); |
2116 | 2152 |
2117 ngx_conf_merge_value(conf->ssl_session_reuse, | 2153 ngx_conf_merge_value(conf->ssl_session_reuse, |