Redefined HTTP_LINE_LENGTH to be based on MAXBUFFSIZE (and set to around
16 KB.) Added the TUNNEL_CONFIGURED() macro to help with testing for the tunnel support code. Create the write_message() function to encapsulate the code which sends the information to the file descriptor. Moved the tunnel code into it's own function.
This commit is contained in:
parent
4a257edd0a
commit
56b541d76b
194
src/reqs.c
194
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
|
* This is where all the work in tinyproxy is actually done. Incoming
|
||||||
* connections have a new thread created for them. The thread then
|
* connections have a new thread created for them. The thread then
|
||||||
@ -44,7 +44,7 @@
|
|||||||
/*
|
/*
|
||||||
* Maximum length of a HTTP line
|
* 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
|
* Macro to help test if the Upstream proxy supported is compiled in and
|
||||||
@ -56,6 +56,15 @@
|
|||||||
# define UPSTREAM_CONFIGURED() (0)
|
# define UPSTREAM_CONFIGURED() (0)
|
||||||
#endif
|
#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
|
* 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
|
* connections. The request line is allocated from the heap, but it must
|
||||||
@ -185,44 +194,78 @@ extract_ssl_url(const char *url, struct request_s *request)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
write_message(int fd, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
size_t size = (1024 * 8); /* start with 8 KB and go from there */
|
||||||
|
char *buf, *tmpbuf;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if ((buf = safemalloc(size)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
va_start(ap, fmt);
|
||||||
|
n = vsnprintf(buf, size, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
/* 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.
|
* Create a connection for HTTP connections.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
establish_http_connection(struct conn_s *connptr, struct request_s *request)
|
establish_http_connection(struct conn_s *connptr, struct request_s *request)
|
||||||
{
|
{
|
||||||
char *buffer;
|
if (write_message(connptr->server_fd,
|
||||||
|
"%s %s HTTP/1.0\r\n",
|
||||||
buffer = safemalloc(HTTP_LINE_LENGTH);
|
request->method, request->path) < 0)
|
||||||
if (!buffer)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (snprintf(buffer, HTTP_LINE_LENGTH, "%s %s HTTP/1.0\r\n", request->method, request->path) < 0)
|
if (write_message(connptr->server_fd, "Host: %s\r\n", request->host) < 0)
|
||||||
goto error;
|
return -1;
|
||||||
if (safe_write(connptr->server_fd, buffer, strlen(buffer)) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send the Connection header since we don't support persistant
|
* Send the Connection header since we don't support persistant
|
||||||
* connections.
|
* connections.
|
||||||
*/
|
*/
|
||||||
if (safe_write(connptr->server_fd, "Connection: close\r\n", 19) < 0)
|
if (safe_write(connptr->server_fd, "Connection: close\r\n", 19) < 0)
|
||||||
goto error;
|
|
||||||
|
|
||||||
safefree(buffer);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
safefree(buffer);
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -476,8 +519,6 @@ static int
|
|||||||
add_xtinyproxy_header(struct conn_s *connptr)
|
add_xtinyproxy_header(struct conn_s *connptr)
|
||||||
{
|
{
|
||||||
char ipaddr[PEER_IP_LENGTH];
|
char ipaddr[PEER_IP_LENGTH];
|
||||||
char xtinyproxy[32];
|
|
||||||
int length;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't try to send if we have an invalid server handle.
|
* 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)
|
if (connptr->server_fd == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
length = snprintf(xtinyproxy, sizeof(xtinyproxy),
|
return write_message(connptr->server_fd,
|
||||||
"X-Tinyproxy: %s\r\n",
|
"X-Tinyproxy: %s\r\n",
|
||||||
getpeer_ip(connptr->client_fd, ipaddr));
|
getpeer_ip(connptr->client_fd, ipaddr));
|
||||||
if (safe_write(connptr->server_fd, xtinyproxy, length) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif /* XTINYPROXY */
|
#endif /* XTINYPROXY */
|
||||||
|
|
||||||
@ -855,6 +892,50 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
* 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
|
* first few steps we are using a blocking socket. If you remember the
|
||||||
@ -894,55 +975,12 @@ handle_connection(int fd)
|
|||||||
goto send_error;
|
goto send_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TUNNEL_SUPPORT
|
if (TUNNEL_CONFIGURED()) {
|
||||||
/*
|
if (connect_to_tunnel(connptr) < 0)
|
||||||
* 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.");
|
|
||||||
|
|
||||||
goto internal_proxy;
|
goto internal_proxy;
|
||||||
}
|
else
|
||||||
|
|
||||||
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;
|
goto relay_proxy;
|
||||||
}
|
}
|
||||||
#endif /* TUNNEL_SUPPORT */
|
|
||||||
|
|
||||||
internal_proxy:
|
internal_proxy:
|
||||||
request_line = read_request_line(connptr);
|
request_line = read_request_line(connptr);
|
||||||
|
Loading…
Reference in New Issue
Block a user