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,