1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-07 04:02:58 +03:00

This is the 1.3.x current proxy into 2.0 - first stage

PR:
Obtained from: Sam Magnuson
Submitted by:  Chuck Murcko
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86923 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chuck Murcko
2000-11-11 11:07:03 +00:00
parent adebe63463
commit 31c42a957c
3 changed files with 637 additions and 587 deletions

View File

@@ -58,7 +58,6 @@
/* CONNECT method for Apache proxy */ /* CONNECT method for Apache proxy */
#include "apr_strings.h"
#include "mod_proxy.h" #include "mod_proxy.h"
#include "http_log.h" #include "http_log.h"
#include "http_main.h" #include "http_main.h"
@@ -123,7 +122,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
int nbytes, i; int nbytes, i;
BUFF *sock_buff; BUFF *sock_buff;
apr_socket_t *client_sock=NULL; apr_socket_t *client_sock = NULL;
apr_pollfd_t *pollfd; apr_pollfd_t *pollfd;
apr_int32_t pollcnt; apr_int32_t pollcnt;
apr_int16_t pollevent; apr_int16_t pollevent;
@@ -144,7 +143,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
} }
/* check if ProxyBlock directive on this host */ /* check if ProxyBlock directive on this host */
destaddr.s_addr = apr_inet_addr(host); destaddr.s_addr = ap_inet_addr(host);
for (i = 0; i < conf->noproxies->nelts; i++) { for (i = 0; i < conf->noproxies->nelts; i++) {
if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL) if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL)
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
@@ -180,7 +179,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
if (ap_proxy_doconnect(sock, (char *)(proxyhost ? proxyhost : host), proxyport ? proxyport : port, r) == -1) { if (ap_proxy_doconnect(sock, (char *)(proxyhost ? proxyhost : host),
proxyport ? proxyport : port, r) == -1) {
apr_close_socket(sock); apr_close_socket(sock);
return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
apr_pstrcat(r->pool, "Could not connect to remote machine:<br>", apr_pstrcat(r->pool, "Could not connect to remote machine:<br>",
@@ -197,9 +197,11 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
*/ */
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
"Sending the CONNECT request to the remote proxy"); "Sending the CONNECT request to the remote proxy");
nbytes = apr_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, r->uri); nbytes = apr_snprintf(buffer, sizeof(buffer),
"CONNECT %s HTTP/1.0" CRLF, r->uri);
apr_send(sock, buffer, &nbytes); apr_send(sock, buffer, &nbytes);
nbytes = apr_snprintf(buffer, sizeof(buffer),"Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); nbytes = apr_snprintf(buffer, sizeof(buffer),
"Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
apr_send(sock, buffer, &nbytes); apr_send(sock, buffer, &nbytes);
} }
else { else {
@@ -215,7 +217,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
if(apr_setup_poll(&pollfd, 2, r->pool) != APR_SUCCESS) if(apr_setup_poll(&pollfd, 2, r->pool) != APR_SUCCESS)
{ {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error apr_setup_poll()"); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: error apr_setup_poll()");
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
@@ -226,16 +229,17 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
just see if a recv gives us anything and do the same to sock (server) side, I'll leave this as TBD so just see if a recv gives us anything and do the same to sock (server) side, I'll leave this as TBD so
one can decide the best path to take one can decide the best path to take
*/ */
if(apr_put_os_sock(&client_sock, (apr_os_sock_t *)get_socket(r->connection->client), if(apr_put_os_sock(&client_sock,
(apr_os_sock_t *)get_socket(r->connection->client),
r->pool) != APR_SUCCESS) r->pool) != APR_SUCCESS)
{ {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error creating client apr_socket_t"); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: error creating client apr_socket_t");
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
apr_add_poll_socket(pollfd, client_sock, APR_POLLIN); apr_add_poll_socket(pollfd, client_sock, APR_POLLIN);
#endif #endif
/* Add the server side to the poll */ /* Add the server side to the poll */
apr_add_poll_socket(pollfd, sock, APR_POLLIN); apr_add_poll_socket(pollfd, sock, APR_POLLIN);
@@ -262,8 +266,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
o += i; o += i;
nbytes -= i; nbytes -= i;
} }
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "Wrote %d bytes to client", nbytes);
"Wrote %d bytes to client", nbytes);
} }
else else
break; break;
@@ -273,7 +276,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
if (pollevent & APR_POLLIN) { if (pollevent & APR_POLLIN) {
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
"client was set"); "client was set");
if(ap_bread(r->connection->client, buffer, HUGE_STRING_LEN, &nbytes) == APR_SUCCESS) { if(ap_bread(r->connection->client, buffer, HUGE_STRING_LEN,
&nbytes) == APR_SUCCESS) {
int o = 0; int o = 0;
while(nbytes) while(nbytes)
{ {
@@ -281,8 +285,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
o += i; o += i;
nbytes -= i; nbytes -= i;
} }
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
"Wrote %d bytes to server", nbytes); NULL, "Wrote %d bytes to server", nbytes);
} }
else else
break; break;

