summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2017-07-15 16:19:01 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2017-07-23 19:02:30 -0400
commit0beb8b89d800f0569d6581f469baa64459188955 (patch)
tree2422c3767b1024371a75edbbc00e9817366f58c6
parentb6d08187627021e01173cc129ba7cc790465d5fd (diff)
downloadlighttpd1.4-0beb8b89d800f0569d6581f469baa64459188955.tar.gz
lighttpd1.4-0beb8b89d800f0569d6581f469baa64459188955.zip
[core] store sockaddr for socket backend procs
store struct sockaddr for socket backend procs at startup
-rw-r--r--src/gw_backend.c143
-rw-r--r--src/gw_backend.h3
2 files changed, 68 insertions, 78 deletions
diff --git a/src/gw_backend.c b/src/gw_backend.c
index c32c70cb..440bac0b 100644
--- a/src/gw_backend.c
+++ b/src/gw_backend.c
@@ -119,6 +119,7 @@ static void gw_proc_free(gw_proc *f) {
buffer_free(f->unixsocket);
buffer_free(f->connection_name);
+ free(f->saddr);
free(f);
}
@@ -356,6 +357,49 @@ static int gw_proc_waitpid(server *srv, gw_host *host, gw_proc *proc) {
return 1;
}
+static int gw_proc_sockaddr_init(server *srv, gw_host *host, gw_proc *proc) {
+ sock_addr addr;
+ socklen_t addrlen;
+
+ if (!buffer_string_is_empty(proc->unixsocket)) {
+ if (1 != sock_addr_from_str_hints(srv, &addr, &addrlen,
+ proc->unixsocket->ptr, AF_UNIX, 0)) {
+ errno = EINVAL;
+ return -1;
+ }
+ buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("unix:"));
+ buffer_append_string_buffer(proc->connection_name, proc->unixsocket);
+ } else {
+ if (1 != sock_addr_from_buffer_hints_numeric(srv, &addr, &addrlen,
+ host->host, host->family,
+ proc->port)) {
+ errno = EINVAL;
+ return -1;
+ }
+ buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("tcp:"));
+ if (!buffer_string_is_empty(host->host)) {
+ buffer_append_string_buffer(proc->connection_name, host->host);
+ } else {
+ buffer_append_string_len(proc->connection_name,
+ CONST_STR_LEN("localhost"));
+ }
+ buffer_append_string_len(proc->connection_name, CONST_STR_LEN(":"));
+ buffer_append_int(proc->connection_name, proc->port);
+ }
+
+ if (NULL != proc->saddr && proc->saddrlen < addrlen) {
+ free(proc->saddr);
+ proc->saddr = NULL;
+ }
+ if (NULL == proc->saddr) {
+ proc->saddr = (struct sockaddr *)malloc(addrlen);
+ force_assert(proc->saddr);
+ }
+ proc->saddrlen = addrlen;
+ memcpy(proc->saddr, &addr, addrlen);
+ return 0;
+}
+
static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
char *dst;
@@ -394,44 +438,13 @@ static int gw_spawn_connection(server *srv, gw_host *host, gw_proc *proc, int de
int gw_fd;
int status;
struct timeval tv = { 0, 10 * 1000 };
- sock_addr addr;
- struct sockaddr *gw_addr = (struct sockaddr *)&addr;
- socklen_t servlen;
if (debug) {
log_error_write(srv, __FILE__, __LINE__, "sdb",
"new proc, socket:", proc->port, proc->unixsocket);
}
- if (!buffer_string_is_empty(proc->unixsocket)) {
- if (1 != sock_addr_from_str_hints(srv, &addr, &servlen,
- proc->unixsocket->ptr, AF_UNIX, 0)) {
- return -1;
- }
- } else {
- if (1 != sock_addr_from_buffer_hints_numeric(srv, &addr, &servlen,
- host->host, host->family,
- proc->port)) {
- return -1;
- }
- }
-
- if (!buffer_string_is_empty(proc->unixsocket)) {
- buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("unix:"));
- buffer_append_string_buffer(proc->connection_name, proc->unixsocket);
- } else {
- buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("tcp:"));
- if (!buffer_string_is_empty(host->host)) {
- buffer_append_string_buffer(proc->connection_name, host->host);
- } else {
- buffer_append_string_len(proc->connection_name,
- CONST_STR_LEN("localhost"));
- }
- buffer_append_string_len(proc->connection_name, CONST_STR_LEN(":"));
- buffer_append_int(proc->connection_name, proc->port);
- }
-
- gw_fd = fdevent_socket_cloexec(gw_addr->sa_family, SOCK_STREAM, 0);
+ gw_fd = fdevent_socket_cloexec(proc->saddr->sa_family, SOCK_STREAM, 0);
if (-1 == gw_fd) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"failed:", strerror(errno));
@@ -439,7 +452,7 @@ static int gw_spawn_connection(server *srv, gw_host *host, gw_proc *proc, int de
}
do {
- status = connect(gw_fd, gw_addr, servlen);
+ status = connect(gw_fd, proc->saddr, proc->saddrlen);
} while (-1 == status && errno == EINTR);
if (-1 == status && errno != ENOENT
@@ -460,7 +473,7 @@ static int gw_spawn_connection(server *srv, gw_host *host, gw_proc *proc, int de
int dfd = -1;
/* reopen socket */
- gw_fd = fdevent_socket_cloexec(gw_addr->sa_family, SOCK_STREAM, 0);
+ gw_fd = fdevent_socket_cloexec(proc->saddr->sa_family, SOCK_STREAM, 0);
if (-1 == gw_fd) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"socket failed:", strerror(errno));
@@ -476,7 +489,7 @@ static int gw_spawn_connection(server *srv, gw_host *host, gw_proc *proc, int de
}
/* create socket */
- if (-1 == bind(gw_fd, gw_addr, servlen)) {
+ if (-1 == bind(gw_fd, proc->saddr, proc->saddrlen)) {
log_error_write(srv, __FILE__, __LINE__, "sbs",
"bind failed for:",
proc->connection_name,
@@ -629,7 +642,15 @@ static void gw_proc_spawn(server *srv, gw_host *host, int debug) {
buffer_append_int(proc->unixsocket, proc->id);
}
- if (gw_spawn_connection(srv, host, proc, debug)) {
+ if (0 != gw_proc_sockaddr_init(srv, host, proc)) {
+ /*(should not happen if host->host validated at startup,
+ * and translated from name to IP address at startup)*/
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ERROR: spawning backend failed.");
+ --host->num_procs;
+ if (proc->id == host->max_id-1) --host->max_id;
+ gw_proc_free(proc);
+ } else if (gw_spawn_connection(srv, host, proc, debug)) {
log_error_write(srv, __FILE__, __LINE__, "s",
"ERROR: spawning backend failed.");
proc->next = host->unused_procs;
@@ -908,48 +929,7 @@ static gw_host * gw_host_get(server *srv, connection *con, gw_extension *extensi
}
static int gw_establish_connection(server *srv, gw_host *host, gw_proc *proc, pid_t pid, int gw_fd, int debug) {
- sock_addr addr;
- struct sockaddr *gw_addr = (struct sockaddr *)&addr;
- socklen_t servlen;
-
- if (!buffer_string_is_empty(proc->unixsocket)) {
- if (1 != sock_addr_from_str_hints(srv, &addr, &servlen,
- proc->unixsocket->ptr, AF_UNIX, 0)) {
- errno = EINVAL;
- return -1;
- }
- } else {
- if (1 != sock_addr_from_buffer_hints_numeric(srv, &addr, &servlen,
- host->host, host->family,
- proc->port)) {
- errno = EINVAL;
- return -1;
- }
- }
-
- if (!buffer_string_is_empty(proc->unixsocket)) {
- if (buffer_string_is_empty(proc->connection_name)) {
- /* on remote spawning we have to set the connection-name now */
- buffer_copy_string_len(proc->connection_name,
- CONST_STR_LEN("unix:"));
- buffer_append_string_buffer(proc->connection_name,proc->unixsocket);
- }
- } else {
- if (buffer_string_is_empty(proc->connection_name)) {
- /* on remote spawning we have to set the connection-name now */
- buffer_copy_string_len(proc->connection_name,CONST_STR_LEN("tcp:"));
- if (!buffer_string_is_empty(host->host)) {
- buffer_append_string_buffer(proc->connection_name, host->host);
- } else {
- buffer_append_string_len(proc->connection_name,
- CONST_STR_LEN("localhost"));
- }
- buffer_append_string_len(proc->connection_name, CONST_STR_LEN(":"));
- buffer_append_int(proc->connection_name, proc->port);
- }
- }
-
- if (-1 == connect(gw_fd, gw_addr, servlen)) {
+ if (-1 == connect(gw_fd, proc->saddr, proc->saddrlen)) {
if (errno == EINPROGRESS ||
errno == EALREADY ||
errno == EINTR) {
@@ -1460,6 +1440,11 @@ int gw_set_defaults_backend(server *srv, gw_plugin_data *p, data_unset *du, size
"\n\tcurrent:", pno, "/", host->max_procs);
}
+ if (0 != gw_proc_sockaddr_init(srv, host, proc)) {
+ gw_proc_free(proc);
+ goto error;
+ }
+
if (!srv->srvconf.preflight_check
&& gw_spawn_connection(srv, host, proc, s->debug)) {
log_error_write(srv, __FILE__, __LINE__, "s",
@@ -1495,6 +1480,8 @@ int gw_set_defaults_backend(server *srv, gw_plugin_data *p, data_unset *du, size
host->min_procs = 1;
host->max_procs = 1;
+
+ if (0 != gw_proc_sockaddr_init(srv, host, proc)) goto error;
}
if (!buffer_string_is_empty(gw_mode)) {
diff --git a/src/gw_backend.h b/src/gw_backend.h
index 2787c97c..5ed2d1d8 100644
--- a/src/gw_backend.h
+++ b/src/gw_backend.h
@@ -4,6 +4,7 @@
#include "first.h"
#include <sys/types.h>
+#include "sys-socket.h"
#include "array.h"
#include "buffer.h"
@@ -19,6 +20,8 @@ typedef struct gw_proc {
size_t id; /* id will be between 1 and max_procs */
buffer *unixsocket; /* config.socket + "-" + id */
unsigned port; /* config.port + pno */
+ socklen_t saddrlen;
+ struct sockaddr *saddr;
/* either tcp:<host>:<port> or unix:<socket> for debugging purposes */
buffer *connection_name;