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
	 Robert James Kaes
						Robert James Kaes