View File

@@ -58,7 +58,6 @@
/* HTTP routines for Apache proxy */ /* HTTP routines for Apache proxy */
#include "apr_strings.h"
#include "mod_proxy.h" #include "mod_proxy.h"
#include "http_log.h" #include "http_log.h"
#include "http_main.h" #include "http_main.h"
@@ -135,7 +134,7 @@ static const char *proxy_location_reverse_map(request_rec *r, const char *url)
return url; return url;
} }
/* Clear all connection-based headers from the incoming headers apr_table_t */ /* Clear all connection-based headers from the incoming headers table */
static void clear_connection(apr_pool_t *p, apr_table_t *headers) static void clear_connection(apr_pool_t *p, apr_table_t *headers)
{ {
const char *name; const char *name;
@@ -174,23 +173,23 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
char *strp2; char *strp2;
char *desthost; char *desthost;
apr_socket_t *sock; apr_socket_t *sock;
int i, len, backasswards, content_length=-1; int i, len, backasswards, content_length = -1;
apr_array_header_t *reqhdrs_arr; apr_array_header_t *reqhdrs_arr;
apr_table_t *resp_hdrs=NULL; apr_table_t *resp_hdrs = NULL;
apr_table_entry_t *reqhdrs; apr_table_entry_t *reqhdrs;
struct sockaddr_in server; struct sockaddr_in server;
struct in_addr destaddr; struct in_addr destaddr;
BUFF *f; BUFF *f;
apr_file_t *cachefp=NULL;
char buffer[HUGE_STRING_LEN]; char buffer[HUGE_STRING_LEN];
char portstr[32]; char portstr[32];
apr_pool_t *p = r->pool; apr_pool_t *p = r->pool;
const long int zero = 0L; const long int zero = 0L;
int destport = 0; int destport = 0;
apr_ssize_t cntr;
char *destportstr = NULL; char *destportstr = NULL;
const char *urlptr = NULL; const char *urlptr = NULL;
char *datestr, *clen; char *datestr, *clen;
apr_ssize_t cntr;
apr_file_t *cachefp = NULL;
void *sconf = r->server->module_config; void *sconf = r->server->module_config;
proxy_server_conf *conf = proxy_server_conf *conf =
@@ -234,8 +233,10 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
/* check if ProxyBlock directive on this host */ /* check if ProxyBlock directive on this host */
destaddr.s_addr = apr_inet_addr(desthost); destaddr.s_addr = apr_inet_addr(desthost);
for (i = 0; i < conf->noproxies->nelts; i++) { for (i = 0; i < conf->noproxies->nelts; i++) {
if ((npent[i].name != NULL && ap_strstr_c(desthost, npent[i].name) != NULL) if ((npent[i].name != NULL
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') && ap_strstr_c(desthost, npent[i].name) != NULL)
|| destaddr.s_addr == npent[i].addr.s_addr
|| npent[i].name[0] == '*')
return ap_proxyerror(r, HTTP_FORBIDDEN, return ap_proxyerror(r, HTTP_FORBIDDEN,
"Connect to remote machine blocked"); "Connect to remote machine blocked");
} }
@@ -246,10 +247,13 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,conf->recv_buffer_size)) { #if !defined(TPF) && !defined(BEOS)
if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,
conf->recv_buffer_size)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
} }
#endif
if (proxyhost != NULL) { if (proxyhost != NULL) {
i = ap_proxy_doconnect(sock, (char *)proxyhost, proxyport, r); i = ap_proxy_doconnect(sock, (char *)proxyhost, proxyport, r);
@@ -262,8 +266,8 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
if (proxyhost != NULL) if (proxyhost != NULL)
return DECLINED; /* try again another way */ return DECLINED; /* try again another way */
else else
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool,
apr_pstrcat(r->pool, "Could not connect to remote machine: ", "Could not connect to remote machine: ",
strerror(errno), NULL)); strerror(errno), NULL));
} }
@@ -291,7 +295,7 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
apr_snprintf(portstr, sizeof portstr, ":%d", i); apr_snprintf(portstr, sizeof portstr, ":%d", i);
} }
/* Generate outgoing Via: header with/without server comment: */ /* Generate outgoing Via: header with/without server comment: */
apr_table_mergen(r->headers_in, "Via", ap_table_mergen(r->headers_in, "Via",
(conf->viaopt == via_full) (conf->viaopt == via_full)
? apr_psprintf(p, "%d.%d %s%s (%s)", ? apr_psprintf(p, "%d.%d %s%s (%s)",
HTTP_VERSION_MAJOR(r->proto_num), HTTP_VERSION_MAJOR(r->proto_num),
@@ -367,6 +371,7 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
/* read the headers. */ /* read the headers. */
/* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
/* Also, take care with headers with multiple occurences. */ /* Also, take care with headers with multiple occurences. */
resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f); resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
if (resp_hdrs == NULL) { if (resp_hdrs == NULL) {
ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server, ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
@@ -391,8 +396,8 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
ap_cache_el_header_add(c, "Via", (conf->viaopt == via_full) ap_cache_el_header_add(c, "Via", (conf->viaopt == via_full)
? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor, ? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor,
ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION) ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION)
: apr_psprintf(p, "%d.%d %s%s", major, minor, ap_get_server_name(r), portstr) : apr_psprintf(p, "%d.%d %s%s", major, minor,
); ap_get_server_name(r), portstr));
} }
} }
else { else {
@@ -436,7 +441,8 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
/* write status line */ /* write status line */
if (!r->assbackwards) if (!r->assbackwards)
ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) { if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ",
r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: error writing status line to cache"); "proxy: error writing status line to cache");
ap_proxy_cache_error(&c); ap_proxy_cache_error(&c);
@@ -451,14 +457,13 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
ap_bsetopt(r->connection->client, BO_BYTECT, &zero); ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
r->sent_bodyct = 1; r->sent_bodyct = 1;
/* Is it an HTTP/0.9 respose? If so, send the extra data */ /* Is it an HTTP/0.9 response? If so, send the extra data */
if (backasswards) { if (backasswards) {
ap_bwrite(r->connection->client, buffer, len, &cntr); ap_bwrite(r->connection->client, buffer, len, &cntr);
cntr = len; cntr = len;
if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) { if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: error writing extra data to cache %ld", "proxy: error writing extra data to cache");
(long)cachefp);
ap_proxy_cache_error(&c); ap_proxy_cache_error(&c);
} }
} }

