summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/reqs.c198
1 files changed, 118 insertions, 80 deletions
diff --git a/src/reqs.c b/src/reqs.c
index ad693fb..59e1c94 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -1,4 +1,4 @@
-/* $Id: reqs.c,v 1.45 2001-12-18 05:01:03 rjkaes Exp $
+/* $Id: reqs.c,v 1.46 2001-12-19 05:13:40 rjkaes Exp $
*
* This is where all the work in tinyproxy is actually done. Incoming
* connections have a new thread created for them. The thread then
@@ -44,7 +44,7 @@
/*
* Maximum length of a HTTP line
*/
-#define HTTP_LINE_LENGTH (1024 * 16)
+#define HTTP_LINE_LENGTH (MAXBUFFSIZE / 6)
/*
* Macro to help test if the Upstream proxy supported is compiled in and
@@ -57,6 +57,15 @@
#endif
/*
+ * Macro to help test if tunnel support is compiled in, and is enabled.
+ */
+#ifdef TUNNEL_SUPPORT
+# define TUNNEL_CONFIGURED() (config.tunnel_name && config.tunnel_port != -1)
+#else
+# define TUNNEL_CONFIGURED() (0)
+#endif
+
+/*
* Read in the first line from the client (the request line for HTTP
* connections. The request line is allocated from the heap, but it must
* be freed in another function.
@@ -186,43 +195,77 @@ extract_ssl_url(const char *url, struct request_s *request)
}
/*
- * Create a connection for HTTP connections.
+ * Send a "message" to the file descriptor provided. This handles the
+ * differences between the various implementations of vsnprintf. This code
+ * was basically stolen from the snprintf() man page of Debian Linux
+ * (although I did fix a memory leak. :)
*/
static int
-establish_http_connection(struct conn_s *connptr, struct request_s *request)
+write_message(int fd, const char *fmt, ...)
{
- char *buffer;
+ size_t n;
+ size_t size = (1024 * 8); /* start with 8 KB and go from there */
+ char *buf, *tmpbuf;
+ va_list ap;
- buffer = safemalloc(HTTP_LINE_LENGTH);
- if (!buffer)
+ if ((buf = safemalloc(size)) == NULL)
return -1;
- if (snprintf(buffer, HTTP_LINE_LENGTH, "%s %s HTTP/1.0\r\n", request->method, request->path) < 0)
- goto error;
- if (safe_write(connptr->server_fd, buffer, strlen(buffer)) < 0)
- goto error;
+ while (1) {
+ va_start(ap, fmt);
+ n = vsnprintf(buf, size, fmt, ap);
+ va_end(ap);
- /*
- * Send headers
- */
- if (snprintf(buffer, HTTP_LINE_LENGTH, "Host: %s\r\n", request->host) < 0)
- goto error;
- if (safe_write(connptr->server_fd, buffer, strlen(buffer)) < 0)
- goto error;
+ /* If that worked, break out so we can send the buffer */
+ if (n > -1 && n < size)
+ break;
+
+ /* Else, try again with more space */
+ if (n > -1)
+ /* precisely what is needed (glibc2.1) */
+ size = n + 1;
+ else
+ /* twice the old size (glibc2.0) */
+ size *= 2;
+
+ if ((tmpbuf = saferealloc(buf, size)) == NULL) {
+ safefree(buf);
+ return -1;
+ } else
+ buf = tmpbuf;
+ }
+
+ if (safe_write(fd, buf, n) < 0) {
+ safefree(buf);
+ return -1;
+ }
+
+ safefree(buf);
+ return 0;
+}
+
+/*
+ * Create a connection for HTTP connections.
+ */
+static int
+establish_http_connection(struct conn_s *connptr, struct request_s *request)
+{
+ if (write_message(connptr->server_fd,
+ "%s %s HTTP/1.0\r\n",
+ request->method, request->path) < 0)
+ return -1;
+
+ if (write_message(connptr->server_fd, "Host: %s\r\n", request->host) < 0)
+ return -1;
/*
* Send the Connection header since we don't support persistant
* connections.
*/
if (safe_write(connptr->server_fd, "Connection: close\r\n", 19) < 0)
- goto error;
+ return -1;
- safefree(buffer);
return 0;
-
- error:
- safefree(buffer);
- return -1;
}
/*
@@ -476,8 +519,6 @@ static int
add_xtinyproxy_header(struct conn_s *connptr)
{
char ipaddr[PEER_IP_LENGTH];
- char xtinyproxy[32];
- int length;
/*
* Don't try to send if we have an invalid server handle.
@@ -485,13 +526,9 @@ add_xtinyproxy_header(struct conn_s *connptr)
if (connptr->server_fd == -1)
return 0;
- length = snprintf(xtinyproxy, sizeof(xtinyproxy),
- "X-Tinyproxy: %s\r\n",
- getpeer_ip(connptr->client_fd, ipaddr));
- if (safe_write(connptr->server_fd, xtinyproxy, length) < 0)
- return -1;
-
- return 0;
+ return write_message(connptr->server_fd,
+ "X-Tinyproxy: %s\r\n",
+ getpeer_ip(connptr->client_fd, ipaddr));
}
#endif /* XTINYPROXY */
@@ -855,6 +892,50 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request)
}
#endif
+#ifdef TUNNEL_SUPPORT
+/*
+ * If tunnel has been configured then redirect any connections to it.
+ */
+static int
+connect_to_tunnel(struct conn_s *connptr)
+{
+ char *request_buf;
+ size_t len;
+ int pos;
+
+ request_buf = safemalloc(HTTP_LINE_LENGTH);
+ if (request_buf) {
+ len = recv(connptr->client_fd, request_buf, HTTP_LINE_LENGTH - 1, MSG_PEEK);
+ for (pos = 0; pos < len && request_buf[pos] != '\n'; pos++)
+ ;
+ request_buf[pos] = '\0';
+
+ log_message(LOG_CONN, "Request: %s", request_buf);
+
+ safefree(request_buf);
+ }
+ log_message(LOG_INFO, "Redirecting to %s:%d",
+ config.tunnel_name, config.tunnel_port);
+
+ connptr->server_fd =
+ opensock(config.tunnel_name, config.tunnel_port);
+
+ if (connptr->server_fd < 0) {
+ log_message(LOG_WARNING,
+ "Could not connect to tunnel.");
+ httperr(connptr, 404, "Unable to connect to tunnel.");
+
+ return -1;
+ }
+
+ log_message(LOG_INFO,
+ "Established a connection to the tunnel \"%s\" using file descriptor %d.",
+ config.tunnel_name, connptr->server_fd);
+
+ return 0;
+}
+#endif
+
/*
* This is the main drive for each connection. As you can tell, for the
* first few steps we are using a blocking socket. If you remember the
@@ -894,55 +975,12 @@ handle_connection(int fd)
goto send_error;
}
-#ifdef TUNNEL_SUPPORT
- /*
- * If tunnel has been configured then redirect any connections to
- * it. I know I used GOTOs, but it seems to me to be the best way
- * of handling this situations. So sue me. :)
- * - rjkaes
- */
- if (config.tunnel_name && config.tunnel_port != -1) {
- char *request_buf;
- size_t len;
- int pos;
-
- request_buf = safemalloc(HTTP_LINE_LENGTH);
- if (request_buf) {
- len = recv(connptr->client_fd, request_buf, HTTP_LINE_LENGTH - 1, MSG_PEEK);
- for (pos = 0; pos < len && request_buf[pos] != '\n'; pos++)
- ;
- request_buf[pos] = '\0';
-
- log_message(LOG_CONN, "Request: %s", request_buf);
-
- safefree(request_buf);
- }
- log_message(LOG_INFO, "Redirecting to %s:%d",
- config.tunnel_name, config.tunnel_port);
-
- connptr->server_fd =
- opensock(config.tunnel_name, config.tunnel_port);
-
- if (connptr->server_fd < 0) {
- log_message(LOG_WARNING,
- "Could not connect to tunnel.");
- httperr(connptr, 404, "Unable to connect to tunnel.");
-
+ if (TUNNEL_CONFIGURED()) {
+ if (connect_to_tunnel(connptr) < 0)
goto internal_proxy;
- }
-
- log_message(LOG_INFO,
- "Established a connection to the tunnel \"%s\" using file descriptor %d.",
- config.tunnel_name, connptr->server_fd);
-
- /*
- * I know GOTOs are evil, but duplicating the code is even
- * more evil.
- * - rjkaes
- */
- goto relay_proxy;
+ else
+ goto relay_proxy;
}
-#endif /* TUNNEL_SUPPORT */
internal_proxy:
request_line = read_request_line(connptr);