summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/conns.c15
-rw-r--r--src/conns.h9
-rw-r--r--src/reqs.c37
3 files changed, 54 insertions, 7 deletions
diff --git a/src/conns.c b/src/conns.c
index feac522..ca8f24e 100644
--- a/src/conns.c
+++ b/src/conns.c
@@ -58,6 +58,21 @@ int conn_init_contents (struct conn_s *connptr, const char *ipaddr,
connptr->cbuffer = cbuffer;
connptr->sbuffer = sbuffer;
+ connptr->request_line = NULL;
+
+ /* These store any error strings */
+ connptr->error_variables = NULL;
+ connptr->error_string = NULL;
+ connptr->error_number = -1;
+
+ connptr->connect_method = CM_FALSE;
+ connptr->show_stats = FALSE;
+
+ connptr->protocol.major = connptr->protocol.minor = 0;
+
+ /* There is _no_ content length initially */
+ connptr->content_length.server = connptr->content_length.client = -1;
+
connptr->server_ip_addr = (sock_ipaddr ?
safestrdup (sock_ipaddr) : NULL);
connptr->server_ip_addr_alt = (sock_ipaddr_alt ?
diff --git a/src/conns.h b/src/conns.h
index 36082f2..7e1919c 100644
--- a/src/conns.h
+++ b/src/conns.h
@@ -24,6 +24,12 @@
#include "main.h"
#include "hsearch.h"
+enum connect_method_e {
+ CM_FALSE = 0,
+ CM_TRUE = 1,
+ CM_UPGRADE = 2,
+};
+
/*
* Connection Definition
*/
@@ -37,8 +43,9 @@ struct conn_s {
/* The request line (first line) from the client */
char *request_line;
+ enum connect_method_e connect_method;
+
/* Booleans */
- unsigned int connect_method;
unsigned int show_stats;
/*
diff --git a/src/reqs.c b/src/reqs.c
index f6fd2be..cf87a9b 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -90,7 +90,7 @@
* connections. The request line is allocated from the heap, but it must
* be freed in another function.
*/
-static int read_request_line (struct conn_s *connptr)
+static int read_request_line (struct conn_s *connptr, char** lines, size_t* lines_len)
{
ssize_t len;
@@ -104,6 +104,12 @@ retry:
return -1;
}
+ *lines = saferealloc(*lines, *lines_len + len + 1);
+ if(*lines) {
+ strcpy(*lines + *lines_len, connptr->request_line);
+ *lines_len += len;
+ }
+
/*
* Strip the new line and carriage return from the string.
*/
@@ -441,7 +447,7 @@ BAD_REQUEST_ERROR:
goto fail;
}
- connptr->connect_method = TRUE;
+ connptr->connect_method = CM_TRUE;
} else {
#ifdef TRANSPARENT_PROXY
if (!do_transparent_proxy
@@ -635,7 +641,7 @@ add_header_to_connection (orderedmap hashofheaders, char *header, size_t len)
/*
* Read all the headers from the stream
*/
-static int get_all_headers (int fd, orderedmap hashofheaders)
+static int get_all_headers (int fd, hashmap_t hashofheaders, char** lines, size_t* lines_len)
{
char *line = NULL;
char *header = NULL;
@@ -655,6 +661,14 @@ static int get_all_headers (int fd, orderedmap hashofheaders)
return -1;
}
+ if(lines) {
+ *lines = saferealloc(*lines, *lines_len + linelen + 1);
+ if(*lines) {
+ strcpy(*lines + *lines_len, line);
+ *lines_len += linelen;
+ }
+ }
+
/*
* If we received a CR LF or a non-continuation line, then add
* the accumulated header field, if any, to the hashmap, and
@@ -1013,7 +1027,7 @@ retry:
/*
* Get all the headers from the remote server in a big hash
*/
- if (get_all_headers (connptr->server_fd, hashofheaders) < 0) {
+ if (get_all_headers (connptr->server_fd, hashofheaders, NULL, NULL) < 0) {
log_message (LOG_WARNING,
"Could not retrieve all the headers from the remote server.");
orderedmap_destroy (hashofheaders);
@@ -1525,6 +1539,9 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
char sock_ipaddr[IP_LENGTH];
char sock_ipaddr_alt[IP_LENGTH]="";
char peer_ipaddr[IP_LENGTH];
+ char peer_string[HOSTNAME_LENGTH];
+ char *lines = NULL;
+ size_t lines_len = 0;
getpeer_information (addr, peer_ipaddr, sizeof(peer_ipaddr));
@@ -1585,7 +1602,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
HC_FAIL();
}
- if (read_request_line (connptr) < 0) {
+ if (read_request_line (connptr, &lines, &lines_len) < 0) {
update_stats (STAT_BADCONN);
indicate_http_error (connptr, 408, "Timeout",
"detail",
@@ -1611,7 +1628,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
/*
* Get all the headers from the client in a big hash.
*/
- if (get_all_headers (connptr->client_fd, hashofheaders) < 0) {
+ if (get_all_headers (connptr->client_fd, hashofheaders, &lines, &lines_len) < 0) {
log_message (LOG_WARNING,
"Could not retrieve all the headers from the client");
indicate_http_error (connptr, 400, "Bad Request",
@@ -1705,6 +1722,11 @@ e401:
"file descriptor %d.", request->host,
connptr->server_fd);
+ if(hashmap_search(hashofheaders, "upgrade") > 0) {
+ connptr->connect_method = CM_UPGRADE;
+ safe_write (connptr->server_fd, lines, lines_len);
+ }
+
if (!connptr->connect_method)
establish_http_connection (connptr, request);
}
@@ -1731,6 +1753,8 @@ e401:
HC_FAIL();
}
+ } else if (connptr->connect_method == CM_UPGRADE) {
+ /* NOP */ ;
} else {
if (send_ssl_response (connptr) < 0) {
log_message (LOG_ERR,
@@ -1749,6 +1773,7 @@ e401:
connptr->client_fd, connptr->server_fd);
done:
+ safefree(lines);
free_request_struct (request);
orderedmap_destroy (hashofheaders);
conn_destroy_contents (connptr);