Mailing List Archive

[6882] cherokee/trunk/cherokee: Enhances the handle_proxy so it can handle multi-IP sources nicely.
Revision: 6882
http://svn.cherokee-project.com/changeset/6882
Author: alo
Date: 2011-10-06 12:06:43 +0200 (Thu, 06 Oct 2011)
Log Message:
-----------
Enhances the handle_proxy so it can handle multi-IP sources nicely.
The proxy handler will try to use the different IPs returned by the
DNS in case some of them is not reachable.

Modified Paths:
--------------
cherokee/trunk/cherokee/access.c
cherokee/trunk/cherokee/handler_proxy.c
cherokee/trunk/cherokee/proxy_hosts.c
cherokee/trunk/cherokee/proxy_hosts.h
cherokee/trunk/cherokee/resolv_cache.c
cherokee/trunk/cherokee/socket.c
cherokee/trunk/cherokee/socket.h
cherokee/trunk/cherokee/source.c

Modified: cherokee/trunk/cherokee/access.c
===================================================================
--- cherokee/trunk/cherokee/access.c 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/access.c 2011-10-06 10:06:43 UTC (rev 6882)
@@ -342,7 +342,7 @@
while (addr != NULL) {
ret = cherokee_ntop (addr->ai_family, addr->ai_addr, ip, sizeof(ip));
if (unlikely(ret!=ret_ok)) return ret;
-
+
TRACE (ENTRIES, "Access: domain '%s' -> IP: %s\n", domain, ip);
ret = cherokee_access_add_ip (entry, (char *)ip);
if (unlikely(ret!=ret_ok)) return ret;

Modified: cherokee/trunk/cherokee/handler_proxy.c
===================================================================
--- cherokee/trunk/cherokee/handler_proxy.c 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/handler_proxy.c 2011-10-06 10:06:43 UTC (rev 6882)
@@ -933,6 +933,14 @@
hdl->init_phase = proxy_init_preconnect;
TRACE(ENTRIES, "Entering phase '%s'\n", "preconnect");

+ /* Get the addrinfo object */
+ if (hdl->pconn->addr_info_ref == NULL) {
+ ret = cherokee_handler_proxy_conn_get_addrinfo (hdl->pconn, hdl->src_ref);
+ if (ret != ret_ok) {
+ return ret_error;
+ }
+ }
+
case proxy_init_preconnect:
/* Configure if respinned
*/
@@ -959,7 +967,7 @@

if (! cherokee_socket_configured (&hdl->pconn->socket))
{
- ret = cherokee_proxy_util_init_socket (&hdl->pconn->socket, hdl->src_ref);
+ ret = cherokee_handler_proxy_conn_init_socket (hdl->pconn, hdl->src_ref);
if (ret != ret_ok) {
hdl->pconn->keepalive_in = false;
conn->error_code = http_bad_gateway;
@@ -985,6 +993,14 @@
case ret_eagain:
return ret_eagain;
case ret_deny:
+ /* Multiple IPs on a single source */
+ if (hdl->pconn->addr_current < hdl->pconn->addr_total) {
+ hdl->pconn->addr_current += 1;
+ cherokee_socket_close (&hdl->pconn->socket);
+ cherokee_socket_clean (&hdl->pconn->socket);
+ goto reconnect;
+ }
+
if (hdl->respinned) {
cherokee_balancer_report_fail (props->balancer, conn, hdl->src_ref);
conn->error_code = http_bad_gateway;

Modified: cherokee/trunk/cherokee/proxy_hosts.c
===================================================================
--- cherokee/trunk/cherokee/proxy_hosts.c 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/proxy_hosts.c 2011-10-06 10:06:43 UTC (rev 6882)
@@ -176,12 +176,18 @@
if (ret != ret_ok)
goto error;

- ret = cherokee_proxy_util_init_socket (&n->socket, src);
+ ret = cherokee_handler_proxy_conn_get_addrinfo (n, src);
if (ret != ret_ok) {
cherokee_handler_proxy_conn_free (n);
goto error;
}

+ ret = cherokee_handler_proxy_conn_init_socket (n, src);
+ if (ret != ret_ok) {
+ cherokee_handler_proxy_conn_free (n);
+ goto error;
+ }
+
cherokee_list_add (&n->listed, &poll->active);
n->poll_ref = poll;
*pconn = n;
@@ -266,6 +272,9 @@
n->size_in = 0;
n->sent_out = 0;
n->enc = pconn_enc_none;
+ n->addr_total = 0;
+ n->addr_current = 0;
+ n->addr_info_ref = NULL;

*pconn = n;
return ret_ok;
@@ -432,50 +441,91 @@
*/

ret_t
-cherokee_proxy_util_init_socket (cherokee_socket_t *socket,
- cherokee_source_t *src)
+cherokee_handler_proxy_conn_init_socket (cherokee_handler_proxy_conn_t *pconn,
+ cherokee_source_t *src)
{
- ret_t ret;
- cherokee_resolv_cache_t *resolv;
- const struct addrinfo *addr_info = NULL;
+ ret_t ret;
+ cherokee_socket_t *socket = &pconn->socket;

TRACE (ENTRIES, "Initializing proxy %s\n", "socket");

- /* Resolve the hostname of the target server */
- ret = cherokee_resolv_cache_get_default (&resolv);
- if (unlikely (ret != ret_ok)) {
- return ret_error;
- }
-
- ret = cherokee_resolv_cache_get_addrinfo (resolv, &src->host, &addr_info);
- if ((ret != ret_ok) || (addr_info == NULL)) {
- return ret_error;
- }
-
/* Ensure that no fd leak happens */
cherokee_socket_close (socket);

/* Create the socket descriptor */
- ret = cherokee_socket_create_fd (socket, addr_info->ai_family);
+ ret = cherokee_socket_create_fd (socket, pconn->addr_info_ref->ai_family);
if (unlikely (ret != ret_ok)) {
return ret_error;
}

/* Update the new socket */
- SOCKET_SIN_PORT(socket) = htons (src->port);
-
- ret = cherokee_socket_update_from_addrinfo (socket, addr_info);
+ ret = cherokee_socket_update_from_addrinfo (socket, pconn->addr_info_ref, pconn->addr_current);
if (unlikely (ret != ret_ok)) {
return ret_error;
}

- TRACE (ENTRIES, "Proxy socket Initialized: %s, target: %s\n",
- SOCKET_AF(socket) == AF_INET6 ? "IPv6": "IPv4", src->host.buf);
+ SOCKET_SIN_PORT(socket) = htons (src->port);

/* Set a few properties */
cherokee_fd_set_closexec (socket->socket);
cherokee_fd_set_nonblocking (socket->socket, true);
cherokee_fd_set_nodelay (socket->socket, true);

+ /* Trace */
+#ifdef TRACE_ENABLED
+ if (cherokee_trace_is_tracing()) {
+ cuint_t ip_num;
+ struct addrinfo *ai;
+ char buf[50];
+
+ ai = pconn->addr_info_ref;
+ ip_num = pconn->addr_current;
+
+ while (ip_num--) {
+ ai = ai->ai_next;
+ }
+
+ ret = cherokee_ntop (pconn->addr_info_ref->ai_family, ai->ai_addr, buf, 50);
+ if (ret == ret_ok) {
+ TRACE (ENTRIES, "Proxy socket Initialized: %s, target: %s, IP: %s\n",
+ SOCKET_AF(socket) == AF_INET6 ? "IPv6": "IPv4", src->host.buf, buf);
+ }
+ }
+#endif
+
return ret_ok;
}
+
+
+ret_t
+cherokee_handler_proxy_conn_get_addrinfo (cherokee_handler_proxy_conn_t *pconn,
+ cherokee_source_t *src)
+{
+ ret_t ret;
+ struct addrinfo *ai;
+ cherokee_resolv_cache_t *resolv;
+
+ /* Resolve the hostname of the target server
+ */
+ ret = cherokee_resolv_cache_get_default (&resolv);
+ if (unlikely (ret != ret_ok)) {
+ return ret_error;
+ }
+
+ ret = cherokee_resolv_cache_get_addrinfo (resolv, &src->host, &pconn->addr_info_ref);
+ if ((ret != ret_ok) || (pconn->addr_info_ref == NULL)) {
+ return ret_error;
+ }
+
+ /* Count the number of IPs
+ */
+ if (pconn->addr_total == 0) {
+ ai = pconn->addr_info_ref;
+ while (ai != NULL) {
+ pconn->addr_total += 1;
+ ai = ai->ai_next;
+ }
+ }
+
+ return ret_ok;
+}

Modified: cherokee/trunk/cherokee/proxy_hosts.h
===================================================================
--- cherokee/trunk/cherokee/proxy_hosts.h 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/proxy_hosts.h 2011-10-06 10:06:43 UTC (rev 6882)
@@ -57,6 +57,11 @@
cherokee_socket_t socket;
cherokee_handler_proxy_poll_t *poll_ref;

+ /* Name resolution */
+ const struct addrinfo *addr_info_ref;
+ cuint_t addr_total;
+ cuint_t addr_current;
+
/* In */
cherokee_handler_proxy_enc_t enc;
cherokee_buffer_t header_in_raw;
@@ -107,12 +112,11 @@
ret_t cherokee_handler_proxy_conn_recv_headers (cherokee_handler_proxy_conn_t *pconn,
cherokee_buffer_t *body,
cherokee_boolean_t flexible);
+ret_t cherokee_handler_proxy_conn_get_addrinfo (cherokee_handler_proxy_conn_t *pconn,
+ cherokee_source_t *src);
+ret_t cherokee_handler_proxy_conn_init_socket (cherokee_handler_proxy_conn_t *pconn,
+ cherokee_source_t *src);

-/* Utils
- */
-ret_t cherokee_proxy_util_init_socket (cherokee_socket_t *socket,
- cherokee_source_t *src);
-
#endif /* CHEROKEE_HANDLER_PROXY_HOSTS_H */



Modified: cherokee/trunk/cherokee/resolv_cache.c
===================================================================
--- cherokee/trunk/cherokee/resolv_cache.c 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/resolv_cache.c 2011-10-06 10:06:43 UTC (rev 6882)
@@ -45,6 +45,7 @@
typedef struct {
struct addrinfo *addr;
cherokee_buffer_t ip_str;
+ cherokee_buffer_t ip_str_all;
} cherokee_resolv_cache_entry_t;

struct cherokee_resolv_cache {
@@ -64,6 +65,7 @@

n->addr = NULL;
cherokee_buffer_init (&n->ip_str);
+ cherokee_buffer_init (&n->ip_str_all);

*entry = n;
return ret_ok;
@@ -80,6 +82,7 @@
}

cherokee_buffer_mrproper (&e->ip_str);
+ cherokee_buffer_mrproper (&e->ip_str_all);
free(entry);
}

@@ -88,9 +91,10 @@
entry_fill_up (cherokee_resolv_cache_entry_t *entry,
cherokee_buffer_t *domain)
{
- ret_t ret;
- char tmp[46]; // Max IPv6 length is 45
- time_t eagain_at = 0;
+ ret_t ret;
+ char tmp[46]; // Max IPv6 length is 45
+ struct addrinfo *addr;
+ time_t eagain_at = 0;

while (true) {
ret = cherokee_gethostbyname (domain->buf, &entry->addr);
@@ -126,6 +130,24 @@
}

cherokee_buffer_add (&entry->ip_str, tmp, strlen(tmp));
+
+ /* Render the text representation (all the IPs)
+ */
+ cherokee_buffer_add_buffer (&entry->ip_str_all, &entry->ip_str);
+
+ addr = entry->addr;
+ while (addr != NULL) {
+ ret = cherokee_ntop (entry->addr->ai_family, addr->ai_addr, tmp, sizeof(tmp));
+ if (ret != ret_ok) {
+ return ret_error;
+ }
+
+ cherokee_buffer_add_char (&entry->ip_str_all, ',');
+ cherokee_buffer_add (&entry->ip_str_all, tmp, strlen(tmp));
+
+ addr = addr->ai_next;
+ }
+
return ret_ok;
}

@@ -246,9 +268,9 @@
if (ret != ret_ok) {
return ret;
}
- TRACE (ENTRIES, "Resolve '%s': added succesfuly as '%s'.\n", domain->buf, entry->ip_str.buf);
+ TRACE (ENTRIES, "Resolve '%s': added succesfuly as '%s'.\n", domain->buf, entry->ip_str_all.buf);
} else {
- TRACE (ENTRIES, "Resolve '%s': hit.\n", domain->buf);
+ TRACE (ENTRIES, "Resolve '%s': hit: %s\n", domain->buf, entry->ip_str_all.buf);
}

/* Return the ip string
@@ -279,7 +301,7 @@

/* Copy it to the socket object
*/
- ret = cherokee_socket_update_from_addrinfo (sock, addr);
+ ret = cherokee_socket_update_from_addrinfo (sock, addr, 0);
if (ret != ret_ok) {
return ret;
}

Modified: cherokee/trunk/cherokee/socket.c
===================================================================
--- cherokee/trunk/cherokee/socket.c 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/socket.c 2011-10-06 10:06:43 UTC (rev 6882)
@@ -367,20 +367,36 @@

ret_t
cherokee_socket_update_from_addrinfo (cherokee_socket_t *socket,
- const struct addrinfo *addr)
+ const struct addrinfo *addr,
+ cuint_t num)
{
+ struct addrinfo *ai;
+
if (unlikely (addr == NULL))
return ret_error;

+ /* Find the right address
+ */
+ ai = addr;
+ while (num > 0) {
+ num -= 1;
+ ai = ai->ai_next;
+ if (ai == NULL) {
+ return ret_not_found;
+ }
+ }
+
+ /* Copy the information
+ */
SOCKET_AF(socket) = addr->ai_family;
socket->client_addr_len = addr->ai_addrlen;

switch (addr->ai_family) {
case AF_INET:
- memcpy (&SOCKET_SIN_ADDR(socket), &((struct sockaddr_in *) addr->ai_addr)->sin_addr, sizeof(struct in_addr));
+ memcpy (&SOCKET_SIN_ADDR(socket), &((struct sockaddr_in *) ai->ai_addr)->sin_addr, sizeof(struct in_addr));
break;
case AF_INET6:
- memcpy (&SOCKET_SIN6_ADDR(socket), &((struct sockaddr_in6 *) addr->ai_addr)->sin6_addr, sizeof(struct in6_addr));
+ memcpy (&SOCKET_SIN6_ADDR(socket), &((struct sockaddr_in6 *) ai->ai_addr)->sin6_addr, sizeof(struct in6_addr));
break;
default:
SHOULDNT_HAPPEN;

Modified: cherokee/trunk/cherokee/socket.h
===================================================================
--- cherokee/trunk/cherokee/socket.h 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/socket.h 2011-10-06 10:06:43 UTC (rev 6882)
@@ -150,6 +150,6 @@
/* Extra
*/
ret_t cherokee_socket_set_sockaddr (cherokee_socket_t *socket, int fd, cherokee_sockaddr_t *sa);
-ret_t cherokee_socket_update_from_addrinfo (cherokee_socket_t *socket, const struct addrinfo *addr_info);
+ret_t cherokee_socket_update_from_addrinfo (cherokee_socket_t *socket, const struct addrinfo *addr_info, cuint_t num);

#endif /* CHEROKEE_SOCKET_H */

Modified: cherokee/trunk/cherokee/source.c
===================================================================
--- cherokee/trunk/cherokee/source.c 2011-10-05 22:14:03 UTC (rev 6881)
+++ cherokee/trunk/cherokee/source.c 2011-10-06 10:06:43 UTC (rev 6882)
@@ -119,7 +119,7 @@
/* Update the new socket */
SOCKET_ADDR_IPv4(sock)->sin_port = htons(src->port);

- ret = cherokee_socket_update_from_addrinfo (sock, addr_info);
+ ret = cherokee_socket_update_from_addrinfo (sock, addr_info, 0);
if (unlikely (ret != ret_ok)) {
return ret_error;
}