summaryrefslogtreecommitdiffhomepage
path: root/src/reqs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reqs.c')
-rw-r--r--src/reqs.c401
1 files changed, 184 insertions, 217 deletions
diff --git a/src/reqs.c b/src/reqs.c
index 76209db..f6fd2be 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -32,7 +32,8 @@
#include "buffer.h"
#include "conns.h"
#include "filter.h"
-#include "hashmap.h"
+#include "hsearch.h"
+#include "orderedmap.h"
#include "heap.h"
#include "html-error.h"
#include "log.h"
@@ -42,7 +43,7 @@
#include "stats.h"
#include "text.h"
#include "utils.h"
-#include "vector.h"
+#include "sblist.h"
#include "reverse-proxy.h"
#include "transparent-proxy.h"
#include "upstream.h"
@@ -50,6 +51,7 @@
#include "conf.h"
#include "basicauth.h"
#include "loop.h"
+#include "mypoll.h"
/*
* Maximum length of a HTTP line
@@ -321,7 +323,7 @@ static int send_ssl_response (struct conn_s *connptr)
* build a new request line. Finally connect to the remote server.
*/
static struct request_s *process_request (struct conn_s *connptr,
- hashmap_t hashofheaders)
+ orderedmap hashofheaders)
{
char *url;
struct request_s *request;
@@ -602,7 +604,7 @@ static int add_xtinyproxy_header (struct conn_s *connptr)
* can be retrieved and manipulated later.
*/
static int
-add_header_to_connection (hashmap_t hashofheaders, char *header, size_t len)
+add_header_to_connection (orderedmap hashofheaders, char *header, size_t len)
{
char *sep;
@@ -620,7 +622,7 @@ add_header_to_connection (hashmap_t hashofheaders, char *header, size_t len)
/* Calculate the new length of just the data */
len -= sep - header - 1;
- return hashmap_insert (hashofheaders, header, sep, len);
+ return orderedmap_append (hashofheaders, header, sep);
}
/*
@@ -633,7 +635,7 @@ add_header_to_connection (hashmap_t hashofheaders, char *header, size_t len)
/*
* Read all the headers from the stream
*/
-static int get_all_headers (int fd, hashmap_t hashofheaders)
+static int get_all_headers (int fd, orderedmap hashofheaders)
{
char *line = NULL;
char *header = NULL;
@@ -726,7 +728,7 @@ static int get_all_headers (int fd, hashmap_t hashofheaders)
* Extract the headers to remove. These headers were listed in the Connection
* and Proxy-Connection headers.
*/
-static int remove_connection_headers (hashmap_t hashofheaders)
+static int remove_connection_headers (orderedmap hashofheaders)
{
static const char *headers[] = {
"connection",
@@ -740,12 +742,13 @@ static int remove_connection_headers (hashmap_t hashofheaders)
for (i = 0; i != (sizeof (headers) / sizeof (char *)); ++i) {
/* Look for the connection header. If it's not found, return. */
- len =
- hashmap_entry_by_key (hashofheaders, headers[i],
- (void **) &data);
- if (len <= 0)
+ data = orderedmap_find(hashofheaders, headers[i]);
+
+ if (!data)
return 0;
+ len = strlen(data);
+
/*
* Go through the data line and replace any special characters
* with a NULL.
@@ -760,7 +763,7 @@ static int remove_connection_headers (hashmap_t hashofheaders)
*/
ptr = data;
while (ptr < data + len) {
- hashmap_remove (hashofheaders, ptr);
+ orderedmap_remove (hashofheaders, ptr);
/* Advance ptr to the next token */
ptr += strlen (ptr) + 1;
@@ -769,7 +772,7 @@ static int remove_connection_headers (hashmap_t hashofheaders)
}
/* Now remove the connection header it self. */
- hashmap_remove (hashofheaders, headers[i]);
+ orderedmap_remove (hashofheaders, headers[i]);
}
return 0;
@@ -779,16 +782,14 @@ static int remove_connection_headers (hashmap_t hashofheaders)
* If there is a Content-Length header, then return the value; otherwise, return
* a negative number.
*/
-static long get_content_length (hashmap_t hashofheaders)
+static long get_content_length (orderedmap hashofheaders)
{
- ssize_t len;
char *data;
long content_length = -1;
- len =
- hashmap_entry_by_key (hashofheaders, "content-length",
- (void **) &data);
- if (len > 0)
+ data = orderedmap_find (hashofheaders, "content-length");
+
+ if (data)
content_length = atol (data);
return content_length;
@@ -802,10 +803,9 @@ static long get_content_length (hashmap_t hashofheaders)
* purposes.
*/
static int
-write_via_header (int fd, hashmap_t hashofheaders,
+write_via_header (int fd, orderedmap hashofheaders,
unsigned int major, unsigned int minor)
{
- ssize_t len;
char hostname[512];
char *data;
int ret;
@@ -825,14 +825,14 @@ write_via_header (int fd, hashmap_t hashofheaders,
* See if there is a "Via" header. If so, again we need to do a bit
* of processing.
*/
- len = hashmap_entry_by_key (hashofheaders, "via", (void **) &data);
- if (len > 0) {
+ data = orderedmap_find (hashofheaders, "via");
+ if (data) {
ret = write_message (fd,
"Via: %s, %hu.%hu %s (%s/%s)\r\n",
data, major, minor, hostname, PACKAGE,
VERSION);
- hashmap_remove (hashofheaders, "via");
+ orderedmap_remove (hashofheaders, "via");
} else {
ret = write_message (fd,
"Via: %hu.%hu %s (%s/%s)\r\n",
@@ -846,7 +846,7 @@ done:
/*
* Number of buckets to use internally in the hashmap.
*/
-#define HEADER_BUCKETS 256
+#define HEADER_BUCKETS 32
/*
* Here we loop through all the headers the client is sending. If we
@@ -855,7 +855,7 @@ done:
* - rjkaes
*/
static int
-process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
+process_client_headers (struct conn_s *connptr, orderedmap hashofheaders)
{
static const char *skipheaders[] = {
"host",
@@ -866,7 +866,7 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
"upgrade"
};
int i;
- hashmap_iter iter;
+ size_t iter;
int ret = 0;
char *data, *header;
@@ -899,7 +899,7 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
* Delete the headers listed in the skipheaders list
*/
for (i = 0; i != (sizeof (skipheaders) / sizeof (char *)); i++) {
- hashmap_remove (hashofheaders, skipheaders[i]);
+ orderedmap_remove (hashofheaders, skipheaders[i]);
}
/* Send, or add the Via header */
@@ -919,27 +919,22 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
/*
* Output all the remaining headers to the remote machine.
*/
- iter = hashmap_first (hashofheaders);
- if (iter >= 0) {
- for (; !hashmap_is_end (hashofheaders, iter); ++iter) {
- hashmap_return_entry (hashofheaders,
- iter, &data, (void **) &header);
-
- if (!is_anonymous_enabled (config)
- || anonymous_search (config, data) > 0) {
- ret =
- write_message (connptr->server_fd,
- "%s: %s\r\n", data, header);
- if (ret < 0) {
- indicate_http_error (connptr, 503,
- "Could not send data to remote server",
- "detail",
- "A network error occurred while "
- "trying to write data to the "
- "remote web server.",
- NULL);
- goto PULL_CLIENT_DATA;
- }
+ iter = 0;
+ while((iter = orderedmap_next(hashofheaders, iter, &data, &header))) {
+ if (!is_anonymous_enabled (config)
+ || anonymous_search (config, data) > 0) {
+ ret =
+ write_message (connptr->server_fd,
+ "%s: %s\r\n", data, header);
+ if (ret < 0) {
+ indicate_http_error (connptr, 503,
+ "Could not send data to remote server",
+ "detail",
+ "A network error occurred while "
+ "trying to write data to the "
+ "remote web server.",
+ NULL);
+ goto PULL_CLIENT_DATA;
}
}
}
@@ -979,8 +974,8 @@ static int process_server_headers (struct conn_s *connptr)
char *response_line;
- hashmap_t hashofheaders;
- hashmap_iter iter;
+ orderedmap hashofheaders;
+ size_t iter;
char *data, *header;
ssize_t len;
int i;
@@ -1009,7 +1004,7 @@ retry:
goto retry;
}
- hashofheaders = hashmap_create (HEADER_BUCKETS);
+ hashofheaders = orderedmap_create (HEADER_BUCKETS);
if (!hashofheaders) {
safefree (response_line);
return -1;
@@ -1021,7 +1016,7 @@ retry:
if (get_all_headers (connptr->server_fd, hashofheaders) < 0) {
log_message (LOG_WARNING,
"Could not retrieve all the headers from the remote server.");
- hashmap_delete (hashofheaders);
+ orderedmap_destroy (hashofheaders);
safefree (response_line);
indicate_http_error (connptr, 503,
@@ -1040,7 +1035,7 @@ retry:
* Instead we'll free all the memory and return.
*/
if (connptr->protocol.major < 1) {
- hashmap_delete (hashofheaders);
+ orderedmap_destroy (hashofheaders);
safefree (response_line);
return 0;
}
@@ -1067,7 +1062,7 @@ retry:
* Delete the headers listed in the skipheaders list
*/
for (i = 0; i != (sizeof (skipheaders) / sizeof (char *)); i++) {
- hashmap_remove (hashofheaders, skipheaders[i]);
+ orderedmap_remove (hashofheaders, skipheaders[i]);
}
/* Send, or add the Via header */
@@ -1089,8 +1084,7 @@ retry:
/* Rewrite the HTTP redirect if needed */
if (config->reversebaseurl &&
- hashmap_entry_by_key (hashofheaders, "location",
- (void **) &header) > 0) {
+ (header = orderedmap_find (hashofheaders, "location"))) {
/* Look for a matching entry in the reversepath list */
while (reverse) {
@@ -1115,7 +1109,7 @@ retry:
"Rewriting HTTP redirect: %s -> %s%s%s",
header, config->reversebaseurl,
(reverse->path + 1), (header + len));
- hashmap_remove (hashofheaders, "location");
+ orderedmap_remove (hashofheaders, "location");
}
}
#endif
@@ -1123,19 +1117,15 @@ retry:
/*
* All right, output all the remaining headers to the client.
*/
- iter = hashmap_first (hashofheaders);
- if (iter >= 0) {
- for (; !hashmap_is_end (hashofheaders, iter); ++iter) {
- hashmap_return_entry (hashofheaders,
- iter, &data, (void **) &header);
-
- ret = write_message (connptr->client_fd,
- "%s: %s\r\n", data, header);
- if (ret < 0)
- goto ERROR_EXIT;
- }
+ iter = 0;
+ while ((iter = orderedmap_next(hashofheaders, iter, &data, &header))) {
+
+ ret = write_message (connptr->client_fd,
+ "%s: %s\r\n", data, header);
+ if (ret < 0)
+ goto ERROR_EXIT;
}
- hashmap_delete (hashofheaders);
+ orderedmap_destroy (hashofheaders);
/* Write the final blank line to signify the end of the headers */
if (safe_write (connptr->client_fd, "\r\n", 2) < 0)
@@ -1144,7 +1134,7 @@ retry:
return 0;
ERROR_EXIT:
- hashmap_delete (hashofheaders);
+ orderedmap_destroy (hashofheaders);
return -1;
}
@@ -1158,74 +1148,39 @@ ERROR_EXIT:
*/
static void relay_connection (struct conn_s *connptr)
{
- fd_set rset, wset;
- struct timeval tv;
- time_t last_access;
int ret;
- double tdiff;
- int maxfd = max (connptr->client_fd, connptr->server_fd) + 1;
ssize_t bytes_received;
- ret = socket_nonblocking (connptr->client_fd);
- if (ret != 0) {
- log_message(LOG_ERR, "Failed to set the client socket "
- "to non-blocking: %s", strerror(errno));
- return;
- }
-
- ret = socket_nonblocking (connptr->server_fd);
- if (ret != 0) {
- log_message(LOG_ERR, "Failed to set the server socket "
- "to non-blocking: %s", strerror(errno));
- return;
- }
-
- last_access = time (NULL);
-
for (;;) {
- FD_ZERO (&rset);
- FD_ZERO (&wset);
-
- tv.tv_sec =
- config->idletimeout - difftime (time (NULL), last_access);
- tv.tv_usec = 0;
+ pollfd_struct fds[2] = {0};
+ fds[0].fd = connptr->client_fd;
+ fds[1].fd = connptr->server_fd;
if (buffer_size (connptr->sbuffer) > 0)
- FD_SET (connptr->client_fd, &wset);
+ fds[0].events |= MYPOLL_WRITE;
if (buffer_size (connptr->cbuffer) > 0)
- FD_SET (connptr->server_fd, &wset);
+ fds[1].events |= MYPOLL_WRITE;
if (buffer_size (connptr->sbuffer) < MAXBUFFSIZE)
- FD_SET (connptr->server_fd, &rset);
+ fds[1].events |= MYPOLL_READ;
if (buffer_size (connptr->cbuffer) < MAXBUFFSIZE)
- FD_SET (connptr->client_fd, &rset);
+ fds[0].events |= MYPOLL_READ;
- ret = select (maxfd, &rset, &wset, NULL, &tv);
+ ret = mypoll(fds, 2, config->idletimeout);
if (ret == 0) {
- tdiff = difftime (time (NULL), last_access);
- if (tdiff > config->idletimeout) {
- log_message (LOG_INFO,
- "Idle Timeout (after select) as %g > %u.",
- tdiff, config->idletimeout);
+ log_message (LOG_INFO,
+ "Idle Timeout (after " SELECT_OR_POLL ")");
return;
- } else {
- continue;
- }
} else if (ret < 0) {
log_message (LOG_ERR,
- "relay_connection: select() error \"%s\". "
+ "relay_connection: " SELECT_OR_POLL "() error \"%s\". "
"Closing connection (client_fd:%d, server_fd:%d)",
strerror (errno), connptr->client_fd,
connptr->server_fd);
return;
- } else {
- /*
- * All right, something was actually selected so mark it.
- */
- last_access = time (NULL);
}
- if (FD_ISSET (connptr->server_fd, &rset)) {
+ if (fds[1].revents & MYPOLL_READ) {
bytes_received =
read_buffer (connptr->server_fd, connptr->sbuffer);
if (bytes_received < 0)
@@ -1235,32 +1190,20 @@ static void relay_connection (struct conn_s *connptr)
if (connptr->content_length.server == 0)
break;
}
- if (FD_ISSET (connptr->client_fd, &rset)
+ if ((fds[0].revents & MYPOLL_READ)
&& read_buffer (connptr->client_fd, connptr->cbuffer) < 0) {
break;
}
- if (FD_ISSET (connptr->server_fd, &wset)
+ if ((fds[1].revents & MYPOLL_WRITE)
&& write_buffer (connptr->server_fd, connptr->cbuffer) < 0) {
break;
}
- if (FD_ISSET (connptr->client_fd, &wset)
+ if ((fds[0].revents & MYPOLL_WRITE)
&& write_buffer (connptr->client_fd, connptr->sbuffer) < 0) {
break;
}
}
- /*
- * Here the server has closed the connection... write the
- * remainder to the client and then exit.
- */
- ret = socket_blocking (connptr->client_fd);
- if (ret != 0) {
- log_message(LOG_ERR,
- "Failed to set client socket to blocking: %s",
- strerror(errno));
- return;
- }
-
while (buffer_size (connptr->sbuffer) > 0) {
if (write_buffer (connptr->client_fd, connptr->sbuffer) < 0)
break;
@@ -1431,7 +1374,7 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
connptr->server_fd =
opensock (cur_upstream->host, cur_upstream->port,
- connptr->server_ip_addr);
+ connptr->server_ip_addr, NULL);
if (connptr->server_fd < 0) {
log_message (LOG_WARNING,
@@ -1487,27 +1430,27 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
#endif
}
+/* this function "drains" remaining bytes in the read pipe from
+ the client. it's usually only called on error before displaying
+ an error code/page. */
static int
get_request_entity(struct conn_s *connptr)
{
int ret;
- fd_set rset, wset;
- struct timeval tv;
+ pollfd_struct fds[1] = {0};
- FD_ZERO (&rset);
- FD_SET (connptr->client_fd, &rset);
- memcpy(&wset, &rset, sizeof wset);
- tv.tv_sec = config->idletimeout;
- tv.tv_usec = 0;
- ret = select (connptr->client_fd + 1, &rset, &wset, NULL, &tv);
+ fds[0].fd = connptr->client_fd;
+ fds[0].events |= MYPOLL_READ;
+
+ ret = mypoll(fds, 1, config->idletimeout);
if (ret == -1) {
log_message (LOG_ERR,
- "Error calling select on client fd %d: %s",
+ "Error calling " SELECT_OR_POLL " on client fd %d: %s",
connptr->client_fd, strerror(errno));
} else if (ret == 0) {
log_message (LOG_INFO, "no entity");
- } else if (ret == 1 && FD_ISSET (connptr->client_fd, &rset)) {
+ } else if (ret == 1 && (fds[0].revents & MYPOLL_READ)) {
ssize_t nread;
nread = read_buffer (connptr->client_fd, connptr->cbuffer);
if (nread < 0) {
@@ -1517,14 +1460,12 @@ get_request_entity(struct conn_s *connptr)
ret = -1;
} else {
log_message (LOG_INFO,
- "Read request entity of %d bytes",
- nread);
+ "Read request entity of %ld bytes",
+ (long) nread);
ret = 0;
}
- } else if (ret == 1 && FD_ISSET (connptr->client_fd, &wset) && connptr->connect_method) {
- ret = 0;
} else {
- log_message (LOG_ERR, "strange situation after select: "
+ log_message (LOG_ERR, "strange situation after " SELECT_OR_POLL ": "
"ret = %d, but client_fd (%d) is not readable...",
ret, connptr->client_fd);
ret = -1;
@@ -1533,6 +1474,31 @@ get_request_entity(struct conn_s *connptr)
return ret;
}
+static void handle_connection_failure(struct conn_s *connptr, int got_headers)
+{
+ /*
+ * First, get the body if there is one.
+ * If we don't read all there is from the socket first,
+ * it is still marked for reading and we won't be able
+ * to send our data properly.
+ */
+ if (!got_headers && get_request_entity (connptr) < 0) {
+ log_message (LOG_WARNING,
+ "Could not retrieve request entity");
+ indicate_http_error (connptr, 400, "Bad Request",
+ "detail",
+ "Could not retrieve the request entity "
+ "the client.", NULL);
+ update_stats (STAT_BADCONN);
+ }
+
+ if (connptr->error_variables) {
+ send_http_error_message (connptr);
+ } else if (connptr->show_stats) {
+ showstats (connptr);
+ }
+}
+
/*
* This is the main drive for each connection. As you can tell, for the
@@ -1543,15 +1509,21 @@ get_request_entity(struct conn_s *connptr)
* tinyproxy code, which was confusing, redundant. Hail progress.
* - rjkaes
*/
-void handle_connection (int fd, union sockaddr_union* addr)
+void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
{
- ssize_t i;
- struct conn_s *connptr;
+
+#define HC_FAIL() \
+ do {handle_connection_failure(connptr, got_headers); goto done;} \
+ while(0)
+
+ int got_headers = 0, fd = connptr->client_fd;
+ size_t i;
struct request_s *request = NULL;
struct timeval tv;
- hashmap_t hashofheaders = NULL;
+ orderedmap hashofheaders = NULL;
char sock_ipaddr[IP_LENGTH];
+ char sock_ipaddr_alt[IP_LENGTH]="";
char peer_ipaddr[IP_LENGTH];
getpeer_information (addr, peer_ipaddr, sizeof(peer_ipaddr));
@@ -1559,14 +1531,25 @@ void handle_connection (int fd, union sockaddr_union* addr)
if (config->bindsame)
getsock_ip (fd, sock_ipaddr);
+ switch (SOCKADDR_UNION_AF(addr)) {
+ case AF_INET:
+ if (config->bind_ipv4mapped)
+ getmapped_ipv6 (config->bind_ipv4mapped, sock_ipaddr, sock_ipaddr_alt);
+ break;
+ case AF_INET6:
+ if (config->bind_ipv6mapped)
+ getmapped_ipv4 (config->bind_ipv6mapped, sock_ipaddr, sock_ipaddr_alt);
+ break;
+ }
+
log_message (LOG_CONN, config->bindsame ?
"Connect (file descriptor %d): %s at [%s]" :
"Connect (file descriptor %d): %s",
fd, peer_ipaddr, sock_ipaddr);
- connptr = initialize_conn (fd, peer_ipaddr,
- config->bindsame ? sock_ipaddr : NULL);
- if (!connptr) {
+ if(!conn_init_contents (connptr, peer_ipaddr,
+ config->bindsame ? sock_ipaddr : NULL,
+ sock_ipaddr_alt[0] ? sock_ipaddr_alt : NULL)) {
close (fd);
return;
}
@@ -1588,7 +1571,7 @@ void handle_connection (int fd, union sockaddr_union* addr)
"You tried to connect to the "
"machine the proxy is running on",
NULL);
- goto fail;
+ HC_FAIL();
}
@@ -1599,7 +1582,7 @@ void handle_connection (int fd, union sockaddr_union* addr)
"The administrator of this proxy has not configured "
"it to service requests from your host.",
NULL);
- goto fail;
+ HC_FAIL();
}
if (read_request_line (connptr) < 0) {
@@ -1608,13 +1591,13 @@ void handle_connection (int fd, union sockaddr_union* addr)
"detail",
"Server timeout waiting for the HTTP request "
"from the client.", NULL);
- goto fail;
+ HC_FAIL();
}
/*
* The "hashofheaders" store the client's headers.
*/
- hashofheaders = hashmap_create (HEADER_BUCKETS);
+ hashofheaders = orderedmap_create (HEADER_BUCKETS);
if (hashofheaders == NULL) {
update_stats (STAT_BADCONN);
indicate_http_error (connptr, 503, "Internal error",
@@ -1622,7 +1605,7 @@ void handle_connection (int fd, union sockaddr_union* addr)
"An internal server error occurred while processing "
"your request. Please contact the administrator.",
NULL);
- goto fail;
+ HC_FAIL();
}
/*
@@ -1636,34 +1619,31 @@ void handle_connection (int fd, union sockaddr_union* addr)
"Could not retrieve all the headers from "
"the client.", NULL);
update_stats (STAT_BADCONN);
- goto fail;
+ HC_FAIL();
}
+ got_headers = 1;
if (config->basicauth_list != NULL) {
- ssize_t len;
char *authstring;
int failure = 1, stathost_connect = 0;
- len = hashmap_entry_by_key (hashofheaders, "proxy-authorization",
- (void **) &authstring);
-
- if (len == 0 && config->stathost) {
- len = hashmap_entry_by_key (hashofheaders, "host",
- (void **) &authstring);
- if (len && !strncmp(authstring, config->stathost, strlen(config->stathost))) {
- len = hashmap_entry_by_key (hashofheaders, "authorization",
- (void **) &authstring);
+ authstring = orderedmap_find (hashofheaders, "proxy-authorization");
+
+ if (!authstring && config->stathost) {
+ authstring = orderedmap_find (hashofheaders, "host");
+ if (authstring && !strncmp(authstring, config->stathost, strlen(config->stathost))) {
+ authstring = orderedmap_find (hashofheaders, "authorization");
stathost_connect = 1;
- } else len = 0;
+ } else authstring = 0;
}
- if (len == 0) {
+ if (!authstring) {
if (stathost_connect) goto e401;
update_stats (STAT_DENIED);
indicate_http_error (connptr, 407, "Proxy Authentication Required",
"detail",
"This proxy requires authentication.",
NULL);
- goto fail;
+ HC_FAIL();
}
if ( /* currently only "basic" auth supported */
(strncmp(authstring, "Basic ", 6) == 0 ||
@@ -1678,22 +1658,20 @@ e401:
"The administrator of this proxy has not configured "
"it to service requests from you.",
NULL);
- goto fail;
+ HC_FAIL();
}
- hashmap_remove (hashofheaders, "proxy-authorization");
+ orderedmap_remove (hashofheaders, "proxy-authorization");
}
/*
* Add any user-specified headers (AddHeader directive) to the
* outgoing HTTP request.
*/
- for (i = 0; i < vector_length (config->add_headers); i++) {
- http_header_t *header = (http_header_t *)
- vector_getentry (config->add_headers, i, NULL);
+ if (config->add_headers)
+ for (i = 0; i < sblist_getsize (config->add_headers); i++) {
+ http_header_t *header = sblist_get (config->add_headers, i);
- hashmap_insert (hashofheaders,
- header->name,
- header->value, strlen (header->value) + 1);
+ orderedmap_append (hashofheaders, header->name, header->value);
}
request = process_request (connptr, hashofheaders);
@@ -1701,24 +1679,25 @@ e401:
if (!connptr->show_stats) {
update_stats (STAT_BADCONN);
}
- goto fail;
+ HC_FAIL();
}
connptr->upstream_proxy = UPSTREAM_HOST (request->host);
if (connptr->upstream_proxy != NULL) {
if (connect_to_upstream (connptr, request) < 0) {
- goto fail;
+ HC_FAIL();
}
} else {
connptr->server_fd = opensock (request->host, request->port,
- connptr->server_ip_addr);
+ connptr->server_ip_addr,
+ connptr->server_ip_addr_alt);
if (connptr->server_fd < 0) {
indicate_http_error (connptr, 500, "Unable to connect",
"detail",
PACKAGE_NAME " "
"was unable to connect to the remote web server.",
"error", strerror (errno), NULL);
- goto fail;
+ HC_FAIL();
}
log_message (LOG_CONN,
@@ -1732,13 +1711,25 @@ e401:
if (process_client_headers (connptr, hashofheaders) < 0) {
update_stats (STAT_BADCONN);
- goto fail;
+ log_message (LOG_INFO,
+ "process_client_headers failed: %s. host \"%s\" using "
+ "file descriptor %d.", strerror(errno),
+ request->host,
+ connptr->server_fd);
+
+ HC_FAIL();
}
if (!connptr->connect_method || UPSTREAM_IS_HTTP(connptr)) {
if (process_server_headers (connptr) < 0) {
update_stats (STAT_BADCONN);
- goto fail;
+ log_message (LOG_INFO,
+ "process_server_headers failed: %s. host \"%s\" using "
+ "file descriptor %d.", strerror(errno),
+ request->host,
+ connptr->server_fd);
+
+ HC_FAIL();
}
} else {
if (send_ssl_response (connptr) < 0) {
@@ -1746,7 +1737,7 @@ e401:
"handle_connection: Could not send SSL greeting "
"to client.");
update_stats (STAT_BADCONN);
- goto fail;
+ HC_FAIL();
}
}
@@ -1757,34 +1748,10 @@ e401:
"and remote client (fd:%d)",
connptr->client_fd, connptr->server_fd);
- goto done;
-
-fail:
- /*
- * First, get the body if there is one.
- * If we don't read all there is from the socket first,
- * it is still marked for reading and we won't be able
- * to send our data properly.
- */
- if (get_request_entity (connptr) < 0) {
- log_message (LOG_WARNING,
- "Could not retrieve request entity");
- indicate_http_error (connptr, 400, "Bad Request",
- "detail",
- "Could not retrieve the request entity "
- "the client.", NULL);
- update_stats (STAT_BADCONN);
- }
-
- if (connptr->error_variables) {
- send_http_error_message (connptr);
- } else if (connptr->show_stats) {
- showstats (connptr);
- }
-
done:
free_request_struct (request);
- hashmap_delete (hashofheaders);
- destroy_conn (connptr);
+ orderedmap_destroy (hashofheaders);
+ conn_destroy_contents (connptr);
return;
+#undef HC_FAIL
}