nginx-0.3.47-RELEASE import
*) Feature: the "upstream" directive.
*) Change: now the "\" escape symbol in the "\"" and "\'" pairs in the
SSI command is always removed.
diff --git a/src/core/nginx.h b/src/core/nginx.h
index ece57f5..72aaa34 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.46"
+#define NGINX_VER "nginx/0.3.47"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index 8f84e36..17c24c7 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -61,7 +61,7 @@
#define NGX_CONF_OK NULL
-#define NGX_CONF_ERROR (char *) -1
+#define NGX_CONF_ERROR (void *) -1
#define NGX_CONF_BLOCK_START 1
#define NGX_CONF_BLOCK_DONE 2
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 1779513..cd066af 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -63,6 +63,9 @@
#include <ngx_radix_tree.h>
#include <ngx_times.h>
#include <ngx_shmtx.h>
+#if (NGX_OPENSSL)
+#include <ngx_event_openssl.h>
+#endif
#include <ngx_inet.h>
#if (NGX_HAVE_UNIX_DOMAIN)
#include <ngx_unix_domain.h>
@@ -71,9 +74,6 @@
#include <ngx_process_cycle.h>
#include <ngx_conf_file.h>
#include <ngx_os.h>
-#if (NGX_OPENSSL)
-#include <ngx_event_openssl.h>
-#endif
#include <ngx_connection.h>
diff --git a/src/core/ngx_cpuinfo.c b/src/core/ngx_cpuinfo.c
index f905cbc..2ed26b8 100644
--- a/src/core/ngx_cpuinfo.c
+++ b/src/core/ngx_cpuinfo.c
@@ -31,16 +31,14 @@
" mov %%ebx, %%esi; "
" cpuid; "
- " mov %%eax, %0; "
- " mov %%ebx, %1; "
- " mov %%edx, %2; "
- " mov %%ecx, %3; "
+ " mov %%eax, (%1); "
+ " mov %%ebx, 4(%1); "
+ " mov %%edx, 8(%1); "
+ " mov %%ecx, 12(%1); "
" mov %%esi, %%ebx; "
- : "=m" (buf[0]), "=m" (buf[1]), "=m" (buf[2]), "=m" (buf[3])
- : "a" (i)
- : "ecx", "edx", "esi" );
+ : : "a" (i), "D" (buf) : "ecx", "edx", "esi", "memory" );
}
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index a42df69..f2b0cf7 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -220,6 +220,339 @@
}
+ngx_int_t
+ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u)
+{
+ u_char *p;
+ size_t len;
+ ngx_int_t port;
+ ngx_uint_t i;
+#if (NGX_HAVE_UNIX_DOMAIN)
+ struct sockaddr_un *saun;
+#endif
+
+ len = u->url.len;
+ p = u->url.data;
+
+ if (ngx_strncasecmp(p, "unix:", 5) == 0) {
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ u->type = NGX_PARSE_URL_UNIX;
+
+ p += 5;
+ len -= 5;
+
+ if (u->uri_part) {
+ for (i = 0; i < len; i++) {
+
+ if (p[i] == ':') {
+ len = i;
+
+ u->uri.len -= len + 1;
+ u->uri.data += len + 1;
+
+ break;
+ }
+ }
+ }
+
+ if (len == 0) {
+ u->err = "no path in the unix domain socket";
+ return NGX_ERROR;
+ }
+
+ if (len + 1 > sizeof(saun->sun_path)) {
+ u->err = "too long path in the unix domain socket";
+ return NGX_ERROR;
+ }
+
+ u->peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
+ if (u->peers == NULL) {
+ return NGX_ERROR;
+ }
+
+ saun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un));
+ if (saun == NULL) {
+ return NGX_ERROR;
+ }
+
+ u->peers->number = 1;
+
+ saun->sun_family = AF_UNIX;
+ (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1);
+
+ u->peers->peer[0].sockaddr = (struct sockaddr *) saun;
+ u->peers->peer[0].socklen = sizeof(struct sockaddr_un);
+ u->peers->peer[0].name = u->url;
+ u->peers->peer[0].uri_separator = ":";
+
+ u->host_header.len = sizeof("localhost") - 1;
+ u->host_header.data = (u_char *) "localhost";
+
+ return NGX_OK;
+
+#else
+ u->err = "the unix domain sockets are not supported on this platform";
+
+ return NGX_ERROR;
+
+#endif
+ }
+
+ if ((p[0] == ':' || p[0] == '/') && !u->listen) {
+ u->err = "invalid host";
+ return NGX_ERROR;
+ }
+
+ u->type = NGX_PARSE_URL_INET;
+
+ u->host.data = p;
+ u->host_header.len = len;
+ u->host_header.data = p;
+
+ for (i = 0; i < len; i++) {
+
+ if (p[i] == ':') {
+ u->port.data = &p[i + 1];
+ u->host.len = i;
+
+ if (!u->uri_part) {
+ u->port.len = &p[len] - u->port.data;
+ break;
+ }
+ }
+
+ if (p[i] == '/') {
+ u->uri.len = len - i;
+ u->uri.data = &p[i];
+ u->host_header.len = i;
+
+ if (u->host.len == 0) {
+ u->host.len = i;
+ }
+
+ if (u->port.data == NULL) {
+ u->default_port = 1;
+ goto port;
+ }
+
+ u->port.len = &p[i] - u->port.data;
+
+ if (u->port.len == 0) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
+
+ break;
+ }
+ }
+
+ if (u->port.data) {
+
+ if (u->port.len == 0) {
+ u->port.len = &p[i] - u->port.data;
+
+ if (u->port.len == 0) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
+ }
+
+ port = ngx_atoi(u->port.data, u->port.len);
+
+ if (port == NGX_ERROR || port < 1 || port > 65536) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
+
+ } else {
+ port = ngx_atoi(p, len);
+
+ if (port == NGX_ERROR) {
+ u->default_port = 1;
+ u->host.len = len;
+
+ goto port;
+ }
+
+ u->port.len = len;
+ u->port.data = p;
+ u->wildcard = 1;
+ }
+
+ u->portn = (in_port_t) port;
+
+port:
+
+ if (u->listen) {
+ return NGX_OK;
+ }
+
+ if (u->default_port) {
+
+ if (u->upstream) {
+ return NGX_OK;
+ }
+
+ if (u->default_portn == 0) {
+ u->err = "no port";
+ return NGX_ERROR;
+ }
+
+ u->portn = u->default_portn;
+
+ u->port.data = ngx_palloc(cf->pool, sizeof("65536") - 1);
+ if (u->port.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ u->port.len = ngx_sprintf(u->port.data, "%d", u->portn) - u->port.data;
+
+ } else if (u->portn) {
+ if (u->portn == u->default_portn) {
+ u->default_port = 1;
+ }
+
+ } else {
+ u->err = "no port";
+ return NGX_ERROR;
+ }
+
+ if (u->host.len == 0) {
+ u->err = "no host";
+ return NGX_ERROR;
+ }
+
+ u->peers = ngx_inet_resolve_peer(cf, &u->host, u->portn);
+
+ if (u->peers == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (u->peers == NGX_CONF_ERROR) {
+ u->err = "host not found";
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_peers_t *
+ngx_inet_resolve_peer(ngx_conf_t *cf, ngx_str_t *name, in_port_t port)
+{
+ u_char *host;
+ size_t len;
+ in_addr_t in_addr;
+ ngx_uint_t i;
+ ngx_peers_t *peers;
+ struct hostent *h;
+ struct sockaddr_in *sin;
+
+ host = ngx_palloc(cf->temp_pool, name->len + 1);
+ if (host == NULL) {
+ return NULL;
+ }
+
+ (void) ngx_cpystrn(host, name->data, name->len + 1);
+
+ /* AF_INET only */
+
+ in_addr = inet_addr((char *) host);
+
+ if (in_addr == INADDR_NONE) {
+ h = gethostbyname((char *) host);
+
+ if (h == NULL || h->h_addr_list[0] == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
+
+ /* MP: ngx_shared_palloc() */
+
+ peers = ngx_pcalloc(cf->pool,
+ sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1));
+ if (peers == NULL) {
+ return NULL;
+ }
+
+ peers->number = i;
+ peers->weight = 1;
+
+ for (i = 0; h->h_addr_list[i] != NULL; i++) {
+
+ sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+ if (sin == NULL) {
+ return NULL;
+ }
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
+
+ peers->peer[i].sockaddr = (struct sockaddr *) sin;
+ peers->peer[i].socklen = sizeof(struct sockaddr_in);
+
+ len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
+
+ peers->peer[i].name.data = ngx_palloc(cf->pool, len);
+ if (peers->peer[i].name.data == NULL) {
+ return NULL;
+ }
+
+ len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin,
+ peers->peer[i].name.data, len);
+
+ peers->peer[i].name.len =
+ ngx_sprintf(&peers->peer[i].name.data[len],
+ ":%d", port)
+ - peers->peer[i].name.data;
+
+ peers->peer[i].uri_separator = "";
+ }
+
+ } else {
+
+ /* MP: ngx_shared_palloc() */
+
+ peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
+ if (peers == NULL) {
+ return NULL;
+ }
+
+ sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+ if (sin == NULL) {
+ return NULL;
+ }
+
+ peers->number = 1;
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ sin->sin_addr.s_addr = in_addr;
+
+ peers->peer[0].sockaddr = (struct sockaddr *) sin;
+ peers->peer[0].socklen = sizeof(struct sockaddr_in);
+
+ peers->peer[0].name.data = ngx_palloc(cf->pool,
+ name->len + sizeof(":65536") - 1);
+ if (peers->peer[0].name.data == NULL) {
+ return NULL;
+ }
+
+ peers->peer[0].name.len = ngx_sprintf(peers->peer[0].name.data, "%V:%d",
+ name, port)
+ - peers->peer[0].name.data;
+
+ peers->peer[0].uri_separator = "";
+ }
+
+ return peers;
+}
+
+
ngx_peers_t *
ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
{
@@ -241,6 +574,7 @@
}
if (u->default_port) {
+
if (u->default_port_value == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"no port in upstream \"%V\"", &u->name);
@@ -277,7 +611,7 @@
u->port = htons(u->port);
- host = ngx_palloc(cf->pool, u->host.len + 1);
+ host = ngx_palloc(cf->temp_pool, u->host.len + 1);
if (host == NULL) {
return NULL;
}
diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h
index a01fc8a..25f9232 100644
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -12,6 +12,10 @@
#include <ngx_core.h>
+#define NGX_PARSE_URL_INET 1
+#define NGX_PARSE_URL_UNIX 2
+
+
typedef struct {
in_addr_t addr;
in_addr_t mask;
@@ -19,6 +23,66 @@
typedef struct {
+ struct sockaddr *sockaddr;
+ socklen_t socklen;
+
+ ngx_str_t name;
+ char *uri_separator;
+
+ ngx_uint_t weight;
+
+ ngx_uint_t fails;
+ time_t accessed;
+
+ ngx_uint_t max_fails;
+ time_t fail_timeout;
+
+#if (NGX_SSL)
+ ngx_ssl_session_t *ssl_session;
+#endif
+} ngx_peer_t;
+
+
+struct ngx_peers_s {
+ ngx_uint_t current;
+ ngx_uint_t weight;
+
+ ngx_uint_t number;
+ ngx_uint_t last_cached;
+
+ /* ngx_mutex_t *mutex; */
+ ngx_connection_t **cached;
+
+ ngx_peer_t peer[1];
+};
+
+
+typedef struct {
+ ngx_int_t type;
+
+ ngx_peers_t *peers;
+
+ ngx_str_t url;
+ ngx_str_t host;
+ ngx_str_t host_header;
+ ngx_str_t port;
+ ngx_str_t uri;
+
+ in_port_t portn;
+ in_port_t default_portn;
+
+ unsigned listen:1;
+ unsigned uri_part:1;
+ unsigned upstream:1;
+
+ unsigned default_port:1;
+ unsigned wildcard:1;
+
+ char *err;
+} ngx_url_t;
+
+
+typedef struct {
ngx_str_t name; /* "schema:host:port/uri" */
ngx_str_t url; /* "host:port/uri" */
ngx_str_t host;
@@ -35,6 +99,7 @@
unsigned uri_part:1;
unsigned port_only:1;
+ unsigned virtual:1;
} ngx_inet_upstream_t;
@@ -45,7 +110,10 @@
ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr);
ngx_peers_t *ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u);
+ngx_peers_t *ngx_inet_resolve_peer(ngx_conf_t *cf, ngx_str_t *name,
+ in_port_t port);
char *ngx_inet_parse_host_port(ngx_inet_upstream_t *u);
+ngx_int_t ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u);
#endif /* _NGX_INET_H_INCLUDED_ */
diff --git a/src/core/ngx_parse.c b/src/core/ngx_parse.c
index f8e5f6c..28e5d96 100644
--- a/src/core/ngx_parse.c
+++ b/src/core/ngx_parse.c
@@ -50,10 +50,10 @@
ngx_int_t
ngx_parse_time(ngx_str_t *line, ngx_int_t sec)
{
- size_t len;
- u_char *start, last;
- ngx_int_t value, total, scale;
- ngx_uint_t max, i;
+ size_t len;
+ u_char *start, last;
+ ngx_int_t value, total, scale;
+ ngx_uint_t max, i;
enum {
st_start = 0,
st_year,