proxy_bind, fastcgi_bind, and memcached_bind
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index 839bb6c..dc14075 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -54,15 +54,7 @@
{
ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
"setsockopt(SO_RCVBUF) failed");
-
- ngx_free_connection(c);
-
- if (ngx_close_socket(s) == -1) {
- ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
- ngx_close_socket_n " failed");
- }
-
- return NGX_ERROR;
+ goto failed;
}
}
@@ -70,14 +62,16 @@
ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
ngx_nonblocking_n " failed");
- ngx_free_connection(c);
+ goto failed;
+ }
- if (ngx_close_socket(s) == -1) {
- ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
- ngx_close_socket_n " failed");
+ if (pc->local) {
+ if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
+ ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
+ "bind(%V) failed", &pc->local->name);
+
+ goto failed;
}
-
- return NGX_ERROR;
}
c->recv = ngx_recv;
@@ -127,7 +121,7 @@
if (ngx_add_conn) {
if (ngx_add_conn(c) == NGX_ERROR) {
- return NGX_ERROR;
+ goto failed;
}
}
@@ -199,7 +193,7 @@
if (ngx_blocking(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
ngx_blocking_n " failed");
- return NGX_ERROR;
+ goto failed;
}
/*
@@ -229,7 +223,7 @@
}
if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
- return NGX_ERROR;
+ goto failed;
}
if (rc == -1) {
@@ -237,7 +231,7 @@
/* NGX_EINPROGRESS */
if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
- return NGX_ERROR;
+ goto failed;
}
return NGX_AGAIN;
@@ -248,6 +242,17 @@
wev->ready = 1;
return NGX_OK;
+
+failed:
+
+ ngx_free_connection(c);
+
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ return NGX_ERROR;
}
diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h
index 4f09524..d64f1bb 100644
--- a/src/event/ngx_event_connect.h
+++ b/src/event/ngx_event_connect.h
@@ -55,6 +55,8 @@
ngx_atomic_t *lock;
#endif
+ ngx_addr_t *local;
+
int rcvbuf;
ngx_log_t *log;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index a4a62e4..ba79cea 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -240,6 +240,13 @@
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
NULL },
+ { ngx_string("fastcgi_bind"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_upsteam_bind_set_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
+ NULL },
+
{ ngx_string("fastcgi_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index 6cf5881..9205215 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -63,6 +63,13 @@
0,
NULL },
+ { ngx_string("memcached_bind"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_upsteam_bind_set_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_memcached_loc_conf_t, upstream.local),
+ NULL },
+
{ ngx_string("memcached_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 88530e1..8f169fe 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -229,6 +229,13 @@
offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
NULL },
+ { ngx_string("proxy_bind"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_upsteam_bind_set_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
+ NULL },
+
{ ngx_string("proxy_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index b95db57..a04aad3 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -479,6 +479,8 @@
return;
}
+ u->peer.local = u->conf->local;
+
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
u->output.alignment = clcf->directio_alignment;
@@ -4196,6 +4198,31 @@
}
+char *
+ngx_http_upsteam_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf)
+{
+ char *p = conf;
+
+ ngx_str_t *value;
+ ngx_addr_t **paddr;
+
+ paddr = (ngx_addr_t **) (p + cmd->offset);
+
+ value = cf->args->elts;
+
+ *paddr = ngx_parse_addr(cf->pool, &value[1]);
+ if (*paddr) {
+ return NGX_CONF_OK;
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid address \"%V\"", &value[1]);
+
+ return NGX_CONF_ERROR;
+}
+
+
ngx_int_t
ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 2d3bc20..09fab00 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -152,6 +152,8 @@
ngx_array_t *hide_headers;
ngx_array_t *pass_headers;
+ ngx_addr_t *local;
+
#if (NGX_HTTP_CACHE)
ngx_shm_zone_t *cache;
@@ -321,6 +323,8 @@
void ngx_http_upstream_init(ngx_http_request_t *r);
ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
ngx_url_t *u, ngx_uint_t flags);
+char *ngx_http_upsteam_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
ngx_str_t *default_hide_headers, ngx_hash_init_t *hash);