From d2af947760f5e7a92ab3bf260744c55ce19ac073 Mon Sep 17 00:00:00 2001 From: wessels <> Date: Thu, 11 Jul 1996 23:42:34 +0000 Subject: [PATCH] redirector up to snuff --- src/Makefile.in | 5 +- src/cache_cf.cc | 60 +++++++++- src/comm.cc | 3 +- src/main.cc | 4 +- src/neighbors.cc | 246 ++++++++++++++++------------------------ src/redirect.cc | 262 +++++++++++++++++++++++++++++++------------ src/send-announce.cc | 3 +- src/squid.h | 4 +- src/ssl.cc | 12 +- src/stat.cc | 28 ++--- src/tunnel.cc | 12 +- 11 files changed, 381 insertions(+), 258 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index a4eae948c3..39edff3c80 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.27 1996/07/09 04:46:49 wessels Exp $ +# $Id: Makefile.in,v 1.28 1996/07/11 17:42:34 wessels Exp $ # # Uncomment and customize the following to suit your needs: # @@ -57,7 +57,8 @@ OBJS = acl.o async_io.o background.o cache_cf.o errorpage.o \ fdstat.o filemap.o ftp.o gopher.o \ hash.o http.o icp.o ident.o ipcache.o \ main.o mime.o neighbors.o objcache.o \ - proto.o send-announce.o ssl.o stack.o stat.o stmem.o \ + proto.o redirect.o send-announce.o ssl.o stack.o \ + stat.o stmem.o \ store.o storetoString.o tools.o ttl.o \ url.o wais.o $(XTRA_OBJS) diff --git a/src/cache_cf.cc b/src/cache_cf.cc index cfa7cee7b1..c0a031915f 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,5 +1,5 @@ /* - * $Id: cache_cf.cc,v 1.57 1996/07/09 05:06:17 wessels Exp $ + * $Id: cache_cf.cc,v 1.58 1996/07/11 17:42:36 wessels Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -130,7 +130,6 @@ static struct { int connectTimeout; int ageMaxDefault; int cleanRate; - int dnsChildren; int maxRequestSize; double hotVmFactor; struct { @@ -151,7 +150,10 @@ static struct { char *ftpget; char *ftpget_opts; char *dnsserver; + char *redirect; } Program; + int dnsChildren; + int redirectChildren; int sourcePing; int quickAbort; int commonLogFormat; @@ -218,7 +220,8 @@ static struct { #define DefaultConnectTimeout (2 * 60) /* 2 min */ #define DefaultDefaultAgeMax (3600 * 24 * 30) /* 30 days */ #define DefaultCleanRate -1 /* disabled */ -#define DefaultDnsChildren 5 /* 3 processes */ +#define DefaultDnsChildren 5 /* 5 processes */ +#define DefaultRedirectChildren 5 /* 5 processes */ #define DefaultMaxRequestSize (100 << 10) /* 100Kb */ #define DefaultHotVmFactor 0.0 /* disabled */ @@ -234,6 +237,7 @@ static struct { #define DefaultFtpgetProgram DEFAULT_FTPGET #define DefaultFtpgetOptions "" #define DefaultDnsserverProgram DEFAULT_DNSSERVER +#define DefaultRedirectProgram (char *)NULL /* default NONE */ #define DefaultEffectiveUser (char *)NULL /* default NONE */ #define DefaultEffectiveGroup (char *)NULL /* default NONE */ #define DefaultAppendDomain (char *)NULL /* default NONE */ @@ -775,6 +779,14 @@ static void parseDnsChildrenLine() Config.dnsChildren = i; } +static void parseRedirectChildrenLine() +{ + char *token; + int i; + GetInteger(i); + Config.redirectChildren = i; +} + static void parseRequestSizeLine() { char *token; @@ -934,6 +946,16 @@ static void parseDnsProgramLine() Config.Program.dnsserver = xstrdup(token); } +static void parseRedirectProgramLine() +{ + char *token; + token = strtok(NULL, w_space); + if (token == NULL) + self_destruct(); + safe_free(Config.Program.redirect); + Config.Program.redirect = xstrdup(token); +} + static void parseEmulateLine() { char *token; @@ -1410,6 +1432,11 @@ int parseConfigFile(file_name) else if (!strcmp(token, "dns_children")) parseDnsChildrenLine(); + else if (!strcmp(token, "redirect_program")) + parseRedirectProgramLine(); + else if (!strcmp(token, "redirect_children")) + parseRedirectChildrenLine(); + /* Parse source_ping line */ else if (!strcmp(token, "source_ping")) parseSourcePingLine(); @@ -1526,14 +1553,25 @@ int parseConfigFile(file_name) if (getDnsChildren() < 1) { printf("WARNING: dns_children was set to a bad value: %d\n", getDnsChildren()); - printf("Setting it to the default (3).\n"); - Config.dnsChildren = 3; + Config.dnsChildren = DefaultDnsChildren; + printf("Setting it to the default (%d).\n", DefaultDnsChildren); } else if (getDnsChildren() > DefaultDnsChildrenMax) { printf("WARNING: dns_children was set to a bad value: %d\n", getDnsChildren()); printf("Setting it to the maximum (%d).\n", DefaultDnsChildrenMax); Config.dnsChildren = DefaultDnsChildrenMax; } + if (getRedirectChildren() < 1) { + printf("WARNING: redirect_children was set to a bad value: %d\n", + getRedirectChildren()); + Config.redirectChildren = DefaultRedirectChildren; + printf("Setting it to the default (%d).\n", DefaultRedirectChildren); + } else if (getRedirectChildren() > DefaultRedirectChildrenMax) { + printf("WARNING: redirect_children was set to a bad value: %d\n", + getRedirectChildren()); + printf("Setting it to the maximum (%d).\n", DefaultRedirectChildrenMax); + Config.redirectChildren = DefaultRedirectChildrenMax; + } fclose(fp); configDoConfigure(); @@ -1652,6 +1690,10 @@ int getDnsChildren() { return Config.dnsChildren; } +int getRedirectChildren() +{ + return Config.redirectChildren; +} int getQuickAbort() { return Config.quickAbort; @@ -1700,6 +1742,10 @@ char *getDnsProgram() { return Config.Program.dnsserver; } +char *getRedirectProgram() +{ + return Config.Program.redirect; +} char *getFtpProgram() { return Config.Program.ftpget; @@ -1840,6 +1886,7 @@ static void configFreeMemory() safe_free(Config.Program.ftpget); safe_free(Config.Program.ftpget_opts); safe_free(Config.Program.dnsserver); + safe_free(Config.Program.redirect); safe_free(Config.Accel.host); safe_free(Config.Accel.prefix); safe_free(Config.appendDomain); @@ -1891,6 +1938,7 @@ static void configSetFactoryDefaults() Config.ageMaxDefault = DefaultDefaultAgeMax; Config.cleanRate = DefaultCleanRate; Config.dnsChildren = DefaultDnsChildren; + Config.redirectChildren = DefaultRedirectChildren; Config.hotVmFactor = DefaultHotVmFactor; Config.sourcePing = DefaultSourcePing; Config.quickAbort = DefaultQuickAbort; @@ -1914,6 +1962,7 @@ static void configSetFactoryDefaults() Config.Program.ftpget = safe_xstrdup(DefaultFtpgetProgram); Config.Program.ftpget_opts = safe_xstrdup(DefaultFtpgetOptions); Config.Program.dnsserver = safe_xstrdup(DefaultDnsserverProgram); + Config.Program.redirect = safe_xstrdup(DefaultRedirectProgram); Config.Accel.host = safe_xstrdup(DefaultAccelHost); Config.Accel.prefix = safe_xstrdup(DefaultAccelPrefix); Config.Accel.port = DefaultAccelPort; @@ -1940,6 +1989,7 @@ static void configDoConfigure() DnsPositiveTtl = Config.positiveDnsTtl; sprintf(ForwardedBy, "Forwarded: by http://%s:%d/", getMyHostname(), getHttpPortNum()); + do_redirect = getRedirectProgram()? 1 : 0; #if !ALLOW_HOT_CACHE diff --git a/src/comm.cc b/src/comm.cc index ba0c3f6747..f2e3a3cc19 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1,6 +1,6 @@ /* - * $Id: comm.cc,v 1.36 1996/07/09 22:58:27 wessels Exp $ + * $Id: comm.cc,v 1.37 1996/07/11 17:42:38 wessels Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -663,6 +663,7 @@ int comm_select(sec, failtime) serverConnectionsClose(); ftpServerClose(); ipcacheShutdownServers(); + redirectShutdownServers(); setSocketShutdownLifetimes(); } nfds = 0; diff --git a/src/main.cc b/src/main.cc index 181eba9eb0..e90d408b19 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,5 @@ /* - * $Id: main.cc,v 1.48 1996/07/09 04:46:52 wessels Exp $ + * $Id: main.cc,v 1.49 1996/07/11 17:42:44 wessels Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -372,6 +372,7 @@ static void mainReinitialize() _db_init(getCacheLogFile(), getDebugOptions()); neighbors_init(); ipcacheOpenServers(); + redirectOpenServers(); serverConnectionsOpen(); (void) ftpInitialize(); if (theOutIcpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy())) @@ -417,6 +418,7 @@ static void mainInitialize() writePidFile(); /* write PID file */ } ipcache_init(); + redirectOpenServers(); neighbors_init(); (void) ftpInitialize(); diff --git a/src/neighbors.cc b/src/neighbors.cc index 73074b61fd..9b52f1de93 100644 --- a/src/neighbors.cc +++ b/src/neighbors.cc @@ -1,5 +1,5 @@ /* - * $Id: neighbors.cc,v 1.24 1996/07/09 03:41:33 wessels Exp $ + * $Id: neighbors.cc,v 1.25 1996/07/11 17:42:45 wessels Exp $ * * DEBUG: section 15 Neighbor Routines * AUTHOR: Harvest Derived @@ -164,12 +164,14 @@ edge *whichEdge(header, from) } -void hierarchy_log_append(url, code, timeout, cache_host) - char *url; +void hierarchy_log_append(entry, code, timeout, cache_host) + StoreEntry *entry; hier_code code; int timeout; char *cache_host; { + char *url = entry->url; + MemObject *mem = entry->mem_obj; static time_t last_time = 0; static char time_str[128]; char *s = NULL; @@ -179,6 +181,8 @@ void hierarchy_log_append(url, code, timeout, cache_host) if (code > HIER_MAX) code = HIER_MAX; + if (mem) + mem->hierarchy_code = code; if (emulate_httpd_log) { if (squid_curtime != last_time) { @@ -553,15 +557,9 @@ int neighborsUdpPing(proto) inet_ntoa(e->in_addr.sin_addr)); /* log it once at the threshold */ if ((e->stats.ack_deficit == HIER_MAX_DEFICIT)) { - if (e->type == EDGE_SIBLING) { - hierarchy_log_append("Detect: ", - HIER_DEAD_NEIGHBOR, 0, - e->host); - } else { - hierarchy_log_append("Detect: ", - HIER_DEAD_PARENT, 0, - e->host); - } + debug(15, 0, "neighborsUdpPing: Detected DEAD %s: %s\n", + e->type == EDGE_SIBLING ? "SIBLING" : "PARENT", + e->host); } } friends->first_ping = e->next; @@ -611,176 +609,119 @@ void neighborsUdpAck(fd, url, header, from, entry, data, data_sz) int n; HttpStateData *httpState = NULL; - debug(15, 6, "neighborsUdpAck: url=%s (%d chars), header=0x%x, from=0x%x, ent=0x%x\n", - url, strlen(url), header, from, entry); - debug(15, 6, " hdr: opcode=%d, ver=%d, shostid=%x, len=%d, rn=0x%x\n", - header->opcode, header->version, header->shostid, - header->length, header->reqnum); - debug(15, 6, " from: fam=%d, port=%d, addr=0x%x\n", - ntohs(from->sin_family), - ntohs(from->sin_port), - ntohl(from->sin_addr.s_addr)); - - /* look up for neighbor/parent entry */ - e = whichEdge(header, from); - - if (e) { - /* reset the deficit. It's alive now. */ - /* Don't care about exact count. */ - if ((e->stats.ack_deficit >= HIER_MAX_DEFICIT)) { - if (e->type == EDGE_SIBLING) { - hierarchy_log_append("Detect: ", - HIER_REVIVE_NEIGHBOR, 0, e->host); - } else { - hierarchy_log_append("Detect: ", - HIER_REVIVE_PARENT, 0, e->host); - } + debug(15, 6, "neighborsUdpAck: opcode %d '%s'\n", + (int) header->opcode, url); + if (header->opcode > ICP_OP_END) + return; + if (mem == NULL) { + debug(15, 1, "Ignoring ICP reply for missing mem_obj: %s\n", url); + return; + } + if ((e = whichEdge(header, from))) { + /* Neighbor is alive, reset the ack deficit */ + if (e->stats.ack_deficit >= HIER_MAX_DEFICIT) { + debug(15, 0, "neighborsUdpAck: Detected REVIVED %s: %s\n", + e->type == EDGE_SIBLING ? "SIBLING" : "PARENT", + e->host); } e->neighbor_up = 1; e->stats.ack_deficit = 0; n = ++e->stats.pings_acked; - if (header->opcode < ICP_OP_END) - e->stats.counts[header->opcode]++; - if (mem) { - if (n > RTT_AV_FACTOR) - n = RTT_AV_FACTOR; - rtt = tvSubMsec(mem->start_ping, current_time); - e->stats.rtt = (e->stats.rtt * (n - 1) + rtt) / n; - } + e->stats.counts[header->opcode]++; + if (n > RTT_AV_FACTOR) + n = RTT_AV_FACTOR; + rtt = tvSubMsec(mem->start_ping, current_time); + e->stats.rtt = (e->stats.rtt * (n - 1) + rtt) / n; } /* check if someone is already fetching it */ - if (BIT_TEST(entry->flag, ENTRY_DISPATCHED) || (entry->ping_status != PING_WAITING)) { - if (entry->ping_status == PING_DONE) { - debug(15, 5, "There is already a cache/source dispatched for this object\n"); - debug(15, 5, "--> \n", entry->url); - debug(15, 5, "--> entry->flag & ENTRY_DISPATCHED = %d\n", - BIT_TEST(entry->flag, ENTRY_DISPATCHED)); - debug(15, 5, "--> entry->ping_status = %d\n", entry->ping_status); - } else { - debug(15, 5, "The ping already timed out.\n"); - debug(15, 5, "--> \n", entry->url); - debug(15, 5, "--> entry->flag & ENTRY_DISPATCHED = %lx\n", - BIT_TEST(entry->flag, ENTRY_DISPATCHED)); - debug(15, 5, "--> entry->ping_status = %d\n", entry->ping_status); - } + if (BIT_TEST(entry->flag, ENTRY_DISPATCHED)) { + debug(15, 5, "neighborsUdpAck: '%s' already being fetched.\n", url); + return; + } + if (entry->ping_status != PING_WAITING) { + debug(15, 5, "neighborsUdpAck: '%s' unexpected ICP reply.\n", url); return; } - debug(15, 6, "neighborsUdpAck - url: %s to us %s \n", - url, e ? inet_ntoa(e->in_addr.sin_addr) : "url-host"); + debug(15, 3, "neighborsUdpAck: %s for '%s' from %s \n", + IcpOpcodeStr[header->opcode], url, e ? e->host : "source"); + mem->e_pings_n_acks++; if (header->opcode == ICP_OP_SECHO) { - /* receive ping back from source or from non-ICP cache */ + /* Received source-ping reply */ if (e) { - debug(15, 6, "Got SECHO from non-ICP cache:%s\n", - inet_ntoa(e->in_addr.sin_addr)); - debug(15, 6, "This is not supposed to happen. Ignored.\n"); + debug(15, 1, "neighborsUdpAck: Ignoring SECHO from %s\n", e->host); } else { - /* if we reach here, source is the one has the fastest respond. */ - /* fetch directly from source */ + /* if we reach here, source-ping reply is the first 'parent', + * so fetch directly from the source */ debug(15, 6, "Source is the first to respond.\n"); - hierarchy_log_append(entry->url, + hierarchy_log_append(entry, HIER_SOURCE_FASTEST, 0, inet_ntoa(from->sin_addr)); - if (mem) - mem->hierarchy_code = HIER_SOURCE_FASTEST; BIT_SET(entry->flag, ENTRY_DISPATCHED); entry->ping_status = PING_DONE; getFromCache(0, entry, NULL, entry->mem_obj->request); + return; } - return; } else if (header->opcode == ICP_OP_HIT_OBJ) { if (entry->object_len != 0) { - debug(15, 0, "Too late UDP_HIT_OBJ '%s'?\n", entry->url); + debug(15, 1, "Too late UDP_HIT_OBJ '%s'?\n", entry->url); + } else { + protoCancelTimeout(0, entry); + entry->ping_status = PING_DONE; + httpState = xcalloc(1, sizeof(HttpStateData)); + httpState->entry = entry; + httpProcessReplyHeader(httpState, data, data_sz); + storeAppend(entry, data, data_sz); + storeComplete(entry); + hierarchy_log_append(entry, + HIER_UDP_HIT_OBJ, + 0, + e ? e->host : inet_ntoa(from->sin_addr)); + if (httpState->reply_hdr) + put_free_8k_page(httpState->reply_hdr); + safe_free(httpState); return; } - protoCancelTimeout(0, entry); - entry->ping_status = PING_DONE; - httpState = xcalloc(1, sizeof(HttpStateData)); - httpState->entry = entry; - httpProcessReplyHeader(httpState, data, data_sz); - storeAppend(entry, data, data_sz); - storeComplete(entry); - hierarchy_log_append(entry->url, - HIER_UDP_HIT_OBJ, - 0, - e ? e->host : inet_ntoa(from->sin_addr)); - if (mem) - mem->hierarchy_code = HIER_UDP_HIT_OBJ; - if (httpState->reply_hdr) - put_free_8k_page(httpState->reply_hdr); - safe_free(httpState); - return; } else if (header->opcode == ICP_OP_HIT) { - /* If an edge is not found, count it as a MISS message. */ - if (!e) { - /* count it as a MISS message */ - mem->e_pings_n_acks++; + if (e == NULL) { + debug(15, 1, "neighborsUdpAck: Ignoring HIT from non-neighbor\n"); + } else { + hierarchy_log_append(entry, + e->type == EDGE_SIBLING ? HIER_NEIGHBOR_HIT : HIER_PARENT_HIT, + 0, + e->host); + BIT_SET(entry->flag, ENTRY_DISPATCHED); + entry->ping_status = PING_DONE; + getFromCache(0, entry, e, entry->mem_obj->request); return; } - /* GOT a HIT here */ - debug(15, 6, "HIT: Getting %s from host: %s\n", entry->url, e->host); - if (e->type == EDGE_SIBLING) { - hierarchy_log_append(entry->url, HIER_NEIGHBOR_HIT, 0, e->host); - if (mem) - mem->hierarchy_code = HIER_NEIGHBOR_HIT; + } else if (header->opcode == ICP_OP_DECHO) { + if (e == NULL) { + debug(15, 1, "neighborsUdpAck: Ignoring DECHO from non-neighbor\n"); + } else if (e->type == EDGE_SIBLING) { + fatal_dump("neighborsUdpAck: Found non-ICP cache as SIBLING\n"); } else { - hierarchy_log_append(entry->url, HIER_PARENT_HIT, 0, e->host); - if (mem) - mem->hierarchy_code = HIER_PARENT_HIT; - } - BIT_SET(entry->flag, ENTRY_DISPATCHED); - entry->ping_status = PING_DONE; - getFromCache(0, entry, e, entry->mem_obj->request); - return; - } else if ((header->opcode == ICP_OP_MISS) || (header->opcode == ICP_OP_DECHO)) { - /* everytime we get here, count it as a miss */ - mem->e_pings_n_acks++; - - if (header->opcode == ICP_OP_DECHO) { - /* receive ping back from non-ICP cache */ - - if (e) { - debug(15, 6, "Got DECHO from non-ICP cache:%s\n", - inet_ntoa(e->in_addr.sin_addr)); - - if (e->type == EDGE_PARENT) { - w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight; - if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) { - debug(15, 6, "Dumb-cache has minimum weighted RTT = %d\n", w_rtt); - mem->e_pings_first_miss = e; - mem->w_rtt = w_rtt; - } - } else { - debug(15, 6, "Dumb Cached as a neighbor does not make sense.\n"); - } - - - } else { - debug(15, 6, "Got DECHO from non-ICP cache: But the host is not in the list.\n"); - debug(15, 6, "Count it anyway.\n"); - } - - } else if (e && e->type == EDGE_PARENT) { - /* ICP_OP_MISS from a cache */ w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight; if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) { mem->e_pings_first_miss = e; mem->w_rtt = w_rtt; } } - if (mem->e_pings_n_acks == mem->e_pings_n_pings) { - BIT_SET(entry->flag, ENTRY_DISPATCHED); - entry->ping_status = PING_DONE; - debug(15, 6, "Receive MISSes from all neighbors and parents\n"); - /* pass in fd=0 here so getFromCache() looks up the real FD - * and resets the timeout handler */ - getFromDefaultSource(0, entry); - return; + } else if (header->opcode == ICP_OP_MISS) { + if (e == NULL) { + debug(15, 1, "neighborsUdpAck: Ignoring MISS from non-neighbor\n"); + } else if (e->type == EDGE_PARENT) { + w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight; + if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) { + mem->e_pings_first_miss = e; + mem->w_rtt = w_rtt; + } } } else if (header->opcode == ICP_OP_DENIED) { - debug(15, 5, "neighborsUdpAck: Access denied for '%s'\n", entry->url); - if (e && e->stats.pings_acked > 100) { + if (e == NULL) { + debug(15, 1, "neighborsUdpAck: Ignoring DENIED from non-neighbor\n"); + } else if (e->stats.pings_acked > 100) { if (100 * e->stats.counts[ICP_OP_DENIED] / e->stats.pings_acked > 95) { debug(15, 0, "95%% of replies from '%s' are UDP_DENIED\n", e->host); debug(15, 0, "Disabling '%s', please check your configuration.\n", e->host); @@ -788,8 +729,17 @@ void neighborsUdpAck(fd, url, header, from, entry, data, data_sz) } } } else { - debug(15, 0, "neighborsUdpAck: WHY ARE WE HERE? header->opcode = %d\n", - header->opcode); + debug(15, 0, "neighborsUdpAck: Unexpected ICP reply: %s\n", + IcpOpcodeStr[header->opcode]); + } + if (mem->e_pings_n_acks == mem->e_pings_n_pings) { + BIT_SET(entry->flag, ENTRY_DISPATCHED); + entry->ping_status = PING_DONE; + debug(15, 6, "neighborsUdpAck: All replies received.\n"); + /* pass in fd=0 here so getFromCache() looks up the real FD + * and resets the timeout handler */ + getFromDefaultSource(0, entry); + return; } } diff --git a/src/redirect.cc b/src/redirect.cc index 8e10056ccf..bb6c1e37b2 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -1,5 +1,5 @@ /* - * $Id: redirect.cc,v 1.2 1996/07/09 03:41:37 wessels Exp $ + * $Id: redirect.cc,v 1.3 1996/07/11 17:42:50 wessels Exp $ * * DEBUG: section 29 Redirector * AUTHOR: Duane Wessels @@ -34,11 +34,9 @@ #define REDIRECT_FLAG_BUSY 0x02 #define REDIRECT_FLAG_CLOSING 0x04 -typedef void (*RH) _PARAMS((int, char *)); - - typedef struct { int fd; + void *data; char *orig_url; RH handler; } redirectStateData; @@ -50,14 +48,28 @@ typedef struct _redirector { char *inbuf; unsigned int size; unsigned int offset; + struct timeval dispatch_time; redirectStateData *redirectState; } redirector_t; +static struct { + int requests; + int replies; + int errors; + int avg_svc_time; + int queue_size; + int use_hist[DefaultRedirectChildrenMax]; +} RedirectStats; + + struct redirectQueueData { struct redirectQueueData *next; redirectStateData *redirectState; }; +/* GLOBALS */ +int do_redirect = 0; + static redirector_t *GetFirstAvailable _PARAMS((void)); static int redirectCreateRedirector _PARAMS((char *command)); static int redirectHandleRead _PARAMS((int, redirector_t *)); @@ -71,8 +83,7 @@ static int NRedirectors = 0; static struct redirectQueueData *redirectQueueHead = NULL; static struct redirectQueueData **redirectQueueTailP = &redirectQueueHead; -/* TCP SOCKET VERSION */ -int redirectCreateRedirector(command) +static int redirectCreateRedirector(command) char *command; { int pid; @@ -88,21 +99,20 @@ int redirectCreateRedirector(command) 0, "socket to redirector"); if (cfd == COMM_ERROR) { - debug(14, 0, "redirect_create_redirector: Failed to create redirector\n"); + debug(29, 0, "redirect_create_redirector: Failed to create redirector\n"); return -1; } len = sizeof(S); memset(&S, '\0', len); if (getsockname(cfd, (struct sockaddr *) &S, &len) < 0) { - debug(14, 0, "redirect_create_redirector: getsockname: %s\n", xstrerror()); + debug(29, 0, "redirect_create_redirector: getsockname: %s\n", xstrerror()); comm_close(cfd); return -1; } port = ntohs(S.sin_port); - debug(14, 4, "redirect_create_redirector: bind to local host.\n"); listen(cfd, 1); if ((pid = fork()) < 0) { - debug(14, 0, "redirect_create_redirector: fork: %s\n", xstrerror()); + debug(29, 0, "redirect_create_redirector: fork: %s\n", xstrerror()); comm_close(cfd); return -1; } @@ -117,38 +127,46 @@ int redirectCreateRedirector(command) return -1; } comm_set_fd_lifetime(sfd, -1); - debug(14, 4, "redirect_create_redirector: FD %d connected to %s #%d.\n", - sfd, command, n_redirector); + debug(29, 4, "redirect_create_redirector: FD %d connected to %s #%d.\n", + sfd, command, n_redirector++); return sfd; } /* child */ no_suid(); /* give up extra priviliges */ - dup2(cfd, 3); - for (fd = FD_SETSIZE; fd > 3; fd--) + if ((fd = accept(cfd, NULL, NULL)) < 0) { + debug(29, 0, "redirect_create_redirector: FD %d accept: %s\n", + cfd, xstrerror()); + _exit(1); + } + dup2(fd, 0); + dup2(fd, 1); + for (fd = 3; fd < FD_SETSIZE; fd++) close(fd); - execlp(command, "(redirector)", "-t", NULL); - debug(14, 0, "redirect_create_redirector: %s: %s\n", command, xstrerror()); + execlp(command, "(redirector)", NULL); + debug(29, 0, "redirect_create_redirector: %s: %s\n", command, xstrerror()); _exit(1); return 0; } - - -int redirectHandleRead(fd, redirector) +static int redirectHandleRead(fd, redirector) int fd; redirector_t *redirector; { int len; redirectStateData *r = redirector->redirectState; char *t = NULL; + int n; + int svc_time; len = read(fd, redirector->inbuf + redirector->offset, redirector->size - redirector->offset); - debug(14, 5, "redirectHandleRead: Result from Redirector %d.\n", - redirector->index + 1); + debug(29, 5, "redirectHandleRead: %d bytes from Redirector #%d.\n", + len, redirector->index + 1); if (len <= 0) { - debug(14, redirector->flags & REDIRECT_FLAG_CLOSING ? 5 : 1, + if (len < 0) + debug(29, 1, "redirectHandleRead: FD %d read: %s\n", fd, xstrerror()); + debug(29, redirector->flags & REDIRECT_FLAG_CLOSING ? 5 : 1, "FD %d: Connection from Redirector #%d is closed, disabling\n", fd, redirector->index + 1); redirector->flags = 0; @@ -165,38 +183,27 @@ int redirectHandleRead(fd, redirector) if ((t = strchr(redirector->inbuf, '\n'))) { /* end of record found */ *t = '\0'; - if (t == redirector->inbuf) - r->handler(r->fd, r->orig_url); - else - r->handler(r->fd, redirector->inbuf); + debug(29, 5, "redirectHandleRead: reply: '%s'\n", redirector->inbuf); + if (r->handler) { + r->handler(r->data, + t == redirector->inbuf ? NULL : redirector->inbuf); + } + safe_free(r); redirector->redirectState = NULL; redirector->flags &= ~REDIRECT_FLAG_BUSY; + redirector->offset = 0; + n = ++RedirectStats.replies; + svc_time = tvSubMsec(redirector->dispatch_time, current_time); + if (n > REDIRECT_AV_FACTOR) + n = REDIRECT_AV_FACTOR; + RedirectStats.avg_svc_time + = (RedirectStats.avg_svc_time * (n - 1) + svc_time) / n; } - while ((r = Dequeue()) && (redirector = GetFirstAvailable())) + while ((redirector = GetFirstAvailable()) && (r = Dequeue())) redirectDispatch(redirector, r); return 0; } -void redirectStart(url, fd, handler) - char *url; - int fd; - RH handler; -{ - redirectStateData *r = NULL; - redirector_t *redirector = NULL; - - if (!handler) - fatal_dump("redirectStart: NULL handler"); - r = xcalloc(1, sizeof(redirectStateData)); - r->fd = fd; - r->orig_url = url; - r->handler = handler; - if ((redirector = GetFirstAvailable())) - redirectDispatch(redirector, r); - else - Enqueue(r); -} - static void Enqueue(r) redirectStateData *r; { @@ -204,6 +211,7 @@ static void Enqueue(r) new->redirectState = r; *redirectQueueTailP = new; redirectQueueTailP = &new->next; + RedirectStats.queue_size++; } static redirectStateData *Dequeue() @@ -217,6 +225,7 @@ static redirectStateData *Dequeue() if (redirectQueueHead == NULL) redirectQueueTailP = &redirectQueueHead; safe_free(old); + RedirectStats.queue_size--; } return r; } @@ -239,26 +248,70 @@ static void redirectDispatch(redirect, r) redirectStateData *r; { char *buf = NULL; + int len; + if (r->handler == NULL) { + debug(29, 1, "redirectDispatch: skipping '%s' because no handler\n", + r->orig_url); + safe_free(r); + return; + } redirect->flags |= REDIRECT_FLAG_BUSY; redirect->redirectState = r; + redirect->dispatch_time = current_time; + len = strlen(r->orig_url) + 1; + buf = xmalloc(len + 1); + sprintf(buf, "%s\n", r->orig_url); comm_write(redirect->fd, - xstrdup(buf), - strlen(buf), + buf, + len, 0, /* timeout */ NULL, /* Handler */ NULL); /* Handler-data */ - debug(14, 5, "redirectDispatch: Request sent to Redirector #%d.\n", - redirect->index + 1); + debug(29, 5, "redirectDispatch: Request sent to Redirector #%d, %d bytes\n", + redirect->index + 1, len); + RedirectStats.use_hist[redirect->index]++; + RedirectStats.requests++; } +/**** PUBLIC FUNCTIONS ****/ + + +void redirectStart(url, fd, handler, data) + char *url; + int fd; + RH handler; + void *data; +{ + redirectStateData *r = NULL; + redirector_t *redirector = NULL; + if (!handler) + fatal_dump("redirectStart: NULL handler"); + if (!do_redirect) { + (*handler) (data, NULL); + return; + } + r = xcalloc(1, sizeof(redirectStateData)); + r->fd = fd; + r->orig_url = url; + r->handler = handler; + r->data = data; + if ((redirector = GetFirstAvailable())) + redirectDispatch(redirector, r); + else + Enqueue(r); +} + void redirectOpenServers() { char *prg = getRedirectProgram(); int k; int redirectsocket; static char fd_note_buf[FD_ASCII_NOTE_SZ]; + static int first_time = 0; + if (!do_redirect) + return; /* free old structures if present */ if (redirect_child_table) { for (k = 0; k < NRedirectors; k++) @@ -267,59 +320,122 @@ void redirectOpenServers() } NRedirectors = getRedirectChildren(); redirect_child_table = xcalloc(NRedirectors, sizeof(redirector_t *)); - debug(14, 1, "redirectOpenServers: Starting %d '%s' processes\n", + debug(29, 1, "redirectOpenServers: Starting %d '%s' processes\n", NRedirectors, prg); for (k = 0; k < NRedirectors; k++) { redirect_child_table[k] = xcalloc(1, sizeof(redirector_t)); if ((redirectsocket = redirectCreateRedirector(prg)) < 0) { - debug(14, 1, "WARNING: Cannot run '%s' process.\n", prg); + debug(29, 1, "WARNING: Cannot run '%s' process.\n", prg); redirect_child_table[k]->flags &= ~REDIRECT_FLAG_ALIVE; } else { redirect_child_table[k]->flags |= REDIRECT_FLAG_ALIVE; redirect_child_table[k]->index = k; redirect_child_table[k]->fd = redirectsocket; + redirect_child_table[k]->inbuf = get_free_4k_page(); + redirect_child_table[k]->size = 4096; + redirect_child_table[k]->offset = 0; sprintf(fd_note_buf, "%s #%d", prg, redirect_child_table[k]->index + 1); fd_note(redirect_child_table[k]->fd, fd_note_buf); commSetNonBlocking(redirect_child_table[k]->fd); - /* set handler for incoming result */ comm_set_select_handler(redirect_child_table[k]->fd, COMM_SELECT_READ, (PF) redirectHandleRead, (void *) redirect_child_table[k]); - debug(14, 3, "redirectOpenServers: 'redirect_server' %d started\n", + debug(29, 3, "redirectOpenServers: 'redirect_server' %d started\n", k); } } + if (first_time == 0) { + first_time++; + memset(&RedirectStats, '\0', sizeof(RedirectStats)); + } +} + +void redirectShutdownServers() +{ + redirector_t *redirect = NULL; + int k; + if (!do_redirect) + return; + for (k = 0; k < NRedirectors; k++) { + redirect = *(redirect_child_table + k); + if (!(redirect->flags & REDIRECT_FLAG_ALIVE)) + continue; + if (redirect->flags & REDIRECT_FLAG_BUSY) + continue; + if (redirect->flags & REDIRECT_FLAG_CLOSING) + continue; + debug(29, 3, "redirectShutdownServers: closing redirector #%d, FD %d\n", + redirect->index + 1, redirect->fd); + comm_close(redirect->fd); + redirect->flags |= REDIRECT_FLAG_CLOSING; + } } + int redirectUnregister(url, fd) char *url; int fd; { - return 0; + redirector_t *redirect = NULL; + redirectStateData *r = NULL; + struct redirectQueueData *rq = NULL; + int k; + int n = 0; + if (!do_redirect) + return 0; + debug(29, 3, "redirectUnregister: FD %d '%s'\n", fd, url); + for (k = 0; k < NRedirectors; k++) { + redirect = *(redirect_child_table + k); + if ((r = redirect->redirectState) == NULL) + continue; + if (r->fd != fd) + continue; + if (strcmp(r->orig_url, url)) + continue; + debug(29, 3, "redirectUnregister: Found match\n"); + r->handler = NULL; + n++; + } + for (rq = redirectQueueHead; rq; rq = rq->next) { + if ((r = rq->redirectState) == NULL) + continue; + if (r->fd != fd) + continue; + if (strcmp(r->orig_url, url)) + continue; + debug(29, 3, "redirectUnregister: Found match.\n"); + r->handler = NULL; + n++; + } + debug(29, 3, "redirectUnregister: Unregistered %d handlers\n", n); + return n; } -void redirectShutdownServers() +void redirectStats(sentry) + StoreEntry *sentry; { - redirector_t *redirector = NULL; int k; - static char *shutdown = "$shutdown\n"; - - debug(14, 3, "redirectShutdownServers:\n"); - - for (k = 0; k < getRedirectChildren(); k++) { - redirector = *(redirect_child_table + k); - debug(14, 3, "redirectShutdownServers: sending '$shutdown' to redirector #%d\n", k); - debug(14, 3, "redirectShutdownServers: --> FD %d\n", redirector->fd); - comm_write(redirector->fd, - xstrdup(shutdown), - strlen(shutdown), - 0, /* timeout */ - NULL, /* Handler */ - NULL); /* Handler-data */ - redirector->flags |= REDIRECT_FLAG_CLOSING; + storeAppendPrintf(sentry, open_bracket); + storeAppendPrintf(sentry, "{Redirector Statistics:}\n"); + storeAppendPrintf(sentry, "{requests: %d}\n", + RedirectStats.requests); + storeAppendPrintf(sentry, "{replies: %d}\n", + RedirectStats.replies); + storeAppendPrintf(sentry, "{queue length: %d}\n", + RedirectStats.queue_size); + storeAppendPrintf(sentry, "{avg service time: %d msec}\n", + RedirectStats.avg_svc_time); + storeAppendPrintf(sentry, "{number of redirectors: %d}\n", + NRedirectors); + storeAppendPrintf(sentry, "{use histogram:}\n"); + for (k = 0; k < NRedirectors; k++) { + storeAppendPrintf(sentry, "{ redirector #%d: %d}\n", + k + 1, + RedirectStats.use_hist[k]); } + storeAppendPrintf(sentry, close_bracket); } diff --git a/src/send-announce.cc b/src/send-announce.cc index 3a5ce5fb14..e3109ce986 100644 --- a/src/send-announce.cc +++ b/src/send-announce.cc @@ -1,5 +1,6 @@ + /* - * $Id: send-announce.cc,v 1.12 1996/07/09 03:41:37 wessels Exp $ + * $Id: send-announce.cc,v 1.13 1996/07/11 17:42:51 wessels Exp $ * * DEBUG: section 27 Cache Announcer * AUTHOR: Duane Wessels diff --git a/src/squid.h b/src/squid.h index 20c3be0a2f..0c67f7f613 100644 --- a/src/squid.h +++ b/src/squid.h @@ -1,6 +1,6 @@ /* - * $Id: squid.h,v 1.25 1996/07/09 04:47:23 wessels Exp $ + * $Id: squid.h,v 1.26 1996/07/11 17:42:53 wessels Exp $ * * AUTHOR: Duane Wessels * @@ -230,6 +230,7 @@ typedef void (*SIH) _PARAMS((int, void *)); /* swap in */ #include "acl.h" #include "util.h" #include "background.h" +#include "redirect.h" #if !HAVE_TEMPNAM #include "tempnam.h" @@ -258,6 +259,7 @@ extern char appname[]; /* main.c */ extern struct in_addr local_addr; /* main.c */ extern char localhost[]; extern struct in_addr any_addr; /* comm.c */ +extern int do_redirect; /* redirect.c */ /* Prototypes and definitions which don't really deserve a seaprate diff --git a/src/ssl.cc b/src/ssl.cc index 8481404c93..d48e7c5f0a 100644 --- a/src/ssl.cc +++ b/src/ssl.cc @@ -1,5 +1,5 @@ /* - * $Id: ssl.cc,v 1.4 1996/07/09 23:00:26 wessels Exp $ + * $Id: ssl.cc,v 1.5 1996/07/11 17:42:53 wessels Exp $ * * DEBUG: section 26 Secure Sockets Layer Proxy * AUTHOR: Duane Wessels @@ -216,11 +216,11 @@ static void sslWriteServer(fd, sslState) COMM_SELECT_READ, (PF) sslReadClient, (void *) sslState); - comm_set_select_handler_plus_timeout(sslState->server.fd, - COMM_SELECT_TIMEOUT, - (PF) sslReadTimeout, - (void *) sslState, - sslState->timeout); + comm_set_select_handler_plus_timeout(sslState->server.fd, + COMM_SELECT_TIMEOUT, + (PF) sslReadTimeout, + (void *) sslState, + sslState->timeout); } else { /* still have more to write */ comm_set_select_handler(sslState->server.fd, diff --git a/src/stat.cc b/src/stat.cc index 4ac1b75511..947a54cc75 100644 --- a/src/stat.cc +++ b/src/stat.cc @@ -1,5 +1,5 @@ /* - * $Id: stat.cc,v 1.37 1996/07/09 23:00:55 wessels Exp $ + * $Id: stat.cc,v 1.38 1996/07/11 17:42:54 wessels Exp $ * * DEBUG: section 18 Cache Manager Statistics * AUTHOR: Harvest Derived @@ -314,8 +314,8 @@ void stat_get(obj, req, sentry) stat_objects_get(obj, sentry, 1); } else if (strcmp(req, "general") == 0) { stat_ipcache_get(sentry); - } else if (strcmp(req, "general") == 0) { - stat_ipcache_get(sentry); + } else if (strcmp(req, "redirector") == 0) { + redirectStats(sentry); } else if (strcmp(req, "utilization") == 0) { stat_utilization_get(obj, sentry); } else if (strcmp(req, "io") == 0) { @@ -507,17 +507,17 @@ void info_get_mallstat(size, number, sentry) } #endif -static char *host_port_fmt (host, port) - char *host; - u_short port; +static char *host_port_fmt(host, port) + char *host; + u_short port; { - static char buf[32]; - sprintf (buf, "%s.%d", host, (int) port); - return buf; + static char buf[32]; + sprintf(buf, "%s.%d", host, (int) port); + return buf; } static void statFiledescriptors(sentry) - StoreEntry *sentry; + StoreEntry *sentry; { int i; int j; @@ -541,8 +541,8 @@ static void statFiledescriptors(sentry) continue; j = fdstatGetType(i); storeAppendPrintf(sentry, "{%4d %-6s ", - i, - fdstatTypeStr[j]); + i, + fdstatTypeStr[j]); switch (j) { case FD_SOCKET: if ((lft = comm_get_fd_lifetime(i)) < 0) @@ -612,8 +612,8 @@ void info_get(obj, sentry) storeAppendPrintf(sentry, "{\tNumber of UDP connections:\t%lu}\n", nudpconn); - f = squid_curtime - squid_starttime; - storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n", + f = squid_curtime - squid_starttime; + storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n", f == 0.0 ? 0.0 : ((ntcpconn + nudpconn) / (f / 3600))); storeAppendPrintf(sentry, "{Cache information for %s:}\n", diff --git a/src/tunnel.cc b/src/tunnel.cc index 779dd0402b..d8d4853583 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -1,5 +1,5 @@ /* - * $Id: tunnel.cc,v 1.4 1996/07/09 23:00:26 wessels Exp $ + * $Id: tunnel.cc,v 1.5 1996/07/11 17:42:53 wessels Exp $ * * DEBUG: section 26 Secure Sockets Layer Proxy * AUTHOR: Duane Wessels @@ -216,11 +216,11 @@ static void sslWriteServer(fd, sslState) COMM_SELECT_READ, (PF) sslReadClient, (void *) sslState); - comm_set_select_handler_plus_timeout(sslState->server.fd, - COMM_SELECT_TIMEOUT, - (PF) sslReadTimeout, - (void *) sslState, - sslState->timeout); + comm_set_select_handler_plus_timeout(sslState->server.fd, + COMM_SELECT_TIMEOUT, + (PF) sslReadTimeout, + (void *) sslState, + sslState->timeout); } else { /* still have more to write */ comm_set_select_handler(sslState->server.fd, -- 2.47.2