[PATCH] suggested proxy connect patch
am 17.05.2002 17:27:10 von billoI have a patch which I created to simulate users on slow or asymmetric
connections. This patch adds two configuration settings to change the
speed of upload or download thru a tunnelling (CONNECT) proxy.
It's a bit rough, but I wanted to get a general feel about it before I
do much more work refining it. If people think it's useful, I'll do
whatever work is needed to make it clean enough to include in
mod_proxy. Or somebody else can take the basic idea and do it a
better way; whatever you think is best.
In a nutshell, I replace send and recv in proxy_connect.c to calculate
a delay between reading chunks of data. It's very much an
approximation, it doesn't simulate byte-by-byte throughput.
One big problem I know is that it uses usleep(), which I don't think is
available on win32, and maybe not even all unix variants.
Anyway, here's the patch, I welcome any comments or feedback. It's
off 1.3.22, but I don't think these files have changed much since then.
Thanks,
billo
Intuit, Inc. billo@billo.com bill_odonnell@intuit.com
--- /u/billo/src/apache_1.3.22/src/modules/proxy/mod_proxy.h 2001-10-05 04:19:15.000000000 -0400
+++ ./mod_proxy.h 2002-05-15 18:31:48.201857000 -0400
@@ -224,6 +224,10 @@
char viaopt_set;
size_t recv_buffer_size;
char recv_buffer_size_set;
+ int throttle_up_speed; /* billo dial-up simulator */
+ char throttle_up_set; /* billo dial-up simulator */
+ int throttle_down_speed; /* billo dial-up simulator */
+ char throttle_down_set; /* billo dial-up simulator */
} proxy_server_conf;
struct hdr_entry {
--- /u/billo/src/apache_1.3.22/src/modules/proxy/proxy_connect.c 2001-10-05 04:19:15.000000000 -0400
+++ ./proxy_connect.c 2002-05-15 18:37:24.476203000 -0400
@@ -96,6 +96,46 @@
* FIXME: no check for r->assbackwards, whatever that is.
*/
+static useconds_t sleep_calc(int speed, int len)
+{
+ useconds_t delay;
+ if (speed == 0) {
+ return 0;
+ }
+ delay = 1000000 / (speed / 8);
+
+ delay = delay * len;
+
+ return delay;
+}
+
+static ssize_t proxy_recv(int s, void *buf, size_t len, int flags, int choke, request_rec *r)
+{
+ if (choke > 0) {
+ ssize_t ret = recv(s, buf, len, flags);
+ useconds_t delay = sleep_calc(choke, ret);
+ /* ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: billo proxy recv delay %d", delay); */
+ usleep(delay);
+ return ret;
+ } else {
+ return recv(s, buf, len, flags);
+ }
+}
+
+static ssize_t proxy_send(int s, void *buf, size_t len, int flags, int choke, request_rec *r)
+{
+ /* ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: billo proxy send"); */
+ if (choke > 0) {
+ ssize_t ret = send(s, buf, len, flags);
+ useconds_t delay = sleep_calc(choke, ret);
+ usleep(delay);
+ return ret;
+ } else {
+ return send(s, buf, len, flags);
+ }
+}
+
+
static int
allowed_port(proxy_server_conf *conf, int port)
{
@@ -109,6 +149,7 @@
return 0;
}
+#define CONNECT_BUFFER_SIZE 256
int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
const char *proxyhost, int proxyport)
@@ -119,8 +160,10 @@
const char *host, *err;
char *p;
int port, sock;
- char buffer[HUGE_STRING_LEN];
+ char buffer[CONNECT_BUFFER_SIZE];
int nbytes, i, j;
+ int throttle_up = 0;
+ int throttle_down = 0;
fd_set fds;
void *sconf = r->server->module_config;
@@ -128,6 +171,12 @@
(proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
+ if (conf->throttle_up_set) {
+ throttle_up = conf->throttle_up_speed;
+ }
+ if (conf->throttle_down_set) {
+ throttle_down = conf->throttle_down_speed;
+ }
memset(&server, '\0', sizeof(server));
server.sin_family = AF_INET;
@@ -260,10 +309,10 @@
if (i) {
if (FD_ISSET(sock, &fds)) {
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "sock was set");
- if ((nbytes = recv(sock, buffer, HUGE_STRING_LEN,0)) != 0) {
+ if ((nbytes = proxy_recv(sock, buffer, CONNECT_BUFFER_SIZE, 0, throttle_down, r)) != 0) {
if (nbytes == -1)
break;
- if (send(ap_bfileno(r->connection->client, B_WR), buffer, nbytes,0) == EOF)
+ if (proxy_send(ap_bfileno(r->connection->client, B_WR), buffer, nbytes,0, throttle_down, r) == EOF)
break;
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Wrote %d bytes to client", nbytes);
}
@@ -272,11 +321,11 @@
}
else if (FD_ISSET(ap_bfileno(r->connection->client, B_WR), &fds)) {
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "client->fd was set");
- if ((nbytes = recv(ap_bfileno(r->connection->client, B_WR), buffer,
- HUGE_STRING_LEN, 0)) != 0) {
+ if ((nbytes = proxy_recv(ap_bfileno(r->connection->client, B_WR), buffer,
+ CONNECT_BUFFER_SIZE, 0, throttle_up, r)) != 0) {
if (nbytes == -1)
break;
- if (send(sock, buffer, nbytes, 0) == EOF)
+ if (proxy_send(sock, buffer, nbytes, 0, throttle_up, r) == EOF)
break;
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Wrote %d bytes to server", nbytes);
}
@@ -294,3 +343,4 @@
return OK;
}
+
--- /u/billo/src/apache_1.3.22/src/modules/proxy/mod_proxy.c 2001-09-24 16:14:27.000000000 -0400
+++ ./mod_proxy.c 2002-05-17 10:45:04.454437000 -0400
@@ -442,6 +507,10 @@
ps->cache.dirlength_set = 0;
ps->cache.cache_completion = DEFAULT_CACHE_COMPLETION;
ps->cache.cache_completion_set = 0;
+ ps->throttle_up_speed = 0; /* default no choke billo 10-may-2002 */
+ ps->throttle_up_set = 0; /* default no choke billo 10-may-2002 */
+ ps->throttle_down_speed = 0; /* default no choke billo 10-may-2002 */
+ ps->throttle_down_set = 0; /* default no choke billo 10-may-2002 */
return ps;
}
@@ -842,6 +917,31 @@
return NULL;
}
+
+static const char *
+ set_throttle_up_speed(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int s = atoi(arg);
+
+ psf->throttle_up_speed = s;
+ psf->throttle_up_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_throttle_down_speed(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int s = atoi(arg);
+
+ psf->throttle_down_speed = s;
+ psf->throttle_down_set = 1;
+ return NULL;
+}
+
static const char*
set_cache_completion(cmd_parms *parms, void *dummy, char *arg)
{
@@ -903,6 +1003,10 @@
"A list of names, hosts or domains to which the proxy will not connect"},
{"ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, TAKE1,
"Receive buffer size for outgoing HTTP and FTP connections in bytes"},
+ {"ProxyConnectThrottleUp", set_throttle_up_speed, NULL, RSRC_CONF, TAKE1,
+ "Reduce throughput of connect proxy (upload direction)"},
+ {"ProxyConnectThrottleDown", set_throttle_down_speed, NULL, RSRC_CONF, TAKE1,
+ "Reduce throughput of connect proxy (download direction)"},
{"NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, ITERATE,
"A list of domains, hosts, or subnets to which the proxy will connect directly"},
{"ProxyDomain", set_proxy_domain, NULL, RSRC_CONF, TAKE1,