View File

@@ -57,21 +57,18 @@
*/ */
/* Utility routines for Apache proxy */ /* Utility routines for Apache proxy */
#include "apr_strings.h"
#include "mod_proxy.h" #include "mod_proxy.h"
#include "http_main.h" #include "http_main.h"
#include "apr_md5.h"
#include "http_log.h" #include "http_log.h"
#include "util_uri.h" #include "util_uri.h"
#include "util_date.h" /* get ap_checkmask() decl. */ #include "util_date.h" /* get ap_checkmask() decl. */
#include "apr_md5.h"
#include <pthread.h>
static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r); static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r); static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
static int proxy_match_word(struct dirconn_entry *This, request_rec *r); static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
static struct per_thread_data *get_per_thread_data(void);
/* already called in the knowledge that the characters are hex digits */ /* already called in the knowledge that the characters are hex digits */
int ap_proxy_hex2c(const char *x) int ap_proxy_hex2c(const char *x)
{ {
@@ -137,8 +134,8 @@ void ap_proxy_c2hex(int ch, char *x)
* and encodes those which must be encoded, and does not touch * and encodes those which must be encoded, and does not touch
* those which must not be touched. * those which must not be touched.
*/ */
char * char *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t, int isenc) int isenc)
{ {
int i, j, ch; int i, j, ch;
char *y; char *y;
@@ -181,7 +178,7 @@ char *
} }
/* decode it if not already done */ /* decode it if not already done */
if (isenc && ch == '%') { if (isenc && ch == '%') {
if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2])) if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
return NULL; return NULL;
ch = ap_proxy_hex2c(&x[i + 1]); ch = ap_proxy_hex2c(&x[i + 1]);
i += 2; i += 2;
@@ -275,7 +272,7 @@ char *
return "Port number in URL > 65535"; return "Port number in URL > 65535";
} }
} }
ap_str_tolower(host); /* DNS names are case insensitive */ ap_str_tolower(host); /* DNS names are case-insensitive */
if (*host == '\0') if (*host == '\0')
return "Missing host in URL"; return "Missing host in URL";
/* check hostname syntax */ /* check hostname syntax */
@@ -283,10 +280,10 @@ char *
if (!apr_isdigit(host[i]) && host[i] != '.') if (!apr_isdigit(host[i]) && host[i] != '.')
break; break;
/* must be an IP address */ /* must be an IP address */
#ifdef WIN32 #if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
if (host[i] == '\0' && (inet_addr(host) == -1)) if (host[i] == '\0' && (inet_addr(host) == -1))
#else #else
if (host[i] == '\0' && (apr_inet_addr(host) == -1 || inet_network(host) == -1)) if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
#endif #endif
{ {
return "Bad IP address in URL"; return "Bad IP address in URL";
@@ -348,7 +345,7 @@ const char *
&min, &sec, &year) != 7) &min, &sec, &year) != 7)
return x; return x;
for (wk = 0; wk < 7; wk++) for (wk = 0; wk < 7; wk++)
if (strcmp(week, apr_day_snames[wk]) == 0) if (strcmp(week, ap_day_snames[wk]) == 0)
break; break;
if (wk == 7) if (wk == 7)
return x; return x;
@@ -356,14 +353,14 @@ const char *
/* check date */ /* check date */
for (mon = 0; mon < 12; mon++) for (mon = 0; mon < 12; mon++)
if (strcmp(month, apr_month_snames[mon]) == 0) if (strcmp(month, ap_month_snames[mon]) == 0)
break; break;
if (mon == 12) if (mon == 12)
return x; return x;
q = apr_palloc(p, 30); q = apr_palloc(p, 30);
apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", apr_day_snames[wk], mday, apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk],
apr_month_snames[mon], year, hour, min, sec); mday, ap_month_snames[mon], year, hour, min, sec);
return q; return q;
} }
@@ -439,7 +436,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
char *value, *end; char *value, *end;
char field[MAX_STRING_LEN]; char field[MAX_STRING_LEN];
resp_hdrs = apr_make_table(r->pool, 20); resp_hdrs = ap_make_table(r->pool, 20);
/* /*
* Read header lines until we get the empty separator line, a read error, * Read header lines until we get the empty separator line, a read error,
@@ -478,7 +475,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end) for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
*end = '\0'; *end = '\0';
apr_table_add(resp_hdrs, buffer, value); ap_table_add(resp_hdrs, buffer, value);
/* the header was too long; at the least we should skip extra data */ /* the header was too long; at the least we should skip extra data */
if (len >= size - 1) { if (len >= size - 1) {
@@ -521,17 +518,20 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
* has its own timeout handler which can set both buffers to EOUT. * has its own timeout handler which can set both buffers to EOUT.
*/ */
#ifdef WIN32 #if defined(WIN32) || defined(TPF) || defined(NETWARE)
/* works fine under win32, so leave it */ /* works fine under win32, so leave it */
alternate_timeouts = 0;
#else #else
/* CHECKME! Since hard_timeout won't work in unix on sends with partial /* CHECKME! Since hard_timeout won't work in unix on sends with partial
* cache completion, we have to alternate between hard_timeout * cache completion, we have to alternate between hard_timeout
* for reads, and soft_timeout for send. This is because we need * for reads, and soft_timeout for send. This is because we need
* to get a return from ap_bwrite to be able to continue caching. * to get a return from ap_bwrite to be able to continue caching.
* BUT, if we *can't* continue anyway, just use hard_timeout. * BUT, if we *can't* continue anyway, just use hard_timeout.
* (Also, if no cache file is written, use hard timeouts)
*/ */
if (!completion || completion->content_length > 0 || completion->cache_completion == 1.0) { if (!completion || completion->content_length > 0
|| completion->cache_completion == 1.0) {
alternate_timeouts = 0; alternate_timeouts = 0;
} }
#endif #endif
@@ -540,9 +540,9 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
* or (after the client aborted) while we can successfully * or (after the client aborted) while we can successfully
* read and finish the configured cache_completion. * read and finish the configured cache_completion.
*/ */
for (ok = 1; ok; cntr=0) { for (ok = 1; ok; cntr = 0) {
/* Read block from server */ /* Read block from server */
if(ap_bread(f, buf, IOBUFSIZE, &cntr) != APR_SUCCESS && !cntr) if (ap_bread(f, buf, IOBUFSIZE, &cntr) != APR_SUCCESS && !cntr)
{ {
if (c != NULL) { if (c != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
@@ -553,7 +553,6 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
} }
else if(cntr == 0) break; else if(cntr == 0) break;
/* Write to cache first. */ /* Write to cache first. */
/*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */ /*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */
wrote_to_cache = cntr; wrote_to_cache = cntr;
@@ -561,7 +560,6 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: error writing to cache"); "proxy: error writing to cache");
ap_proxy_cache_error(&c); ap_proxy_cache_error(&c);
cachefp = NULL;
} else { } else {
written += n; written += n;
} }
@@ -614,7 +612,7 @@ void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *t)
ap_bvputs(fp, respline, CRLF, NULL); ap_bvputs(fp, respline, CRLF, NULL);
for (i = 0; i < apr_table_elts(t)->nelts; ++i) { for (i = 0; i < ap_table_elts(t)->nelts; ++i) {
if (elts[i].key != NULL) { if (elts[i].key != NULL) {
ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL); ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL);
apr_table_addn(r->headers_out, elts[i].key, elts[i].val); apr_table_addn(r->headers_out, elts[i].key, elts[i].val);
@@ -626,7 +624,7 @@ void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *t)
/* /*
* list is a comma-separated list of case insensitive tokens, with * list is a comma-separated list of case-insensitive tokens, with
* optional whitespace around the tokens. * optional whitespace around the tokens.
* The return returns 1 if the token val is found in the list, or 0 * The return returns 1 if the token val is found in the list, or 0
* otherwise. * otherwise.
@@ -658,7 +656,6 @@ int ap_proxy_liststr(const char *list, const char *val)
return 0; return 0;
} }
/* /*
* Converts 8 hex digits to a time integer * Converts 8 hex digits to a time integer
*/ */
@@ -740,11 +737,7 @@ const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
{ {
int i; int i;
struct hostent *hp; struct hostent *hp;
/* XXX - Either get rid of TLS, or use pthread/APR functions */ struct per_thread_data *ptd = get_per_thread_data();
#define APACHE_TLS
static APACHE_TLS struct hostent hpbuf;
static APACHE_TLS u_long ipaddr;
static APACHE_TLS char *charpbuf[2];
for (i = 0; host[i] != '\0'; i++) for (i = 0; host[i] != '\0'; i++)
if (!apr_isdigit(host[i]) && host[i] != '.') if (!apr_isdigit(host[i]) && host[i] != '.')
@@ -756,17 +749,17 @@ const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
return "Host not found"; return "Host not found";
} }
else { else {
ipaddr = apr_inet_addr(host); ptd->ipaddr = ap_inet_addr(host);
hp = gethostbyaddr((char *) &ipaddr, sizeof(u_long), AF_INET); hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
if (hp == NULL) { if (hp == NULL) {
memset(&hpbuf, 0, sizeof(hpbuf)); memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf));
hpbuf.h_name = 0; ptd->hpbuf.h_name = 0;
hpbuf.h_addrtype = AF_INET; ptd->hpbuf.h_addrtype = AF_INET;
hpbuf.h_length = sizeof(u_long); ptd->hpbuf.h_length = sizeof(ptd->ipaddr);
hpbuf.h_addr_list = charpbuf; ptd->hpbuf.h_addr_list = ptd->charpbuf;
hpbuf.h_addr_list[0] = (char *) &ipaddr; ptd->hpbuf.h_addr_list[0] = (char *) &ptd->ipaddr;
hpbuf.h_addr_list[1] = 0; ptd->hpbuf.h_addr_list[1] = 0;
hp = &hpbuf; hp = &ptd->hpbuf;
} }
} }
*reqhp = *hp; *reqhp = *hp;
@@ -809,7 +802,7 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
long bits; long bits;
/* if the address is given with an explicit netmask, use that */ /* if the address is given with an explicit netmask, use that */
/* Due to a deficiency in apr_inet_addr(), it is impossible to parse */ /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
/* "partial" addresses (with less than 4 quads) correctly, i.e. */ /* "partial" addresses (with less than 4 quads) correctly, i.e. */
/* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */ /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
/* I therefore have to parse the IP address manually: */ /* I therefore have to parse the IP address manually: */
@@ -881,18 +874,19 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
if (bits != 32) /* no warning for fully qualified IP address */ if (bits != 32) /* no warning for fully qualified IP address */
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld", "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
inet_ntoa(This->addr), bits); inet_ntoa(This->addr), bits);
} }
This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits)); This->mask.s_addr = htonl(INADDR_NONE << (32 - bits));
if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) { if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Warning: NetMask and IP-Addr disagree in %s/%ld", ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"Warning: NetMask and IP-Addr disagree in %s/%ld\n",
inet_ntoa(This->addr), bits); inet_ntoa(This->addr), bits);
This->addr.s_addr &= This->mask.s_addr; This->addr.s_addr &= This->mask.s_addr;
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
" Set to %s/%ld", " Set to %s/%ld\n",
inet_ntoa(This->addr), bits); inet_ntoa(This->addr), bits);
} }
@@ -1134,6 +1128,7 @@ static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, request_rec *r) int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, request_rec *r)
{ {
int i; int i;
for (i = 0; host[i] != '\0'; i++) for (i = 0; host[i] != '\0'; i++)
if (!apr_isdigit(host[i]) && host[i] != '.') if (!apr_isdigit(host[i]) && host[i] != '.')
break; break;
@@ -1151,14 +1146,15 @@ int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, reques
else if (rv == APR_SUCCESS) else if (rv == APR_SUCCESS)
return 0; return 0;
else { else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy connect to %s port %d failed", host, port); ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy connect to %s port %d failed", host, port);
return -1; return -1;
} }
} }
return -1; return -1;
} }
/* This function is called by apr_table_do() for all header lines */ /* This function is called by ap_table_do() for all header lines */
/* (from proxy_http.c and proxy_ftp.c) */ /* (from proxy_http.c and proxy_ftp.c) */
/* It is passed a table_do_args struct pointer and a MIME field and value pair */ /* It is passed a table_do_args struct pointer and a MIME field and value pair */
int ap_proxy_send_hdr_line(void *p, const char *key, const char *value) int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
@@ -1168,7 +1164,7 @@ int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
return 1; return 1;
if (!r->assbackwards) if (!r->assbackwards)
ap_rvputs(r, key, ": ", value, CRLF, NULL); ap_rvputs(r, key, ": ", value, CRLF, NULL);
return 1; /* tell apr_table_do() to continue calling us for more headers */ return 1; /* tell ap_table_do() to continue calling us for more headers */
} }
/* send a text line to one or two BUFF's; return line length */ /* send a text line to one or two BUFF's; return line length */
@@ -1182,6 +1178,51 @@ unsigned ap_proxy_bputs2(const char *data, BUFF *client, ap_cache_el *cache)
return len; return len;
} }
#if defined WIN32
static DWORD tls_index;
BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
{
LPVOID memptr;
switch (reason) {
case DLL_PROCESS_ATTACH:
tls_index = TlsAlloc();
case DLL_THREAD_ATTACH: /* intentional no break */
TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));
break;
case DLL_THREAD_DETACH:
memptr = TlsGetValue (tls_index);
if (memptr) {
free (memptr);
TlsSetValue (tls_index, 0);
}
break;
}
return TRUE;
}
#endif
static struct per_thread_data *get_per_thread_data(void)
{
#if 0
#if defined(WIN32)
return (struct per_thread_data *) TlsGetValue (tls_index);
#else
static APACHE_TLS struct per_thread_data sptd;
return &sptd;
#endif
#endif
return NULL;
}
int ap_proxy_cache_send(request_rec *r, ap_cache_el *c) int ap_proxy_cache_send(request_rec *r, ap_cache_el *c)
{ {
apr_file_t *cachefp = NULL; apr_file_t *cachefp = NULL;