From: robertc <> Date: Sat, 22 Feb 2003 05:50:04 +0000 (+0000) Subject: Summary: Ran astyle over src subtree. X-Git-Tag: SQUID_3_0_PRE1~319 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=62e7632691c3b133845270bc31cdddd7e0018754;p=thirdparty%2Fsquid.git Summary: Ran astyle over src subtree. Keywords: Astyle is the formatter of choice for squid-3 C++ code. See http://www.squid-cache.org/~robertc/squid-3-style.txt for the squid 3 style conventions. --- diff --git a/src/ACL.h b/src/ACL.h index 5e9161bd1c..88fb506045 100644 --- a/src/ACL.h +++ b/src/ACL.h @@ -1,6 +1,6 @@ /* - * $Id: ACL.h,v 1.6 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACL.h,v 1.7 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -46,8 +46,11 @@ SQUIDCEXTERN void aclParseAccessLine(acl_access **); SQUIDCEXTERN void aclParseAclList(acl_list **); SQUIDCEXTERN int aclIsProxyAuth(const char *name); SQUIDCEXTERN err_type aclGetDenyInfoPage(acl_deny_info_list ** head, const char *name); + SQUIDCEXTERN void aclParseDenyInfoLine(struct _acl_deny_info_list **); + SQUIDCEXTERN void aclDestroyDenyInfoList(struct _acl_deny_info_list **); + SQUIDCEXTERN void aclDestroyRegexList(struct _relist *data); SQUIDCEXTERN int aclMatchRegex(relist * data, const char *word); wordlist *aclDumpRegexList(relist * data); @@ -57,8 +60,10 @@ SQUIDCEXTERN int aclPurgeMethodInUse(acl_access *); SQUIDCEXTERN void aclCacheMatchFlush(dlink_list * cache); extern void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head); -class ACL { - public: +class ACL +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -77,6 +82,7 @@ class ACL { virtual void parse(); virtual char const *typeString() const; virtual squid_acl aclType() const { return type;} + virtual bool isProxyAuth() const; virtual bool requiresRequest() const; virtual int match(ACLChecklist * checklist); @@ -84,46 +90,56 @@ class ACL { virtual wordlist *dump() const; virtual bool valid () const; int checklistMatches(ACLChecklist *); - + /* only relevant to METHOD acl's */ virtual bool containsPURGE() const; /* only relecant to ASN acl's */ void startCache(); - + int cacheMatchAcl(dlink_list * cache, ACLChecklist *); virtual int matchForCache(ACLChecklist *checklist); char name[ACL_NAME_SZ]; char *cfgline; ACL *next; - private: + +private: static MemPool *Pool; squid_acl type; - protected: + +protected: void *data; - public: - class Prototype { - public: - Prototype (); - Prototype (ACL const *, char const *); - ~Prototype(); - static bool Registered(char const *); - static ACL *Factory (char const *); - private: - ACL const*prototype; - char const *typeString; - private: - static Vector * Registry; - static void *Initialized; - typedef Vector::iterator iterator; - typedef Vector::const_iterator const_iterator; - void registerMe(); + +public: + + class Prototype + { + + public: + Prototype (); + Prototype (ACL const *, char const *); + ~Prototype(); + static bool Registered(char const *); + static ACL *Factory (char const *); + + private: + ACL const*prototype; + char const *typeString; + + private: + static Vector * Registry; + static void *Initialized; + typedef Vector::iterator iterator; + typedef Vector::const_iterator const_iterator; + void registerMe(); }; }; -class acl_access { - public: +class acl_access +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -132,12 +148,15 @@ class acl_access { acl_list *aclList; char *cfgline; acl_access *next; - private: + +private: CBDATA_CLASS(acl_access); }; -class ACLList { - public: +class ACLList +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -148,7 +167,8 @@ class ACLList { int op; acl *_acl; ACLList *next; - private: + +private: static MemPool *Pool; }; diff --git a/src/ACLASN.h b/src/ACLASN.h index 67c8f79078..18875ceac2 100644 --- a/src/ACLASN.h +++ b/src/ACLASN.h @@ -1,6 +1,6 @@ /* - * $Id: ACLASN.h,v 1.1 2003/02/16 02:23:18 robertc Exp $ + * $Id: ACLASN.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -38,12 +38,16 @@ #include "ACLChecklist.h" #include "ACLIP.h" -class ASNLookup : public ACLChecklist::AsyncState { - public: +class ASNLookup : public ACLChecklist::AsyncState +{ + +public: static ASNLookup *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static ASNLookup instance_; static IPH LookupDone; }; + #endif /* SQUID_ACLASN_H */ diff --git a/src/ACLBrowser.h b/src/ACLBrowser.h index a8005dac9c..335752ed6e 100644 --- a/src/ACLBrowser.h +++ b/src/ACLBrowser.h @@ -1,6 +1,6 @@ /* - * $Id: ACLBrowser.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLBrowser.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,8 +40,10 @@ #include "ACLRequestHeaderStrategy.h" #include "ACLStrategised.h" -class ACLBrowser { - private: +class ACLBrowser +{ + +private: static ACL::Prototype RegistryProtoype; static ACLStrategised RegistryEntry_; }; diff --git a/src/ACLCertificate.h b/src/ACLCertificate.h index 63dbff62d0..f853ea743f 100644 --- a/src/ACLCertificate.h +++ b/src/ACLCertificate.h @@ -1,6 +1,6 @@ /* - * $Id: ACLCertificate.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLCertificate.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -43,22 +43,28 @@ class ACLCertificateStrategy : public ACLMatchStrategy { - public: + +public: virtual int match (ACLData * &, ACLChecklist *); static ACLCertificateStrategy *Instance(); /* Not implemented to prevent copies of the instance. */ /* Not private to prevent brain dead g+++ warnings about * private constructors with no friends */ ACLCertificateStrategy(ACLCertificateStrategy const &); - private: + +private: static ACLCertificateStrategy Instance_; ACLCertificateStrategy(){} + ACLCertificateStrategy&operator=(ACLCertificateStrategy const &); }; -class ACLCertificate { - public: - private: +class ACLCertificate +{ + +public: + +private: static ACL::Prototype UserRegistryProtoype; static ACLStrategised UserRegistryEntry_; static ACL::Prototype CARegistryProtoype; diff --git a/src/ACLCertificateData.cc b/src/ACLCertificateData.cc index 89ecd57bf8..1c40d5e22b 100644 --- a/src/ACLCertificateData.cc +++ b/src/ACLCertificateData.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLCertificateData.cc,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLCertificateData.cc,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -45,8 +45,10 @@ ACLCertificateData::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLCertificateData)); + if (!Pool) - Pool = memPoolCreate("ACLCertificateData", sizeof (ACLCertificateData)); + Pool = memPoolCreate("ACLCertificateData", sizeof (ACLCertificateData)); + return memPoolAlloc(Pool); } @@ -64,14 +66,14 @@ ACLCertificateData::deleteSelf() const ACLCertificateData::ACLCertificateData(SSLGETATTRIBUTE *sslStrategy) : attribute (NULL), values (NULL), sslAttributeCall (sslStrategy) -{ -} +{} ACLCertificateData::ACLCertificateData(ACLCertificateData const &old) : attribute (NULL), values (NULL), sslAttributeCall (old.sslAttributeCall) { assert (!old.values); + if (old.attribute) - attribute = xstrdup (old.attribute); + attribute = xstrdup (old.attribute); } template @@ -84,9 +86,10 @@ xRefFree(T &thing) ACLCertificateData::~ACLCertificateData() { safe_free (attribute); + if (values) - values->destroy(xRefFree); -} + values->destroy(xRefFree); +} template inline int @@ -106,15 +109,20 @@ bool ACLCertificateData::match(SSL *ssl) { if (!ssl) - return 0; - + return 0; + char const *value = sslAttributeCall(ssl, attribute); + if (value == NULL) - return 0; + return 0; + debug(28, 3) ("aclMatchCertificateList: checking '%s'\n", value); + values = values->splay((char *)value, splaystrcmp); + debug(28, 3) ("aclMatchCertificateList: '%s' %s\n", - value, splayLastResult ? "NOT found" : "found"); + value, splayLastResult ? "NOT found" : "found"); + return !splayLastResult; } @@ -142,17 +150,21 @@ void ACLCertificateData::parse() { char *newAttribute = strtokFile(); + if (!newAttribute) - self_destruct(); + self_destruct(); + /* an acl must use consistent attributes in all config lines */ if (attribute) { - if (strcasecmp(newAttribute, attribute) != 0) - self_destruct(); + if (strcasecmp(newAttribute, attribute) != 0) + self_destruct(); } else - attribute = xstrdup(newAttribute); + attribute = xstrdup(newAttribute); + char *t; + while ((t = strtokFile())) { - values = values->insert(xstrdup(t), splaystrcmp); + values = values->insert(xstrdup(t), splaystrcmp); } } diff --git a/src/ACLCertificateData.h b/src/ACLCertificateData.h index 6c24c15b87..0cd302429d 100644 --- a/src/ACLCertificateData.h +++ b/src/ACLCertificateData.h @@ -1,6 +1,6 @@ /* - * $Id: ACLCertificateData.h,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLCertificateData.h,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,8 +40,10 @@ #include "ACLData.h" #include "ssl_support.h" -class ACLCertificateData : public ACLData { - public: +class ACLCertificateData : public ACLData +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -54,10 +56,11 @@ class ACLCertificateData : public ACLData { wordlist *dump(); void parse(); virtual ACLData *clone() const; - + char *attribute; SplayNode *values; - private: + +private: static MemPool *Pool; SSLGETATTRIBUTE *sslAttributeCall; }; diff --git a/src/ACLChecklist.cc b/src/ACLChecklist.cc index d9389c88f8..b955a31c59 100644 --- a/src/ACLChecklist.cc +++ b/src/ACLChecklist.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLChecklist.cc,v 1.6 2003/02/21 12:02:30 robertc Exp $ + * $Id: ACLChecklist.cc,v 1.7 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -43,44 +43,53 @@ int ACLChecklist::authenticated() { http_hdr_type headertype; + if (NULL == request) { - fatal ("requiresRequest SHOULD have been true for this ACL!!"); - return 0; + fatal ("requiresRequest SHOULD have been true for this ACL!!"); + return 0; } else if (!request->flags.accelerated) { - /* Proxy authorization on proxy requests */ - headertype = HDR_PROXY_AUTHORIZATION; + /* Proxy authorization on proxy requests */ + headertype = HDR_PROXY_AUTHORIZATION; } else if (request->flags.internal) { - /* WWW authorization on accelerated internal requests */ - headertype = HDR_AUTHORIZATION; + /* WWW authorization on accelerated internal requests */ + headertype = HDR_AUTHORIZATION; } else { #if AUTH_ON_ACCELERATION - /* WWW authorization on accelerated requests */ - headertype = HDR_AUTHORIZATION; + /* WWW authorization on accelerated requests */ + headertype = HDR_AUTHORIZATION; #else - debug(28, 1) ("ACHChecklist::authenticated: authentication not applicable on accelerated requests.\n"); - return -1; + + debug(28, 1) ("ACHChecklist::authenticated: authentication not applicable on accelerated requests.\n"); + return -1; #endif + } + /* get authed here */ /* Note: this fills in auth_user_request when applicable */ switch (authenticateTryToAuthenticateAndSetAuthUser(&auth_user_request, headertype, request, conn(), src_addr)) { + case AUTH_ACL_CANNOT_AUTHENTICATE: - debug(28, 4) ("aclMatchAcl: returning 0 user authenticated but not authorised.\n"); - return 0; + debug(28, 4) ("aclMatchAcl: returning 0 user authenticated but not authorised.\n"); + return 0; + case AUTH_AUTHENTICATED: - return 1; - break; + return 1; + break; + case AUTH_ACL_HELPER: - debug(28, 4) ("aclMatchAcl: returning 0 sending credentials to helper.\n"); - changeState (ProxyAuthLookup::Instance()); - return 0; + debug(28, 4) ("aclMatchAcl: returning 0 sending credentials to helper.\n"); + changeState (ProxyAuthLookup::Instance()); + return 0; + case AUTH_ACL_CHALLENGE: - debug(28, 4) ("aclMatchAcl: returning 0 sending authentication challenge.\n"); - changeState (ProxyAuthNeeded::Instance()); - return 0; + debug(28, 4) ("aclMatchAcl: returning 0 sending authentication challenge.\n"); + changeState (ProxyAuthNeeded::Instance()); + return 0; + default: - fatal("unexpected authenticateAuthenticate reply\n"); - return 0; + fatal("unexpected authenticateAuthenticate reply\n"); + return 0; } } @@ -95,58 +104,68 @@ ACLChecklist::currentAnswer(allow_t const newAnswer) { allow_ = newAnswer; } - + void ACLChecklist::check() { if (checking()) - return; + return; + /* deny if no rules present */ currentAnswer(ACCESS_DENIED); + /* NOTE: This holds a cbdata reference to the current access_list * entry, not the whole list. */ while (accessList != NULL) { - /* - * If the _acl_access is no longer valid (i.e. its been - * freed because of a reconfigure), then bail on this - * access check. For now, return ACCESS_DENIED. - */ - if (!cbdataReferenceValid(accessList)) { - cbdataReferenceDone(accessList); - debug (28,4)("ACLChecklist::check: %p accessList is invalid\n", this); - continue; - } - - checking (true); - checkAccessList(); - checking (false); - if (asyncInProgress()) { - return; - } - - if (finished()) { - /* - * We are done. Either the request - * is allowed, denied, requires authentication. - */ - debug(28, 3) ("ACLChecklist::check: %p match found, calling back with %d\n", this, currentAnswer()); - cbdataReferenceDone(accessList); /* A */ - checkCallback(currentAnswer()); - /* From here on in, this may be invalid */ - return; - } - /* - * Reference the next access entry - */ - const acl_access *A = accessList; - assert (A); - accessList = cbdataReference(A->next); - cbdataReferenceDone(A); + /* + * If the _acl_access is no longer valid (i.e. its been + * freed because of a reconfigure), then bail on this + * access check. For now, return ACCESS_DENIED. + */ + + if (!cbdataReferenceValid(accessList)) { + cbdataReferenceDone(accessList); + debug (28,4)("ACLChecklist::check: %p accessList is invalid\n", this); + continue; + } + + checking (true); + checkAccessList(); + checking (false); + + if (asyncInProgress()) { + return; + } + + if (finished()) { + /* + * We are done. Either the request + * is allowed, denied, requires authentication. + */ + debug(28, 3) ("ACLChecklist::check: %p match found, calling back with %d\n", this, currentAnswer()); + cbdataReferenceDone(accessList); /* A */ + checkCallback(currentAnswer()); + /* From here on in, this may be invalid */ + return; + } + + /* + * Reference the next access entry + */ + const acl_access *A = accessList; + + assert (A); + + accessList = cbdataReference(A->next); + + cbdataReferenceDone(A); } + /* dropped off the end of the list */ debug(28, 3) ("ACLChecklist::check: %p NO match found, returning %d\n", this, - currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED); + currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED); + checkCallback(currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED); } @@ -186,10 +205,11 @@ ACLChecklist::checkAccessList() currentAnswer(accessList->allow); /* does the current AND clause match */ bool match = matchAclList(accessList->aclList); + if (match) - markFinished(); + markFinished(); else - checkForAsync(); + checkForAsync(); } void @@ -206,37 +226,47 @@ ACLChecklist::checkCallback(allow_t answer) debug(28, 3) ("ACLChecklist::checkCallback: %p answer=%d\n", this, answer); /* During reconfigure, we can end up not finishing call * sequences into the auth code */ + if (auth_user_request) { - /* the checklist lock */ - authenticateAuthUserRequestUnlock(auth_user_request); - /* it might have been connection based */ - assert(conn()); - conn()->auth_user_request = NULL; - conn()->auth_type = AUTH_BROKEN; - auth_user_request = NULL; + /* the checklist lock */ + authenticateAuthUserRequestUnlock(auth_user_request); + /* it might have been connection based */ + assert(conn()); + conn()->auth_user_request = NULL; + conn()->auth_type = AUTH_BROKEN; + auth_user_request = NULL; } + callback_ = callback; callback = NULL; + if (cbdataReferenceValidDone(callback_data, &cbdata_)) - callback_(answer, cbdata_); + callback_(answer, cbdata_); + delete this; } + bool ACLChecklist::matchAclList(const acl_list * head, bool const fast) { PROF_start(aclMatchAclList); const acl_list *node = head; + while (node) { - bool nodeMatched = node->matches(this); - if (fast) - changeState(NullState::Instance()); - if (!nodeMatched || state_ != NullState::Instance()) { - debug(28, 3) ("aclmatchAclList: %p returning false (AND list entry failed to match)\n", this); - PROF_stop(aclMatchAclList); - return false; - } - node = node->next; + bool nodeMatched = node->matches(this); + + if (fast) + changeState(NullState::Instance()); + + if (!nodeMatched || state_ != NullState::Instance()) { + debug(28, 3) ("aclmatchAclList: %p returning false (AND list entry failed to match)\n", this); + PROF_stop(aclMatchAclList); + return false; + } + + node = node->next; } + debug(28, 3) ("aclmatchAclList: %p returning true (AND list satisfied)\n", this); PROF_stop(aclMatchAclList); return true; @@ -255,7 +285,7 @@ ACLChecklist::operator new (size_t size) cbdataReference(result); return result; } - + void ACLChecklist::operator delete (void *address) { @@ -272,24 +302,27 @@ ACLChecklist::deleteSelf() const } ACLChecklist::ACLChecklist() : accessList (NULL), my_port (0), request (NULL), - reply (NULL), - auth_user_request (NULL) + reply (NULL), + auth_user_request (NULL) #if SQUID_SNMP - ,snmp_community(NULL) + ,snmp_community(NULL) #endif - , callback (NULL), - callback_data (NULL), - extacl_entry (NULL), - conn_(NULL), - async_(false), - finished_(false), - allow_(ACCESS_DENIED), - state_(NullState::Instance()), - destinationDomainChecked_(false), - sourceDomainChecked_(false) + , callback (NULL), + callback_data (NULL), + extacl_entry (NULL), + conn_(NULL), + async_(false), + finished_(false), + allow_(ACCESS_DENIED), + state_(NullState::Instance()), + destinationDomainChecked_(false), + sourceDomainChecked_(false) { + memset (&src_addr, '\0', sizeof (struct in_addr)); + memset (&dst_addr, '\0', sizeof (struct in_addr)); + memset (&my_addr, '\0', sizeof (struct in_addr)); rfc931[0] = '\0'; memset (&state, '\0', sizeof (state)); @@ -298,13 +331,19 @@ ACLChecklist::ACLChecklist() : accessList (NULL), my_port (0), request (NULL), ACLChecklist::~ACLChecklist() { assert (!asyncInProgress()); + if (extacl_entry) - cbdataReferenceDone(extacl_entry); + cbdataReferenceDone(extacl_entry); + if (request) - requestUnlink(request); + requestUnlink(request); + request = NULL; + cbdataReferenceDone(conn_); + cbdataReferenceDone(accessList); + debug (28,4)("ACLChecklist::~ACLChecklist: destroyed %p\n", this); } @@ -336,8 +375,7 @@ ACLChecklist::NullState::Instance() void ACLChecklist::NullState::checkForAsync(ACLChecklist *) const -{ -} + {} ACLChecklist::NullState ACLChecklist::NullState::_instance; diff --git a/src/ACLChecklist.h b/src/ACLChecklist.h index d955127806..b8291cb61c 100644 --- a/src/ACLChecklist.h +++ b/src/ACLChecklist.h @@ -1,6 +1,6 @@ /* - * $Id: ACLChecklist.h,v 1.6 2003/02/21 12:02:30 robertc Exp $ + * $Id: ACLChecklist.h,v 1.7 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,8 +36,10 @@ #include "typedefs.h" -class ACLChecklist { - public: +class ACLChecklist +{ + +public: /* State class. * This abstract class defines the behaviour of @@ -52,22 +54,28 @@ class ACLChecklist { * refcounted objects. */ - class AsyncState { - public: - virtual void checkForAsync(ACLChecklist *) const = 0; - protected: - void changeState (ACLChecklist *, AsyncState *) const; + class AsyncState + { + + public: + virtual void checkForAsync(ACLChecklist *) const = 0; + + protected: + void changeState (ACLChecklist *, AsyncState *) const; }; - class NullState : public AsyncState { - public: - static NullState *Instance(); - virtual void checkForAsync(ACLChecklist *) const; - private: - static NullState _instance; +class NullState : public AsyncState + { + + public: + static NullState *Instance(); + virtual void checkForAsync(ACLChecklist *) const; + + private: + static NullState _instance; }; - - + + void *operator new(size_t); void operator delete(void *); void deleteSelf() const; @@ -96,10 +104,13 @@ class ACLChecklist { void checkForAsync(); void changeState (AsyncState *); AsyncState *asyncState() const; - + const acl_access *accessList; + struct in_addr src_addr; + struct in_addr dst_addr; + struct in_addr my_addr; unsigned short my_port; request_t *request; @@ -109,8 +120,10 @@ class ACLChecklist { auth_user_request_t *auth_user_request; acl_lookup_state state[ACL_ENUM_MAX]; #if SQUID_SNMP + char *snmp_community; #endif + PF *callback; void *callback_data; external_acl_entry *extacl_entry; @@ -118,6 +131,7 @@ class ACLChecklist { void markDestinationDomainChecked(); bool sourceDomainChecked() const; void markSourceDomainChecked(); + private: CBDATA_CLASS(ACLChecklist); ConnStateData *conn_; /* hack for ident and NTLM */ @@ -133,8 +147,8 @@ private: }; SQUIDCEXTERN ACLChecklist *aclChecklistCreate(const acl_access *, - request_t *, - const char *ident); + request_t *, + const char *ident); SQUIDCEXTERN int aclCheckFast(const acl_access *A, ACLChecklist *); #endif /* SQUID_ACLCHECKLIST_H */ diff --git a/src/ACLData.h b/src/ACLData.h index 2310a82a21..a02f589443 100644 --- a/src/ACLData.h +++ b/src/ACLData.h @@ -1,6 +1,6 @@ /* - * $Id: ACLData.h,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLData.h,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,11 +37,15 @@ #define SQUID_ACLDATA_H template -class ACLData { - public: + +class ACLData +{ + +public: virtual void deleteSelf() const =0; virtual ~ACLData() {} + virtual bool match(M) =0; virtual wordlist *dump() =0; virtual void parse() =0; diff --git a/src/ACLDestinationDomain.cc b/src/ACLDestinationDomain.cc index 95450b945c..fab9519dfa 100644 --- a/src/ACLDestinationDomain.cc +++ b/src/ACLDestinationDomain.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLDestinationDomain.cc,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLDestinationDomain.cc,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -47,8 +47,10 @@ ACLDestinationDomain::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLDestinationDomain)); + if (!Pool) - Pool = memPoolCreate("ACLDestinationDomain", sizeof (ACLDestinationDomain)); + Pool = memPoolCreate("ACLDestinationDomain", sizeof (ACLDestinationDomain)); + return memPoolAlloc(Pool); } @@ -70,9 +72,10 @@ ACLDestinationDomain::~ACLDestinationDomain() } ACLDestinationDomain::ACLDestinationDomain(ACLData *newData, char const *theType) : data (newData), type_(theType) {} + ACLDestinationDomain::ACLDestinationDomain (ACLDestinationDomain const &old) : data (old.data->clone()), type_(old.type_) -{ -} +{} + ACLDestinationDomain & ACLDestinationDomain::operator= (ACLDestinationDomain const &rhs) { @@ -97,18 +100,24 @@ int ACLDestinationDomain::match(ACLChecklist *checklist) { const ipcache_addrs *ia = NULL; + if ((ia = ipcacheCheckNumeric(checklist->request->host)) == NULL) - return data->match(checklist->request->host); + return data->match(checklist->request->host); + const char *fqdn = NULL; + fqdn = fqdncache_gethostbyaddr(ia->in_addrs[0], FQDN_LOOKUP_IF_MISS); + if (fqdn) - return data->match(fqdn); + return data->match(fqdn); + if (!checklist->destinationDomainChecked()) { - debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - name, inet_ntoa(ia->in_addrs[0])); - checklist->changeState(DestinationDomainLookup::Instance()); - return 0; + debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", + name, inet_ntoa(ia->in_addrs[0])); + checklist->changeState(DestinationDomainLookup::Instance()); + return 0; } + return data->match("none"); } @@ -138,15 +147,16 @@ DestinationDomainLookup::checkForAsync(ACLChecklist *checklist)const ipcache_addrs *ia; ia = ipcacheCheckNumeric(checklist->request->host); + if (ia == NULL) { - /* Make fatal? XXX this is checked during match() */ - checklist->markDestinationDomainChecked(); - checklist->changeState (ACLChecklist::NullState::Instance()); + /* Make fatal? XXX this is checked during match() */ + checklist->markDestinationDomainChecked(); + checklist->changeState (ACLChecklist::NullState::Instance()); } else { - checklist->asyncInProgress(true); - checklist->dst_addr = ia->in_addrs[0]; - fqdncache_nbgethostbyaddr(checklist->dst_addr, - LookupDone, checklist); + checklist->asyncInProgress(true); + checklist->dst_addr = ia->in_addrs[0]; + fqdncache_nbgethostbyaddr(checklist->dst_addr, + LookupDone, checklist); } } diff --git a/src/ACLDestinationDomain.h b/src/ACLDestinationDomain.h index 062e3eab80..c38706e52b 100644 --- a/src/ACLDestinationDomain.h +++ b/src/ACLDestinationDomain.h @@ -1,6 +1,6 @@ /* - * $Id: ACLDestinationDomain.h,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLDestinationDomain.h,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -39,17 +39,22 @@ #include "ACLData.h" #include "ACLChecklist.h" -class DestinationDomainLookup : public ACLChecklist::AsyncState { - public: +class DestinationDomainLookup : public ACLChecklist::AsyncState +{ + +public: static DestinationDomainLookup *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static DestinationDomainLookup instance_; static void LookupDone(const char *, void *); }; -class ACLDestinationDomain : public ACL { - public: +class ACLDestinationDomain : public ACL +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -58,16 +63,19 @@ class ACLDestinationDomain : public ACL { ACLDestinationDomain(ACLData *, char const *); ACLDestinationDomain (ACLDestinationDomain const &); ACLDestinationDomain &operator= (ACLDestinationDomain const &); - + virtual char const *typeString() const; virtual squid_acl aclType() const { return ACL_DERIVED;} + virtual void parse(); virtual int match(ACLChecklist *checklist); virtual wordlist *dump() const; virtual bool valid () const; virtual bool requiresRequest() const {return true;} + virtual ACL *clone()const; - private: + +private: static MemPool *Pool; static Prototype LiteralRegistryProtoype; static Prototype LegacyRegistryProtoype; diff --git a/src/ACLDestinationIP.cc b/src/ACLDestinationIP.cc index e3a282ad0d..000aa528e2 100644 --- a/src/ACLDestinationIP.cc +++ b/src/ACLDestinationIP.cc @@ -43,8 +43,10 @@ ACLDestinationIP::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLDestinationIP)); + if (!Pool) - Pool = memPoolCreate("ACLDestinationIP", sizeof (ACLDestinationIP)); + Pool = memPoolCreate("ACLDestinationIP", sizeof (ACLDestinationIP)); + return memPoolAlloc(Pool); } @@ -70,21 +72,24 @@ int ACLDestinationIP::match(ACLChecklist *checklist) { const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->host, IP_LOOKUP_IF_MISS); + if (ia) { - /* Entry in cache found */ - for (int k = 0; k < (int) ia->count; k++) { - if (ACLIP::match(ia->in_addrs[k])) - return 1; - } - return 0; + /* Entry in cache found */ + + for (int k = 0; k < (int) ia->count; k++) { + if (ACLIP::match(ia->in_addrs[k])) + return 1; + } + + return 0; } else if (!checklist->request->flags.destinationIPLookedUp()) { - /* No entry in cache, lookup not attempted */ - debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - name, checklist->request->host); - checklist->changeState (DestinationIPLookup::Instance()); - return 0; + /* No entry in cache, lookup not attempted */ + debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", + name, checklist->request->host); + checklist->changeState (DestinationIPLookup::Instance()); + return 0; } else { - return ACLIP::match(no_addr); + return ACLIP::match(no_addr); } } diff --git a/src/ACLDestinationIP.h b/src/ACLDestinationIP.h index 2f612c1404..3693aae671 100644 --- a/src/ACLDestinationIP.h +++ b/src/ACLDestinationIP.h @@ -38,27 +38,35 @@ #include "ACLChecklist.h" #include "ACLIP.h" -class DestinationIPLookup : public ACLChecklist::AsyncState { - public: +class DestinationIPLookup : public ACLChecklist::AsyncState +{ + +public: static DestinationIPLookup *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static DestinationIPLookup instance_; static IPH LookupDone; }; -class ACLDestinationIP : public ACLIP { - public: +class ACLDestinationIP : public ACLIP +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; virtual char const *typeString() const; virtual squid_acl aclType() const { return ACL_DERIVED;} + virtual int match(ACLChecklist *checklist); virtual bool requiresRequest() const {return true;} + virtual ACL *clone()const; - private: + +private: static MemPool *Pool; static Prototype RegistryProtoype; static ACLDestinationIP RegistryEntry_; diff --git a/src/ACLDomainData.cc b/src/ACLDomainData.cc index cb0684a7b6..0968cfa952 100644 --- a/src/ACLDomainData.cc +++ b/src/ACLDomainData.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLDomainData.cc,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLDomainData.cc,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -45,8 +45,10 @@ ACLDomainData::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLDomainData)); + if (!Pool) - Pool = memPoolCreate("ACLDomainData", sizeof (ACLDomainData)); + Pool = memPoolCreate("ACLDomainData", sizeof (ACLDomainData)); + return memPoolAlloc(Pool); } @@ -72,8 +74,8 @@ xRefFree(T &thing) ACLDomainData::~ACLDomainData() { if (domains) - domains->destroy(xRefFree); -} + domains->destroy(xRefFree); +} template inline int @@ -102,17 +104,20 @@ aclDomainCompare(T const &a, T const &b) char * const d2 = (char *const )a; int ret; ret = aclHostDomainCompare(d1, d2); + if (ret != 0) { - char *const d3 = d2; - char *const d4 = d1; - ret = aclHostDomainCompare(d3, d4); + char *const d3 = d2; + char *const d4 = d1; + ret = aclHostDomainCompare(d3, d4); } + /* FIXME this warning may display d1 and d2 when it should display d3 and d4 */ if (ret == 0) { - debug(28, 0) ("WARNING: '%s' is a subdomain of '%s'\n", d1, d2); - debug(28, 0) ("WARNING: because of this '%s' is ignored to keep splay tree searching predictable\n", (char *) a); - debug(28, 0) ("WARNING: You should probably remove '%s' from the ACL named '%s'\n", d1, AclMatchedName); + debug(28, 0) ("WARNING: '%s' is a subdomain of '%s'\n", d1, d2); + debug(28, 0) ("WARNING: because of this '%s' is ignored to keep splay tree searching predictable\n", (char *) a); + debug(28, 0) ("WARNING: You should probably remove '%s' from the ACL named '%s'\n", d1, AclMatchedName); } + return ret; } @@ -131,11 +136,15 @@ bool ACLDomainData::match(char const *host) { if (host == NULL) - return 0; + return 0; + debug(28, 3) ("aclMatchDomainList: checking '%s'\n", host); + domains = domains->splay((char *)host, aclHostDomainCompare); + debug(28, 3) ("aclMatchDomainList: '%s' %s\n", - host, splayLastResult ? "NOT found" : "found"); + host, splayLastResult ? "NOT found" : "found"); + return !splayLastResult; } @@ -162,9 +171,10 @@ void ACLDomainData::parse() { char *t = NULL; + while ((t = strtokFile())) { - Tolower(t); - domains = domains->insert(xstrdup(t), aclDomainCompare); + Tolower(t); + domains = domains->insert(xstrdup(t), aclDomainCompare); } } diff --git a/src/ACLDomainData.h b/src/ACLDomainData.h index 1bae5773c3..196ff89706 100644 --- a/src/ACLDomainData.h +++ b/src/ACLDomainData.h @@ -1,6 +1,6 @@ /* - * $Id: ACLDomainData.h,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLDomainData.h,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -39,8 +39,10 @@ #include "ACL.h" #include "ACLData.h" -class ACLDomainData : public ACLData { - public: +class ACLDomainData : public ACLData +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -50,9 +52,10 @@ class ACLDomainData : public ACLData { wordlist *dump(); void parse(); virtual ACLData *clone() const; - + SplayNode *domains; - private: + +private: static MemPool *Pool; }; diff --git a/src/ACLIP.cc b/src/ACLIP.cc index 1cf8f451a7..20e2413a37 100644 --- a/src/ACLIP.cc +++ b/src/ACLIP.cc @@ -57,11 +57,15 @@ ACLIP::DumpIpListWalkee(acl_ip_data * const & ip, void *state) wordlist **W = static_cast(state); memBufDefInit(&mb); memBufPrintf(&mb, "%s", inet_ntoa(ip->addr1)); + if (ip->addr2.s_addr != any_addr.s_addr) - memBufPrintf(&mb, "-%s", inet_ntoa(ip->addr2)); + memBufPrintf(&mb, "-%s", inet_ntoa(ip->addr2)); + if (ip->mask.s_addr != no_addr.s_addr) - memBufPrintf(&mb, "/%s", inet_ntoa(ip->mask)); + memBufPrintf(&mb, "/%s", inet_ntoa(ip->mask)); + wordlistAdd(W, mb.buf); + memBufClean(&mb); } @@ -76,14 +80,17 @@ acl_ip_data::toStr(char *buf, int len) const char b2[20]; char b3[20]; snprintf(b1, 20, "%s", inet_ntoa(addr1)); + if (addr2.s_addr != any_addr.s_addr) - snprintf(b2, 20, "-%s", inet_ntoa(addr2)); + snprintf(b2, 20, "-%s", inet_ntoa(addr2)); else - b2[0] = '\0'; + b2[0] = '\0'; + if (mask.s_addr != no_addr.s_addr) - snprintf(b3, 20, "/%s", inet_ntoa(mask)); + snprintf(b3, 20, "/%s", inet_ntoa(mask)); else - b3[0] = '\0'; + b3[0] = '\0'; + snprintf(buf, len, "%s%s%s", b1, b2, b3); } @@ -104,24 +111,30 @@ acl_ip_data::toStr(char *buf, int len) const int aclIpAddrNetworkCompare(acl_ip_data * const &p, acl_ip_data * const &q) { + struct in_addr A = p->addr1; + const struct in_addr B = q->addr1; + const struct in_addr C = q->addr2; A.s_addr &= q->mask.s_addr; /* apply netmask */ + if (C.s_addr == 0) { /* single address check */ - if (ntohl(A.s_addr) > ntohl(B.s_addr)) - return 1; - else if (ntohl(A.s_addr) < ntohl(B.s_addr)) - return -1; - else - return 0; + + if (ntohl(A.s_addr) > ntohl(B.s_addr)) + return 1; + else if (ntohl(A.s_addr) < ntohl(B.s_addr)) + return -1; + else + return 0; } else { /* range address check */ - if (ntohl(A.s_addr) > ntohl(C.s_addr)) - return 1; - else if (ntohl(A.s_addr) < ntohl(B.s_addr)) - return -1; - else - return 0; + + if (ntohl(A.s_addr) > ntohl(C.s_addr)) + return 1; + else if (ntohl(A.s_addr) < ntohl(B.s_addr)) + return -1; + else + return 0; } } @@ -137,24 +150,27 @@ acl_ip_data::NetworkCompare(acl_ip_data * const & a, acl_ip_data * const &b) { int ret; ret = aclIpAddrNetworkCompare(b, a); + if (ret != 0) { - ret = aclIpAddrNetworkCompare(a, b); + ret = aclIpAddrNetworkCompare(a, b); } + if (ret == 0) { - char buf_n1[60]; - char buf_n2[60]; - char buf_a[60]; - b->toStr(buf_n1, 60); - a->toStr(buf_n2, 60); - a->toStr(buf_a, 60); - /* TODO: this warning may display the wrong way around */ - debug(28, 0) ("WARNING: '%s' is a subnetwork of " - "'%s'\n", buf_n1, buf_n2); - debug(28, 0) ("WARNING: because of this '%s' is ignored " - "to keep splay tree searching predictable\n", buf_a); - debug(28, 0) ("WARNING: You should probably remove '%s' " - "from the ACL named '%s'\n", buf_n1, AclMatchedName); + char buf_n1[60]; + char buf_n2[60]; + char buf_a[60]; + b->toStr(buf_n1, 60); + a->toStr(buf_n2, 60); + a->toStr(buf_a, 60); + /* TODO: this warning may display the wrong way around */ + debug(28, 0) ("WARNING: '%s' is a subnetwork of " + "'%s'\n", buf_n1, buf_n2); + debug(28, 0) ("WARNING: because of this '%s' is ignored " + "to keep splay tree searching predictable\n", buf_a); + debug(28, 0) ("WARNING: You should probably remove '%s' " + "from the ACL named '%s'\n", buf_n1, AclMatchedName); } + return ret; } @@ -164,43 +180,54 @@ acl_ip_data::NetworkCompare(acl_ip_data * const & a, acl_ip_data * const &b) * This function should NOT be called if 'asc' is a hostname! */ bool + acl_ip_data::DecodeAddress(const char *asc, struct in_addr *addr, struct in_addr *mask) { u_int32_t a; int a1 = 0, a2 = 0, a3 = 0, a4 = 0; - switch (sscanf(asc, "%d.%d.%d.%d", &a1, &a2, &a3, &a4)) { + switch (sscanf(asc, "%d.%d.%d.%d", &a1, &a2, &a3, &a4)) + { + case 4: /* a dotted quad */ - if (!safe_inet_addr(asc, addr)) { - debug(28, 0) ("DecodeAddress: unsafe IP address: '%s'\n", asc); - fatal("DecodeAddress: unsafe IP address"); - } - break; + + if (!safe_inet_addr(asc, addr)) { + debug(28, 0) ("DecodeAddress: unsafe IP address: '%s'\n", asc); + fatal("DecodeAddress: unsafe IP address"); + } + + break; + case 1: /* a significant bits value for a mask */ - if (a1 >= 0 && a1 < 33) { - addr->s_addr = a1 ? htonl(0xfffffffful << (32 - a1)) : 0; - break; - } + + if (a1 >= 0 && a1 < 33) { + addr->s_addr = a1 ? htonl(0xfffffffful << (32 - a1)) : 0; + break; + } + default: - debug(28, 0) ("DecodeAddress: Invalid IP address '%s'\n", asc); - return 0; /* This is not valid address */ + debug(28, 0) ("DecodeAddress: Invalid IP address '%s'\n", asc); + return 0; /* This is not valid address */ } - if (mask != NULL) { /* mask == NULL if called to decode a netmask */ - - /* Guess netmask */ - a = (u_int32_t) ntohl(addr->s_addr); - if (!(a & 0xFFFFFFFFul)) - mask->s_addr = htonl(0x00000000ul); - else if (!(a & 0x00FFFFFF)) - mask->s_addr = htonl(0xFF000000ul); - else if (!(a & 0x0000FFFF)) - mask->s_addr = htonl(0xFFFF0000ul); - else if (!(a & 0x000000FF)) - mask->s_addr = htonl(0xFFFFFF00ul); - else - mask->s_addr = htonl(0xFFFFFFFFul); + if (mask != NULL) + { /* mask == NULL if called to decode a netmask */ + + /* Guess netmask */ + a = (u_int32_t) ntohl(addr->s_addr); + + if (!(a & 0xFFFFFFFFul)) + mask->s_addr = htonl(0x00000000ul); + else if (!(a & 0x00FFFFFF)) + mask->s_addr = htonl(0xFF000000ul); + else if (!(a & 0x0000FFFF)) + mask->s_addr = htonl(0xFFFF0000ul); + else if (!(a & 0x000000FF)) + mask->s_addr = htonl(0xFFFFFF00ul); + else + mask->s_addr = htonl(0xFFFFFFFFul); } + return 1; } @@ -220,93 +247,116 @@ acl_ip_data::FactoryParse(const char *t) char c; debug(28, 5) ("aclParseIpData: %s\n", t); acl_ip_data *q = new acl_ip_data; + if (!strcasecmp(t, "all")) { - q->addr1.s_addr = 0; - q->addr2.s_addr = 0; - q->mask.s_addr = 0; - return q; + q->addr1.s_addr = 0; + q->addr2.s_addr = 0; + q->mask.s_addr = 0; + return q; } + LOCAL_ARRAY(char, addr1, 256); + if (sscanf(t, SCAN_ACL1, addr1, addr2, mask) == 3) { - (void) 0; + (void) 0; } else if (sscanf(t, SCAN_ACL2, addr1, addr2, &c) == 2) { - mask[0] = '\0'; + mask[0] = '\0'; } else if (sscanf(t, SCAN_ACL3, addr1, mask) == 2) { - addr2[0] = '\0'; + addr2[0] = '\0'; } else if (sscanf(t, SCAN_ACL4, addr1, &c) == 1) { - addr2[0] = '\0'; - mask[0] = '\0'; + addr2[0] = '\0'; + mask[0] = '\0'; } else if (sscanf(t, "%[^/]/%s", addr1, mask) == 2) { - addr2[0] = '\0'; + addr2[0] = '\0'; } else if (sscanf(t, "%s", addr1) == 1) { - /* - * Note, must use plain gethostbyname() here because at startup - * ipcache hasn't been initialized - */ - struct hostent *hp; - if ((hp = gethostbyname(addr1)) == NULL) { - debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t); - delete q; - return NULL; - } - Q = &q; - for (x = hp->h_addr_list; x != NULL && *x != NULL; x++) { - if ((r = *Q) == NULL) - r = *Q = new acl_ip_data; - xmemcpy(&r->addr1.s_addr, *x, sizeof(r->addr1.s_addr)); - r->addr2.s_addr = 0; - r->mask.s_addr = no_addr.s_addr; /* 255.255.255.255 */ - Q = &r->next; - debug(28, 3) ("%s --> %s\n", addr1, inet_ntoa(r->addr1)); - } - return q; + /* + * Note, must use plain gethostbyname() here because at startup + * ipcache hasn't been initialized + */ + + struct hostent *hp; + + if ((hp = gethostbyname(addr1)) == NULL) { + debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t); + delete q; + return NULL; + } + + Q = &q; + + for (x = hp->h_addr_list; x != NULL && *x != NULL; x++) { + if ((r = *Q) == NULL) + r = *Q = new acl_ip_data; + + xmemcpy(&r->addr1.s_addr, *x, sizeof(r->addr1.s_addr)); + + r->addr2.s_addr = 0; + + r->mask.s_addr = no_addr.s_addr; /* 255.255.255.255 */ + + Q = &r->next; + + debug(28, 3) ("%s --> %s\n", addr1, inet_ntoa(r->addr1)); + } + + return q; } else { - debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t); - delete q; - return NULL; + debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t); + delete q; + return NULL; } + /* Decode addr1 */ if (!DecodeAddress(addr1, &q->addr1, &q->mask)) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown first address '%s'\n", addr1); - delete q; - return NULL; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown first address '%s'\n", addr1); + delete q; + return NULL; } + /* Decode addr2 */ if (*addr2 && !DecodeAddress(addr2, &q->addr2, &q->mask)) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown second address '%s'\n", addr2); - delete q; - return NULL; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown second address '%s'\n", addr2); + delete q; + return NULL; } + /* Decode mask */ if (*mask && !DecodeAddress(mask, &q->mask, NULL)) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown netmask '%s'\n", mask); - delete q; - return NULL; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown netmask '%s'\n", mask); + delete q; + return NULL; } + if ((q->addr1.s_addr & q->mask.s_addr) != q->addr1.s_addr || - (q->addr2.s_addr & q->mask.s_addr) != q->addr2.s_addr) - debug(28, 0) ("aclParseIpData: WARNING: Netmask masks away part of the specified IP in '%s'\n", t); + (q->addr2.s_addr & q->mask.s_addr) != q->addr2.s_addr) + debug(28, 0) ("aclParseIpData: WARNING: Netmask masks away part of the specified IP in '%s'\n", t); + q->addr1.s_addr &= q->mask.s_addr; + q->addr2.s_addr &= q->mask.s_addr; + /* 1.2.3.4/255.255.255.0 --> 1.2.3.0 */ return q; } + void ACLIP::parse() { char *t = NULL; + while ((t = strtokFile())) { - acl_ip_data *q = acl_ip_data::FactoryParse(t); - while (q != NULL) { - data = data->insert(q, acl_ip_data::NetworkCompare); - q = q->next; - } + acl_ip_data *q = acl_ip_data::FactoryParse(t); + + while (q != NULL) { + data = data->insert(q, acl_ip_data::NetworkCompare); + q = q->next; + } } } @@ -330,6 +380,7 @@ ACLIP::valid () const } int + ACLIP::match(struct in_addr &clientip) { static acl_ip_data ClientAddress (any_addr, any_addr, no_addr, NULL); @@ -344,7 +395,7 @@ ACLIP::match(struct in_addr &clientip) acl_ip_data *ClientAddressPointer = &ClientAddress; data = data->splay(ClientAddressPointer, aclIpAddrNetworkCompare); debug(28, 3) ("aclMatchIp: '%s' %s\n", - inet_ntoa(clientip), splayLastResult ? "NOT found" : "found"); + inet_ntoa(clientip), splayLastResult ? "NOT found" : "found"); return !splayLastResult; } @@ -354,8 +405,10 @@ acl_ip_data::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (acl_ip_data)); + if (!Pool) - Pool = memPoolCreate("acl_ip_data", sizeof (acl_ip_data)); + Pool = memPoolCreate("acl_ip_data", sizeof (acl_ip_data)); + return memPoolAlloc(Pool); } @@ -372,4 +425,5 @@ acl_ip_data::deleteSelf() const } acl_ip_data::acl_ip_data () :addr1(any_addr), addr2(any_addr), mask (any_addr), next (NULL) {} + acl_ip_data::acl_ip_data (struct in_addr const &anAddress1, struct in_addr const &anAddress2, struct in_addr const &aMask, acl_ip_data *aNext) : addr1(anAddress1), addr2(anAddress2), mask(aMask), next(aNext){} diff --git a/src/ACLIP.h b/src/ACLIP.h index 33b8ddb872..438f616b14 100644 --- a/src/ACLIP.h +++ b/src/ACLIP.h @@ -38,48 +38,62 @@ #include "ACL.h" #include "splay.h" -class acl_ip_data { - public: +class acl_ip_data +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; static acl_ip_data *FactoryParse(char const *); static int NetworkCompare(acl_ip_data * const & a, acl_ip_data * const &b); - + acl_ip_data (); + acl_ip_data (struct in_addr const &, struct in_addr const &, struct in_addr const &, acl_ip_data *); void toStr(char *buf, int len) const; + struct in_addr addr1; /* if addr2 non-zero then its a range */ + struct in_addr addr2; + struct in_addr mask; acl_ip_data *next; /* used for parsing, not for storing */ - private: + +private: + static bool DecodeAddress(const char *asc, struct in_addr *addr, struct in_addr *mask); static MemPool *Pool; }; -class ACLIP : public ACL { - public: +class ACLIP : public ACL +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const = 0; ACLIP() : data(NULL){} + ~ACLIP(); - + typedef SplayNode IPSplay; virtual char const *typeString() const = 0; virtual squid_acl aclType() const = 0; virtual void parse(); -// virtual bool isProxyAuth() const {return true;} + // virtual bool isProxyAuth() const {return true;} virtual int match(ACLChecklist *checklist) = 0; virtual wordlist *dump() const; virtual bool valid () const; - protected: + +protected: + int match(struct in_addr &); IPSplay *data; - private: + +private: static void DumpIpListWalkee(acl_ip_data * const & ip, void *state); }; diff --git a/src/ACLIdent.cc b/src/ACLIdent.cc index 4aea7defb3..48ed709a67 100644 --- a/src/ACLIdent.cc +++ b/src/ACLIdent.cc @@ -47,8 +47,10 @@ ACLIdent::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLIdent)); + if (!Pool) - Pool = memPoolCreate("ACLIdent", sizeof (ACLIdent)); + Pool = memPoolCreate("ACLIdent", sizeof (ACLIdent)); + return memPoolAlloc(Pool); } @@ -70,9 +72,10 @@ ACLIdent::~ACLIdent() } ACLIdent::ACLIdent(ACLData *newData, char const *newType) : data (newData), type_ (newType) {} + ACLIdent::ACLIdent (ACLIdent const &old) : data (old.data->clone()), type_ (old.type_) -{ -} +{} + ACLIdent & ACLIdent::operator= (ACLIdent const &rhs) { @@ -99,10 +102,10 @@ int ACLIdent::match(ACLChecklist *checklist) { if (checklist->rfc931[0]) { - return data->match(checklist->rfc931); + return data->match(checklist->rfc931); } else { - checklist->changeState(IdentLookup::Instance()); - return 0; + checklist->changeState(IdentLookup::Instance()); + return 0; } } @@ -142,13 +145,14 @@ IdentLookup::checkForAsync(ACLChecklist *checklist)const { checklist->asyncInProgress(true); debug(28, 3) ("IdentLookup::checkForAsync: Doing ident lookup\n"); + if (checklist->conn() && cbdataReferenceValid(checklist->conn())) { - identStart(&checklist->conn()->me, &checklist->conn()->peer, - LookupDone, checklist); + identStart(&checklist->conn()->me, &checklist->conn()->peer, + LookupDone, checklist); } else { - debug(28, 1) ("IdentLookup::checkForAsync: Can't start ident lookup. No client connection\n"); - checklist->currentAnswer(ACCESS_DENIED); - checklist->markFinished(); + debug(28, 1) ("IdentLookup::checkForAsync: Can't start ident lookup. No client connection\n"); + checklist->currentAnswer(ACCESS_DENIED); + checklist->markFinished(); } } @@ -159,17 +163,21 @@ IdentLookup::LookupDone(const char *ident, void *data) assert (checklist->asyncState() == IdentLookup::Instance()); if (ident) { - xstrncpy(checklist->rfc931, ident, USER_IDENT_SZ); + xstrncpy(checklist->rfc931, ident, USER_IDENT_SZ); } else { - xstrncpy(checklist->rfc931, dash_str, USER_IDENT_SZ); + xstrncpy(checklist->rfc931, dash_str, USER_IDENT_SZ); } + /* * Cache the ident result in the connection, to avoid redoing ident lookup * over and over on persistent connections */ if (cbdataReferenceValid(checklist->conn()) && !checklist->conn()->rfc931[0]) - xstrncpy(checklist->conn()->rfc931, checklist->rfc931, USER_IDENT_SZ); + xstrncpy(checklist->conn()->rfc931, checklist->rfc931, USER_IDENT_SZ); + checklist->asyncInProgress(false); + checklist->changeState (ACLChecklist::NullState::Instance()); + checklist->check(); } diff --git a/src/ACLIdent.h b/src/ACLIdent.h index e06ab87df2..ec6d179b75 100644 --- a/src/ACLIdent.h +++ b/src/ACLIdent.h @@ -39,17 +39,22 @@ #include "ACLChecklist.h" #include "ACLData.h" -class IdentLookup : public ACLChecklist::AsyncState { - public: +class IdentLookup : public ACLChecklist::AsyncState +{ + +public: static IdentLookup *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static IdentLookup instance_; static void LookupDone(const char *ident, void *data); }; -class ACLIdent : public ACL { - public: +class ACLIdent : public ACL +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -58,16 +63,19 @@ class ACLIdent : public ACL { ACLIdent (ACLIdent const &old); ACLIdent & operator= (ACLIdent const &rhs); ~ACLIdent(); - + virtual char const *typeString() const; virtual squid_acl aclType() const { return ACL_DERIVED;} + virtual void parse(); virtual bool isProxyAuth() const {return true;} + virtual int match(ACLChecklist *checklist); virtual wordlist *dump() const; virtual bool valid () const; virtual ACL *clone()const; - private: + +private: static MemPool *Pool; static Prototype UserRegistryProtoype; static ACLIdent UserRegistryEntry_; diff --git a/src/ACLMatchStrategy.h b/src/ACLMatchStrategy.h index fe369bfa71..8cd54e4526 100644 --- a/src/ACLMatchStrategy.h +++ b/src/ACLMatchStrategy.h @@ -1,6 +1,6 @@ /* - * $Id: ACLMatchStrategy.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLMatchStrategy.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -39,13 +39,19 @@ #include "ACLData.h" /* Perhaps this should live in ACL? */ + template -class ACLMatchStrategy { - public: + +class ACLMatchStrategy +{ + +public: typedef M MatchType; virtual int match (ACLData * &, ACLChecklist *) = 0; virtual bool requiresRequest() const {return false;} - virtual ~ACLMatchStrategy(){} -}; + + virtual ~ACLMatchStrategy(){}} + +; #endif /* SQUID_ACLMATCHSTRATEGY_H */ diff --git a/src/ACLMyIP.cc b/src/ACLMyIP.cc index 8f662939b3..d41d16ebe9 100644 --- a/src/ACLMyIP.cc +++ b/src/ACLMyIP.cc @@ -43,8 +43,10 @@ ACLMyIP::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLMyIP)); + if (!Pool) - Pool = memPoolCreate("ACLMyIP", sizeof (ACLMyIP)); + Pool = memPoolCreate("ACLMyIP", sizeof (ACLMyIP)); + return memPoolAlloc(Pool); } diff --git a/src/ACLMyIP.h b/src/ACLMyIP.h index 80c46a7bd6..64c8f21c0b 100644 --- a/src/ACLMyIP.h +++ b/src/ACLMyIP.h @@ -37,8 +37,10 @@ #define SQUID_ACLMYIP_H #include "ACLIP.h" -class ACLMyIP : public ACLIP { - public: +class ACLMyIP : public ACLIP +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -46,9 +48,11 @@ class ACLMyIP : public ACLIP { virtual char const *typeString() const; virtual squid_acl aclType() const { return ACL_DERIVED;} + virtual int match(ACLChecklist *checklist); virtual ACL *clone()const; - private: + +private: static MemPool *Pool; static Prototype RegistryProtoype; static ACLMyIP RegistryEntry_; diff --git a/src/ACLProxyAuth.cc b/src/ACLProxyAuth.cc index 1c57925b61..c528af833b 100644 --- a/src/ACLProxyAuth.cc +++ b/src/ACLProxyAuth.cc @@ -47,8 +47,10 @@ ACLProxyAuth::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLProxyAuth)); + if (!Pool) - Pool = memPoolCreate("ACLProxyAuth", sizeof (ACLProxyAuth)); + Pool = memPoolCreate("ACLProxyAuth", sizeof (ACLProxyAuth)); + return memPoolAlloc(Pool); } @@ -70,9 +72,10 @@ ACLProxyAuth::~ACLProxyAuth() } ACLProxyAuth::ACLProxyAuth(ACLData *newData, char const *theType) : data (newData), type_(theType) {} + ACLProxyAuth::ACLProxyAuth (ACLProxyAuth const &old) : data (old.data->clone()), type_(old.type_) -{ -} +{} + ACLProxyAuth & ACLProxyAuth::operator= (ACLProxyAuth const &rhs) { @@ -91,15 +94,17 @@ void ACLProxyAuth::parse() { if (authenticateSchemeCount() == 0) { - debug(28, 0) ("aclProxyAuth::parse: IGNORING: Proxy Auth ACL '%s' " - "because no authentication schemes were compiled.\n", cfgline); - return; + debug(28, 0) ("aclProxyAuth::parse: IGNORING: Proxy Auth ACL '%s' " + "because no authentication schemes were compiled.\n", cfgline); + return; } + if (authenticateActiveSchemeCount() == 0) { - debug(28, 0) ("aclProxyAuth::parse: IGNORING: Proxy Auth ACL '%s' " - "because no authentication schemes are fully configured.\n", cfgline); - return; + debug(28, 0) ("aclProxyAuth::parse: IGNORING: Proxy Auth ACL '%s' " + "because no authentication schemes are fully configured.\n", cfgline); + return; } + data->parse(); } @@ -107,9 +112,12 @@ int ACLProxyAuth::match(ACLChecklist *checklist) { int ti; + if ((ti = checklist->authenticated()) != 1) - return ti; + return ti; + ti = matchProxyAuth(checklist); + return ti; } @@ -146,7 +154,7 @@ ProxyAuthLookup::checkForAsync(ACLChecklist *checklist)const { checklist->asyncInProgress(true); debug(28, 3) - ("ACLChecklist::checkForAsync: checking password via authenticator\n"); + ("ACLChecklist::checkForAsync: checking password via authenticator\n"); auth_user_request_t *auth_user_request; /* make sure someone created auth_user_request for us */ @@ -164,18 +172,22 @@ ProxyAuthLookup::LookupDone(void *data, char *result) assert (checklist->asyncState() == ProxyAuthLookup::Instance()); if (result != NULL) - fatal("AclLookupProxyAuthDone: Old code floating around somewhere.\nMake clean and if that doesn't work, report a bug to the squid developers.\n"); + fatal("AclLookupProxyAuthDone: Old code floating around somewhere.\nMake clean and if that doesn't work, report a bug to the squid developers.\n"); + if (!authenticateValidateUser(checklist->auth_user_request) || checklist->conn() == NULL) { - /* credentials could not be checked either way - * restart the whole process */ - /* OR the connection was closed, there's no way to continue */ - authenticateAuthUserRequestUnlock(checklist->auth_user_request); - if (checklist->conn()) { - checklist->conn()->auth_user_request = NULL; - checklist->conn()->auth_type = AUTH_BROKEN; - } - checklist->auth_user_request = NULL; + /* credentials could not be checked either way + * restart the whole process */ + /* OR the connection was closed, there's no way to continue */ + authenticateAuthUserRequestUnlock(checklist->auth_user_request); + + if (checklist->conn()) { + checklist->conn()->auth_user_request = NULL; + checklist->conn()->auth_type = AUTH_BROKEN; + } + + checklist->auth_user_request = NULL; } + checklist->asyncInProgress(false); checklist->changeState (ACLChecklist::NullState::Instance()); checklist->check(); @@ -221,7 +233,7 @@ ACLProxyAuth::matchProxyAuth(ACLChecklist *checklist) checkAuthForCaching(checklist); /* check to see if we have matched the user-acl before */ int result = cacheMatchAcl(&checklist->auth_user_request->auth_user-> - proxy_match_cache, checklist); + proxy_match_cache, checklist); checklist->auth_user_request = NULL; return result; } diff --git a/src/ACLProxyAuth.h b/src/ACLProxyAuth.h index 15d711c841..119a3017c1 100644 --- a/src/ACLProxyAuth.h +++ b/src/ACLProxyAuth.h @@ -39,25 +39,33 @@ #include "ACLData.h" #include "ACLChecklist.h" -class ProxyAuthLookup : public ACLChecklist::AsyncState { - public: +class ProxyAuthLookup : public ACLChecklist::AsyncState +{ + +public: static ProxyAuthLookup *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static ProxyAuthLookup instance_; static void LookupDone(void *data, char *result); }; -class ProxyAuthNeeded : public ACLChecklist::AsyncState { - public: +class ProxyAuthNeeded : public ACLChecklist::AsyncState +{ + +public: static ProxyAuthNeeded *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static ProxyAuthNeeded instance_; }; -class ACLProxyAuth : public ACL { - public: +class ACLProxyAuth : public ACL +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -66,18 +74,22 @@ class ACLProxyAuth : public ACL { ACLProxyAuth(ACLData *, char const *); ACLProxyAuth (ACLProxyAuth const &); ACLProxyAuth &operator= (ACLProxyAuth const &); - + virtual char const *typeString() const; virtual squid_acl aclType() const { return ACL_DERIVED;} + virtual void parse(); virtual bool isProxyAuth() const {return true;} + virtual int match(ACLChecklist *checklist); virtual wordlist *dump() const; virtual bool valid () const; virtual bool requiresRequest() const {return true;} + virtual ACL *clone()const; virtual int matchForCache(ACLChecklist *checklist); - private: + +private: static MemPool *Pool; static Prototype UserRegistryProtoype; static ACLProxyAuth UserRegistryEntry_; diff --git a/src/ACLReferer.h b/src/ACLReferer.h index 73b26206dd..9f865d99f7 100644 --- a/src/ACLReferer.h +++ b/src/ACLReferer.h @@ -1,6 +1,6 @@ /* - * $Id: ACLReferer.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLReferer.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,8 +40,10 @@ #include "ACLRequestHeaderStrategy.h" #include "ACLStrategised.h" -class ACLReferer { - private: +class ACLReferer +{ + +private: static ACL::Prototype RegistryProtoype; static ACLStrategised RegistryEntry_; }; diff --git a/src/ACLRegexData.cc b/src/ACLRegexData.cc index 3d89563155..09cebae95d 100644 --- a/src/ACLRegexData.cc +++ b/src/ACLRegexData.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLRegexData.cc,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLRegexData.cc,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -46,8 +46,10 @@ ACLRegexData::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLRegexData)); + if (!Pool) - Pool = memPoolCreate("ACLRegexData", sizeof (ACLRegexData)); + Pool = memPoolCreate("ACLRegexData", sizeof (ACLRegexData)); + return memPoolAlloc(Pool); } @@ -66,7 +68,7 @@ ACLRegexData::deleteSelf() const ACLRegexData::~ACLRegexData() { aclDestroyRegexList(data); -} +} bool ACLRegexData::match(char const *user) diff --git a/src/ACLRegexData.h b/src/ACLRegexData.h index 2f304fa9d5..f42007429a 100644 --- a/src/ACLRegexData.h +++ b/src/ACLRegexData.h @@ -1,6 +1,6 @@ /* - * $Id: ACLRegexData.h,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLRegexData.h,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,8 +37,10 @@ #define SQUID_ACLREGEXDATA_H #include "ACLData.h" -class ACLRegexData : public ACLData { - public: +class ACLRegexData : public ACLData +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -48,7 +50,8 @@ class ACLRegexData : public ACLData { virtual wordlist *dump(); virtual void parse(); virtual ACLData *clone() const; - private: + +private: static MemPool *Pool; relist *data; }; diff --git a/src/ACLRequestHeaderStrategy.h b/src/ACLRequestHeaderStrategy.h index 9f627f3f55..2fd0b92917 100644 --- a/src/ACLRequestHeaderStrategy.h +++ b/src/ACLRequestHeaderStrategy.h @@ -1,6 +1,6 @@ /* - * $Id: ACLRequestHeaderStrategy.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLRequestHeaderStrategy.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,19 +40,24 @@ #include "ACLMatchStrategy.h" template + class ACLRequestHeaderStrategy : public ACLMatchStrategy { - public: + +public: virtual int match (ACLData * &, ACLChecklist *); virtual bool requiresRequest() const {return true;} + static ACLRequestHeaderStrategy *Instance(); /* Not implemented to prevent copies of the instance. */ /* Not private to prevent brain dead g+++ warnings about * private constructors with no friends */ ACLRequestHeaderStrategy(ACLRequestHeaderStrategy const &); - private: + +private: static ACLRequestHeaderStrategy Instance_; ACLRequestHeaderStrategy(){} + ACLRequestHeaderStrategy&operator=(ACLRequestHeaderStrategy const &); }; @@ -61,8 +66,10 @@ int ACLRequestHeaderStrategy
::match (ACLData * &data, ACLChecklist *checklist) { char const *theHeader = httpHeaderGetStr(&checklist->request->header, header); + if (NULL == theHeader) - return 0; + return 0; + return data->match(theHeader); } diff --git a/src/ACLRequestMIMEType.h b/src/ACLRequestMIMEType.h index 0e463c5b87..14002993b9 100644 --- a/src/ACLRequestMIMEType.h +++ b/src/ACLRequestMIMEType.h @@ -1,6 +1,6 @@ /* - * $Id: ACLRequestMIMEType.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLRequestMIMEType.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -41,8 +41,10 @@ #include "ACLStrategised.h" #include "ACLChecklist.h" -class ACLRequestMIMEType { - private: +class ACLRequestMIMEType +{ + +private: static ACL::Prototype RegistryProtoype; static ACLStrategised RegistryEntry_; }; @@ -52,8 +54,10 @@ int ACLRequestHeaderStrategy::match (ACLData * &data, ACLChecklist *checklist) { char const *theHeader = httpHeaderGetStr(&checklist->request->header, HDR_CONTENT_TYPE); + if (NULL == theHeader) - theHeader = ""; + theHeader = ""; + return data->match(theHeader); } diff --git a/src/ACLSourceDomain.cc b/src/ACLSourceDomain.cc index ef3ba4f6d2..42a6e6b2ce 100644 --- a/src/ACLSourceDomain.cc +++ b/src/ACLSourceDomain.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLSourceDomain.cc,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLSourceDomain.cc,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -77,16 +77,18 @@ ACLSourceDomainStrategy::match (ACLData * &data, ACLChecklist *checkl { const char *fqdn = NULL; fqdn = fqdncache_gethostbyaddr(checklist->src_addr, FQDN_LOOKUP_IF_MISS); + if (fqdn) { - return data->match(fqdn); + return data->match(fqdn); } else if (!checklist->sourceDomainChecked()) { - /* FIXME: reinstate a means to get to "name" - debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - name, inet_ntoa(checklist->src_addr)); - */ - checklist->changeState(SourceDomainLookup::Instance()); - return 0; + /* FIXME: reinstate a means to get to "name" + debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", + name, inet_ntoa(checklist->src_addr)); + */ + checklist->changeState(SourceDomainLookup::Instance()); + return 0; } + return data->match("none"); } diff --git a/src/ACLSourceDomain.h b/src/ACLSourceDomain.h index adb8187091..782117ff8e 100644 --- a/src/ACLSourceDomain.h +++ b/src/ACLSourceDomain.h @@ -1,6 +1,6 @@ /* - * $Id: ACLSourceDomain.h,v 1.2 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLSourceDomain.h,v 1.3 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -42,30 +42,38 @@ class ACLSourceDomainStrategy : public ACLMatchStrategy { - public: + +public: virtual int match (ACLData * &, ACLChecklist *); static ACLSourceDomainStrategy *Instance(); /* Not implemented to prevent copies of the instance. */ /* Not private to prevent brain dead g+++ warnings about * private constructors with no friends */ ACLSourceDomainStrategy(ACLSourceDomainStrategy const &); - private: + +private: static ACLSourceDomainStrategy Instance_; ACLSourceDomainStrategy(){} + ACLSourceDomainStrategy&operator=(ACLSourceDomainStrategy const &); }; -class SourceDomainLookup : public ACLChecklist::AsyncState { - public: +class SourceDomainLookup : public ACLChecklist::AsyncState +{ + +public: static SourceDomainLookup *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static SourceDomainLookup instance_; static void LookupDone(const char *, void *); }; -class ACLSourceDomain { - private: +class ACLSourceDomain +{ + +private: static ACL::Prototype LiteralRegistryProtoype; static ACLStrategised LiteralRegistryEntry_; static ACL::Prototype RegexRegistryProtoype; diff --git a/src/ACLSourceIP.cc b/src/ACLSourceIP.cc index 3c1de1deba..09cc20ba7f 100644 --- a/src/ACLSourceIP.cc +++ b/src/ACLSourceIP.cc @@ -43,8 +43,10 @@ ACLSourceIP::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLSourceIP)); + if (!Pool) - Pool = memPoolCreate("ACLSourceIP", sizeof (ACLSourceIP)); + Pool = memPoolCreate("ACLSourceIP", sizeof (ACLSourceIP)); + return memPoolAlloc(Pool); } diff --git a/src/ACLSourceIP.h b/src/ACLSourceIP.h index ed98c21ef4..a6ce8d4265 100644 --- a/src/ACLSourceIP.h +++ b/src/ACLSourceIP.h @@ -37,17 +37,21 @@ #define SQUID_ACLSOURCEIP_H #include "ACLIP.h" -class ACLSourceIP : public ACLIP { - public: +class ACLSourceIP : public ACLIP +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; virtual char const *typeString() const; virtual squid_acl aclType() const { return ACL_DERIVED;} + virtual int match(ACLChecklist *checklist); virtual ACL *clone()const; - private: + +private: static MemPool *Pool; static Prototype RegistryProtoype; static ACLSourceIP RegistryEntry_; diff --git a/src/ACLStrategised.h b/src/ACLStrategised.h index ed27675ebc..cef22eae59 100644 --- a/src/ACLStrategised.h +++ b/src/ACLStrategised.h @@ -1,6 +1,6 @@ /* - * $Id: ACLStrategised.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLStrategised.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,8 +40,11 @@ #include "ACLMatchStrategy.h" template -class ACLStrategised : public ACL { - public: + +class ACLStrategised : public ACL +{ + +public: typedef M MatchType; void *operator new(size_t); void operator delete(void *); @@ -51,16 +54,19 @@ class ACLStrategised : public ACL { ACLStrategised(ACLData *, ACLMatchStrategy *, char const *); ACLStrategised (ACLStrategised const &); ACLStrategised &operator= (ACLStrategised const &); - + virtual char const *typeString() const; virtual squid_acl aclType() const { return ACL_DERIVED;} + virtual bool requiresRequest() const {return matcher->requiresRequest();} + virtual void parse(); virtual int match(ACLChecklist *checklist); virtual wordlist *dump() const; virtual bool valid () const; virtual ACL *clone()const; - private: + +private: static MemPool *Pool; ACLData *data; char const *type_; @@ -78,8 +84,10 @@ ACLStrategised::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLStrategised)); + if (!Pool) - Pool = memPoolCreate("ACLStrategised", sizeof (ACLStrategised)); + Pool = memPoolCreate("ACLStrategised", sizeof (ACLStrategised)); + return memPoolAlloc(Pool); } @@ -105,10 +113,11 @@ ACLStrategised::~ACLStrategised() template ACLStrategised::ACLStrategised(ACLData *newData, ACLMatchStrategy *theStrategy, char const *theType) : data (newData), type_(theType), matcher(theStrategy) {} + template ACLStrategised::ACLStrategised (ACLStrategised const &old) : data (old.data->clone()), type_(old.type_), matcher (old.matcher) -{ -} +{} + template ACLStrategised & ACLStrategised::operator= (ACLStrategised const &rhs) diff --git a/src/ACLTime.h b/src/ACLTime.h index 5ee1400e34..60a96e21d3 100644 --- a/src/ACLTime.h +++ b/src/ACLTime.h @@ -1,6 +1,6 @@ /* - * $Id: ACLTime.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLTime.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -42,21 +42,26 @@ class ACLTimeStrategy : public ACLMatchStrategy { - public: + +public: virtual int match (ACLData * &, ACLChecklist *); static ACLTimeStrategy *Instance(); /* Not implemented to prevent copies of the instance. */ /* Not private to prevent brain dead g+++ warnings about * private constructors with no friends */ ACLTimeStrategy(ACLTimeStrategy const &); - private: + +private: static ACLTimeStrategy Instance_; ACLTimeStrategy(){} + ACLTimeStrategy&operator=(ACLTimeStrategy const &); }; -class ACLTime { - public: +class ACLTime +{ + +public: static ACL::Prototype RegistryProtoype; static ACLStrategised RegistryEntry_; }; diff --git a/src/ACLTimeData.cc b/src/ACLTimeData.cc index b67009c709..c02542725b 100644 --- a/src/ACLTimeData.cc +++ b/src/ACLTimeData.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLTimeData.cc,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLTimeData.cc,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -45,8 +45,10 @@ ACLTimeData::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLTimeData)); + if (!Pool) - Pool = memPoolCreate("ACLTimeData", sizeof (ACLTimeData)); + Pool = memPoolCreate("ACLTimeData", sizeof (ACLTimeData)); + return memPoolAlloc(Pool); } @@ -63,11 +65,11 @@ ACLTimeData::deleteSelf() const } ACLTimeData::ACLTimeData () : weekbits (0), start (0), stop (0), next (NULL) {} - -ACLTimeData::ACLTimeData(ACLTimeData const &old) : weekbits(old.weekbits), start (old.start), stop (old.stop), next (NULL) + +ACLTimeData::ACLTimeData(ACLTimeData const &old) : weekbits(old.weekbits), start (old.start), stop (old.stop), next (NULL) { if (old.next) - next = (ACLTimeData *)old.next->clone(); + next = (ACLTimeData *)old.next->clone(); } ACLTimeData& @@ -77,37 +79,46 @@ ACLTimeData::operator=(ACLTimeData const &old) start = old.start; stop = old.stop; next = NULL; + if (old.next) - next = (ACLTimeData *)old.next->clone(); + next = (ACLTimeData *)old.next->clone(); + return *this; } ACLTimeData::~ACLTimeData() { if (next) - next->deleteSelf(); -} + next->deleteSelf(); +} bool ACLTimeData::match(time_t when) { static time_t last_when = 0; + static struct tm tm; time_t t; + if (when != last_when) { - last_when = when; - xmemcpy(&tm, localtime(&when), sizeof(struct tm)); + last_when = when; + + xmemcpy(&tm, localtime(&when), sizeof(struct tm)); } + t = (time_t) (tm.tm_hour * 60 + tm.tm_min); ACLTimeData *data = this; + while (data) { - debug(28, 3) ("aclMatchTime: checking %d in %d-%d, weekbits=%x\n", - (int) t, (int) data->start, (int) data->stop, data->weekbits); + debug(28, 3) ("aclMatchTime: checking %d in %d-%d, weekbits=%x\n", + (int) t, (int) data->start, (int) data->stop, data->weekbits); - if (t >= data->start && t <= data->stop && (data->weekbits & (1 << tm.tm_wday))) - return 1; - data = data->next; + if (t >= data->start && t <= data->stop && (data->weekbits & (1 << tm.tm_wday))) + return 1; + + data = data->next; } + return 0; } @@ -117,19 +128,21 @@ ACLTimeData::dump() wordlist *W = NULL; char buf[128]; ACLTimeData *t = this; + while (t != NULL) { - snprintf(buf, sizeof(buf), "%c%c%c%c%c%c%c %02d:%02d-%02d:%02d", - t->weekbits & ACL_SUNDAY ? 'S' : '-', - t->weekbits & ACL_MONDAY ? 'M' : '-', - t->weekbits & ACL_TUESDAY ? 'T' : '-', - t->weekbits & ACL_WEDNESDAY ? 'W' : '-', - t->weekbits & ACL_THURSDAY ? 'H' : '-', - t->weekbits & ACL_FRIDAY ? 'F' : '-', - t->weekbits & ACL_SATURDAY ? 'A' : '-', - t->start / 60, t->start % 60, t->stop / 60, t->stop % 60); - wordlistAdd(&W, buf); - t = t->next; + snprintf(buf, sizeof(buf), "%c%c%c%c%c%c%c %02d:%02d-%02d:%02d", + t->weekbits & ACL_SUNDAY ? 'S' : '-', + t->weekbits & ACL_MONDAY ? 'M' : '-', + t->weekbits & ACL_TUESDAY ? 'T' : '-', + t->weekbits & ACL_WEDNESDAY ? 'W' : '-', + t->weekbits & ACL_THURSDAY ? 'H' : '-', + t->weekbits & ACL_FRIDAY ? 'F' : '-', + t->weekbits & ACL_SATURDAY ? 'A' : '-', + t->start / 60, t->start % 60, t->stop / 60, t->stop % 60); + wordlistAdd(&W, buf); + t = t->next; } + return W; } @@ -137,81 +150,109 @@ void ACLTimeData::parse() { ACLTimeData **Tail; - for (Tail = &next; *Tail; Tail = &((*Tail)->next)); + + for (Tail = &next; *Tail; Tail = &((*Tail)->next)) + + ; ACLTimeData *q = NULL; + if (Tail == &next) - q = new ACLTimeData; + q = new ACLTimeData; else - q = this; + q = this; + int h1, m1, h2, m2; + char *t = NULL; + while ((t = strtokFile())) { - if (*t < '0' || *t > '9') { - /* assume its day-of-week spec */ - while (*t) { - switch (*t++) { - case 'S': - q->weekbits |= ACL_SUNDAY; - break; - case 'M': - q->weekbits |= ACL_MONDAY; - break; - case 'T': - q->weekbits |= ACL_TUESDAY; - break; - case 'W': - q->weekbits |= ACL_WEDNESDAY; - break; - case 'H': - q->weekbits |= ACL_THURSDAY; - break; - case 'F': - q->weekbits |= ACL_FRIDAY; - break; - case 'A': - q->weekbits |= ACL_SATURDAY; - break; - case 'D': - q->weekbits |= ACL_WEEKDAYS; - break; - case '-': - /* ignore placeholder */ - break; - default: - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseTimeSpec: Bad Day '%c'\n", *t); - break; - } - } - } else { - /* assume its time-of-day spec */ - if (sscanf(t, "%d:%d-%d:%d", &h1, &m1, &h2, &m2) < 4) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseTimeSpec: IGNORING Bad time range\n"); - if (q != this) - q->deleteSelf(); - return; - } - q->start = h1 * 60 + m1; - q->stop = h2 * 60 + m2; - if (q->start > q->stop) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseTimeSpec: IGNORING Reversed time range\n"); - if (q != this) - q->deleteSelf(); - return; - } - } + if (*t < '0' || *t > '9') { + /* assume its day-of-week spec */ + + while (*t) { + switch (*t++) { + + case 'S': + q->weekbits |= ACL_SUNDAY; + break; + + case 'M': + q->weekbits |= ACL_MONDAY; + break; + + case 'T': + q->weekbits |= ACL_TUESDAY; + break; + + case 'W': + q->weekbits |= ACL_WEDNESDAY; + break; + + case 'H': + q->weekbits |= ACL_THURSDAY; + break; + + case 'F': + q->weekbits |= ACL_FRIDAY; + break; + + case 'A': + q->weekbits |= ACL_SATURDAY; + break; + + case 'D': + q->weekbits |= ACL_WEEKDAYS; + break; + + case '-': + /* ignore placeholder */ + break; + + default: + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseTimeSpec: Bad Day '%c'\n", *t); + break; + } + } + } else { + /* assume its time-of-day spec */ + + if (sscanf(t, "%d:%d-%d:%d", &h1, &m1, &h2, &m2) < 4) { + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseTimeSpec: IGNORING Bad time range\n"); + + if (q != this) + q->deleteSelf(); + + return; + } + + q->start = h1 * 60 + m1; + q->stop = h2 * 60 + m2; + + if (q->start > q->stop) { + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseTimeSpec: IGNORING Reversed time range\n"); + + if (q != this) + q->deleteSelf(); + + return; + } + } } + if (q->start == 0 && q->stop == 0) - q->stop = 23 * 60 + 59; + q->stop = 23 * 60 + 59; + if (q->weekbits == 0) - q->weekbits = ACL_ALLWEEK; + q->weekbits = ACL_ALLWEEK; + if (q != this) - *(Tail) = q; + *(Tail) = q; } diff --git a/src/ACLTimeData.h b/src/ACLTimeData.h index f9cd452401..144a90b4f0 100644 --- a/src/ACLTimeData.h +++ b/src/ACLTimeData.h @@ -1,6 +1,6 @@ /* - * $Id: ACLTimeData.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLTimeData.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -39,8 +39,10 @@ #include "ACL.h" #include "ACLData.h" -class ACLTimeData : public ACLData { - public: +class ACLTimeData : public ACLData +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -53,8 +55,8 @@ class ACLTimeData : public ACLData { wordlist *dump(); void parse(); virtual ACLData *clone() const; - - private: + +private: static MemPool *Pool; int weekbits; int start; diff --git a/src/ACLUrl.h b/src/ACLUrl.h index 4e1bf970e8..7ff0c3d2b9 100644 --- a/src/ACLUrl.h +++ b/src/ACLUrl.h @@ -1,6 +1,6 @@ /* - * $Id: ACLUrl.h,v 1.1 2003/02/17 07:01:34 robertc Exp $ + * $Id: ACLUrl.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -41,22 +41,28 @@ class ACLUrlStrategy : public ACLMatchStrategy { - public: + +public: virtual int match (ACLData * &, ACLChecklist *); virtual bool requiresRequest() const {return true;} + static ACLUrlStrategy *Instance(); /* Not implemented to prevent copies of the instance. */ /* Not private to prevent brain dead g+++ warnings about * private constructors with no friends */ ACLUrlStrategy(ACLUrlStrategy const &); - private: + +private: static ACLUrlStrategy Instance_; ACLUrlStrategy(){} + ACLUrlStrategy&operator=(ACLUrlStrategy const &); }; -class ACLUrl { - public: +class ACLUrl +{ + +public: static ACL::Prototype RegistryProtoype; static ACL::Prototype LegacyRegistryProtoype; static ACLStrategised RegistryEntry_; diff --git a/src/ACLUrlPath.h b/src/ACLUrlPath.h index 997ff78bcb..45b89e4f0f 100644 --- a/src/ACLUrlPath.h +++ b/src/ACLUrlPath.h @@ -1,6 +1,6 @@ /* - * $Id: ACLUrlPath.h,v 1.1 2003/02/17 07:01:35 robertc Exp $ + * $Id: ACLUrlPath.h,v 1.2 2003/02/21 22:50:04 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -42,22 +42,28 @@ class ACLUrlPathStrategy : public ACLMatchStrategy { - public: + +public: virtual int match (ACLData * &, ACLChecklist *); virtual bool requiresRequest() const {return true;} + static ACLUrlPathStrategy *Instance(); /* Not implemented to prevent copies of the instance. */ /* Not private to prevent brain dead g+++ warnings about * private constructors with no friends */ ACLUrlPathStrategy(ACLUrlPathStrategy const &); - private: + +private: static ACLUrlPathStrategy Instance_; ACLUrlPathStrategy(){} + ACLUrlPathStrategy&operator=(ACLUrlPathStrategy const &); }; -class ACLUrlPath { - public: +class ACLUrlPath +{ + +public: static ACL::Prototype RegistryProtoype; static ACL::Prototype LegacyRegistryProtoype; static ACLStrategised RegistryEntry_; diff --git a/src/ACLUserData.cc b/src/ACLUserData.cc index 2b7a1faeee..161eab3a2f 100644 --- a/src/ACLUserData.cc +++ b/src/ACLUserData.cc @@ -45,8 +45,10 @@ ACLUserData::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLUserData)); + if (!Pool) - Pool = memPoolCreate("ACLUserData", sizeof (ACLUserData)); + Pool = memPoolCreate("ACLUserData", sizeof (ACLUserData)); + return memPoolAlloc(Pool); } @@ -72,8 +74,8 @@ xRefFree(T &thing) ACLUserData::~ACLUserData() { if (names) - names->destroy(xRefFree); -} + names->destroy(xRefFree); +} template inline int @@ -95,25 +97,29 @@ ACLUserData::match(char const *user) SplayNode *Top = names; debug(28, 7) ("aclMatchUser: user is %s, case_insensitive is %d\n", - user, flags.case_insensitive); + user, flags.case_insensitive); debug(28, 8) ("Top is %p, Top->data is %s\n", Top, - (char *) (Top != NULL ? (Top)->data : "Unavailable")); + (char *) (Top != NULL ? (Top)->data : "Unavailable")); if (user == NULL) - return 0; + return 0; if (flags.required) { - debug(28, 7) ("aclMatchUser: user REQUIRED and auth-info present.\n"); - return 1; + debug(28, 7) ("aclMatchUser: user REQUIRED and auth-info present.\n"); + return 1; } + if (flags.case_insensitive) - Top = Top->splay((char *)user, splaystrcasecmp); + Top = Top->splay((char *)user, splaystrcasecmp); else - Top = Top->splay((char *)user, splaystrcmp); + Top = Top->splay((char *)user, splaystrcmp); + /* Top=splay_splay(user,Top,(splayNode::SPLAYCMP *)dumping_strcmp); */ debug(28, 7) ("aclMatchUser: returning %d,Top is %p, Top->data is %s\n", - !splayLastResult, Top, (char *) (Top ? Top->data : "Unavailable")); + !splayLastResult, Top, (char *) (Top ? Top->data : "Unavailable")); + names = Top; + return !splayLastResult; } @@ -128,16 +134,19 @@ wordlist * ACLUserData::dump() { wordlist *wl = NULL; + if (flags.case_insensitive) - wordlistAdd(&wl, "-i"); + wordlistAdd(&wl, "-i"); + /* damn this is VERY inefficient for long ACL lists... filling * a wordlist this way costs Sum(1,N) iterations. For instance * a 1000-elements list will be filled in 499500 iterations. */ if (flags.required) - wordlistAdd(&wl, "REQUIRED"); + wordlistAdd(&wl, "REQUIRED"); else if (names) - names->walk(aclDumpUserListWalkee, &wl); + names->walk(aclDumpUserListWalkee, &wl); + return wl; } @@ -146,30 +155,37 @@ ACLUserData::parse() { debug(28, 2) ("aclParseUserList: parsing user list\n"); char *t = NULL; + if ((t = strtokFile())) { - debug(28, 5) ("aclParseUserList: First token is %s\n", t); - if (strcmp("-i", t) == 0) { - debug(28, 5) ("aclParseUserList: Going case-insensitive\n"); - flags.case_insensitive = 1; - } else if (strcmp("REQUIRED", t) == 0) { - debug(28, 5) ("aclParseUserList: REQUIRED-type enabled\n"); - flags.required = 1; - } else { - if (flags.case_insensitive) - Tolower(t); - names = names->insert(xstrdup(t), splaystrcmp); - } + debug(28, 5) ("aclParseUserList: First token is %s\n", t); + + if (strcmp("-i", t) == 0) { + debug(28, 5) ("aclParseUserList: Going case-insensitive\n"); + flags.case_insensitive = 1; + } else if (strcmp("REQUIRED", t) == 0) { + debug(28, 5) ("aclParseUserList: REQUIRED-type enabled\n"); + flags.required = 1; + } else { + if (flags.case_insensitive) + Tolower(t); + + names = names->insert(xstrdup(t), splaystrcmp); + } } + debug(28, 3) ("aclParseUserList: Case-insensitive-switch is %d\n", - flags.case_insensitive); + flags.case_insensitive); /* we might inherit from a previous declaration */ debug(28, 4) ("aclParseUserList: parsing user list\n"); + while ((t = strtokFile())) { - debug(28, 6) ("aclParseUserList: Got token: %s\n", t); - if (flags.case_insensitive) - Tolower(t); - names = names->insert(xstrdup(t), splaystrcmp); + debug(28, 6) ("aclParseUserList: Got token: %s\n", t); + + if (flags.case_insensitive) + Tolower(t); + + names = names->insert(xstrdup(t), splaystrcmp); } } diff --git a/src/ACLUserData.h b/src/ACLUserData.h index 0101335945..790caadbca 100644 --- a/src/ACLUserData.h +++ b/src/ACLUserData.h @@ -39,8 +39,10 @@ #include "ACL.h" #include "ACLData.h" -class ACLUserData : public ACLData { - public: +class ACLUserData : public ACLData +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -50,13 +52,22 @@ class ACLUserData : public ACLData { wordlist *dump(); void parse(); virtual ACLData *clone() const; - + SplayNode *names; - struct { - unsigned int case_insensitive:1; - unsigned int required:1; - } flags; - private: + + struct + { + +unsigned int case_insensitive: + 1; + +unsigned int required: + 1; + } + + flags; + +private: static MemPool *Pool; }; diff --git a/src/CacheDigest.cc b/src/CacheDigest.cc index dc5638e073..c11459638d 100644 --- a/src/CacheDigest.cc +++ b/src/CacheDigest.cc @@ -1,6 +1,6 @@ /* - * $Id: CacheDigest.cc,v 1.35 2003/01/23 00:37:12 robertc Exp $ + * $Id: CacheDigest.cc,v 1.36 2003/02/21 22:50:04 robertc Exp $ * * DEBUG: section 70 Cache Digest * AUTHOR: Alex Rousskov @@ -39,12 +39,16 @@ #if USE_CACHE_DIGESTS /* local types */ -typedef struct { + +typedef struct +{ int bit_count; /* total number of bits */ int bit_on_count; /* #bits turned on */ int bseq_len_sum; /* sum of all bit seq length */ int bseq_count; /* number of bit seqs */ -} CacheDigestStats; +} + +CacheDigestStats; /* local functions */ static void cacheDigestHashKey(const CacheDigest * cd, const cache_key * key); @@ -64,7 +68,7 @@ cacheDigestInit(CacheDigest * cd, int capacity, int bpe) cd->mask_size = mask_size; cd->mask = (char *)xcalloc(cd->mask_size, 1); debug(70, 2) ("cacheDigestInit: capacity: %d entries, bpe: %d; size: %d bytes\n", - cd->capacity, cd->bits_per_entry, cd->mask_size); + cd->capacity, cd->bits_per_entry, cd->mask_size); } CacheDigest * @@ -131,10 +135,10 @@ cacheDigestTest(const CacheDigest * cd, const cache_key * key) cacheDigestHashKey(cd, key); /* test corresponding bits */ return - CBIT_TEST(cd->mask, hashed_keys[0]) && - CBIT_TEST(cd->mask, hashed_keys[1]) && - CBIT_TEST(cd->mask, hashed_keys[2]) && - CBIT_TEST(cd->mask, hashed_keys[3]); + CBIT_TEST(cd->mask, hashed_keys[0]) && + CBIT_TEST(cd->mask, hashed_keys[1]) && + CBIT_TEST(cd->mask, hashed_keys[2]) && + CBIT_TEST(cd->mask, hashed_keys[3]); } void @@ -145,30 +149,41 @@ cacheDigestAdd(CacheDigest * cd, const cache_key * key) cacheDigestHashKey(cd, key); /* turn on corresponding bits */ #if CD_FAST_ADD + CBIT_SET(cd->mask, hashed_keys[0]); CBIT_SET(cd->mask, hashed_keys[1]); CBIT_SET(cd->mask, hashed_keys[2]); CBIT_SET(cd->mask, hashed_keys[3]); #else + { - int on_xition_cnt = 0; - if (!CBIT_TEST(cd->mask, hashed_keys[0])) { - CBIT_SET(cd->mask, hashed_keys[0]); - on_xition_cnt++; - } - if (!CBIT_TEST(cd->mask, hashed_keys[1])) { - CBIT_SET(cd->mask, hashed_keys[1]); - on_xition_cnt++; - } - if (!CBIT_TEST(cd->mask, hashed_keys[2])) { - CBIT_SET(cd->mask, hashed_keys[2]); - on_xition_cnt++; - } - if (!CBIT_TEST(cd->mask, hashed_keys[3])) { - CBIT_SET(cd->mask, hashed_keys[3]); - on_xition_cnt++; - } - statHistCount(&statCounter.cd.on_xition_count, on_xition_cnt); + int on_xition_cnt = 0; + + if (!CBIT_TEST(cd->mask, hashed_keys[0])) + { + CBIT_SET(cd->mask, hashed_keys[0]); + on_xition_cnt++; + } + + if (!CBIT_TEST(cd->mask, hashed_keys[1])) + { + CBIT_SET(cd->mask, hashed_keys[1]); + on_xition_cnt++; + } + + if (!CBIT_TEST(cd->mask, hashed_keys[2])) + { + CBIT_SET(cd->mask, hashed_keys[2]); + on_xition_cnt++; + } + + if (!CBIT_TEST(cd->mask, hashed_keys[3])) + { + CBIT_SET(cd->mask, hashed_keys[3]); + on_xition_cnt++; + } + + statHistCount(&statCounter.cd.on_xition_count, on_xition_cnt); } #endif cd->count++; @@ -194,18 +209,23 @@ cacheDigestStats(const CacheDigest * cd, CacheDigestStats * stats) int cur_seq_type = 1; assert(stats); memset(stats, 0, sizeof(*stats)); + while (pos-- > 0) { - const int is_on = 0 != CBIT_TEST(cd->mask, pos); - if (is_on) - on_count++; - if (is_on != cur_seq_type || !pos) { - seq_len_sum += cur_seq_len; - seq_count++; - cur_seq_type = is_on; - cur_seq_len = 0; - } - cur_seq_len++; + const int is_on = 0 != CBIT_TEST(cd->mask, pos); + + if (is_on) + on_count++; + + if (is_on != cur_seq_type || !pos) { + seq_len_sum += cur_seq_len; + seq_count++; + cur_seq_type = is_on; + cur_seq_len = 0; + } + + cur_seq_len++; } + stats->bit_count = cd->mask_size * 8; stats->bit_on_count = on_count; stats->bseq_len_sum = seq_len_sum; @@ -225,16 +245,17 @@ void cacheDigestGuessStatsUpdate(cd_guess_stats * stats, int real_hit, int guess_hit) { assert(stats); + if (real_hit) { - if (guess_hit) - stats->true_hits++; - else - stats->false_misses++; + if (guess_hit) + stats->true_hits++; + else + stats->false_misses++; } else { - if (guess_hit) - stats->false_hits++; - else - stats->true_misses++; + if (guess_hit) + stats->false_hits++; + else + stats->true_misses++; } } @@ -251,26 +272,27 @@ cacheDigestGuessStatsReport(const cd_guess_stats * stats, StoreEntry * sentry, c assert(tot_count == hit_count + miss_count); /* paranoid */ if (!tot_count) { - storeAppendPrintf(sentry, "no guess stats for %s available\n", label); - return; + storeAppendPrintf(sentry, "no guess stats for %s available\n", label); + return; } + storeAppendPrintf(sentry, "Digest guesses stats for %s:\n", label); storeAppendPrintf(sentry, "guess\t hit\t\t miss\t\t total\t\t\n"); storeAppendPrintf(sentry, " \t #\t %%\t #\t %%\t #\t %%\t\n"); storeAppendPrintf(sentry, "true\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", - stats->true_hits, xpercent(stats->true_hits, tot_count), - stats->true_misses, xpercent(stats->true_misses, tot_count), - true_count, xpercent(true_count, tot_count)); + stats->true_hits, xpercent(stats->true_hits, tot_count), + stats->true_misses, xpercent(stats->true_misses, tot_count), + true_count, xpercent(true_count, tot_count)); storeAppendPrintf(sentry, "false\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", - stats->false_hits, xpercent(stats->false_hits, tot_count), - stats->false_misses, xpercent(stats->false_misses, tot_count), - false_count, xpercent(false_count, tot_count)); + stats->false_hits, xpercent(stats->false_hits, tot_count), + stats->false_misses, xpercent(stats->false_misses, tot_count), + false_count, xpercent(false_count, tot_count)); storeAppendPrintf(sentry, "all\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", - hit_count, xpercent(hit_count, tot_count), - miss_count, xpercent(miss_count, tot_count), - tot_count, xpercent(tot_count, tot_count)); + hit_count, xpercent(hit_count, tot_count), + miss_count, xpercent(miss_count, tot_count), + tot_count, xpercent(tot_count, tot_count)); storeAppendPrintf(sentry, "\tclose_hits: %d ( %d%%) /* cd said hit, doc was in the peer cache, but we got a miss */\n", - stats->close_hits, xpercentInt(stats->close_hits, stats->false_hits)); + stats->close_hits, xpercentInt(stats->close_hits, stats->false_hits)); } void @@ -280,25 +302,25 @@ cacheDigestReport(CacheDigest * cd, const char *label, StoreEntry * e) assert(cd && e); cacheDigestStats(cd, &stats); storeAppendPrintf(e, "%s digest: size: %d bytes\n", - label ? label : "", stats.bit_count / 8 - ); + label ? label : "", stats.bit_count / 8 + ); storeAppendPrintf(e, "\t entries: count: %d capacity: %d util: %d%%\n", - cd->count, - cd->capacity, - xpercentInt(cd->count, cd->capacity) - ); + cd->count, + cd->capacity, + xpercentInt(cd->count, cd->capacity) + ); storeAppendPrintf(e, "\t deletion attempts: %d\n", - cd->del_count - ); + cd->del_count + ); storeAppendPrintf(e, "\t bits: per entry: %d on: %d capacity: %d util: %d%%\n", - cd->bits_per_entry, - stats.bit_on_count, stats.bit_count, - xpercentInt(stats.bit_on_count, stats.bit_count) - ); + cd->bits_per_entry, + stats.bit_on_count, stats.bit_count, + xpercentInt(stats.bit_on_count, stats.bit_count) + ); storeAppendPrintf(e, "\t bit-seq: count: %d avg.len: %.2f\n", - stats.bseq_count, - xdiv(stats.bseq_len_sum, stats.bseq_count) - ); + stats.bseq_count, + xdiv(stats.bseq_len_sum, stats.bseq_count) + ); } size_t @@ -319,8 +341,8 @@ cacheDigestHashKey(const CacheDigest * cd, const cache_key * key) hashed_keys[2] = htonl(tmp_keys[2]) % bit_count; hashed_keys[3] = htonl(tmp_keys[3]) % bit_count; debug(70, 9) ("cacheDigestHashKey: %s -(%d)-> %d %d %d %d\n", - storeKeyText(key), bit_count, - hashed_keys[0], hashed_keys[1], hashed_keys[2], hashed_keys[3]); + storeKeyText(key), bit_count, + hashed_keys[0], hashed_keys[1], hashed_keys[2], hashed_keys[3]); } #endif diff --git a/src/CommonPool.h b/src/CommonPool.h index 1903d45d48..6f2acbd96b 100644 --- a/src/CommonPool.h +++ b/src/CommonPool.h @@ -1,6 +1,6 @@ /* - * $Id: CommonPool.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: CommonPool.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -50,17 +50,22 @@ * Then we have a legacy composite which returns class 1/2/3, and new * composites which return a descriptor of some sort. */ -class CommonPool { - public: + +class CommonPool +{ + +public: void *operator new(size_t); void operator delete (void *); void deleteSelf() const; static CommonPool *Factory (unsigned char _class, CompositePoolNode::Pointer&); char const* theClassTypeLabel() const {return typeLabel.buf();} + protected: CommonPool(); String typeLabel; }; + #endif #endif /* COMMONPOOL_H */ diff --git a/src/CompositePoolNode.h b/src/CompositePoolNode.h index c6a98d8b9f..208caccdd3 100644 --- a/src/CompositePoolNode.h +++ b/src/CompositePoolNode.h @@ -1,6 +1,6 @@ /* - * $Id: CompositePoolNode.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: CompositePoolNode.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -48,19 +48,26 @@ #include "DelayIdComposite.h" class StoreEntry; + class AuthUserRequest; -class CompositePoolNode : public RefCountable, public Updateable { + +class CompositePoolNode : public RefCountable, public Updateable +{ + public: typedef RefCount Pointer; void *operator new(size_t); void operator delete (void *); virtual void deleteSelf() const; virtual ~CompositePoolNode(){} + virtual void stats(StoreEntry * sentry) =0; virtual void dump(StoreEntry *entry) const =0; virtual void update(int incr) =0; virtual void parse() = 0; + virtual DelayIdComposite::Pointer id(struct in_addr &src_addr, AuthUserRequest *) = 0; }; + #endif #endif /* COMPOSITEPOOLNODE_H */ diff --git a/src/Config.h b/src/Config.h index 9b423f6f88..cb35da60c6 100644 --- a/src/Config.h +++ b/src/Config.h @@ -1,6 +1,6 @@ /* - * $Id: Config.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: Config.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,10 +35,12 @@ #ifndef SQUID_CONFIG_H_ #define SQUID_CONFIG_H_ - -class ConfigParser { + +class ConfigParser +{ + public: - static void ParseUShort(u_short *var); + static void ParseUShort(u_short *var); }; #endif /* SQUID_CONFIG_H_ */ diff --git a/src/ConnectionDetail.h b/src/ConnectionDetail.h index 272a52e0e9..db6c60071b 100644 --- a/src/ConnectionDetail.h +++ b/src/ConnectionDetail.h @@ -1,5 +1,5 @@ /* - * $Id: ConnectionDetail.h,v 1.1 2003/02/14 13:59:50 robertc Exp $ + * $Id: ConnectionDetail.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Robert Collins @@ -37,9 +37,13 @@ #ifndef _SQUIDCONNECTIONDETAIL_H_ #define _SQUIDCONNECTIONDETAIL_H_ -class ConnectionDetail { - public: +class ConnectionDetail +{ + +public: + struct sockaddr_in me; + struct sockaddr_in peer; }; diff --git a/src/Debug.h b/src/Debug.h index 1839d37bbc..bf690e0f51 100644 --- a/src/Debug.h +++ b/src/Debug.h @@ -1,6 +1,6 @@ /* - * $Id: Debug.h,v 1.2 2003/01/23 00:37:12 robertc Exp $ + * $Id: Debug.h,v 1.3 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 0 Debug Routines * AUTHOR: Harvest Derived @@ -36,11 +36,12 @@ #ifndef SQUID_DEBUG #define SQUID_DEBUG -class Debug +class Debug { + public: - static int Levels[MAX_DEBUG_SECTIONS]; - static int level; + static int Levels[MAX_DEBUG_SECTIONS]; + static int level; }; #endif /* SQUID_DEBUG */ diff --git a/src/DelayBucket.cc b/src/DelayBucket.cc index 757bd3f9ec..a1c6102bd8 100644 --- a/src/DelayBucket.cc +++ b/src/DelayBucket.cc @@ -1,6 +1,6 @@ /* - * $Id: DelayBucket.cc,v 1.2 2003/02/13 22:20:37 robertc Exp $ + * $Id: DelayBucket.cc,v 1.3 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -72,8 +72,8 @@ void DelayBucket::update (DelaySpec const &rate, int incr) { if (rate.restore_bps != -1 && - (level() += rate.restore_bps * incr) > rate.max_bytes) - level() = rate.max_bytes; + (level() += rate.restore_bps * incr) > rate.max_bytes) + level() = rate.max_bytes; } int @@ -93,8 +93,8 @@ void DelayBucket::init (DelaySpec const &rate) { level() = (int) (((double)rate.max_bytes * - Config.Delay.initial) / 100); + Config.Delay.initial) / 100); } - + #endif diff --git a/src/DelayBucket.h b/src/DelayBucket.h index 40f0fbf26d..6729f69d51 100644 --- a/src/DelayBucket.h +++ b/src/DelayBucket.h @@ -1,6 +1,6 @@ /* - * $Id: DelayBucket.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelayBucket.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -38,15 +38,21 @@ class DelaySpec; /* don't use remote storage for these */ -class DelayBucket { + +class DelayBucket +{ + public: int const& level() const {return level_;} + int & level() {return level_;} + void stats(StoreEntry *)const; void update (DelaySpec const &, int incr); int bytesWanted (int min, int max) const; void bytesIn(int qty); void init (DelaySpec const &); + private: int level_; }; diff --git a/src/DelayConfig.cc b/src/DelayConfig.cc index e635a8f4e3..334fe5c5f9 100644 --- a/src/DelayConfig.cc +++ b/src/DelayConfig.cc @@ -1,6 +1,6 @@ /* - * $Id: DelayConfig.cc,v 1.3 2003/02/12 06:10:58 robertc Exp $ + * $Id: DelayConfig.cc,v 1.4 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -62,16 +62,20 @@ DelayConfig::parsePoolClass() ushort pool; ConfigParser::ParseUShort(&pool); + if (pool < 1 || pool > DelayPools::pools()) { - debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d not in 1 .. %d\n", pool, DelayPools::pools()); - return; + debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d not in 1 .. %d\n", pool, DelayPools::pools()); + return; } + ushort delay_class_; ConfigParser::ParseUShort(&delay_class_); + if (delay_class_ < 1 || delay_class_ > 4) { - debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d class %d not in 1 .. 4\n", pool, delay_class_); - return; + debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d class %d not in 1 .. 4\n", pool, delay_class_); + return; } + pool--; DelayPools::delay_data[pool].createPool(delay_class_); @@ -82,16 +86,19 @@ DelayConfig::parsePoolRates() { ushort pool; ConfigParser::ParseUShort(&pool); + if (pool < 1 || pool > DelayPools::pools()) { - debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, DelayPools::pools()); - return; + debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, DelayPools::pools()); + return; } + pool--; if (!DelayPools::delay_data[pool].theComposite().getRaw()) { - debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d attempt to set rates with class not set\n", pool + 1); - return; + debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d attempt to set rates with class not set\n", pool + 1); + return; } + DelayPools::delay_data[pool].parse(); } @@ -101,10 +108,12 @@ DelayConfig::parsePoolAccess() ushort pool; ConfigParser::ParseUShort(&pool); + if (pool < 1 || pool > DelayPools::pools()) { - debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, DelayPools::pools()); - return; + debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, DelayPools::pools()); + return; } + --pool; aclParseAccessLine(&DelayPools::delay_data[pool].access); } @@ -122,11 +131,14 @@ DelayConfig::dumpPoolCount(StoreEntry * entry, const char *name) const int i; if (!DelayPools::pools()) { - storeAppendPrintf(entry, "%s 0\n", name); - return; + storeAppendPrintf(entry, "%s 0\n", name); + return; } + storeAppendPrintf(entry, "%s %d\n", name, DelayPools::pools()); + for (i = 0; i < DelayPools::pools(); i++) - DelayPools::delay_data[i].dump (entry, i); + DelayPools::delay_data[i].dump (entry, i); } + #endif diff --git a/src/DelayConfig.h b/src/DelayConfig.h index b70368f7ec..07a4372dc4 100644 --- a/src/DelayConfig.h +++ b/src/DelayConfig.h @@ -1,6 +1,6 @@ /* - * $Id: DelayConfig.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelayConfig.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,8 +36,10 @@ #ifndef SQUID_DELAYCONFIG_H #define SQUID_DELAYCONFIG_H -class DelayConfig { - public: +class DelayConfig +{ + +public: void freePoolCount(); void dumpPoolCount(StoreEntry * entry, const char *name) const; void parsePoolCount(); diff --git a/src/DelayId.cc b/src/DelayId.cc index 700a69d350..4b1c8d9eb1 100644 --- a/src/DelayId.cc +++ b/src/DelayId.cc @@ -1,6 +1,6 @@ /* - * $Id: DelayId.cc,v 1.3 2003/02/13 10:28:01 robertc Exp $ + * $Id: DelayId.cc,v 1.4 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -65,18 +65,16 @@ */ DelayId::DelayId () : pool_ (0), compositeId(NULL) -{ -} +{} -DelayId::DelayId (unsigned short aPool) : -pool_ (aPool), compositeId (NULL) +DelayId::DelayId (unsigned short aPool) : + pool_ (aPool), compositeId (NULL) { debug (77,3)("DelayId::DelayId: Pool %du\n", aPool); } DelayId::~DelayId () -{ -} +{} void DelayId::compositePosition(DelayIdComposite::Pointer newPosition) @@ -99,7 +97,7 @@ DelayId::operator == (DelayId const &rhs) const return pool_ == rhs.pool_ && compositeId == rhs.compositeId; } -DelayId::operator bool() const +DelayId::operator bool() const { return pool_ || compositeId.getRaw(); } @@ -113,24 +111,28 @@ DelayId::DelayClient(clientHttpRequest * http) r = http->request; if (r->client_addr.s_addr == INADDR_BROADCAST) { - debug(77, 2) ("delayClient: WARNING: Called with 'allones' address, ignoring\n"); - return DelayId(); + debug(77, 2) ("delayClient: WARNING: Called with 'allones' address, ignoring\n"); + return DelayId(); } ACLChecklist ch; ch.src_addr = r->client_addr; ch.my_addr = r->my_addr; ch.my_port = r->my_port; + if (http->conn) - ch.conn(cbdataReference(http->conn)); + ch.conn(cbdataReference(http->conn)); + ch.request = requestLink(r); + for (pool = 0; pool < DelayPools::pools(); pool++) - if (DelayPools::delay_data[pool].theComposite().getRaw() && - aclCheckFast(DelayPools::delay_data[pool].access, &ch)) { - DelayId result (pool + 1); - result.compositePosition(DelayPools::delay_data[pool].theComposite()->id(ch.src_addr, r->auth_user_request)); - return result; - } + if (DelayPools::delay_data[pool].theComposite().getRaw() && + aclCheckFast(DelayPools::delay_data[pool].access, &ch)) { + DelayId result (pool + 1); + result.compositePosition(DelayPools::delay_data[pool].theComposite()->id(ch.src_addr, r->auth_user_request)); + return result; + } + return DelayId(); } @@ -142,13 +144,16 @@ int DelayId::bytesWanted(int min, int max) const { /* unlimited */ + if (! (*this)) - return XMAX(min, max); - + return XMAX(min, max); + /* limited */ int nbytes = XMAX(min, max); + if (compositeId.getRaw()) - nbytes = compositeId->bytesWanted(min, nbytes); + nbytes = compositeId->bytesWanted(min, nbytes); + return nbytes; } @@ -161,14 +166,15 @@ void DelayId::bytesIn(int qty) { if (! (*this)) - return; + return; unsigned short tempPool = pool() - 1; assert (tempPool != 0xFFFF); if (compositeId.getRaw()) - compositeId->bytesIn(qty); + compositeId->bytesIn(qty); } + #endif diff --git a/src/DelayId.h b/src/DelayId.h index 8d83a3b8c7..13369ced7d 100644 --- a/src/DelayId.h +++ b/src/DelayId.h @@ -1,6 +1,6 @@ /* - * $Id: DelayId.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelayId.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -39,8 +39,10 @@ class ClientHttpRequest; #include "DelayIdComposite.h" -class DelayId { - public: +class DelayId +{ + +public: static DelayId DelayClient (ClientHttpRequest *); DelayId (); DelayId (unsigned short); @@ -53,8 +55,10 @@ class DelayId { operator bool() const; int bytesWanted(int min, int max) const; void bytesIn (int qty); - private: + +private: unsigned short pool_; DelayIdComposite::Pointer compositeId; }; + #endif /* SQUID_DELAYID_H */ diff --git a/src/DelayIdComposite.h b/src/DelayIdComposite.h index da934ad409..5716315b2e 100644 --- a/src/DelayIdComposite.h +++ b/src/DelayIdComposite.h @@ -1,6 +1,6 @@ /* - * $Id: DelayIdComposite.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelayIdComposite.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -45,11 +45,14 @@ #include "squid.h" #include "RefCount.h" -class DelayIdComposite : public RefCountable { +class DelayIdComposite : public RefCountable +{ + public: typedef RefCount Pointer; virtual void deleteSelf() const = 0; virtual inline ~DelayIdComposite(){} + virtual int bytesWanted (int min, int max) const =0; virtual void bytesIn(int qty) = 0; }; diff --git a/src/DelayPool.cc b/src/DelayPool.cc index 8373f4cb32..31491e816e 100644 --- a/src/DelayPool.cc +++ b/src/DelayPool.cc @@ -1,6 +1,6 @@ /* - * $Id: DelayPool.cc,v 1.2 2003/02/06 09:57:35 robertc Exp $ + * $Id: DelayPool.cc,v 1.3 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -53,9 +53,10 @@ DelayPool::DelayPool() : pool (NULL), access (NULL) DelayPool::~DelayPool() { if (pool) - freeData(); + freeData(); + if (access) - aclDestroyAccessList(&access); + aclDestroyAccessList(&access); } void @@ -68,22 +69,30 @@ DelayPool::parse() void DelayPool::dump (StoreEntry *entry, unsigned int i) const { - if (!theComposite().getRaw()) - return; - storeAppendPrintf(entry, "delay_class %d %s\n", i + 1, pool->theClassTypeLabel()); - LOCAL_ARRAY(char, nom, 32); - snprintf(nom, 32, "delay_access %d", i + 1); - dump_acl_access(entry, nom, access); - storeAppendPrintf(entry, "delay_parameters %d", i + 1); - theComposite()->dump (entry); - storeAppendPrintf(entry, "\n"); + if (!theComposite().getRaw()) + return; + + storeAppendPrintf(entry, "delay_class %d %s\n", i + 1, pool->theClassTypeLabel()); + + LOCAL_ARRAY(char, nom, 32); + + snprintf(nom, 32, "delay_access %d", i + 1); + + dump_acl_access(entry, nom, access); + + storeAppendPrintf(entry, "delay_parameters %d", i + 1); + + theComposite()->dump (entry); + + storeAppendPrintf(entry, "\n"); } void DelayPool::createPool(u_char delay_class) { if (pool) - freeData(); + freeData(); + pool = CommonPool::Factory(delay_class, theComposite_); } diff --git a/src/DelayPool.h b/src/DelayPool.h index 17999a65b7..0b31b0c53f 100644 --- a/src/DelayPool.h +++ b/src/DelayPool.h @@ -1,6 +1,6 @@ /* - * $Id: DelayPool.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelayPool.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -47,11 +47,15 @@ #include "CompositePoolNode.h" class StoreEntry; + class CommonPool; + class acl_access; -class DelayPool { - public: +class DelayPool +{ + +public: DelayPool(); ~DelayPool(); void freeData(); @@ -60,10 +64,14 @@ class DelayPool { void dump (StoreEntry *, unsigned int poolNumberMinusOne) const; CommonPool *pool; CompositePoolNode::Pointer theComposite() {return theComposite_;} + CompositePoolNode::Pointer const theComposite() const{return theComposite_;} + acl_access *access; - private: + +private: CompositePoolNode::Pointer theComposite_; }; + #endif #endif /* DELAYPOOL_H */ diff --git a/src/DelayPools.h b/src/DelayPools.h index 2669f8cea4..91b2b2bd38 100644 --- a/src/DelayPools.h +++ b/src/DelayPools.h @@ -1,6 +1,6 @@ /* - * $Id: DelayPools.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelayPools.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -38,15 +38,21 @@ #include "Array.h" -class Updateable { - public: +class Updateable +{ + +public: virtual ~Updateable(){} + virtual void update(int) = 0; }; class DelayPool; -class DelayPools { - public: + +class DelayPools +{ + +public: static void Init(); static void Update(void *); static void SetNoDelay(int fd); @@ -60,7 +66,8 @@ class DelayPools { static void deregisterForUpdates (Updateable *); static long MemoryUsed; static DelayPool *delay_data; - private: + +private: static void Stats(StoreEntry *); static void InitDelayData(); static time_t LastUpdate; @@ -69,4 +76,5 @@ class DelayPools { static void FreeDelayData (); static Vector toUpdate; }; + #endif /* SQUID_DELAYPOOLS_H */ diff --git a/src/DelaySpec.cc b/src/DelaySpec.cc index 3c8e1e0ad8..5bed8e394b 100644 --- a/src/DelaySpec.cc +++ b/src/DelaySpec.cc @@ -1,6 +1,6 @@ /* - * $Id: DelaySpec.cc,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelaySpec.cc,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -45,16 +45,16 @@ #include "Store.h" DelaySpec::DelaySpec() : restore_bps(-1), max_bytes (-1) -{ -} +{} void DelaySpec::stats (StoreEntry * sentry, char const *label) const { if (restore_bps == -1) { - storeAppendPrintf(sentry, "\t%s:\n\t\tDisabled.\n\n", label); - return; + storeAppendPrintf(sentry, "\t%s:\n\t\tDisabled.\n\n", label); + return; } + storeAppendPrintf(sentry, "\t%s:\n", label); storeAppendPrintf(sentry, "\t\tMax: %d\n", max_bytes); storeAppendPrintf(sentry, "\t\tRestore: %d\n", restore_bps); @@ -72,13 +72,19 @@ DelaySpec::parse() int i; char *token; token = strtok(NULL, "/"); + if (token == NULL) - self_destruct(); + self_destruct(); + if (sscanf(token, "%d", &i) != 1) - self_destruct(); + self_destruct(); + restore_bps = i; + i = GetInteger(); + max_bytes = i; } + #endif diff --git a/src/DelaySpec.h b/src/DelaySpec.h index 9bf01e5f61..661247fc7c 100644 --- a/src/DelaySpec.h +++ b/src/DelaySpec.h @@ -1,6 +1,6 @@ /* - * $Id: DelaySpec.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: DelaySpec.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -34,8 +34,10 @@ #ifndef SQUID_DELAYSPEC_H #define SQUID_DELAYSPEC_H -class DelaySpec { - public: +class DelaySpec +{ + +public: DelaySpec(); void stats (StoreEntry * sentry, char const *) const; void dump (StoreEntry *) const; diff --git a/src/DelayUser.cc b/src/DelayUser.cc index 5c8de374e9..316eba9e86 100644 --- a/src/DelayUser.cc +++ b/src/DelayUser.cc @@ -1,6 +1,6 @@ /* - * $Id: DelayUser.cc,v 1.3 2003/02/08 01:45:47 robertc Exp $ + * $Id: DelayUser.cc,v 1.4 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -88,8 +88,7 @@ DelayUserCmp(DelayUserBucket::Pointer const &left, DelayUserBucket::Pointer cons void DelayUserFree(DelayUserBucket::Pointer &) -{ -} +{} void DelayUserStatsWalkee(DelayUserBucket::Pointer const ¤t, void *state) @@ -101,13 +100,17 @@ void DelayUser::stats(StoreEntry * sentry) { spec.stats (sentry, "Per User"); + if (spec.restore_bps == -1) - return; + return; + storeAppendPrintf(sentry, "\t\tCurrent: "); + if (!buckets.head) { - storeAppendPrintf (sentry, "Not used yet.\n\n"); - return; + storeAppendPrintf (sentry, "Not used yet.\n\n"); + return; } + buckets.head->walk(DelayUserStatsWalkee, sentry); storeAppendPrintf(sentry, "\n\n"); } @@ -118,12 +121,14 @@ DelayUser::dump(StoreEntry *entry) const spec.dump(entry); } -struct DelayUserUpdater +struct DelayUserUpdater { DelayUserUpdater (DelaySpec &_spec, int _incr):spec(_spec),incr(_incr){}; + DelaySpec spec; int incr; }; + void DelayUserUpdateWalkee(DelayUserBucket::Pointer const ¤t, void *state) { @@ -131,6 +136,7 @@ DelayUserUpdateWalkee(DelayUserBucket::Pointer const ¤t, void *state) /* This doesn't change the value of the DelayUserBucket, so is safe */ const_cast(current.getRaw())->theBucket.update(t->spec, t->incr); } + void DelayUser::update(int incr) { @@ -145,10 +151,12 @@ DelayUser::parse() } DelayIdComposite::Pointer + DelayUser::id(struct in_addr &src_addr, AuthUserRequest *authRequest) { if (!authRequest) - return new NullDelayId; + return new NullDelayId; + return new Id(this, authRequest->auth_user); } @@ -209,10 +217,12 @@ DelayUser::Id::Id(DelayUser::Pointer aDelayUser,AuthUser *aUser) : theUser(aDela { theBucket = new DelayUserBucket(aUser); DelayUserBucket::Pointer const *existing = theUser->buckets.find(theBucket, DelayUserCmp); + if (existing) { - theBucket = *existing; - return; + theBucket = *existing; + return; } + theBucket->theBucket.init(theUser->spec); theUser->buckets.head = theUser->buckets.head->insert (theBucket, DelayUserCmp); } @@ -233,4 +243,5 @@ DelayUser::Id::bytesIn(int qty) { theBucket->theBucket.bytesIn(qty); } + #endif diff --git a/src/DelayUser.h b/src/DelayUser.h index f539e43db9..0ebfb6e3db 100644 --- a/src/DelayUser.h +++ b/src/DelayUser.h @@ -1,6 +1,6 @@ /* - * $Id: DelayUser.h,v 1.2 2003/02/08 01:45:47 robertc Exp $ + * $Id: DelayUser.h,v 1.3 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -49,12 +49,15 @@ #include "Array.h" #include "splay.h" -class DelayUserBucket : public RefCountable { - public: +class DelayUserBucket : public RefCountable +{ + +public: typedef RefCount Pointer; void *operator new(size_t); void operator delete (void *); virtual void deleteSelf() const {delete this;} + void stats(StoreEntry *)const; DelayUserBucket(AuthUser *); ~DelayUserBucket(); @@ -62,7 +65,9 @@ class DelayUserBucket : public RefCountable { AuthUser *authUser; }; -class DelayUser : public CompositePoolNode { +class DelayUser : public CompositePoolNode +{ + public: typedef RefCount Pointer; void *operator new(size_t); @@ -74,23 +79,30 @@ public: virtual void dump(StoreEntry *entry) const; virtual void update(int incr); virtual void parse(); + virtual DelayIdComposite::Pointer id(struct in_addr &src_addr, AuthUserRequest *); private: - class Id:public DelayIdComposite { - public: - void *operator new(size_t); - void operator delete (void *); - virtual void deleteSelf() const; - Id (DelayUser::Pointer, AuthUser *); - ~Id(); - virtual int bytesWanted (int min, int max) const; - virtual void bytesIn(int qty); - private: - DelayUser::Pointer theUser; - DelayUserBucket::Pointer theBucket; + +class Id:public DelayIdComposite + { + + public: + void *operator new(size_t); + void operator delete (void *); + virtual void deleteSelf() const; + Id (DelayUser::Pointer, AuthUser *); + ~Id(); + virtual int bytesWanted (int min, int max) const; + virtual void bytesIn(int qty); + + private: + DelayUser::Pointer theUser; + DelayUserBucket::Pointer theBucket; }; + DelaySpec spec; Splay buckets; }; + #endif /* DELAYUSER_H */ diff --git a/src/DelayVector.cc b/src/DelayVector.cc index afb00c55bf..b4d0e54744 100644 --- a/src/DelayVector.cc +++ b/src/DelayVector.cc @@ -1,6 +1,6 @@ /* - * $Id: DelayVector.cc,v 1.2 2003/02/06 09:57:36 robertc Exp $ + * $Id: DelayVector.cc,v 1.3 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -64,16 +64,16 @@ DelayVector::deleteSelf() const } DelayVector::~DelayVector() -{ -} +{} void DelayVector::stats(StoreEntry * sentry) { iterator pos = pools.begin(); + while (pos != pools.end()) { - (*pos)->stats(sentry); - ++pos; + (*pos)->stats(sentry); + ++pos; } } @@ -81,9 +81,10 @@ void DelayVector::dump(StoreEntry *entry) const { const_iterator pos = pools.begin(); + while (pos != pools.end()) { - (*pos)->dump(entry); - ++pos; + (*pos)->dump(entry); + ++pos; } } @@ -91,9 +92,10 @@ void DelayVector::update(int incr) { iterator pos = pools.begin(); + while (pos != pools.end()) { - (*pos)->update(incr); - ++pos; + (*pos)->update(incr); + ++pos; } } @@ -101,13 +103,15 @@ void DelayVector::parse() { iterator pos = pools.begin(); + while (pos != pools.end()) { - (*pos)->parse(); - ++pos; + (*pos)->parse(); + ++pos; } } DelayIdComposite::Pointer + DelayVector::id(struct in_addr &src_addr, AuthUserRequest *authUser) { return new Id(this, src_addr, authUser); @@ -143,9 +147,11 @@ DelayVector::Id::Id(DelayVector::Pointer aDelayVector,struct in_addr &src_addr, { debug(77,3)("DelayVector::Id::Id\n"); DelayVector::iterator pos = theVector->pools.begin(); - while (pos != theVector->pools.end()) { - ids.push_back ((*pos)->id (src_addr, authUser)); - ++pos; + + while (pos != theVector->pools.end()) + { + ids.push_back ((*pos)->id (src_addr, authUser)); + ++pos; } } @@ -159,10 +165,12 @@ DelayVector::Id::bytesWanted (int min, int max) const { int nbytes = max; const_iterator pos = ids.begin(); + while (pos != ids.end()) { - nbytes = XMIN (nbytes, (*pos)->bytesWanted(min, nbytes)); - ++pos; + nbytes = XMIN (nbytes, (*pos)->bytesWanted(min, nbytes)); + ++pos; } + nbytes = XMAX(min, nbytes); return nbytes; } @@ -171,9 +179,11 @@ void DelayVector::Id::bytesIn(int qty) { iterator pos = ids.begin(); + while (pos != ids.end()) { - (*pos)->bytesIn(qty); - ++pos; + (*pos)->bytesIn(qty); + ++pos; } } + #endif diff --git a/src/DelayVector.h b/src/DelayVector.h index 07299b7cdd..31a825377e 100644 --- a/src/DelayVector.h +++ b/src/DelayVector.h @@ -1,6 +1,6 @@ /* - * $Id: DelayVector.h,v 1.2 2003/02/06 09:57:36 robertc Exp $ + * $Id: DelayVector.h,v 1.3 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -38,7 +38,9 @@ #include "CompositePoolNode.h" -class DelayVector : public CompositePoolNode{ +class DelayVector : public CompositePoolNode +{ + public: typedef RefCount Pointer; void *operator new(size_t); @@ -49,24 +51,32 @@ public: virtual void dump(StoreEntry *entry) const; virtual void update(int incr); virtual void parse(); + virtual DelayIdComposite::Pointer id(struct in_addr &src_addr, AuthUserRequest *); void push_back (CompositePoolNode::Pointer); + private: - class Id:public DelayIdComposite { - public: - void *operator new(size_t); - void operator delete (void *); - virtual void deleteSelf() const; - Id (DelayVector::Pointer,struct in_addr &src_addr, AuthUserRequest *); - ~Id(); - virtual int bytesWanted (int min, int max) const; - virtual void bytesIn(int qty); - private: - DelayVector::Pointer theVector; - Vector ids; - typedef Vector::iterator iterator; - typedef Vector::const_iterator const_iterator; + +class Id:public DelayIdComposite + { + + public: + void *operator new(size_t); + void operator delete (void *); + virtual void deleteSelf() const; + + Id (DelayVector::Pointer,struct in_addr &src_addr, AuthUserRequest *); + ~Id(); + virtual int bytesWanted (int min, int max) const; + virtual void bytesIn(int qty); + + private: + DelayVector::Pointer theVector; + Vector ids; + typedef Vector::iterator iterator; + typedef Vector::const_iterator const_iterator; }; + Vector pools; typedef Vector::iterator iterator; typedef Vector::const_iterator const_iterator; diff --git a/src/ETag.cc b/src/ETag.cc index f802ec3260..4c8ae357b0 100644 --- a/src/ETag.cc +++ b/src/ETag.cc @@ -1,6 +1,6 @@ /* - * $Id: ETag.cc,v 1.9 2003/01/23 00:37:12 robertc Exp $ + * $Id: ETag.cc,v 1.10 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: none ETag parsing support * AUTHOR: Alex Rousskov @@ -49,12 +49,16 @@ etagParseInit(ETag * etag, const char *str) assert(etag && str); etag->str = NULL; etag->weak = !strncmp(str, "W/", 2); + if (etag->weak) - str += 2; + str += 2; + /* check format (quoted-string) */ len = strlen(str); + if (len >= 2 && str[0] == '"' && str[len - 1] == '"') - etag->str = str; + etag->str = str; + return etag->str != NULL; } diff --git a/src/ExternalACL.h b/src/ExternalACL.h index 26a0186d90..0762d41c1d 100644 --- a/src/ExternalACL.h +++ b/src/ExternalACL.h @@ -1,6 +1,6 @@ /* - * $Id: ExternalACL.h,v 1.1 2003/02/13 08:07:47 robertc Exp $ + * $Id: ExternalACL.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,12 +36,17 @@ #ifndef SQUID_EXTERNALACL_H #define SQUID_EXTERNALACL_H #include "ACLChecklist.h" -class ExternalACLLookup : public ACLChecklist::AsyncState { - public: + +class ExternalACLLookup : public ACLChecklist::AsyncState +{ + +public: static ExternalACLLookup *Instance(); virtual void checkForAsync(ACLChecklist *)const; - private: + +private: static ExternalACLLookup instance_; static void LookupDone(void *data, void *result); }; + #endif /* SQUID_EXTERNALACL_H */ diff --git a/src/Generic.h b/src/Generic.h index fba0c374b4..fd5e15e78f 100644 --- a/src/Generic.h +++ b/src/Generic.h @@ -1,6 +1,6 @@ /* - * $Id: Generic.h,v 1.3 2003/01/23 00:37:12 robertc Exp $ + * $Id: Generic.h,v 1.4 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,7 +35,9 @@ #define SQUID_GENERIC_H template -struct unary_function { + +struct unary_function +{ typedef _Arg argument_type; typedef _Result result_type; }; @@ -44,7 +46,8 @@ template T& for_each(L const &head, T& visitor) { for (L const *node = &head; node; node=node->next) - visitor(*node); + visitor(*node); + return visitor; } @@ -53,7 +56,8 @@ template T& for_each(dlink_list const &collection, T& visitor) { for (dlink_node const *node = collection.head; node; node=node->next) - visitor(*(typename T::argument_type const *)node->data); + visitor(*(typename T::argument_type const *)node->data); + return visitor; } diff --git a/src/HttpBody.cc b/src/HttpBody.cc index be776c7746..3a6654b45a 100644 --- a/src/HttpBody.cc +++ b/src/HttpBody.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpBody.cc,v 1.19 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpBody.cc,v 1.20 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 56 HTTP Message Body * AUTHOR: Alex Rousskov @@ -46,8 +46,9 @@ void httpBodyClean(HttpBody * body) { assert(body); + if (!memBufIsNull(&body->mb)) - memBufClean(&body->mb); + memBufClean(&body->mb); } /* set body by absorbing mb */ @@ -63,8 +64,9 @@ void httpBodyPackInto(const HttpBody * body, Packer * p) { assert(body && p); + if (body->mb.size) - packerAppend(p, body->mb.buf, body->mb.size); + packerAppend(p, body->mb.buf, body->mb.size); } #if UNUSED_CODE @@ -73,4 +75,5 @@ httpBodyPtr(const HttpBody * body) { return body->mb.buf ? body->mb.buf : ""; } + #endif diff --git a/src/HttpHdrCc.cc b/src/HttpHdrCc.cc index 1ca31e13c9..f1300e76f3 100644 --- a/src/HttpHdrCc.cc +++ b/src/HttpHdrCc.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrCc.cc,v 1.24 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHdrCc.cc,v 1.25 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 65 HTTP Cache Control Header * AUTHOR: Alex Rousskov @@ -39,20 +39,22 @@ /* this table is used for parsing cache control header */ static const HttpHeaderFieldAttrs CcAttrs[CC_ENUM_END] = -{ - {"public", (http_hdr_type)CC_PUBLIC}, - {"private", (http_hdr_type)CC_PRIVATE}, - {"no-cache", (http_hdr_type)CC_NO_CACHE}, - {"no-store", (http_hdr_type)CC_NO_STORE}, - {"no-transform", (http_hdr_type)CC_NO_TRANSFORM}, - {"must-revalidate", (http_hdr_type)CC_MUST_REVALIDATE}, - {"proxy-revalidate", (http_hdr_type)CC_PROXY_REVALIDATE}, - {"only-if-cached", (http_hdr_type)CC_ONLY_IF_CACHED}, - {"max-age", (http_hdr_type)CC_MAX_AGE}, - {"s-maxage", (http_hdr_type)CC_S_MAXAGE}, - {"max-stale", (http_hdr_type)CC_MAX_STALE}, - {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */ -}; + { + {"public", (http_hdr_type)CC_PUBLIC}, + + {"private", (http_hdr_type)CC_PRIVATE}, + {"no-cache", (http_hdr_type)CC_NO_CACHE}, + {"no-store", (http_hdr_type)CC_NO_STORE}, + {"no-transform", (http_hdr_type)CC_NO_TRANSFORM}, + {"must-revalidate", (http_hdr_type)CC_MUST_REVALIDATE}, + {"proxy-revalidate", (http_hdr_type)CC_PROXY_REVALIDATE}, + {"only-if-cached", (http_hdr_type)CC_ONLY_IF_CACHED}, + {"max-age", (http_hdr_type)CC_MAX_AGE}, + {"s-maxage", (http_hdr_type)CC_S_MAXAGE}, + {"max-stale", (http_hdr_type)CC_MAX_STALE}, + {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */ + }; + HttpHeaderFieldInfo *CcFieldsInfo = NULL; http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader) @@ -96,10 +98,12 @@ HttpHdrCc * httpHdrCcParseCreate(const String * str) { HttpHdrCc *cc = httpHdrCcCreate(); + if (!httpHdrCcParseInit(cc, str)) { - httpHdrCcDestroy(cc); - cc = NULL; + httpHdrCcDestroy(cc); + cc = NULL; } + return cc; } @@ -115,52 +119,72 @@ httpHdrCcParseInit(HttpHdrCc * cc, const String * str) assert(cc && str); /* iterate through comma separated list */ + while (strListGetItem(str, ',', &item, &ilen, &pos)) { - /* strip '=' statements @?@ */ - if ((p = strchr(item, '=')) && (p - item < ilen)) - ilen = p++ - item; - /* find type */ - type = (http_hdr_cc_type ) httpHeaderIdByName(item, ilen, - CcFieldsInfo, CC_ENUM_END); - if (type < 0) { - debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, str->buf()); - type = CC_OTHER; - } - if (EBIT_TEST(cc->mask, type)) { - if (type != CC_OTHER) - debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, str->buf()); - CcFieldsInfo[type].stat.repCount++; - continue; - } - /* update mask */ - EBIT_SET(cc->mask, type); - /* post-processing special cases */ - switch (type) { - case CC_MAX_AGE: - if (!p || !httpHeaderParseInt(p, &cc->max_age)) { - debug(65, 2) ("cc: invalid max-age specs near '%s'\n", item); - cc->max_age = -1; - EBIT_CLR(cc->mask, type); - } - break; - case CC_S_MAXAGE: - if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) { - debug(65, 2) ("cc: invalid s-maxage specs near '%s'\n", item); - cc->s_maxage = -1; - EBIT_CLR(cc->mask, type); - } - break; - case CC_MAX_STALE: - if (!p || !httpHeaderParseInt(p, &cc->max_stale)) { - debug(65, 2) ("cc: max-stale directive is valid without value\n"); - cc->max_stale = -1; - } - break; - default: - /* note that we ignore most of '=' specs */ - break; - } + /* strip '=' statements @?@ */ + + if ((p = strchr(item, '=')) && (p - item < ilen)) + ilen = p++ - item; + + /* find type */ + type = (http_hdr_cc_type ) httpHeaderIdByName(item, ilen, + CcFieldsInfo, CC_ENUM_END); + + if (type < 0) { + debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, str->buf()); + type = CC_OTHER; + } + + if (EBIT_TEST(cc->mask, type)) { + if (type != CC_OTHER) + debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, str->buf()); + + CcFieldsInfo[type].stat.repCount++; + + continue; + } + + /* update mask */ + EBIT_SET(cc->mask, type); + + /* post-processing special cases */ + switch (type) { + + case CC_MAX_AGE: + + if (!p || !httpHeaderParseInt(p, &cc->max_age)) { + debug(65, 2) ("cc: invalid max-age specs near '%s'\n", item); + cc->max_age = -1; + EBIT_CLR(cc->mask, type); + } + + break; + + case CC_S_MAXAGE: + + if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) { + debug(65, 2) ("cc: invalid s-maxage specs near '%s'\n", item); + cc->s_maxage = -1; + EBIT_CLR(cc->mask, type); + } + + break; + + case CC_MAX_STALE: + + if (!p || !httpHeaderParseInt(p, &cc->max_stale)) { + debug(65, 2) ("cc: max-stale directive is valid without value\n"); + cc->max_stale = -1; + } + + break; + + default: + /* note that we ignore most of '=' specs */ + break; + } } + return cc->mask != 0; } @@ -190,24 +214,26 @@ httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p) http_hdr_cc_type flag; int pcount = 0; assert(cc && p); + for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) { - if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { + if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { + + /* print option name */ + packerPrintf(p, (pcount ? ", %s" : "%s"), CcFieldsInfo[flag].name.buf()); - /* print option name */ - packerPrintf(p, (pcount ? ", %s" : "%s"), CcFieldsInfo[flag].name.buf()); + /* handle options with values */ - /* handle options with values */ - if (flag == CC_MAX_AGE) - packerPrintf(p, "=%d", (int) cc->max_age); + if (flag == CC_MAX_AGE) + packerPrintf(p, "=%d", (int) cc->max_age); - if (flag == CC_S_MAXAGE) - packerPrintf(p, "=%d", (int) cc->s_maxage); + if (flag == CC_S_MAXAGE) + packerPrintf(p, "=%d", (int) cc->s_maxage); - if (flag == CC_MAX_STALE) - packerPrintf(p, "=%d", (int) cc->max_stale); + if (flag == CC_MAX_STALE) + packerPrintf(p, "=%d", (int) cc->max_stale); - pcount++; - } + pcount++; + } } } @@ -215,12 +241,16 @@ void httpHdrCcJoinWith(HttpHdrCc * cc, const HttpHdrCc * new_cc) { assert(cc && new_cc); + if (cc->max_age < 0) - cc->max_age = new_cc->max_age; + cc->max_age = new_cc->max_age; + if (cc->s_maxage < 0) - cc->s_maxage = new_cc->s_maxage; + cc->s_maxage = new_cc->s_maxage; + if (cc->max_stale < 0) - cc->max_stale = new_cc->max_stale; + cc->max_stale = new_cc->max_stale; + cc->mask |= new_cc->mask; } @@ -230,10 +260,11 @@ httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age) { assert(cc); cc->max_age = max_age; + if (max_age >= 0) - EBIT_SET(cc->mask, CC_MAX_AGE); + EBIT_SET(cc->mask, CC_MAX_AGE); else - EBIT_CLR(cc->mask, CC_MAX_AGE); + EBIT_CLR(cc->mask, CC_MAX_AGE); } /* negative s_maxage will clean old s-maxage setting */ @@ -242,10 +273,11 @@ httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage) { assert(cc); cc->s_maxage = s_maxage; + if (s_maxage >= 0) - EBIT_SET(cc->mask, CC_S_MAXAGE); + EBIT_SET(cc->mask, CC_S_MAXAGE); else - EBIT_CLR(cc->mask, CC_S_MAXAGE); + EBIT_CLR(cc->mask, CC_S_MAXAGE); } void @@ -253,9 +285,10 @@ httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist) { http_hdr_cc_type c; assert(cc); + for (c = CC_PUBLIC; c < CC_ENUM_END; ++c) - if (EBIT_TEST(cc->mask, c)) - statHistCount(hist, c); + if (EBIT_TEST(cc->mask, c)) + statHistCount(hist, c); } void @@ -265,7 +298,8 @@ httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int c const int id = (int) val; const int valid_id = id >= 0 && id < CC_ENUM_END; const char *name = valid_id ? CcFieldsInfo[id].name.buf() : "INVALID"; + if (count || valid_id) - storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", - id, name, count, xdiv(count, dump_stat->ccParsedCount)); + storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", + id, name, count, xdiv(count, dump_stat->ccParsedCount)); } diff --git a/src/HttpHdrContRange.cc b/src/HttpHdrContRange.cc index 8e79e39c08..e72f111786 100644 --- a/src/HttpHdrContRange.cc +++ b/src/HttpHdrContRange.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrContRange.cc,v 1.16 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHdrContRange.cc,v 1.17 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 68 HTTP Content-Range Header * AUTHOR: Alex Rousskov @@ -66,36 +66,46 @@ httpHdrRangeRespSpecParseInit(HttpHdrRangeSpec * spec, const char *field, int fl const char *p; assert(spec); spec->offset = spec->length = range_spec_unknown; + if (flen < 2) - return 0; + return 0; + /* is spec given ? */ if (*field == '*') - return 1; + return 1; + /* check format, must be %d-%d */ if (!((p = strchr(field, '-')) && (p - field < flen))) { - debug(68, 2) ("invalid (no '-') resp-range-spec near: '%s'\n", field); - return 0; + debug(68, 2) ("invalid (no '-') resp-range-spec near: '%s'\n", field); + return 0; } + /* parse offset */ if (!httpHeaderParseSize(field, &spec->offset)) - return 0; + return 0; + p++; + /* do we have last-pos ? */ if (p - field < flen) { - ssize_t last_pos; - if (!httpHeaderParseSize(p, &last_pos)) - return 0; - spec->length = size_diff(last_pos + 1, spec->offset); + ssize_t last_pos; + + if (!httpHeaderParseSize(p, &last_pos)) + return 0; + + spec->length = size_diff(last_pos + 1, spec->offset); } + /* Ensure typecast is safe */ assert (spec->length >= 0); - + /* we managed to parse, check if the result makes sence */ if (known_spec((size_t)spec->length) && spec->length == 0) { - debug(68, 2) ("invalid range (%ld += %ld) in resp-range-spec near: '%s'\n", - (long int) spec->offset, (long int) spec->length, field); - return 0; + debug(68, 2) ("invalid range (%ld += %ld) in resp-range-spec near: '%s'\n", + (long int) spec->offset, (long int) spec->length, field); + return 0; } + return 1; } @@ -105,12 +115,12 @@ httpHdrRangeRespSpecPackInto(const HttpHdrRangeSpec * spec, Packer * p) /* Ensure typecast is safe */ assert (spec->length >= 0); assert (spec->length >= 0); - + if (!known_spec((size_t)spec->offset) || !known_spec((size_t)spec->length)) - packerPrintf(p, "*"); + packerPrintf(p, "*"); else - packerPrintf(p, "bytes %ld-%ld", - (long int) spec->offset, (long int) spec->offset + spec->length - 1); + packerPrintf(p, "bytes %ld-%ld", + (long int) spec->offset, (long int) spec->offset + spec->length - 1); } /* @@ -130,10 +140,12 @@ HttpHdrContRange * httpHdrContRangeParseCreate(const char *str) { HttpHdrContRange *r = httpHdrContRangeCreate(); + if (!httpHdrContRangeParseInit(r, str)) { - httpHdrContRangeDestroy(r); - r = NULL; + httpHdrContRangeDestroy(r); + r = NULL; } + return r; } @@ -145,24 +157,32 @@ httpHdrContRangeParseInit(HttpHdrContRange * range, const char *str) assert(range && str); debug(68, 8) ("parsing content-range field: '%s'\n", str); /* check range type */ + if (strncasecmp(str, "bytes ", 6)) - return 0; + return 0; + str += 6; + /* split */ if (!(p = strchr(str, '/'))) - return 0; + return 0; + if (*str == '*') - range->spec.offset = range->spec.length = range_spec_unknown; + range->spec.offset = range->spec.length = range_spec_unknown; else if (!httpHdrRangeRespSpecParseInit(&range->spec, str, p - str)) - return 0; + return 0; + p++; + if (*p == '*') - range->elength = range_spec_unknown; + range->elength = range_spec_unknown; else if (!httpHeaderParseSize(p, &range->elength)) - return 0; + return 0; + debug(68, 8) ("parsed content-range field: %ld-%ld / %ld\n", - (long int) range->spec.offset, (long int) range->spec.offset + range->spec.length - 1, - (long int) range->elength); + (long int) range->spec.offset, (long int) range->spec.offset + range->spec.length - 1, + (long int) range->elength); + return 1; } @@ -190,10 +210,11 @@ httpHdrContRangePackInto(const HttpHdrContRange * range, Packer * p) httpHdrRangeRespSpecPackInto(&range->spec, p); /* Ensure typecast is safe */ assert (range->elength >= 0); + if (!known_spec((size_t)range->elength)) - packerPrintf(p, "/*"); + packerPrintf(p, "/*"); else - packerPrintf(p, "/%ld", (long int) range->elength); + packerPrintf(p, "/%ld", (long int) range->elength); } void diff --git a/src/HttpHdrContRange.h b/src/HttpHdrContRange.h index af5bda361a..a6d94a199a 100644 --- a/src/HttpHdrContRange.h +++ b/src/HttpHdrContRange.h @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrContRange.h,v 1.1 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHdrContRange.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,7 +37,10 @@ #include "HttpHeaderRange.h" /* http content-range header field */ -class HttpHdrContRange { + +class HttpHdrContRange +{ + public: HttpHdrRangeSpec spec; ssize_t elength; /* entity length, not content length */ diff --git a/src/HttpHdrExtField.cc b/src/HttpHdrExtField.cc index 6f74371346..ba25aa3639 100644 --- a/src/HttpHdrExtField.cc +++ b/src/HttpHdrExtField.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrExtField.cc,v 1.10 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHdrExtField.cc,v 1.11 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 69 HTTP Header: Extension Field * AUTHOR: Alex Rousskov @@ -43,7 +43,7 @@ static HttpHdrExtField *httpHdrExtFieldDoCreate(const char *name, int name_len, static HttpHdrExtField * httpHdrExtFieldDoCreate(const char *name, int name_len, - const char *value, int value_len) + const char *value, int value_len) { HttpHdrExtField *f = xcalloc(1, sizeof(HttpHdrExtField)); stringLimitInit(&f->name, name, name_len); @@ -55,8 +55,8 @@ HttpHdrExtField * httpHdrExtFieldCreate(const char *name, const char *value) { return httpHdrExtFieldDoCreate( - name, strlen(name), - value, strlen(value)); + name, strlen(name), + value, strlen(value)); } /* parses ext field; returns fresh ext field on success and NULL on failure */ @@ -69,16 +69,17 @@ httpHdrExtFieldParseCreate(const char *field_start, const char *field_end) /* note: value_end == field_end */ if (!name_end || name_end <= field_start || name_end > field_end) - return NULL; + return NULL; value_start = name_end + 1; /* skip ':' */ + /* skip white space */ while (value_start < field_end && xisspace(*value_start)) - value_start++; + value_start++; return httpHdrExtFieldDoCreate( - field_start, name_end - field_start, - value_start, field_end - value_start); + field_start, name_end - field_start, + value_start, field_end - value_start); } void @@ -95,6 +96,6 @@ httpHdrExtFieldDup(HttpHdrExtField * f) { assert(f); return httpHdrExtFieldDoCreate( - f->name.buf(), f->name.size(), - f->value.buf(), f->value.size()); + f->name.buf(), f->name.size(), + f->value.buf(), f->value.size()); } diff --git a/src/HttpHdrRange.cc b/src/HttpHdrRange.cc index fc27bf74f0..4b336d13ad 100644 --- a/src/HttpHdrRange.cc +++ b/src/HttpHdrRange.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrRange.cc,v 1.30 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHdrRange.cc,v 1.31 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 64 HTTP Range Header * AUTHOR: Alex Rousskov @@ -74,8 +74,10 @@ void * HttpHdrRangeSpec::operator new(size_t size) { assert (size == sizeof (HttpHdrRangeSpec)); + if (!Pool) - Pool = memPoolCreate ("HttpHdrRangeSpec", sizeof (HttpHdrRangeSpec)); + Pool = memPoolCreate ("HttpHdrRangeSpec", sizeof (HttpHdrRangeSpec)); + return memPoolAlloc(Pool); } @@ -90,7 +92,7 @@ HttpHdrRangeSpec::deleteSelf() const { delete this; } - + HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition){} /* parses range-spec and returns new object on success */ @@ -98,8 +100,10 @@ HttpHdrRangeSpec * HttpHdrRangeSpec::Create(const char *field, int flen) { HttpHdrRangeSpec spec; + if (!spec.parseInit(field, flen)) - return NULL; + return NULL; + return new HttpHdrRangeSpec(spec); } @@ -107,35 +111,44 @@ bool HttpHdrRangeSpec::parseInit(const char *field, int flen) { const char *p; + if (flen < 2) - return false; + return false; + /* is it a suffix-byte-range-spec ? */ if (*field == '-') { - if (!httpHeaderParseSize(field + 1, &length)) - return false; + if (!httpHeaderParseSize(field + 1, &length)) + return false; } else - /* must have a '-' somewhere in _this_ field */ - if (!((p = strchr(field, '-')) || (p - field >= flen))) { - debug(64, 2) ("ignoring invalid (missing '-') range-spec near: '%s'\n", field); - return false; - } else { - if (!httpHeaderParseSize(field, &offset)) - return false; - p++; - /* do we have last-pos ? */ - if (p - field < flen) { - ssize_t last_pos; - if (!httpHeaderParseSize(p, &last_pos)) - return false; - HttpHdrRangeSpec::HttpRange aSpec (offset, last_pos + 1); - length = aSpec.size(); - } - } + /* must have a '-' somewhere in _this_ field */ + if (!((p = strchr(field, '-')) || (p - field >= flen))) { + debug(64, 2) ("ignoring invalid (missing '-') range-spec near: '%s'\n", field); + return false; + } else { + if (!httpHeaderParseSize(field, &offset)) + return false; + + p++; + + /* do we have last-pos ? */ + if (p - field < flen) { + ssize_t last_pos; + + if (!httpHeaderParseSize(p, &last_pos)) + return false; + + HttpHdrRangeSpec::HttpRange aSpec (offset, last_pos + 1); + + length = aSpec.size(); + } + } + /* we managed to parse, check if the result makes sence */ if (length == 0) { - debug(64, 2) ("ignoring invalid (zero length) range-spec near: '%s'\n", field); - return false; + debug(64, 2) ("ignoring invalid (zero length) range-spec near: '%s'\n", field); + return false; } + return true; } @@ -143,22 +156,22 @@ void HttpHdrRangeSpec::packInto(Packer * packer) const { if (!known_spec(offset)) /* suffix */ - packerPrintf(packer, "-%ld", (long int) length); + packerPrintf(packer, "-%ld", (long int) length); else if (!known_spec(length)) /* trailer */ - packerPrintf(packer, "%ld-", (long int) offset); + packerPrintf(packer, "%ld-", (long int) offset); else /* range */ - packerPrintf(packer, "%ld-%ld", - (long int) offset, (long int) offset + length - 1); + packerPrintf(packer, "%ld-%ld", + (long int) offset, (long int) offset + length - 1); } void HttpHdrRangeSpec::outputInfo( char const *note) const { debug(64, 5) ("HttpHdrRangeSpec::canonize: %s: [%ld, %ld) len: %ld\n", - note, (long int) offset, (long int) offset + length, (long int) length); + note, (long int) offset, (long int) offset + length, (long int) length); } -/* fills "absent" positions in range specification based on response body size +/* fills "absent" positions in range specification based on response body size * returns true if the range is still valid * range is valid if its intersection with [0,length-1] is not empty */ @@ -167,26 +180,34 @@ HttpHdrRangeSpec::canonize(size_t clen) { outputInfo ("have"); HttpRange object(0, clen); - if (!known_spec(offset)) /* suffix */ { - assert(known_spec(length)); - offset = object.intersection(HttpRange (clen - length, clen)).start; - } else if (!known_spec(length)) /* trailer */ { - assert(known_spec(offset)); - HttpRange newRange = object.intersection(HttpRange (offset, clen)); - length = newRange.size(); + + if (!known_spec(offset)) /* suffix */ + { + assert(known_spec(length)); + offset = object.intersection(HttpRange (clen - length, clen)).start; + } else if (!known_spec(length)) /* trailer */ + { + assert(known_spec(offset)); + HttpRange newRange = object.intersection(HttpRange (offset, clen)); + length = newRange.size(); } /* we have a "range" now, adjust length if needed */ assert(known_spec(length)); + assert(known_spec(offset)); + HttpRange newRange = object.intersection (HttpRange (offset, offset + length)); + length = newRange.size(); + outputInfo ("done"); + return length > 0; } -/* merges recepient with donor if possible; returns true on success +/* merges recepient with donor if possible; returns true on success * both specs must be canonized prior to merger, of course */ -bool +bool HttpHdrRangeSpec::mergeWith(const HttpHdrRangeSpec * donor) { bool merged (false); @@ -199,24 +220,28 @@ HttpHdrRangeSpec::mergeWith(const HttpHdrRangeSpec * donor) assert(length > 0); assert(donor->length > 0); /* do we have a left hand side overlap? */ + if (donor->offset < offset && offset <= donor_rhs) { - offset = donor->offset; /* decrease left offset */ - merged = 1; + offset = donor->offset; /* decrease left offset */ + merged = 1; } + /* do we have a right hand side overlap? */ if (donor->offset <= rhs && rhs < donor_rhs) { - rhs = donor_rhs; /* increase right offset */ - merged = 1; + rhs = donor_rhs; /* increase right offset */ + merged = 1; } + /* adjust length if offsets have been changed */ if (merged) { - assert(rhs > offset); - length = rhs - offset; + assert(rhs > offset); + length = rhs - offset; } else { - /* does recepient contain donor? */ - merged = - offset <= donor->offset && donor->offset < rhs; + /* does recepient contain donor? */ + merged = + offset <= donor->offset && donor->offset < rhs; } + #endif return merged; } @@ -231,8 +256,10 @@ void * HttpHdrRange::operator new(size_t size) { assert (size == sizeof (HttpHdrRange)); + if (!Pool) - Pool = memPoolCreate ("HttpHdrRange", sizeof (HttpHdrRange)); + Pool = memPoolCreate ("HttpHdrRange", sizeof (HttpHdrRange)); + return memPoolAlloc(Pool); } @@ -247,19 +274,20 @@ HttpHdrRange::deleteSelf() const { delete this; } - + HttpHdrRange::HttpHdrRange () : clen (HttpHdrRangeSpec::UnknownPosition) -{ -} +{} HttpHdrRange * HttpHdrRange::ParseCreate(const String * range_spec) { HttpHdrRange *r = new HttpHdrRange; + if (!r->parseInit(range_spec)) { - r->deleteSelf(); - r = NULL; + r->deleteSelf(); + r = NULL; } + return r; } @@ -275,21 +303,27 @@ HttpHdrRange::parseInit(const String * range_spec) ++ParsedCount; debug(64, 8) ("parsing range field: '%s'\n", range_spec->buf()); /* check range type */ + if (range_spec->nCaseCmp("bytes=", 6)) - return 0; + return 0; + /* skip "bytes="; hack! */ pos = range_spec->buf() + 5; + /* iterate through comma separated list */ while (strListGetItem(range_spec, ',', &item, &ilen, &pos)) { - HttpHdrRangeSpec *spec = HttpHdrRangeSpec::Create(item, ilen); - /* - * HTTP/1.1 draft says we must ignore the whole header field if one spec - * is invalid. However, RFC 2068 just says that we must ignore that spec. - */ - if (spec) - specs.push_back(spec); - ++count; + HttpHdrRangeSpec *spec = HttpHdrRangeSpec::Create(item, ilen); + /* + * HTTP/1.1 draft says we must ignore the whole header field if one spec + * is invalid. However, RFC 2068 just says that we must ignore that spec. + */ + + if (spec) + specs.push_back(spec); + + ++count; } + debug(64, 8) ("parsed range range count: %d, kept %d\n", count, specs.size()); return specs.count != 0; } @@ -297,14 +331,16 @@ HttpHdrRange::parseInit(const String * range_spec) HttpHdrRange::~HttpHdrRange() { while (specs.size()) - specs.pop_back()->deleteSelf(); + specs.pop_back()->deleteSelf(); } HttpHdrRange::HttpHdrRange(HttpHdrRange const &old) : specs() { specs.reserve(old.specs.size()); + for (const_iterator i = old.begin(); i != old.end(); ++i) - specs.push_back(new HttpHdrRangeSpec ( **i)); + specs.push_back(new HttpHdrRangeSpec ( **i)); + assert(old.specs.size() == specs.size()); } @@ -337,11 +373,14 @@ HttpHdrRange::packInto(Packer * packer) const { const_iterator pos = begin(); assert(this); + while (pos != end()) { - if (pos != begin()) - packerAppend(packer, ",", 1); - (*pos)->packInto(packer); - ++pos; + if (pos != begin()) + packerAppend(packer, ",", 1); + + (*pos)->packInto(packer); + + ++pos; } } @@ -354,17 +393,20 @@ HttpHdrRange::merge (Vector &basis) * take one spec from "goods" and merge it with specs from * "specs" (if any) until there is no overlap */ iterator i = basis.begin(); + while (i != basis.end()) { - if (specs.size() && (*i)->mergeWith(specs.back())) { - /* merged with current so get rid of the prev one */ - specs.pop_back()->deleteSelf(); - continue; /* re-iterate */ - } - specs.push_back (*i); - ++i; /* progress */ + if (specs.size() && (*i)->mergeWith(specs.back())) { + /* merged with current so get rid of the prev one */ + specs.pop_back()->deleteSelf(); + continue; /* re-iterate */ + } + + specs.push_back (*i); + ++i; /* progress */ } + debug(64, 3) ("HttpHdrRange::merge: had %d specs, merged %d specs\n", - basis.size(), basis.size() - specs.size()); + basis.size(), basis.size() - specs.size()); } @@ -372,14 +414,16 @@ void HttpHdrRange::getCanonizedSpecs (Vector ©) { /* canonize each entry and destroy bad ones if any */ + for (iterator pos (begin()); pos != end(); ++pos) { - if ((*pos)->canonize(clen)) - copy.push_back (*pos); - else - (*pos)->deleteSelf(); + if ((*pos)->canonize(clen)) + copy.push_back (*pos); + else + (*pos)->deleteSelf(); } + debug(64, 3) ("HttpHdrRange::getCanonizedSpecs: found %d bad specs\n", - specs.size() - copy.size()); + specs.size() - copy.size()); } #include "HttpHdrContRange.h" @@ -395,10 +439,12 @@ int HttpHdrRange::canonize(HttpReply *rep) { assert(this && rep); + if (rep->content_range) - clen = rep->content_range->elength; + clen = rep->content_range->elength; else - clen = rep->content_length; + clen = rep->content_length; + return canonize (clen); } @@ -411,7 +457,7 @@ HttpHdrRange::canonize (size_t newClen) getCanonizedSpecs(goods); merge (goods); debug(64, 3) ("HttpHdrRange::canonize: finished with %d specs\n", - specs.count); + specs.count); return specs.count > 0; } @@ -424,14 +470,19 @@ HttpHdrRange::isComplex() const assert(this); /* check that all rangers are in "strong" order */ const_iterator pos (begin()); + while (pos != end()) { - /* Ensure typecasts is safe */ - assert ((*pos)->offset >= 0); - if ((unsigned int)(*pos)->offset < offset) - return 1; - offset = (*pos)->offset + (*pos)->length; - ++pos; + /* Ensure typecasts is safe */ + assert ((*pos)->offset >= 0); + + if ((unsigned int)(*pos)->offset < offset) + return 1; + + offset = (*pos)->offset + (*pos)->length; + + ++pos; } + return 0; } @@ -446,17 +497,23 @@ HttpHdrRange::willBeComplex() const /* check that all rangers are in "strong" order, */ /* as far as we can tell without the content length */ size_t offset = 0; + for (const_iterator pos (begin()); pos != end(); ++pos) { - if (!known_spec((*pos)->offset)) /* ignore unknowns */ - continue; - /* Ensure typecasts is safe */ - assert ((*pos)->offset >= 0); - if ((size_t) (*pos)->offset < offset) - return true; - offset = (*pos)->offset; - if (known_spec((*pos)->length)) /* avoid unknowns */ - offset += (*pos)->length; + if (!known_spec((*pos)->offset)) /* ignore unknowns */ + continue; + + /* Ensure typecasts is safe */ + assert ((*pos)->offset >= 0); + + if ((size_t) (*pos)->offset < offset) + return true; + + offset = (*pos)->offset; + + if (known_spec((*pos)->length)) /* avoid unknowns */ + offset += (*pos)->length; } + return false; } @@ -471,11 +528,14 @@ HttpHdrRange::firstOffset() const ssize_t offset = HttpHdrRangeSpec::UnknownPosition; assert(this); const_iterator pos = begin(); + while (pos != end()) { - if ((*pos)->offset < offset || !known_spec(offset)) - offset = (*pos)->offset; - ++pos; + if ((*pos)->offset < offset || !known_spec(offset)) + offset = (*pos)->offset; + + ++pos; } + return offset; } @@ -491,21 +551,27 @@ HttpHdrRange::lowestOffset(ssize_t size) const ssize_t offset = HttpHdrRangeSpec::UnknownPosition; const_iterator pos = begin(); assert(this); + while (pos != end()) { - ssize_t current = (*pos)->offset; - if (!known_spec(current)) { - if ((*pos)->length > size || !known_spec((*pos)->length)) - return 0; /* Unknown. Assume start of file */ - current = size - (*pos)->length; - } - if (current < offset || !known_spec(offset)) - offset = current; - ++pos; + ssize_t current = (*pos)->offset; + + if (!known_spec(current)) { + if ((*pos)->length > size || !known_spec((*pos)->length)) + return 0; /* Unknown. Assume start of file */ + + current = size - (*pos)->length; + } + + if (current < offset || !known_spec(offset)) + offset = current; + + ++pos; } + return known_spec(offset) ? offset : 0; } -/* +/* * Return true if the first range offset is larger than the configured * limit. */ @@ -513,14 +579,17 @@ bool HttpHdrRange::offsetLimitExceeded() const { if (NULL == this) - /* not a range request */ - return false; + /* not a range request */ + return false; + if (-1 == (ssize_t)Config.rangeOffsetLimit) - /* disabled */ - return false; + /* disabled */ + return false; + if ((ssize_t)Config.rangeOffsetLimit >= firstOffset()) - /* below the limit */ - return false; + /* below the limit */ + return false; + return true; } @@ -528,7 +597,8 @@ const HttpHdrRangeSpec * HttpHdrRangeIter::currentSpec() const { if (pos.incrementable()) - return *pos; + return *pos; + return NULL; } @@ -536,8 +606,9 @@ void HttpHdrRangeIter::updateSpec() { assert (debt_size == 0); + if (pos.incrementable()) { - debt(currentSpec()->length); + debt(currentSpec()->length); } } @@ -545,13 +616,13 @@ ssize_t HttpHdrRangeIter::debt() const { debug(64, 3) ("HttpHdrRangeIter::debt: debt is %d\n", - (int)debt_size); + (int)debt_size); return debt_size; } void HttpHdrRangeIter::debt(ssize_t newDebt) { debug(64, 3) ("HttpHdrRangeIter::debt: was %d now %d\n", - (int)debt_size, (int)newDebt); + (int)debt_size, (int)newDebt); debt_size = newDebt; } diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index 8d2ce64824..0476ec4adc 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.cc,v 1.84 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHeader.cc,v 1.85 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 55 HTTP Header * AUTHOR: Alex Rousskov @@ -68,73 +68,75 @@ * After reorganization, field id can be used as an index to the table. */ static const HttpHeaderFieldAttrs HeadersAttrs[] = -{ - {"Accept", HDR_ACCEPT, ftStr}, - {"Accept-Charset", HDR_ACCEPT_CHARSET, ftStr}, - {"Accept-Encoding", HDR_ACCEPT_ENCODING, ftStr}, - {"Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr}, - {"Accept-Ranges", HDR_ACCEPT_RANGES, ftStr}, - {"Age", HDR_AGE, ftInt}, - {"Allow", HDR_ALLOW, ftStr}, - {"Authorization", HDR_AUTHORIZATION, ftStr}, /* for now */ - {"Cache-Control", HDR_CACHE_CONTROL, ftPCc}, - {"Connection", HDR_CONNECTION, ftStr}, - {"Content-Base", HDR_CONTENT_BASE, ftStr}, - {"Content-Encoding", HDR_CONTENT_ENCODING, ftStr}, - {"Content-Language", HDR_CONTENT_LANGUAGE, ftStr}, - {"Content-Length", HDR_CONTENT_LENGTH, ftInt}, - {"Content-Location", HDR_CONTENT_LOCATION, ftStr}, - {"Content-MD5", HDR_CONTENT_MD5, ftStr}, /* for now */ - {"Content-Range", HDR_CONTENT_RANGE, ftPContRange}, - {"Content-Type", HDR_CONTENT_TYPE, ftStr}, - {"Cookie", HDR_COOKIE, ftStr}, - {"Date", HDR_DATE, ftDate_1123}, - {"ETag", HDR_ETAG, ftETag}, - {"Expires", HDR_EXPIRES, ftDate_1123}, - {"From", HDR_FROM, ftStr}, - {"Host", HDR_HOST, ftStr}, - {"If-Match", HDR_IF_MATCH, ftStr}, /* for now */ - {"If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123}, - {"If-None-Match", HDR_IF_NONE_MATCH, ftStr}, /* for now */ - {"If-Range", HDR_IF_RANGE, ftDate_1123_or_ETag}, - {"Last-Modified", HDR_LAST_MODIFIED, ftDate_1123}, - {"Link", HDR_LINK, ftStr}, - {"Location", HDR_LOCATION, ftStr}, - {"Max-Forwards", HDR_MAX_FORWARDS, ftInt}, - {"Mime-Version", HDR_MIME_VERSION, ftStr}, /* for now */ - {"Pragma", HDR_PRAGMA, ftStr}, - {"Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr}, - {"Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr}, - {"Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr}, - {"Proxy-Connection", HDR_PROXY_CONNECTION, ftStr}, - {"Public", HDR_PUBLIC, ftStr}, - {"Range", HDR_RANGE, ftPRange}, - {"Referer", HDR_REFERER, ftStr}, - {"Request-Range", HDR_REQUEST_RANGE, ftPRange}, /* usually matches HDR_RANGE */ - {"Retry-After", HDR_RETRY_AFTER, ftStr}, /* for now (ftDate_1123 or ftInt!) */ - {"Server", HDR_SERVER, ftStr}, - {"Set-Cookie", HDR_SET_COOKIE, ftStr}, - {"Title", HDR_TITLE, ftStr}, - {"Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr}, - {"Upgrade", HDR_UPGRADE, ftStr}, /* for now */ - {"User-Agent", HDR_USER_AGENT, ftStr}, - {"Vary", HDR_VARY, ftStr}, /* for now */ - {"Via", HDR_VIA, ftStr}, /* for now */ - {"Warning", HDR_WARNING, ftStr}, /* for now */ - {"WWW-Authenticate", HDR_WWW_AUTHENTICATE, ftStr}, - {"Authentication-Info", HDR_AUTHENTICATION_INFO, ftStr}, - {"X-Cache", HDR_X_CACHE, ftStr}, - {"X-Cache-Lookup", HDR_X_CACHE_LOOKUP, ftStr}, - {"X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr}, - {"X-Request-URI", HDR_X_REQUEST_URI, ftStr}, - {"X-Squid-Error", HDR_X_SQUID_ERROR, ftStr}, - {"Negotiate", HDR_NEGOTIATE, ftStr}, + { + {"Accept", HDR_ACCEPT, ftStr}, + + {"Accept-Charset", HDR_ACCEPT_CHARSET, ftStr}, + {"Accept-Encoding", HDR_ACCEPT_ENCODING, ftStr}, + {"Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr}, + {"Accept-Ranges", HDR_ACCEPT_RANGES, ftStr}, + {"Age", HDR_AGE, ftInt}, + {"Allow", HDR_ALLOW, ftStr}, + {"Authorization", HDR_AUTHORIZATION, ftStr}, /* for now */ + {"Cache-Control", HDR_CACHE_CONTROL, ftPCc}, + {"Connection", HDR_CONNECTION, ftStr}, + {"Content-Base", HDR_CONTENT_BASE, ftStr}, + {"Content-Encoding", HDR_CONTENT_ENCODING, ftStr}, + {"Content-Language", HDR_CONTENT_LANGUAGE, ftStr}, + {"Content-Length", HDR_CONTENT_LENGTH, ftInt}, + {"Content-Location", HDR_CONTENT_LOCATION, ftStr}, + {"Content-MD5", HDR_CONTENT_MD5, ftStr}, /* for now */ + {"Content-Range", HDR_CONTENT_RANGE, ftPContRange}, + {"Content-Type", HDR_CONTENT_TYPE, ftStr}, + {"Cookie", HDR_COOKIE, ftStr}, + {"Date", HDR_DATE, ftDate_1123}, + {"ETag", HDR_ETAG, ftETag}, + {"Expires", HDR_EXPIRES, ftDate_1123}, + {"From", HDR_FROM, ftStr}, + {"Host", HDR_HOST, ftStr}, + {"If-Match", HDR_IF_MATCH, ftStr}, /* for now */ + {"If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123}, + {"If-None-Match", HDR_IF_NONE_MATCH, ftStr}, /* for now */ + {"If-Range", HDR_IF_RANGE, ftDate_1123_or_ETag}, + {"Last-Modified", HDR_LAST_MODIFIED, ftDate_1123}, + {"Link", HDR_LINK, ftStr}, + {"Location", HDR_LOCATION, ftStr}, + {"Max-Forwards", HDR_MAX_FORWARDS, ftInt}, + {"Mime-Version", HDR_MIME_VERSION, ftStr}, /* for now */ + {"Pragma", HDR_PRAGMA, ftStr}, + {"Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr}, + {"Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr}, + {"Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr}, + {"Proxy-Connection", HDR_PROXY_CONNECTION, ftStr}, + {"Public", HDR_PUBLIC, ftStr}, + {"Range", HDR_RANGE, ftPRange}, + {"Referer", HDR_REFERER, ftStr}, + {"Request-Range", HDR_REQUEST_RANGE, ftPRange}, /* usually matches HDR_RANGE */ + {"Retry-After", HDR_RETRY_AFTER, ftStr}, /* for now (ftDate_1123 or ftInt!) */ + {"Server", HDR_SERVER, ftStr}, + {"Set-Cookie", HDR_SET_COOKIE, ftStr}, + {"Title", HDR_TITLE, ftStr}, + {"Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr}, + {"Upgrade", HDR_UPGRADE, ftStr}, /* for now */ + {"User-Agent", HDR_USER_AGENT, ftStr}, + {"Vary", HDR_VARY, ftStr}, /* for now */ + {"Via", HDR_VIA, ftStr}, /* for now */ + {"Warning", HDR_WARNING, ftStr}, /* for now */ + {"WWW-Authenticate", HDR_WWW_AUTHENTICATE, ftStr}, + {"Authentication-Info", HDR_AUTHENTICATION_INFO, ftStr}, + {"X-Cache", HDR_X_CACHE, ftStr}, + {"X-Cache-Lookup", HDR_X_CACHE_LOOKUP, ftStr}, + {"X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr}, + {"X-Request-URI", HDR_X_REQUEST_URI, ftStr}, + {"X-Squid-Error", HDR_X_SQUID_ERROR, ftStr}, + {"Negotiate", HDR_NEGOTIATE, ftStr}, #if X_ACCELERATOR_VARY - {"X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr}, + {"X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr}, #endif - {"Front-End-Https", HDR_FRONT_END_HTTPS, ftStr}, - {"Other:", HDR_OTHER, ftStr} /* ':' will not allow matches */ -}; + {"Front-End-Https", HDR_FRONT_END_HTTPS, ftStr}, + {"Other:", HDR_OTHER, ftStr} /* ':' will not allow matches */ + }; + static HttpHeaderFieldInfo *Headers = NULL; http_hdr_type &operator++ (http_hdr_type &aHeader) @@ -150,88 +152,88 @@ http_hdr_type &operator++ (http_hdr_type &aHeader) */ static HttpHeaderMask ListHeadersMask; /* set run-time using ListHeadersArr */ static http_hdr_type ListHeadersArr[] = -{ - HDR_ACCEPT, - HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE, - HDR_ACCEPT_RANGES, HDR_ALLOW, - HDR_CACHE_CONTROL, - HDR_CONTENT_ENCODING, - HDR_CONTENT_LANGUAGE, - HDR_CONNECTION, - HDR_IF_MATCH, HDR_IF_NONE_MATCH, - HDR_LINK, HDR_PRAGMA, - HDR_PROXY_CONNECTION, - HDR_TRANSFER_ENCODING, - HDR_UPGRADE, - HDR_VARY, - HDR_VIA, - /* HDR_WARNING, */ - HDR_WWW_AUTHENTICATE, - HDR_AUTHENTICATION_INFO, - HDR_PROXY_AUTHENTICATION_INFO, - /* HDR_EXPECT, HDR_TE, HDR_TRAILER */ + { + HDR_ACCEPT, + HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE, + HDR_ACCEPT_RANGES, HDR_ALLOW, + HDR_CACHE_CONTROL, + HDR_CONTENT_ENCODING, + HDR_CONTENT_LANGUAGE, + HDR_CONNECTION, + HDR_IF_MATCH, HDR_IF_NONE_MATCH, + HDR_LINK, HDR_PRAGMA, + HDR_PROXY_CONNECTION, + HDR_TRANSFER_ENCODING, + HDR_UPGRADE, + HDR_VARY, + HDR_VIA, + /* HDR_WARNING, */ + HDR_WWW_AUTHENTICATE, + HDR_AUTHENTICATION_INFO, + HDR_PROXY_AUTHENTICATION_INFO, + /* HDR_EXPECT, HDR_TE, HDR_TRAILER */ #if X_ACCELERATOR_VARY - HDR_X_ACCELERATOR_VARY, + HDR_X_ACCELERATOR_VARY, #endif - HDR_X_FORWARDED_FOR -}; + HDR_X_FORWARDED_FOR + }; /* general-headers */ static http_hdr_type GeneralHeadersArr[] = -{ - HDR_CACHE_CONTROL, HDR_CONNECTION, HDR_DATE, HDR_PRAGMA, - HDR_TRANSFER_ENCODING, - HDR_UPGRADE, - /* HDR_TRAILER, */ - HDR_VIA -}; + { + HDR_CACHE_CONTROL, HDR_CONNECTION, HDR_DATE, HDR_PRAGMA, + HDR_TRANSFER_ENCODING, + HDR_UPGRADE, + /* HDR_TRAILER, */ + HDR_VIA + }; /* entity-headers */ static http_hdr_type EntityHeadersArr[] = -{ - HDR_ALLOW, HDR_CONTENT_BASE, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, - HDR_CONTENT_LENGTH, HDR_CONTENT_LOCATION, HDR_CONTENT_MD5, - HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, HDR_ETAG, HDR_EXPIRES, HDR_LAST_MODIFIED, HDR_LINK, - HDR_OTHER -}; + { + HDR_ALLOW, HDR_CONTENT_BASE, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, + HDR_CONTENT_LENGTH, HDR_CONTENT_LOCATION, HDR_CONTENT_MD5, + HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, HDR_ETAG, HDR_EXPIRES, HDR_LAST_MODIFIED, HDR_LINK, + HDR_OTHER + }; static HttpHeaderMask ReplyHeadersMask; /* set run-time using ReplyHeaders */ static http_hdr_type ReplyHeadersArr[] = -{ - HDR_ACCEPT, HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE, - HDR_ACCEPT_RANGES, HDR_AGE, - HDR_LOCATION, HDR_MAX_FORWARDS, - HDR_MIME_VERSION, HDR_PUBLIC, HDR_RETRY_AFTER, HDR_SERVER, HDR_SET_COOKIE, - HDR_VARY, - HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE, - HDR_X_CACHE_LOOKUP, - HDR_X_REQUEST_URI, + { + HDR_ACCEPT, HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE, + HDR_ACCEPT_RANGES, HDR_AGE, + HDR_LOCATION, HDR_MAX_FORWARDS, + HDR_MIME_VERSION, HDR_PUBLIC, HDR_RETRY_AFTER, HDR_SERVER, HDR_SET_COOKIE, + HDR_VARY, + HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE, + HDR_X_CACHE_LOOKUP, + HDR_X_REQUEST_URI, #if X_ACCELERATOR_VARY - HDR_X_ACCELERATOR_VARY, + HDR_X_ACCELERATOR_VARY, #endif - HDR_X_SQUID_ERROR -}; + HDR_X_SQUID_ERROR + }; static HttpHeaderMask RequestHeadersMask; /* set run-time using RequestHeaders */ static http_hdr_type RequestHeadersArr[] = -{ - HDR_AUTHORIZATION, HDR_FROM, HDR_HOST, - HDR_IF_MATCH, HDR_IF_MODIFIED_SINCE, HDR_IF_NONE_MATCH, - HDR_IF_RANGE, HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION, - HDR_PROXY_AUTHORIZATION, HDR_RANGE, HDR_REFERER, HDR_REQUEST_RANGE, - HDR_USER_AGENT, HDR_X_FORWARDED_FOR -}; + { + HDR_AUTHORIZATION, HDR_FROM, HDR_HOST, + HDR_IF_MATCH, HDR_IF_MODIFIED_SINCE, HDR_IF_NONE_MATCH, + HDR_IF_RANGE, HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION, + HDR_PROXY_AUTHORIZATION, HDR_RANGE, HDR_REFERER, HDR_REQUEST_RANGE, + HDR_USER_AGENT, HDR_X_FORWARDED_FOR + }; /* header accounting */ static HttpHeaderStat HttpHeaderStats[] = -{ - {"all"}, + { + {"all"}, #if USE_HTCP - {"HTCP reply"}, + {"HTCP reply"}, #endif - {"request"}, - {"reply"} -}; + {"request"}, + {"reply"} + }; static int HttpHeaderStatCount = countof(HttpHeaderStats); static int HeaderEntryParsedCount = 0; @@ -262,33 +264,52 @@ httpHeaderInitModule(void) assert(8 * sizeof(HttpHeaderMask) >= HDR_ENUM_END); /* all headers must be described */ assert(countof(HeadersAttrs) == HDR_ENUM_END); + if (!Headers) - Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + /* create masks */ httpHeaderMaskInit(&ListHeadersMask, 0); + httpHeaderCalcMask(&ListHeadersMask, (const int *) ListHeadersArr, countof(ListHeadersArr)); + httpHeaderMaskInit(&ReplyHeadersMask, 0); + httpHeaderCalcMask(&ReplyHeadersMask, (const int *) ReplyHeadersArr, countof(ReplyHeadersArr)); + httpHeaderCalcMask(&ReplyHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr)); + httpHeaderCalcMask(&ReplyHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr)); + httpHeaderMaskInit(&RequestHeadersMask, 0); + httpHeaderCalcMask(&RequestHeadersMask, (const int *) RequestHeadersArr, countof(RequestHeadersArr)); + httpHeaderCalcMask(&RequestHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr)); + httpHeaderCalcMask(&RequestHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr)); + /* init header stats */ assert(HttpHeaderStatCount == hoReply + 1); + for (i = 0; i < HttpHeaderStatCount; i++) - httpHeaderStatInit(HttpHeaderStats + i, HttpHeaderStats[i].label); + httpHeaderStatInit(HttpHeaderStats + i, HttpHeaderStats[i].label); + HttpHeaderStats[hoRequest].owner_mask = &RequestHeadersMask; + HttpHeaderStats[hoReply].owner_mask = &ReplyHeadersMask; + #if USE_HTCP + HttpHeaderStats[hoHtcpReply].owner_mask = &ReplyHeadersMask; + #endif /* init dependent modules */ httpHdrCcInitModule(); + /* register with cache manager */ cachemgrRegister("http_headers", - "HTTP Header Statistics", httpHeaderStoreReport, 0, 1); + "HTTP Header Statistics", httpHeaderStoreReport, 0, 1); } void @@ -339,17 +360,20 @@ httpHeaderClean(HttpHeader * hdr) statHistCount(&HttpHeaderStats[hdr->owner].hdrUCountDistr, hdr->entries.count); HttpHeaderStats[hdr->owner].destroyedCount++; HttpHeaderStats[hdr->owner].busyDestroyedCount += hdr->entries.count > 0; + while ((e = httpHeaderGetEntry(hdr, &pos))) { - /* tmp hack to try to avoid coredumps */ - if (e->id < 0 || e->id >= HDR_ENUM_END) { - debug(55, 0) ("httpHeaderClean BUG: entry[%d] is invalid (%d). Ignored.\n", - (int) pos, e->id); - } else { - statHistCount(&HttpHeaderStats[hdr->owner].fieldTypeDistr, e->id); - /* yes, this destroy() leaves us in an incosistent state */ - httpHeaderEntryDestroy(e); - } + /* tmp hack to try to avoid coredumps */ + + if (e->id < 0 || e->id >= HDR_ENUM_END) { + debug(55, 0) ("httpHeaderClean BUG: entry[%d] is invalid (%d). Ignored.\n", + (int) pos, e->id); + } else { + statHistCount(&HttpHeaderStats[hdr->owner].fieldTypeDistr, e->id); + /* yes, this destroy() leaves us in an incosistent state */ + httpHeaderEntryDestroy(e); + } } + arrayClean(&hdr->entries); } @@ -364,7 +388,7 @@ httpHeaderAppend(HttpHeader * dest, const HttpHeader * src) debug(55, 7) ("appending hdr: %p += %p\n", dest, src); while ((e = httpHeaderGetEntry(src, &pos))) { - httpHeaderAddEntry(dest, httpHeaderEntryClone(e)); + httpHeaderAddEntry(dest, httpHeaderEntryClone(e)); } } @@ -379,11 +403,14 @@ httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMas debug(55, 7) ("updating hdr: %p <- %p\n", old, fresh); while ((e = httpHeaderGetEntry(fresh, &pos))) { - /* deny bad guys (ok to check for HDR_OTHER) here */ - if (denied_mask && CBIT_TEST(*denied_mask, e->id)) - continue; - httpHeaderDelByName(old, e->name.buf()); - httpHeaderAddEntry(old, httpHeaderEntryClone(e)); + /* deny bad guys (ok to check for HDR_OTHER) here */ + + if (denied_mask && CBIT_TEST(*denied_mask, e->id)) + continue; + + httpHeaderDelByName(old, e->name.buf()); + + httpHeaderAddEntry(old, httpHeaderEntryClone(e)); } } @@ -410,33 +437,43 @@ httpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_e debug(55, 7) ("parsing hdr: (%p)\n%s\n", hdr, getStringPrefix(header_start, header_end)); HttpHeaderStats[hdr->owner].parsedCount++; /* commonn format headers are ":[ws]" lines delimited by */ + while (field_start < header_end) { - const char *field_end; - const char *field_ptr = field_start; - do { - field_end = field_ptr = field_ptr + strcspn(field_ptr, "\r\n"); - /* skip CRLF */ - if (*field_ptr == '\r') - field_ptr++; - if (*field_ptr == '\n') - field_ptr++; - } - while (*field_ptr == ' ' || *field_ptr == '\t'); - if (!*field_end || field_end > header_end) - return httpHeaderReset(hdr); /* missing */ - e = httpHeaderEntryParseCreate(field_start, field_end); - if (e != NULL) - httpHeaderAddEntry(hdr, e); - else - debug(55, 2) ("warning: ignoring unparseable http header field near '%s'\n", - getStringPrefix(field_start, field_end)); - field_start = field_end; - /* skip CRLF */ - if (*field_start == '\r') - field_start++; - if (*field_start == '\n') - field_start++; + const char *field_end; + const char *field_ptr = field_start; + + do { + field_end = field_ptr = field_ptr + strcspn(field_ptr, "\r\n"); + /* skip CRLF */ + + if (*field_ptr == '\r') + field_ptr++; + + if (*field_ptr == '\n') + field_ptr++; + } while (*field_ptr == ' ' || *field_ptr == '\t'); + + if (!*field_end || field_end > header_end) + return httpHeaderReset(hdr); /* missing */ + + e = httpHeaderEntryParseCreate(field_start, field_end); + + if (e != NULL) + httpHeaderAddEntry(hdr, e); + else + debug(55, 2) ("warning: ignoring unparseable http header field near '%s'\n", + getStringPrefix(field_start, field_end)); + + field_start = field_end; + + /* skip CRLF */ + if (*field_start == '\r') + field_start++; + + if (*field_start == '\n') + field_start++; } + return 1; /* even if no fields where found, it is a valid header */ } @@ -449,8 +486,9 @@ httpHeaderPackInto(const HttpHeader * hdr, Packer * p) assert(hdr && p); debug(55, 7) ("packing hdr: (%p)\n", hdr); /* pack all entries one by one */ + while ((e = httpHeaderGetEntry(hdr, &pos))) - httpHeaderEntryPackInto(e, p); + httpHeaderEntryPackInto(e, p); } /* returns next valid entry */ @@ -459,10 +497,12 @@ httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos) { assert(hdr && pos); assert(*pos >= HttpHeaderInitPos && *pos < (ssize_t)hdr->entries.count); + for ((*pos)++; *pos < (ssize_t)hdr->entries.count; (*pos)++) { - if (hdr->entries.items[*pos]) - return (HttpHeaderEntry*)hdr->entries.items[*pos]; + if (hdr->entries.items[*pos]) + return (HttpHeaderEntry*)hdr->entries.items[*pos]; } + return NULL; } @@ -481,15 +521,19 @@ httpHeaderFindEntry(const HttpHeader * hdr, http_hdr_type id) assert(!CBIT_TEST(ListHeadersMask, id)); /* check mask first */ + if (!CBIT_TEST(hdr->mask, id)) - return NULL; + return NULL; + /* looks like we must have it, do linear search */ while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (e->id == id) - return e; + if (e->id == id) + return e; } + /* hm.. we thought it was there, but it was not found */ assert(0); + return NULL; /* not reached */ } @@ -507,13 +551,16 @@ httpHeaderFindLastEntry(const HttpHeader * hdr, http_hdr_type id) assert(!CBIT_TEST(ListHeadersMask, id)); /* check mask first */ + if (!CBIT_TEST(hdr->mask, id)) - return NULL; + return NULL; + /* looks like we must have it, do linear search */ while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (e->id == id) - result = e; + if (e->id == id) + result = e; } + assert(result); /* must be there! */ return result; } @@ -529,13 +576,15 @@ httpHeaderDelByName(HttpHeader * hdr, const char *name) HttpHeaderEntry *e; httpHeaderMaskInit(&hdr->mask, 0); /* temporal inconsistency */ debug(55, 7) ("deleting '%s' fields in hdr %p\n", name, hdr); + while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (!strCaseCmp(e->name, name)) { - httpHeaderDelAt(hdr, pos); - count++; - } else - CBIT_SET(hdr->mask, e->id); + if (!strCaseCmp(e->name, name)) { + httpHeaderDelAt(hdr, pos); + count++; + } else + CBIT_SET(hdr->mask, e->id); } + return count; } @@ -550,14 +599,17 @@ httpHeaderDelById(HttpHeader * hdr, http_hdr_type id) assert(hdr); assert_eid(id); assert_eid(id != HDR_OTHER); /* does not make sense */ + if (!CBIT_TEST(hdr->mask, id)) - return 0; + return 0; + while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (e->id == id) { - httpHeaderDelAt(hdr, pos); - count++; - } + if (e->id == id) { + httpHeaderDelAt(hdr, pos); + count++; + } } + CBIT_CLR(hdr->mask, id); assert(count); return count; @@ -581,7 +633,7 @@ httpHeaderDelAt(HttpHeader * hdr, HttpHeaderPos pos) } -/* appends an entry; +/* appends an entry; * does not call httpHeaderEntryClone() so one should not reuse "*e" */ void @@ -591,12 +643,15 @@ httpHeaderAddEntry(HttpHeader * hdr, HttpHeaderEntry * e) assert_eid(e->id); debug(55, 7) ("%p adding entry: %d at %d\n", - hdr, e->id, hdr->entries.count); + hdr, e->id, hdr->entries.count); + if (CBIT_TEST(hdr->mask, e->id)) - Headers[e->id].stat.repCount++; + Headers[e->id].stat.repCount++; else - CBIT_SET(hdr->mask, e->id); + CBIT_SET(hdr->mask, e->id); + arrayAppend(&hdr->entries, e); + /* increment header length, allow for ": " and crlf */ hdr->len += e->name.size() + 2 + e->value.size() + 2; } @@ -611,21 +666,27 @@ httpHeaderGetList(const HttpHeader * hdr, http_hdr_type id) debug(55, 6) ("%p: joining for id %d\n", hdr, id); /* only fields from ListHeaders array can be "listed" */ assert(CBIT_TEST(ListHeadersMask, id)); + if (!CBIT_TEST(hdr->mask, id)) - return s; + return s; + while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (e->id == id) - strListAdd(&s, e->value.buf(), ','); + if (e->id == id) + strListAdd(&s, e->value.buf(), ','); } + /* * note: we might get an empty (len==0) string if there was an "empty" * header; we must not get a NULL string though. */ assert(s.buf()); + /* temporary warning: remove it! @?@ @?@ @?@ */ if (!s.size()) - debug(55, 3) ("empty list header: %s (%d)\n", Headers[id].name.buf(), id); + debug(55, 3) ("empty list header: %s (%d)\n", Headers[id].name.buf(), id); + debug(55, 6) ("%p: joined for id %d: %s\n", hdr, id, s.buf()); + return s; } @@ -636,9 +697,11 @@ httpHeaderGetStrOrList(const HttpHeader * hdr, http_hdr_type id) HttpHeaderEntry *e; if (CBIT_TEST(ListHeadersMask, id)) - return httpHeaderGetList(hdr, id); + return httpHeaderGetList(hdr, id); + if ((e = httpHeaderFindEntry(hdr, id))) - return e->value; + return e->value; + return String::Null; } @@ -658,15 +721,17 @@ httpHeaderGetByName(const HttpHeader * hdr, const char *name) /* First try the quick path */ id = httpHeaderIdByNameDef(name, strlen(name)); + if (id != -1) - return httpHeaderGetStrOrList(hdr, id); + return httpHeaderGetStrOrList(hdr, id); /* Sorry, an unknown header name. Do linear search */ while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (e->id == HDR_OTHER && strCaseCmp(e->name, name) == 0) { - strListAdd(&result, e->value.buf(), ','); - } + if (e->id == HDR_OTHER && strCaseCmp(e->name, name) == 0) { + strListAdd(&result, e->value.buf(), ','); + } } + return result; } @@ -689,11 +754,12 @@ httpHeaderGetByNameListMember(const HttpHeader * hdr, const char *name, const ch header = httpHeaderGetByName(hdr, name); while (strListGetItem(&header, separator, &item, &ilen, &pos)) { - if (strncmp(item, member, mlen) == 0 && item[mlen] == '=') { - result.append(item + mlen + 1, ilen - mlen - 1); - break; - } + if (strncmp(item, member, mlen) == 0 && item[mlen] == '=') { + result.append(item + mlen + 1, ilen - mlen - 1); + break; + } } + return result; } @@ -716,11 +782,12 @@ httpHeaderGetListMember(const HttpHeader * hdr, http_hdr_type id, const char *me header = httpHeaderGetStrOrList(hdr, id); while (strListGetItem(&header, separator, &item, &ilen, &pos)) { - if (strncmp(item, member, mlen) == 0 && item[mlen] == '=') { - result.append(item + mlen + 1, ilen - mlen - 1); - break; - } + if (strncmp(item, member, mlen) == 0 && item[mlen] == '=') { + result.append(item + mlen + 1, ilen - mlen - 1); + break; + } } + header.clean(); return result; } @@ -858,8 +925,10 @@ httpHeaderGetInt(const HttpHeader * hdr, http_hdr_type id) assert_eid(id); assert(Headers[id].type == ftInt); /* must be of an appropriate type */ HttpHeaderEntry *e; + if ((e = httpHeaderFindEntry(hdr, id))) - return httpHeaderEntryGetInt (e); + return httpHeaderEntryGetInt (e); + return -1; } @@ -870,10 +939,12 @@ httpHeaderGetTime(const HttpHeader * hdr, http_hdr_type id) time_t value = -1; assert_eid(id); assert(Headers[id].type == ftDate_1123); /* must be of an appropriate type */ + if ((e = httpHeaderFindEntry(hdr, id))) { - value = parse_rfc1123(e->value.buf()); - httpHeaderNoteParsedEntry(e->id, e->value, value < 0); + value = parse_rfc1123(e->value.buf()); + httpHeaderNoteParsedEntry(e->id, e->value, value < 0); } + return value; } @@ -884,10 +955,12 @@ httpHeaderGetStr(const HttpHeader * hdr, http_hdr_type id) HttpHeaderEntry *e; assert_eid(id); assert(Headers[id].type == ftStr); /* must be of an appropriate type */ + if ((e = httpHeaderFindEntry(hdr, id))) { - httpHeaderNoteParsedEntry(e->id, e->value, 0); /* no errors are possible */ - return e->value.buf(); + httpHeaderNoteParsedEntry(e->id, e->value, 0); /* no errors are possible */ + return e->value.buf(); } + return NULL; } @@ -898,10 +971,12 @@ httpHeaderGetLastStr(const HttpHeader * hdr, http_hdr_type id) HttpHeaderEntry *e; assert_eid(id); assert(Headers[id].type == ftStr); /* must be of an appropriate type */ + if ((e = httpHeaderFindLastEntry(hdr, id))) { - httpHeaderNoteParsedEntry(e->id, e->value, 0); /* no errors are possible */ - return e->value.buf(); + httpHeaderNoteParsedEntry(e->id, e->value, 0); /* no errors are possible */ + return e->value.buf(); } + return NULL; } @@ -910,15 +985,23 @@ httpHeaderGetCc(const HttpHeader * hdr) { HttpHdrCc *cc; String s; + if (!CBIT_TEST(hdr->mask, HDR_CACHE_CONTROL)) - return NULL; + return NULL; + s = httpHeaderGetList(hdr, HDR_CACHE_CONTROL); + cc = httpHdrCcParseCreate(&s); + HttpHeaderStats[hdr->owner].ccParsedCount++; + if (cc) - httpHdrCcUpdateStats(cc, &HttpHeaderStats[hdr->owner].ccTypeDistr); + httpHdrCcUpdateStats(cc, &HttpHeaderStats[hdr->owner].ccTypeDistr); + httpHeaderNoteParsedEntry(HDR_CACHE_CONTROL, s, !cc); + s.clean(); + return cc; } @@ -931,11 +1014,13 @@ httpHeaderGetRange(const HttpHeader * hdr) * who knows, some clients might send Request-Range only; * this "if" should work correctly in both cases; * hopefully no clients send mismatched headers! */ + if ((e = httpHeaderFindEntry(hdr, HDR_RANGE)) || - (e = httpHeaderFindEntry(hdr, HDR_REQUEST_RANGE))) { - r = HttpHdrRange::ParseCreate(&e->value); - httpHeaderNoteParsedEntry(e->id, e->value, !r); + (e = httpHeaderFindEntry(hdr, HDR_REQUEST_RANGE))) { + r = HttpHdrRange::ParseCreate(&e->value); + httpHeaderNoteParsedEntry(e->id, e->value, !r); } + return r; } @@ -944,10 +1029,12 @@ httpHeaderGetContRange(const HttpHeader * hdr) { HttpHdrContRange *cr = NULL; HttpHeaderEntry *e; + if ((e = httpHeaderFindEntry(hdr, HDR_CONTENT_RANGE))) { - cr = httpHdrContRangeParseCreate(e->value.buf()); - httpHeaderNoteParsedEntry(e->id, e->value, !cr); + cr = httpHdrContRangeParseCreate(e->value.buf()); + httpHeaderNoteParsedEntry(e->id, e->value, !cr); } + return cr; } @@ -958,18 +1045,26 @@ httpHeaderGetAuth(const HttpHeader * hdr, http_hdr_type id, const char *auth_sch int l; assert(hdr && auth_scheme); field = httpHeaderGetStr(hdr, id); + if (!field) /* no authorization field */ - return NULL; + return NULL; + l = strlen(auth_scheme); + if (!l || strncasecmp(field, auth_scheme, l)) /* wrong scheme */ - return NULL; + return NULL; + field += l; + if (!xisspace(*field)) /* wrong scheme */ - return NULL; + return NULL; + /* skip white space */ field += xcountws(field); + if (!*field) /* no authorization cookie */ - return NULL; + return NULL; + return base64_decode(field); } @@ -977,11 +1072,13 @@ ETag httpHeaderGetETag(const HttpHeader * hdr, http_hdr_type id) { ETag etag = - {NULL, -1}; + {NULL, -1}; HttpHeaderEntry *e; assert(Headers[id].type == ftETag); /* must be of an appropriate type */ + if ((e = httpHeaderFindEntry(hdr, id))) - etagParseInit(&etag, e->value.buf()); + etagParseInit(&etag, e->value.buf()); + return etag; } @@ -992,19 +1089,22 @@ httpHeaderGetTimeOrTag(const HttpHeader * hdr, http_hdr_type id) HttpHeaderEntry *e; assert(Headers[id].type == ftDate_1123_or_ETag); /* must be of an appropriate type */ memset(&tot, 0, sizeof(tot)); + if ((e = httpHeaderFindEntry(hdr, id))) { - const char *str = e->value.buf(); - /* try as an ETag */ - if (etagParseInit(&tot.tag, str)) { - tot.valid = tot.tag.str != NULL; - tot.time = -1; - } else { - /* or maybe it is time? */ - tot.time = parse_rfc1123(str); - tot.valid = tot.time >= 0; - tot.tag.str = NULL; - } + const char *str = e->value.buf(); + /* try as an ETag */ + + if (etagParseInit(&tot.tag, str)) { + tot.valid = tot.tag.str != NULL; + tot.time = -1; + } else { + /* or maybe it is time? */ + tot.time = parse_rfc1123(str); + tot.valid = tot.time >= 0; + tot.tag.str = NULL; + } } + assert(tot.time < 0 || !tot.tag.str); /* paranoid */ return tot; } @@ -1020,13 +1120,18 @@ httpHeaderEntryCreate(http_hdr_type id, const char *name, const char *value) assert_eid(id); e = (HttpHeaderEntry *)memAllocate(MEM_HTTP_HDR_ENTRY); e->id = id; + if (id != HDR_OTHER) - e->name = Headers[id].name; + e->name = Headers[id].name; else - e->name = name; + e->name = name; + e->value = value; + Headers[id].stat.aliveCount++; + debug(55, 9) ("created entry %p: '%s: %s'\n", e, e->name.buf(), e->value.buf()); + return e; } @@ -1037,12 +1142,18 @@ httpHeaderEntryDestroy(HttpHeaderEntry * e) assert_eid(e->id); debug(55, 9) ("destroying entry %p: '%s: %s'\n", e, e->name.buf(), e->value.buf()); /* clean name if needed */ + if (e->id == HDR_OTHER) - e->name.clean(); + e->name.clean(); + e->value.clean(); + assert(Headers[e->id].stat.aliveCount); + Headers[e->id].stat.aliveCount--; + e->id = HDR_BAD_HDR; + memFree(e, MEM_HTTP_HDR_ENTRY); } @@ -1061,44 +1172,63 @@ httpHeaderEntryParseCreate(const char *field_start, const char *field_end) HeaderEntryParsedCount++; /* do we have a valid field name within this field? */ + if (!name_len || name_end > field_end) - return NULL; + return NULL; + if (name_len > 65536) { - /* String has a 64K limit */ - debug(55, 1) ("WARNING: ignoring header name of %d bytes\n", name_len); - return NULL; + /* String has a 64K limit */ + debug(55, 1) ("WARNING: ignoring header name of %d bytes\n", name_len); + return NULL; } + /* now we know we can parse it */ e = (HttpHeaderEntry *)memAllocate(MEM_HTTP_HDR_ENTRY); + debug(55, 9) ("creating entry %p: near '%s'\n", e, getStringPrefix(field_start, field_end)); + /* is it a "known" field? */ id = httpHeaderIdByName(field_start, name_len, Headers, HDR_ENUM_END); + if (id < 0) - id = HDR_OTHER; + id = HDR_OTHER; + assert_eid(id); + e->id = id; + /* set field name */ if (id == HDR_OTHER) - e->name.limitInit(field_start, name_len); + e->name.limitInit(field_start, name_len); else - e->name = Headers[id].name; + e->name = Headers[id].name; + /* trim field value */ while (value_start < field_end && xisspace(*value_start)) - value_start++; + value_start++; + if (field_end - value_start > 65536) { - /* String has a 64K limit */ - debug(55, 1) ("WARNING: ignoring '%s' header of %d bytes\n", - e->name.buf(), (int) (field_end - value_start)); - if (e->id == HDR_OTHER) - e->name.clean(); - memFree(e, MEM_HTTP_HDR_ENTRY); - return NULL; + /* String has a 64K limit */ + debug(55, 1) ("WARNING: ignoring '%s' header of %d bytes\n", + e->name.buf(), (int) (field_end - value_start)); + + if (e->id == HDR_OTHER) + e->name.clean(); + + memFree(e, MEM_HTTP_HDR_ENTRY); + + return NULL; } + /* set field value */ e->value.limitInit(value_start, field_end - value_start); + Headers[id].stat.seenCount++; + Headers[id].stat.aliveCount++; + debug(55, 9) ("created entry %p: '%s: %s'\n", e, e->name.buf(), e->value.buf()); + return e; } @@ -1122,10 +1252,11 @@ static void httpHeaderNoteParsedEntry(http_hdr_type id, String context, int error) { Headers[id].stat.parsCount++; + if (error) { - Headers[id].stat.errCount++; - debug(55, 2) ("cannot parse hdr field: '%s: %s'\n", - Headers[id].name.buf(), context.buf()); + Headers[id].stat.errCount++; + debug(55, 2) ("cannot parse hdr field: '%s: %s'\n", + Headers[id].name.buf(), context.buf()); } } @@ -1145,20 +1276,22 @@ httpHeaderFieldStatDumper(StoreEntry * sentry, int idx, double val, double size, const char *name = valid_id ? Headers[id].name.buf() : "INVALID"; int visible = count > 0; /* for entries with zero count, list only those that belong to current type of message */ + if (!visible && valid_id && dump_stat->owner_mask) - visible = CBIT_TEST(*dump_stat->owner_mask, id); + visible = CBIT_TEST(*dump_stat->owner_mask, id); + if (visible) - storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", - id, name, count, xdiv(count, dump_stat->busyDestroyedCount)); + storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", + id, name, count, xdiv(count, dump_stat->busyDestroyedCount)); } static void httpHeaderFldsPerHdrDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) - storeAppendPrintf(sentry, "%2d\t %5d\t %5d\t %6.2f\n", - idx, (int) val, count, - xpercent(count, dump_stat->destroyedCount)); + storeAppendPrintf(sentry, "%2d\t %5d\t %5d\t %6.2f\n", + idx, (int) val, count, + xpercent(count, dump_stat->destroyedCount)); } @@ -1171,15 +1304,15 @@ httpHeaderStatDump(const HttpHeaderStat * hs, StoreEntry * e) storeAppendPrintf(e, "\nHeader Stats: %s\n", hs->label); storeAppendPrintf(e, "\nField type distribution\n"); storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n", - "id", "name", "count", "#/header"); + "id", "name", "count", "#/header"); statHistDump(&hs->fieldTypeDistr, e, httpHeaderFieldStatDumper); storeAppendPrintf(e, "\nCache-control directives distribution\n"); storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n", - "id", "name", "count", "#/cc_field"); + "id", "name", "count", "#/cc_field"); statHistDump(&hs->ccTypeDistr, e, httpHdrCcStatDumper); storeAppendPrintf(e, "\nNumber of fields per header distribution\n"); storeAppendPrintf(e, "%2s\t %-5s\t %5s\t %6s\n", - "id", "#flds", "count", "%total"); + "id", "#flds", "count", "%total"); statHistDump(&hs->hdrUCountDistr, e, httpHeaderFldsPerHdrDumper); dump_stat = NULL; } @@ -1192,33 +1325,37 @@ httpHeaderStoreReport(StoreEntry * e) assert(e); HttpHeaderStats[0].parsedCount = - HttpHeaderStats[hoRequest].parsedCount + HttpHeaderStats[hoReply].parsedCount; + HttpHeaderStats[hoRequest].parsedCount + HttpHeaderStats[hoReply].parsedCount; HttpHeaderStats[0].ccParsedCount = - HttpHeaderStats[hoRequest].ccParsedCount + HttpHeaderStats[hoReply].ccParsedCount; + HttpHeaderStats[hoRequest].ccParsedCount + HttpHeaderStats[hoReply].ccParsedCount; HttpHeaderStats[0].destroyedCount = - HttpHeaderStats[hoRequest].destroyedCount + HttpHeaderStats[hoReply].destroyedCount; + HttpHeaderStats[hoRequest].destroyedCount + HttpHeaderStats[hoReply].destroyedCount; HttpHeaderStats[0].busyDestroyedCount = - HttpHeaderStats[hoRequest].busyDestroyedCount + HttpHeaderStats[hoReply].busyDestroyedCount; + HttpHeaderStats[hoRequest].busyDestroyedCount + HttpHeaderStats[hoReply].busyDestroyedCount; for (i = 1; i < HttpHeaderStatCount; i++) { - httpHeaderStatDump(HttpHeaderStats + i, e); - storeAppendPrintf(e, "%s\n", "
"); + httpHeaderStatDump(HttpHeaderStats + i, e); + storeAppendPrintf(e, "%s\n", "
"); } + /* field stats for all messages */ storeAppendPrintf(e, "\nHttp Fields Stats (replies and requests)\n"); + storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\t %6s\n", - "id", "name", "#alive", "%err", "%repeat"); + "id", "name", "#alive", "%err", "%repeat"); + for (ht = (http_hdr_type)0; ht < HDR_ENUM_END; ++ht) { - HttpHeaderFieldInfo *f = Headers + ht; - storeAppendPrintf(e, "%2d\t %-20s\t %5d\t %6.3f\t %6.3f\n", - f->id, f->name.buf(), f->stat.aliveCount, - xpercent(f->stat.errCount, f->stat.parsCount), - xpercent(f->stat.repCount, f->stat.seenCount)); + HttpHeaderFieldInfo *f = Headers + ht; + storeAppendPrintf(e, "%2d\t %-20s\t %5d\t %6.3f\t %6.3f\n", + f->id, f->name.buf(), f->stat.aliveCount, + xpercent(f->stat.errCount, f->stat.parsCount), + xpercent(f->stat.repCount, f->stat.seenCount)); } + storeAppendPrintf(e, "Headers Parsed: %d + %d = %d\n", - HttpHeaderStats[hoRequest].parsedCount, - HttpHeaderStats[hoReply].parsedCount, - HttpHeaderStats[0].parsedCount); + HttpHeaderStats[hoRequest].parsedCount, + HttpHeaderStats[hoReply].parsedCount, + HttpHeaderStats[0].parsedCount); storeAppendPrintf(e, "Hdr Fields Parsed: %d\n", HeaderEntryParsedCount); } @@ -1226,13 +1363,16 @@ http_hdr_type httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end) { int i; + for (i = 0; i < end; ++i) { - if (name_len >= 0 && name_len != info[i].name.size()) - continue; - if (!strncasecmp(name, info[i].name.buf(), - name_len < 0 ? info[i].name.size() + 1 : name_len)) - return info[i].id; + if (name_len >= 0 && name_len != info[i].name.size()) + continue; + + if (!strncasecmp(name, info[i].name.buf(), + name_len < 0 ? info[i].name.size() + 1 : name_len)) + return info[i].id; } + return HDR_BAD_HDR; } @@ -1240,7 +1380,8 @@ http_hdr_type httpHeaderIdByNameDef(const char *name, int name_len) { if (!Headers) - Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + return httpHeaderIdByName(name, name_len, Headers, HDR_ENUM_END); } @@ -1248,7 +1389,9 @@ const char * httpHeaderNameById(int id) { if (!Headers) - Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + assert(id >= 0 && id < HDR_ENUM_END); + return HeadersAttrs[id].name; } diff --git a/src/HttpHeader.h b/src/HttpHeader.h index dbb65aab92..fb0f8335c0 100644 --- a/src/HttpHeader.h +++ b/src/HttpHeader.h @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.h,v 1.2 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHeader.h,v 1.3 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -38,7 +38,9 @@ #include "HttpHeaderRange.h" /* constant attributes of http header fields */ -struct _HttpHeaderFieldAttrs { + +struct _HttpHeaderFieldAttrs +{ const char *name; http_hdr_type id; field_type type; diff --git a/src/HttpHeaderRange.h b/src/HttpHeaderRange.h index 7056872b32..e9e05e8195 100644 --- a/src/HttpHeaderRange.h +++ b/src/HttpHeaderRange.h @@ -1,6 +1,6 @@ /* - * $Id: HttpHeaderRange.h,v 1.1 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpHeaderRange.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -38,14 +38,17 @@ typedef struct _HttpReply HttpReply; /* http byte-range-spec */ -class HttpHdrRangeSpec { - public: + +class HttpHdrRangeSpec +{ + +public: void *operator new(size_t); void operator delete (void *); void deleteSelf() const; typedef Range HttpRange; static ssize_t const UnknownPosition; - + HttpHdrRangeSpec(); static HttpHdrRangeSpec *Create(const char *field, int fieldLen); @@ -56,6 +59,7 @@ class HttpHdrRangeSpec { bool mergeWith(const HttpHdrRangeSpec * donor); ssize_t offset; ssize_t length; + private: static MemPool *Pool; }; @@ -64,7 +68,10 @@ private: * This object holds all range specs in order of their appearence * in the request because we SHOULD preserve that order. */ -class HttpHdrRange { + +class HttpHdrRange +{ + public: void *operator new(size_t); void operator delete (void *); @@ -85,7 +92,7 @@ public: const_iterator begin () const; iterator end(); const_iterator end() const; - + /* adjust specs after the length is known */ int canonize(size_t); int canonize(HttpReply *rep); @@ -99,6 +106,7 @@ public: ssize_t lowestOffset(ssize_t) const; bool offsetLimitExceeded() const; Vector specs; + private: static MemPool *Pool; void getCanonizedSpecs (Vector ©); @@ -107,8 +115,11 @@ private: }; /* data for iterating thru range specs */ -class HttpHdrRangeIter { - public: + +class HttpHdrRangeIter +{ + +public: HttpHdrRange::iterator pos; const HttpHdrRangeSpec *currentSpec() const; void updateSpec(); @@ -118,4 +129,5 @@ class HttpHdrRangeIter { String boundary; /* boundary for multipart responses */ bool valid; }; + #endif /* SQUID_HTTPHEADERRANGE_H */ diff --git a/src/HttpHeaderTools.cc b/src/HttpHeaderTools.cc index 248b3cd141..2bcca3ecab 100644 --- a/src/HttpHeaderTools.cc +++ b/src/HttpHeaderTools.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpHeaderTools.cc,v 1.37 2003/02/12 06:10:58 robertc Exp $ + * $Id: HttpHeaderTools.cc,v 1.38 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 66 HTTP Header Tools * AUTHOR: Alex Rousskov @@ -55,20 +55,21 @@ httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count) table = (HttpHeaderFieldInfo *)xcalloc(count, sizeof(HttpHeaderFieldInfo)); for (i = 0; i < count; ++i) { - const http_hdr_type id = attrs[i].id; - HttpHeaderFieldInfo *info = table + id; - /* sanity checks */ - assert(id >= 0 && id < count); - assert(attrs[i].name); - assert(info->id == 0 && info->type == 0); /* was not set before */ - /* copy and init fields */ - info->id = id; - info->type = attrs[i].type; - info->name = attrs[i].name; - assert(info->name.size()); - /* init stats */ - memset(&info->stat, 0, sizeof(info->stat)); + const http_hdr_type id = attrs[i].id; + HttpHeaderFieldInfo *info = table + id; + /* sanity checks */ + assert(id >= 0 && id < count); + assert(attrs[i].name); + assert(info->id == 0 && info->type == 0); /* was not set before */ + /* copy and init fields */ + info->id = id; + info->type = attrs[i].type; + info->name = attrs[i].name; + assert(info->name.size()); + /* init stats */ + memset(&info->stat, 0, sizeof(info->stat)); } + return table; } @@ -76,8 +77,10 @@ void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * table, int count) { int i; + for (i = 0; i < count; ++i) - table[i].name.clean(); + table[i].name.clean(); + xfree(table); } @@ -96,8 +99,8 @@ httpHeaderCalcMask(HttpHeaderMask * mask, const int *enums, size_t count) assert(count < sizeof(*mask) * 8); /* check for overflow */ for (i = 0; i < count; ++i) { - assert(!CBIT_TEST(*mask, enums[i])); /* check for duplicates */ - CBIT_SET(*mask, enums[i]); + assert(!CBIT_TEST(*mask, enums[i])); /* check for duplicates */ + CBIT_SET(*mask, enums[i]); } } @@ -107,13 +110,14 @@ void httpHeaderPutStrf(HttpHeader * hdr, http_hdr_type id, const char *fmt,...) #else httpHeaderPutStrf(va_alist) - va_dcl +va_dcl #endif { #if STDC_HEADERS va_list args; va_start(args, fmt); #else + va_list args; HttpHeader *hdr = NULL; http_hdr_type id = HDR_ENUM_END; @@ -123,6 +127,7 @@ httpHeaderPutStrf(va_alist) id = va_arg(args, http_hdr_type); fmt = va_arg(args, char *); #endif + httpHeaderPutStrvf(hdr, id, fmt, args); va_end(args); } @@ -163,16 +168,20 @@ httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive) http_hdr_type ht; int res; /* what type of header do we have? */ + if (httpHeaderHas(hdr, HDR_PROXY_CONNECTION)) - ht = HDR_PROXY_CONNECTION; + ht = HDR_PROXY_CONNECTION; else if (httpHeaderHas(hdr, HDR_CONNECTION)) - ht = HDR_CONNECTION; + ht = HDR_CONNECTION; else - return 0; + return 0; list = httpHeaderGetList(hdr, ht); + res = strListIsMember(&list, directive, ','); + list.clean(); + return res; } @@ -186,10 +195,12 @@ strListIsMember(const String * list, const char *m, char del) int mlen; assert(list && m); mlen = strlen(m); + while (strListGetItem(list, del, &item, &ilen, &pos)) { - if (mlen == ilen && !strncasecmp(item, m, ilen)) - return 1; + if (mlen == ilen && !strncasecmp(item, m, ilen)) + return 1; } + return 0; } @@ -209,13 +220,16 @@ strListIsSubstr(const String * list, const char *s, char del) */ #ifdef BROKEN_CODE + const char *pos = NULL; const char *item; assert(list && s); + while (strListGetItem(list, del, &item, NULL, &pos)) { - if (strstr(item, s)) - return 1; + if (strstr(item, s)) + return 1; } + return 0; #endif } @@ -225,13 +239,15 @@ void strListAdd(String * str, const char *item, char del) { assert(str && item); + if (str->size()) { - char buf[3]; - buf[0] = del; - buf[1] = ' '; - buf[2] = '\0'; - str->append(buf, 2); + char buf[3]; + buf[0] = del; + buf[1] = ' '; + buf[2] = '\0'; + str->append(buf, 2); } + str->append(item, strlen(item)); } @@ -248,30 +264,39 @@ strListGetItem(const String * str, char del, const char **item, int *ilen, const { size_t len; assert(str && item && pos); + if (*pos) { - if (!**pos) /* end of string */ - return 0; - else - (*pos)++; + if (!**pos) /* end of string */ + return 0; + else + (*pos)++; } else { - *pos = str->buf(); - if (!*pos) - return 0; + *pos = str->buf(); + + if (!*pos) + return 0; } /* skip leading ws (ltrim) */ *pos += xcountws(*pos); + *item = *pos; /* remember item's start */ + /* find next delimiter */ *pos = strchr(*item, del); + if (!*pos) /* last item */ - *pos = *item + strlen(*item); + *pos = *item + strlen(*item); + len = *pos - *item; /* *pos points to del or '\0' */ + /* rtrim */ while (len > 0 && xisspace((*item)[len - 1])) - len--; + len--; + if (ilen) - *ilen = len; + *ilen = len; + return len > 0; } @@ -295,10 +320,12 @@ httpHeaderParseInt(const char *start, int *value) { assert(value); *value = atoi(start); + if (!*value && !xisdigit(*start)) { - debug(66, 2) ("failed to parse an int header field near '%s'\n", start); - return 0; + debug(66, 2) ("failed to parse an int header field near '%s'\n", start); + return 0; } + return 1; } @@ -330,44 +357,59 @@ httpHeaderTestParser(const char *hstr) MemBuf mb; assert(hstr); /* skip start line if any */ + if (!strncasecmp(hstr, "HTTP/", 5)) { - const char *p = strchr(hstr, '\n'); - if (p) - hstr = p + 1; + const char *p = strchr(hstr, '\n'); + + if (p) + hstr = p + 1; } + /* skip invalid first line if any */ if (xisspace(*hstr)) { - const char *p = strchr(hstr, '\n'); - if (p) - hstr = p + 1; + const char *p = strchr(hstr, '\n'); + + if (p) + hstr = p + 1; } + hstr_len = strlen(hstr); /* skip terminator if any */ + if (strstr(hstr, "\n\r\n")) - hstr_len -= 2; + hstr_len -= 2; else if (strstr(hstr, "\n\n")) - hstr_len -= 1; + hstr_len -= 1; + httpHeaderInit(&hdr, hoReply); + /* Debug::Levels[55] = 8; */ parse_success = httpHeaderParse(&hdr, hstr, hstr + hstr_len); + /* Debug::Levels[55] = 2; */ if (!parse_success) { - debug(66, 2) ("TEST (%d): failed to parsed a header: {\n%s}\n", bug_count, hstr); - return; + debug(66, 2) ("TEST (%d): failed to parsed a header: {\n%s}\n", bug_count, hstr); + return; } + /* we think that we parsed it, veryfy */ memBufDefInit(&mb); + packerToMemInit(&p, &mb); + httpHeaderPackInto(&hdr, &p); + if ((pos = abs(httpHeaderStrCmp(hstr, mb.buf, hstr_len)))) { - bug_count++; - debug(66, 2) ("TEST (%d): hdr parsing bug (pos: %d near '%s'): expected: {\n%s} got: {\n%s}\n", - bug_count, pos, hstr + pos, hstr, mb.buf); + bug_count++; + debug(66, 2) ("TEST (%d): hdr parsing bug (pos: %d near '%s'): expected: {\n%s} got: {\n%s}\n", + bug_count, pos, hstr + pos, hstr, mb.buf); } + httpHeaderClean(&hdr); packerClean(&p); memBufClean(&mb); } + #endif @@ -380,25 +422,34 @@ httpHeaderStrCmp(const char *h1, const char *h2, int len) int len2 = 0; assert(h1 && h2); /* fast check first */ + if (!strncasecmp(h1, h2, len)) - return 0; + return 0; + while (1) { - const char c1 = xtoupper(h1[len1 += xcountws(h1 + len1)]); - const char c2 = xtoupper(h2[len2 += xcountws(h2 + len2)]); - if (c1 < c2) - return -len1; - if (c1 > c2) - return +len1; - if (!c1 && !c2) - return 0; - if (c1) - len1++; - if (c2) - len2++; + const char c1 = xtoupper(h1[len1 += xcountws(h1 + len1)]); + const char c2 = xtoupper(h2[len2 += xcountws(h2 + len2)]); + + if (c1 < c2) + return -len1; + + if (c1 > c2) + return +len1; + + if (!c1 && !c2) + return 0; + + if (c1) + len1++; + + if (c2) + len2++; } + /* NOTREACHED */ return 0; } + #endif /* @@ -416,19 +467,20 @@ httpHdrMangle(HttpHeaderEntry * e, request_t * request) assert(e); hm = &Config.header_access[e->id]; checklist = aclChecklistCreate(hm->access_list, request, NULL); + if (1 == aclCheckFast(hm->access_list, checklist)) { - /* aclCheckFast returns 1 for allow. */ - retval = 1; + /* aclCheckFast returns 1 for allow. */ + retval = 1; } else if (NULL == hm->replacement) { - /* It was denied, and we don't have any replacement */ - retval = 0; + /* It was denied, and we don't have any replacement */ + retval = 0; } else { - /* It was denied, but we have a replacement. Replace the - * header on the fly, and return that the new header - * is allowed. - */ - e->value = hm->replacement; - retval = 1; + /* It was denied, but we have a replacement. Replace the + * header on the fly, and return that the new header + * is allowed. + */ + e->value = hm->replacement; + retval = 1; } delete checklist; @@ -441,7 +493,8 @@ httpHdrMangleList(HttpHeader * l, request_t * request) { HttpHeaderEntry *e; HttpHeaderPos p = HttpHeaderInitPos; + while ((e = httpHeaderGetEntry(l, &p))) - if (0 == httpHdrMangle(e, request)) - httpHeaderDelAt(l, p); + if (0 == httpHdrMangle(e, request)) + httpHeaderDelAt(l, p); } diff --git a/src/HttpMsg.cc b/src/HttpMsg.cc index 4fc11286da..574be91d38 100644 --- a/src/HttpMsg.cc +++ b/src/HttpMsg.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpMsg.cc,v 1.11 2003/01/23 00:37:12 robertc Exp $ + * $Id: HttpMsg.cc,v 1.12 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 74 HTTP Message * AUTHOR: Alex Rousskov @@ -47,26 +47,33 @@ httpMsgIsolateHeaders(const char **parse_start, const char **blk_start, const ch size_t l = strlen(*parse_start); size_t end = headersEnd(*parse_start, l); int nnl; + if (end) { - *blk_start = *parse_start; - *blk_end = *parse_start + end - 1; - /* - * leave blk_end pointing to the first character after the - * first newline which terminates the headers - */ - assert(**blk_end == '\n'); - while (*(*blk_end - 1) == '\r') - (*blk_end)--; - assert(*(*blk_end - 1) == '\n'); - *parse_start += end; - return 1; + *blk_start = *parse_start; + *blk_end = *parse_start + end - 1; + /* + * leave blk_end pointing to the first character after the + * first newline which terminates the headers + */ + assert(**blk_end == '\n'); + + while (*(*blk_end - 1) == '\r') + (*blk_end)--; + + assert(*(*blk_end - 1) == '\n'); + + *parse_start += end; + + return 1; } + /* * If we didn't find the end of headers, and parse_start does * NOT point to a CR or NL character, then return failure */ if (**parse_start != '\r' && **parse_start != '\n') - return 0; /* failure */ + return 0; /* failure */ + /* * If we didn't find the end of headers, and parse_start does point * to an empty line, then we have empty headers. Skip all CR and @@ -74,43 +81,49 @@ httpMsgIsolateHeaders(const char **parse_start, const char **blk_start, const ch * the first character after the first NL. */ *blk_start = *parse_start; + *blk_end = *blk_start; + for (nnl = 0; nnl == 0; (*parse_start)++) { - if (**parse_start == '\r') - (void) 0; - else if (**parse_start == '\n') - nnl++; - else - break; + if (**parse_start == '\r') + (void) 0; + else if (**parse_start == '\n') + nnl++; + else + break; } + return 1; } -/* returns true if connection should be "persistent" +/* returns true if connection should be "persistent" * after processing this message */ int httpMsgIsPersistent(http_version_t http_ver, const HttpHeader * hdr) { if ((http_ver.major >= 1) && (http_ver.minor >= 1)) { - /* - * for modern versions of HTTP: persistent unless there is - * a "Connection: close" header. - */ - return !httpHeaderHasConnDir(hdr, "close"); + /* + * for modern versions of HTTP: persistent unless there is + * a "Connection: close" header. + */ + return !httpHeaderHasConnDir(hdr, "close"); } else { - /* - * Persistent connections in Netscape 3.x are allegedly broken, - * return false if it is a browser connection. If there is a - * VIA header, then we assume this is NOT a browser connection. - */ - const char *agent = httpHeaderGetStr(hdr, HDR_USER_AGENT); - if (agent && !httpHeaderHas(hdr, HDR_VIA)) { - if (!strncasecmp(agent, "Mozilla/3.", 10)) - return 0; - if (!strncasecmp(agent, "Netscape/3.", 11)) - return 0; - } - /* for old versions of HTTP: persistent if has "keep-alive" */ - return httpHeaderHasConnDir(hdr, "keep-alive"); + /* + * Persistent connections in Netscape 3.x are allegedly broken, + * return false if it is a browser connection. If there is a + * VIA header, then we assume this is NOT a browser connection. + */ + const char *agent = httpHeaderGetStr(hdr, HDR_USER_AGENT); + + if (agent && !httpHeaderHas(hdr, HDR_VIA)) { + if (!strncasecmp(agent, "Mozilla/3.", 10)) + return 0; + + if (!strncasecmp(agent, "Netscape/3.", 11)) + return 0; + } + + /* for old versions of HTTP: persistent if has "keep-alive" */ + return httpHeaderHasConnDir(hdr, "keep-alive"); } } diff --git a/src/HttpReply.cc b/src/HttpReply.cc index 7d5e3ff1f9..94fa4694b3 100644 --- a/src/HttpReply.cc +++ b/src/HttpReply.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.cc,v 1.53 2003/02/12 06:10:58 robertc Exp $ + * $Id: HttpReply.cc,v 1.54 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -45,11 +45,11 @@ /* these entity-headers must be ignored if a bogus server sends them in 304 */ static HttpHeaderMask Denied304HeadersMask; static http_hdr_type Denied304HeadersArr[] = -{ - HDR_ALLOW, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, HDR_CONTENT_LENGTH, - HDR_CONTENT_LOCATION, HDR_CONTENT_RANGE, HDR_LAST_MODIFIED, HDR_LINK, - HDR_OTHER -}; + { + HDR_ALLOW, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, HDR_CONTENT_LENGTH, + HDR_CONTENT_LOCATION, HDR_CONTENT_RANGE, HDR_LAST_MODIFIED, HDR_LINK, + HDR_OTHER + }; HttpMsgParseState &operator++ (HttpMsgParseState &aState) { @@ -213,7 +213,7 @@ httpReplySwapOut(HttpReply * rep, StoreEntry * e) MemBuf httpPackedReply(http_version_t ver, http_status status, const char *ctype, - int clen, time_t lmt, time_t expires) + int clen, time_t lmt, time_t expires) { HttpReply *rep = httpReplyCreate(); MemBuf mb; @@ -226,8 +226,8 @@ httpPackedReply(http_version_t ver, http_status status, const char *ctype, HttpReply * httpReplyMake304 (const HttpReply * rep) { - static const http_hdr_type ImsEntries[] = - {HDR_DATE, HDR_CONTENT_TYPE, HDR_EXPIRES, HDR_LAST_MODIFIED, /* eof */ HDR_OTHER}; + static const http_hdr_type ImsEntries[] = {HDR_DATE, HDR_CONTENT_TYPE, HDR_EXPIRES, HDR_LAST_MODIFIED, /* eof */ HDR_OTHER}; + HttpReply *rv; int t; HttpHeaderEntry *e; @@ -245,9 +245,12 @@ httpReplyMake304 (const HttpReply * rep) /* rv->keep_alive */ httpBuildVersion(&ver, 1, 0); httpStatusLineSet(&rv->sline, ver, - HTTP_NOT_MODIFIED, ""); + HTTP_NOT_MODIFIED, ""); + for (t = 0; ImsEntries[t] != HDR_OTHER; ++t) - if ((e = httpHeaderFindEntry(&rep->header, ImsEntries[t])))httpHeaderAddEntry(&rv->header, httpHeaderEntryClone(e)); + if ((e = httpHeaderFindEntry(&rep->header, ImsEntries[t]))) + httpHeaderAddEntry(&rv->header, httpHeaderEntryClone(e)); + /* rv->body */ return rv; } @@ -269,7 +272,7 @@ httpPacked304Reply(const HttpReply * rep) void httpReplySetHeaders(HttpReply * reply, http_version_t ver, http_status status, const char *reason, - const char *ctype, int clen, time_t lmt, time_t expires) + const char *ctype, int clen, time_t lmt, time_t expires) { HttpHeader *hdr; assert(reply); @@ -278,20 +281,28 @@ httpReplySetHeaders(HttpReply * reply, http_version_t ver, http_status status, c httpHeaderPutStr(hdr, HDR_SERVER, full_appname_string); httpHeaderPutStr(hdr, HDR_MIME_VERSION, "1.0"); httpHeaderPutTime(hdr, HDR_DATE, squid_curtime); + if (ctype) { - httpHeaderPutStr(hdr, HDR_CONTENT_TYPE, ctype); - reply->content_type = ctype; + httpHeaderPutStr(hdr, HDR_CONTENT_TYPE, ctype); + reply->content_type = ctype; } else - reply->content_type = StringNull; + reply->content_type = StringNull; + if (clen >= 0) - httpHeaderPutInt(hdr, HDR_CONTENT_LENGTH, clen); + httpHeaderPutInt(hdr, HDR_CONTENT_LENGTH, clen); + if (expires >= 0) - httpHeaderPutTime(hdr, HDR_EXPIRES, expires); + httpHeaderPutTime(hdr, HDR_EXPIRES, expires); + if (lmt > 0) /* this used to be lmt != 0 @?@ */ - httpHeaderPutTime(hdr, HDR_LAST_MODIFIED, lmt); + httpHeaderPutTime(hdr, HDR_LAST_MODIFIED, lmt); + reply->date = squid_curtime; + reply->content_length = clen; + reply->expires = expires; + reply->last_modified = lmt; } @@ -317,34 +328,44 @@ httpRedirectReply(HttpReply * reply, http_status status, const char *loc) * 0 = they do not match */ int -httpReplyValidatorsMatch(HttpReply const * rep, HttpReply const * otherRep) { +httpReplyValidatorsMatch(HttpReply const * rep, HttpReply const * otherRep) +{ String one,two; assert (rep && otherRep); /* Numbers first - easiest to check */ /* Content-Length */ /* TODO: remove -1 bypass */ + if (rep->content_length != otherRep->content_length - && rep->content_length > -1 && - otherRep->content_length > -1) - return 0; + && rep->content_length > -1 && + otherRep->content_length > -1) + return 0; + /* ETag */ one = httpHeaderGetStrOrList(&rep->header, HDR_ETAG); + two = httpHeaderGetStrOrList(&otherRep->header, HDR_ETAG); + if (!one.buf() || !two.buf() || strcasecmp (one.buf(), two.buf())) { - one.clean(); - two.clean(); - return 0; + one.clean(); + two.clean(); + return 0; } + if (rep->last_modified != otherRep->last_modified) - return 0; + return 0; + /* MD5 */ one = httpHeaderGetStrOrList(&rep->header, HDR_CONTENT_MD5); + two = httpHeaderGetStrOrList(&otherRep->header, HDR_CONTENT_MD5); + if (strcasecmp (one.buf(), two.buf())) { - one.clean(); - two.clean(); - return 0; + one.clean(); + two.clean(); + return 0; } + return 1; } @@ -359,7 +380,7 @@ httpReplyUpdateOnNotModified(HttpReply * rep, HttpReply const * freshRep) httpReplyHdrCacheClean(rep); /* update raw headers */ httpHeaderUpdate(&rep->header, &freshRep->header, - (const HttpHeaderMask *) &Denied304HeadersMask); + (const HttpHeaderMask *) &Denied304HeadersMask); /* init cache */ httpReplyHdrCacheInit(rep); } @@ -378,39 +399,47 @@ static time_t httpReplyHdrExpirationTime(const HttpReply * rep) { /* The s-maxage and max-age directive takes priority over Expires */ + if (rep->cache_control) { - if (rep->date >= 0) { - if (rep->cache_control->s_maxage >= 0) - return rep->date + rep->cache_control->s_maxage; - if (rep->cache_control->max_age >= 0) - return rep->date + rep->cache_control->max_age; - } else { - /* - * Conservatively handle the case when we have a max-age - * header, but no Date for reference? - */ - if (rep->cache_control->s_maxage >= 0) - return squid_curtime; - if (rep->cache_control->max_age >= 0) - return squid_curtime; - } + if (rep->date >= 0) { + if (rep->cache_control->s_maxage >= 0) + return rep->date + rep->cache_control->s_maxage; + + if (rep->cache_control->max_age >= 0) + return rep->date + rep->cache_control->max_age; + } else { + /* + * Conservatively handle the case when we have a max-age + * header, but no Date for reference? + */ + + if (rep->cache_control->s_maxage >= 0) + return squid_curtime; + + if (rep->cache_control->max_age >= 0) + return squid_curtime; + } } + if (Config.onoff.vary_ignore_expire && - httpHeaderHas(&rep->header, HDR_VARY)) { - const time_t d = httpHeaderGetTime(&rep->header, HDR_DATE); - const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES); - if (d == e) - return -1; + httpHeaderHas(&rep->header, HDR_VARY)) { + const time_t d = httpHeaderGetTime(&rep->header, HDR_DATE); + const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES); + + if (d == e) + return -1; } + if (httpHeaderHas(&rep->header, HDR_EXPIRES)) { - const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES); - /* - * HTTP/1.0 says that robust implementations should consider - * bad or malformed Expires header as equivalent to "expires - * immediately." - */ - return e < 0 ? squid_curtime : e; + const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES); + /* + * HTTP/1.0 says that robust implementations should consider + * bad or malformed Expires header as equivalent to "expires + * immediately." + */ + return e < 0 ? squid_curtime : e; } + return -1; } @@ -424,13 +453,18 @@ httpReplyHdrCacheInit(HttpReply * rep) rep->date = httpHeaderGetTime(hdr, HDR_DATE); rep->last_modified = httpHeaderGetTime(hdr, HDR_LAST_MODIFIED); str = httpHeaderGetStr(hdr, HDR_CONTENT_TYPE); + if (str) - rep->content_type.limitInit(str, strcspn(str, ";\t ")); + rep->content_type.limitInit(str, strcspn(str, ";\t ")); else - rep->content_type = StringNull; + rep->content_type = StringNull; + rep->cache_control = httpHeaderGetCc(hdr); + rep->content_range = httpHeaderGetContRange(hdr); + rep->keep_alive = httpMsgIsPersistent(rep->sline.version, &rep->header); + /* be sure to set expires after date and cache-control */ rep->expires = httpReplyHdrExpirationTime(rep); } @@ -440,10 +474,12 @@ static void httpReplyHdrCacheClean(HttpReply * rep) { rep->content_type.clean(); + if (rep->cache_control) - httpHdrCcDestroy(rep->cache_control); + httpHdrCcDestroy(rep->cache_control); + if (rep->content_range) - httpHdrContRangeDestroy(rep->content_range); + httpHdrContRangeDestroy(rep->content_range); } /* @@ -464,32 +500,41 @@ httpReplyParseStep(HttpReply * rep, const char *buf, int atEnd) assert(rep->pstate < psParsed); *parse_end_ptr = parse_start; + if (rep->pstate == psReadyToParseStartLine) { - if (!httpReplyIsolateStart(&parse_start, &blk_start, &blk_end)) - return 0; - if (!httpStatusLineParse(&rep->sline, blk_start, blk_end)) - return httpReplyParseError(rep); - - *parse_end_ptr = parse_start; - rep->hdr_sz = *parse_end_ptr - buf; - ++rep->pstate; + if (!httpReplyIsolateStart(&parse_start, &blk_start, &blk_end)) + return 0; + + if (!httpStatusLineParse(&rep->sline, blk_start, blk_end)) + return httpReplyParseError(rep); + + *parse_end_ptr = parse_start; + + rep->hdr_sz = *parse_end_ptr - buf; + + ++rep->pstate; } + if (rep->pstate == psReadyToParseHeaders) { - if (!httpMsgIsolateHeaders(&parse_start, &blk_start, &blk_end)) { - if (atEnd) - blk_start = parse_start, blk_end = blk_start + strlen(blk_start); - else - return 0; - } - if (!httpHeaderParse(&rep->header, blk_start, blk_end)) - return httpReplyParseError(rep); - - httpReplyHdrCacheInit(rep); - - *parse_end_ptr = parse_start; - rep->hdr_sz = *parse_end_ptr - buf; - ++rep->pstate; + if (!httpMsgIsolateHeaders(&parse_start, &blk_start, &blk_end)) { + if (atEnd) + blk_start = parse_start, blk_end = blk_start + strlen(blk_start); + else + return 0; + } + + if (!httpHeaderParse(&rep->header, blk_start, blk_end)) + return httpReplyParseError(rep); + + httpReplyHdrCacheInit(rep); + + *parse_end_ptr = parse_start; + + rep->hdr_sz = *parse_end_ptr - buf; + + ++rep->pstate; } + return 1; } @@ -510,17 +555,22 @@ static int httpReplyIsolateStart(const char **parse_start, const char **blk_start, const char **blk_end) { int slen = strcspn(*parse_start, "\r\n"); + if (!(*parse_start)[slen]) /* no CRLF found */ - return 0; + return 0; *blk_start = *parse_start; + *blk_end = *blk_start + slen; + while (**blk_end == '\r') /* CR */ - (*blk_end)++; + (*blk_end)++; + if (**blk_end == '\n') /* LF */ - (*blk_end)++; + (*blk_end)++; *parse_start = *blk_end; + return 1; } @@ -531,15 +581,16 @@ int httpReplyBodySize(method_t method, HttpReply const * reply) { if (METHOD_HEAD == method) - return 0; + return 0; else if (reply->sline.status == HTTP_OK) - (void) 0; /* common case, continue */ + (void) 0; /* common case, continue */ else if (reply->sline.status == HTTP_NO_CONTENT) - return 0; + return 0; else if (reply->sline.status == HTTP_NOT_MODIFIED) - return 0; + return 0; else if (reply->sline.status < HTTP_OK) - return 0; + return 0; + return reply->content_length; } @@ -552,18 +603,21 @@ httpReplyBodyBuildSize(request_t * request, HttpReply * reply, dlink_list * body body_size *bs; ACLChecklist *checklist; bs = (body_size *) bodylist->head; + while (bs) { - checklist = aclChecklistCreate(bs->access_list, request, NULL); - checklist->reply = reply; - if (1 != aclCheckFast(bs->access_list, checklist)) { - /* deny - skip this entry */ - bs = (body_size *) bs->node.next; - } else { - /* Allow - use this entry */ - reply->maxBodySize = bs->maxsize; - bs = NULL; - debug(58, 3) ("httpReplyBodyBuildSize: Setting maxBodySize to %ld\n", (long int) reply->maxBodySize); - } - delete checklist; + checklist = aclChecklistCreate(bs->access_list, request, NULL); + checklist->reply = reply; + + if (1 != aclCheckFast(bs->access_list, checklist)) { + /* deny - skip this entry */ + bs = (body_size *) bs->node.next; + } else { + /* Allow - use this entry */ + reply->maxBodySize = bs->maxsize; + bs = NULL; + debug(58, 3) ("httpReplyBodyBuildSize: Setting maxBodySize to %ld\n", (long int) reply->maxBodySize); + } + + delete checklist; } } diff --git a/src/HttpReply.h b/src/HttpReply.h index 9fcd8892f1..6aaac79f12 100644 --- a/src/HttpReply.h +++ b/src/HttpReply.h @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.h,v 1.1 2003/01/23 00:37:13 robertc Exp $ + * $Id: HttpReply.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -56,10 +56,10 @@ extern MemBuf httpReplyPack(const HttpReply * rep); extern void httpReplySwapOut(HttpReply * rep, StoreEntry * e); /* set commonly used info with one call */ extern void httpReplySetHeaders(HttpReply * rep, http_version_t ver, http_status status, - const char *reason, const char *ctype, int clen, time_t lmt, time_t expires); + const char *reason, const char *ctype, int clen, time_t lmt, time_t expires); /* do everything in one call: init, set, pack, clean, return MemBuf */ extern MemBuf httpPackedReply(http_version_t ver, http_status status, const char *ctype, - int clen, time_t lmt, time_t expires); + int clen, time_t lmt, time_t expires); /* construct 304 reply and pack it into MemBuf, return MemBuf */ extern MemBuf httpPacked304Reply(const HttpReply * rep); /* construct a 304 reply and return it */ diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index 40908a7327..d690744d34 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpRequest.cc,v 1.34 2003/02/12 06:10:58 robertc Exp $ + * $Id: HttpRequest.cc,v 1.35 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 73 HTTP Request * AUTHOR: Duane Wessels @@ -46,14 +46,22 @@ requestCreate(method_t method, protocol_t protocol, const char *aUrlpath) request_t *req = static_cast(memAllocate(MEM_REQUEST_T)); req->method = method; req->protocol = protocol; + if (aUrlpath) - req->urlpath = aUrlpath; + req->urlpath = aUrlpath; + req->max_forwards = -1; + req->lastmod = -1; + req->client_addr = no_addr; + req->my_addr = no_addr; + httpHeaderInit(&req->header, hoRequest); + httpRequestHdrCacheInit(req); + return req; } @@ -61,18 +69,27 @@ void requestDestroy(request_t * req) { assert(req); + if (req->body_connection) - clientAbortBody(req); + clientAbortBody(req); + if (req->auth_user_request) - authenticateAuthUserRequestUnlock(req->auth_user_request); + authenticateAuthUserRequestUnlock(req->auth_user_request); + safe_free(req->canonical); + safe_free(req->vary_headers); + req->urlpath.clean(); + httpHeaderClean(&req->header); + if (req->cache_control) - httpHdrCcDestroy(req->cache_control); + httpHdrCcDestroy(req->cache_control); + if (req->range) - req->range->deleteSelf(); + req->range->deleteSelf(); + memFree(req, MEM_REQUEST_T); } @@ -88,10 +105,13 @@ void requestUnlink(request_t * request) { if (!request) - return; + return; + assert(request->link_count > 0); + if (--request->link_count > 0) - return; + return; + requestDestroy(request); } @@ -99,11 +119,15 @@ int httpRequestParseHeader(request_t * req, const char *parse_start) { const char *blk_start, *blk_end; + if (!httpMsgIsolateHeaders(&parse_start, &blk_start, &blk_end)) - return 0; + return 0; + int result = httpHeaderParse(&req->header, blk_start, blk_end); + if (result) - httpRequestHdrCacheInit(req); + httpRequestHdrCacheInit(req); + return result; } @@ -125,7 +149,7 @@ httpRequestPack(const request_t * req, Packer * p) assert(req && p); /* pack request-line */ packerPrintf(p, "%s %s HTTP/1.0\r\n", - RequestMethodStr[req->method], req->urlpath.buf()); + RequestMethodStr[req->method], req->urlpath.buf()); /* headers */ httpHeaderPackInto(&req->header, p); /* trailer */ @@ -149,9 +173,9 @@ httpRequestPrefixLen(const request_t * req) { assert(req); return strlen(RequestMethodStr[req->method]) + 1 + - req->urlpath.size() + 1 + - 4 + 1 + 3 + 2 + - req->header.len + 2; + req->urlpath.size() + 1 + + 4 + 1 + 3 + 2 + + req->header.len + 2; } /* @@ -163,8 +187,10 @@ httpRequestHdrAllowed(const HttpHeaderEntry * e, String * strConn) { assert(e); /* check connection header */ + if (strConn && strListIsMember(strConn, e->name.buf(), ',')) - return 0; + return 0; + return 1; } @@ -173,25 +199,33 @@ static void httpRequestHdrCacheInit(request_t * req) { const HttpHeader *hdr = &req->header; -/* const char *str; */ + /* const char *str; */ req->content_length = httpHeaderGetInt(hdr, HDR_CONTENT_LENGTH); /* TODO: canonicalise these into an HttpEntity */ #if 0 + req->date = httpHeaderGetTime(hdr, HDR_DATE); req->last_modified = httpHeaderGetTime(hdr, HDR_LAST_MODIFIED); str = httpHeaderGetStr(hdr, HDR_CONTENT_TYPE); + if (str) - stringLimitInit(&req->content_type, str, strcspn(str, ";\t ")); + stringLimitInit(&req->content_type, str, strcspn(str, ";\t ")); else - req->content_type = StringNull; + req->content_type = StringNull; + #endif + req->cache_control = httpHeaderGetCc(hdr); + req->range = httpHeaderGetRange(hdr); + #if 0 + req->keep_alive = httpMsgIsPersistent(req->http_ver, &req->header); /* be sure to set expires after date and cache-control */ req->expires = httpReplyHdrExpirationTime(req); + #endif } diff --git a/src/HttpStatusLine.cc b/src/HttpStatusLine.cc index a74b4c9b57..844b2cd773 100644 --- a/src/HttpStatusLine.cc +++ b/src/HttpStatusLine.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpStatusLine.cc,v 1.26 2003/01/23 00:37:13 robertc Exp $ + * $Id: HttpStatusLine.cc,v 1.27 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 57 HTTP Status-line * AUTHOR: Alex Rousskov @@ -73,10 +73,10 @@ httpStatusLinePackInto(const HttpStatusLine * sline, Packer * p) assert(sline && p); debug(57, 9) ("packing sline %p using %p:\n", sline, p); debug(57, 9) (HttpStatusLineFormat, sline->version.major, - sline->version.minor, sline->status, - sline->reason ? sline->reason : httpStatusString(sline->status)); + sline->version.minor, sline->status, + sline->reason ? sline->reason : httpStatusString(sline->status)); packerPrintf(p, HttpStatusLineFormat, sline->version.major, - sline->version.minor, sline->status, httpStatusLineReason(sline)); + sline->version.minor, sline->status, httpStatusLineReason(sline)); } /* pack fields using Packer */ @@ -85,17 +85,24 @@ httpStatusLineParse(HttpStatusLine * sline, const char *start, const char *end) { assert(sline); sline->status = HTTP_INVALID_HEADER; /* Squid header parsing error */ + if (strncasecmp(start, "HTTP/", 5)) - return 0; + return 0; + start += 5; + if (!xisdigit(*start)) - return 0; + return 0; + if (sscanf(start, "%d.%d", &sline->version.major, &sline->version.minor) != 2) { - debug(57, 7) ("httpStatusLineParse: Invalid HTTP identifier.\n"); + debug(57, 7) ("httpStatusLineParse: Invalid HTTP identifier.\n"); } + if (!(start = strchr(start, ' '))) - return 0; + return 0; + sline->status = (http_status) atoi(++start); + /* we ignore 'reason-phrase' */ return 1; /* success */ } @@ -112,128 +119,170 @@ httpStatusString(http_status status) { /* why not to return matching string instead of using "p" ? @?@ */ const char *p = NULL; + switch (status) { + case 0: - p = "Init"; /* we init .status with code 0 */ - break; + p = "Init"; /* we init .status with code 0 */ + break; + case HTTP_CONTINUE: - p = "Continue"; - break; + p = "Continue"; + break; + case HTTP_SWITCHING_PROTOCOLS: - p = "Switching Protocols"; - break; + p = "Switching Protocols"; + break; + case HTTP_OK: - p = "OK"; - break; + p = "OK"; + break; + case HTTP_CREATED: - p = "Created"; - break; + p = "Created"; + break; + case HTTP_ACCEPTED: - p = "Accepted"; - break; + p = "Accepted"; + break; + case HTTP_NON_AUTHORITATIVE_INFORMATION: - p = "Non-Authoritative Information"; - break; + p = "Non-Authoritative Information"; + break; + case HTTP_NO_CONTENT: - p = "No Content"; - break; + p = "No Content"; + break; + case HTTP_RESET_CONTENT: - p = "Reset Content"; - break; + p = "Reset Content"; + break; + case HTTP_PARTIAL_CONTENT: - p = "Partial Content"; - break; + p = "Partial Content"; + break; + case HTTP_MULTIPLE_CHOICES: - p = "Multiple Choices"; - break; + p = "Multiple Choices"; + break; + case HTTP_MOVED_PERMANENTLY: - p = "Moved Permanently"; - break; + p = "Moved Permanently"; + break; + case HTTP_MOVED_TEMPORARILY: - p = "Moved Temporarily"; - break; + p = "Moved Temporarily"; + break; + case HTTP_SEE_OTHER: - p = "See Other"; - break; + p = "See Other"; + break; + case HTTP_NOT_MODIFIED: - p = "Not Modified"; - break; + p = "Not Modified"; + break; + case HTTP_USE_PROXY: - p = "Use Proxy"; - break; + p = "Use Proxy"; + break; + case HTTP_TEMPORARY_REDIRECT: - p = "Temporary Redirect"; - break; + p = "Temporary Redirect"; + break; + case HTTP_BAD_REQUEST: - p = "Bad Request"; - break; + p = "Bad Request"; + break; + case HTTP_UNAUTHORIZED: - p = "Unauthorized"; - break; + p = "Unauthorized"; + break; + case HTTP_PAYMENT_REQUIRED: - p = "Payment Required"; - break; + p = "Payment Required"; + break; + case HTTP_FORBIDDEN: - p = "Forbidden"; - break; + p = "Forbidden"; + break; + case HTTP_NOT_FOUND: - p = "Not Found"; - break; + p = "Not Found"; + break; + case HTTP_METHOD_NOT_ALLOWED: - p = "Method Not Allowed"; - break; + p = "Method Not Allowed"; + break; + case HTTP_NOT_ACCEPTABLE: - p = "Not Acceptable"; - break; + p = "Not Acceptable"; + break; + case HTTP_PROXY_AUTHENTICATION_REQUIRED: - p = "Proxy Authentication Required"; - break; + p = "Proxy Authentication Required"; + break; + case HTTP_REQUEST_TIMEOUT: - p = "Request Time-out"; - break; + p = "Request Time-out"; + break; + case HTTP_CONFLICT: - p = "Conflict"; - break; + p = "Conflict"; + break; + case HTTP_GONE: - p = "Gone"; - break; + p = "Gone"; + break; + case HTTP_LENGTH_REQUIRED: - p = "Length Required"; - break; + p = "Length Required"; + break; + case HTTP_PRECONDITION_FAILED: - p = "Precondition Failed"; - break; + p = "Precondition Failed"; + break; + case HTTP_REQUEST_ENTITY_TOO_LARGE: - p = "Request Entity Too Large"; - break; + p = "Request Entity Too Large"; + break; + case HTTP_REQUEST_URI_TOO_LARGE: - p = "Request-URI Too Large"; - break; + p = "Request-URI Too Large"; + break; + case HTTP_UNSUPPORTED_MEDIA_TYPE: - p = "Unsupported Media Type"; - break; + p = "Unsupported Media Type"; + break; + case HTTP_INTERNAL_SERVER_ERROR: - p = "Internal Server Error"; - break; + p = "Internal Server Error"; + break; + case HTTP_NOT_IMPLEMENTED: - p = "Not Implemented"; - break; + p = "Not Implemented"; + break; + case HTTP_BAD_GATEWAY: - p = "Bad Gateway"; - break; + p = "Bad Gateway"; + break; + case HTTP_SERVICE_UNAVAILABLE: - p = "Service Unavailable"; - break; + p = "Service Unavailable"; + break; + case HTTP_GATEWAY_TIMEOUT: - p = "Gateway Time-out"; - break; + p = "Gateway Time-out"; + break; + case HTTP_HTTP_VERSION_NOT_SUPPORTED: - p = "HTTP Version not supported"; - break; + p = "HTTP Version not supported"; + break; + default: - p = "Unknown"; - debug(57, 3) ("Unknown HTTP status code: %d\n", status); - break; + p = "Unknown"; + debug(57, 3) ("Unknown HTTP status code: %d\n", status); + break; } + return p; } diff --git a/src/ICP.h b/src/ICP.h index 476fb1f478..088e43b317 100644 --- a/src/ICP.h +++ b/src/ICP.h @@ -1,6 +1,6 @@ /* - * $Id: ICP.h,v 1.3 2003/01/23 00:37:13 robertc Exp $ + * $Id: ICP.h,v 1.4 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,7 +40,9 @@ * DO NOT add ore move fields on pain of breakage. * DO NOT add virtual methods. */ -struct _icp_common_t { + +struct _icp_common_t +{ unsigned char opcode; /* opcode */ unsigned char version; /* version number */ unsigned short length; /* total length (bytes) */ @@ -49,8 +51,10 @@ struct _icp_common_t { u_int32_t pad; u_int32_t shostid; /* sender host id */ #ifdef __cplusplus - _icp_common_t(); - _icp_common_t(char *buf, unsigned int len); + + _icp_common_t(); + _icp_common_t(char *buf, unsigned int len); + void handleReply(char *buf, struct sockaddr_in *from); static _icp_common_t *createMessage(icp_opcode opcode, int flags, const char *url, int reqnum, int pad); icp_opcode getOpCode() const; @@ -59,20 +63,25 @@ struct _icp_common_t { #ifdef __cplusplus -inline icp_opcode & operator++ (icp_opcode & aCode) { +inline icp_opcode & operator++ (icp_opcode & aCode) +{ aCode = (icp_opcode) (++(int) aCode); return aCode; } /* todo: mempool this */ -class ICPState { - public: + +class ICPState +{ + +public: ICPState(icp_common_t &); virtual ~ ICPState(); icp_common_t header; request_t *request; int fd; + struct sockaddr_in from; char *url; }; @@ -80,30 +89,41 @@ class ICPState { #endif typedef struct _icpUdpData icpUdpData; -struct _icpUdpData { + +struct _icpUdpData +{ + struct sockaddr_in address; void *msg; size_t len; icpUdpData *next; #ifndef LESS_TIMING + struct timeval start; #endif + log_type logcode; + struct timeval queue_time; }; request_t * - icpGetRequest(char *url, int reqnum, int fd, struct sockaddr_in *from); + +icpGetRequest(char *url, int reqnum, int fd, struct sockaddr_in *from); + int icpAccessAllowed(struct sockaddr_in *from, request_t * icp_request); + SQUIDCEXTERN void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const struct sockaddr_in *from); extern icp_opcode icpGetCommonOpcode(); SQUIDCEXTERN int icpUdpSend(int, const struct sockaddr_in *, icp_common_t *, log_type, int); SQUIDCEXTERN log_type icpLogFromICPCode(icp_opcode opcode); + void icpDenyAccess(struct sockaddr_in *from, char *url, int reqnum, int fd); SQUIDCEXTERN PF icpHandleUdp; SQUIDCEXTERN PF icpUdpSendQueue; + SQUIDCEXTERN void icpHandleIcpV3(int, struct sockaddr_in, char *, int); SQUIDCEXTERN int icpCheckUdpHit(StoreEntry *, request_t * request); SQUIDCEXTERN void icpConnectionsOpen(void); diff --git a/src/IPInterception.cc b/src/IPInterception.cc index 1c5affcacd..c658f312b9 100644 --- a/src/IPInterception.cc +++ b/src/IPInterception.cc @@ -1,6 +1,6 @@ /* - * $Id: IPInterception.cc,v 1.5 2003/02/21 19:53:01 hno Exp $ + * $Id: IPInterception.cc,v 1.6 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 89 NAT / IP Interception * AUTHOR: Robert Collins @@ -80,8 +80,10 @@ #if IPF_TRANSPARENT int + clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) { + struct natlookup natLookup; static int natfd = -1; static int siocgnatl_cmd = SIOCGNATL & 0xff; @@ -92,19 +94,24 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s natLookup.nl_inip = me.sin_addr; natLookup.nl_outip = peer.sin_addr; natLookup.nl_flags = IPN_TCP; - if (natfd < 0) { - int save_errno; - enter_suid(); - natfd = open(IPL_NAT, O_RDONLY, 0); - save_errno = errno; - leave_suid(); - errno = save_errno; + + if (natfd < 0) + { + int save_errno; + enter_suid(); + natfd = open(IPL_NAT, O_RDONLY, 0); + save_errno = errno; + leave_suid(); + errno = save_errno; } - if (natfd < 0) { - debug(50, 1) ("parseHttpRequest: NAT open failed: %s\n", - xstrerror()); - return -1; + + if (natfd < 0) + { + debug(50, 1) ("parseHttpRequest: NAT open failed: %s\n", + xstrerror()); + return -1; } + /* * IP-Filter changed the type for SIOCGNATL between * 3.3 and 3.4. It also changed the cmd value for @@ -112,59 +119,83 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s * put something in configure and use ifdefs here, but * this seems simpler. */ - if (63 == siocgnatl_cmd) { - struct natlookup *nlp = &natLookup; - x = ioctl(natfd, SIOCGNATL, &nlp); - } else { - x = ioctl(natfd, SIOCGNATL, &natLookup); + if (63 == siocgnatl_cmd) + { + + struct natlookup *nlp = &natLookup; + x = ioctl(natfd, SIOCGNATL, &nlp); + } else + { + x = ioctl(natfd, SIOCGNATL, &natLookup); + } + + if (x < 0) + { + if (errno != ESRCH) { + debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n"); + close(natfd); + natfd = -1; + } + + return -1; + } else + { + if (me.sin_addr.s_addr != natLookup.nl_realip.s_addr) + dst->sin_family = AF_INET; + + dst->sin_port = natLookup.nl_realport; + + dst->sin_addr = natLookup.nl_realip; + + return 0; } - if (x < 0) { - if (errno != ESRCH) { - debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n"); - close(natfd); - natfd = -1; - } - return -1; - } else { - if (me.sin_addr.s_addr != natLookup.nl_realip.s_addr) - dst->sin_family = AF_INET; - dst->sin_port = natLookup.nl_realport; - dst->sin_addr = natLookup.nl_realip; - return 0; - } else { - return -1; - } + else + { + return -1; } } +} + #elif LINUX_NETFILTER int + clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) { size_t sock_sz = sizeof(*dst); memcpy(dst, &me, sizeof(*dst)); + if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, dst, &sock_sz) != 0) - return -1; + return -1; debug(33, 5) ("clientNatLookup: addr = %s", inet_ntoa(dst->sin_addr)); + if (me.sin_addr.s_addr != dst->sin_addr.s_addr) - return 0; + return 0; else - return -1; + return -1; } + #elif PF_TRANSPARENT int + clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) { + struct pfioc_natlook nl; static int pffd = -1; + + if (pffd < 0) + pffd = open("/dev/pf", O_RDWR); + if (pffd < 0) - pffd = open("/dev/pf", O_RDWR); - if (pffd < 0) { - debug(50, 1) ("parseHttpRequest: PF open failed: %s\n", - xstrerror()); - return -1; + { + debug(50, 1) ("parseHttpRequest: PF open failed: %s\n", + xstrerror()); + return -1; } + memset(dst, 0, sizeof(*dst)); + memset(&nl, 0, sizeof(struct pfioc_natlook)); nl.saddr.v4.s_addr = peer.sin_addr.s_addr; nl.sport = peer.sin_port; @@ -173,30 +204,38 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s nl.af = AF_INET; nl.proto = IPPROTO_TCP; nl.direction = PF_OUT; - if (ioctl(pffd, DIOCNATLOOK, &nl)) { - if (errno != ENOENT) { - debug(50, 1) ("parseHttpRequest: PF lookup failed: ioctl(DIOCNATLOOK)\n"); - close(pffd); - pffd = -1; - } - return -1; - } else { - int natted = me.sin_addr.s_addr != nt.rdaddr.v4.s_addr; - dst->sin_family = AF_INET; - dst->sin_port = nl.rdport; - dst->sin_addr = nl.rdaddr.v4; - if (natted) - return 0; - else - return -1; + + if (ioctl(pffd, DIOCNATLOOK, &nl)) + { + if (errno != ENOENT) { + debug(50, 1) ("parseHttpRequest: PF lookup failed: ioctl(DIOCNATLOOK)\n"); + close(pffd); + pffd = -1; + } + + return -1; + } else + { + int natted = me.sin_addr.s_addr != nt.rdaddr.v4.s_addr; + dst->sin_family = AF_INET; + dst->sin_port = nl.rdport; + dst->sin_addr = nl.rdaddr.v4; + + if (natted) + return 0; + else + return -1; } } + #else int + clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) { debug(33, 1) ("WARNING: transparent proxying not supported\n"); return -1; } + #endif diff --git a/src/IPInterception.h b/src/IPInterception.h index d112968343..5a6bf609f7 100644 --- a/src/IPInterception.h +++ b/src/IPInterception.h @@ -1,6 +1,6 @@ /* - * $Id: IPInterception.h,v 1.5 2003/02/21 19:53:01 hno Exp $ + * $Id: IPInterception.h,v 1.6 2003/02/21 22:50:05 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,6 +35,7 @@ #define SQUID_IPINTERCEPTION_H SQUIDCEXTERN int + clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst); #endif /* SQUID_IPINTERCEPTION_H */ diff --git a/src/Mem.h b/src/Mem.h index e75ae4d73c..ebdc116180 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -1,6 +1,6 @@ /* - * $Id: Mem.h,v 1.1 2003/01/23 00:37:14 robertc Exp $ + * $Id: Mem.h,v 1.2 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 13 High Level Memory Pool Management * AUTHOR: Harvest Derived @@ -36,13 +36,15 @@ #ifndef SQUID_MEM #define SQUID_MEM -class Mem { +class Mem +{ + public: - static void Init(); - static void Stats(StoreEntry *); - static void CleanIdlePools(void *unused); - static void Report(StoreEntry *); - static void PoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e); + static void Init(); + static void Stats(StoreEntry *); + static void CleanIdlePools(void *unused); + static void Report(StoreEntry *); + static void PoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e); }; #endif /* SQUID_MEM */ diff --git a/src/MemBuf.cc b/src/MemBuf.cc index 710933b942..31fadee7c9 100644 --- a/src/MemBuf.cc +++ b/src/MemBuf.cc @@ -1,6 +1,6 @@ /* - * $Id: MemBuf.cc,v 1.33 2003/01/23 00:37:14 robertc Exp $ + * $Id: MemBuf.cc,v 1.34 2003/02/21 22:50:05 robertc Exp $ * * DEBUG: section 59 auto-growing Memory Buffer with printf * AUTHOR: Alex Rousskov @@ -152,7 +152,7 @@ memBufClean(MemBuf * mb) mb->size = mb->capacity = 0; } -/* cleans the buffer without changing its capacity +/* cleans the buffer without changing its capacity * if called with a Null buffer, calls memBufDefInit() */ void memBufReset(MemBuf * mb) @@ -160,12 +160,12 @@ memBufReset(MemBuf * mb) assert(mb); if (memBufIsNull(mb)) { - memBufDefInit(mb); + memBufDefInit(mb); } else { - assert(!mb->stolen); /* not frozen */ - /* reset */ - memset(mb->buf, 0, mb->capacity); - mb->size = 0; + assert(!mb->stolen); /* not frozen */ + /* reset */ + memset(mb->buf, 0, mb->capacity); + mb->size = 0; } } @@ -174,9 +174,12 @@ int memBufIsNull(MemBuf * mb) { assert(mb); + if (!mb->buf && !mb->max_capacity && !mb->capacity && !mb->size) - return 1; /* is null (not initialized) */ + return 1; /* is null (not initialized) */ + assert(mb->buf && mb->max_capacity && mb->capacity); /* paranoid */ + return 0; } @@ -190,12 +193,16 @@ memBufAppend(MemBuf * mb, const char *buf, mb_size_t sz) assert(!mb->stolen); /* not frozen */ if (sz > 0) { - if (mb->size + sz + 1 > mb->capacity) - memBufGrow(mb, mb->size + sz + 1); - assert(mb->size + sz <= mb->capacity); /* paranoid */ - xmemcpy(mb->buf + mb->size, buf, sz); - mb->size += sz; - mb->buf[mb->size] = '\0'; /* \0 terminate in case we are used as a string. Not counted in the size */ + if (mb->size + sz + 1 > mb->capacity) + memBufGrow(mb, mb->size + sz + 1); + + assert(mb->size + sz <= mb->capacity); /* paranoid */ + + xmemcpy(mb->buf + mb->size, buf, sz); + + mb->size += sz; + + mb->buf[mb->size] = '\0'; /* \0 terminate in case we are used as a string. Not counted in the size */ } } @@ -209,7 +216,7 @@ memBufPrintf(MemBuf * mb, const char *fmt,...) #else void memBufPrintf(va_alist) - va_dcl +va_dcl { va_list args; MemBuf *mb = NULL; @@ -219,6 +226,7 @@ memBufPrintf(va_alist) mb = va_arg(args, MemBuf *); fmt = va_arg(args, char *); #endif + memBufVPrintf(mb, fmt, args); va_end(args); } @@ -226,33 +234,36 @@ memBufPrintf(va_alist) /* vprintf for other printf()'s to use; calls vsnprintf, extends buf if needed */ void -memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) -{ +memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) { int sz = 0; assert(mb && fmt); assert(mb->buf); assert(!mb->stolen); /* not frozen */ /* assert in Grow should quit first, but we do not want to have a scary infinite loop */ + while (mb->capacity <= mb->max_capacity) { - mb_size_t free_space = mb->capacity - mb->size; - /* put as much as we can */ - sz = vsnprintf(mb->buf + mb->size, free_space, fmt, vargs); - /* check for possible overflow */ - /* snprintf on Linuz returns -1 on overflows */ - /* snprintf on FreeBSD returns at least free_space on overflows */ - if (sz < 0 || sz >= free_space) - memBufGrow(mb, mb->capacity + 1); - else - break; + mb_size_t free_space = mb->capacity - mb->size; + /* put as much as we can */ + sz = vsnprintf(mb->buf + mb->size, free_space, fmt, vargs); + /* check for possible overflow */ + /* snprintf on Linuz returns -1 on overflows */ + /* snprintf on FreeBSD returns at least free_space on overflows */ + + if (sz < 0 || sz >= free_space) + memBufGrow(mb, mb->capacity + 1); + else + break; } + mb->size += sz; /* on Linux and FreeBSD, '\0' is not counted in return value */ /* on XXX it might be counted */ /* check that '\0' is appended and not counted */ + if (!mb->size || mb->buf[mb->size - 1]) { - assert(!mb->buf[mb->size]); + assert(!mb->buf[mb->size]); } else { - mb->size--; + mb->size--; } } @@ -264,8 +275,7 @@ memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) * (you still can read-access .buf and .size) */ FREE * -memBufFreeFunc(MemBuf * mb) -{ +memBufFreeFunc(MemBuf * mb) { FREE *ff; assert(mb); assert(mb->buf); @@ -278,8 +288,7 @@ memBufFreeFunc(MemBuf * mb) /* grows (doubles) internal buffer to satisfy required minimal capacity */ static void -memBufGrow(MemBuf * mb, mb_size_t min_cap) -{ +memBufGrow(MemBuf * mb, mb_size_t min_cap) { size_t new_cap; size_t buf_cap; @@ -288,22 +297,26 @@ memBufGrow(MemBuf * mb, mb_size_t min_cap) assert(mb->capacity < min_cap); /* determine next capacity */ + if (min_cap > 64 * 1024) { - new_cap = 64 * 1024; - while (new_cap < (size_t) min_cap) - new_cap += 64 * 1024; /* increase in reasonable steps */ + new_cap = 64 * 1024; + + while (new_cap < (size_t) min_cap) + new_cap += 64 * 1024; /* increase in reasonable steps */ } else { - new_cap = (size_t) min_cap; + new_cap = (size_t) min_cap; } /* last chance to fit before we assert(!overflow) */ if (new_cap > (size_t) mb->max_capacity) - new_cap = (size_t) mb->max_capacity; + new_cap = (size_t) mb->max_capacity; assert(new_cap <= (size_t) mb->max_capacity); /* no overflow */ + assert(new_cap > (size_t) mb->capacity); /* progress */ buf_cap = (size_t) mb->capacity; + mb->buf = (char *)memReallocBuf(mb->buf, new_cap, &buf_cap); /* done */ @@ -315,8 +328,7 @@ memBufGrow(MemBuf * mb, mb_size_t min_cap) /* puts report on MemBuf _module_ usage into mb */ void -memBufReport(MemBuf * mb) -{ +memBufReport(MemBuf * mb) { assert(mb); memBufPrintf(mb, "memBufReport is not yet implemented @?@\n"); } diff --git a/src/MemBuf.h b/src/MemBuf.h index cd9c1e32e8..19419db94b 100644 --- a/src/MemBuf.h +++ b/src/MemBuf.h @@ -1,6 +1,6 @@ /* - * $Id: MemBuf.h,v 1.1 2003/01/23 00:37:14 robertc Exp $ + * $Id: MemBuf.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,8 +36,11 @@ /* auto-growing memory-resident buffer with printf interface */ /* note: when updating this struct, update MemBufNULL #define */ -class MemBuf { - public: + +class MemBuf +{ + +public: _SQUID_INLINE_ MemBuf(); /* public, read-only */ char *buf; @@ -46,7 +49,9 @@ class MemBuf { /* private, stay away; use interface function instead */ mb_size_t max_capacity; /* when grows: assert(new_capacity <= max_capacity) */ mb_size_t capacity; /* allocated space */ - unsigned stolen:1; /* the buffer has been stolen for use by someone else */ + +unsigned stolen: + 1; /* the buffer has been stolen for use by someone else */ }; /* to initialize static variables (see also MemBufNull) */ diff --git a/src/MemObject.cc b/src/MemObject.cc index 7e8dabb943..283fb4929d 100644 --- a/src/MemObject.cc +++ b/src/MemObject.cc @@ -1,6 +1,6 @@ /* - * $Id: MemObject.cc,v 1.4 2003/02/13 22:20:37 robertc Exp $ + * $Id: MemObject.cc,v 1.5 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 19 Store Memory Primitives * AUTHOR: Robert Collins @@ -59,6 +59,7 @@ url_checksum(const char *url) xmemcpy(&ck, digest, sizeof(ck)); return ck; } + #endif MemPool *MemObject::pool = NULL; @@ -68,8 +69,10 @@ MemObject::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (MemObject)); + if (!pool) - pool = memPoolCreate("MemObject", sizeof (MemObject)); + pool = memPoolCreate("MemObject", sizeof (MemObject)); + return memPoolAlloc(pool); } @@ -83,19 +86,24 @@ size_t MemObject::inUseCount() { if (!pool) - return 0; + return 0; + MemPoolStats stats; + memPoolGetStats (&stats, pool); + return stats.items_inuse; } MemObject::MemObject(char const *aUrl, char const *aLog_url) : -_reply (httpReplyCreate()) + _reply (httpReplyCreate()) { url = xstrdup(aUrl); #if URL_CHECKSUM_DEBUG + chksum = url_checksum(url); #endif + log_url = xstrdup(aLog_url); object_sz = -1; fd = -1; @@ -108,22 +116,33 @@ MemObject::~MemObject() const Ctx ctx = ctx_enter(url); debug(20, 3) ("destroy_MemObject: destroying %p\n", this); #if URL_CHECKSUM_DEBUG + assert(chksum == url_checksum(url)); #endif + if (!shutting_down) assert(swapout.sio == NULL); + data_hdr.freeContent(); + /* * There is no way to abort FD-less clients, so they might * still have mem->clients set if mem->fd == -1 */ assert(fd == -1 || clients.head == NULL); + httpReplyDestroy((HttpReply *)_reply); + requestUnlink(request); + request = NULL; + ctx_exit(ctx); /* must exit before we free mem->url */ + safe_free(url); + safe_free(log_url); /* XXX account log_url */ + safe_free(vary_headers); } @@ -156,30 +175,31 @@ void MemObject::dump() const { debug(20, 1) ("MemObject->data.head: %p\n", - data_hdr.head); + data_hdr.head); debug(20, 1) ("MemObject->data.tail: %p\n", - data_hdr.tail); + data_hdr.tail); #if 0 /* do we want this one? */ debug(20, 1) ("MemObject->data.origin_offset: %d\n", - data_hdr.head ? data_hdr.head->nodeBuffer.offset : 0); + data_hdr.head ? data_hdr.head->nodeBuffer.offset : 0); #endif + debug(20, 1) ("MemObject->start_ping: %d.%06d\n", - (int) start_ping.tv_sec, - (int) start_ping.tv_usec); + (int) start_ping.tv_sec, + (int) start_ping.tv_usec); debug(20, 1) ("MemObject->inmem_hi: %d\n", - (int) data_hdr.endOffset()); + (int) data_hdr.endOffset()); debug(20, 1) ("MemObject->inmem_lo: %d\n", - (int) inmem_lo); + (int) inmem_lo); debug(20, 1) ("MemObject->nclients: %d\n", - nclients); + nclients); debug(20, 1) ("MemObject->reply: %p\n", - _reply); + _reply); debug(20, 1) ("MemObject->request: %p\n", - request); + request); debug(20, 1) ("MemObject->log_url: %p %s\n", - log_url, - checkNullString(log_url)); + log_url, + checkNullString(log_url)); } HttpReply const * @@ -191,19 +211,25 @@ MemObject::getReply() const struct LowestMemReader : public unary_function { LowestMemReader(off_t seed):current(seed){} - void operator() (store_client const &x) - { - if (x.memReaderHasLowerOffset(current)) - current = x.copyInto.offset; } + + void operator() (store_client const &x) + { + if (x.memReaderHasLowerOffset(current)) + current = x.copyInto.offset; + } + off_t current; }; struct StoreClientStats : public unary_function { StoreClientStats(StoreEntry *anEntry):where(anEntry),index(0){} - void operator()(store_client const &x) { - x.dumpStats(where, index++); + + void operator()(store_client const &x) + { + x.dumpStats(where, index++); } + StoreEntry *where; size_t index; }; @@ -212,15 +238,18 @@ void MemObject::stat (StoreEntry *s) const { storeAppendPrintf(s, "\t%s %s\n", - RequestMethodStr[method], log_url); + RequestMethodStr[method], log_url); storeAppendPrintf(s, "\tinmem_lo: %d\n", (int) inmem_lo); storeAppendPrintf(s, "\tinmem_hi: %d\n", (int) data_hdr.endOffset()); storeAppendPrintf(s, "\tswapout: %d bytes queued\n", - (int) swapout.queue_offset); + (int) swapout.queue_offset); + if (swapout.sio.getRaw()) - storeAppendPrintf(s, "\tswapout: %d bytes written\n", - (int) swapout.sio->offset()); + storeAppendPrintf(s, "\tswapout: %d bytes written\n", + (int) swapout.sio->offset()); + StoreClientStats statsVisitor(s); + for_each(clients, statsVisitor); } @@ -233,8 +262,9 @@ MemObject::endOffset () const size_t MemObject::size() const { - if (object_sz < 0) - return endOffset(); + if (object_sz < 0) + return endOffset(); + return object_sz; } @@ -254,7 +284,7 @@ MemObject::lowestMemReaderOffset() const LowestMemReader lowest (endOffset() + 1); for_each (clients, lowest); - + return lowest.current; } @@ -278,6 +308,7 @@ MemObject::checkUrlChecksum () const { assert(chksum == url_checksum(url)); } + #endif /* @@ -297,11 +328,15 @@ MemObject::objectBytesOnDisk() const * meaning we haven't even opened the swapout file * yet. */ + if (swapout.sio.getRaw() == NULL) - return 0; + return 0; + off_t nwritten = swapout.sio->offset(); + if (nwritten <= (off_t)swap_hdr_sz) - return 0; + return 0; + return (size_t) (nwritten - swap_hdr_sz); } @@ -313,10 +348,11 @@ MemObject::policyLowestOffsetToKeep() const * as in the case of a range request. */ off_t lowest_offset = lowestMemReaderOffset(); + if (endOffset() < lowest_offset || - endOffset() - inmem_lo > (ssize_t)Config.Store.maxInMemObjSize) - return lowest_offset; - + endOffset() - inmem_lo > (ssize_t)Config.Store.maxInMemObjSize) + return lowest_offset; + return inmem_lo; } @@ -333,11 +369,15 @@ MemObject::trimSwappable() * walked to the next page. (mem->swapout.memnode) */ off_t on_disk; + if ((on_disk = objectBytesOnDisk()) - 1 < new_mem_lo) - new_mem_lo = on_disk - 1; + new_mem_lo = on_disk - 1; + if (new_mem_lo == -1) - new_mem_lo = 0; /* the above might become -1 */ + new_mem_lo = 0; /* the above might become -1 */ + data_hdr.freeDataUpto(new_mem_lo); + inmem_lo = new_mem_lo; } @@ -358,7 +398,7 @@ MemObject::isContiguous() const bool result = data_hdr.hasContigousContentRange (inmem_lo, endOffset()); /* XXX : make this higher level */ debug (19, result ? 2 : 1) ("MemObject::isContiguous: Returning %s\n", - result ? "true" : "false"); + result ? "true" : "false"); return result; } @@ -368,21 +408,27 @@ MemObject::mostBytesWanted(int max) const #if DELAY_POOLS #if 0 int i = -1; + for (dlink_node *node = clients.head; node; node = node->next) { - store_client *sc = (store_client *) node->data; - if (!sc->callbackPending()) - /* not waiting for more data */ - continue; - if (sc->getType() != STORE_MEM_CLIENT) - continue; - i = sc->delayId.bytesWanted(i, XMIN(sc->copyInto.length, (size_t)max)); + store_client *sc = (store_client *) node->data; + + if (!sc->callbackPending()) + /* not waiting for more data */ + continue; + + if (sc->getType() != STORE_MEM_CLIENT) + continue; + + i = sc->delayId.bytesWanted(i, XMIN(sc->copyInto.length, (size_t)max)); } + return XMAX(i, 0); #endif /* identify delay id with largest allowance */ DelayId largestAllowance = mostBytesAllowed (); return largestAllowance.bytesWanted(0, max); #else + return max; #endif } @@ -394,28 +440,36 @@ MemObject::mostBytesAllowed() const int j; int jmax = -1; DelayId result; + for (dlink_node *node = clients.head; node; node = node->next) { - store_client *sc = (store_client *) node->data; + store_client *sc = (store_client *) node->data; #if 0 - /* This test is invalid because the client may be writing data - * and thus will want data immediately. - * If we include the test, there is a race condition when too much - * data is read - if all sc's are writing when a read is scheduled. - * XXX: fixme. - */ - if (!sc->callbackPending()) - /* not waiting for more data */ - continue; + /* This test is invalid because the client may be writing data + * and thus will want data immediately. + * If we include the test, there is a race condition when too much + * data is read - if all sc's are writing when a read is scheduled. + * XXX: fixme. + */ + + if (!sc->callbackPending()) + /* not waiting for more data */ + continue; + #endif - if (sc->getType() != STORE_MEM_CLIENT) - /* reading off disk */ - continue; - j = sc->delayId.bytesWanted(0, sc->copyInto.length); - if (j > jmax) { - jmax = j; - result = sc->delayId; - } + + if (sc->getType() != STORE_MEM_CLIENT) + /* reading off disk */ + continue; + + j = sc->delayId.bytesWanted(0, sc->copyInto.length); + + if (j > jmax) { + jmax = j; + result = sc->delayId; + } } + return result; } + #endif diff --git a/src/MemObject.h b/src/MemObject.h index 182c87323c..5dbcf6680a 100644 --- a/src/MemObject.h +++ b/src/MemObject.h @@ -1,6 +1,6 @@ /* - * $Id: MemObject.h,v 1.2 2003/02/05 10:36:48 robertc Exp $ + * $Id: MemObject.h,v 1.3 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -44,10 +44,12 @@ class store_client; #include "DelayId.h" #endif -class MemObject { +class MemObject +{ + public: static size_t inUseCount(); - + void dump() const; void *operator new (size_t); void operator delete (void *); @@ -59,12 +61,12 @@ public: HttpReply const *getReply() const; void stat (StoreEntry *s) const; off_t endOffset () const; - size_t size() const; + size_t size() const; void reset(); off_t lowestMemReaderOffset() const; bool readAheadPolicyCanRead() const; void addClient(store_client *); - /* XXX belongs in MemObject::swapout, once swaphdrsz is managed + /* XXX belongs in MemObject::swapout, once swaphdrsz is managed * better */ size_t objectBytesOnDisk() const; @@ -74,11 +76,13 @@ public: bool isContiguous() const; int mostBytesWanted(int max) const; #if DELAY_POOLS + DelayId mostBytesAllowed() const; #endif #if URL_CHECKSUM_DEBUG + void checkUrlChecksum() const; #endif @@ -88,31 +92,43 @@ public: off_t inmem_lo; dlink_list clients; int nclients; - struct { + + struct + { off_t queue_offset; /* relative to in-mem data */ mem_node *memnode; /* which node we're currently paging out */ - StoreIOState::Pointer sio; - } swapout; + StoreIOState::Pointer sio; + } + + swapout; /* Read only - this reply must be preserved by store clients */ /* The original reply. possibly with updated metadata. */ request_t *request; + struct timeval start_ping; IRCB *ping_reply_callback; void *ircb_data; int fd; /* FD of client creating this entry */ - struct { + + struct + { STABH *callback; void *data; - } abort; + } + + abort; char *log_url; RemovalPolicyNode repl; int id; ssize_t object_sz; size_t swap_hdr_sz; #if URL_CHECKSUM_DEBUG + unsigned int chksum; #endif + const char *vary_headers; + private: static MemPool *pool; diff --git a/src/NullDelayId.cc b/src/NullDelayId.cc index ceaaaa4dae..9b37f89685 100644 --- a/src/NullDelayId.cc +++ b/src/NullDelayId.cc @@ -1,6 +1,6 @@ /* - * $Id: NullDelayId.cc,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: NullDelayId.cc,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -63,5 +63,6 @@ NullDelayId::deleteSelf() const { delete this; } + #endif diff --git a/src/NullDelayId.h b/src/NullDelayId.h index b965580d59..33a177b001 100644 --- a/src/NullDelayId.h +++ b/src/NullDelayId.h @@ -1,6 +1,6 @@ /* - * $Id: NullDelayId.h,v 1.1 2003/02/05 10:36:48 robertc Exp $ + * $Id: NullDelayId.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -46,13 +46,17 @@ #include "RefCount.h" #include "DelayIdComposite.h" -class NullDelayId : public DelayIdComposite { - public: +class NullDelayId : public DelayIdComposite +{ + +public: void *operator new(size_t); void operator delete (void *); virtual void deleteSelf() const; virtual int bytesWanted (int min, int max) const {return XMAX(min,max);} - virtual void bytesIn(int qty) {} -}; + + virtual void bytesIn(int qty) {}} + +; #endif #endif /* NULLDELAYID_H */ diff --git a/src/Packer.cc b/src/Packer.cc index e00eae4849..7b831eddb5 100644 --- a/src/Packer.cc +++ b/src/Packer.cc @@ -1,6 +1,6 @@ /* - * $Id: Packer.cc,v 1.15 2003/01/23 00:37:14 robertc Exp $ + * $Id: Packer.cc,v 1.16 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 60 Packer: A uniform interface to store-like modules * AUTHOR: Alex Rousskov @@ -151,7 +151,7 @@ packerPrintf(Packer * p, const char *fmt,...) #else void packerPrintf(va_alist) - va_dcl +va_dcl { va_list args; Packer *p = NULL; @@ -161,6 +161,7 @@ packerPrintf(va_alist) p = va_arg(args, Packer *); fmt = va_arg(args, char *); #endif + assert(p); assert(p->real_handler && p->vprintf); p->vprintf(p->real_handler, fmt, args); diff --git a/src/ProfStats.cc b/src/ProfStats.cc index cd95c407a7..8caf8dc67a 100644 --- a/src/ProfStats.cc +++ b/src/ProfStats.cc @@ -1,6 +1,6 @@ /* - * $Id: ProfStats.cc,v 1.3 2003/01/23 00:37:14 robertc Exp $ + * $Id: ProfStats.cc,v 1.4 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 81 CPU Profiling Routines * AUTHOR: Andres Kroonmaa @@ -84,9 +84,10 @@ static int xprof_comp(xprof_stats_node ** ii, xprof_stats_node ** jj) { if ((*ii)->hist.summ < (*jj)->hist.summ) - return (1); + return (1); + if ((*ii)->hist.summ > (*jj)->hist.summ) - return (-1); + return (-1); return (0); } @@ -97,8 +98,9 @@ xprof_sorthist(TimersArray * xprof_list) int i; for (i = 0; i < XPROF_LAST; i++) { - sortlist[i] = xprof_list[i]; + sortlist[i] = xprof_list[i]; } + qsort(&sortlist[XPROF_hash_lookup], XPROF_LAST - XPROF_hash_lookup, sizeof(xprof_stats_node *), (QS *) xprof_comp); } @@ -108,15 +110,15 @@ static void xprof_show_item(StoreEntry * sentry, const char *name, xprof_stats_data * hist) { storeAppendPrintf(sentry, - "%s\t %llu\t %llu\t %llu\t %llu\t %llu\t %.2f\t %6.3f\t\n", - name, - hist->count, - hist->summ, - (hist->best != XP_NOBEST ? hist->best : 0), - hist->count ? hist->summ / hist->count : 0, - hist->worst, - hist->count / time_frame, - dpercent((double) hist->summ, (double) hist->delta)); + "%s\t %llu\t %llu\t %llu\t %llu\t %llu\t %.2f\t %6.3f\t\n", + name, + hist->count, + hist->summ, + (hist->best != XP_NOBEST ? hist->best : 0), + hist->count ? hist->summ / hist->count : 0, + hist->worst, + hist->count / time_frame, + dpercent((double) hist->summ, (double) hist->delta)); } static void @@ -130,34 +132,44 @@ xprof_summary_item(StoreEntry * sentry, char *descr, TimersArray * list) hist = &sortlist[0]; show = &hist[0]->hist; + if (!hist[0]->hist.delta) - show = &hist[0]->accu; + show = &hist[0]->accu; time_frame = (double) show->delta / (double) xprof_average_delta; storeAppendPrintf(sentry, "\n%s:", descr); + storeAppendPrintf(sentry, " (Cumulated time: %llu, %.2f sec)\n", - show->delta, - time_frame - ); + show->delta, + time_frame + ); + storeAppendPrintf(sentry, - "Probe Name\t Events\t cumulated time \t best case \t average \t worst case\t Rate / sec \t %% in int\n"); + "Probe Name\t Events\t cumulated time \t best case \t average \t worst case\t Rate / sec \t %% in int\n"); for (i = 0; i < XPROF_LAST; i++) { - if (!hist[i]->name) - continue; - - show = &hist[i]->hist; - if (!show->count) - continue; - xprof_show_item(sentry, hist[i]->name, show); - - Totals.count += show->count; - Totals.summ += show->summ; - Totals.best += (show->best != XP_NOBEST ? show->best : 0); - Totals.worst += show->worst; - Totals.delta = (show->delta > Totals.delta ? show->delta : Totals.delta); + if (!hist[i]->name) + continue; + + show = &hist[i]->hist; + + if (!show->count) + continue; + + xprof_show_item(sentry, hist[i]->name, show); + + Totals.count += show->count; + + Totals.summ += show->summ; + + Totals.best += (show->best != XP_NOBEST ? show->best : 0); + + Totals.worst += show->worst; + + Totals.delta = (show->delta > Totals.delta ? show->delta : Totals.delta); } + xprof_show_item(sentry, "TOTALS", &Totals); } @@ -172,41 +184,44 @@ xprof_average(TimersArray ** list, int secs) int doavg = (xprof_events % secs); if (!*list) - *list = (TimersArray *)xcalloc(XPROF_LAST, sizeof(xprof_stats_node)); + *list = (TimersArray *)xcalloc(XPROF_LAST, sizeof(xprof_stats_node)); hist = *list; + now = get_tick(); for (i = 0; i < XPROF_LAST; i++) { - hist[i]->name = head[i]->name; - hist[i]->accu.summ += head[i]->accu.summ; - hist[i]->accu.count += head[i]->accu.count; /* accumulate multisec */ - - if (!hist[i]->accu.best) - hist[i]->accu.best = head[i]->accu.best; - - if (hist[i]->accu.best > head[i]->accu.best) - hist[i]->accu.best = head[i]->accu.best; - - if (hist[i]->accu.worst < head[i]->accu.worst) - hist[i]->accu.worst = head[i]->accu.worst; - - hist[i]->accu.delta += xprof_delta; - if (!doavg) { - /* we have X seconds accumulated */ - xprof_move(&hist[i]->accu, &hist[i]->hist); - xprof_reset(&hist[i]->accu); - - hist[i]->accu.start = now; - } - /* reset 0sec counters */ - if (secs == 1) { - keep = head[i]->accu.start; - xprof_move(&head[i]->accu, &head[i]->hist); - xprof_reset(&head[i]->accu); - hist[i]->accu.delta = 0; - head[i]->accu.start = keep; - } + hist[i]->name = head[i]->name; + hist[i]->accu.summ += head[i]->accu.summ; + hist[i]->accu.count += head[i]->accu.count; /* accumulate multisec */ + + if (!hist[i]->accu.best) + hist[i]->accu.best = head[i]->accu.best; + + if (hist[i]->accu.best > head[i]->accu.best) + hist[i]->accu.best = head[i]->accu.best; + + if (hist[i]->accu.worst < head[i]->accu.worst) + hist[i]->accu.worst = head[i]->accu.worst; + + hist[i]->accu.delta += xprof_delta; + + if (!doavg) { + /* we have X seconds accumulated */ + xprof_move(&hist[i]->accu, &hist[i]->hist); + xprof_reset(&hist[i]->accu); + + hist[i]->accu.start = now; + } + + /* reset 0sec counters */ + if (secs == 1) { + keep = head[i]->accu.start; + xprof_move(&head[i]->accu, &head[i]->hist); + xprof_reset(&head[i]->accu); + hist[i]->accu.delta = 0; + head[i]->accu.start = keep; + } } } @@ -217,15 +232,15 @@ xprof_summary(StoreEntry * sentry) storeAppendPrintf(sentry, "CPU Profiling Statistics:\n"); storeAppendPrintf(sentry, - " (CPU times are in arbitrary units, most probably in CPU clock ticks)\n"); + " (CPU times are in arbitrary units, most probably in CPU clock ticks)\n"); storeAppendPrintf(sentry, - "Probe Name\t Event Count\t last Interval \t Avg Interval \t since squid start \t (since system boot) \n"); + "Probe Name\t Event Count\t last Interval \t Avg Interval \t since squid start \t (since system boot) \n"); storeAppendPrintf(sentry, "Total\t %lu\t %llu \t %llu \t %llu \t %llu\n", - (long unsigned) xprof_events, - xprof_delta, - xprof_average_delta, - now - xprof_verystart, - now); + (long unsigned) xprof_events, + xprof_delta, + xprof_average_delta, + now - xprof_verystart, + now); xprof_summary_item(sentry, "Last 1 sec averages", xprof_stats_avg1sec); xprof_summary_item(sentry, "Last 5 sec averages", xprof_stats_avg5sec); @@ -242,8 +257,8 @@ static inline void xprof_chk_overhead(int samples) { while (samples--) { - PROF_start(PROF_OVERHEAD); - PROF_stop(PROF_OVERHEAD); + PROF_start(PROF_OVERHEAD); + PROF_stop(PROF_OVERHEAD); } } @@ -252,11 +267,12 @@ static void xprof_Init(void) { if (xprof_inited) - return; + return; xprof_delta = xprof_verystart = xprof_start_t = now; xprof_inited = 1; + cachemgrRegister("cpu_profile", "CPU Profiling Stats", xprof_summary, 0, 1); } @@ -270,22 +286,35 @@ xprof_event(void *data) xprof_events++; if (!xprof_average_delta) - xprof_average_delta = xprof_delta; + xprof_average_delta = xprof_delta; + if (xprof_average_delta > (xprof_delta >> 1)) - xprof_average_delta = xprof_average_delta - (xprof_average_delta >> 8) + (xprof_delta >> 8); + xprof_average_delta = xprof_average_delta - (xprof_average_delta >> 8) + (xprof_delta >> 8); xprof_nesting++; + xprof_chk_overhead(2); + xprof_average(&xprof_stats_avg24hour, 24 * 3600); + xprof_average(&xprof_stats_avg5hour, 5 * 3600); + xprof_average(&xprof_stats_avg1hour, 3600); + xprof_average(&xprof_stats_avg30min, 1800); + xprof_average(&xprof_stats_avg5min, 300); + xprof_average(&xprof_stats_avg1min, 60); + xprof_average(&xprof_stats_avg30sec, 30); + xprof_average(&xprof_stats_avg5sec, 5); + xprof_average(&xprof_stats_avg1sec, 1); + xprof_chk_overhead(30); + xprof_nesting--; eventAdd("cpuProfiling", xprof_event, NULL, 1.0, 1); diff --git a/src/SquidString.h b/src/SquidString.h index 6d2e9b2a2d..2f7340da3d 100644 --- a/src/SquidString.h +++ b/src/SquidString.h @@ -1,6 +1,6 @@ /* - * $Id: SquidString.h,v 1.1 2003/02/02 13:27:43 robertc Exp $ + * $Id: SquidString.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 67 String * AUTHOR: Duane Wessels @@ -36,17 +36,19 @@ #ifndef SQUID_STRING_H #define SQUID_STRING_H -class String { +class String +{ + public: static const String Null; _SQUID_INLINE_ String(); String (char const *); String (String const &); ~String(); - + String &operator =(char const *); String &operator =(String const &); - + _SQUID_INLINE_ int size() const; _SQUID_INLINE_ char const * buf() const; void init (char const *); @@ -59,9 +61,11 @@ public: void append (String const &); void absorb(String &old); _SQUID_INLINE_ int nCaseCmp (char const *aString, int aLen) const; + private: /* never reference these directly! */ unsigned short int size_; /* buffer size; 64K limit */ + public: unsigned short int len_; /* current length */ char *buf_; diff --git a/src/StatHist.cc b/src/StatHist.cc index a17b52c52e..497598f9a5 100644 --- a/src/StatHist.cc +++ b/src/StatHist.cc @@ -1,6 +1,6 @@ /* - * $Id: StatHist.cc,v 1.29 2003/01/23 00:37:14 robertc Exp $ + * $Id: StatHist.cc,v 1.30 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 62 Generic Histogram * AUTHOR: Duane Wessels @@ -54,10 +54,10 @@ static int statHistBin(const StatHist * H, double v); static double statHistVal(const StatHist * H, int bin); static StatHistBinDumper statHistBinDumper; #if !defined(_SQUID_HPUX_) || !defined(__GNUC__) - /* - * HP-UX and GCC (2.8?) give strange errors when these simple - * functions are static. - */ +/* + * HP-UX and GCC (2.8?) give strange errors when these simple + * functions are static. + */ static hbase_f Log; static hbase_f Exp; static hbase_f Null; @@ -111,7 +111,7 @@ statHistCopy(StatHist * Dest, const StatHist * Orig) assert(Dest->bins); /* better be safe than sorry */ debug(62, 3) ("statHistCopy: capacity %d %d\n", - Dest->capacity, Orig->capacity); + Dest->capacity, Orig->capacity); assert(Dest->capacity == Orig->capacity); debug(62, 3) ("statHistCopy: min %f %f\n", Dest->min, Orig->min); assert(Dest->min == Orig->min); @@ -123,9 +123,9 @@ statHistCopy(StatHist * Dest, const StatHist * Orig) assert(Dest->val_out == Orig->val_out); /* actual copy */ debug(62, 3) ("statHistCopy: copying %ld bytes to %p from %p\n", - (long int) (Dest->capacity * sizeof(*Dest->bins)), - Dest->bins, - Orig->bins); + (long int) (Dest->capacity * sizeof(*Dest->bins)), + Dest->bins, + Orig->bins); xmemcpy(Dest->bins, Orig->bins, Dest->capacity * sizeof(*Dest->bins)); } @@ -139,8 +139,9 @@ statHistSafeCopy(StatHist * Dest, const StatHist * Orig) { assert(Dest && Orig); assert(Dest->bins); + if (Dest->capacity == Orig->capacity) - statHistCopy(Dest, Orig); + statHistCopy(Dest, Orig); } void @@ -157,17 +158,24 @@ statHistBin(const StatHist * H, double v) { int bin; #if BROKEN_STAT_HIST_BIN + return 0; /* NOTREACHED */ #endif + v -= H->min; /* offset */ + if (v <= 0.0) /* too small */ - return 0; + return 0; + bin = (int) floor(H->scale * H->val_in(v) + 0.5); + if (bin < 0) /* should not happen */ - bin = 0; + bin = 0; + if (bin >= H->capacity) /* too big */ - bin = H->capacity - 1; + bin = H->capacity - 1; + return bin; } @@ -191,32 +199,47 @@ statHistDeltaMedian(const StatHist * A, const StatHist * B) double f; int *D = (int *)xcalloc(A->capacity, sizeof(int)); assert(A->capacity == B->capacity); + for (i = 0; i < A->capacity; i++) { - D[i] = B->bins[i] - A->bins[i]; - assert(D[i] >= 0); + D[i] = B->bins[i] - A->bins[i]; + assert(D[i] >= 0); } + for (i = 0; i < A->capacity; i++) - s1 += D[i]; + s1 += D[i]; + h = s1 >> 1; + for (i = 0; i < A->capacity; i++) { - J = i; - b += D[J]; - if (a <= h && h <= b) - break; - I = i; - a += D[I]; + J = i; + b += D[J]; + + if (a <= h && h <= b) + break; + + I = i; + + a += D[I]; } + xfree(D); + if (s1 == 0) - return 0.0; + return 0.0; + if (a > h) - return 0.0; + return 0.0; + if (a >= b) - return 0.0; + return 0.0; + if (I >= J) - return 0.0; + return 0.0; + f = (h - a) / (b - a); + K = (int) floor(f * (double) (J - I) + I); + return statHistVal(A, K); } @@ -224,8 +247,8 @@ static void statHistBinDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) - storeAppendPrintf(sentry, "\t%3d/%f\t%d\t%f\n", - idx, val, count, count / size); + storeAppendPrintf(sentry, "\t%3d/%f\t%d\t%f\n", + idx, val, count, count / size); } void @@ -233,13 +256,15 @@ statHistDump(const StatHist * H, StoreEntry * sentry, StatHistBinDumper * bd) { int i; double left_border = H->min; + if (!bd) - bd = statHistBinDumper; + bd = statHistBinDumper; + for (i = 0; i < H->capacity; i++) { - const double right_border = statHistVal(H, i + 1); - assert(right_border - left_border > 0.0); - bd(sentry, i, left_border, right_border - left_border, H->bins[i]); - left_border = right_border; + const double right_border = statHistVal(H, i + 1); + assert(right_border - left_border > 0.0); + bd(sentry, i, left_border, right_border - left_border, H->bins[i]); + left_border = right_border; } } @@ -290,8 +315,8 @@ void statHistEnumDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) - storeAppendPrintf(sentry, "%2d\t %5d\t %5d\n", - idx, (int) val, count); + storeAppendPrintf(sentry, "%2d\t %5d\t %5d\n", + idx, (int) val, count); } void @@ -304,5 +329,5 @@ void statHistIntDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) - storeAppendPrintf(sentry, "%9d\t%9d\n", (int) val, count); + storeAppendPrintf(sentry, "%9d\t%9d\n", (int) val, count); } diff --git a/src/Store.h b/src/Store.h index 15efec74f9..09e9e884d8 100644 --- a/src/Store.h +++ b/src/Store.h @@ -1,6 +1,6 @@ /* - * $Id: Store.h,v 1.6 2003/01/23 00:37:14 robertc Exp $ + * $Id: Store.h,v 1.7 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,14 +37,18 @@ #include "StoreIOBuffer.h" class StoreClient; + class MemObject; typedef void STSETUP(storefs_entry_t *); -class StoreEntry : public hash_link { + +class StoreEntry : public hash_link +{ + public: static int CheckDeferRead(int fd, void *data); static void FsAdd(const char *, STSETUP *); - + virtual const char *getMD5Text() const; virtual HttpReply const *getReply() const; virtual void write (StoreIOBuffer); @@ -67,24 +71,40 @@ public: u_short refcount; u_short flags; /* END OF ON-DISK STORE_META_STD */ - sfileno swap_filen:25; - sdirno swap_dirn:7; + +sfileno swap_filen: + 25; + +sdirno swap_dirn: + 7; u_short lock_count; /* Assume < 65536! */ - mem_status_t mem_status:3; - ping_status_t ping_status:3; - store_status_t store_status:3; - swap_status_t swap_status:3; + +mem_status_t mem_status: + 3; + +ping_status_t ping_status: + 3; + +store_status_t store_status: + 3; + +swap_status_t swap_status: + 3; + public: static size_t inUseCount(); static void getPublicByRequestMethod(StoreClient * aClient, request_t * request, const method_t method); static void getPublicByRequest(StoreClient * aClient, request_t * request); static void getPublic(StoreClient * aClient, const char *uri, const method_t method); - virtual bool isNull() { - return false; + virtual bool isNull() + { + return false; } + void *operator new(size_t byteCount); void operator delete(void *address); + private: static MemPool *pool; @@ -93,25 +113,34 @@ private: class NullStoreEntry:public StoreEntry { + public: static NullStoreEntry *getInstance(); - bool isNull() { - return true; + bool isNull() + { + return true; } + const char *getMD5Text() const; _SQUID_INLINE_ HttpReply const *getReply() const; void write (StoreIOBuffer){} + bool isEmpty () const {return true;} + int checkDeferRead(int fd) const {return 1;} + void operator delete(void *address); void complete(){} - private: + +private: store_client_t storeClientType() const{return STORE_MEM_CLIENT;} + char const *getSerialisedMetaData(); bool swapoutPossible() {return false;} + void trimMemory() {} - + static NullStoreEntry _instance; }; diff --git a/src/StoreClient.h b/src/StoreClient.h index bb8de1359e..c63cf98130 100644 --- a/src/StoreClient.h +++ b/src/StoreClient.h @@ -1,6 +1,6 @@ /* - * $Id: StoreClient.h,v 1.8 2003/02/06 09:57:36 robertc Exp $ + * $Id: StoreClient.h,v 1.9 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,10 +40,13 @@ typedef void STCB(void *, StoreIOBuffer); /* store callback */ class StoreEntry; -class StoreClient { +class StoreClient +{ + public: - virtual ~StoreClient () {} - virtual void created (StoreEntry *newEntry) = 0; + virtual ~StoreClient () {} + + virtual void created (StoreEntry *newEntry) = 0; }; #if DELAY_POOLS @@ -51,7 +54,10 @@ public: #endif /* keep track each client receiving data from that particular StoreEntry */ -class store_client { + +class store_client +{ + public: void *operator new (size_t); void operator delete(void *); @@ -69,36 +75,56 @@ public: off_t cmp_offset; #if STORE_CLIENT_LIST_DEBUG + void *owner; #endif + StoreEntry *entry; /* ptr to the parent StoreEntry, argh! */ StoreIOState::Pointer swapin_sio; - struct { - unsigned int disk_io_pending:1; - unsigned int store_copying:1; - unsigned int copy_event_pending:1; - } flags; + + struct + { + +unsigned int disk_io_pending: + 1; + +unsigned int store_copying: + 1; + +unsigned int copy_event_pending: + 1; + } + + flags; #if DELAY_POOLS + DelayId delayId; void setDelayId(DelayId delay_id); #endif + dlink_node node; /* Below here is private - do no alter outside storeClient calls */ StoreIOBuffer copyInto; + private: static MemPool *pool; void fileRead(); void unpackHeader(char const *buf, ssize_t len); - + int type; bool object_ok; - struct Callback { - Callback ():callback_handler(NULL), callback_data(NULL){} - Callback (STCB *, void *); - STCB *callback_handler; - void *callback_data; - } _callback; + + struct Callback + { + Callback ():callback_handler(NULL), callback_data(NULL){} + + Callback (STCB *, void *); + STCB *callback_handler; + void *callback_data; + } + + _callback; }; SQUIDCEXTERN void storeClientCopy(store_client *, StoreEntry *, StoreIOBuffer, STCB *, void *); diff --git a/src/StoreIOBuffer.h b/src/StoreIOBuffer.h index 21e7f1a21d..04d49aaf4c 100644 --- a/src/StoreIOBuffer.h +++ b/src/StoreIOBuffer.h @@ -1,6 +1,6 @@ /* - * $Id: StoreIOBuffer.h,v 1.2 2003/01/23 00:37:14 robertc Exp $ + * $Id: StoreIOBuffer.h,v 1.3 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -34,17 +34,26 @@ #ifndef SQUID_STOREIORESULT_H #define SQUID_STOREIORESULT_H -class StoreIOBuffer { +class StoreIOBuffer +{ + public: StoreIOBuffer():length(0), offset (0), data (NULL){flags.error = 0;} + StoreIOBuffer(size_t aLength, off_t anOffset, char *someData) : - length (aLength), offset (anOffset), data (someData) - { - flags.error = 0; - } - struct { - int error:1; - } flags; + length (aLength), offset (anOffset), data (someData) + { + flags.error = 0; + } + + struct + { + +int error: + 1; + } + + flags; size_t length; off_t offset; char *data; diff --git a/src/StoreIOState.cc b/src/StoreIOState.cc index 7fa230ab4e..c6eb20834b 100644 --- a/src/StoreIOState.cc +++ b/src/StoreIOState.cc @@ -1,6 +1,6 @@ /* - * $Id: StoreIOState.cc,v 1.2 2003/01/23 00:37:14 robertc Exp $ + * $Id: StoreIOState.cc,v 1.3 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section ?? Swap Dir base object * AUTHOR: Robert Collins @@ -35,7 +35,7 @@ #include "squid.h" #include "StoreIOState.h" - + void * storeIOState::operator new (size_t amount) { @@ -43,7 +43,7 @@ storeIOState::operator new (size_t amount) return (void *)1; } -void +void storeIOState::operator delete (void *address){assert (0);} storeIOState::storeIOState() @@ -60,7 +60,8 @@ storeIOState::offset() const storeIOState::~storeIOState() { if (read.callback_data) - cbdataReferenceDone(read.callback_data); + cbdataReferenceDone(read.callback_data); + if (callback_data) - cbdataReferenceDone(callback_data); + cbdataReferenceDone(callback_data); } diff --git a/src/StoreIOState.h b/src/StoreIOState.h index a763a7fd9e..5695deef5f 100644 --- a/src/StoreIOState.h +++ b/src/StoreIOState.h @@ -1,6 +1,6 @@ /* - * $Id: StoreIOState.h,v 1.3 2003/01/23 00:37:14 robertc Exp $ + * $Id: StoreIOState.h,v 1.4 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,7 +35,10 @@ #define SQUID_STOREIOSTATE_H #include "RefCount.h" -class storeIOState : public RefCountable{ + +class storeIOState : public RefCountable +{ + public: /* storeIOState does not get mempooled - it's children do */ @@ -51,7 +54,7 @@ public: virtual void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) = 0; virtual void write(char const *buf, size_t size, off_t offset, FREE * free_func) = 0; virtual void close() = 0; - + sdirno swap_dirn; sfileno swap_filen; StoreEntry *e; /* Need this so the FS layers can play god */ @@ -60,16 +63,28 @@ public: STFNCB *file_callback; /* called on delayed sfileno assignments */ STIOCB *callback; void *callback_data; - struct { - STRCB *callback; - void *callback_data; - } read; - struct { - unsigned int closing:1; /* debugging aid */ - } flags; + + struct + { + STRCB *callback; + void *callback_data; + } + + read; + + struct + { + +unsigned int closing: + 1; /* debugging aid */ + } + + flags; }; -class StoreIOState { +class StoreIOState +{ + public: typedef RefCount Pointer; }; diff --git a/src/StoreMeta.cc b/src/StoreMeta.cc index 58316180fd..152d9aafc7 100644 --- a/src/StoreMeta.cc +++ b/src/StoreMeta.cc @@ -1,6 +1,6 @@ /* - * $Id: StoreMeta.cc,v 1.1 2003/01/23 00:37:14 robertc Exp $ + * $Id: StoreMeta.cc,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 20 Storage Manager Swapfile Metadata * AUTHOR: Kostas Anagnostakis @@ -46,37 +46,45 @@ bool StoreMeta::validType(char type) { /* VOID is reserved, and new types have to be added as classes */ + if (type <= STORE_META_VOID || type >= STORE_META_END) { - debug(20, 0) ("storeSwapMetaUnpack: bad type (%d)!\n", type); - return false; + debug(20, 0) ("storeSwapMetaUnpack: bad type (%d)!\n", type); + return false; } + /* Unused in any current squid code */ if (type == STORE_META_KEY_URL || - type == STORE_META_KEY_SHA || - type == STORE_META_HITMETERING || - type == STORE_META_VALID) { - debug (20,0)("Obsolete and unused type (%d) in disk metadata\n", type); - return false; + type == STORE_META_KEY_SHA || + type == STORE_META_HITMETERING || + type == STORE_META_VALID) { + debug (20,0)("Obsolete and unused type (%d) in disk metadata\n", type); + return false; } + return true; } -class IntRange{ +class IntRange +{ + public: - IntRange (int minimum, int maximum) : _min (minimum), _max (maximum) - { - if (_min > _max) { - int temp = _min; - _min = _max; - _max = temp; - } - } + IntRange (int minimum, int maximum) : _min (minimum), _max (maximum) + { + if (_min > _max) { + int temp = _min; + _min = _max; + _max = temp; + } + } + bool includes (int anInt) const - { - if (anInt < _min || anInt > _max) - return false; - return true; - } + { + if (anInt < _min || anInt > _max) + return false; + + return true; + } + private: int _min; int _max; @@ -88,10 +96,11 @@ const int StoreMeta::MaximumTLVLength = 1 << 16; bool StoreMeta::validLength(int length) const { - if (!IntRange (MinimumTLVLength, MaximumTLVLength).includes(length)){ - debug(20, 0) ("storeSwapMetaUnpack: insane length (%d)!\n", length); - return false; + if (!IntRange (MinimumTLVLength, MaximumTLVLength).includes(length)) { + debug(20, 0) ("storeSwapMetaUnpack: insane length (%d)!\n", length); + return false; } + return true; } @@ -101,28 +110,37 @@ StoreMeta::Factory (char type, size_t len, void const *value) { if (!validType(type)) return NULL; + StoreMeta *result; + switch (type) { - case STORE_META_KEY: - result = new StoreMetaMD5; - break; - case STORE_META_URL: - result = new StoreMetaURL; - break; - case STORE_META_STD: - result = new StoreMetaSTD; - break; - case STORE_META_VARY_HEADERS: - result = new StoreMetaVary; - break; - default: - debug (20,0)("Attempt to create unknown concrete StoreMeta\n"); - return NULL; + + case STORE_META_KEY: + result = new StoreMetaMD5; + break; + + case STORE_META_URL: + result = new StoreMetaURL; + break; + + case STORE_META_STD: + result = new StoreMetaSTD; + break; + + case STORE_META_VARY_HEADERS: + result = new StoreMetaVary; + break; + + default: + debug (20,0)("Attempt to create unknown concrete StoreMeta\n"); + return NULL; } + if (!result->validLength(len)) { - result->deleteSelf(); - return NULL; + result->deleteSelf(); + return NULL; } + result->length = len; result->value = xmalloc(len); xmemcpy(result->value, value, len); @@ -133,10 +151,11 @@ void StoreMeta::FreeList(StoreMeta **head) { StoreMeta *node; + while ((node = *head) != NULL) { - *head = node->next; - xfree(node->value); - node->deleteSelf(); + *head = node->next; + xfree(node->value); + node->deleteSelf(); } } @@ -148,22 +167,27 @@ StoreMeta::Add(StoreMeta **tail, StoreMeta *aNode) return &aNode->next; /* return new tail pointer */ } -bool +bool StoreMeta::checkConsistency(StoreEntry *e) const { - switch (getType()) - { - case STORE_META_KEY: - case STORE_META_URL: - case STORE_META_VARY_HEADERS: - assert(0); - break; - case STORE_META_STD: - break; - default: - debug(20, 1) ("WARNING: got unused STORE_META type %d\n", getType()); - break; - } + switch (getType()) { + + case STORE_META_KEY: + + case STORE_META_URL: + + case STORE_META_VARY_HEADERS: + assert(0); + break; + + case STORE_META_STD: + break; + + default: + debug(20, 1) ("WARNING: got unused STORE_META type %d\n", getType()); + break; + } + return true; } diff --git a/src/StoreMeta.h b/src/StoreMeta.h index ac7ff78580..6bb256314f 100644 --- a/src/StoreMeta.h +++ b/src/StoreMeta.h @@ -1,6 +1,6 @@ /* - * $Id: StoreMeta.h,v 1.1 2003/01/23 00:37:14 robertc Exp $ + * $Id: StoreMeta.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,8 +35,12 @@ #define SQUID_TYPELENGTHVALUE_H class StoreEntry; + typedef class StoreMeta tlv; -class StoreMeta { + +class StoreMeta +{ + public: virtual void deleteSelf() = 0; static bool validType(char); @@ -45,15 +49,16 @@ public: static StoreMeta *Factory (char type, size_t len, void const *value); static StoreMeta **Add(StoreMeta **tail, StoreMeta *aNode); static void FreeList (StoreMeta **head); - + virtual char getType() const = 0; virtual bool validLength(int) const; virtual bool checkConsistency(StoreEntry *) const; virtual ~StoreMeta(){} - + int length; void *value; tlv *next; + private: }; diff --git a/src/StoreMetaMD5.cc b/src/StoreMetaMD5.cc index a8b03f6825..9108b3ec75 100644 --- a/src/StoreMetaMD5.cc +++ b/src/StoreMetaMD5.cc @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaMD5.cc,v 1.1 2003/01/23 00:37:14 robertc Exp $ + * $Id: StoreMetaMD5.cc,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 20 Storage Manager Swapfile Metadata * AUTHOR: Kostas Anagnostakis @@ -45,8 +45,10 @@ StoreMetaMD5::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (StoreMetaMD5)); + if (!pool) - pool = memPoolCreate("StoreMetaMD5", sizeof (StoreMetaMD5)); + pool = memPoolCreate("StoreMetaMD5", sizeof (StoreMetaMD5)); + return memPoolAlloc(pool); } @@ -62,7 +64,7 @@ StoreMetaMD5::deleteSelf() delete this; } -bool +bool StoreMetaMD5::validLength(int len) const { return len == MD5_DIGEST_CHARS; @@ -70,20 +72,24 @@ StoreMetaMD5::validLength(int len) const int StoreMetaMD5::md5_mismatches = 0; -bool +bool StoreMetaMD5::checkConsistency(StoreEntry *e) const { assert (getType() == STORE_META_KEY_MD5); assert(length == MD5_DIGEST_CHARS); + if (!EBIT_TEST(e->flags, KEY_PRIVATE) && - memcmp(value, e->key, MD5_DIGEST_CHARS)) { - debug(20, 2) ("storeClientReadHeader: swapin MD5 mismatch\n"); -// debug(20, 2) ("\t%s\n", storeKeyText((const cache_key *)value)); - debug(20, 2) ("\t%s\n", e->getMD5Text()); - if (isPowTen(++md5_mismatches)) - debug(20, 1) ("WARNING: %d swapin MD5 mismatches\n", - md5_mismatches); - return false; + memcmp(value, e->key, MD5_DIGEST_CHARS)) { + debug(20, 2) ("storeClientReadHeader: swapin MD5 mismatch\n"); + // debug(20, 2) ("\t%s\n", storeKeyText((const cache_key *)value)); + debug(20, 2) ("\t%s\n", e->getMD5Text()); + + if (isPowTen(++md5_mismatches)) + debug(20, 1) ("WARNING: %d swapin MD5 mismatches\n", + md5_mismatches); + + return false; } + return true; } diff --git a/src/StoreMetaMD5.h b/src/StoreMetaMD5.h index 54651254f5..ee789f025e 100644 --- a/src/StoreMetaMD5.h +++ b/src/StoreMetaMD5.h @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaMD5.h,v 1.1 2003/01/23 00:37:14 robertc Exp $ + * $Id: StoreMetaMD5.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,16 +36,19 @@ #include "StoreMeta.h" -class StoreMetaMD5 : public StoreMeta { +class StoreMetaMD5 : public StoreMeta +{ + public: void *operator new (size_t); void operator delete (void *); void deleteSelf(); - + char getType() const {return STORE_META_KEY_MD5;} + bool validLength(int) const; bool checkConsistency(StoreEntry *) const; - + private: static MemPool *pool; static int md5_mismatches; diff --git a/src/StoreMetaSTD.cc b/src/StoreMetaSTD.cc index 2fe3b271d9..ec4dc9bb2c 100644 --- a/src/StoreMetaSTD.cc +++ b/src/StoreMetaSTD.cc @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaSTD.cc,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaSTD.cc,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 20 Storage Manager Swapfile Metadata * AUTHOR: Kostas Anagnostakis @@ -45,8 +45,10 @@ StoreMetaSTD::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (StoreMetaSTD)); + if (!pool) - pool = memPoolCreate("StoreMetaSTD", sizeof (StoreMetaSTD)); + pool = memPoolCreate("StoreMetaSTD", sizeof (StoreMetaSTD)); + return memPoolAlloc(pool); } diff --git a/src/StoreMetaSTD.h b/src/StoreMetaSTD.h index 1c78e8bb5d..24357d7a2f 100644 --- a/src/StoreMetaSTD.h +++ b/src/StoreMetaSTD.h @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaSTD.h,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaSTD.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,16 +36,19 @@ #include "StoreMeta.h" -class StoreMetaSTD : public StoreMeta { +class StoreMetaSTD : public StoreMeta +{ + public: void *operator new (size_t); void operator delete (void *); void deleteSelf(); - + char getType() const {return STORE_META_STD;} + bool validLength(int) const; -// bool checkConsistency(StoreEntry *) const; - + // bool checkConsistency(StoreEntry *) const; + private: static MemPool *pool; }; diff --git a/src/StoreMetaURL.cc b/src/StoreMetaURL.cc index 57bc9b2684..150f983156 100644 --- a/src/StoreMetaURL.cc +++ b/src/StoreMetaURL.cc @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaURL.cc,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaURL.cc,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 20 Storage Manager Swapfile Metadata * AUTHOR: Kostas Anagnostakis @@ -45,8 +45,10 @@ StoreMetaURL::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (StoreMetaURL)); + if (!pool) - pool = memPoolCreate("StoreMetaURL", sizeof (StoreMetaURL)); + pool = memPoolCreate("StoreMetaURL", sizeof (StoreMetaURL)); + return memPoolAlloc(pool); } @@ -62,16 +64,19 @@ StoreMetaURL::deleteSelf() delete this; } -bool +bool StoreMetaURL::checkConsistency(StoreEntry *e) const { assert (getType() == STORE_META_URL); + if (!e->mem_obj->url) - return true; + return true; + if (strcasecmp(e->mem_obj->url, (char *)value)) { - debug(20, 1) ("storeClientReadHeader: URL mismatch\n"); - debug(20, 1) ("\t{%s} != {%s}\n", (char *) value, e->mem_obj->url); - return false; + debug(20, 1) ("storeClientReadHeader: URL mismatch\n"); + debug(20, 1) ("\t{%s} != {%s}\n", (char *) value, e->mem_obj->url); + return false; } + return true; } diff --git a/src/StoreMetaURL.h b/src/StoreMetaURL.h index 747c4d2da6..6c2efbbfb6 100644 --- a/src/StoreMetaURL.h +++ b/src/StoreMetaURL.h @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaURL.h,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaURL.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,15 +36,18 @@ #include "StoreMeta.h" -class StoreMetaURL : public StoreMeta { +class StoreMetaURL : public StoreMeta +{ + public: void *operator new (size_t); void operator delete (void *); void deleteSelf(); - + char getType() const {return STORE_META_URL;} + bool checkConsistency(StoreEntry *) const; - + private: static MemPool *pool; }; diff --git a/src/StoreMetaUnpacker.cc b/src/StoreMetaUnpacker.cc index 1fb726d8c0..e1d648d561 100644 --- a/src/StoreMetaUnpacker.cc +++ b/src/StoreMetaUnpacker.cc @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaUnpacker.cc,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaUnpacker.cc,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 20 Storage Manager Swapfile Unpacker * AUTHOR: Robert Collins @@ -43,16 +43,20 @@ bool StoreMetaUnpacker::isBufferSane() { if (buf[0] != (char) STORE_META_OK) - return false; + return false; + /* * sanity check on 'buflen' value. It should be at least big * enough to hold one type and one length. */ getBufferLength(); + if (*hdr_len <= MinimumBufferLength) - return false; + return false; + if (*hdr_len > buflen) - return false; + return false; + return true; } @@ -85,17 +89,23 @@ StoreMetaUnpacker::doOneEntry() { getType(); getLength(); + if (position + length > *hdr_len) { debug(20, 0) ("storeSwapMetaUnpack: overflow!\n"); debug(20, 0) ("\ttype=%d, length=%d, *hdr_len=%d, offset=%d\n", - type, length, *hdr_len, (int) position); + type, length, *hdr_len, (int) position); return false; } + StoreMeta *newNode = StoreMeta::Factory(type, length, &buf[position]); + if (!newNode) - return false; + return false; + tail = StoreMeta::Add (tail, newNode); + position += length; + return true; } @@ -111,13 +121,18 @@ StoreMetaUnpacker::createStoreMeta () tlv *TLV = NULL; tail = &TLV; assert(hdr_len != NULL); + if (!isBufferSane()) - return NULL; + return NULL; + getBufferLength(); + assert (position == 1 + sizeof(int)); + while (moreToProcess()) { - if (!doOneEntry()) - break; + if (!doOneEntry()) + break; } + return TLV; } diff --git a/src/StoreMetaUnpacker.h b/src/StoreMetaUnpacker.h index bc427eba4a..8cc261e82c 100644 --- a/src/StoreMetaUnpacker.h +++ b/src/StoreMetaUnpacker.h @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaUnpacker.h,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaUnpacker.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,14 +35,18 @@ #define SQUID_TYPELENGTHVALUEUNPACKER_H class StoreMeta; -class StoreMetaUnpacker { + +class StoreMetaUnpacker +{ + public: StoreMetaUnpacker (const char *buf, ssize_t bufferLength, int *hdrlen); StoreMeta *createStoreMeta(); bool isBufferSane(); + private: static off_t const MinimumBufferLength; - + void getBufferLength(); void getType(); void getLength(); diff --git a/src/StoreMetaVary.cc b/src/StoreMetaVary.cc index 83b4863a82..8743a4ed7d 100644 --- a/src/StoreMetaVary.cc +++ b/src/StoreMetaVary.cc @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaVary.cc,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaVary.cc,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 20 Storage Manager Swapfile Metadata * AUTHOR: Kostas Anagnostakis @@ -45,8 +45,10 @@ StoreMetaVary::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (StoreMetaVary)); + if (!pool) - pool = memPoolCreate("StoreMetaVary", sizeof (StoreMetaVary)); + pool = memPoolCreate("StoreMetaVary", sizeof (StoreMetaVary)); + return memPoolAlloc(pool); } @@ -62,17 +64,20 @@ StoreMetaVary::deleteSelf() delete this; } -bool +bool StoreMetaVary::checkConsistency(StoreEntry *e) const { assert (getType() == STORE_META_VARY_HEADERS); + if (!e->mem_obj->vary_headers) { - /* XXX separate this mutator from the query */ - /* Assume the object is OK.. remember the vary request headers */ - e->mem_obj->vary_headers = xstrdup((char *)value); - return true; + /* XXX separate this mutator from the query */ + /* Assume the object is OK.. remember the vary request headers */ + e->mem_obj->vary_headers = xstrdup((char *)value); + return true; } + if (strcmp(e->mem_obj->vary_headers, (char *)value) != 0) - return false; + return false; + return true; } diff --git a/src/StoreMetaVary.h b/src/StoreMetaVary.h index 58a6a0ba31..269a04238d 100644 --- a/src/StoreMetaVary.h +++ b/src/StoreMetaVary.h @@ -1,6 +1,6 @@ /* - * $Id: StoreMetaVary.h,v 1.1 2003/01/23 00:37:15 robertc Exp $ + * $Id: StoreMetaVary.h,v 1.2 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,15 +36,18 @@ #include "StoreMeta.h" -class StoreMetaVary : public StoreMeta { +class StoreMetaVary : public StoreMeta +{ + public: void *operator new (size_t); void operator delete (void *); void deleteSelf(); - + char getType() const {return STORE_META_VARY_HEADERS;} + bool checkConsistency(StoreEntry *) const; - + private: static MemPool *pool; }; diff --git a/src/String.cc b/src/String.cc index 3f59c381f0..124edd7b36 100644 --- a/src/String.cc +++ b/src/String.cc @@ -1,6 +1,6 @@ /* - * $Id: String.cc,v 1.12 2003/01/23 00:37:15 robertc Exp $ + * $Id: String.cc,v 1.13 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 67 String * AUTHOR: Duane Wessels @@ -49,10 +49,11 @@ void String::init(char const *str) { assert(this); + if (str) - limitInit(str, strlen(str)); + limitInit(str, strlen(str)); else - clean(); + clean(); } String::String (char const *aString) : size_(0), len_(0), buf_(NULL) @@ -72,11 +73,13 @@ String & String::operator = (String const &old) { clean (); + if (old.len_) - limitInit (old.buf_, old.len_); + limitInit (old.buf_, old.len_); + return *this; } - + void String::limitInit(const char *str, int len) { @@ -96,10 +99,14 @@ void String::clean() { assert(this); + if (buf_) - memFreeString(size_, buf_); + memFreeString(size_, buf_); + len_ = 0; + size_ = 0; + buf_ = NULL; } @@ -120,19 +127,24 @@ String::append(const char *str, int len) { assert(this); assert(str && len >= 0); + if (len_ + len < size_) { - strncat(buf_, str, len); - len_ += len; + strncat(buf_, str, len); + len_ += len; } else { - String snew; - snew.len_ = len_ + len; - snew.initBuf(snew.len_ + 1); - if (buf_) - xmemcpy(snew.buf_, buf_, len_); - if (len) - xmemcpy(snew.buf_ + len_, str, len); - snew.buf_[snew.len_] = '\0'; - absorb(snew); + String snew; + snew.len_ = len_ + len; + snew.initBuf(snew.len_ + 1); + + if (buf_) + xmemcpy(snew.buf_, buf_, len_); + + if (len) + xmemcpy(snew.buf_ + len_, str, len); + + snew.buf_[snew.len_] = '\0'; + + absorb(snew); } } diff --git a/src/SwapDir.cc b/src/SwapDir.cc index 4043482682..002a88b371 100644 --- a/src/SwapDir.cc +++ b/src/SwapDir.cc @@ -1,6 +1,6 @@ /* - * $Id: SwapDir.cc,v 1.2 2003/01/23 00:37:15 robertc Exp $ + * $Id: SwapDir.cc,v 1.3 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section ?? Swap Dir base object * AUTHOR: Robert Collins @@ -45,7 +45,8 @@ SwapDir::Factory (_storefs_entry const &fs) return result; } -SwapDir::~SwapDir() { +SwapDir::~SwapDir() +{ xfree(path); } @@ -90,17 +91,23 @@ bool SwapDir::canLog(StoreEntry const &e)const { if (e.swap_filen < 0) - return false; + return false; + if (e.swap_status != SWAPOUT_DONE) - return false; + return false; + if (e.swap_file_sz <= 0) - return false; + return false; + if (EBIT_TEST(e.flags, RELEASE_REQUEST)) - return false; + return false; + if (EBIT_TEST(e.flags, KEY_PRIVATE)) - return false; + return false; + if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) - return false; + return false; + return true; } diff --git a/src/SwapDir.h b/src/SwapDir.h index 6c59848e0f..2abd4e667b 100644 --- a/src/SwapDir.h +++ b/src/SwapDir.h @@ -1,6 +1,6 @@ /* - * $Id: SwapDir.h,v 1.2 2003/01/23 00:37:15 robertc Exp $ + * $Id: SwapDir.h,v 1.3 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -41,12 +41,17 @@ typedef void STFSSTARTUP(void); typedef void STFSSHUTDOWN(void); typedef SwapDir *STFSNEW(void); -struct SwapDir { + +struct SwapDir +{ + public: static SwapDir *Factory (_storefs_entry const &fs); - SwapDir() : max_objsize (-1){ - fs.blksize = 1024; + SwapDir() : max_objsize (-1) + { + fs.blksize = 1024; } + virtual ~SwapDir(); virtual void reconfigure(int, char *) = 0; const char *type; @@ -59,10 +64,18 @@ public: RemovalPolicy *repl; int removals; int scanned; - struct { - unsigned int selected:1; - unsigned int read_only:1; - } flags; + + struct + { + +unsigned int selected: + 1; + +unsigned int read_only: + 1; + } + + flags; virtual void init() = 0; /* Initialise the fs */ virtual void newFileSystem(); /* Create a new fs */ virtual void dump(StoreEntry &)const; /* Dump fs config snippet */ @@ -83,18 +96,28 @@ public: virtual void openLog(); virtual void closeLog(); virtual void logEntry(const StoreEntry & e, int op) const; - class CleanLog { - public: - virtual ~CleanLog(){} - virtual const StoreEntry *nextEntry() = 0; - virtual void write(StoreEntry const &) = 0; + + class CleanLog + { + + public: + virtual ~CleanLog(){} + + virtual const StoreEntry *nextEntry() = 0; + virtual void write(StoreEntry const &) = 0; }; + CleanLog *cleanLog; virtual int writeCleanStart(); virtual void writeCleanDone(); virtual void parse(int index, char *path) = 0; - struct { - int blksize; - } fs; + + struct + { + int blksize; + } + + fs; }; + #endif /* SQUID_SWAPDIR_H */ diff --git a/src/access_log.cc b/src/access_log.cc index 56aa03b719..34862558f3 100644 --- a/src/access_log.cc +++ b/src/access_log.cc @@ -1,6 +1,6 @@ /* - * $Id: access_log.cc,v 1.79 2003/01/23 00:37:15 robertc Exp $ + * $Id: access_log.cc,v 1.80 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 46 Access Log * AUTHOR: Duane Wessels @@ -45,42 +45,47 @@ static Logfile *headerslog = NULL; #if MULTICAST_MISS_STREAM static int mcast_miss_fd = -1; + static struct sockaddr_in mcast_miss_to; static void mcast_encode(unsigned int *, size_t, const unsigned int *); #endif const char *log_tags[] = -{ - "NONE", - "TCP_HIT", - "TCP_MISS", - "TCP_REFRESH_HIT", - "TCP_REF_FAIL_HIT", - "TCP_REFRESH_MISS", - "TCP_CLIENT_REFRESH_MISS", - "TCP_IMS_HIT", - "TCP_SWAPFAIL_MISS", - "TCP_NEGATIVE_HIT", - "TCP_MEM_HIT", - "TCP_DENIED", - "TCP_OFFLINE_HIT", + { + "NONE", + "TCP_HIT", + "TCP_MISS", + "TCP_REFRESH_HIT", + "TCP_REF_FAIL_HIT", + "TCP_REFRESH_MISS", + "TCP_CLIENT_REFRESH_MISS", + "TCP_IMS_HIT", + "TCP_SWAPFAIL_MISS", + "TCP_NEGATIVE_HIT", + "TCP_MEM_HIT", + "TCP_DENIED", + "TCP_OFFLINE_HIT", #if LOG_TCP_REDIRECTS - "TCP_REDIRECT", + "TCP_REDIRECT", #endif - "UDP_HIT", - "UDP_MISS", - "UDP_DENIED", - "UDP_INVALID", - "UDP_MISS_NOFETCH", - "ICP_QUERY", - "LOG_TYPE_MAX" -}; + "UDP_HIT", + "UDP_MISS", + "UDP_DENIED", + "UDP_INVALID", + "UDP_MISS_NOFETCH", + "ICP_QUERY", + "LOG_TYPE_MAX" + }; #if FORW_VIA_DB -typedef struct { + +typedef struct +{ hash_link hash; int n; -} fvdb_entry; +} + +fvdb_entry; static hash_table *via_table = NULL; static hash_table *forw_table = NULL; static void fvdbInit(void); @@ -96,22 +101,22 @@ static int LogfileStatus = LOG_DISABLE; #define LOG_BUF_SZ (MAX_URL<<2) static const char c2x[] = -"000102030405060708090a0b0c0d0e0f" -"101112131415161718191a1b1c1d1e1f" -"202122232425262728292a2b2c2d2e2f" -"303132333435363738393a3b3c3d3e3f" -"404142434445464748494a4b4c4d4e4f" -"505152535455565758595a5b5c5d5e5f" -"606162636465666768696a6b6c6d6e6f" -"707172737475767778797a7b7c7d7e7f" -"808182838485868788898a8b8c8d8e8f" -"909192939495969798999a9b9c9d9e9f" -"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" -"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" -"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" -"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" -"e0e1e2e3e4e5e6e7e8e9eaebecedeeef" -"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f" + "505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; /* log_quote -- URL-style encoding on MIME headers. */ @@ -122,11 +127,13 @@ log_quote(const char *header) int i; char *buf; char *buf_cursor; + if (header == NULL) { - buf = static_cast(xcalloc(1, 1)); - *buf = '\0'; - return buf; + buf = static_cast(xcalloc(1, 1)); + *buf = '\0'; + return buf; } + buf = static_cast(xcalloc(1, (strlen(header) * 3) + 1)); buf_cursor = buf; /* @@ -135,49 +142,54 @@ log_quote(const char *header) * modulo the inclusion of space (x40) to make the raw logs a bit * more readable. */ + while ((c = *(const unsigned char *) header++) != '\0') { #if !OLD_LOG_MIME - if (c == '\r') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'r'; - } else if (c == '\n') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'n'; - } else + + if (c == '\r') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'r'; + } else if (c == '\n') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'n'; + } else #endif - if (c <= 0x1F - || c >= 0x7F + if (c <= 0x1F + || c >= 0x7F #if OLD_LOG_MIME - || c == '"' - || c == '#' - || c == '%' - || c == ';' - || c == '<' - || c == '>' - || c == '?' - || c == '{' - || c == '}' - || c == '|' - || c == '\\' - || c == '^' - || c == '~' - || c == '`' + || c == '"' + || c == '#' + || c == '%' + || c == ';' + || c == '<' + || c == '>' + || c == '?' + || c == '{' + || c == '}' + || c == '|' + || c == '\\' + || c == '^' + || c == '~' + || c == '`' #endif - || c == '[' - || c == ']') { - *buf_cursor++ = '%'; - i = c * 2; - *buf_cursor++ = c2x[i]; - *buf_cursor++ = c2x[i + 1]; + || c == '[' + || c == ']') { + *buf_cursor++ = '%'; + i = c * 2; + *buf_cursor++ = c2x[i]; + *buf_cursor++ = c2x[i + 1]; #if !OLD_LOG_MIME - } else if (c == '\\') { - *buf_cursor++ = '\\'; - *buf_cursor++ = '\\'; + + } else if (c == '\\') { + *buf_cursor++ = '\\'; + *buf_cursor++ = '\\'; #endif - } else { - *buf_cursor++ = (char) c; - } + + } else { + *buf_cursor++ = (char) c; + } } + *buf_cursor = '\0'; return buf; } @@ -190,35 +202,39 @@ username_quote(const char *header) int i; char *buf; char *buf_cursor; + if (header == NULL) { - buf = static_cast(xcalloc(1, 1)); - *buf = '\0'; - return buf; + buf = static_cast(xcalloc(1, 1)); + *buf = '\0'; + return buf; } + buf = static_cast(xcalloc(1, (strlen(header) * 3) + 1)); buf_cursor = buf; /* * We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF * to prevent garbage in the logs. CR and LF are also there just in case. */ + while ((c = *(const unsigned char *) header++) != '\0') { - if (c == '\r') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'r'; - } else if (c == '\n') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'n'; - } else if (c <= 0x1F - || c >= 0x7F - || c == ' ') { - *buf_cursor++ = '%'; - i = c * 2; - *buf_cursor++ = c2x[i]; - *buf_cursor++ = c2x[i + 1]; - } else { - *buf_cursor++ = (char) c; - } + if (c == '\r') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'r'; + } else if (c == '\n') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'n'; + } else if (c <= 0x1F + || c >= 0x7F + || c == ' ') { + *buf_cursor++ = '%'; + i = c * 2; + *buf_cursor++ = c2x[i]; + *buf_cursor++ = c2x[i + 1]; + } else { + *buf_cursor++ = (char) c; + } } + *buf_cursor = '\0'; return buf; } @@ -227,7 +243,8 @@ static char * accessLogFormatName(const char *name) { if (NULL == name) - return NULL; + return NULL; + return username_quote(name); } @@ -236,34 +253,44 @@ accessLogSquid(AccessLogEntry * al) { const char *client = NULL; const char *user = NULL; + if (Config.onoff.log_fqdn) - client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); + client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); + if (client == NULL) - client = inet_ntoa(al->cache.caddr); + client = inet_ntoa(al->cache.caddr); + user = accessLogFormatName(al->cache.authuser); + #if USE_SSL + if (!user) - user = accessLogFormatName(al->cache.ssluser); + user = accessLogFormatName(al->cache.ssluser); + #endif + if (!user) - user = accessLogFormatName(al->cache.rfc931); + user = accessLogFormatName(al->cache.rfc931); + if (user && !*user) - safe_free(user); + safe_free(user); + logfilePrintf(logfile, "%9d.%03d %6d %s %s/%03d %ld %s %s %s %s%s/%s %s", - (int) current_time.tv_sec, - (int) current_time.tv_usec / 1000, - al->cache.msec, - client, - log_tags[al->cache.code], - al->http.code, - (long int) al->cache.size, - al->_private.method_str, - al->url, - user ? user : dash_str, - al->hier.ping.timedout ? "TIMEOUT_" : "", - hier_strings[al->hier.code], - al->hier.host, - al->http.content_type); + (int) current_time.tv_sec, + (int) current_time.tv_usec / 1000, + al->cache.msec, + client, + log_tags[al->cache.code], + al->http.code, + (long int) al->cache.size, + al->_private.method_str, + al->url, + user ? user : dash_str, + al->hier.ping.timedout ? "TIMEOUT_" : "", + hier_strings[al->hier.code], + al->hier.host, + al->http.content_type); + safe_free(user); } @@ -272,25 +299,32 @@ accessLogCommon(AccessLogEntry * al) { const char *client = NULL; char *user1 = NULL, *user2 = NULL; + if (Config.onoff.log_fqdn) - client = fqdncache_gethostbyaddr(al->cache.caddr, 0); + client = fqdncache_gethostbyaddr(al->cache.caddr, 0); + if (client == NULL) - client = inet_ntoa(al->cache.caddr); + client = inet_ntoa(al->cache.caddr); + user1 = accessLogFormatName(al->cache.authuser); + user2 = accessLogFormatName(al->cache.rfc931); + logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %ld %s:%s", - client, - user2 ? user2 : dash_str, - user1 ? user1 : dash_str, - mkhttpdlogtime(&squid_curtime), - al->_private.method_str, - al->url, - al->http.version.major, al->http.version.minor, - al->http.code, - (long int) al->cache.size, - log_tags[al->cache.code], - hier_strings[al->hier.code]); + client, + user2 ? user2 : dash_str, + user1 ? user1 : dash_str, + mkhttpdlogtime(&squid_curtime), + al->_private.method_str, + al->url, + al->http.version.major, al->http.version.minor, + al->http.code, + (long int) al->cache.size, + log_tags[al->cache.code], + hier_strings[al->hier.code]); + safe_free(user1); + safe_free(user2); } @@ -298,52 +332,63 @@ void accessLogLog(AccessLogEntry * al) { if (LogfileStatus != LOG_ENABLE) - return; + return; + if (al->url == NULL) - al->url = dash_str; + al->url = dash_str; + if (!al->http.content_type || *al->http.content_type == '\0') - al->http.content_type = dash_str; + al->http.content_type = dash_str; + if (al->icp.opcode) - al->_private.method_str = icp_opcode_str[al->icp.opcode]; + al->_private.method_str = icp_opcode_str[al->icp.opcode]; else - al->_private.method_str = RequestMethodStr[al->http.method]; + al->_private.method_str = RequestMethodStr[al->http.method]; + if (al->hier.host[0] == '\0') - xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN); + xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN); if (Config.onoff.common_log) - accessLogCommon(al); + accessLogCommon(al); else - accessLogSquid(al); + accessLogSquid(al); + if (Config.onoff.log_mime_hdrs) { - char *ereq = log_quote(al->headers.request); - char *erep = log_quote(al->headers.reply); - logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep); - safe_free(ereq); - safe_free(erep); + char *ereq = log_quote(al->headers.request); + char *erep = log_quote(al->headers.reply); + logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep); + safe_free(ereq); + safe_free(erep); } else { - logfilePrintf(logfile, "\n"); + logfilePrintf(logfile, "\n"); } + logfileFlush(logfile); #if MULTICAST_MISS_STREAM + if (al->cache.code != LOG_TCP_MISS) - (void) 0; + (void) 0; else if (al->http.method != METHOD_GET) - (void) 0; + (void) 0; else if (mcast_miss_fd < 0) - (void) 0; + (void) 0; else { - unsigned int ibuf[365]; - size_t isize; - xstrncpy((char *) ibuf, al->url, 364 * sizeof(int)); - isize = ((strlen(al->url) + 8) / 8) * 2; - if (isize > 364) - isize = 364; - mcast_encode((unsigned int *) ibuf, isize, - (const unsigned int *) Config.mcast_miss.encode_key); - comm_udp_sendto(mcast_miss_fd, - &mcast_miss_to, sizeof(mcast_miss_to), - ibuf, isize * sizeof(int)); + unsigned int ibuf[365]; + size_t isize; + xstrncpy((char *) ibuf, al->url, 364 * sizeof(int)); + isize = ((strlen(al->url) + 8) / 8) * 2; + + if (isize > 364) + isize = 364; + + mcast_encode((unsigned int *) ibuf, isize, + (const unsigned int *) Config.mcast_miss.encode_key); + + comm_udp_sendto(mcast_miss_fd, + &mcast_miss_to, sizeof(mcast_miss_to), + ibuf, isize * sizeof(int)); } + #endif } @@ -353,11 +398,16 @@ accessLogRotate(void) #if FORW_VIA_DB fvdbClear(); #endif + if (NULL == logfile) - return; + return; + logfileRotate(logfile); + #if HEADERS_LOG + logfileRotate(headerslog); + #endif } @@ -365,19 +415,25 @@ void accessLogClose(void) { if (NULL == logfile) - return; + return; + logfileClose(logfile); + logfile = NULL; + #if HEADERS_LOG + logfileClose(headerslog); + headerslog = NULL; + #endif } void hierarchyNote(HierarchyLogEntry * hl, - hier_code code, - const char *cache_peer) + hier_code code, + const char *cache_peer) { assert(hl != NULL); hl->code = code; @@ -388,51 +444,69 @@ void accessLogInit(void) { assert(sizeof(log_tags) == (LOG_TYPE_MAX + 1) * sizeof(char *)); + if (strcasecmp(Config.Log.access, "none") == 0) - return; + return; + logfile = logfileOpen(Config.Log.access, MAX_URL << 1, 1); + LogfileStatus = LOG_ENABLE; + #if HEADERS_LOG + headerslog = logfileOpen("/usr/local/squid/logs/headers.log", 512); + assert(NULL != headerslog); + #endif #if FORW_VIA_DB + fvdbInit(); + #endif #if MULTICAST_MISS_STREAM + if (Config.mcast_miss.addr.s_addr != no_addr.s_addr) { - memset(&mcast_miss_to, '\0', sizeof(mcast_miss_to)); - mcast_miss_to.sin_family = AF_INET; - mcast_miss_to.sin_port = htons(Config.mcast_miss.port); - mcast_miss_to.sin_addr.s_addr = Config.mcast_miss.addr.s_addr; - mcast_miss_fd = comm_open(SOCK_DGRAM, - 0, - Config.Addrs.udp_incoming, - Config.mcast_miss.port, - COMM_NONBLOCKING, - "Multicast Miss Stream"); - if (mcast_miss_fd < 0) - fatal("Cannot open Multicast Miss Stream Socket"); - debug(46, 1) ("Multicast Miss Stream Socket opened on FD %d\n", - mcast_miss_fd); - mcastSetTtl(mcast_miss_fd, Config.mcast_miss.ttl); - if (strlen(Config.mcast_miss.encode_key) < 16) - fatal("mcast_encode_key is too short, must be 16 characters"); + memset(&mcast_miss_to, '\0', sizeof(mcast_miss_to)); + mcast_miss_to.sin_family = AF_INET; + mcast_miss_to.sin_port = htons(Config.mcast_miss.port); + mcast_miss_to.sin_addr.s_addr = Config.mcast_miss.addr.s_addr; + mcast_miss_fd = comm_open(SOCK_DGRAM, + 0, + Config.Addrs.udp_incoming, + Config.mcast_miss.port, + COMM_NONBLOCKING, + "Multicast Miss Stream"); + + if (mcast_miss_fd < 0) + fatal("Cannot open Multicast Miss Stream Socket"); + + debug(46, 1) ("Multicast Miss Stream Socket opened on FD %d\n", + mcast_miss_fd); + + mcastSetTtl(mcast_miss_fd, Config.mcast_miss.ttl); + + if (strlen(Config.mcast_miss.encode_key) < 16) + fatal("mcast_encode_key is too short, must be 16 characters"); } + #endif } const char * accessLogTime(time_t t) { + struct tm *tm; static char buf[128]; static time_t last_t = 0; + if (t != last_t) { - tm = localtime(&t); - strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); - last_t = t; + tm = localtime(&t); + strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); + last_t = t; } + return buf; } @@ -446,21 +520,25 @@ fvdbInit(void) forw_table = hash_create((HASHCMP *) strcmp, 977, hash4); cachemgrRegister("via_headers", "Via Request Headers", fvdbDumpVia, 0, 1); cachemgrRegister("forw_headers", "X-Forwarded-For Request Headers", - fvdbDumpForw, 0, 1); + fvdbDumpForw, 0, 1); } static void fvdbCount(hash_table * hash, const char *key) { fvdb_entry *fv; + if (NULL == hash) - return; + return; + fv = hash_lookup(hash, key); + if (NULL == fv) { - fv = static_cast (xcalloc(1, sizeof(fvdb_entry))); - fv->hash.key = xstrdup(key); - hash_join(hash, &fv->hash); + fv = static_cast (xcalloc(1, sizeof(fvdb_entry))); + fv->hash.key = xstrdup(key); + hash_join(hash, &fv->hash); } + fv->n++; } @@ -481,12 +559,15 @@ fvdbDumpTable(StoreEntry * e, hash_table * hash) { hash_link *h; fvdb_entry *fv; + if (hash == NULL) - return; + return; + hash_first(hash); + while ((h = hash_next(hash))) { - fv = (fvdb_entry *) h; - storeAppendPrintf(e, "%9d %s\n", fv->n, hashKeyStr(&fv->hash)); + fv = (fvdb_entry *) h; + storeAppendPrintf(e, "%9d %s\n", fv->n, hashKeyStr(&fv->hash)); } } @@ -546,17 +627,20 @@ mcast_encode(unsigned int *ibuf, size_t isize, const unsigned int *key) const unsigned int k2 = htonl(key[2]); const unsigned int k3 = htonl(key[3]); int i; + for (i = 0; i < isize; i += 2) { - y = htonl(ibuf[i]); - z = htonl(ibuf[i + 1]); - sum = 0; - for (n = 32; n; n--) { - sum += delta; - y += (z << 4) + (k0 ^ z) + (sum ^ (z >> 5)) + k1; - z += (y << 4) + (k2 ^ y) + (sum ^ (y >> 5)) + k3; - } - ibuf[i] = htonl(y); - ibuf[i + 1] = htonl(z); + y = htonl(ibuf[i]); + z = htonl(ibuf[i + 1]); + sum = 0; + + for (n = 32; n; n--) { + sum += delta; + y += (z << 4) + (k0 ^ z) + (sum ^ (z >> 5)) + k1; + z += (y << 4) + (k2 ^ y) + (sum ^ (y >> 5)) + k3; + } + + ibuf[i] = htonl(y); + ibuf[i + 1] = htonl(z); } } @@ -573,41 +657,53 @@ headersLog(int cs, int pq, method_t m, void *data) unsigned short S; char *hmask; int ccmask = 0; + if (0 == pq) { - /* reply */ - rep = data; - req = NULL; - magic = 0x0050; - hmask = rep->header.mask; - if (rep->cache_control) - ccmask = rep->cache_control->mask; + /* reply */ + rep = data; + req = NULL; + magic = 0x0050; + hmask = rep->header.mask; + + if (rep->cache_control) + ccmask = rep->cache_control->mask; } else { - /* request */ - req = data; - rep = NULL; - magic = 0x0051; - hmask = req->header.mask; - if (req->cache_control) - ccmask = req->cache_control->mask; + /* request */ + req = data; + rep = NULL; + magic = 0x0051; + hmask = req->header.mask; + + if (req->cache_control) + ccmask = req->cache_control->mask; } + if (0 == cs) { - /* client */ - magic |= 0x4300; + /* client */ + magic |= 0x4300; } else { - /* server */ - magic |= 0x5300; + /* server */ + magic |= 0x5300; } + magic = htons(magic); ccmask = htonl(ccmask); + if (0 == pq) - S = (unsigned short) rep->sline.status; + S = (unsigned short) rep->sline.status; else - S = (unsigned short) HTTP_STATUS_NONE; + S = (unsigned short) HTTP_STATUS_NONE; + logfileWrite(headerslog, &magic, sizeof(magic)); + logfileWrite(headerslog, &M, sizeof(M)); + logfileWrite(headerslog, &S, sizeof(S)); + logfileWrite(headerslog, hmask, sizeof(HttpHeaderMask)); + logfileWrite(headerslog, &ccmask, sizeof(int)); + logfileFlush(headerslog); } @@ -625,20 +721,28 @@ int logTypeIsATcpHit(log_type code) { /* this should be a bitmap for better optimization */ + if (code == LOG_TCP_HIT) - return 1; + return 1; + if (code == LOG_TCP_IMS_HIT) - return 1; + return 1; + if (code == LOG_TCP_REFRESH_FAIL_HIT) - return 1; + return 1; + if (code == LOG_TCP_REFRESH_HIT) - return 1; + return 1; + if (code == LOG_TCP_NEGATIVE_HIT) - return 1; + return 1; + if (code == LOG_TCP_MEM_HIT) - return 1; + return 1; + if (code == LOG_TCP_OFFLINE_HIT) - return 1; + return 1; + return 0; } diff --git a/src/acl.cc b/src/acl.cc index b93529d8dc..4425065176 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -1,5 +1,5 @@ /* - * $Id: acl.cc,v 1.304 2003/02/17 07:01:35 robertc Exp $ + * $Id: acl.cc,v 1.305 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -57,6 +57,7 @@ static int aclMatchWordList(wordlist *, const char *); static void aclParseUserMaxIP(void *data); static void aclDestroyUserMaxIP(void *data); static wordlist *aclDumpUserMaxIP(void *data); + static int aclMatchUserMaxIP(void *, auth_user_request_t *, struct in_addr); static squid_acl aclStrToType(const char *s); static wordlist *aclDumpIntlistList(intlist * data); @@ -68,6 +69,7 @@ static wordlist *aclDumpMethodList(intlist * data); #if USE_ARP_ACL static void aclParseArpList(void *curlist); static int decode_eth(const char *asc, char *eth); + static int aclMatchArp(void *dataptr, struct in_addr c); static wordlist *aclDumpArpList(void *); static splayNode::SPLAYCMP aclArpCompare; @@ -80,8 +82,10 @@ ACL::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACL)); + if (!Pool) - Pool = memPoolCreate("ACL", sizeof (ACL)); + Pool = memPoolCreate("ACL", sizeof (ACL)); + return memPoolAlloc(Pool); } @@ -116,37 +120,54 @@ static squid_acl aclStrToType(const char *s) { if (!strcmp(s, "port")) - return ACL_URL_PORT; + return ACL_URL_PORT; + if (!strcmp(s, "myport")) - return ACL_MY_PORT; + return ACL_MY_PORT; + if (!strcmp(s, "maxconn")) - return ACL_MAXCONN; + return ACL_MAXCONN; + if (!strncmp(s, "proto", 5)) - return ACL_PROTO; + return ACL_PROTO; + if (!strcmp(s, "method")) - return ACL_METHOD; + return ACL_METHOD; + if (!strcmp(s, "src_as")) - return ACL_SRC_ASN; + return ACL_SRC_ASN; + if (!strcmp(s, "dst_as")) - return ACL_DST_ASN; + return ACL_DST_ASN; + #if SQUID_SNMP + if (!strcmp(s, "snmp_community")) - return ACL_SNMP_COMMUNITY; + return ACL_SNMP_COMMUNITY; + #endif #if SRC_RTT_NOT_YET_FINISHED + if (!strcmp(s, "src_rtt")) - return ACL_NETDB_SRC_RTT; + return ACL_NETDB_SRC_RTT; + #endif #if USE_ARP_ACL + if (!strcmp(s, "arp")) - return ACL_SRC_ARP; + return ACL_SRC_ARP; + #endif + if (!strcmp(s, "rep_mime_type")) - return ACL_REP_MIME_TYPE; + return ACL_REP_MIME_TYPE; + if (!strcmp(s, "max_user_ip")) - return ACL_MAX_USER_IP; + return ACL_MAX_USER_IP; + if (!strcmp(s, "external")) - return ACL_EXTERNAL; + return ACL_EXTERNAL; + return ACL_NONE; } @@ -155,37 +176,54 @@ const char * aclTypeToStr(squid_acl type) { if (type == ACL_URL_PORT) - return "port"; + return "port"; + if (type == ACL_MY_PORT) - return "myport"; + return "myport"; + if (type == ACL_MAXCONN) - return "maxconn"; + return "maxconn"; + if (type == ACL_PROTO) - return "proto"; + return "proto"; + if (type == ACL_METHOD) - return "method"; + return "method"; + if (type == ACL_SRC_ASN) - return "src_as"; + return "src_as"; + if (type == ACL_DST_ASN) - return "dst_as"; + return "dst_as"; + #if SQUID_SNMP + if (type == ACL_SNMP_COMMUNITY) - return "snmp_community"; + return "snmp_community"; + #endif #if SRC_RTT_NOT_YET_FINISHED + if (type == ACL_NETDB_SRC_RTT) - return "src_rtt"; + return "src_rtt"; + #endif #if USE_ARP_ACL + if (type == ACL_SRC_ARP) - return "arp"; + return "arp"; + #endif + if (type == ACL_REP_MIME_TYPE) - return "rep_mime_type"; + return "rep_mime_type"; + if (type == ACL_MAX_USER_IP) - return "max_user_ip"; + return "max_user_ip"; + if (type == ACL_EXTERNAL) - return "external"; + return "external"; + return "ERROR"; } @@ -193,9 +231,11 @@ acl * ACL::FindByName(const char *name) { acl *a; + for (a = Config.aclList; a; a = a->next) - if (!strcasecmp(a->name, name)) - return a; + if (!strcasecmp(a->name, name)) + return a; + return NULL; } @@ -205,12 +245,15 @@ aclParseIntlist(void *curlist) intlist **Tail; intlist *q = NULL; char *t = NULL; - for (Tail = (intlist **)curlist; *Tail; Tail = &((*Tail)->next)); + + for (Tail = (intlist **)curlist; *Tail; Tail = &((*Tail)->next)) + + ; while ((t = strtokFile())) { - q = (intlist *)memAllocate(MEM_INTLIST); - q->i = atoi(t); - *(Tail) = q; - Tail = &q->next; + q = (intlist *)memAllocate(MEM_INTLIST); + q->i = atoi(t); + *(Tail) = q; + Tail = &q->next; } } @@ -220,17 +263,23 @@ aclParseIntRange(void *curlist) intrange **Tail; intrange *q = NULL; char *t = NULL; - for (Tail = (intrange **)curlist; *Tail; Tail = &((*Tail)->next)); + + for (Tail = (intrange **)curlist; *Tail; Tail = &((*Tail)->next)) + + ; while ((t = strtokFile())) { - q = (intrange *)xcalloc(1, sizeof(intrange)); - q->i = atoi(t); - t = strchr(t, '-'); - if (t && *(++t)) - q->j = atoi(t); - else - q->j = q->i; - *(Tail) = q; - Tail = &q->next; + q = (intrange *)xcalloc(1, sizeof(intrange)); + q->i = atoi(t); + t = strchr(t, '-'); + + if (t && *(++t)) + q->j = atoi(t); + else + q->j = q->i; + + *(Tail) = q; + + Tail = &q->next; } } @@ -241,13 +290,16 @@ aclParseProtoList(void *curlist) intlist *q = NULL; char *t = NULL; protocol_t protocol; - for (Tail = (intlist **)curlist; *Tail; Tail = &((*Tail)->next)); + + for (Tail = (intlist **)curlist; *Tail; Tail = &((*Tail)->next)) + + ; while ((t = strtokFile())) { - protocol = urlParseProtocol(t); - q = (intlist *)memAllocate(MEM_INTLIST); - q->i = (int) protocol; - *(Tail) = q; - Tail = &q->next; + protocol = urlParseProtocol(t); + q = (intlist *)memAllocate(MEM_INTLIST); + q->i = (int) protocol; + *(Tail) = q; + Tail = &q->next; } } @@ -257,12 +309,15 @@ aclParseMethodList(void *curlist) intlist **Tail; intlist *q = NULL; char *t = NULL; - for (Tail = (intlist **)curlist; *Tail; Tail = &((*Tail)->next)); + + for (Tail = (intlist **)curlist; *Tail; Tail = &((*Tail)->next)) + + ; while ((t = strtokFile())) { - q = (intlist *)memAllocate(MEM_INTLIST); - q->i = (int) urlParseMethod(t); - *(Tail) = q; - Tail = &q->next; + q = (intlist *)memAllocate(MEM_INTLIST); + q->i = (int) urlParseMethod(t); + *(Tail) = q; + Tail = &q->next; } } @@ -275,30 +330,36 @@ aclParseRegexList(void *curlist) regex_t comp; int errcode; int flags = REG_EXTENDED | REG_NOSUB; - for (Tail = (relist **)curlist; *Tail; Tail = &((*Tail)->next)); + + for (Tail = (relist **)curlist; *Tail; Tail = &((*Tail)->next)) + + ; while ((t = strtokFile())) { - if (strcmp(t, "-i") == 0) { - flags |= REG_ICASE; - continue; - } - if (strcmp(t, "+i") == 0) { - flags &= ~REG_ICASE; - continue; - } - if ((errcode = regcomp(&comp, t, flags)) != 0) { - char errbuf[256]; - regerror(errcode, &comp, errbuf, sizeof errbuf); - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseRegexList: Invalid regular expression '%s': %s\n", - t, errbuf); - continue; - } - q = (relist *)memAllocate(MEM_RELIST); - q->pattern = xstrdup(t); - q->regex = comp; - *(Tail) = q; - Tail = &q->next; + if (strcmp(t, "-i") == 0) { + flags |= REG_ICASE; + continue; + } + + if (strcmp(t, "+i") == 0) { + flags &= ~REG_ICASE; + continue; + } + + if ((errcode = regcomp(&comp, t, flags)) != 0) { + char errbuf[256]; + regerror(errcode, &comp, errbuf, sizeof errbuf); + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseRegexList: Invalid regular expression '%s': %s\n", + t, errbuf); + continue; + } + + q = (relist *)memAllocate(MEM_RELIST); + q->pattern = xstrdup(t); + q->regex = comp; + *(Tail) = q; + Tail = &q->next; } } @@ -307,55 +368,75 @@ static void aclParseWordList(void *curlist) { char *t = NULL; + while ((t = strtokFile())) - wordlistAdd((wordlist **)curlist, t); + wordlistAdd((wordlist **)curlist, t); } + #endif ACL * ACL::Factory (char const *type) { ACL *result = Prototype::Factory (type); + if (result) - return result; + return result; + squid_acl const acltype = aclStrToType(type); + switch (acltype) { - case ACL_URL_PORT: - case ACL_MY_PORT: - case ACL_MAXCONN: - case ACL_PROTO: - case ACL_METHOD: - case ACL_SRC_ASN: - case ACL_DST_ASN: + + case ACL_URL_PORT: + + case ACL_MY_PORT: + + case ACL_MAXCONN: + + case ACL_PROTO: + + case ACL_METHOD: + + case ACL_SRC_ASN: + + case ACL_DST_ASN: #if SQUID_SNMP - case ACL_SNMP_COMMUNITY: + + case ACL_SNMP_COMMUNITY: #endif #if SRC_RTT_NOT_YET_FINISHED - case ACL_NETDB_SRC_RTT: + + case ACL_NETDB_SRC_RTT: #endif #if USE_ARP_ACL - case ACL_SRC_ARP: + + case ACL_SRC_ARP: #endif - case ACL_REP_MIME_TYPE: - case ACL_MAX_USER_IP: - case ACL_EXTERNAL: - result = new ACL(acltype); - break; - case ACL_DERIVED: - default: - fatal ("Unknown acl type in ACL::Factory"); + + case ACL_REP_MIME_TYPE: + + case ACL_MAX_USER_IP: + + case ACL_EXTERNAL: + result = new ACL(acltype); + break; + + case ACL_DERIVED: + + default: + fatal ("Unknown acl type in ACL::Factory"); }; + assert (result); + return result; } ACL::ACL (squid_acl const acltype) : type (acltype) -{ -} +{} ACL::ACL () : type(ACL_NONE) -{ -} +{} char const * ACL::typeString() const @@ -374,41 +455,49 @@ ACL::ParseAclLine(acl ** head) int new_acl = 0; /* snarf the ACL name */ + if ((t = strtok(NULL, w_space)) == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAclLine: missing ACL name.\n"); - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAclLine: missing ACL name.\n"); + return; } + xstrncpy(aclname, t, ACL_NAME_SZ); /* snarf the ACL type */ + if ((t = strtok(NULL, w_space)) == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAclLine: missing ACL type.\n"); - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAclLine: missing ACL type.\n"); + return; } + if ((acltype = aclStrToType(t)) == ACL_NONE && !Prototype::Registered (t)) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAclLine: Invalid ACL type '%s'\n", t); - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAclLine: Invalid ACL type '%s'\n", t); + return; } + if ((A = FindByName(aclname)) == NULL) { - debug(28, 3) ("aclParseAclLine: Creating ACL '%s'\n", aclname); - A = ACL::Factory(t); - xstrncpy(A->name, aclname, ACL_NAME_SZ); - A->cfgline = xstrdup(config_input_line); - new_acl = 1; + debug(28, 3) ("aclParseAclLine: Creating ACL '%s'\n", aclname); + A = ACL::Factory(t); + xstrncpy(A->name, aclname, ACL_NAME_SZ); + A->cfgline = xstrdup(config_input_line); + new_acl = 1; } else { - /* FIXME: strcmp the registry typeString */ - if (acltype != ACL_NONE && acltype != A->aclType()) { - debug(28, 0) ("aclParseAclLine: ACL '%s' already exists with different type, skipping.\n", A->name); - return; - } - debug(28, 3) ("aclParseAclLine: Appending to '%s'\n", aclname); - new_acl = 0; + /* FIXME: strcmp the registry typeString */ + + if (acltype != ACL_NONE && acltype != A->aclType()) { + debug(28, 0) ("aclParseAclLine: ACL '%s' already exists with different type, skipping.\n", A->name); + return; + } + + debug(28, 3) ("aclParseAclLine: Appending to '%s'\n", aclname); + new_acl = 0; } + /* * Here we set AclMatchedName in case we need to use it in a * warning message in aclDomainCompare(). @@ -417,23 +506,28 @@ ACL::ParseAclLine(acl ** head) /*split the function here */ A->parse(); + /* * Clear AclMatchedName from our temporary hack */ AclMatchedName = NULL; /* ugly */ + if (!new_acl) - return; + return; + if (!A->valid()) { - debug(28, 0) ("aclParseAclLine: IGNORING invalid ACL: %s\n", - A->cfgline); - A->deleteSelf(); - /* Do we need this? */ - A = NULL; - return; + debug(28, 0) ("aclParseAclLine: IGNORING invalid ACL: %s\n", + A->cfgline); + A->deleteSelf(); + /* Do we need this? */ + A = NULL; + return; } + /* append */ while (*head) - head = &(*head)->next; + head = &(*head)->next; + *head = A; } @@ -445,54 +539,70 @@ ACL::valid () const void ACL::parse() -{ +{ switch (aclType()) { + case ACL_REP_MIME_TYPE: - aclParseRegexList(&data); - break; + aclParseRegexList(&data); + break; + case ACL_SRC_ASN: + case ACL_MAXCONN: + case ACL_DST_ASN: - aclParseIntlist(&data); - break; + aclParseIntlist(&data); + break; + case ACL_MAX_USER_IP: - aclParseUserMaxIP(&data); - break; + aclParseUserMaxIP(&data); + break; #if SRC_RTT_NOT_YET_FINISHED + case ACL_NETDB_SRC_RTT: - aclParseIntlist(&data); - break; + aclParseIntlist(&data); + break; #endif + case ACL_URL_PORT: + case ACL_MY_PORT: - aclParseIntRange(&data); - break; + aclParseIntRange(&data); + break; + case ACL_PROTO: - aclParseProtoList(&data); - break; + aclParseProtoList(&data); + break; + case ACL_METHOD: - aclParseMethodList(&data); - break; + aclParseMethodList(&data); + break; + case ACL_DERIVED: - fatal ("overriden"); - break; + fatal ("overriden"); + break; #if SQUID_SNMP + case ACL_SNMP_COMMUNITY: - aclParseWordList(&data); - break; + aclParseWordList(&data); + break; #endif #if USE_ARP_ACL + case ACL_SRC_ARP: - aclParseArpList(&data); - break; + aclParseArpList(&data); + break; #endif + case ACL_EXTERNAL: - aclParseExternal(&data); - break; + aclParseExternal(&data); + break; + case ACL_NONE: + case ACL_ENUM_MAX: - fatal("Bad ACL type"); - break; + fatal("Bad ACL type"); + break; } } @@ -504,19 +614,26 @@ aclGetDenyInfoPage(acl_deny_info_list ** head, const char *name) acl_name_list *L = NULL; A = *head; + if (NULL == *head) /* empty list */ - return ERR_NONE; + return ERR_NONE; + while (A) { - L = A->acl_list; - if (NULL == L) /* empty list should never happen, but in case */ - continue; - while (L) { - if (!strcmp(name, L->name)) - return A->err_page_id; - L = L->next; - } - A = A->next; + L = A->acl_list; + + if (NULL == L) /* empty list should never happen, but in case */ + continue; + + while (L) { + if (!strcmp(name, L->name)) + return A->err_page_id; + + L = L->next; + } + + A = A->next; } + return ERR_NONE; } @@ -525,10 +642,13 @@ int aclIsProxyAuth(const char *name) { if (NULL == name) - return false; + return false; + acl *a; + if ((a = ACL::FindByName(name))) - return a->isProxyAuth(); + return a->isProxyAuth(); + return false; } @@ -558,32 +678,39 @@ aclParseDenyInfoLine(acl_deny_info_list ** head) acl_name_list **Tail = NULL; /* first expect a page name */ + if ((t = strtok(NULL, w_space)) == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseDenyInfoLine: missing 'error page' parameter.\n"); - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseDenyInfoLine: missing 'error page' parameter.\n"); + return; } + A = (acl_deny_info_list *)memAllocate(MEM_ACL_DENY_INFO_LIST); A->err_page_id = errorReservePageId(t); A->err_page_name = xstrdup(t); A->next = (acl_deny_info_list *) NULL; /* next expect a list of ACL names */ Tail = &A->acl_list; + while ((t = strtok(NULL, w_space))) { - L = (acl_name_list *)memAllocate(MEM_ACL_NAME_LIST); - xstrncpy(L->name, t, ACL_NAME_SZ); - *Tail = L; - Tail = &L->next; + L = (acl_name_list *)memAllocate(MEM_ACL_NAME_LIST); + xstrncpy(L->name, t, ACL_NAME_SZ); + *Tail = L; + Tail = &L->next; } + if (A->acl_list == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseDenyInfoLine: deny_info line contains no ACL's, skipping\n"); - memFree(A, MEM_ACL_DENY_INFO_LIST); - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseDenyInfoLine: deny_info line contains no ACL's, skipping\n"); + memFree(A, MEM_ACL_DENY_INFO_LIST); + return; } - for (B = *head, T = head; B; T = &B->next, B = B->next); /* find the tail */ + + for (B = *head, T = head; B; T = &B->next, B = B->next) + + ; /* find the tail */ *T = A; } @@ -596,51 +723,59 @@ aclParseAccessLine(acl_access ** head) acl_access **T = NULL; /* first expect either 'allow' or 'deny' */ + if ((t = strtok(NULL, w_space)) == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAccessLine: missing 'allow' or 'deny'.\n"); - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAccessLine: missing 'allow' or 'deny'.\n"); + return; } + A = new acl_access; if (!strcmp(t, "allow")) - A->allow = ACCESS_ALLOWED; + A->allow = ACCESS_ALLOWED; else if (!strcmp(t, "deny")) - A->allow = ACCESS_DENIED; + A->allow = ACCESS_DENIED; else { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAccessLine: expecting 'allow' or 'deny', got '%s'.\n", t); - delete A; - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAccessLine: expecting 'allow' or 'deny', got '%s'.\n", t); + delete A; + return; } + aclParseAclList(&A->aclList); + if (A->aclList == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAccessLine: Access line contains no ACL's, skipping\n"); - delete A; - return; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAccessLine: Access line contains no ACL's, skipping\n"); + delete A; + return; } + A->cfgline = xstrdup(config_input_line); /* Append to the end of this list */ - for (B = *head, T = head; B; T = &B->next, B = B->next); + + for (B = *head, T = head; B; T = &B->next, B = B->next) + + ; *T = A; + /* We lock _acl_access structures in ACLChecklist::check() */ } ACLList::ACLList() : op (1), _acl (NULL), next (NULL) -{ -} +{} void ACLList::negated(bool isNegated) { if (isNegated) - op = 0; + op = 0; else - op = 1; + op = 1; } void @@ -652,24 +787,29 @@ aclParseAclList(acl_list ** head) /* next expect a list of ACL names, possibly preceeded * by '!' for negation */ + while ((t = strtok(NULL, w_space))) { - acl_list *L (new ACLList); - if (*t == '!') { - L->negated (true); - t++; - } - debug(28, 3) ("aclParseAccessLine: looking for ACL name '%s'\n", t); - a = ACL::FindByName(t); - if (a == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAccessLine: ACL name '%s' not found.\n", t); - L->deleteSelf(); - continue; - } - L->_acl = a; - *Tail = L; - Tail = &L->next; + acl_list *L (new ACLList); + + if (*t == '!') { + L->negated (true); + t++; + } + + debug(28, 3) ("aclParseAccessLine: looking for ACL name '%s'\n", t); + a = ACL::FindByName(t); + + if (a == NULL) { + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAccessLine: ACL name '%s' not found.\n", t); + L->deleteSelf(); + continue; + } + + L->_acl = a; + *Tail = L; + Tail = &L->next; } } @@ -677,26 +817,35 @@ int aclMatchRegex(relist * data, const char *word) { relist *first, *prev; + if (word == NULL) - return 0; + return 0; + debug(28, 3) ("aclMatchRegex: checking '%s'\n", word); + first = data; + prev = NULL; + while (data) { - debug(28, 3) ("aclMatchRegex: looking for '%s'\n", data->pattern); - if (regexec(&data->regex, word, 0, 0, 0) == 0) { - if (prev != NULL) { - /* shift the element just found to the second position - * in the list */ - prev->next = data->next; - data->next = first->next; - first->next = data; - } - return 1; - } - prev = data; - data = data->next; + debug(28, 3) ("aclMatchRegex: looking for '%s'\n", data->pattern); + + if (regexec(&data->regex, word, 0, 0, 0) == 0) { + if (prev != NULL) { + /* shift the element just found to the second position + * in the list */ + prev->next = data->next; + data->next = first->next; + first->next = data; + } + + return 1; + } + + prev = data; + data = data->next; } + return 0; } @@ -725,14 +874,18 @@ ACL::cacheMatchAcl(dlink_list * cache, ACLChecklist *checklist) acl_proxy_auth_match_cache *auth_match; dlink_node *link; link = cache->head; + while (link) { - auth_match = (acl_proxy_auth_match_cache *)link->data; - if (auth_match->acl_data == this) { - debug(28, 4) ("ACL::cacheMatchAcl: cache hit on acl '%p'\n", this); - return auth_match->matchrv; - } - link = link->next; + auth_match = (acl_proxy_auth_match_cache *)link->data; + + if (auth_match->acl_data == this) { + debug(28, 4) ("ACL::cacheMatchAcl: cache hit on acl '%p'\n", this); + return auth_match->matchrv; + } + + link = link->next; } + auth_match = NULL; auth_match = (acl_proxy_auth_match_cache *)memAllocate(MEM_ACL_PROXY_AUTH_MATCH); auth_match->matchrv = matchForCache (checklist); @@ -747,12 +900,13 @@ aclCacheMatchFlush(dlink_list * cache) acl_proxy_auth_match_cache *auth_match; dlink_node *link, *tmplink; link = cache->head; + while (link) { - auth_match = (acl_proxy_auth_match_cache *)link->data; - tmplink = link; - link = link->next; - dlinkDelete(tmplink, cache); - memFree(auth_match, MEM_ACL_PROXY_AUTH_MATCH); + auth_match = (acl_proxy_auth_match_cache *)link->data; + tmplink = link; + link = link->next; + dlinkDelete(tmplink, cache); + memFree(auth_match, MEM_ACL_PROXY_AUTH_MATCH); } } @@ -765,26 +919,34 @@ aclParseUserMaxIP(void *data) acl_user_ip_data **acldata = (acl_user_ip_data **)data; char *t = NULL; CBDATA_INIT_TYPE(acl_user_ip_data); + if (*acldata) { - debug(28, 1) ("Attempting to alter already set User max IP acl\n"); - return; + debug(28, 1) ("Attempting to alter already set User max IP acl\n"); + return; } + *acldata = cbdataAlloc(acl_user_ip_data); t = strtokFile(); + if (!t) - goto error; + goto error; + debug(28, 5) ("aclParseUserMaxIP: First token is %s\n", t); + if (strcmp("-s", t) == 0) { - debug(28, 5) ("aclParseUserMaxIP: Going strict\n"); - (*acldata)->flags.strict = 1; - t = strtokFile(); - if (!t) - goto error; + debug(28, 5) ("aclParseUserMaxIP: Going strict\n"); + (*acldata)->flags.strict = 1; + t = strtokFile(); + + if (!t) + goto error; } + (*acldata)->max = atoi(t); debug(28, 5) ("aclParseUserMaxIP: Max IP address's %d\n", (int) (*acldata)->max); return; - error: + +error: fatal("aclParseUserMaxIP: Malformed ACL %d\n"); } @@ -792,8 +954,10 @@ void aclDestroyUserMaxIP(void *data) { acl_user_ip_data **acldata = (acl_user_ip_data **)data; + if (*acldata) - cbdataFree(*acldata); + cbdataFree(*acldata); + *acldata = NULL; } @@ -803,21 +967,26 @@ aclDumpUserMaxIP(void *data) acl_user_ip_data *acldata = (acl_user_ip_data *)data; wordlist *W = NULL; char buf[128]; + if (acldata->flags.strict) - wordlistAdd(&W, "-s"); + wordlistAdd(&W, "-s"); + snprintf(buf, sizeof(buf), "%lu", (unsigned long int) acldata->max); + wordlistAdd(&W, buf); + return W; } -/* +/* * aclMatchUserMaxIP - check for users logging in from multiple IP's * 0 : No match * 1 : Match */ int aclMatchUserMaxIP(void *data, auth_user_request_t * auth_user_request, - struct in_addr src_addr) + + struct in_addr src_addr) { /* * the logic for flush the ip list when the limit is hit vs keep @@ -827,24 +996,26 @@ aclMatchUserMaxIP(void *data, auth_user_request_t * auth_user_request, acl_user_ip_data *acldata = (acl_user_ip_data *)data; if (authenticateAuthUserRequestIPCount(auth_user_request) <= acldata->max) - return 0; + return 0; /* this is a match */ - if (acldata->flags.strict) { - /* - * simply deny access - the user name is already associated with - * the request - */ - /* remove _this_ ip, as it is the culprit for going over the limit */ - authenticateAuthUserRequestRemoveIp(auth_user_request, src_addr); - debug(28, 4) ("aclMatchUserMaxIP: Denying access in strict mode\n"); - } else { - /* - * non-strict - remove some/all of the cached entries - * ie to allow the user to move machines easily - */ - authenticateAuthUserRequestClearIp(auth_user_request); - debug(28, 4) ("aclMatchUserMaxIP: Denying access in non-strict mode - flushing the user ip cache\n"); + if (acldata->flags.strict) + { + /* + * simply deny access - the user name is already associated with + * the request + */ + /* remove _this_ ip, as it is the culprit for going over the limit */ + authenticateAuthUserRequestRemoveIp(auth_user_request, src_addr); + debug(28, 4) ("aclMatchUserMaxIP: Denying access in strict mode\n"); + } else + { + /* + * non-strict - remove some/all of the cached entries + * ie to allow the user to move machines easily + */ + authenticateAuthUserRequestClearIp(auth_user_request); + debug(28, 4) ("aclMatchUserMaxIP: Denying access in non-strict mode - flushing the user ip cache\n"); } return 1; @@ -856,20 +1027,24 @@ aclMatchInteger(intlist * data, int i) intlist *first, *prev; first = data; prev = NULL; + while (data) { - if (data->i == i) { - if (prev != NULL) { - /* shift the element just found to the second position - * in the list */ - prev->next = data->next; - data->next = first->next; - first->next = data; - } - return 1; - } - prev = data; - data = data->next; + if (data->i == i) { + if (prev != NULL) { + /* shift the element just found to the second position + * in the list */ + prev->next = data->next; + data->next = first->next; + first->next = data; + } + + return 1; + } + + prev = data; + data = data->next; } + return 0; } @@ -879,25 +1054,30 @@ aclMatchIntegerRange(intrange * data, int i) intrange *first, *prev; first = data; prev = NULL; + while (data) { - if (i < data->i) { - (void) 0; - } else if (i > data->j) { - (void) 0; - } else { - /* matched */ - if (prev != NULL) { - /* shift the element just found to the second position - * in the list */ - prev->next = data->next; - data->next = first->next; - first->next = data; - } - return 1; - } - prev = data; - data = data->next; + if (i < data->i) { + (void) 0; + } else if (i > data->j) { + (void) 0; + } else { + /* matched */ + + if (prev != NULL) { + /* shift the element just found to the second position + * in the list */ + prev->next = data->next; + data->next = first->next; + first->next = data; + } + + return 1; + } + + prev = data; + data = data->next; } + return 0; } @@ -906,14 +1086,19 @@ static int aclMatchWordList(wordlist * w, const char *word) { debug(28, 3) ("aclMatchWordList: looking for '%s'\n", word); + while (w != NULL) { - debug(28, 3) ("aclMatchWordList: checking '%s'\n", w->key); - if (!strcmp(w->key, word)) - return 1; - w = w->next; + debug(28, 3) ("aclMatchWordList: checking '%s'\n", w->key); + + if (!strcmp(w->key, word)) + return 1; + + w = w->next; } + return 0; } + #endif @@ -921,16 +1106,23 @@ bool ACL::requiresRequest() const { switch (aclType()) { + case ACL_DST_ASN: + case ACL_MAX_USER_IP: + case ACL_METHOD: + case ACL_PROTO: + case ACL_REP_MIME_TYPE: + case ACL_URL_PORT: - /* These ACL types require checklist->request */ - return true; + /* These ACL types require checklist->request */ + return true; + default: - return false; + return false; } } @@ -938,9 +1130,9 @@ int ACL::checklistMatches(ACLChecklist *checklist) { if (NULL == checklist->request && requiresRequest()) { - debug(28, 1) ("WARNING: '%s' ACL is used but there is no" - " HTTP request -- access denied.\n", name); - return 0; + debug(28, 1) ("WARNING: '%s' ACL is used but there is no" + " HTTP request -- access denied.\n", name); + return 0; } debug(28, 3) ("aclMatchAcl: checking '%s'\n", cfgline); @@ -956,79 +1148,111 @@ ACL::match(ACLChecklist * checklist) int k, ti; switch (aclType()) { + case ACL_MAXCONN: - k = clientdbEstablished(checklist->src_addr, 0); - return ((k > ((intlist *) data)->i) ? 1 : 0); - /* NOTREACHED */ + k = clientdbEstablished(checklist->src_addr, 0); + return ((k > ((intlist *) data)->i) ? 1 : 0); + /* NOTREACHED */ + case ACL_URL_PORT: - return aclMatchIntegerRange((intrange *)data, (int) r->port); - /* NOTREACHED */ + return aclMatchIntegerRange((intrange *)data, (int) r->port); + /* NOTREACHED */ + case ACL_MY_PORT: - return aclMatchIntegerRange((intrange *)data, (int) checklist->my_port); - /* NOTREACHED */ + return aclMatchIntegerRange((intrange *)data, (int) checklist->my_port); + /* NOTREACHED */ + case ACL_PROTO: - return aclMatchInteger((intlist *)data, r->protocol); - /* NOTREACHED */ + return aclMatchInteger((intlist *)data, r->protocol); + /* NOTREACHED */ + case ACL_METHOD: - return aclMatchInteger((intlist *)data, r->method); - /* NOTREACHED */ + return aclMatchInteger((intlist *)data, r->method); + /* NOTREACHED */ + case ACL_MAX_USER_IP: - if ((ti = checklist->authenticated()) != 1) - return ti; - ti = aclMatchUserMaxIP(data, checklist->auth_user_request, - checklist->src_addr); - checklist->auth_user_request = NULL; - return ti; - /* NOTREACHED */ + + if ((ti = checklist->authenticated()) != 1) + return ti; + + ti = aclMatchUserMaxIP(data, checklist->auth_user_request, + checklist->src_addr); + + checklist->auth_user_request = NULL; + + return ti; + + /* NOTREACHED */ #if SQUID_SNMP + case ACL_SNMP_COMMUNITY: - return aclMatchWordList((wordlist *)data, checklist->snmp_community); - /* NOTREACHED */ + return aclMatchWordList((wordlist *)data, checklist->snmp_community); + + /* NOTREACHED */ #endif + case ACL_SRC_ASN: - return asnMatchIp(data, checklist->src_addr); - /* NOTREACHED */ + return asnMatchIp(data, checklist->src_addr); + + /* NOTREACHED */ + case ACL_DST_ASN: - ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS); - if (ia) { - for (k = 0; k < (int) ia->count; k++) { - if (asnMatchIp(data, ia->in_addrs[k])) - return 1; - } - return 0; - } else if (checklist->state[ACL_DST_ASN] == ACL_LOOKUP_NONE) { - debug(28, 3) ("asnMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - name, r->host); - checklist->changeState (DestinationIPLookup::Instance()); - } else { - return asnMatchIp(data, no_addr); - } - return 0; - /* NOTREACHED */ + ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS); + + if (ia) { + for (k = 0; k < (int) ia->count; k++) { + if (asnMatchIp(data, ia->in_addrs[k])) + return 1; + } + + return 0; + } else if (checklist->state[ACL_DST_ASN] == ACL_LOOKUP_NONE) { + debug(28, 3) ("asnMatchAcl: Can't yet compare '%s' ACL for '%s'\n", + name, r->host); + checklist->changeState (DestinationIPLookup::Instance()); + } else { + return asnMatchIp(data, no_addr); + } + + return 0; + /* NOTREACHED */ #if USE_ARP_ACL + case ACL_SRC_ARP: - return aclMatchArp(&data, checklist->src_addr); - /* NOTREACHED */ + return aclMatchArp(&data, checklist->src_addr); + /* NOTREACHED */ #endif + case ACL_REP_MIME_TYPE: - if (!checklist->reply) - return 0; - header = httpHeaderGetStr(&checklist->reply->header, HDR_CONTENT_TYPE); - if (NULL == header) - header = ""; - return aclMatchRegex((relist *)data, header); - /* NOTREACHED */ + + if (!checklist->reply) + return 0; + + header = httpHeaderGetStr(&checklist->reply->header, HDR_CONTENT_TYPE); + + if (NULL == header) + header = ""; + + return aclMatchRegex((relist *)data, header); + + /* NOTREACHED */ + case ACL_EXTERNAL: - return aclMatchExternal(data, checklist); - /* NOTREACHED */ + return aclMatchExternal(data, checklist); + + /* NOTREACHED */ + case ACL_NONE: + case ACL_ENUM_MAX: - break; + break; + case ACL_DERIVED: - fatal ("overridden"); + fatal ("overridden"); } + debug(28, 0) ("aclMatchAcl: '%s' has bad type %d\n", - name, aclType()); + name, aclType()); return 0; } @@ -1038,14 +1262,16 @@ ACLList::matches (ACLChecklist *checklist) const assert (_acl); AclMatchedName = _acl->name; debug(28, 3) ("ACLList::matches: checking %s%s\n", - op ? null_string : "!", _acl->name); + op ? null_string : "!", _acl->name); + if (_acl->checklistMatches(checklist) != op) { - return false; + return false; } + return true; } -/* Warning: do not cbdata lock checklist here - it +/* Warning: do not cbdata lock checklist here - it * may be static or on the stack */ int @@ -1054,14 +1280,18 @@ aclCheckFast(const acl_access * A, ACLChecklist * checklist) allow_t allow = ACCESS_DENIED; PROF_start(aclCheckFast); debug(28, 5) ("aclCheckFast: list: %p\n", A); + while (A) { - allow = A->allow; - if (checklist->matchAclList(A->aclList, true)) { - PROF_stop(aclCheckFast); - return allow == ACCESS_ALLOWED; - } - A = A->next; + allow = A->allow; + + if (checklist->matchAclList(A->aclList, true)) { + PROF_stop(aclCheckFast); + return allow == ACCESS_ALLOWED; + } + + A = A->next; } + debug(28, 5) ("aclCheckFast: no matches, returning: %d\n", allow == ACCESS_DENIED); PROF_stop(aclCheckFast); return allow == ACCESS_DENIED; @@ -1092,19 +1322,26 @@ aclChecklistCreate(const acl_access * A, request_t * request, const char *ident) int i; ACLChecklist *checklist = new ACLChecklist; checklist->accessList = cbdataReference(A); + if (request != NULL) { - checklist->request = requestLink(request); - checklist->src_addr = request->client_addr; - checklist->my_addr = request->my_addr; - checklist->my_port = request->my_port; + checklist->request = requestLink(request); + checklist->src_addr = request->client_addr; + checklist->my_addr = request->my_addr; + checklist->my_port = request->my_port; } + for (i = 0; i < ACL_ENUM_MAX; i++) - checklist->state[i] = ACL_LOOKUP_NONE; + checklist->state[i] = ACL_LOOKUP_NONE; + #if USE_IDENT + if (ident) - xstrncpy(checklist->rfc931, ident, USER_IDENT_SZ); + xstrncpy(checklist->rfc931, ident, USER_IDENT_SZ); + #endif + checklist->auth_user_request = NULL; + return checklist; } @@ -1116,11 +1353,12 @@ void aclDestroyRegexList(relist * data) { relist *next = NULL; + for (; data; data = next) { - next = data->next; - regfree(&data->regex); - safe_free(data->pattern); - memFree(data, MEM_RELIST); + next = data->next; + regfree(&data->regex); + safe_free(data->pattern); + memFree(data, MEM_RELIST); } } @@ -1128,66 +1366,87 @@ void aclDestroyAcls(acl ** head) { ACL *next = NULL; + for (acl *a = *head; a; a = next) { - next = a->next; - a->deleteSelf(); + next = a->next; + a->deleteSelf(); } + *head = NULL; } ACL::~ACL() { debug(28, 3) ("aclDestroyAcls: '%s'\n", cfgline); + switch (aclType()) { #if USE_ARP_ACL - case ACL_SRC_ARP: + + case ACL_SRC_ARP: #endif #if SQUID_SNMP - case ACL_SNMP_COMMUNITY: - wordlistDestroy((wordlist **) & data); - break; + + case ACL_SNMP_COMMUNITY: + wordlistDestroy((wordlist **) & data); + break; #endif - /* Destroyed in the children */ - case ACL_DERIVED: - break; - case ACL_REP_MIME_TYPE: - aclDestroyRegexList((relist *)data); - break; - case ACL_PROTO: - case ACL_METHOD: - case ACL_SRC_ASN: - case ACL_DST_ASN: + /* Destroyed in the children */ + + case ACL_DERIVED: + break; + + case ACL_REP_MIME_TYPE: + aclDestroyRegexList((relist *)data); + break; + + case ACL_PROTO: + + case ACL_METHOD: + + case ACL_SRC_ASN: + + case ACL_DST_ASN: #if SRC_RTT_NOT_YET_FINISHED - case ACL_NETDB_SRC_RTT: + + case ACL_NETDB_SRC_RTT: #endif - case ACL_MAXCONN: - intlistDestroy((intlist **) & data); - break; - case ACL_MAX_USER_IP: - aclDestroyUserMaxIP(&data); - break; - case ACL_URL_PORT: - case ACL_MY_PORT: - aclDestroyIntRange((intrange *)data); - break; - case ACL_EXTERNAL: - aclDestroyExternal(&data); - break; - case ACL_NONE: - case ACL_ENUM_MAX: - debug(28, 1) ("aclDestroyAcls: no case for ACL type %d\n", aclType()); - break; - } - safe_free(cfgline); + + case ACL_MAXCONN: + intlistDestroy((intlist **) & data); + break; + + case ACL_MAX_USER_IP: + aclDestroyUserMaxIP(&data); + break; + + case ACL_URL_PORT: + + case ACL_MY_PORT: + aclDestroyIntRange((intrange *)data); + break; + + case ACL_EXTERNAL: + aclDestroyExternal(&data); + break; + + case ACL_NONE: + + case ACL_ENUM_MAX: + debug(28, 1) ("aclDestroyAcls: no case for ACL type %d\n", aclType()); + break; + } + + safe_free(cfgline); } void aclDestroyAclList(acl_list ** head) { acl_list *l; + for (l = *head; l; l = *head) { - *head = l->next; - l->deleteSelf(); + *head = l->next; + l->deleteSelf(); } } @@ -1196,13 +1455,15 @@ aclDestroyAccessList(acl_access ** list) { acl_access *l = NULL; acl_access *next = NULL; + for (l = *list; l; l = next) { - debug(28, 3) ("aclDestroyAccessList: '%s'\n", l->cfgline); - next = l->next; - aclDestroyAclList(&l->aclList); - safe_free(l->cfgline); - cbdataFree(l); + debug(28, 3) ("aclDestroyAccessList: '%s'\n", l->cfgline); + next = l->next; + aclDestroyAclList(&l->aclList); + safe_free(l->cfgline); + cbdataFree(l); } + *list = NULL; } @@ -1218,14 +1479,16 @@ aclDestroyDenyInfoList(acl_deny_info_list ** list) acl_name_list *l_next = NULL; for (a = *list; a; a = a_next) { - for (l = a->acl_list; l; l = l_next) { - l_next = l->next; - safe_free(l); - } - a_next = a->next; - xfree(a->err_page_name); - memFree(a, MEM_ACL_DENY_INFO_LIST); + for (l = a->acl_list; l; l = l_next) { + l_next = l->next; + safe_free(l); + } + + a_next = a->next; + xfree(a->err_page_name); + memFree(a, MEM_ACL_DENY_INFO_LIST); } + *list = NULL; } @@ -1234,9 +1497,10 @@ aclDestroyIntRange(intrange * list) { intrange *w = NULL; intrange *n = NULL; + for (w = list; w; w = n) { - n = w->next; - safe_free(w); + n = w->next; + safe_free(w); } } @@ -1244,10 +1508,12 @@ wordlist * aclDumpRegexList(relist * data) { wordlist *W = NULL; + while (data != NULL) { - wordlistAdd(&W, data->pattern); - data = data->next; + wordlistAdd(&W, data->pattern); + data = data->next; } + return W; } @@ -1256,11 +1522,13 @@ aclDumpIntlistList(intlist * data) { wordlist *W = NULL; char buf[32]; + while (data != NULL) { - snprintf(buf, sizeof(buf), "%d", data->i); - wordlistAdd(&W, buf); - data = data->next; + snprintf(buf, sizeof(buf), "%d", data->i); + wordlistAdd(&W, buf); + data = data->next; } + return W; } @@ -1269,14 +1537,18 @@ aclDumpIntRangeList(intrange * data) { wordlist *W = NULL; char buf[32]; + while (data != NULL) { - if (data->i == data->j) - snprintf(buf, sizeof(buf), "%d", data->i); - else - snprintf(buf, sizeof(buf), "%d-%d", data->i, data->j); - wordlistAdd(&W, buf); - data = data->next; + if (data->i == data->j) + snprintf(buf, sizeof(buf), "%d", data->i); + else + snprintf(buf, sizeof(buf), "%d-%d", data->i, data->j); + + wordlistAdd(&W, buf); + + data = data->next; } + return W; } @@ -1284,10 +1556,12 @@ static wordlist * aclDumpProtoList(intlist * data) { wordlist *W = NULL; + while (data != NULL) { - wordlistAdd(&W, ProtocolStr[data->i]); - data = data->next; + wordlistAdd(&W, ProtocolStr[data->i]); + data = data->next; } + return W; } @@ -1295,10 +1569,12 @@ static wordlist * aclDumpMethodList(intlist * data) { wordlist *W = NULL; + while (data != NULL) { - wordlistAdd(&W, RequestMethodStr[data->i]); - data = data->next; + wordlistAdd(&W, RequestMethodStr[data->i]); + data = data->next; } + return W; } @@ -1314,36 +1590,52 @@ ACL::dump() const { switch (aclType()) { #if SQUID_SNMP + case ACL_SNMP_COMMUNITY: - return wordlistDup((wordlist *)data); + return wordlistDup((wordlist *)data); #endif + case ACL_DERIVED: - fatal ("unused"); + fatal ("unused"); + case ACL_REP_MIME_TYPE: - return aclDumpRegexList((relist *)data); + return aclDumpRegexList((relist *)data); + case ACL_SRC_ASN: + case ACL_MAXCONN: + case ACL_DST_ASN: - return aclDumpIntlistList((intlist *)data); + return aclDumpIntlistList((intlist *)data); + case ACL_MAX_USER_IP: - return aclDumpUserMaxIP(data); + return aclDumpUserMaxIP(data); + case ACL_URL_PORT: + case ACL_MY_PORT: - return aclDumpIntRangeList((intrange *)data); + return aclDumpIntRangeList((intrange *)data); + case ACL_PROTO: - return aclDumpProtoList((intlist *)data); + return aclDumpProtoList((intlist *)data); + case ACL_METHOD: - return aclDumpMethodList((intlist *)data); + return aclDumpMethodList((intlist *)data); #if USE_ARP_ACL + case ACL_SRC_ARP: - return aclDumpArpList(data); + return aclDumpArpList(data); #endif + case ACL_EXTERNAL: - return aclDumpExternal(data); + return aclDumpExternal(data); + case ACL_NONE: + case ACL_ENUM_MAX: - break; + break; } + debug(28, 1) ("ACL::dumpGeneric: no case for ACL type %d\n", aclType()); return NULL; } @@ -1365,14 +1657,17 @@ acl_access::containsPURGE() const { acl_access const *a = this; acl_list *b; + for (; a; a = a->next) { - for (b = a->aclList; b; b = b->next) { - if (ACL_METHOD != b->_acl->aclType()) - continue; - if (b->_acl->containsPURGE()) - return true; - } + for (b = a->aclList; b; b = b->next) { + if (ACL_METHOD != b->_acl->aclType()) + continue; + + if (b->_acl->containsPURGE()) + return true; + } } + return false; } @@ -1380,7 +1675,8 @@ bool ACL::containsPURGE() const { if (aclMatchInteger((intlist *)data, METHOD_PURGE)) - return true; + return true; + return false; } @@ -1437,10 +1733,12 @@ static int decode_eth(const char *asc, char *eth) { int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0; + if (sscanf(asc, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) { - debug(28, 0) ("decode_eth: Invalid ethernet address '%s'\n", asc); - return 0; /* This is not valid address */ + debug(28, 0) ("decode_eth: Invalid ethernet address '%s'\n", asc); + return 0; /* This is not valid address */ } + eth[0] = (u_char) a1; eth[1] = (u_char) a2; eth[2] = (u_char) a3; @@ -1456,18 +1754,21 @@ aclParseArpData(const char *t) LOCAL_ARRAY(char, eth, 256); acl_arp_data *q = (acl_arp_data *)xcalloc(1, sizeof(acl_arp_data)); debug(28, 5) ("aclParseArpData: %s\n", t); + if (sscanf(t, "%[0-9a-fA-F:]", eth) != 1) { - debug(28, 0) ("aclParseArpData: Bad ethernet address: '%s'\n", t); - safe_free(q); - return NULL; + debug(28, 0) ("aclParseArpData: Bad ethernet address: '%s'\n", t); + safe_free(q); + return NULL; } + if (!decode_eth(eth, q->eth)) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseArpData: Ignoring invalid ARP acl entry: can't parse '%s'\n", eth); - safe_free(q); - return NULL; + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseArpData: Ignoring invalid ARP acl entry: can't parse '%s'\n", eth); + safe_free(q); + return NULL; } + return q; } @@ -1481,10 +1782,12 @@ aclParseArpList(void *curlist) char *t = NULL; splayNode **Top = (splayNode **)curlist; acl_arp_data *q = NULL; + while ((t = strtokFile())) { - if ((q = aclParseArpData(t)) == NULL) - continue; - *Top = splay_insert(q, *Top, aclArpCompare); + if ((q = aclParseArpData(t)) == NULL) + continue; + + *Top = splay_insert(q, *Top, aclArpCompare); } } @@ -1492,13 +1795,19 @@ aclParseArpList(void *curlist) /* aclMatchArp */ /***************/ static int + aclMatchArp(void *dataptr, struct in_addr c) { #if defined(_SQUID_LINUX_) + struct arpreq arpReq; + struct sockaddr_in ipAddr; + unsigned char ifbuffer[sizeof(struct ifreq) * 64]; + struct ifconf ifc; + struct ifreq *ifr; int offset; splayNode **Top = (splayNode **)dataptr; @@ -1520,140 +1829,197 @@ aclMatchArp(void *dataptr, struct in_addr c) ipAddr.sin_port = 0; ipAddr.sin_addr = c; memset(&arpReq, '\0', sizeof(arpReq)); + xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); /* Query ARP table */ - if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) { - /* Skip non-ethernet interfaces */ - if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { - return 0; - } - debug(28, 4) ("Got address %02x:%02x:%02x:%02x:%02x:%02x\n", - arpReq.arp_ha.sa_data[0] & 0xff, arpReq.arp_ha.sa_data[1] & 0xff, - arpReq.arp_ha.sa_data[2] & 0xff, arpReq.arp_ha.sa_data[3] & 0xff, - arpReq.arp_ha.sa_data[4] & 0xff, arpReq.arp_ha.sa_data[5] & 0xff); - /* Do lookup */ - const void *X = arpReq.arp_ha.sa_data; - *Top = splay_splay(&X, *Top, aclArpCompare); - debug(28, 3) ("aclMatchArp: '%s' %s\n", - inet_ntoa(c), splayLastResult ? "NOT found" : "found"); - return (0 == splayLastResult); + + if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) + { + /* Skip non-ethernet interfaces */ + + if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { + return 0; + } + + debug(28, 4) ("Got address %02x:%02x:%02x:%02x:%02x:%02x\n", + arpReq.arp_ha.sa_data[0] & 0xff, arpReq.arp_ha.sa_data[1] & 0xff, + arpReq.arp_ha.sa_data[2] & 0xff, arpReq.arp_ha.sa_data[3] & 0xff, + arpReq.arp_ha.sa_data[4] & 0xff, arpReq.arp_ha.sa_data[5] & 0xff); + /* Do lookup */ + const void *X = arpReq.arp_ha.sa_data; + *Top = splay_splay(&X, *Top, aclArpCompare); + debug(28, 3) ("aclMatchArp: '%s' %s\n", + inet_ntoa(c), splayLastResult ? "NOT found" : "found"); + return (0 == splayLastResult); } + /* lookup list of interface names */ ifc.ifc_len = sizeof(ifbuffer); + ifc.ifc_buf = (char *)ifbuffer; - if (ioctl(HttpSockets[0], SIOCGIFCONF, &ifc) < 0) { - debug(28, 1) ("Attempt to retrieve interface list failed: %s\n", - xstrerror()); - return 0; + + if (ioctl(HttpSockets[0], SIOCGIFCONF, &ifc) < 0) + { + debug(28, 1) ("Attempt to retrieve interface list failed: %s\n", + xstrerror()); + return 0; } - if (ifc.ifc_len > (int)sizeof(ifbuffer)) { - debug(28, 1) ("Interface list too long - %d\n", ifc.ifc_len); - return 0; + + if (ifc.ifc_len > (int)sizeof(ifbuffer)) + { + debug(28, 1) ("Interface list too long - %d\n", ifc.ifc_len); + return 0; } + /* Attempt ARP lookup on each interface */ offset = 0; - while (offset < ifc.ifc_len) { - ifr = (struct ifreq *) (ifbuffer + offset); - offset += sizeof(*ifr); - /* Skip loopback and aliased interfaces */ - if (0 == strncmp(ifr->ifr_name, "lo", 2)) - continue; - if (NULL != strchr(ifr->ifr_name, ':')) - continue; - debug(28, 4) ("Looking up ARP address for %s on %s\n", inet_ntoa(c), - ifr->ifr_name); - /* Set up structures for ARP lookup */ - ipAddr.sin_family = AF_INET; - ipAddr.sin_port = 0; - ipAddr.sin_addr = c; - memset(&arpReq, '\0', sizeof(arpReq)); - xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); - strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1); - arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0'; - /* Query ARP table */ - if (-1 == ioctl(HttpSockets[0], SIOCGARP, &arpReq)) { - /* - * Query failed. Do not log failed lookups or "device - * not supported" - */ - if (ENXIO == errno) - (void) 0; - else if (ENODEV == errno) - (void) 0; - else - debug(28, 1) ("ARP query failed: %s: %s\n", - ifr->ifr_name, xstrerror()); - continue; - } - /* Skip non-ethernet interfaces */ - if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) - continue; - debug(28, 4) ("Got address %02x:%02x:%02x:%02x:%02x:%02x on %s\n", - arpReq.arp_ha.sa_data[0] & 0xff, - arpReq.arp_ha.sa_data[1] & 0xff, - arpReq.arp_ha.sa_data[2] & 0xff, - arpReq.arp_ha.sa_data[3] & 0xff, - arpReq.arp_ha.sa_data[4] & 0xff, - arpReq.arp_ha.sa_data[5] & 0xff, ifr->ifr_name); - /* Do lookup */ - const void *X = arpReq.arp_ha.sa_data; - *Top = splay_splay(&X, *Top, aclArpCompare); - /* Return if match, otherwise continue to other interfaces */ - if (0 == splayLastResult) { - debug(28, 3) ("aclMatchArp: %s found on %s\n", - inet_ntoa(c), ifr->ifr_name); - return 1; - } - /* - * Should we stop looking here? Can the same IP address - * exist on multiple interfaces? - */ + + while (offset < ifc.ifc_len) + { + + ifr = (struct ifreq *) (ifbuffer + offset); + offset += sizeof(*ifr); + /* Skip loopback and aliased interfaces */ + + if (0 == strncmp(ifr->ifr_name, "lo", 2)) + continue; + + if (NULL != strchr(ifr->ifr_name, ':')) + continue; + + debug(28, 4) ("Looking up ARP address for %s on %s\n", inet_ntoa(c), + ifr->ifr_name); + + /* Set up structures for ARP lookup */ + ipAddr.sin_family = AF_INET; + + ipAddr.sin_port = 0; + + ipAddr.sin_addr = c; + + memset(&arpReq, '\0', sizeof(arpReq)); + + xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); + + strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1); + + arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0'; + + /* Query ARP table */ + if (-1 == ioctl(HttpSockets[0], SIOCGARP, &arpReq)) { + /* + * Query failed. Do not log failed lookups or "device + * not supported" + */ + + if (ENXIO == errno) + (void) 0; + else if (ENODEV == errno) + (void) 0; + else + debug(28, 1) ("ARP query failed: %s: %s\n", + ifr->ifr_name, xstrerror()); + + continue; + } + + /* Skip non-ethernet interfaces */ + if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) + continue; + + debug(28, 4) ("Got address %02x:%02x:%02x:%02x:%02x:%02x on %s\n", + arpReq.arp_ha.sa_data[0] & 0xff, + arpReq.arp_ha.sa_data[1] & 0xff, + arpReq.arp_ha.sa_data[2] & 0xff, + arpReq.arp_ha.sa_data[3] & 0xff, + arpReq.arp_ha.sa_data[4] & 0xff, + arpReq.arp_ha.sa_data[5] & 0xff, ifr->ifr_name); + + /* Do lookup */ + const void *X = arpReq.arp_ha.sa_data; + + *Top = splay_splay(&X, *Top, aclArpCompare); + + /* Return if match, otherwise continue to other interfaces */ + if (0 == splayLastResult) { + debug(28, 3) ("aclMatchArp: %s found on %s\n", + inet_ntoa(c), ifr->ifr_name); + return 1; + } + + /* + * Should we stop looking here? Can the same IP address + * exist on multiple interfaces? + */ } + #elif defined(_SQUID_SOLARIS_) + struct arpreq arpReq; + struct sockaddr_in ipAddr; + unsigned char ifbuffer[sizeof(struct ifreq) * 64]; + struct ifconf ifc; + struct ifreq *ifr; + int offset; + splayNode **Top = dataptr; + /* - * Set up structures for ARP lookup with blank interface name - */ + * Set up structures for ARP lookup with blank interface name + */ ipAddr.sin_family = AF_INET; + ipAddr.sin_port = 0; + ipAddr.sin_addr = c; + memset(&arpReq, '\0', sizeof(arpReq)); + xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); + /* Query ARP table */ - if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) { - /* - * Solaris (at least 2.6/x86) does not use arp_ha.sa_family - - * it returns 00:00:00:00:00:00 for non-ethernet media - */ - if (arpReq.arp_ha.sa_data[0] == 0 && - arpReq.arp_ha.sa_data[1] == 0 && - arpReq.arp_ha.sa_data[2] == 0 && - arpReq.arp_ha.sa_data[3] == 0 && - arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) - return 0; - debug(28, 4) ("Got address %02x:%02x:%02x:%02x:%02x:%02x\n", - arpReq.arp_ha.sa_data[0] & 0xff, arpReq.arp_ha.sa_data[1] & 0xff, - arpReq.arp_ha.sa_data[2] & 0xff, arpReq.arp_ha.sa_data[3] & 0xff, - arpReq.arp_ha.sa_data[4] & 0xff, arpReq.arp_ha.sa_data[5] & 0xff); - /* Do lookup */ - *Top = splay_splay(&arpReq.arp_ha.sa_data, *Top, aclArpCompare); - debug(28, 3) ("aclMatchArp: '%s' %s\n", - inet_ntoa(c), splayLastResult ? "NOT found" : "found"); - return (0 == splayLastResult); + if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) + { + /* + * Solaris (at least 2.6/x86) does not use arp_ha.sa_family - + * it returns 00:00:00:00:00:00 for non-ethernet media + */ + + if (arpReq.arp_ha.sa_data[0] == 0 && + arpReq.arp_ha.sa_data[1] == 0 && + arpReq.arp_ha.sa_data[2] == 0 && + arpReq.arp_ha.sa_data[3] == 0 && + arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0) + return 0; + + debug(28, 4) ("Got address %02x:%02x:%02x:%02x:%02x:%02x\n", + arpReq.arp_ha.sa_data[0] & 0xff, arpReq.arp_ha.sa_data[1] & 0xff, + arpReq.arp_ha.sa_data[2] & 0xff, arpReq.arp_ha.sa_data[3] & 0xff, + arpReq.arp_ha.sa_data[4] & 0xff, arpReq.arp_ha.sa_data[5] & 0xff); + + /* Do lookup */ + *Top = splay_splay(&arpReq.arp_ha.sa_data, *Top, aclArpCompare); + + debug(28, 3) ("aclMatchArp: '%s' %s\n", + inet_ntoa(c), splayLastResult ? "NOT found" : "found"); + + return (0 == splayLastResult); } + #else WRITE ME; + #endif /* * Address was not found on any interface */ debug(28, 3) ("aclMatchArp: %s NOT found\n", inet_ntoa(c)); + return 0; } @@ -1718,8 +2084,8 @@ aclDumpArpListWalkee(void * const &node, void *state) acl_arp_data *arp = (acl_arp_data *)node; static char buf[24]; snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", - arp->eth[0], arp->eth[1], arp->eth[2], arp->eth[3], - arp->eth[4], arp->eth[5]); + arp->eth[0], arp->eth[1], arp->eth[2], arp->eth[3], + arp->eth[4], arp->eth[5]); wordlistAdd((wordlist **)state, buf); } @@ -1742,8 +2108,10 @@ ACLList::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (ACLList)); + if (!Pool) - Pool = memPoolCreate("ACLList", sizeof (ACLList)); + Pool = memPoolCreate("ACLList", sizeof (ACLList)); + return memPoolAlloc(Pool); } @@ -1785,7 +2153,7 @@ acl_access::deleteSelf () const ACL::Prototype::Prototype() : prototype (NULL), typeString (NULL) {} -ACL::Prototype::Prototype (ACL const *aPrototype, char const *aType) : prototype (aPrototype), typeString (aType) +ACL::Prototype::Prototype (ACL const *aPrototype, char const *aType) : prototype (aPrototype), typeString (aType) { registerMe (); } @@ -1794,11 +2162,12 @@ Vector * ACL::Prototype::Registry; void *ACL::Prototype::Initialized; bool -ACL::Prototype::Registered(char const *aType) +ACL::Prototype::Registered(char const *aType) { for (iterator i = Registry->begin(); i != Registry->end(); ++i) - if (!strcmp (aType, (*i)->typeString)) - return true; + if (!strcmp (aType, (*i)->typeString)) + return true; + return false; } @@ -1806,17 +2175,19 @@ void ACL::Prototype::registerMe () { if (!Registry || (Initialized != ((char *)Registry - 5)) ) { - /* TODO: extract this */ - /* Not initialised */ - Registry = new Vector ; - Initialized = (char *)Registry - 5; + /* TODO: extract this */ + /* Not initialised */ + Registry = new Vector ; + Initialized = (char *)Registry - 5; } + if (Registered (typeString)) - fatalf ("Attempt to register %s twice", typeString); + fatalf ("Attempt to register %s twice", typeString); + Registry->push_back (this); } -ACL::Prototype::~Prototype() +ACL::Prototype::~Prototype() { debug (28,2)("ACL::Prototype::~Prototype: TODO: unregister me\n"); } @@ -1825,8 +2196,9 @@ ACL * ACL::Prototype::Factory (char const *typeToClone) { for (iterator i = Registry->begin(); i != Registry->end(); ++i) - if (!strcmp (typeToClone, (*i)->typeString)) - return (*i)->prototype->clone(); + if (!strcmp (typeToClone, (*i)->typeString)) + return (*i)->prototype->clone(); + return NULL; } diff --git a/src/asn.cc b/src/asn.cc index 24034e2286..8ae2699760 100644 --- a/src/asn.cc +++ b/src/asn.cc @@ -1,6 +1,6 @@ /* - * $Id: asn.cc,v 1.89 2003/02/12 06:11:00 robertc Exp $ + * $Id: asn.cc,v 1.90 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 53 AS Number handling * AUTHOR: Duane Wessels, Kostas Anagnostakis @@ -55,6 +55,7 @@ typedef u_char m_int[1 + sizeof(unsigned int)]; /* END of definitions for radix tree entries */ /* Head for ip to asn radix tree */ + struct squid_radix_node_head *AS_tree_head; /* @@ -62,12 +63,15 @@ struct squid_radix_node_head *AS_tree_head; * an intlist but it's coded as a structure for future * enhancements (e.g. expires) */ -struct _as_info { + +struct _as_info +{ intlist *as_number; time_t expires; /* NOTUSED */ }; -struct _ASState { +struct _ASState +{ StoreEntry *entry; store_client *sc; request_t *request; @@ -79,10 +83,14 @@ struct _ASState { }; typedef struct _ASState ASState; + typedef struct _as_info as_info; /* entry into the radix tree */ -struct _rtentry { + +struct _rtentry +{ + struct squid_radix_node e_nodes[2]; as_info *e_info; m_int e_addr; @@ -94,7 +102,9 @@ typedef struct _rtentry rtentry_t; static int asnAddNet(char *, int); static void asnCacheStart(int as); static STCB asHandleReply; + static int destroyRadixNode(struct squid_radix_node *rn, void *w); + static int printRadixNode(struct squid_radix_node *rn, void *sentry); static void asnAclInitialize(acl * acls); static void asStateFree(void *data); @@ -104,9 +114,11 @@ static OBJH asnStats; /* PUBLIC */ int + asnMatchIp(void *data, struct in_addr addr) { unsigned long lh; + struct squid_radix_node *rn; as_info *e; m_int m_addr; @@ -116,26 +128,36 @@ asnMatchIp(void *data, struct in_addr addr) debug(53, 3) ("asnMatchIp: Called for %s.\n", inet_ntoa(addr)); if (AS_tree_head == NULL) - return 0; + return 0; + if (addr.s_addr == no_addr.s_addr) - return 0; + return 0; + if (addr.s_addr == any_addr.s_addr) - return 0; + return 0; + store_m_int(lh, m_addr); + rn = squid_rn_match(m_addr, AS_tree_head); - if (rn == NULL) { - debug(53, 3) ("asnMatchIp: Address not in as db.\n"); - return 0; + + if (rn == NULL) + { + debug(53, 3) ("asnMatchIp: Address not in as db.\n"); + return 0; } + debug(53, 3) ("asnMatchIp: Found in db!\n"); e = ((rtentry_t *) rn)->e_info; assert(e); + for (a = (intlist *) data; a; a = a->next) - for (b = e->as_number; b; b = b->next) - if (a->i == b->i) { - debug(53, 5) ("asnMatchIp: Found a match!\n"); - return 1; - } + for (b = e->as_number; b; b = b->next) + if (a->i == b->i) + { + debug(53, 5) ("asnMatchIp: Found a match!\n"); + return 1; + } + debug(53, 5) ("asnMatchIp: AS not in as db.\n"); return 0; } @@ -145,10 +167,12 @@ asnAclInitialize(acl * acls) { acl *a; debug(53, 3) ("asnAclInitialize\n"); + for (a = acls; a; a = a->next) { - if (a->aclType() != ACL_DST_ASN && a->aclType() != ACL_SRC_ASN) - continue; - a->startCache(); + if (a->aclType() != ACL_DST_ASN && a->aclType() != ACL_SRC_ASN) + continue; + + a->startCache(); } } @@ -156,8 +180,9 @@ void ACL::startCache() { assert (aclType() == ACL_DST_ASN || aclType() == ACL_SRC_ASN); + for (intlist *i = (intlist *)data; i; i = i->next) - asnCacheStart(i->i); + asnCacheStart(i->i); } /* initialize the radix tree structure */ @@ -171,10 +196,14 @@ asnInit(void) static int inited = 0; squid_max_keylen = 40; CBDATA_INIT_TYPE(ASState); + if (0 == inited++) - squid_rn_init(); + squid_rn_init(); + squid_rn_inithead((void **) &AS_tree_head, 8); + asnAclInitialize(Config.aclList); + cachemgrRegister("asndb", "AS Number Database", asnStats, 0, 1); } @@ -182,6 +211,7 @@ void asnFreeMemory(void) { squid_rn_walktree(AS_tree_head, destroyRadixNode, AS_tree_head); + destroyRadixNode((struct squid_radix_node *) 0, (void *) AS_tree_head); } @@ -210,23 +240,25 @@ asnCacheStart(int as) req = urlParse(METHOD_GET, asres); assert(NULL != req); asState->request = requestLink(req); + if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) { - e = storeCreateEntry(asres, asres, request_flags(), METHOD_GET); - asState->sc = storeClientListAdd(e, asState); - fwdStart(-1, e, asState->request); + e = storeCreateEntry(asres, asres, request_flags(), METHOD_GET); + asState->sc = storeClientListAdd(e, asState); + fwdStart(-1, e, asState->request); } else { - storeLockObject(e); - asState->sc = storeClientListAdd(e, asState); + storeLockObject(e); + asState->sc = storeClientListAdd(e, asState); } + asState->entry = e; asState->offset = 0; asState->reqofs = 0; StoreIOBuffer readBuffer (AS_REQBUF_SZ, asState->offset, asState->reqbuf); storeClientCopy(asState->sc, - e, - readBuffer, - asHandleReply, - asState); + e, + readBuffer, + asHandleReply, + asState); } static void @@ -243,45 +275,52 @@ asHandleReply(void *data, StoreIOBuffer result) debug(53, 3) ("asHandleReply: buffer='%s'\n", buf); /* First figure out whether we should abort the request */ + if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { - asStateFree(asState); - return; + asStateFree(asState); + return; } + if (result.length == 0 && asState->dataRead) { - debug(53, 3) ("asHandleReply: Done: %s\n", storeUrl(e)); - asStateFree(asState); - return; + debug(53, 3) ("asHandleReply: Done: %s\n", storeUrl(e)); + asStateFree(asState); + return; } else if (result.flags.error) { - debug(53, 1) ("asHandleReply: Called with Error set and size=%u\n", (unsigned int) result.length); - asStateFree(asState); - return; + debug(53, 1) ("asHandleReply: Called with Error set and size=%u\n", (unsigned int) result.length); + asStateFree(asState); + return; } else if (HTTP_OK != e->getReply()->sline.status) { - debug(53, 1) ("WARNING: AS %d whois request failed\n", - asState->as_number); - asStateFree(asState); - return; + debug(53, 1) ("WARNING: AS %d whois request failed\n", + asState->as_number); + asStateFree(asState); + return; } + /* * Next, attempt to parse our request * Remembering that the actual buffer size is retsize + reqofs! */ s = buf; + while (s - buf < (off_t)(result.length + asState->reqofs) && *s != '\0') { - while (*s && xisspace(*s)) - s++; - for (t = s; *t; t++) { - if (xisspace(*t)) - break; - } - if (*t == '\0') { - /* oof, word should continue on next block */ - break; - } - *t = '\0'; - debug(53, 3) ("asHandleReply: AS# %s (%d)\n", s, asState->as_number); - asnAddNet(s, asState->as_number); - s = t + 1; - asState->dataRead = 1; + while (*s && xisspace(*s)) + s++; + + for (t = s; *t; t++) { + if (xisspace(*t)) + break; + } + + if (*t == '\0') { + /* oof, word should continue on next block */ + break; + } + + *t = '\0'; + debug(53, 3) ("asHandleReply: AS# %s (%d)\n", s, asState->as_number); + asnAddNet(s, asState->as_number); + s = t + 1; + asState->dataRead = 1; } /* @@ -290,6 +329,7 @@ asHandleReply(void *data, StoreIOBuffer result) * around for the next request */ leftoversz = (asState->reqofs + result.length) - (s - buf); + assert(leftoversz >= 0); /* @@ -302,29 +342,32 @@ asHandleReply(void *data, StoreIOBuffer result) * Next, update our offset and reqofs, and kick off a copy if required */ asState->offset += result.length; + asState->reqofs = leftoversz; + debug(53, 3) ("asState->offset = %ld\n", (long int) asState->offset); + if (e->store_status == STORE_PENDING) { - debug(53, 3) ("asHandleReply: store_status == STORE_PENDING: %s\n", storeUrl(e)); - StoreIOBuffer tempBuffer (AS_REQBUF_SZ - asState->reqofs, - asState->offset, - asState->reqbuf + asState->reqofs); - storeClientCopy(asState->sc, - e, - tempBuffer, - asHandleReply, - asState); + debug(53, 3) ("asHandleReply: store_status == STORE_PENDING: %s\n", storeUrl(e)); + StoreIOBuffer tempBuffer (AS_REQBUF_SZ - asState->reqofs, + asState->offset, + asState->reqbuf + asState->reqofs); + storeClientCopy(asState->sc, + e, + tempBuffer, + asHandleReply, + asState); } else { - StoreIOBuffer tempBuffer; - debug(53, 3) ("asHandleReply: store complete, but data recieved %s\n", storeUrl(e)); - tempBuffer.offset = asState->offset; - tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; - tempBuffer.data = asState->reqbuf + asState->reqofs; - storeClientCopy(asState->sc, - e, - tempBuffer, - asHandleReply, - asState); + StoreIOBuffer tempBuffer; + debug(53, 3) ("asHandleReply: store complete, but data recieved %s\n", storeUrl(e)); + tempBuffer.offset = asState->offset; + tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; + tempBuffer.data = asState->reqbuf + asState->reqofs; + storeClientCopy(asState->sc, + e, + tempBuffer, + asHandleReply, + asState); } } @@ -347,86 +390,119 @@ static int asnAddNet(char *as_string, int as_number) { rtentry_t *e = (rtentry_t *)xmalloc(sizeof(rtentry_t)); + struct squid_radix_node *rn; char dbg1[32], dbg2[32]; intlist **Tail = NULL; intlist *q = NULL; as_info *asinfo = NULL; + struct in_addr in_a, in_m; long mask, addr; char *t; int bitl; t = strchr(as_string, '/'); + if (t == NULL) { - debug(53, 3) ("asnAddNet: failed, invalid response from whois server.\n"); - return 0; + debug(53, 3) ("asnAddNet: failed, invalid response from whois server.\n"); + return 0; } + *t = '\0'; addr = inet_addr(as_string); bitl = atoi(t + 1); + if (bitl < 0) - bitl = 0; + bitl = 0; + if (bitl > 32) - bitl = 32; + bitl = 32; + mask = bitl ? 0xfffffffful << (32 - bitl) : 0; in_a.s_addr = addr; + in_m.s_addr = mask; + xstrncpy(dbg1, inet_ntoa(in_a), 32); + xstrncpy(dbg2, inet_ntoa(in_m), 32); + addr = ntohl(addr); + /*mask = ntohl(mask); */ debug(53, 3) ("asnAddNet: called for %s/%s\n", dbg1, dbg2); + memset(e, '\0', sizeof(rtentry_t)); + store_m_int(addr, e->e_addr); + store_m_int(mask, e->e_mask); + rn = squid_rn_lookup(e->e_addr, e->e_mask, AS_tree_head); + if (rn != NULL) { - asinfo = ((rtentry_t *) rn)->e_info; - if (intlistFind(asinfo->as_number, as_number)) { - debug(53, 3) ("asnAddNet: Ignoring repeated network '%s/%d' for AS %d\n", - dbg1, bitl, as_number); - } else { - debug(53, 3) ("asnAddNet: Warning: Found a network with multiple AS numbers!\n"); - for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next); - q = (intlist *)xcalloc(1, sizeof(intlist)); - q->i = as_number; - *(Tail) = q; - e->e_info = asinfo; - } + asinfo = ((rtentry_t *) rn)->e_info; + + if (intlistFind(asinfo->as_number, as_number)) { + debug(53, 3) ("asnAddNet: Ignoring repeated network '%s/%d' for AS %d\n", + dbg1, bitl, as_number); + } else { + debug(53, 3) ("asnAddNet: Warning: Found a network with multiple AS numbers!\n"); + + for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next) + + ; + q = (intlist *)xcalloc(1, sizeof(intlist)); + + q->i = as_number; + + *(Tail) = q; + + e->e_info = asinfo; + } } else { - q = (intlist *)xcalloc(1, sizeof(intlist)); - q->i = as_number; - asinfo = (as_info *)xmalloc(sizeof(asinfo)); - asinfo->as_number = q; - rn = squid_rn_addroute(e->e_addr, e->e_mask, AS_tree_head, e->e_nodes); - rn = squid_rn_match(e->e_addr, AS_tree_head); - assert(rn != NULL); - e->e_info = asinfo; + q = (intlist *)xcalloc(1, sizeof(intlist)); + q->i = as_number; + asinfo = (as_info *)xmalloc(sizeof(asinfo)); + asinfo->as_number = q; + rn = squid_rn_addroute(e->e_addr, e->e_mask, AS_tree_head, e->e_nodes); + rn = squid_rn_match(e->e_addr, AS_tree_head); + assert(rn != NULL); + e->e_info = asinfo; } + if (rn == 0) { - xfree(e); - debug(53, 3) ("asnAddNet: Could not add entry.\n"); - return 0; + xfree(e); + debug(53, 3) ("asnAddNet: Could not add entry.\n"); + return 0; } + e->e_info = asinfo; return 1; } static int + destroyRadixNode(struct squid_radix_node *rn, void *w) { + struct squid_radix_node_head *rnh = (struct squid_radix_node_head *) w; - if (rn && !(rn->rn_flags & RNF_ROOT)) { - rtentry_t *e = (rtentry_t *) rn; - rn = squid_rn_delete(rn->rn_key, rn->rn_mask, rnh); - if (rn == 0) - debug(53, 3) ("destroyRadixNode: internal screwup\n"); - destroyRadixNodeInfo(e->e_info); - xfree(rn); + if (rn && !(rn->rn_flags & RNF_ROOT)) + { + rtentry_t *e = (rtentry_t *) rn; + rn = squid_rn_delete(rn->rn_key, rn->rn_mask, rnh); + + if (rn == 0) + debug(53, 3) ("destroyRadixNode: internal screwup\n"); + + destroyRadixNodeInfo(e->e_info); + + xfree(rn); } + return 1; } @@ -435,11 +511,13 @@ destroyRadixNodeInfo(as_info * e_info) { intlist *prev = NULL; intlist *data = e_info->as_number; + while (data) { - prev = data; - data = data->next; - xfree(prev); + prev = data; + data = data->next; + xfree(prev); } + xfree(data); } @@ -447,34 +525,43 @@ static int mask_len(u_long mask) { int len = 32; + if (mask == 0) - return 0; + return 0; + while ((mask & 1) == 0) { - len--; - mask >>= 1; + len--; + mask >>= 1; } + return len; } static int + printRadixNode(struct squid_radix_node *rn, void *_sentry) { StoreEntry *sentry = (StoreEntry *)_sentry; rtentry_t *e = (rtentry_t *) rn; intlist *q; as_info *asinfo; + struct in_addr addr; + struct in_addr mask; assert(e); assert(e->e_info); (void) get_m_int(addr.s_addr, e->e_addr); (void) get_m_int(mask.s_addr, e->e_mask); storeAppendPrintf(sentry, "%15s/%d\t", - inet_ntoa(addr), mask_len(ntohl(mask.s_addr))); + inet_ntoa(addr), mask_len(ntohl(mask.s_addr))); asinfo = e->e_info; assert(asinfo->as_number); + for (q = asinfo->as_number; q; q = q->next) - storeAppendPrintf(sentry, " %d", q->i); + storeAppendPrintf(sentry, " %d", q->i); + storeAppendPrintf(sentry, "\n"); + return 0; } diff --git a/src/auth/basic/auth_basic.cc b/src/auth/basic/auth_basic.cc index ed0ee7cd5e..b134397373 100644 --- a/src/auth/basic/auth_basic.cc +++ b/src/auth/basic/auth_basic.cc @@ -1,5 +1,5 @@ /* - * $Id: auth_basic.cc,v 1.23 2003/02/06 09:57:39 robertc Exp $ + * $Id: auth_basic.cc,v 1.24 2003/02/21 22:50:26 robertc Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Duane Wessels @@ -114,18 +114,25 @@ static void authBasicDone(void) { if (basicauthenticators) - helperShutdown(basicauthenticators); + helperShutdown(basicauthenticators); + authbasic_initialised = 0; + if (!shutting_down) - return; + return; + if (basicauthenticators) - helperFree(basicauthenticators); + helperFree(basicauthenticators); + basicauthenticators = NULL; + #if DEBUGSHUTDOWN + if (basic_data_pool) { - memPoolDestroy(&basic_data_pool); - basic_data_pool = NULL; + memPoolDestroy(&basic_data_pool); + basic_data_pool = NULL; } + #endif debug(29, 2) ("authBasicDone: Basic authentication Shutdown.\n"); } @@ -140,11 +147,12 @@ static int authBasicConfigured() { if ((basicConfig != NULL) && (basicConfig->authenticate != NULL) && - (basicConfig->authenticateChildren != 0) && - (basicConfig->basicAuthRealm != NULL)) { - debug(29, 9) ("authBasicConfigured: returning configured\n"); - return 1; + (basicConfig->authenticateChildren != 0) && + (basicConfig->basicAuthRealm != NULL)) { + debug(29, 9) ("authBasicConfigured: returning configured\n"); + return 1; } + debug(29, 9) ("authBasicConfigured: returning unconfigured\n"); return 0; } @@ -153,9 +161,12 @@ static int authenticateBasicAuthenticated(auth_user_request_t * auth_user_request) { basic_data *basic_auth = static_cast(auth_user_request->auth_user->scheme_data); + if ((basic_auth->flags.credentials_ok == 1) && (basic_auth->credentials_checkedtime + basicConfig->credentialsTTL > squid_curtime)) - return 1; + return 1; + debug(29, 4) ("User not authenticated or credentials need rechecking.\n"); + return 0; } @@ -165,6 +176,7 @@ authenticateBasiccmpUsername(basic_data * u1, basic_data * u2) { return strcmp(u1->username, u2->username); } + #endif /* log a basic user in @@ -182,42 +194,53 @@ authenticateBasicAuthenticateUser(auth_user_request_t * auth_user_request, reque basic_auth = static_cast(auth_user->scheme_data); /* if the password is not ok, do an identity */ + if (basic_auth->flags.credentials_ok != 1) - return; + return; /* are we about to recheck the credentials externally? */ if ((basic_auth->credentials_checkedtime + basicConfig->credentialsTTL) <= squid_curtime) { - debug(29, 4) ("authBasicAuthenticate: credentials expired - rechecking\n"); - return; + debug(29, 4) ("authBasicAuthenticate: credentials expired - rechecking\n"); + return; } + /* we have been through the external helper, and the credentials haven't expired */ debug(29, 9) ("authenticateBasicAuthenticateuser: user '%s' authenticated\n", - basic_auth->username); + basic_auth->username); /* Decode now takes care of finding the auth_user struct in the cache */ /* after external auth occurs anyway */ auth_user->expiretime = current_time.tv_sec; + return; } int authenticateBasicDirection(auth_user_request_t * auth_user_request) { -/* null auth_user is checked for by authenticateDirection */ + /* null auth_user is checked for by authenticateDirection */ auth_user_t *auth_user = auth_user_request->auth_user; basic_data *basic_auth = static_cast(auth_user->scheme_data); + switch (basic_auth->flags.credentials_ok) { + case 0: /* not checked */ - return -1; + return -1; + case 1: /* checked & ok */ - if (basic_auth->credentials_checkedtime + basicConfig->credentialsTTL <= squid_curtime) - return -1; - return 0; + + if (basic_auth->credentials_checkedtime + basicConfig->credentialsTTL <= squid_curtime) + return -1; + + return 0; + case 2: /* paused while waiting for a username:password check on another request */ - return -1; + return -1; + case 3: /* authentication process failed. */ - return -2; + return -2; } + return -2; } @@ -225,8 +248,8 @@ void authenticateBasicFixErrorHeader(auth_user_request_t * auth_user_request, HttpReply * rep, http_hdr_type type, request_t * request) { if (basicConfig->authenticate) { - debug(29, 9) ("authenticateFixErrorHeader: Sending type:%d header: 'Basic realm=\"%s\"'\n", type, basicConfig->basicAuthRealm); - httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", basicConfig->basicAuthRealm); + debug(29, 9) ("authenticateFixErrorHeader: Sending type:%d header: 'Basic realm=\"%s\"'\n", type, basicConfig->basicAuthRealm); + httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", basicConfig->basicAuthRealm); } } @@ -235,13 +258,18 @@ void authBasicFreeConfig(authScheme * scheme) { if (basicConfig == NULL) - return; + return; + assert(basicConfig == scheme->scheme_data); + if (basicConfig->authenticate) - wordlistDestroy(&basicConfig->authenticate); + wordlistDestroy(&basicConfig->authenticate); + if (basicConfig->basicAuthRealm) - safe_free(basicConfig->basicAuthRealm); + safe_free(basicConfig->basicAuthRealm); + xfree(basicConfig); + basicConfig = NULL; } @@ -250,11 +278,15 @@ authenticateBasicFreeUser(auth_user_t * auth_user) { basic_data *basic_auth = static_cast(auth_user->scheme_data); debug(29, 5) ("authenticateBasicFreeUser: Clearing Basic scheme data\n"); + if (basic_auth->username) - xfree(basic_auth->username); + xfree(basic_auth->username); + if (basic_auth->passwd) - xfree(basic_auth->passwd); + xfree(basic_auth->passwd); + memPoolFree(basic_data_pool, auth_user->scheme_data); + auth_user->scheme_data = NULL; } @@ -268,31 +300,43 @@ authenticateBasicHandleReply(void *data, char *reply) char *t = NULL; void *cbdata; debug(29, 9) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : ""); + if (reply) { - if ((t = strchr(reply, ' '))) - *t = '\0'; - if (*reply == '\0') - reply = NULL; + if ((t = strchr(reply, ' '))) + *t = '\0'; + + if (*reply == '\0') + reply = NULL; } + assert(r->auth_user_request != NULL); assert(r->auth_user_request->auth_user->auth_type == AUTH_BASIC); auth_user = r->auth_user_request->auth_user; basic_auth = static_cast(auth_user->scheme_data); + if (reply && (strncasecmp(reply, "OK", 2) == 0)) - basic_auth->flags.credentials_ok = 1; + basic_auth->flags.credentials_ok = 1; else - basic_auth->flags.credentials_ok = 3; + basic_auth->flags.credentials_ok = 3; + basic_auth->credentials_checkedtime = squid_curtime; + if (cbdataReferenceValidDone(r->data, &cbdata)) - r->handler(cbdata, NULL); + r->handler(cbdata, NULL); + cbdataReferenceDone(r->data); + while (basic_auth->auth_queue) { - tmpnode = basic_auth->auth_queue->next; - if (cbdataReferenceValidDone(basic_auth->auth_queue->data, &cbdata)) - basic_auth->auth_queue->handler(cbdata, NULL); - xfree(basic_auth->auth_queue); - basic_auth->auth_queue = tmpnode; + tmpnode = basic_auth->auth_queue->next; + + if (cbdataReferenceValidDone(basic_auth->auth_queue->data, &cbdata)) + basic_auth->auth_queue->handler(cbdata, NULL); + + xfree(basic_auth->auth_queue); + + basic_auth->auth_queue = tmpnode; } + authenticateStateFree(r); } @@ -302,14 +346,16 @@ authBasicCfgDump(StoreEntry * entry, const char *name, authScheme * scheme) auth_basic_config *config = static_cast(scheme->scheme_data); wordlist *list = config->authenticate; storeAppendPrintf(entry, "%s %s", name, "basic"); + while (list != NULL) { - storeAppendPrintf(entry, " %s", list->key); - list = list->next; + storeAppendPrintf(entry, " %s", list->key); + list = list->next; } + storeAppendPrintf(entry, "\n%s %s realm %s\n%s %s children %d\n%s %s credentialsttl %d seconds\n", - name, "basic", config->basicAuthRealm, - name, "basic", config->authenticateChildren, - name, "basic", (int) config->credentialsTTL); + name, "basic", config->basicAuthRealm, + name, "basic", config->authenticateChildren, + name, "basic", (int) config->credentialsTTL); } @@ -317,28 +363,32 @@ static void authBasicParse(authScheme * scheme, int n_configured, char *param_str) { if (scheme->scheme_data == NULL) { - assert(basicConfig == NULL); - /* this is the first param to be found */ - scheme->scheme_data = xmalloc(sizeof(auth_basic_config)); - memset(scheme->scheme_data, 0, sizeof(auth_basic_config)); - basicConfig = static_cast(scheme->scheme_data); - basicConfig->authenticateChildren = 5; - basicConfig->credentialsTTL = 2 * 60 * 60; /* two hours */ + assert(basicConfig == NULL); + /* this is the first param to be found */ + scheme->scheme_data = xmalloc(sizeof(auth_basic_config)); + memset(scheme->scheme_data, 0, sizeof(auth_basic_config)); + basicConfig = static_cast(scheme->scheme_data); + basicConfig->authenticateChildren = 5; + basicConfig->credentialsTTL = 2 * 60 * 60; /* two hours */ } + basicConfig = static_cast(scheme->scheme_data); + if (strcasecmp(param_str, "program") == 0) { - if (basicConfig->authenticate) - wordlistDestroy(&basicConfig->authenticate); - parse_wordlist(&basicConfig->authenticate); - requirePathnameExists("authparam basic program", basicConfig->authenticate->key); + if (basicConfig->authenticate) + wordlistDestroy(&basicConfig->authenticate); + + parse_wordlist(&basicConfig->authenticate); + + requirePathnameExists("authparam basic program", basicConfig->authenticate->key); } else if (strcasecmp(param_str, "children") == 0) { - parse_int(&basicConfig->authenticateChildren); + parse_int(&basicConfig->authenticateChildren); } else if (strcasecmp(param_str, "realm") == 0) { - parse_eol(&basicConfig->basicAuthRealm); + parse_eol(&basicConfig->basicAuthRealm); } else if (strcasecmp(param_str, "credentialsttl") == 0) { - parse_time_t(&basicConfig->credentialsTTL); + parse_time_t(&basicConfig->credentialsTTL); } else { - debug(28, 0) ("unrecognised basic auth scheme parameter '%s'\n", param_str); + debug(28, 0) ("unrecognised basic auth scheme parameter '%s'\n", param_str); } } @@ -356,8 +406,10 @@ char const * authenticateBasicUsername(auth_user_t const * auth_user) { basic_data *basic_auth = static_cast(auth_user->scheme_data); + if (basic_auth) - return basic_auth->username; + return basic_auth->username; + return NULL; } @@ -376,8 +428,7 @@ authBasicDataNew(void) #if UNUSED_CODE static void authBasicDataFree(basic_data * basic_auth) -{ -} +{} #endif @@ -386,14 +437,17 @@ authBasicAuthUserFindUsername(const char *username) { AuthUserHashPointer *usernamehash; debug(29, 9) ("authBasicAuthUserFindUsername: Looking for user '%s'\n", username); + if (username && (usernamehash = static_cast(hash_lookup(proxy_auth_username_cache, username)))) { - while (usernamehash) { - if ((authUserHashPointerUser(usernamehash)->auth_type == AUTH_BASIC) && - !strcmp(username, (char const *)usernamehash->key)) - return authUserHashPointerUser(usernamehash); - usernamehash = static_cast(usernamehash->next); - } + while (usernamehash) { + if ((authUserHashPointerUser(usernamehash)->auth_type == AUTH_BASIC) && + !strcmp(username, (char const *)usernamehash->key)) + return authUserHashPointerUser(usernamehash); + + usernamehash = static_cast(usernamehash->next); + } } + return NULL; } @@ -417,116 +471,137 @@ authenticateBasicDecodeAuth(auth_user_request_t * auth_user_request, const char /* decode the username */ /* trim BASIC from string */ + while (!xisspace(*proxy_auth)) - proxy_auth++; + proxy_auth++; local_basic.passwd = NULL; /* Trim leading whitespace before decoding */ while (xisspace(*proxy_auth)) - proxy_auth++; + proxy_auth++; + /* username and password */ sent_auth = xstrdup(proxy_auth); + /* Trim trailing \n before decoding */ strtok(sent_auth, "\n"); + cleartext = uudecode(sent_auth); + xfree(sent_auth); + /* * Don't allow NL or CR in the credentials. * Oezguer Kesim */ strtok(cleartext, "\r\n"); + debug(29, 9) ("authenticateBasicDecodeAuth: cleartext = '%s'\n", cleartext); + local_basic.username = xstrndup(cleartext, USER_IDENT_SZ); + xfree(cleartext); + if ((cleartext = strchr(local_basic.username, ':')) != NULL) - *(cleartext)++ = '\0'; + *(cleartext)++ = '\0'; + local_basic.passwd = cleartext; + if (cleartext == NULL) { - debug(29, 4) ("authenticateBasicDecodeAuth: no password in proxy authorization header '%s'\n", - proxy_auth); - local_basic.passwd = NULL; - authenticateSetDenyMessage (auth_user_request, "no password was present in the HTTP [proxy-]authorization header. This is most likely a browser bug"); + debug(29, 4) ("authenticateBasicDecodeAuth: no password in proxy authorization header '%s'\n", + proxy_auth); + local_basic.passwd = NULL; + authenticateSetDenyMessage (auth_user_request, "no password was present in the HTTP [proxy-]authorization header. This is most likely a browser bug"); } else if (*cleartext == '\0') { - debug(29, 4) ("authenticateBasicDecodeAuth: Disallowing empty password," - "user is '%s'\n", local_basic.username); - local_basic.passwd = NULL; - authenticateSetDenyMessage (auth_user_request, "Request denied because you provided an empty password. Users MUST have a password."); + debug(29, 4) ("authenticateBasicDecodeAuth: Disallowing empty password," + "user is '%s'\n", local_basic.username); + local_basic.passwd = NULL; + authenticateSetDenyMessage (auth_user_request, "Request denied because you provided an empty password. Users MUST have a password."); } + /* special case: we have to free the strings for user and password * if we are not returning a filled out structure */ if (local_basic.passwd == NULL) { - if (local_basic.username) { - /* log the username */ - debug(29, 9) ("authBasicDecodeAuth: Creating new user for logging '%s'\n", local_basic.username); - /* new auth_user */ - auth_user = authenticateAuthUserNew("basic"); - /* new scheme data */ - basic_auth = authBasicDataNew(); - /* save the credentials */ - basic_auth->username = local_basic.username; - /* link the scheme data in */ - auth_user->scheme_data = basic_auth; - /* set the auth_user type */ - auth_user->auth_type = AUTH_BROKEN; - /* link the request to the user */ - auth_user_request->auth_user = auth_user; - /* lock for the auth_user_request link */ - authenticateAuthUserLock(auth_user); - node = dlinkNodeNew(); - dlinkAdd(auth_user_request, node, &auth_user->requests); - } - return; + if (local_basic.username) { + /* log the username */ + debug(29, 9) ("authBasicDecodeAuth: Creating new user for logging '%s'\n", local_basic.username); + /* new auth_user */ + auth_user = authenticateAuthUserNew("basic"); + /* new scheme data */ + basic_auth = authBasicDataNew(); + /* save the credentials */ + basic_auth->username = local_basic.username; + /* link the scheme data in */ + auth_user->scheme_data = basic_auth; + /* set the auth_user type */ + auth_user->auth_type = AUTH_BROKEN; + /* link the request to the user */ + auth_user_request->auth_user = auth_user; + /* lock for the auth_user_request link */ + authenticateAuthUserLock(auth_user); + node = dlinkNodeNew(); + dlinkAdd(auth_user_request, node, &auth_user->requests); + } + + return; } else { - local_basic.passwd = xstrndup(cleartext, USER_IDENT_SZ); + local_basic.passwd = xstrndup(cleartext, USER_IDENT_SZ); } /* now lookup and see if we have a matching auth_user structure in memory. */ if ((auth_user = authBasicAuthUserFindUsername(local_basic.username)) == NULL) { - /* the user doesn't exist in the username cache yet */ - debug(29, 9) ("authBasicDecodeAuth: Creating new user '%s'\n", local_basic.username); - /* new auth_user */ - auth_user = authenticateAuthUserNew("basic"); - /* new scheme data */ - basic_auth = authBasicDataNew(); - /* save the credentials */ - basic_auth->username = local_basic.username; - basic_auth->passwd = local_basic.passwd; - /* link the scheme data in */ - auth_user->scheme_data = basic_auth; - /* set the auth_user type */ - auth_user->auth_type = AUTH_BASIC; - /* current time for timeouts */ - auth_user->expiretime = current_time.tv_sec; - - /* this auth_user struct is the 'lucky one' to get added to the username cache */ - /* the requests after this link to the auth_user */ - /* store user in hash */ - authenticateUserNameCacheAdd(auth_user); + /* the user doesn't exist in the username cache yet */ + debug(29, 9) ("authBasicDecodeAuth: Creating new user '%s'\n", local_basic.username); + /* new auth_user */ + auth_user = authenticateAuthUserNew("basic"); + /* new scheme data */ + basic_auth = authBasicDataNew(); + /* save the credentials */ + basic_auth->username = local_basic.username; + basic_auth->passwd = local_basic.passwd; + /* link the scheme data in */ + auth_user->scheme_data = basic_auth; + /* set the auth_user type */ + auth_user->auth_type = AUTH_BASIC; + /* current time for timeouts */ + auth_user->expiretime = current_time.tv_sec; + + /* this auth_user struct is the 'lucky one' to get added to the username cache */ + /* the requests after this link to the auth_user */ + /* store user in hash */ + authenticateUserNameCacheAdd(auth_user); } else { - debug(29, 9) ("authBasicDecodeAuth: Found user '%s' in the user cache as '%p'\n", local_basic.username, auth_user); - xfree(local_basic.username); - basic_auth = static_cast(auth_user->scheme_data); - if (strcmp(local_basic.passwd, basic_auth->passwd)) { - debug(29, 4) ("authBasicDecodeAuth: new password found. Updating in user master record and resetting auth state to unchecked\n"); - basic_auth->flags.credentials_ok = 0; - xfree(basic_auth->passwd); - basic_auth->passwd = local_basic.passwd; - } else - xfree(local_basic.passwd); - if (basic_auth->flags.credentials_ok == 3) { - debug(29, 4) ("authBasicDecodeAuth: last attempt to authenticate this user failed, resetting auth state to unchecked\n"); - basic_auth->flags.credentials_ok = 0; - } + debug(29, 9) ("authBasicDecodeAuth: Found user '%s' in the user cache as '%p'\n", local_basic.username, auth_user); + xfree(local_basic.username); + basic_auth = static_cast(auth_user->scheme_data); + + if (strcmp(local_basic.passwd, basic_auth->passwd)) { + debug(29, 4) ("authBasicDecodeAuth: new password found. Updating in user master record and resetting auth state to unchecked\n"); + basic_auth->flags.credentials_ok = 0; + xfree(basic_auth->passwd); + basic_auth->passwd = local_basic.passwd; + } else + xfree(local_basic.passwd); + + if (basic_auth->flags.credentials_ok == 3) { + debug(29, 4) ("authBasicDecodeAuth: last attempt to authenticate this user failed, resetting auth state to unchecked\n"); + basic_auth->flags.credentials_ok = 0; + } } + /* link the request to the user */ auth_user_request->auth_user = auth_user; + /* lock for the auth_user_request link */ authenticateAuthUserLock(auth_user); + node = dlinkNodeNew(); + dlinkAdd(auth_user_request, node, &auth_user->requests); + return; } @@ -536,23 +611,32 @@ static void authBasicInit(authScheme * scheme) { static int init = 0; + if (basicConfig->authenticate) { - if (!basic_data_pool) - basic_data_pool = memPoolCreate("Basic Scheme User Data", sizeof(basic_data)); - authbasic_initialised = 1; - if (basicauthenticators == NULL) - basicauthenticators = helperCreate("basicauthenticator"); - basicauthenticators->cmdline = basicConfig->authenticate; - basicauthenticators->n_to_start = basicConfig->authenticateChildren; - basicauthenticators->ipc_type = IPC_STREAM; - helperOpenServers(basicauthenticators); - if (!init) { - cachemgrRegister("basicauthenticator", - "Basic User Authenticator Stats", - authenticateBasicStats, 0, 1); - init++; - } - CBDATA_INIT_TYPE(AuthenticateStateData); + if (!basic_data_pool) + basic_data_pool = memPoolCreate("Basic Scheme User Data", sizeof(basic_data)); + + authbasic_initialised = 1; + + if (basicauthenticators == NULL) + basicauthenticators = helperCreate("basicauthenticator"); + + basicauthenticators->cmdline = basicConfig->authenticate; + + basicauthenticators->n_to_start = basicConfig->authenticateChildren; + + basicauthenticators->ipc_type = IPC_STREAM; + + helperOpenServers(basicauthenticators); + + if (!init) { + cachemgrRegister("basicauthenticator", + "Basic User Authenticator Stats", + authenticateBasicStats, 0, 1); + init++; + } + + CBDATA_INIT_TYPE(AuthenticateStateData); } } @@ -570,34 +654,36 @@ authenticateBasicStart(auth_user_request_t * auth_user_request, RH * handler, vo assert(auth_user_request->auth_user->scheme_data != NULL); basic_auth = static_cast(auth_user_request->auth_user->scheme_data); debug(29, 9) ("authenticateStart: '%s:%s'\n", basic_auth->username, - basic_auth->passwd); + basic_auth->passwd); + if (basicConfig->authenticate == NULL) { - handler(data, NULL); - return; + handler(data, NULL); + return; } + /* check to see if the auth_user already has a request outstanding */ if (basic_auth->flags.credentials_ok == 2) { - /* there is a request with the same credentials already being verified */ - BasicAuthQueueNode *node; - node = static_cast(xmalloc(sizeof(BasicAuthQueueNode))); - assert(node); - /* save the details */ - node->next = basic_auth->auth_queue; - basic_auth->auth_queue = node; - node->auth_user_request = auth_user_request; - node->handler = handler; - node->data = cbdataReference(data); - return; + /* there is a request with the same credentials already being verified */ + BasicAuthQueueNode *node; + node = static_cast(xmalloc(sizeof(BasicAuthQueueNode))); + assert(node); + /* save the details */ + node->next = basic_auth->auth_queue; + basic_auth->auth_queue = node; + node->auth_user_request = auth_user_request; + node->handler = handler; + node->data = cbdataReference(data); + return; } else { - r = cbdataAlloc(AuthenticateStateData); - r->handler = handler; - r->data = cbdataReference(data); - r->auth_user_request = auth_user_request; - /* mark the user as haveing verification in progress */ - basic_auth->flags.credentials_ok = 2; - xstrncpy(user, rfc1738_escape(basic_auth->username), sizeof(user)); - xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass)); - snprintf(buf, sizeof(buf), "%s %s\n", user, pass); - helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r); + r = cbdataAlloc(AuthenticateStateData); + r->handler = handler; + r->data = cbdataReference(data); + r->auth_user_request = auth_user_request; + /* mark the user as haveing verification in progress */ + basic_auth->flags.credentials_ok = 2; + xstrncpy(user, rfc1738_escape(basic_auth->username), sizeof(user)); + xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass)); + snprintf(buf, sizeof(buf), "%s %s\n", user, pass); + helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r); } } diff --git a/src/auth/basic/auth_basic.h b/src/auth/basic/auth_basic.h index 6027c15f02..5f715aa824 100644 --- a/src/auth/basic/auth_basic.h +++ b/src/auth/basic/auth_basic.h @@ -9,7 +9,10 @@ #define DefaultAuthenticateChildrenMax 32 /* 32 processes */ /* Generic */ -class AuthenticateStateData { + +class AuthenticateStateData +{ + public: void *data; auth_user_request_t *auth_user_request; @@ -17,7 +20,10 @@ public: }; /* queue of auth requests waiting for verification to occur */ -class BasicAuthQueueNode { + +class BasicAuthQueueNode +{ + public: BasicAuthQueueNode *next; AuthUserRequest *auth_user_request; @@ -25,19 +31,30 @@ public: void *data; }; -class basic_data { +class basic_data +{ + public: char *username; char *passwd; time_t credentials_checkedtime; - struct { - unsigned int credentials_ok:2; /*0=unchecked,1=ok,2=failed */ - } flags; + + struct + { + +unsigned int credentials_ok: + 2; /*0=unchecked,1=ok,2=failed */ + } + + flags; BasicAuthQueueNode *auth_queue; }; /* configuration runtime data */ -class auth_basic_config { + +class auth_basic_config +{ + public: int authenticateChildren; char *basicAuthRealm; diff --git a/src/auth/digest/auth_digest.cc b/src/auth/digest/auth_digest.cc index d778916254..baa73d7d65 100644 --- a/src/auth/digest/auth_digest.cc +++ b/src/auth/digest/auth_digest.cc @@ -1,6 +1,6 @@ /* - * $Id: auth_digest.cc,v 1.20 2003/02/06 09:57:40 robertc Exp $ + * $Id: auth_digest.cc,v 1.21 2003/02/21 22:50:27 robertc Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Robert Collins @@ -120,9 +120,11 @@ static void authDigestNonceEncode(digest_nonce_h * nonce) { if (!nonce) - return; + return; + if (nonce->key) - xfree(nonce->key); + xfree(nonce->key); + nonce->key = xstrdup(base64_encode_bin((char *) &(nonce->noncedata), sizeof(digest_nonce_data))); } @@ -132,44 +134,44 @@ authenticateDigestNonceNew(void) digest_nonce_h *newnonce = static_cast < digest_nonce_h * >(memPoolAlloc(digest_nonce_pool)); digest_nonce_h *temp; -/* NONCE CREATION - NOTES AND REASONING. RBC 20010108 - * === EXCERPT FROM RFC 2617 === - * The contents of the nonce are implementation dependent. The quality - * of the implementation depends on a good choice. A nonce might, for - * example, be constructed as the base 64 encoding of - * - * time-stamp H(time-stamp ":" ETag ":" private-key) - * - * where time-stamp is a server-generated time or other non-repeating - * value, ETag is the value of the HTTP ETag header associated with - * the requested entity, and private-key is data known only to the - * server. With a nonce of this form a server would recalculate the - * hash portion after receiving the client authentication header and - * reject the request if it did not match the nonce from that header - * or if the time-stamp value is not recent enough. In this way the - * server can limit the time of the nonce's validity. The inclusion of - * the ETag prevents a replay request for an updated version of the - * resource. (Note: including the IP address of the client in the - * nonce would appear to offer the server the ability to limit the - * reuse of the nonce to the same client that originally got it. - * However, that would break proxy farms, where requests from a single - * user often go through different proxies in the farm. Also, IP - * address spoofing is not that hard.) - * ==== - * - * Now for my reasoning: - * We will not accept a unrecognised nonce->we have all recognisable - * nonces stored If we send out unique base64 encodings we guarantee - * that a given nonce applies to only one user (barring attacks or - * really bad timing with expiry and creation). Using a random - * component in the nonce allows us to loop to find a unique nonce. - * We use H(nonce_data) so the nonce is meaningless to the reciever. - * So our nonce looks like base64(H(timestamp,pointertohash,randomdata)) - * And even if our randomness is not very random (probably due to - * bad coding on my part) we don't really care - the timestamp and - * memory pointer should provide enough protection for the users - * authentication. - */ + /* NONCE CREATION - NOTES AND REASONING. RBC 20010108 + * === EXCERPT FROM RFC 2617 === + * The contents of the nonce are implementation dependent. The quality + * of the implementation depends on a good choice. A nonce might, for + * example, be constructed as the base 64 encoding of + * + * time-stamp H(time-stamp ":" ETag ":" private-key) + * + * where time-stamp is a server-generated time or other non-repeating + * value, ETag is the value of the HTTP ETag header associated with + * the requested entity, and private-key is data known only to the + * server. With a nonce of this form a server would recalculate the + * hash portion after receiving the client authentication header and + * reject the request if it did not match the nonce from that header + * or if the time-stamp value is not recent enough. In this way the + * server can limit the time of the nonce's validity. The inclusion of + * the ETag prevents a replay request for an updated version of the + * resource. (Note: including the IP address of the client in the + * nonce would appear to offer the server the ability to limit the + * reuse of the nonce to the same client that originally got it. + * However, that would break proxy farms, where requests from a single + * user often go through different proxies in the farm. Also, IP + * address spoofing is not that hard.) + * ==== + * + * Now for my reasoning: + * We will not accept a unrecognised nonce->we have all recognisable + * nonces stored If we send out unique base64 encodings we guarantee + * that a given nonce applies to only one user (barring attacks or + * really bad timing with expiry and creation). Using a random + * component in the nonce allows us to loop to find a unique nonce. + * We use H(nonce_data) so the nonce is meaningless to the reciever. + * So our nonce looks like base64(H(timestamp,pointertohash,randomdata)) + * And even if our randomness is not very random (probably due to + * bad coding on my part) we don't really care - the timestamp and + * memory pointer should provide enough protection for the users + * authentication. + */ /* create a new nonce */ newnonce->nc = 0; @@ -183,11 +185,13 @@ authenticateDigestNonceNew(void) * loop until we get a unique nonce. The nonce creation must * have a random factor */ + while ((temp = authenticateDigestNonceFindNonce((char const *) (newnonce->key)))) { - /* create a new nonce */ - newnonce->noncedata.randomdata = squid_random(); - authDigestNonceEncode(newnonce); + /* create a new nonce */ + newnonce->noncedata.randomdata = squid_random(); + authDigestNonceEncode(newnonce); } + hash_join(digest_nonce_cache, newnonce); /* the cache's link */ authDigestNonceLink(newnonce); @@ -200,14 +204,19 @@ static void authenticateDigestNonceDelete(digest_nonce_h * nonce) { if (nonce) { - assert(nonce->references == 0); + assert(nonce->references == 0); #if UNREACHABLECODE - if (nonce->flags.incache) - hash_remove_link(digest_nonce_cache, nonce); + + if (nonce->flags.incache) + hash_remove_link(digest_nonce_cache, nonce); + #endif - assert(nonce->flags.incache == 0); - safe_free(nonce->key); - memPoolFree(digest_nonce_pool, nonce); + + assert(nonce->flags.incache == 0); + + safe_free(nonce->key); + + memPoolFree(digest_nonce_pool, nonce); } } @@ -215,41 +224,45 @@ static void authenticateDigestNonceSetup(void) { if (!digest_nonce_pool) - digest_nonce_pool = memPoolCreate("Digest Scheme nonce's", sizeof(digest_nonce_h)); + digest_nonce_pool = memPoolCreate("Digest Scheme nonce's", sizeof(digest_nonce_h)); + if (!digest_nonce_cache) { - digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); - assert(digest_nonce_cache); - eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval, 1); + digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); + assert(digest_nonce_cache); + eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval, 1); } } static void authenticateDigestNonceShutdown(void) { - /* + /* * We empty the cache of any nonces left in there. */ digest_nonce_h *nonce; + if (digest_nonce_cache) { - debug(29, 2) ("authenticateDigestNonceShutdown: Shutting down nonce cache \n"); - hash_first(digest_nonce_cache); - while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) { - assert(nonce->flags.incache); - authDigestNoncePurge(nonce); - } + debug(29, 2) ("authenticateDigestNonceShutdown: Shutting down nonce cache \n"); + hash_first(digest_nonce_cache); + + while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) { + assert(nonce->flags.incache); + authDigestNoncePurge(nonce); + } } + #if DEBUGSHUTDOWN if (digest_nonce_pool) { - memPoolDestroy(&digest_nonce_pool); + memPoolDestroy(&digest_nonce_pool); } + #endif debug(29, 2) ("authenticateDigestNonceShutdown: Nonce cache shutdown\n"); } static void authenticateDigestNonceReconfigure(void) -{ -} +{} static void authenticateDigestNonceCacheCleanup(void *data) @@ -263,24 +276,28 @@ authenticateDigestNonceCacheCleanup(void *data) digest_nonce_h *nonce; debug(29, 3) ("authenticateDigestNonceCacheCleanup: Cleaning the nonce cache now\n"); debug(29, 3) ("authenticateDigestNonceCacheCleanup: Current time: %ld\n", - (long int) current_time.tv_sec); + (long int) current_time.tv_sec); hash_first(digest_nonce_cache); + while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) { - debug(29, 3) ("authenticateDigestNonceCacheCleanup: nonce entry : %p '%s'\n", nonce, (char *) nonce->key); - debug(29, 4) ("authenticateDigestNonceCacheCleanup: Creation time: %ld\n", (long int) nonce->noncedata.creationtime); - if (authDigestNonceIsStale(nonce)) { - debug(29, 4) ("authenticateDigestNonceCacheCleanup: Removing nonce %s from cache due to timeout.\n", (char *) nonce->key); - assert(nonce->flags.incache); - /* invalidate nonce so future requests fail */ - nonce->flags.valid = 0; - /* if it is tied to a auth_user, remove the tie */ - authDigestNonceUserUnlink(nonce); - authDigestNoncePurge(nonce); - } + debug(29, 3) ("authenticateDigestNonceCacheCleanup: nonce entry : %p '%s'\n", nonce, (char *) nonce->key); + debug(29, 4) ("authenticateDigestNonceCacheCleanup: Creation time: %ld\n", (long int) nonce->noncedata.creationtime); + + if (authDigestNonceIsStale(nonce)) { + debug(29, 4) ("authenticateDigestNonceCacheCleanup: Removing nonce %s from cache due to timeout.\n", (char *) nonce->key); + assert(nonce->flags.incache); + /* invalidate nonce so future requests fail */ + nonce->flags.valid = 0; + /* if it is tied to a auth_user, remove the tie */ + authDigestNonceUserUnlink(nonce); + authDigestNoncePurge(nonce); + } } + debug(29, 3) ("authenticateDigestNonceCacheCleanup: Finished cleaning the nonce cache.\n"); + if (authenticateDigestActive()) - eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval, 1); + eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval, 1); } static void @@ -296,30 +313,36 @@ static int authDigestNonceLinks(digest_nonce_h * nonce) { if (!nonce) - return -1; + return -1; + return nonce->references; } + #endif static void authDigestNonceUnlink(digest_nonce_h * nonce) { assert(nonce != NULL); + if (nonce->references > 0) { - nonce->references--; + nonce->references--; } else { - debug(29, 1) ("authDigestNonceUnlink; Attempt to lower nonce %p refcount below 0!\n", nonce); + debug(29, 1) ("authDigestNonceUnlink; Attempt to lower nonce %p refcount below 0!\n", nonce); } + debug(29, 9) ("authDigestNonceUnlink: nonce '%p' now at '%d'.\n", nonce, nonce->references); + if (nonce->references == 0) - authenticateDigestNonceDelete(nonce); + authenticateDigestNonceDelete(nonce); } static const char * authenticateDigestNonceNonceb64(digest_nonce_h * nonce) { if (!nonce) - return NULL; + return NULL; + return (char const *) nonce->key; } @@ -327,13 +350,19 @@ static digest_nonce_h * authenticateDigestNonceFindNonce(const char *nonceb64) { digest_nonce_h *nonce = NULL; + if (nonceb64 == NULL) - return NULL; + return NULL; + debug(29, 9) ("authDigestNonceFindNonce:looking for nonceb64 '%s' in the nonce cache.\n", nonceb64); + nonce = static_cast < digest_nonce_h * >(hash_lookup(digest_nonce_cache, nonceb64)); + if ((nonce == NULL) || (strcmp(authenticateDigestNonceNonceb64(nonce), nonceb64))) - return NULL; + return NULL; + debug(29, 9) ("authDigestNonceFindNonce: Found nonce '%p'\n", nonce); + return nonce; } @@ -342,25 +371,31 @@ authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9]) { unsigned long intnc; /* do we have a nonce ? */ + if (!nonce) - return 0; + return 0; + intnc = strtol(nc, NULL, 16); + if ((digestConfig->NonceStrictness && intnc != nonce->nc + 1) || - intnc < nonce->nc + 1) { - debug(29, 4) ("authDigestNonceIsValid: Nonce count doesn't match\n"); - nonce->flags.valid = 0; - return 0; + intnc < nonce->nc + 1) { + debug(29, 4) ("authDigestNonceIsValid: Nonce count doesn't match\n"); + nonce->flags.valid = 0; + return 0; } + /* has it already been invalidated ? */ if (!nonce->flags.valid) { - debug(29, 4) ("authDigestNonceIsValid: Nonce already invalidated\n"); - return 0; + debug(29, 4) ("authDigestNonceIsValid: Nonce already invalidated\n"); + return 0; } + /* seems ok */ /* increment the nonce count - we've already checked that intnc is a * valid representation for us, so we don't need the test here. */ nonce->nc = intnc; + return -1; } @@ -368,42 +403,50 @@ static int authDigestNonceIsStale(digest_nonce_h * nonce) { /* do we have a nonce ? */ + if (!nonce) - return -1; + return -1; + /* has it's max duration expired? */ if (nonce->noncedata.creationtime + digestConfig->noncemaxduration < current_time.tv_sec) { - debug(29, 4) ("authDigestNonceIsStale: Nonce is too old. %ld %d %ld\n", (long int) nonce->noncedata.creationtime, (int) digestConfig->noncemaxduration, (long int) current_time.tv_sec); - nonce->flags.valid = 0; - return -1; + debug(29, 4) ("authDigestNonceIsStale: Nonce is too old. %ld %d %ld\n", (long int) nonce->noncedata.creationtime, (int) digestConfig->noncemaxduration, (long int) current_time.tv_sec); + nonce->flags.valid = 0; + return -1; } + if (nonce->nc > 99999998) { - debug(29, 4) ("authDigestNonceIsStale: Nonce count overflow\n"); - nonce->flags.valid = 0; - return -1; + debug(29, 4) ("authDigestNonceIsStale: Nonce count overflow\n"); + nonce->flags.valid = 0; + return -1; } + if (nonce->nc > digestConfig->noncemaxuses) { - debug(29, 4) ("authDigestNoncelastRequest: Nonce count over user limit\n"); - nonce->flags.valid = 0; - return -1; + debug(29, 4) ("authDigestNoncelastRequest: Nonce count over user limit\n"); + nonce->flags.valid = 0; + return -1; } + /* seems ok */ return 0; } - /* return -1 if the digest will be stale on the next request */ +/* return -1 if the digest will be stale on the next request */ static int authDigestNonceLastRequest(digest_nonce_h * nonce) { if (!nonce) - return -1; + return -1; + if (nonce->nc == 99999997) { - debug(29, 4) ("authDigestNoncelastRequest: Nonce count about to overflow\n"); - return -1; + debug(29, 4) ("authDigestNoncelastRequest: Nonce count about to overflow\n"); + return -1; } + if (nonce->nc >= digestConfig->noncemaxuses - 1) { - debug(29, 4) ("authDigestNoncelastRequest: Nonce count about to hit user limit\n"); - return -1; + debug(29, 4) ("authDigestNoncelastRequest: Nonce count about to hit user limit\n"); + return -1; } + /* and other tests are possible. */ return 0; } @@ -412,16 +455,20 @@ static void authDigestNoncePurge(digest_nonce_h * nonce) { if (!nonce) - return; + return; + if (!nonce->flags.incache) - return; + return; + hash_remove_link(digest_nonce_cache, nonce); + nonce->flags.incache = 0; + /* the cache's link */ authDigestNonceUnlink(nonce); } - /* USER related functions */ +/* USER related functions */ #if NOT_USED @@ -430,6 +477,7 @@ authDigestUsercmpname(digest_user_h * u1, digest_user_h * u2) { return strcmp(u1->username, u2->username); } + #endif static auth_user_t * @@ -438,16 +486,21 @@ authDigestUserFindUsername(const char *username) auth_user_hash_pointer *usernamehash; auth_user_t *auth_user; debug(29, 9) ("authDigestUserFindUsername: Looking for user '%s'\n", username); + if (username && (usernamehash = static_cast < auth_user_hash_pointer * >(hash_lookup(proxy_auth_username_cache, username)))) { - while ((authUserHashPointerUser(usernamehash)->auth_type != AUTH_DIGEST) && - (usernamehash->next)) - usernamehash = static_cast < auth_user_hash_pointer * >(usernamehash->next); - auth_user = NULL; - if (authUserHashPointerUser(usernamehash)->auth_type == AUTH_DIGEST) { - auth_user = authUserHashPointerUser(usernamehash); - } - return auth_user; + while ((authUserHashPointerUser(usernamehash)->auth_type != AUTH_DIGEST) && + (usernamehash->next)) + usernamehash = static_cast < auth_user_hash_pointer * >(usernamehash->next); + + auth_user = NULL; + + if (authUserHashPointerUser(usernamehash)->auth_type == AUTH_DIGEST) { + auth_user = authUserHashPointerUser(usernamehash); + } + + return auth_user; } + return NULL; } @@ -461,7 +514,7 @@ static void authDigestUserSetup(void) { if (!digest_user_pool) - digest_user_pool = memPoolCreate("Digest Scheme User Data", sizeof(digest_user_h)); + digest_user_pool = memPoolCreate("Digest Scheme User Data", sizeof(digest_user_h)); } static void @@ -473,17 +526,21 @@ authDigestUserShutdown(void) auth_user_hash_pointer *usernamehash; auth_user_t *auth_user; hash_first(proxy_auth_username_cache); + while ((usernamehash = ((auth_user_hash_pointer *) hash_next(proxy_auth_username_cache)))) { - auth_user = authUserHashPointerUser(usernamehash); - if (authscheme_list[auth_user->auth_module - 1].typestr && - strcmp(authscheme_list[auth_user->auth_module - 1].typestr, "digest") == 0) - /* it's digest */ - authenticateAuthUserUnlock(auth_user); + auth_user = authUserHashPointerUser(usernamehash); + + if (authscheme_list[auth_user->auth_module - 1].typestr && + strcmp(authscheme_list[auth_user->auth_module - 1].typestr, "digest") == 0) + /* it's digest */ + authenticateAuthUserUnlock(auth_user); } + #if DEBUGSHUTDOWN if (digest_user_pool) { - memPoolDestroy(&digest_user_pool); + memPoolDestroy(&digest_user_pool); } + #endif } @@ -495,25 +552,35 @@ static void authDigestRequestDelete(digest_request_h * digest_request) { if (digest_request->nonceb64) - xfree(digest_request->nonceb64); + xfree(digest_request->nonceb64); + if (digest_request->cnonce) - xfree(digest_request->cnonce); + xfree(digest_request->cnonce); + if (digest_request->realm) - xfree(digest_request->realm); + xfree(digest_request->realm); + if (digest_request->pszPass) - xfree(digest_request->pszPass); + xfree(digest_request->pszPass); + if (digest_request->algorithm) - xfree(digest_request->algorithm); + xfree(digest_request->algorithm); + if (digest_request->pszMethod) - xfree(digest_request->pszMethod); + xfree(digest_request->pszMethod); + if (digest_request->qop) - xfree(digest_request->qop); + xfree(digest_request->qop); + if (digest_request->uri) - xfree(digest_request->uri); + xfree(digest_request->uri); + if (digest_request->response) - xfree(digest_request->response); + xfree(digest_request->response); + if (digest_request->nonce) - authDigestNonceUnlink(digest_request->nonce); + authDigestNonceUnlink(digest_request->nonce); + memPoolFree(digest_request_pool, digest_request); } @@ -521,7 +588,7 @@ static void authDigestAURequestFree(auth_user_request_t * auth_user_request) { if (auth_user_request->scheme_data != NULL) - authDigestRequestDelete(static_cast < digest_request_h * >(auth_user_request->scheme_data)); + authDigestRequestDelete(static_cast < digest_request_h * >(auth_user_request->scheme_data)); } static digest_request_h * @@ -537,7 +604,7 @@ static void authDigestRequestSetup(void) { if (!digest_request_pool) - digest_request_pool = memPoolCreate("Digest Scheme Request Data", sizeof(digest_request_h)); + digest_request_pool = memPoolCreate("Digest Scheme Request Data", sizeof(digest_request_h)); } static void @@ -545,9 +612,11 @@ authDigestRequestShutdown(void) { /* No requests should be in progress when we get here */ #if DEBUGSHUTDOWN + if (digest_request_pool) { - memPoolDestroy(&digest_request_pool); + memPoolDestroy(&digest_request_pool); } + #endif } @@ -556,16 +625,20 @@ static void authDigestDone(void) { if (digestauthenticators) - helperShutdown(digestauthenticators); + helperShutdown(digestauthenticators); + authdigest_initialised = 0; + if (!shutting_down) { - authenticateDigestNonceReconfigure(); - return; + authenticateDigestNonceReconfigure(); + return; } + if (digestauthenticators) { - helperFree(digestauthenticators); - digestauthenticators = NULL; + helperFree(digestauthenticators); + digestauthenticators = NULL; } + authDigestRequestShutdown(); authDigestUserShutdown(); authenticateDigestNonceShutdown(); @@ -579,16 +652,18 @@ authDigestCfgDump(StoreEntry * entry, const char *name, authScheme * scheme) wordlist *list = config->authenticate; debug(29, 9) ("authDigestCfgDump: Dumping configuration\n"); storeAppendPrintf(entry, "%s %s", name, "digest"); + while (list != NULL) { - storeAppendPrintf(entry, " %s", list->key); - list = list->next; + storeAppendPrintf(entry, " %s", list->key); + list = list->next; } + storeAppendPrintf(entry, "\n%s %s realm %s\n%s %s children %d\n%s %s nonce_max_count %d\n%s %s nonce_max_duration %d seconds\n%s %s nonce_garbage_interval %d seconds\n", - name, "digest", config->digestAuthRealm, - name, "digest", config->authenticateChildren, - name, "digest", config->noncemaxuses, - name, "digest", (int) config->noncemaxduration, - name, "digest", (int) config->nonceGCInterval); + name, "digest", config->digestAuthRealm, + name, "digest", config->authenticateChildren, + name, "digest", config->noncemaxuses, + name, "digest", (int) config->noncemaxduration, + name, "digest", (int) config->nonceGCInterval); } void @@ -607,8 +682,10 @@ authSchemeSetup_digest(authscheme_entry_t * authscheme) authscheme->FreeUser = authenticateDigestUserFree; authscheme->AddHeader = authDigestAddHeader; #if WAITING_FOR_TE + authscheme->AddTrailer = authDigestAddTrailer; #endif + authscheme->authStart = authenticateDigestStart; authscheme->authStats = authenticateDigestStats; authscheme->authUserUsername = authenticateDigestUsername; @@ -625,13 +702,15 @@ authenticateDigestActive(void) { return (authdigest_initialised == 1) ? 1 : 0; } + static int authDigestConfigured(void) { if ((digestConfig != NULL) && (digestConfig->authenticate != NULL) && - (digestConfig->authenticateChildren != 0) && - (digestConfig->digestAuthRealm != NULL) && (digestConfig->noncemaxduration > -1)) - return 1; + (digestConfig->authenticateChildren != 0) && + (digestConfig->digestAuthRealm != NULL) && (digestConfig->noncemaxduration > -1)) + return 1; + return 0; } @@ -639,10 +718,11 @@ static int authDigestAuthenticated(auth_user_request_t * auth_user_request) { digest_user_h *digest_user = static_cast < digest_user_h * >(auth_user_request->auth_user->scheme_data); + if (digest_user->flags.credentials_ok == 1) - return 1; + return 1; else - return 0; + return 0; } /* log a digest user in @@ -665,49 +745,55 @@ authenticateDigestAuthenticateUser(auth_user_request_t * auth_user_request, requ digest_user = static_cast < digest_user_h * >(auth_user->scheme_data); /* if the check has corrupted the user, just return */ + if (digest_user->flags.credentials_ok == 3) { - return; + return; } + assert(auth_user_request->scheme_data != NULL); digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); /* do we have the HA1 */ + if (!digest_user->HA1created) { - digest_user->flags.credentials_ok = 2; - return; + digest_user->flags.credentials_ok = 2; + return; } + if (digest_request->nonce == NULL) { - /* this isn't a nonce we issued */ - /* TODO: record breaks in authentication at the request level - * This is probably best done with support changes at the - * auth_rewrite level -RBC - * and can wait for auth_rewrite V2. - * RBC 20010902 further note: flags.credentials ok is now - * a local scheme flag, so we can move this to the request - * level at any time. - */ - digest_user->flags.credentials_ok = 3; - return; + /* this isn't a nonce we issued */ + /* TODO: record breaks in authentication at the request level + * This is probably best done with support changes at the + * auth_rewrite level -RBC + * and can wait for auth_rewrite V2. + * RBC 20010902 further note: flags.credentials ok is now + * a local scheme flag, so we can move this to the request + * level at any time. + */ + digest_user->flags.credentials_ok = 3; + return; } + DigestCalcHA1(digest_request->algorithm, NULL, NULL, NULL, - authenticateDigestNonceNonceb64(digest_request->nonce), - digest_request->cnonce, - digest_user->HA1, SESSIONKEY); + authenticateDigestNonceNonceb64(digest_request->nonce), + digest_request->cnonce, + digest_user->HA1, SESSIONKEY); DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce), - digest_request->nc, digest_request->cnonce, digest_request->qop, - RequestMethodStr[request->method], digest_request->uri, HA2, Response); + digest_request->nc, digest_request->cnonce, digest_request->qop, + RequestMethodStr[request->method], digest_request->uri, HA2, Response); debug(29, 9) ("\nResponse = '%s'\n" - "squid is = '%s'\n", digest_request->response, Response); + "squid is = '%s'\n", digest_request->response, Response); if (strcasecmp(digest_request->response, Response)) { - digest_user->flags.credentials_ok = 3; - return; + digest_user->flags.credentials_ok = 3; + return; } + digest_user->flags.credentials_ok = 1; /* password was checked and did match */ debug(29, 4) ("authenticateDigestAuthenticateuser: user '%s' validated OK\n", - digest_user->username); + digest_user->username); /* auth_user is now linked, we reset these values * after external auth occurs anyway */ @@ -721,20 +807,28 @@ authenticateDigestDirection(auth_user_request_t * auth_user_request) digest_request_h *digest_request; digest_user_h *digest_user = static_cast < digest_user_h * >(auth_user_request->auth_user->scheme_data); /* null auth_user is checked for by authenticateDirection */ + switch (digest_user->flags.credentials_ok) { + case 0: /* not checked */ - return -1; + return -1; + case 1: /* checked & ok */ - digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); - if (authDigestNonceIsStale(digest_request->nonce)) - /* send stale response to the client agent */ - return -2; - return 0; + digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); + + if (authDigestNonceIsStale(digest_request->nonce)) + /* send stale response to the client agent */ + return -2; + + return 0; + case 2: /* partway through checking. */ - return -1; + return -1; + case 3: /* authentication process failed. */ - return -2; + return -2; } + return -2; } @@ -744,25 +838,30 @@ authDigestAddHeader(auth_user_request_t * auth_user_request, HttpReply * rep, in { enum http_hdr_type type; digest_request_h *digest_request; + if (!auth_user_request) - return; + return; + digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); + /* don't add to authentication error pages */ if ((!accel && rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED) - || (accel && rep->sline.status == HTTP_UNAUTHORIZED)) - return; + || (accel && rep->sline.status == HTTP_UNAUTHORIZED)) + return; + type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO; #if WAITING_FOR_TE /* test for http/1.1 transfer chunked encoding */ if (chunkedtest) - return; + return; + #endif if ((digestConfig->authenticate) && authDigestNonceLastRequest(digest_request->nonce)) { - digest_request->flags.authinfo_sent = 1; - debug(29, 9) ("authDigestAddHead: Sending type:%d header: 'nextnonce=\"%s\"", type, authenticateDigestNonceNonceb64(digest_request->nonce)); - httpHeaderPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(digest_request->nonce)); + digest_request->flags.authinfo_sent = 1; + debug(29, 9) ("authDigestAddHead: Sending type:%d header: 'nextnonce=\"%s\"", type, authenticateDigestNonceNonceb64(digest_request->nonce)); + httpHeaderPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(digest_request->nonce)); } } @@ -773,23 +872,29 @@ authDigestAddTrailer(auth_user_request_t * auth_user_request, HttpReply * rep, i { int type; digest_request_h *digest_request; + if (!auth_user_request) - return; + return; + digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); + /* has the header already been send? */ if (digest_request->flags.authinfo_sent) - return; + return; + /* don't add to authentication error pages */ if ((!accel && rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED) - || (accel && rep->sline.status == HTTP_UNAUTHORIZED)) - return; + || (accel && rep->sline.status == HTTP_UNAUTHORIZED)) + return; + type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO; if ((digestConfig->authenticate) && authDigestNonceLastRequest(digest_request->nonce)) { - debug(29, 9) ("authDigestAddTrailer: Sending type:%d header: 'nextnonce=\"%s\"", type, authenticateDigestNonceNonceb64(digest_request->nonce)); - httpTrailerPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(digest_request->nonce)); + debug(29, 9) ("authDigestAddTrailer: Sending type:%d header: 'nextnonce=\"%s\"", type, authenticateDigestNonceNonceb64(digest_request->nonce)); + httpTrailerPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(digest_request->nonce)); } } + #endif /* add the [www-|Proxy-]authenticate header on a 407 or 401 reply */ @@ -799,14 +904,16 @@ authenticateDigestFixHeader(auth_user_request_t * auth_user_request, HttpReply * digest_request_h *digest_request; int stale = 0; digest_nonce_h *nonce = authenticateDigestNonceNew(); + if (auth_user_request && authDigestAuthenticated(auth_user_request) && auth_user_request->scheme_data) { - digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); - stale = authDigestNonceIsStale(digest_request->nonce); + digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); + stale = authDigestNonceIsStale(digest_request->nonce); } + if (digestConfig->authenticate) { - debug(29, 9) ("authenticateFixHeader: Sending type:%d header: 'Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s\n", type, digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); - /* in the future, for WWW auth we may want to support the domain entry */ - httpHeaderPutStrf(&rep->header, type, "Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s", digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); + debug(29, 9) ("authenticateFixHeader: Sending type:%d header: 'Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s\n", type, digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); + /* in the future, for WWW auth we may want to support the domain entry */ + httpHeaderPutStrf(&rep->header, type, "Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s", digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); } } @@ -816,18 +923,21 @@ authenticateDigestUserFree(auth_user_t * auth_user) digest_user_h *digest_user = static_cast < digest_user_h * >(auth_user->scheme_data); dlink_node *link, *tmplink; debug(29, 9) ("authenticateDigestFreeUser: Clearing Digest scheme data\n"); + if (!digest_user) - return; + return; + safe_free(digest_user->username); link = digest_user->nonces.head; + while (link) { - tmplink = link; - link = link->next; - dlinkDelete(tmplink, &digest_user->nonces); - authDigestNoncePurge(static_cast < digest_nonce_h * >(tmplink->data)); - authDigestNonceUnlink(static_cast < digest_nonce_h * >(tmplink->data)); - dlinkNodeDelete(tmplink); + tmplink = link; + link = link->next; + dlinkDelete(tmplink, &digest_user->nonces); + authDigestNoncePurge(static_cast < digest_nonce_h * >(tmplink->data)); + authDigestNonceUnlink(static_cast < digest_nonce_h * >(tmplink->data)); + dlinkNodeDelete(tmplink); } memPoolFree(digest_user_pool, auth_user->scheme_data); @@ -844,25 +954,31 @@ authenticateDigestHandleReply(void *data, char *reply) char *t = NULL; void *cbdata; debug(29, 9) ("authenticateDigestHandleReply: {%s}\n", reply ? reply : ""); + if (reply) { - if ((t = strchr(reply, ' '))) - *t = '\0'; - if (*reply == '\0') - reply = NULL; + if ((t = strchr(reply, ' '))) + *t = '\0'; + + if (*reply == '\0') + reply = NULL; } + assert(r->auth_user_request != NULL); auth_user_request = r->auth_user_request; assert(auth_user_request->scheme_data != NULL); digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); digest_user = static_cast < digest_user_h * >(auth_user_request->auth_user->scheme_data); + if (reply && (strncasecmp(reply, "ERR", 3) == 0)) - digest_user->flags.credentials_ok = 3; + digest_user->flags.credentials_ok = 3; else { - CvtBin(reply, digest_user->HA1); - digest_user->HA1created = 1; + CvtBin(reply, digest_user->HA1); + digest_user->HA1created = 1; } + if (cbdataReferenceValidDone(r->data, &cbdata)) - r->handler(cbdata, NULL); + r->handler(cbdata, NULL); + authenticateStateFree(r); } @@ -872,23 +988,31 @@ static void authDigestInit(authScheme * scheme) { static int init = 0; + if (digestConfig->authenticate) { - authDigestUserSetup(); - authDigestRequestSetup(); - authenticateDigestNonceSetup(); - authdigest_initialised = 1; - if (digestauthenticators == NULL) - digestauthenticators = helperCreate("digestauthenticator"); - digestauthenticators->cmdline = digestConfig->authenticate; - digestauthenticators->n_to_start = digestConfig->authenticateChildren; - digestauthenticators->ipc_type = IPC_STREAM; - helperOpenServers(digestauthenticators); - if (!init) { - cachemgrRegister("digestauthenticator", "Digest User Authenticator Stats", - authenticateDigestStats, 0, 1); - init++; - } - CBDATA_INIT_TYPE(DigestAuthenticateStateData); + authDigestUserSetup(); + authDigestRequestSetup(); + authenticateDigestNonceSetup(); + authdigest_initialised = 1; + + if (digestauthenticators == NULL) + digestauthenticators = helperCreate("digestauthenticator"); + + digestauthenticators->cmdline = digestConfig->authenticate; + + digestauthenticators->n_to_start = digestConfig->authenticateChildren; + + digestauthenticators->ipc_type = IPC_STREAM; + + helperOpenServers(digestauthenticators); + + if (!init) { + cachemgrRegister("digestauthenticator", "Digest User Authenticator Stats", + authenticateDigestStats, 0, 1); + init++; + } + + CBDATA_INIT_TYPE(DigestAuthenticateStateData); } } @@ -898,12 +1022,17 @@ void authDigestFreeConfig(authScheme * scheme) { if (digestConfig == NULL) - return; + return; + assert(digestConfig == scheme->scheme_data); + if (digestConfig->authenticate) - wordlistDestroy(&digestConfig->authenticate); + wordlistDestroy(&digestConfig->authenticate); + safe_free(digestConfig->digestAuthRealm); + xfree(digestConfig); + digestConfig = NULL; } @@ -911,41 +1040,45 @@ static void authDigestParse(authScheme * scheme, int n_configured, char *param_str) { if (scheme->scheme_data == NULL) { - assert(digestConfig == NULL); - /* this is the first param to be found */ - scheme->scheme_data = xmalloc(sizeof(auth_digest_config)); - memset(scheme->scheme_data, 0, sizeof(auth_digest_config)); - digestConfig = static_cast < auth_digest_config * >(scheme->scheme_data); - digestConfig->authenticateChildren = 5; - /* 5 minutes */ - digestConfig->nonceGCInterval = 5 * 60; - /* 30 minutes */ - digestConfig->noncemaxduration = 30 * 60; - /* 50 requests */ - digestConfig->noncemaxuses = 50; - /* strict nonce count behaviour */ - digestConfig->NonceStrictness = 1; + assert(digestConfig == NULL); + /* this is the first param to be found */ + scheme->scheme_data = xmalloc(sizeof(auth_digest_config)); + memset(scheme->scheme_data, 0, sizeof(auth_digest_config)); + digestConfig = static_cast < auth_digest_config * >(scheme->scheme_data); + digestConfig->authenticateChildren = 5; + /* 5 minutes */ + digestConfig->nonceGCInterval = 5 * 60; + /* 30 minutes */ + digestConfig->noncemaxduration = 30 * 60; + /* 50 requests */ + digestConfig->noncemaxuses = 50; + /* strict nonce count behaviour */ + digestConfig->NonceStrictness = 1; } + digestConfig = static_cast < auth_digest_config * >(scheme->scheme_data); + if (strcasecmp(param_str, "program") == 0) { - if (digestConfig->authenticate) - wordlistDestroy(&digestConfig->authenticate); - parse_wordlist(&digestConfig->authenticate); - requirePathnameExists("authparam digest program", digestConfig->authenticate->key); + if (digestConfig->authenticate) + wordlistDestroy(&digestConfig->authenticate); + + parse_wordlist(&digestConfig->authenticate); + + requirePathnameExists("authparam digest program", digestConfig->authenticate->key); } else if (strcasecmp(param_str, "children") == 0) { - parse_int(&digestConfig->authenticateChildren); + parse_int(&digestConfig->authenticateChildren); } else if (strcasecmp(param_str, "realm") == 0) { - parse_eol(&digestConfig->digestAuthRealm); + parse_eol(&digestConfig->digestAuthRealm); } else if (strcasecmp(param_str, "nonce_garbage_interval") == 0) { - parse_time_t(&digestConfig->nonceGCInterval); + parse_time_t(&digestConfig->nonceGCInterval); } else if (strcasecmp(param_str, "nonce_max_duration") == 0) { - parse_time_t(&digestConfig->noncemaxduration); + parse_time_t(&digestConfig->noncemaxduration); } else if (strcasecmp(param_str, "nonce_max_count") == 0) { - parse_int((int *) &digestConfig->noncemaxuses); + parse_int((int *) &digestConfig->noncemaxuses); } else if (strcasecmp(param_str, "nonce_strictness") == 0) { - parse_onoff(&digestConfig->NonceStrictness); + parse_onoff(&digestConfig->NonceStrictness); } else { - debug(28, 0) ("unrecognised digest auth scheme parameter '%s'\n", param_str); + debug(28, 0) ("unrecognised digest auth scheme parameter '%s'\n", param_str); } } @@ -964,25 +1097,32 @@ authDigestNonceUserUnlink(digest_nonce_h * nonce) { digest_user_h *digest_user; dlink_node *link, *tmplink; + if (!nonce) - return; + return; + if (!nonce->auth_user) - return; + return; + digest_user = static_cast < digest_user_h * >(nonce->auth_user->scheme_data); - /* unlink from the user list. Yes we're crossing structures but this is the only + + /* unlink from the user list. Yes we're crossing structures but this is the only * time this code is needed */ link = digest_user->nonces.head; + while (link) { - tmplink = link; - link = link->next; - if (tmplink->data == nonce) { - dlinkDelete(tmplink, &digest_user->nonces); - authDigestNonceUnlink(static_cast < digest_nonce_h * >(tmplink->data)); - dlinkNodeDelete(tmplink); - link = NULL; - } + tmplink = link; + link = link->next; + + if (tmplink->data == nonce) { + dlinkDelete(tmplink, &digest_user->nonces); + authDigestNonceUnlink(static_cast < digest_nonce_h * >(tmplink->data)); + dlinkNodeDelete(tmplink); + link = NULL; + } } + /* this reference to auth_user was not locked because freeeing the auth_user frees * the nonce too. */ @@ -996,22 +1136,33 @@ authDigestUserLinkNonce(auth_user_t * auth_user, digest_nonce_h * nonce) { dlink_node *node; digest_user_h *digest_user; + if (!auth_user || !nonce) - return; + return; + if (!auth_user->scheme_data) - return; + return; + digest_user = static_cast < digest_user_h * >(auth_user->scheme_data); + node = digest_user->nonces.head; + while (node && (node->data != nonce)) - node = node->next; + node = node->next; + if (node) - return; + return; + node = dlinkNodeNew(); + dlinkAddTail(nonce, node, &digest_user->nonces); + authDigestNonceLink(nonce); + /* ping this nonce to this auth user */ assert((nonce->auth_user == NULL) || (nonce->auth_user = auth_user)); - /* we don't lock this reference because removing the auth_user removes the + + /* we don't lock this reference because removing the auth_user removes the * hash too. Of course if that changes we're stuffed so read the code huh? */ nonce->auth_user = auth_user; @@ -1022,8 +1173,10 @@ static char const * authenticateDigestUsername(auth_user_t const *auth_user) { digest_user_h *digest_user = static_cast < digest_user_h * >(auth_user->scheme_data); + if (digest_user) - return digest_user->username; + return digest_user->username; + return NULL; } @@ -1080,91 +1233,130 @@ authenticateDigestDecodeAuth(auth_user_request_t * auth_user_request, const char digest_request = authDigestRequestNew(); /* trim DIGEST from string */ + while (!xisspace(*proxy_auth)) - proxy_auth++; + proxy_auth++; /* Trim leading whitespace before decoding */ while (xisspace(*proxy_auth)) - proxy_auth++; + proxy_auth++; String temp(proxy_auth); + while (strListGetItem(&temp, ',', &item, &ilen, &pos)) { - if ((p = strchr(item, '=')) && (p - item < ilen)) - ilen = p++ - item; - if (!strncmp(item, "username", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - /* quote mark */ - p++; - username = xstrndup(p, strchr(p, '"') + 1 - p); - debug(29, 9) ("authDigestDecodeAuth: Found Username '%s'\n", username); - } else if (!strncmp(item, "realm", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - /* quote mark */ - p++; - digest_request->realm = xstrndup(p, strchr(p, '"') + 1 - p); - debug(29, 9) ("authDigestDecodeAuth: Found realm '%s'\n", digest_request->realm); - } else if (!strncmp(item, "qop", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - if (*p == '\"') - /* quote mark */ - p++; - digest_request->qop = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); - debug(29, 9) ("authDigestDecodeAuth: Found qop '%s'\n", digest_request->qop); - } else if (!strncmp(item, "algorithm", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - if (*p == '\"') - /* quote mark */ - p++; - digest_request->algorithm = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); - debug(29, 9) ("authDigestDecodeAuth: Found algorithm '%s'\n", digest_request->algorithm); - } else if (!strncmp(item, "uri", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - /* quote mark */ - p++; - digest_request->uri = xstrndup(p, strchr(p, '"') + 1 - p); - debug(29, 9) ("authDigestDecodeAuth: Found uri '%s'\n", digest_request->uri); - } else if (!strncmp(item, "nonce", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - /* quote mark */ - p++; - digest_request->nonceb64 = xstrndup(p, strchr(p, '"') + 1 - p); - debug(29, 9) ("authDigestDecodeAuth: Found nonce '%s'\n", digest_request->nonceb64); - } else if (!strncmp(item, "nc", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - xstrncpy(digest_request->nc, p, 9); - debug(29, 9) ("authDigestDecodeAuth: Found noncecount '%s'\n", digest_request->nc); - } else if (!strncmp(item, "cnonce", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - /* quote mark */ - p++; - digest_request->cnonce = xstrndup(p, strchr(p, '"') + 1 - p); - debug(29, 9) ("authDigestDecodeAuth: Found cnonce '%s'\n", digest_request->cnonce); - } else if (!strncmp(item, "response", ilen)) { - /* white space */ - while (xisspace(*p)) - p++; - /* quote mark */ - p++; - digest_request->response = xstrndup(p, strchr(p, '"') + 1 - p); - debug(29, 9) ("authDigestDecodeAuth: Found response '%s'\n", digest_request->response); - } + if ((p = strchr(item, '=')) && (p - item < ilen)) + ilen = p++ - item; + + if (!strncmp(item, "username", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + /* quote mark */ + p++; + + username = xstrndup(p, strchr(p, '"') + 1 - p); + + debug(29, 9) ("authDigestDecodeAuth: Found Username '%s'\n", username); + } else if (!strncmp(item, "realm", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + /* quote mark */ + p++; + + digest_request->realm = xstrndup(p, strchr(p, '"') + 1 - p); + + debug(29, 9) ("authDigestDecodeAuth: Found realm '%s'\n", digest_request->realm); + } else if (!strncmp(item, "qop", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + if (*p == '\"') + /* quote mark */ + p++; + + digest_request->qop = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); + + debug(29, 9) ("authDigestDecodeAuth: Found qop '%s'\n", digest_request->qop); + } else if (!strncmp(item, "algorithm", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + if (*p == '\"') + /* quote mark */ + p++; + + digest_request->algorithm = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); + + debug(29, 9) ("authDigestDecodeAuth: Found algorithm '%s'\n", digest_request->algorithm); + } else if (!strncmp(item, "uri", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + /* quote mark */ + p++; + + digest_request->uri = xstrndup(p, strchr(p, '"') + 1 - p); + + debug(29, 9) ("authDigestDecodeAuth: Found uri '%s'\n", digest_request->uri); + } else if (!strncmp(item, "nonce", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + /* quote mark */ + p++; + + digest_request->nonceb64 = xstrndup(p, strchr(p, '"') + 1 - p); + + debug(29, 9) ("authDigestDecodeAuth: Found nonce '%s'\n", digest_request->nonceb64); + } else if (!strncmp(item, "nc", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + xstrncpy(digest_request->nc, p, 9); + + debug(29, 9) ("authDigestDecodeAuth: Found noncecount '%s'\n", digest_request->nc); + } else if (!strncmp(item, "cnonce", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + /* quote mark */ + p++; + + digest_request->cnonce = xstrndup(p, strchr(p, '"') + 1 - p); + + debug(29, 9) ("authDigestDecodeAuth: Found cnonce '%s'\n", digest_request->cnonce); + } else if (!strncmp(item, "response", ilen)) { + /* white space */ + + while (xisspace(*p)) + p++; + + /* quote mark */ + p++; + + digest_request->response = xstrndup(p, strchr(p, '"') + 1 - p); + + debug(29, 9) ("authDigestDecodeAuth: Found response '%s'\n", digest_request->response); + } } + temp.clean(); @@ -1180,100 +1372,111 @@ authenticateDigestDecodeAuth(auth_user_request_t * auth_user_request, const char */ /* first the NONCE count */ + if (digest_request->cnonce && strlen(digest_request->nc) != 8) { - debug(29, 4) ("authenticateDigestDecode: nonce count length invalid\n"); - authDigestLogUsername(auth_user_request, username); + debug(29, 4) ("authenticateDigestDecode: nonce count length invalid\n"); + authDigestLogUsername(auth_user_request, username); - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + /* now the nonce */ nonce = authenticateDigestNonceFindNonce(digest_request->nonceb64); + if ((nonce == NULL) || !(authDigestNonceIsValid(nonce, digest_request->nc))) { - /* we couldn't find a matching nonce! */ - debug(29, 4) ("authenticateDigestDecode: Unexpected or invalid nonce recieved\n"); - authDigestLogUsername(auth_user_request, username); - - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + /* we couldn't find a matching nonce! */ + debug(29, 4) ("authenticateDigestDecode: Unexpected or invalid nonce recieved\n"); + authDigestLogUsername(auth_user_request, username); + + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + digest_request->nonce = nonce; authDigestNonceLink(nonce); - /* check the qop is what we expected. Note that for compatability with + /* check the qop is what we expected. Note that for compatability with * RFC 2069 we should support a missing qop. Tough. */ + if (!digest_request->qop || strcmp(digest_request->qop, QOP_AUTH)) { - /* we recieved a qop option we didn't send */ - debug(29, 4) ("authenticateDigestDecode: Invalid qop option recieved\n"); - authDigestLogUsername(auth_user_request, username); - - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + /* we recieved a qop option we didn't send */ + debug(29, 4) ("authenticateDigestDecode: Invalid qop option recieved\n"); + authDigestLogUsername(auth_user_request, username); + + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + /* we can't check the URI just yet. We'll check it in the * authenticate phase */ /* is the response the correct length? */ if (!digest_request->response || strlen(digest_request->response) != 32) { - debug(29, 4) ("authenticateDigestDecode: Response length invalid\n"); - authDigestLogUsername(auth_user_request, username); + debug(29, 4) ("authenticateDigestDecode: Response length invalid\n"); + authDigestLogUsername(auth_user_request, username); - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + /* do we have a username ? */ if (!username || username[0] == '\0') { - debug(29, 4) ("authenticateDigestDecode: Empty or not present username\n"); - authDigestLogUsername(auth_user_request, username); + debug(29, 4) ("authenticateDigestDecode: Empty or not present username\n"); + authDigestLogUsername(auth_user_request, username); - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + /* check that we're not being hacked / the username hasn't changed */ if (nonce->auth_user && strcmp(username, nonce->auth_user->username())) { - debug(29, 4) ("authenticateDigestDecode: Username for the nonce does not equal the username for the request\n"); - authDigestLogUsername(auth_user_request, username); + debug(29, 4) ("authenticateDigestDecode: Username for the nonce does not equal the username for the request\n"); + authDigestLogUsername(auth_user_request, username); - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + /* if we got a qop, did we get a cnonce or did we get a cnonce wihtout a qop? */ if ((digest_request->qop && !digest_request->cnonce) - || (!digest_request->qop && digest_request->cnonce)) { - debug(29, 4) ("authenticateDigestDecode: qop without cnonce, or vice versa!\n"); - authDigestLogUsername(auth_user_request, username); - - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + || (!digest_request->qop && digest_request->cnonce)) { + debug(29, 4) ("authenticateDigestDecode: qop without cnonce, or vice versa!\n"); + authDigestLogUsername(auth_user_request, username); + + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + /* check the algorithm is present and supported */ if (!digest_request->algorithm) - digest_request->algorithm = xstrndup("MD5", 4); + digest_request->algorithm = xstrndup("MD5", 4); else if (strcmp(digest_request->algorithm, "MD5") - && strcmp(digest_request->algorithm, "MD5-sess")) { - debug(29, 4) ("authenticateDigestDecode: invalid algorithm specified!\n"); - authDigestLogUsername(auth_user_request, username); - - /* we don't need the scheme specific data anymore */ - authDigestRequestDelete(digest_request); - auth_user_request->scheme_data = NULL; - return; + && strcmp(digest_request->algorithm, "MD5-sess")) { + debug(29, 4) ("authenticateDigestDecode: invalid algorithm specified!\n"); + authDigestLogUsername(auth_user_request, username); + + /* we don't need the scheme specific data anymore */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data = NULL; + return; } + /* the method we'll check at the authenticate step as well */ @@ -1282,46 +1485,51 @@ authenticateDigestDecodeAuth(auth_user_request_t * auth_user_request, const char /* find the user */ if ((auth_user = authDigestUserFindUsername(username)) == NULL) { - /* the user doesn't exist in the username cache yet */ - debug(29, 9) ("authDigestDecodeAuth: Creating new digest user '%s'\n", username); - /* new auth_user */ - auth_user = authenticateAuthUserNew("digest"); - /* new scheme user data */ - digest_user = authDigestUserNew(); - /* save the username */ - digest_user->username = username; - /* link the primary struct in */ - auth_user->scheme_data = digest_user; - /* set the user type */ - auth_user->auth_type = AUTH_DIGEST; - /* this auth_user struct is the one to get added to the - * username cache */ - /* store user in hash's */ - authenticateUserNameCacheAdd(auth_user); - /* - * Add the digest to the user so we can tell if a hacking - * or spoofing attack is taking place. We do this by assuming - * the user agent won't change user name without warning. - */ - authDigestUserLinkNonce(auth_user, nonce); + /* the user doesn't exist in the username cache yet */ + debug(29, 9) ("authDigestDecodeAuth: Creating new digest user '%s'\n", username); + /* new auth_user */ + auth_user = authenticateAuthUserNew("digest"); + /* new scheme user data */ + digest_user = authDigestUserNew(); + /* save the username */ + digest_user->username = username; + /* link the primary struct in */ + auth_user->scheme_data = digest_user; + /* set the user type */ + auth_user->auth_type = AUTH_DIGEST; + /* this auth_user struct is the one to get added to the + * username cache */ + /* store user in hash's */ + authenticateUserNameCacheAdd(auth_user); + /* + * Add the digest to the user so we can tell if a hacking + * or spoofing attack is taking place. We do this by assuming + * the user agent won't change user name without warning. + */ + authDigestUserLinkNonce(auth_user, nonce); } else { - debug(29, 9) ("authDigestDecodeAuth: Found user '%s' in the user cache as '%p'\n", username, auth_user); - digest_user = static_cast < digest_user_h * >(auth_user->scheme_data); - xfree(username); + debug(29, 9) ("authDigestDecodeAuth: Found user '%s' in the user cache as '%p'\n", username, auth_user); + digest_user = static_cast < digest_user_h * >(auth_user->scheme_data); + xfree(username); } + /*link the request and the user */ auth_user_request->auth_user = auth_user; + auth_user_request->scheme_data = digest_request; + /* lock for the request link */ authenticateAuthUserLock(auth_user); + node = dlinkNodeNew(); + dlinkAdd(auth_user_request, node, &auth_user->requests); debug(29, 9) ("username = '%s'\nrealm = '%s'\nqop = '%s'\nalgorithm = '%s'\nuri = '%s'\nnonce = '%s'\nnc = '%s'\ncnonce = '%s'\nresponse = '%s'\ndigestnonce = '%p'\n", - digest_user->username, digest_request->realm, - digest_request->qop, digest_request->algorithm, - digest_request->uri, digest_request->nonceb64, - digest_request->nc, digest_request->cnonce, digest_request->response, nonce); + digest_user->username, digest_request->realm, + digest_request->qop, digest_request->algorithm, + digest_request->uri, digest_request->nonceb64, + digest_request->nc, digest_request->cnonce, digest_request->response, nonce); return; } @@ -1342,11 +1550,13 @@ authenticateDigestStart(auth_user_request_t * auth_user_request, RH * handler, v digest_request = static_cast < digest_request_h * >(auth_user_request->scheme_data); digest_user = static_cast < digest_user_h * >(auth_user_request->auth_user->scheme_data); debug(29, 9) ("authenticateStart: '\"%s\":\"%s\"'\n", digest_user->username, - digest_request->realm); + digest_request->realm); + if (digestConfig->authenticate == NULL) { - handler(data, NULL); - return; + handler(data, NULL); + return; } + r = cbdataAlloc(DigestAuthenticateStateData); r->handler = handler; r->data = cbdataReference(data); diff --git a/src/auth/digest/auth_digest.h b/src/auth/digest/auth_digest.h index ac89255429..06976f8ae8 100644 --- a/src/auth/digest/auth_digest.h +++ b/src/auth/digest/auth_digest.h @@ -8,7 +8,10 @@ #include "rfc2617.h" /* Generic */ -class DigestAuthenticateStateData { + +class DigestAuthenticateStateData +{ + public: void *data; auth_user_request_t *auth_user_request; @@ -16,24 +19,35 @@ public: }; typedef struct _digest_request_h digest_request_h; + typedef struct _digest_user_h digest_user_h; + typedef struct _digest_nonce_data digest_nonce_data; typedef struct _digest_nonce_h digest_nonce_h; -struct _digest_user_h { +struct _digest_user_h +{ char *username; HASH HA1; int HA1created; - struct { - unsigned int credentials_ok:2; /*0=unchecked,1=ok,2=failed */ - } flags; + + struct + { + +unsigned int credentials_ok: + 2; /*0=unchecked,1=ok,2=failed */ + } + + flags; /* what nonces have been allocated to this user */ dlink_list nonces; }; /* the digest_request structure is what follows the http_request around */ -struct _digest_request_h { + +struct _digest_request_h +{ char *nonceb64; /* "dcd98b7102dd2f0e8b11d0f600bfb0c093" */ char *cnonce; /* "0a4f113b" */ char *realm; /* = "testrealm@host.com" */ @@ -44,14 +58,22 @@ struct _digest_request_h { char *qop; /* = "auth" */ char *uri; /* = "/dir/index.html" */ char *response; - struct { - unsigned int authinfo_sent:1; - } flags; + + struct + { + +unsigned int authinfo_sent: + 1; + } + + flags; digest_nonce_h *nonce; }; /* data to be encoded into the nonce's b64 representation */ -struct _digest_nonce_data { + +struct _digest_nonce_data +{ time_t creationtime; /* in memory address of the nonce struct (similar purpose to an ETag) */ digest_nonce_h *self; @@ -59,7 +81,9 @@ struct _digest_nonce_data { }; /* the nonce structure we'll pass around */ -struct _digest_nonce_h : public hash_link { + +struct _digest_nonce_h : public hash_link +{ digest_nonce_data noncedata; /* number of uses we've seen of this nonce */ unsigned long nc; @@ -68,14 +92,24 @@ struct _digest_nonce_h : public hash_link { /* the auth_user this nonce has been tied to */ auth_user_t *auth_user; /* has this nonce been invalidated ? */ - struct { - unsigned int valid:1; - unsigned int incache:1; - } flags; + + struct + { + +unsigned int valid: + 1; + +unsigned int incache: + 1; + } + + flags; }; /* configuration runtime data */ -struct _auth_digest_config { + +struct _auth_digest_config +{ int authenticateChildren; char *digestAuthRealm; wordlist *authenticate; diff --git a/src/auth/ntlm/auth_ntlm.cc b/src/auth/ntlm/auth_ntlm.cc index 045fe5512c..c1ad40514d 100644 --- a/src/auth/ntlm/auth_ntlm.cc +++ b/src/auth/ntlm/auth_ntlm.cc @@ -1,6 +1,6 @@ /* - * $Id: auth_ntlm.cc,v 1.28 2003/02/06 09:57:40 robertc Exp $ + * $Id: auth_ntlm.cc,v 1.29 2003/02/21 22:50:28 robertc Exp $ * * DEBUG: section 29 NTLM Authenticator * AUTHOR: Robert Collins @@ -103,24 +103,34 @@ static void authNTLMDone(void) { debug(29, 2) ("authNTLMDone: shutting down NTLM authentication.\n"); + if (ntlmauthenticators) - helperStatefulShutdown(ntlmauthenticators); + helperStatefulShutdown(ntlmauthenticators); + authntlm_initialised = 0; + if (!shutting_down) - return; + return; + if (ntlmauthenticators) - helperStatefulFree(ntlmauthenticators); + helperStatefulFree(ntlmauthenticators); + ntlmauthenticators = NULL; + #if DEBUGSHUTDOWN + if (ntlm_helper_state_pool) { - memPoolDestroy(&ntlm_helper_state_pool); + memPoolDestroy(&ntlm_helper_state_pool); } + if (ntlm_request_pool) { - memPoolDestroy(&ntlm_request_pool); + memPoolDestroy(&ntlm_request_pool); } + if (ntlm_user_pool) { - memPoolDestroy(&ntlm_user_pool); + memPoolDestroy(&ntlm_user_pool); } + #endif debug(29, 2) ("authNTLMDone: NTLM authentication Shutdown.\n"); } @@ -130,11 +140,15 @@ static void authNTLMFreeConfig(authScheme * scheme) { if (ntlmConfig == NULL) - return; + return; + assert(ntlmConfig == scheme->scheme_data); + if (ntlmConfig->authenticate) - wordlistDestroy(&ntlmConfig->authenticate); + wordlistDestroy(&ntlmConfig->authenticate); + xfree(ntlmConfig); + ntlmConfig = NULL; } @@ -144,14 +158,16 @@ authNTLMCfgDump(StoreEntry * entry, const char *name, authScheme * scheme) auth_ntlm_config *config = static_cast(scheme->scheme_data); wordlist *list = config->authenticate; storeAppendPrintf(entry, "%s %s", name, "ntlm"); + while (list != NULL) { - storeAppendPrintf(entry, " %s", list->key); - list = list->next; + storeAppendPrintf(entry, " %s", list->key); + list = list->next; } + storeAppendPrintf(entry, "\n%s %s children %d\n%s %s max_challenge_reuses %d\n%s %s max_challenge_lifetime %d seconds\n", - name, "ntlm", config->authenticateChildren, - name, "ntlm", config->challengeuses, - name, "ntlm", (int) config->challengelifetime); + name, "ntlm", config->authenticateChildren, + name, "ntlm", config->challengeuses, + name, "ntlm", (int) config->challengelifetime); } @@ -159,30 +175,35 @@ static void authNTLMParse(authScheme * scheme, int n_configured, char *param_str) { if (scheme->scheme_data == NULL) { - assert(ntlmConfig == NULL); - /* this is the first param to be found */ - scheme->scheme_data = xmalloc(sizeof(auth_ntlm_config)); - memset(scheme->scheme_data, 0, sizeof(auth_ntlm_config)); - ntlmConfig = static_cast(scheme->scheme_data); - ntlmConfig->authenticateChildren = 5; - ntlmConfig->challengeuses = 0; - ntlmConfig->challengelifetime = 60; + assert(ntlmConfig == NULL); + /* this is the first param to be found */ + scheme->scheme_data = xmalloc(sizeof(auth_ntlm_config)); + memset(scheme->scheme_data, 0, sizeof(auth_ntlm_config)); + ntlmConfig = static_cast(scheme->scheme_data); + ntlmConfig->authenticateChildren = 5; + ntlmConfig->challengeuses = 0; + ntlmConfig->challengelifetime = 60; } + ntlmConfig = static_cast(scheme->scheme_data); + if (strcasecmp(param_str, "program") == 0) { - if (ntlmConfig->authenticate) - wordlistDestroy(&ntlmConfig->authenticate); - parse_wordlist(&ntlmConfig->authenticate); - requirePathnameExists("authparam ntlm program", ntlmConfig->authenticate->key); + if (ntlmConfig->authenticate) + wordlistDestroy(&ntlmConfig->authenticate); + + parse_wordlist(&ntlmConfig->authenticate); + + requirePathnameExists("authparam ntlm program", ntlmConfig->authenticate->key); } else if (strcasecmp(param_str, "children") == 0) { - parse_int(&ntlmConfig->authenticateChildren); + parse_int(&ntlmConfig->authenticateChildren); } else if (strcasecmp(param_str, "max_challenge_reuses") == 0) { - parse_int(&ntlmConfig->challengeuses); + parse_int(&ntlmConfig->challengeuses); } else if (strcasecmp(param_str, "max_challenge_lifetime") == 0) { - parse_time_t(&ntlmConfig->challengelifetime); + parse_time_t(&ntlmConfig->challengelifetime); } else { - debug(28, 0) ("unrecognised ntlm auth scheme parameter '%s'\n", param_str); + debug(28, 0) ("unrecognised ntlm auth scheme parameter '%s'\n", param_str); } + /* * disable client side request pipelining. There is a race with * NTLM when the client sends a second request on an NTLM @@ -192,7 +213,7 @@ authNTLMParse(authScheme * scheme, int n_configured, char *param_str) * test, but that can wait for the modular parser to be integrated. */ if (ntlmConfig->authenticate) - Config.onoff.pipeline_prefetch = 0; + Config.onoff.pipeline_prefetch = 0; } @@ -227,43 +248,61 @@ static void authNTLMInit(authScheme * scheme) { static int ntlminit = 0; + if (ntlmConfig->authenticate) { - if (!ntlm_helper_state_pool) - ntlm_helper_state_pool = memPoolCreate("NTLM Helper State data", sizeof(ntlm_helper_state_t)); - if (!ntlm_user_pool) - ntlm_user_pool = memPoolCreate("NTLM Scheme User Data", sizeof(ntlm_user_t)); - if (!ntlm_request_pool) - ntlm_request_pool = memPoolCreate("NTLM Scheme Request Data", sizeof(ntlm_request_t)); - if (!ntlm_user_hash_pool) - ntlm_user_hash_pool = memPoolCreate("NTLM Header Hash Data", sizeof(struct ProxyAuthCachePointer)); - authntlm_initialised = 1; - if (ntlmauthenticators == NULL) - ntlmauthenticators = helperStatefulCreate("ntlmauthenticator"); - if (!proxy_auth_cache) - proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); - assert(proxy_auth_cache); - ntlmauthenticators->cmdline = ntlmConfig->authenticate; - ntlmauthenticators->n_to_start = ntlmConfig->authenticateChildren; - ntlmauthenticators->ipc_type = IPC_STREAM; - ntlmauthenticators->datapool = ntlm_helper_state_pool; - ntlmauthenticators->IsAvailable = authenticateNTLMHelperServerAvailable; - ntlmauthenticators->OnEmptyQueue = authenticateNTLMHelperServerOnEmpty; - helperStatefulOpenServers(ntlmauthenticators); - /* - * TODO: In here send the initial YR to preinitialise the - * challenge cache - */ - /* - * Think about this... currently we ask when the challenge - * is needed. Better? - */ - if (!ntlminit) { - cachemgrRegister("ntlmauthenticator", - "NTLM User Authenticator Stats", - authenticateNTLMStats, 0, 1); - ntlminit++; - } - CBDATA_INIT_TYPE(authenticateStateData); + if (!ntlm_helper_state_pool) + ntlm_helper_state_pool = memPoolCreate("NTLM Helper State data", sizeof(ntlm_helper_state_t)); + + if (!ntlm_user_pool) + ntlm_user_pool = memPoolCreate("NTLM Scheme User Data", sizeof(ntlm_user_t)); + + if (!ntlm_request_pool) + ntlm_request_pool = memPoolCreate("NTLM Scheme Request Data", sizeof(ntlm_request_t)); + + if (!ntlm_user_hash_pool) + + ntlm_user_hash_pool = memPoolCreate("NTLM Header Hash Data", sizeof(struct ProxyAuthCachePointer)); + + authntlm_initialised = 1; + + if (ntlmauthenticators == NULL) + ntlmauthenticators = helperStatefulCreate("ntlmauthenticator"); + + if (!proxy_auth_cache) + proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); + + assert(proxy_auth_cache); + + ntlmauthenticators->cmdline = ntlmConfig->authenticate; + + ntlmauthenticators->n_to_start = ntlmConfig->authenticateChildren; + + ntlmauthenticators->ipc_type = IPC_STREAM; + + ntlmauthenticators->datapool = ntlm_helper_state_pool; + + ntlmauthenticators->IsAvailable = authenticateNTLMHelperServerAvailable; + + ntlmauthenticators->OnEmptyQueue = authenticateNTLMHelperServerOnEmpty; + + helperStatefulOpenServers(ntlmauthenticators); + + /* + * TODO: In here send the initial YR to preinitialise the + * challenge cache + */ + /* + * Think about this... currently we ask when the challenge + * is needed. Better? + */ + if (!ntlminit) { + cachemgrRegister("ntlmauthenticator", + "NTLM User Authenticator Stats", + authenticateNTLMStats, 0, 1); + ntlminit++; + } + + CBDATA_INIT_TYPE(authenticateStateData); } } @@ -278,9 +317,10 @@ static int authNTLMConfigured() { if ((ntlmConfig != NULL) && (ntlmConfig->authenticate != NULL) && (ntlmConfig->authenticateChildren != 0) && (ntlmConfig->challengeuses > -1) && (ntlmConfig->challengelifetime > -1)) { - debug(29, 9) ("authNTLMConfigured: returning configured\n"); - return 1; + debug(29, 9) ("authNTLMConfigured: returning configured\n"); + return 1; } + debug(29, 9) ("authNTLMConfigured: returning unconfigured\n"); return 0; } @@ -292,20 +332,28 @@ authenticateNTLMDirection(auth_user_request_t * auth_user_request) { ntlm_request_t *ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); /* null auth_user is checked for by authenticateDirection */ + switch (ntlm_request->auth_state) { + case AUTHENTICATE_STATE_NONE: /* no progress at all. */ - debug(29, 1) ("authenticateNTLMDirection: called before NTLM Authenticate!. Report a bug to squid-dev. au %p\n", auth_user_request); - /* fall thru */ + debug(29, 1) ("authenticateNTLMDirection: called before NTLM Authenticate!. Report a bug to squid-dev. au %p\n", auth_user_request); + /* fall thru */ + case AUTHENTICATE_STATE_FAILED: - return -2; + return -2; + case AUTHENTICATE_STATE_NEGOTIATE: /* send to helper */ + case AUTHENTICATE_STATE_RESPONSE: /*send to helper */ - return -1; + return -1; + case AUTHENTICATE_STATE_CHALLENGE: /* send to client */ - return 1; + return 1; + case AUTHENTICATE_STATE_DONE: /* do nothing.. */ - return 0; + return 0; } + return -2; } @@ -318,40 +366,47 @@ static void authenticateNTLMFixErrorHeader(auth_user_request_t * auth_user_request, HttpReply * rep, http_hdr_type type, request_t * request) { ntlm_request_t *ntlm_request; + if (ntlmConfig->authenticate) { - /* New request, no user details */ - if (auth_user_request == NULL) { - debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM'\n", type); - httpHeaderPutStrf(&rep->header, type, "NTLM"); - /* drop the connection */ - httpHeaderDelByName(&rep->header, "keep-alive"); - /* NTLM has problems if the initial connection is not dropped - * I haven't checked the RFC compliance of this hack - RBCollins */ - request->flags.proxy_keepalive = 0; - } else { - ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); - switch (ntlm_request->auth_state) { - case AUTHENTICATE_STATE_NONE: - case AUTHENTICATE_STATE_FAILED: - debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM'\n", type); - httpHeaderPutStrf(&rep->header, type, "NTLM"); - /* drop the connection */ - httpHeaderDelByName(&rep->header, "keep-alive"); - /* NTLM has problems if the initial connection is not dropped - * I haven't checked the RFC compliance of this hack - RBCollins */ - request->flags.proxy_keepalive = 0; - break; - case AUTHENTICATE_STATE_CHALLENGE: - /* we are 'waiting' for a response */ - /* pass the challenge to the client */ - debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM %s'\n", type, ntlm_request->authchallenge); - httpHeaderPutStrf(&rep->header, type, "NTLM %s", ntlm_request->authchallenge); - break; - default: - debug(29, 0) ("authenticateNTLMFixErrorHeader: state %d.\n", ntlm_request->auth_state); - fatal("unexpected state in AuthenticateNTLMFixErrorHeader.\n"); - } - } + /* New request, no user details */ + + if (auth_user_request == NULL) { + debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM'\n", type); + httpHeaderPutStrf(&rep->header, type, "NTLM"); + /* drop the connection */ + httpHeaderDelByName(&rep->header, "keep-alive"); + /* NTLM has problems if the initial connection is not dropped + * I haven't checked the RFC compliance of this hack - RBCollins */ + request->flags.proxy_keepalive = 0; + } else { + ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + + switch (ntlm_request->auth_state) { + + case AUTHENTICATE_STATE_NONE: + + case AUTHENTICATE_STATE_FAILED: + debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM'\n", type); + httpHeaderPutStrf(&rep->header, type, "NTLM"); + /* drop the connection */ + httpHeaderDelByName(&rep->header, "keep-alive"); + /* NTLM has problems if the initial connection is not dropped + * I haven't checked the RFC compliance of this hack - RBCollins */ + request->flags.proxy_keepalive = 0; + break; + + case AUTHENTICATE_STATE_CHALLENGE: + /* we are 'waiting' for a response */ + /* pass the challenge to the client */ + debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM %s'\n", type, ntlm_request->authchallenge); + httpHeaderPutStrf(&rep->header, type, "NTLM %s", ntlm_request->authchallenge); + break; + + default: + debug(29, 0) ("authenticateNTLMFixErrorHeader: state %d.\n", ntlm_request->auth_state); + fatal("unexpected state in AuthenticateNTLMFixErrorHeader.\n"); + } + } } } @@ -359,18 +414,23 @@ static void authNTLMRequestFree(ntlm_request_t * ntlm_request) { if (!ntlm_request) - return; + return; + if (ntlm_request->ntlmnegotiate) - xfree(ntlm_request->ntlmnegotiate); + xfree(ntlm_request->ntlmnegotiate); + if (ntlm_request->authchallenge) - xfree(ntlm_request->authchallenge); + xfree(ntlm_request->authchallenge); + if (ntlm_request->ntlmauthenticate) - xfree(ntlm_request->ntlmauthenticate); + xfree(ntlm_request->ntlmauthenticate); + if (ntlm_request->authserver != NULL && ntlm_request->authserver_deferred) { - debug(29, 9) ("authenticateNTLMRequestFree: releasing server '%p'\n", ntlm_request->authserver); - helperStatefulReleaseServer(ntlm_request->authserver); - ntlm_request->authserver = NULL; + debug(29, 9) ("authenticateNTLMRequestFree: releasing server '%p'\n", ntlm_request->authserver); + helperStatefulReleaseServer(ntlm_request->authserver); + ntlm_request->authserver = NULL; } + memPoolFree(ntlm_request_pool, ntlm_request); } @@ -378,7 +438,7 @@ static void authNTLMAURequestFree(auth_user_request_t * auth_user_request) { if (auth_user_request->scheme_data) - authNTLMRequestFree(static_cast< ntlm_request_t *>(auth_user_request->scheme_data)); + authNTLMRequestFree(static_cast< ntlm_request_t *>(auth_user_request->scheme_data)); auth_user_request->scheme_data = NULL; } @@ -390,21 +450,25 @@ authenticateNTLMFreeUser(auth_user_t * auth_user) ProxyAuthCachePointer *proxy_auth_hash; debug(29, 5) ("authenticateNTLMFreeUser: Clearing NTLM scheme data\n"); + if (ntlm_user->username) - xfree(ntlm_user->username); + xfree(ntlm_user->username); + /* were they linked in by one or more proxy-authenticate headers */ link = ntlm_user->proxy_auth_list.head; + while (link) { - debug(29, 9) ("authenticateFreeProxyAuthUser: removing proxy_auth hash entry '%p'\n", link->data); - proxy_auth_hash = static_cast(link->data); - tmplink = link; - link = link->next; - dlinkDelete(tmplink, &ntlm_user->proxy_auth_list); - hash_remove_link(proxy_auth_cache, (hash_link *) proxy_auth_hash); - /* free the key (usually the proxy_auth header) */ - xfree(proxy_auth_hash->key); - memPoolFree(ntlm_user_hash_pool, proxy_auth_hash); + debug(29, 9) ("authenticateFreeProxyAuthUser: removing proxy_auth hash entry '%p'\n", link->data); + proxy_auth_hash = static_cast(link->data); + tmplink = link; + link = link->next; + dlinkDelete(tmplink, &ntlm_user->proxy_auth_list); + hash_remove_link(proxy_auth_cache, (hash_link *) proxy_auth_hash); + /* free the key (usually the proxy_auth header) */ + xfree(proxy_auth_hash->key); + memPoolFree(ntlm_user_hash_pool, proxy_auth_hash); } + memPoolFree(ntlm_user_pool, ntlm_user); auth_user->scheme_data = NULL; } @@ -418,15 +482,21 @@ authenticateNTLMHandleplaceholder(void *data, void *lastserver, char *reply) assert(reply == NULL); assert(r->auth_user_request); /* standard callback stuff */ + if (!cbdataReferenceValid(r->data)) { - debug(29, 1) ("AuthenticateNTLMHandlePlacheholder: invalid callback data.\n"); - return result; + debug(29, 1) ("AuthenticateNTLMHandlePlacheholder: invalid callback data.\n"); + return result; } + /* call authenticateNTLMStart to retry this request */ debug(29, 9) ("authenticateNTLMHandleplaceholder: calling authenticateNTLMStart\n"); + authenticateNTLMStart(r->auth_user_request, r->handler, r->data); + cbdataReferenceDone(r->data); + authenticateStateFree(r); + return result; } @@ -442,172 +512,199 @@ authenticateNTLMHandleReply(void *data, void *lastserver, char *reply) ntlm_user_t *ntlm_user; ntlm_request_t *ntlm_request; debug(29, 9) ("authenticateNTLMHandleReply: Helper: '%p' {%s}\n", lastserver, reply ? reply : ""); + if (!cbdataReferenceValid(r->data)) { - debug(29, 1) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%p'.\n", lastserver); - cbdataReferenceDone(r->data); - authenticateStateFree(r); - debug(29, 9) ("NTLM HandleReply, telling stateful helper : %d\n", S_HELPER_RELEASE); - return S_HELPER_RELEASE; + debug(29, 1) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%p'.\n", lastserver); + cbdataReferenceDone(r->data); + authenticateStateFree(r); + debug(29, 9) ("NTLM HandleReply, telling stateful helper : %d\n", S_HELPER_RELEASE); + return S_HELPER_RELEASE; } + if (!reply) { - /* - * TODO: this occurs when a helper crashes. We should clean - * up that helpers resources and queued requests. - */ - fatal("authenticateNTLMHandleReply: called with no result string\n"); + /* + * TODO: this occurs when a helper crashes. We should clean + * up that helpers resources and queued requests. + */ + fatal("authenticateNTLMHandleReply: called with no result string\n"); } + /* seperate out the useful data */ if (strncasecmp(reply, "TT ", 3) == 0) { - reply += 3; - /* we have been given a Challenge */ - /* we should check we weren't given an empty challenge */ - /* copy the challenge to the state data */ - helperstate = static_cast(helperStatefulServerGetData(static_cast(lastserver))); - if (helperstate == NULL) - fatal("lost NTLM helper state! quitting\n"); - helperstate->challenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); - helperstate->challengeuses = 0; - helperstate->renewed = squid_curtime; - /* and we satisfy the request that happended on the refresh boundary */ - /* note this code is now in two places FIXME */ - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); - assert(ntlm_request != NULL); - result = S_HELPER_DEFER; - /* reserve the server for future authentication */ - ntlm_request->authserver_deferred = 1; - debug(29, 9) ("authenticateNTLMHandleReply: helper '%p'\n", lastserver); - assert(ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE); - ntlm_request->authserver = static_cast(lastserver); - ntlm_request->authchallenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); + reply += 3; + /* we have been given a Challenge */ + /* we should check we weren't given an empty challenge */ + /* copy the challenge to the state data */ + helperstate = static_cast(helperStatefulServerGetData(static_cast(lastserver))); + + if (helperstate == NULL) + fatal("lost NTLM helper state! quitting\n"); + + helperstate->challenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); + + helperstate->challengeuses = 0; + + helperstate->renewed = squid_curtime; + + /* and we satisfy the request that happended on the refresh boundary */ + /* note this code is now in two places FIXME */ + assert(r->auth_user_request != NULL); + + assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); + + auth_user_request = r->auth_user_request; + + ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + + assert(ntlm_request != NULL); + + result = S_HELPER_DEFER; + + /* reserve the server for future authentication */ + ntlm_request->authserver_deferred = 1; + + debug(29, 9) ("authenticateNTLMHandleReply: helper '%p'\n", lastserver); + + assert(ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE); + + ntlm_request->authserver = static_cast(lastserver); + + ntlm_request->authchallenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); } else if (strncasecmp(reply, "AF ", 3) == 0) { - /* we're finished, release the helper */ - reply += 3; - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - assert(auth_user_request->scheme_data != NULL); - ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); - auth_user = auth_user_request->auth_user; - ntlm_user = static_cast(auth_user_request->auth_user->scheme_data); - assert(ntlm_user != NULL); - result = S_HELPER_RELEASE; - /* we only expect OK when finishing the handshake */ - assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); - ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); - ntlm_request->authserver = NULL; + /* we're finished, release the helper */ + reply += 3; + assert(r->auth_user_request != NULL); + assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); + auth_user_request = r->auth_user_request; + assert(auth_user_request->scheme_data != NULL); + ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + auth_user = auth_user_request->auth_user; + ntlm_user = static_cast(auth_user_request->auth_user->scheme_data); + assert(ntlm_user != NULL); + result = S_HELPER_RELEASE; + /* we only expect OK when finishing the handshake */ + assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); + ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); + ntlm_request->authserver = NULL; #ifdef NTLM_FAIL_OPEN + } else if (strncasecmp(reply, "LD ", 3) == 0) { - /* This is a variant of BH, which rather than deny access - * allows the user through. The helper is starved and then refreshed - * via YR, all pending authentications are likely to fail also. - * It is meant for those helpers which occasionally fail for - * no reason at all (casus belli, NTLMSSP helper on NT domain, - * failing about 1 auth out of 1k. - * The code is a merge from the BH case with snippets of the AF - * case */ - /* AF code: mark user as authenticated */ - reply += 3; - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - assert(auth_user_request->scheme_data != NULL); - ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); - auth_user = auth_user_request->auth_user; - ntlm_user = static_cast(auth_user_request->auth_user->scheme_data); - assert(ntlm_user != NULL); - result = S_HELPER_RELEASE; - /* we only expect LD when finishing the handshake */ - assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); - ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); - helperstate = helperStatefulServerGetData(ntlm_request->authserver); - ntlm_request->authserver = NULL; - /* BH code: mark helper as broken */ - /* mark it for starving */ - helperstate->starve = 1; + /* This is a variant of BH, which rather than deny access + * allows the user through. The helper is starved and then refreshed + * via YR, all pending authentications are likely to fail also. + * It is meant for those helpers which occasionally fail for + * no reason at all (casus belli, NTLMSSP helper on NT domain, + * failing about 1 auth out of 1k. + * The code is a merge from the BH case with snippets of the AF + * case */ + /* AF code: mark user as authenticated */ + reply += 3; + assert(r->auth_user_request != NULL); + assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); + auth_user_request = r->auth_user_request; + assert(auth_user_request->scheme_data != NULL); + ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + auth_user = auth_user_request->auth_user; + ntlm_user = static_cast(auth_user_request->auth_user->scheme_data); + assert(ntlm_user != NULL); + result = S_HELPER_RELEASE; + /* we only expect LD when finishing the handshake */ + assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); + ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); + helperstate = helperStatefulServerGetData(ntlm_request->authserver); + ntlm_request->authserver = NULL; + /* BH code: mark helper as broken */ + /* mark it for starving */ + helperstate->starve = 1; #endif + } else if (strncasecmp(reply, "NA ", 3) == 0) { - /* TODO: only work with auth_user here if it exists */ - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - auth_user = auth_user_request->auth_user; - assert(auth_user != NULL); - ntlm_user = static_cast(auth_user->scheme_data); - ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); - assert((ntlm_user != NULL) && (ntlm_request != NULL)); - /* todo: action of Negotiate state on error */ - result = S_HELPER_RELEASE; /*some error has occured. no more requests */ - ntlm_request->authserver = NULL; - debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); - ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; - if ((t = strchr(reply, ' '))) /* strip after a space */ - *t = '\0'; + /* TODO: only work with auth_user here if it exists */ + assert(r->auth_user_request != NULL); + assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); + auth_user_request = r->auth_user_request; + auth_user = auth_user_request->auth_user; + assert(auth_user != NULL); + ntlm_user = static_cast(auth_user->scheme_data); + ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + assert((ntlm_user != NULL) && (ntlm_request != NULL)); + /* todo: action of Negotiate state on error */ + result = S_HELPER_RELEASE; /*some error has occured. no more requests */ + ntlm_request->authserver = NULL; + debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); + ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; + + if ((t = strchr(reply, ' '))) /* strip after a space */ + *t = '\0'; } else if (strncasecmp(reply, "NA", 2) == 0) { - /* NTLM Helper protocol violation! */ - fatal("NTLM Helper returned invalid response \"NA\" - a error message MUST be attached\n"); + /* NTLM Helper protocol violation! */ + fatal("NTLM Helper returned invalid response \"NA\" - a error message MUST be attached\n"); } else if (strncasecmp(reply, "BH ", 3) == 0) { - /* TODO kick off a refresh process. This can occur after a YR or after - * a KK. If after a YR release the helper and resubmit the request via - * Authenticate NTLM start. - * If after a KK deny the user's request w/ 407 and mark the helper as - * Needing YR. */ - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - auth_user = auth_user_request->auth_user; - assert(auth_user != NULL); - ntlm_user = static_cast(auth_user->scheme_data); - ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); - assert((ntlm_user != NULL) && (ntlm_request != NULL)); - result = S_HELPER_RELEASE; /*some error has occured. no more requests for - * this helper */ - assert(ntlm_request->authserver ? ntlm_request->authserver == lastserver : 1); - helperstate = static_cast(helperStatefulServerGetData(ntlm_request->authserver)); - ntlm_request->authserver = NULL; - if (ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE) { - /* The helper broke on YR. It automatically - * resets */ - debug(29, 1) ("authenticateNTLMHandleReply: Error obtaining challenge from helper: %p. Error returned '%s'\n", lastserver, reply); - /* mark it for starving */ - helperstate->starve = 1; - /* resubmit the request. This helper is currently busy, so we will get - * a different one. Our auth state stays the same */ - authenticateNTLMStart(auth_user_request, r->handler, r->data); - /* don't call the callback */ - cbdataReferenceDone(r->data); - authenticateStateFree(r); - debug(29, 9) ("NTLM HandleReply, telling stateful helper : %d\n", result); - return result; - } - /* the helper broke on a KK */ - /* first the standard KK stuff */ - debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); - if ((t = strchr(reply, ' '))) /* strip after a space */ - *t = '\0'; - /* now we mark the helper for resetting. */ - helperstate->starve = 1; - ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; + /* TODO kick off a refresh process. This can occur after a YR or after + * a KK. If after a YR release the helper and resubmit the request via + * Authenticate NTLM start. + * If after a KK deny the user's request w/ 407 and mark the helper as + * Needing YR. */ + assert(r->auth_user_request != NULL); + assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); + auth_user_request = r->auth_user_request; + auth_user = auth_user_request->auth_user; + assert(auth_user != NULL); + ntlm_user = static_cast(auth_user->scheme_data); + ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + assert((ntlm_user != NULL) && (ntlm_request != NULL)); + result = S_HELPER_RELEASE; /*some error has occured. no more requests for + * this helper */ + assert(ntlm_request->authserver ? ntlm_request->authserver == lastserver : 1); + helperstate = static_cast(helperStatefulServerGetData(ntlm_request->authserver)); + ntlm_request->authserver = NULL; + + if (ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE) { + /* The helper broke on YR. It automatically + * resets */ + debug(29, 1) ("authenticateNTLMHandleReply: Error obtaining challenge from helper: %p. Error returned '%s'\n", lastserver, reply); + /* mark it for starving */ + helperstate->starve = 1; + /* resubmit the request. This helper is currently busy, so we will get + * a different one. Our auth state stays the same */ + authenticateNTLMStart(auth_user_request, r->handler, r->data); + /* don't call the callback */ + cbdataReferenceDone(r->data); + authenticateStateFree(r); + debug(29, 9) ("NTLM HandleReply, telling stateful helper : %d\n", result); + return result; + } + + /* the helper broke on a KK */ + /* first the standard KK stuff */ + debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); + + if ((t = strchr(reply, ' '))) /* strip after a space */ + *t = '\0'; + + /* now we mark the helper for resetting. */ + helperstate->starve = 1; + + ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; } else { - /* TODO: only work with auth_user here if it exists */ - /* TODO: take the request state into consideration */ - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - auth_user = auth_user_request->auth_user; - assert(auth_user != NULL); - ntlm_user = static_cast(auth_user->scheme_data); - ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); - assert((ntlm_user != NULL) && (ntlm_request != NULL)); - debug(29, 1) ("authenticateNTLMHandleReply: *** Unsupported helper response ***, '%s'\n", reply); - /* **** NOTE THIS CODE IS EFFECTIVELY UNTESTED **** */ - /* restart the authentication process */ - ntlm_request->auth_state = AUTHENTICATE_STATE_NONE; - assert(ntlm_request->authserver ? ntlm_request->authserver == lastserver : 1); - ntlm_request->authserver = NULL; + /* TODO: only work with auth_user here if it exists */ + /* TODO: take the request state into consideration */ + assert(r->auth_user_request != NULL); + assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); + auth_user_request = r->auth_user_request; + auth_user = auth_user_request->auth_user; + assert(auth_user != NULL); + ntlm_user = static_cast(auth_user->scheme_data); + ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + assert((ntlm_user != NULL) && (ntlm_request != NULL)); + debug(29, 1) ("authenticateNTLMHandleReply: *** Unsupported helper response ***, '%s'\n", reply); + /* **** NOTE THIS CODE IS EFFECTIVELY UNTESTED **** */ + /* restart the authentication process */ + ntlm_request->auth_state = AUTHENTICATE_STATE_NONE; + assert(ntlm_request->authserver ? ntlm_request->authserver == lastserver : 1); + ntlm_request->authserver = NULL; } + r->handler(r->data, NULL); cbdataReferenceDone(r->data); authenticateStateFree(r); @@ -627,8 +724,10 @@ static int authenticateNTLMValidChallenge(ntlm_helper_state_t * helperstate) { debug(29, 9) ("authenticateNTLMValidChallenge: Challenge is %s\n", helperstate->challenge ? "Valid" : "Invalid"); + if (helperstate->challenge == NULL) - return 0; + return 0; + return 1; } @@ -639,20 +738,24 @@ authenticateNTLMChangeChallenge_p(ntlm_helper_state_t * helperstate) /* don't check for invalid challenges just for expiry choices */ /* this is needed because we have to starve the helper until all old * requests have been satisfied */ + if (!helperstate->renewed) { - /* first use, no challenge has been set. Without this check, it will - * loop forever */ - debug(29, 5) ("authenticateNTLMChangeChallenge_p: first use\n"); - return 0; + /* first use, no challenge has been set. Without this check, it will + * loop forever */ + debug(29, 5) ("authenticateNTLMChangeChallenge_p: first use\n"); + return 0; } + if (helperstate->challengeuses > ntlmConfig->challengeuses) { - debug(29, 4) ("authenticateNTLMChangeChallenge_p: Challenge uses (%d) exceeded max uses (%d)\n", helperstate->challengeuses, ntlmConfig->challengeuses); - return 1; + debug(29, 4) ("authenticateNTLMChangeChallenge_p: Challenge uses (%d) exceeded max uses (%d)\n", helperstate->challengeuses, ntlmConfig->challengeuses); + return 1; } + if (helperstate->renewed + ntlmConfig->challengelifetime < squid_curtime) { - debug(29, 4) ("authenticateNTLMChangeChallenge_p: Challenge exceeded max lifetime by %d seconds\n", (int) (squid_curtime - (helperstate->renewed + ntlmConfig->challengelifetime))); - return 1; + debug(29, 4) ("authenticateNTLMChangeChallenge_p: Challenge exceeded max lifetime by %d seconds\n", (int) (squid_curtime - (helperstate->renewed + ntlmConfig->challengelifetime))); + return 1; } + debug(29, 9) ("Challenge is to be reused\n"); return 0; } @@ -680,100 +783,115 @@ authenticateNTLMStart(auth_user_request_t * auth_user_request, RH * handler, voi assert(data); assert(auth_user->auth_type = AUTH_NTLM); debug(29, 9) ("authenticateNTLMStart: auth state '%d'\n", ntlm_request->auth_state); + switch (ntlm_request->auth_state) { + case AUTHENTICATE_STATE_NEGOTIATE: - sent_string = ntlm_request->ntlmnegotiate; - break; + sent_string = ntlm_request->ntlmnegotiate; + break; + case AUTHENTICATE_STATE_RESPONSE: - sent_string = ntlm_request->ntlmauthenticate; - assert(ntlm_request->authserver); - debug(29, 9) ("authenticateNTLMStart: Asking NTLMauthenticator '%p'.\n", ntlm_request->authserver); - break; + sent_string = ntlm_request->ntlmauthenticate; + assert(ntlm_request->authserver); + debug(29, 9) ("authenticateNTLMStart: Asking NTLMauthenticator '%p'.\n", ntlm_request->authserver); + break; + default: - fatal("Invalid authenticate state for NTLMStart"); + fatal("Invalid authenticate state for NTLMStart"); } while (!xisspace(*sent_string)) /*trim NTLM */ - sent_string++; + sent_string++; while (xisspace(*sent_string)) /*trim leading spaces */ - sent_string++; + sent_string++; debug(29, 9) ("authenticateNTLMStart: state '%d'\n", ntlm_request->auth_state); + debug(29, 9) ("authenticateNTLMStart: '%s'\n", sent_string); + if (ntlmConfig->authenticate == NULL) { - debug(29, 0) ("authenticateNTLMStart: no NTLM program specified:'%s'\n", sent_string); - handler(data, NULL); - return; + debug(29, 0) ("authenticateNTLMStart: no NTLM program specified:'%s'\n", sent_string); + handler(data, NULL); + return; } + /* this is ugly TODO: move the challenge generation routines to their own function and * tidy the logic up to make use of the efficiency we now have */ switch (ntlm_request->auth_state) { + case AUTHENTICATE_STATE_NEGOTIATE: - /* - * 1: get a helper server - * 2: does it have a challenge? - * 3: tell it to get a challenge, or give ntlmauthdone the challenge - */ - server = helperStatefulDefer(ntlmauthenticators); - helperstate = server ? static_cast(helperStatefulServerGetData(server)) : NULL; - while ((server != NULL) && authenticateNTLMChangeChallenge_p(helperstate)) { - /* flag this helper for challenge changing */ - helperstate->starve = 1; - /* and release the deferred request */ - helperStatefulReleaseServer(server); - /* Get another deferrable server */ - server = helperStatefulDefer(ntlmauthenticators); - helperstate = server ? static_cast(helperStatefulServerGetData(server)) : NULL; - } - if (server == NULL) - debug(29, 9) ("unable to get a deferred ntlm helper... all helpers are refreshing challenges. Queuing as a placeholder request.\n"); - - ntlm_request->authserver = server; - /* tell the log what helper we have been given */ - debug(29, 9) ("authenticateNTLMStart: helper '%p' assigned\n", server); - /* server and valid challenge? */ - if ((server == NULL) || !authenticateNTLMValidChallenge(helperstate)) { - /* No server, or server with invalid challenge */ - r = cbdataAlloc(authenticateStateData); - r->handler = handler; - r->data = cbdataReference(data); - r->auth_user_request = auth_user_request; - if (server == NULL) { - helperStatefulSubmit(ntlmauthenticators, NULL, authenticateNTLMHandleplaceholder, r, NULL); - } else { - /* Server with invalid challenge */ - snprintf(buf, 8192, "YR\n"); - helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver); - } - } else { - /* (server != NULL and we have a valid challenge) */ - /* TODO: turn the below into a function and call from here and handlereply */ - /* increment the challenge uses */ - helperstate->challengeuses++; - /* assign the challenge */ - ntlm_request->authchallenge = xstrndup(helperstate->challenge, NTLM_CHALLENGE_SZ + 5); - /* we're not actually submitting a request, so we need to release the helper - * should the connection close unexpectedly - */ - ntlm_request->authserver_deferred = 1; - handler(data, NULL); - } - - break; + /* + * 1: get a helper server + * 2: does it have a challenge? + * 3: tell it to get a challenge, or give ntlmauthdone the challenge + */ + server = helperStatefulDefer(ntlmauthenticators); + helperstate = server ? static_cast(helperStatefulServerGetData(server)) : NULL; + + while ((server != NULL) && authenticateNTLMChangeChallenge_p(helperstate)) { + /* flag this helper for challenge changing */ + helperstate->starve = 1; + /* and release the deferred request */ + helperStatefulReleaseServer(server); + /* Get another deferrable server */ + server = helperStatefulDefer(ntlmauthenticators); + helperstate = server ? static_cast(helperStatefulServerGetData(server)) : NULL; + } + + if (server == NULL) + debug(29, 9) ("unable to get a deferred ntlm helper... all helpers are refreshing challenges. Queuing as a placeholder request.\n"); + + ntlm_request->authserver = server; + + /* tell the log what helper we have been given */ + debug(29, 9) ("authenticateNTLMStart: helper '%p' assigned\n", server); + + /* server and valid challenge? */ + if ((server == NULL) || !authenticateNTLMValidChallenge(helperstate)) { + /* No server, or server with invalid challenge */ + r = cbdataAlloc(authenticateStateData); + r->handler = handler; + r->data = cbdataReference(data); + r->auth_user_request = auth_user_request; + + if (server == NULL) { + helperStatefulSubmit(ntlmauthenticators, NULL, authenticateNTLMHandleplaceholder, r, NULL); + } else { + /* Server with invalid challenge */ + snprintf(buf, 8192, "YR\n"); + helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver); + } + } else { + /* (server != NULL and we have a valid challenge) */ + /* TODO: turn the below into a function and call from here and handlereply */ + /* increment the challenge uses */ + helperstate->challengeuses++; + /* assign the challenge */ + ntlm_request->authchallenge = xstrndup(helperstate->challenge, NTLM_CHALLENGE_SZ + 5); + /* we're not actually submitting a request, so we need to release the helper + * should the connection close unexpectedly + */ + ntlm_request->authserver_deferred = 1; + handler(data, NULL); + } + + break; + case AUTHENTICATE_STATE_RESPONSE: - r = cbdataAlloc(authenticateStateData); - r->handler = handler; - r->data = cbdataReference(data); - r->auth_user_request = auth_user_request; - snprintf(buf, 8192, "KK %s\n", sent_string); - /* getting rid of deferred request status */ - ntlm_request->authserver_deferred = 0; - helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver); - debug(29, 9) ("authenticateNTLMstart: finished\n"); - break; + r = cbdataAlloc(authenticateStateData); + r->handler = handler; + r->data = cbdataReference(data); + r->auth_user_request = auth_user_request; + snprintf(buf, 8192, "KK %s\n", sent_string); + /* getting rid of deferred request status */ + ntlm_request->authserver_deferred = 0; + helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver); + debug(29, 9) ("authenticateNTLMstart: finished\n"); + break; + default: - fatal("Invalid authenticate state for NTLMStart"); + fatal("Invalid authenticate state for NTLMStart"); } } @@ -782,15 +900,17 @@ static int authenticateNTLMHelperServerAvailable(void *data) { ntlm_helper_state_t *statedata = static_cast(data); + if (statedata != NULL) { - if (statedata->starve) { - debug(29, 4) ("authenticateNTLMHelperServerAvailable: starving - returning 0\n"); - return 0; - } else { - debug(29, 4) ("authenticateNTLMHelperServerAvailable: not starving - returning 1\n"); - return 1; - } + if (statedata->starve) { + debug(29, 4) ("authenticateNTLMHelperServerAvailable: starving - returning 0\n"); + return 0; + } else { + debug(29, 4) ("authenticateNTLMHelperServerAvailable: not starving - returning 1\n"); + return 1; + } } + debug(29, 4) ("authenticateNTLMHelperServerAvailable: no state data - returning 0\n"); return 0; } @@ -799,16 +919,18 @@ static void authenticateNTLMHelperServerOnEmpty(void *data) { ntlm_helper_state_t *statedata = static_cast(data); + if (statedata == NULL) - return; + return; + if (statedata->starve) { - /* we have been starving the helper */ - debug(29, 9) ("authenticateNTLMHelperServerOnEmpty: resetting challenge details\n"); - statedata->starve = 0; - statedata->challengeuses = 0; - statedata->renewed = 0; - xfree(statedata->challenge); - statedata->challenge = NULL; + /* we have been starving the helper */ + debug(29, 9) ("authenticateNTLMHelperServerOnEmpty: resetting challenge details\n"); + statedata->starve = 0; + statedata->challengeuses = 0; + statedata->renewed = 0; + xfree(statedata->challenge); + statedata->challenge = NULL; } } @@ -832,22 +954,28 @@ authenticateNTLMOnCloseConnection(ConnStateData * conn) { ntlm_request_t *ntlm_request; assert(conn != NULL); + if (conn->auth_user_request != NULL) { - assert(conn->auth_user_request->scheme_data != NULL); - ntlm_request = static_cast< ntlm_request_t *>(conn->auth_user_request->scheme_data); - assert(ntlm_request->conn == conn); - if (ntlm_request->authserver != NULL && ntlm_request->authserver_deferred) - authenticateNTLMReleaseServer(conn->auth_user_request); - /* unlock the connection based lock */ - debug(29, 9) ("authenticateNTLMOnCloseConnection: Unlocking auth_user from the connection.\n"); - /* This still breaks the abstraction, but is at least read only now */ - /* Ensure that the auth user request will be getting closed */ - /* IFF we start persisting the struct after the conn closes - say for logging - * then this test may become invalid - */ - assert(authenticateRequestRefCount(conn->auth_user_request) == 1); - authenticateAuthUserRequestUnlock(conn->auth_user_request); - conn->auth_user_request = NULL; + assert(conn->auth_user_request->scheme_data != NULL); + ntlm_request = static_cast< ntlm_request_t *>(conn->auth_user_request->scheme_data); + assert(ntlm_request->conn == conn); + + if (ntlm_request->authserver != NULL && ntlm_request->authserver_deferred) + authenticateNTLMReleaseServer(conn->auth_user_request); + + /* unlock the connection based lock */ + debug(29, 9) ("authenticateNTLMOnCloseConnection: Unlocking auth_user from the connection.\n"); + + /* This still breaks the abstraction, but is at least read only now */ + /* Ensure that the auth user request will be getting closed */ + /* IFF we start persisting the struct after the conn closes - say for logging + * then this test may become invalid + */ + assert(authenticateRequestRefCount(conn->auth_user_request) == 1); + + authenticateAuthUserRequestUnlock(conn->auth_user_request); + + conn->auth_user_request = NULL; } } @@ -856,8 +984,10 @@ static const char * authenticateNTLMUsername(auth_user_t const * auth_user) { ntlm_user_t *ntlm_user = static_cast(auth_user->scheme_data); + if (ntlm_user) - return ntlm_user->username; + return ntlm_user->username; + return NULL; } @@ -913,17 +1043,22 @@ authenticateNTLMcmpUsername(ntlm_user_t * u1, ntlm_user_t * u2) static void authenticateProxyAuthCacheAddLink(const char *key, auth_user_t * auth_user) { + struct ProxyAuthCachePointer *proxy_auth_hash; dlink_node *node; ntlm_user_t *ntlm_user; ntlm_user = static_cast(auth_user->scheme_data); node = ntlm_user->proxy_auth_list.head; /* prevent duplicates */ + while (node) { - if (!strcmp(key, (char const *)((struct ProxyAuthCachePointer *) node->data)->key)) - return; - node = node->next; + + if (!strcmp(key, (char const *)((struct ProxyAuthCachePointer *) node->data)->key)) + return; + + node = node->next; } + proxy_auth_hash = static_cast(memPoolAlloc(ntlm_user_hash_pool)); proxy_auth_hash->key = xstrdup(key); proxy_auth_hash->auth_user = auth_user; @@ -936,9 +1071,12 @@ static int authNTLMAuthenticated(auth_user_request_t * auth_user_request) { ntlm_request_t *ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); + if (ntlm_request->auth_state == AUTHENTICATE_STATE_DONE) - return 1; + return 1; + debug(29, 9) ("User not fully authenticated.\n"); + return 0; } @@ -946,6 +1084,7 @@ static void authenticateNTLMAuthenticateUser(auth_user_request_t * auth_user_request, request_t * request, ConnStateData * conn, http_hdr_type type) { const char *proxy_auth; + struct ProxyAuthCachePointer *proxy_auth_hash = NULL; auth_user_hash_pointer *usernamehash; auth_user_t *auth_user; @@ -964,126 +1103,145 @@ authenticateNTLMAuthenticateUser(auth_user_request_t * auth_user_request, reques ntlm_request = static_cast< ntlm_request_t *>(auth_user_request->scheme_data); /* Check that we are in the client side, where we can generate * auth challenges */ + if (!conn) { - ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; - debug(29, 1) ("authenticateNTLMAuthenticateUser: attempt to perform authentication without a connection!\n"); - return; + ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; + debug(29, 1) ("authenticateNTLMAuthenticateUser: attempt to perform authentication without a connection!\n"); + return; } - + switch (ntlm_request->auth_state) { + case AUTHENTICATE_STATE_NONE: - /* we've recieved a negotiate request. pass to a helper */ - debug(29, 9) ("authenticateNTLMAuthenticateUser: auth state ntlm none. %s\n", proxy_auth); - ntlm_request->auth_state = AUTHENTICATE_STATE_NEGOTIATE; - ntlm_request->ntlmnegotiate = xstrndup(proxy_auth, NTLM_CHALLENGE_SZ + 5); - conn->auth_type = AUTH_NTLM; - conn->auth_user_request = auth_user_request; - ntlm_request->conn = conn; - /* and lock for the connection duration */ - debug(29, 9) ("authenticateNTLMAuthenticateUser: Locking auth_user from the connection.\n"); - authenticateAuthUserRequestLock(auth_user_request); - return; - break; + /* we've recieved a negotiate request. pass to a helper */ + debug(29, 9) ("authenticateNTLMAuthenticateUser: auth state ntlm none. %s\n", proxy_auth); + ntlm_request->auth_state = AUTHENTICATE_STATE_NEGOTIATE; + ntlm_request->ntlmnegotiate = xstrndup(proxy_auth, NTLM_CHALLENGE_SZ + 5); + conn->auth_type = AUTH_NTLM; + conn->auth_user_request = auth_user_request; + ntlm_request->conn = conn; + /* and lock for the connection duration */ + debug(29, 9) ("authenticateNTLMAuthenticateUser: Locking auth_user from the connection.\n"); + authenticateAuthUserRequestLock(auth_user_request); + return; + break; + case AUTHENTICATE_STATE_NEGOTIATE: - ntlm_request->auth_state = AUTHENTICATE_STATE_CHALLENGE; - /* We _MUST_ have the auth challenge by now */ - assert(ntlm_request->authchallenge); - return; - break; + ntlm_request->auth_state = AUTHENTICATE_STATE_CHALLENGE; + /* We _MUST_ have the auth challenge by now */ + assert(ntlm_request->authchallenge); + return; + break; + case AUTHENTICATE_STATE_CHALLENGE: - /* we should have recieved a NTLM challenge. pass it to the same - * helper process */ - debug(29, 9) ("authenticateNTLMAuthenticateUser: auth state challenge with header %s.\n", proxy_auth); - /* do a cache lookup here. If it matches it's a successful ntlm - * challenge - release the helper and use the existing auth_user - * details. */ - if (strncmp("NTLM ", proxy_auth, 5) == 0) { - ntlm_request->ntlmauthenticate = xstrdup(proxy_auth); - } else { - fatal("Incorrect scheme in auth header\n"); - /* TODO: more fault tolerance.. reset the auth scheme here */ - } - /* cache entries have authenticateauthheaderchallengestring */ - snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", - ntlm_request->ntlmauthenticate, - ntlm_request->authchallenge); - /* see if we already know this user's authenticate */ - debug(29, 9) ("aclMatchProxyAuth: cache lookup with key '%s'\n", ntlmhash); - assert(proxy_auth_cache != NULL); - proxy_auth_hash = static_cast(hash_lookup(proxy_auth_cache, ntlmhash)); - if (!proxy_auth_hash) { /* not in the hash table */ - debug(29, 4) ("authenticateNTLMAuthenticateUser: proxy-auth cache miss.\n"); - ntlm_request->auth_state = AUTHENTICATE_STATE_RESPONSE; - /* verify with the ntlm helper */ - } else { - debug(29, 4) ("authenticateNTLMAuthenticateUser: ntlm proxy-auth cache hit\n"); - /* throw away the temporary entry */ - ntlm_request->authserver_deferred = 0; - authenticateNTLMReleaseServer(auth_user_request); - authenticateAuthUserMerge(auth_user, proxy_auth_hash->auth_user); - auth_user = proxy_auth_hash->auth_user; - auth_user_request->auth_user = auth_user; - ntlm_request->auth_state = AUTHENTICATE_STATE_DONE; - /* we found one */ - debug(29, 9) ("found matching cache entry\n"); - assert(auth_user->auth_type == AUTH_NTLM); - /* get the existing entries details */ - ntlm_user = static_cast(auth_user->scheme_data); - debug(29, 9) ("Username to be used is %s\n", ntlm_user->username); - /* on ntlm auth we do not unlock the auth_user until the - * connection is dropped. Thank MS for this quirk */ - auth_user->expiretime = current_time.tv_sec; - } - return; - break; + /* we should have recieved a NTLM challenge. pass it to the same + * helper process */ + debug(29, 9) ("authenticateNTLMAuthenticateUser: auth state challenge with header %s.\n", proxy_auth); + /* do a cache lookup here. If it matches it's a successful ntlm + * challenge - release the helper and use the existing auth_user + * details. */ + + if (strncmp("NTLM ", proxy_auth, 5) == 0) { + ntlm_request->ntlmauthenticate = xstrdup(proxy_auth); + } else { + fatal("Incorrect scheme in auth header\n"); + /* TODO: more fault tolerance.. reset the auth scheme here */ + } + + /* cache entries have authenticateauthheaderchallengestring */ + snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", + ntlm_request->ntlmauthenticate, + ntlm_request->authchallenge); + + /* see if we already know this user's authenticate */ + debug(29, 9) ("aclMatchProxyAuth: cache lookup with key '%s'\n", ntlmhash); + + assert(proxy_auth_cache != NULL); + + proxy_auth_hash = static_cast(hash_lookup(proxy_auth_cache, ntlmhash)); + + if (!proxy_auth_hash) { /* not in the hash table */ + debug(29, 4) ("authenticateNTLMAuthenticateUser: proxy-auth cache miss.\n"); + ntlm_request->auth_state = AUTHENTICATE_STATE_RESPONSE; + /* verify with the ntlm helper */ + } else { + debug(29, 4) ("authenticateNTLMAuthenticateUser: ntlm proxy-auth cache hit\n"); + /* throw away the temporary entry */ + ntlm_request->authserver_deferred = 0; + authenticateNTLMReleaseServer(auth_user_request); + authenticateAuthUserMerge(auth_user, proxy_auth_hash->auth_user); + auth_user = proxy_auth_hash->auth_user; + auth_user_request->auth_user = auth_user; + ntlm_request->auth_state = AUTHENTICATE_STATE_DONE; + /* we found one */ + debug(29, 9) ("found matching cache entry\n"); + assert(auth_user->auth_type == AUTH_NTLM); + /* get the existing entries details */ + ntlm_user = static_cast(auth_user->scheme_data); + debug(29, 9) ("Username to be used is %s\n", ntlm_user->username); + /* on ntlm auth we do not unlock the auth_user until the + * connection is dropped. Thank MS for this quirk */ + auth_user->expiretime = current_time.tv_sec; + } + + return; + break; + case AUTHENTICATE_STATE_RESPONSE: - /* auth-challenge pair cache miss. We've just got the response from the helper */ - /*add to cache and let them through */ - ntlm_request->auth_state = AUTHENTICATE_STATE_DONE; - /* this connection is authenticated */ - debug(29, 4) ("authenticated\nch %s\nauth %s\nauthuser %s\n", - ntlm_request->authchallenge, - ntlm_request->ntlmauthenticate, - ntlm_user->username); - /* cache entries have authenticateauthheaderchallengestring */ - snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", - ntlm_request->ntlmauthenticate, - ntlm_request->authchallenge); - /* see if this is an existing user with a different proxy_auth - * string */ - if ((usernamehash = static_cast(hash_lookup(proxy_auth_username_cache, ntlm_user->username)))) { - while ((authUserHashPointerUser(usernamehash)->auth_type != auth_user->auth_type) && (usernamehash->next) && !authenticateNTLMcmpUsername(static_cast(authUserHashPointerUser(usernamehash)->scheme_data), ntlm_user)) - usernamehash = static_cast(usernamehash->next); - if (authUserHashPointerUser(usernamehash)->auth_type == auth_user->auth_type) { - /* - * add another link from the new proxy_auth to the - * auth_user structure and update the information */ - assert(proxy_auth_hash == NULL); - authenticateProxyAuthCacheAddLink(ntlmhash, authUserHashPointerUser(usernamehash)); - /* we can't seamlessly recheck the username due to the - * challenge nature of the protocol. Just free the - * temporary auth_user */ - authenticateAuthUserMerge(auth_user, authUserHashPointerUser(usernamehash)); - auth_user = authUserHashPointerUser(usernamehash); - auth_user_request->auth_user = auth_user; - } - } else { - /* store user in hash's */ - authenticateUserNameCacheAdd(auth_user); - authenticateProxyAuthCacheAddLink(ntlmhash, auth_user); - } - /* set these to now because this is either a new login from an - * existing user or a new user */ - auth_user->expiretime = current_time.tv_sec; - return; - break; + /* auth-challenge pair cache miss. We've just got the response from the helper */ + /*add to cache and let them through */ + ntlm_request->auth_state = AUTHENTICATE_STATE_DONE; + /* this connection is authenticated */ + debug(29, 4) ("authenticated\nch %s\nauth %s\nauthuser %s\n", + ntlm_request->authchallenge, + ntlm_request->ntlmauthenticate, + ntlm_user->username); + /* cache entries have authenticateauthheaderchallengestring */ + snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", + ntlm_request->ntlmauthenticate, + ntlm_request->authchallenge); + /* see if this is an existing user with a different proxy_auth + * string */ + + if ((usernamehash = static_cast(hash_lookup(proxy_auth_username_cache, ntlm_user->username))) + ) { + while ((authUserHashPointerUser(usernamehash)->auth_type != auth_user->auth_type) && (usernamehash->next) && !authenticateNTLMcmpUsername(static_cast(authUserHashPointerUser(usernamehash)->scheme_data), ntlm_user) + ) + usernamehash = static_cast(usernamehash->next); + if (authUserHashPointerUser(usernamehash)->auth_type == auth_user->auth_type) { + /* + * add another link from the new proxy_auth to the + * auth_user structure and update the information */ + assert(proxy_auth_hash == NULL); + authenticateProxyAuthCacheAddLink(ntlmhash, authUserHashPointerUser(usernamehash)); + /* we can't seamlessly recheck the username due to the + * challenge nature of the protocol. Just free the + * temporary auth_user */ + authenticateAuthUserMerge(auth_user, authUserHashPointerUser(usernamehash)); + auth_user = authUserHashPointerUser(usernamehash); + auth_user_request->auth_user = auth_user; + } + } else { + /* store user in hash's */ + authenticateUserNameCacheAdd(auth_user); + authenticateProxyAuthCacheAddLink(ntlmhash, auth_user); + } + + /* set these to now because this is either a new login from an + * existing user or a new user */ + auth_user->expiretime = current_time.tv_sec; + return; + break; + case AUTHENTICATE_STATE_DONE: - fatal("authenticateNTLMAuthenticateUser: unexpect auth state DONE! Report a bug to the squid developers.\n"); - break; + fatal("authenticateNTLMAuthenticateUser: unexpect auth state DONE! Report a bug to the squid developers.\n"); + break; + case AUTHENTICATE_STATE_FAILED: - /* we've failed somewhere in authentication */ - debug(29, 9) ("authenticateNTLMAuthenticateUser: auth state ntlm failed. %s\n", proxy_auth); - return; + /* we've failed somewhere in authentication */ + debug(29, 9) ("authenticateNTLMAuthenticateUser: auth state ntlm failed. %s\n", proxy_auth); + return; } + return; } diff --git a/src/auth/ntlm/auth_ntlm.h b/src/auth/ntlm/auth_ntlm.h index 5c2de44bc4..e658356284 100644 --- a/src/auth/ntlm/auth_ntlm.h +++ b/src/auth/ntlm/auth_ntlm.h @@ -18,19 +18,25 @@ typedef enum { } auth_state_t; /* connection level auth state */ /* Generic */ -typedef struct { + +typedef struct +{ void *data; auth_user_request_t *auth_user_request; RH *handler; -} authenticateStateData; +} + +authenticateStateData; -struct _ntlm_user { +struct _ntlm_user +{ /* what username did this connection get? */ char *username; dlink_list proxy_auth_list; }; -struct _ntlm_request { +struct _ntlm_request +{ /* what negotiate string did the client use? */ char *ntlmnegotiate; /* what challenge did we give the client? */ @@ -47,7 +53,8 @@ struct _ntlm_request { ConnStateData *conn; }; -struct _ntlm_helper_state_t { +struct _ntlm_helper_state_t +{ char *challenge; /* the challenge to use with this helper */ int starve; /* 0= normal operation. 1=don't hand out any more challenges */ int challengeuses; /* the number of times this challenge has been issued */ @@ -55,22 +62,28 @@ struct _ntlm_helper_state_t { }; /* configuration runtime data */ -struct _auth_ntlm_config { + +struct _auth_ntlm_config +{ int authenticateChildren; wordlist *authenticate; int challengeuses; time_t challengelifetime; }; -struct ProxyAuthCachePointer : public hash_link { +struct ProxyAuthCachePointer : public hash_link +{ dlink_node link; /* other hash entries that point to the same auth_user */ auth_user_t *auth_user; }; typedef struct _ntlm_user ntlm_user_t; + typedef struct _ntlm_request ntlm_request_t; + typedef struct _ntlm_helper_state_t ntlm_helper_state_t; + typedef struct _auth_ntlm_config auth_ntlm_config; #endif diff --git a/src/authenticate.cc b/src/authenticate.cc index ba25757f7e..ee35023e6e 100644 --- a/src/authenticate.cc +++ b/src/authenticate.cc @@ -1,6 +1,6 @@ /* - * $Id: authenticate.cc,v 1.53 2003/02/13 10:28:01 robertc Exp $ + * $Id: authenticate.cc,v 1.54 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Robert Collins @@ -65,12 +65,15 @@ authenticateAuthSchemeConfigured(const char *proxy_auth) { authScheme *scheme; int i; + for (i = 0; i < Config.authConfiguration.n_configured; i++) { - scheme = Config.authConfiguration.schemes + i; - if ((strncasecmp(proxy_auth, scheme->typestr, strlen(scheme->typestr)) == 0) && - (authscheme_list[scheme->Id].Active())) - return 1; + scheme = Config.authConfiguration.schemes + i; + + if ((strncasecmp(proxy_auth, scheme->typestr, strlen(scheme->typestr)) == 0) && + (authscheme_list[scheme->Id].Active())) + return 1; } + return 0; } @@ -78,11 +81,13 @@ int authenticateAuthSchemeId(const char *typestr) { int i = 0; + for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) { - if (strncasecmp(typestr, authscheme_list[i].typestr, strlen(authscheme_list[i].typestr)) == 0) { - return i; - } + if (strncasecmp(typestr, authscheme_list[i].typestr, strlen(authscheme_list[i].typestr)) == 0) { + return i; + } } + return -1; } @@ -92,11 +97,13 @@ AuthUserRequest::decodeAuth(const char *proxy_auth) int i = 0; assert(proxy_auth != NULL); debug(29, 9) ("authenticateDecodeAuth: header = '%s'\n", proxy_auth); - if (!authenticateAuthSchemeConfigured(proxy_auth) || - (i = authenticateAuthSchemeId(proxy_auth)) == -1) { - debug(29, 1) ("AuthUserRequest::decodeAuth: Unsupported or unconfigured proxy-auth scheme, '%s'\n", proxy_auth); - return; + + if (!authenticateAuthSchemeConfigured(proxy_auth) || + (i = authenticateAuthSchemeId(proxy_auth)) == -1) { + debug(29, 1) ("AuthUserRequest::decodeAuth: Unsupported or unconfigured proxy-auth scheme, '%s'\n", proxy_auth); + return; } + assert (i >= 0); authscheme_list[i].decodeauth(this, proxy_auth); auth_user->auth_module = i + 1; @@ -112,9 +119,9 @@ char const * AuthUserRequest::username() const { if (auth_user) - return auth_user->username(); + return auth_user->username(); else - return NULL; + return NULL; } size_t @@ -129,15 +136,17 @@ authenticateOnCloseConnection(ConnStateData * conn) { auth_user_request_t *auth_user_request; assert(conn != NULL); + if (conn->auth_user_request != NULL) { - auth_user_request = conn->auth_user_request; - /* if the auth type gets reset, the connection shouldn't - * remain linked to it - the next type might not be conn based - */ - assert(auth_user_request->auth_user->auth_module); - if (authscheme_list[auth_user_request->auth_user->auth_module - 1].oncloseconnection) { - authscheme_list[auth_user_request->auth_user->auth_module - 1].oncloseconnection(conn); - } + auth_user_request = conn->auth_user_request; + /* if the auth type gets reset, the connection shouldn't + * remain linked to it - the next type might not be conn based + */ + assert(auth_user_request->auth_user->auth_module); + + if (authscheme_list[auth_user_request->auth_user->auth_module - 1].oncloseconnection) { + authscheme_list[auth_user_request->auth_user->auth_module - 1].oncloseconnection(conn); + } } } @@ -149,10 +158,11 @@ AuthUserRequest::start(RH * handler, void *data) { assert(handler); debug(29, 9) ("authenticateStart: auth_user_request '%p'\n", this); + if (auth_user->auth_module > 0) - authscheme_list[auth_user->auth_module - 1].authStart(this, handler, data); + authscheme_list[auth_user->auth_module - 1].authStart(this, handler, data); else - handler(data, NULL); + handler(data, NULL); } void @@ -171,32 +181,39 @@ int authenticateValidateUser(auth_user_request_t * auth_user_request) { debug(29, 9) ("authenticateValidateUser: Validating Auth_user request '%p'.\n", auth_user_request); + if (auth_user_request == NULL) { - debug(29, 4) ("authenticateValidateUser: Auth_user_request was NULL!\n"); - return 0; + debug(29, 4) ("authenticateValidateUser: Auth_user_request was NULL!\n"); + return 0; } + if (auth_user_request->auth_user == NULL) { - debug(29, 4) ("authenticateValidateUser: No associated auth_user structure\n"); - return 0; + debug(29, 4) ("authenticateValidateUser: No associated auth_user structure\n"); + return 0; } + if (auth_user_request->auth_user->auth_type == AUTH_UNKNOWN) { - debug(29, 4) ("authenticateValidateUser: Auth_user '%p' uses unknown scheme.\n", auth_user_request->auth_user); - return 0; + debug(29, 4) ("authenticateValidateUser: Auth_user '%p' uses unknown scheme.\n", auth_user_request->auth_user); + return 0; } + if (auth_user_request->auth_user->auth_type == AUTH_BROKEN) { - debug(29, 4) ("authenticateValidateUser: Auth_user '%p' is broken for it's scheme.\n", auth_user_request->auth_user); - return 0; + debug(29, 4) ("authenticateValidateUser: Auth_user '%p' is broken for it's scheme.\n", auth_user_request->auth_user); + return 0; } + if (!auth_user_request->auth_user->scheme_data) { - debug(29, 4) ("authenticateValidateUser: auth_user '%p' has no scheme data\n", auth_user_request->auth_user); - return 0; + debug(29, 4) ("authenticateValidateUser: auth_user '%p' has no scheme data\n", auth_user_request->auth_user); + return 0; } + /* any other sanity checks that we need in the future */ /* Thus should a module call to something like authValidate */ /* finally return ok */ debug(29, 5) ("authenticateValidateUser: Validated Auth_user request '%p'.\n", auth_user_request); + return 1; } @@ -206,14 +223,16 @@ AuthUser::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (AuthUser)); + if (!pool) - pool = memPoolCreate("Authenticate User Data", sizeof (auth_user_t)); + pool = memPoolCreate("Authenticate User Data", sizeof (auth_user_t)); + return memPoolAlloc(pool); } AuthUser::AuthUser (const char *scheme) : -auth_type (AUTH_UNKNOWN), auth_module (authenticateAuthSchemeId(scheme) + 1), -usernamehash (NULL), ipcount (0), expiretime (0), references (0), scheme_data (NULL) + auth_type (AUTH_UNKNOWN), auth_module (authenticateAuthSchemeId(scheme) + 1), + usernamehash (NULL), ipcount (0), expiretime (0), references (0), scheme_data (NULL) { proxy_auth_list.head = proxy_auth_list.tail = NULL; proxy_match_cache.head = proxy_match_cache.tail = NULL; @@ -225,7 +244,8 @@ char const * AuthUser::username () const { if (auth_module <= 0) - return NULL; + return NULL; + return authscheme_list[auth_module - 1].authUserUsername(this); } @@ -240,8 +260,10 @@ AuthUserRequest::operator new (size_t byteCount) { /* derived classes with different sizes must implement their own new */ assert (byteCount == sizeof (AuthUserRequest)); + if (!pool) - pool = memPoolCreate("Authenticate Request Data", sizeof(auth_user_request_t)); + pool = memPoolCreate("Authenticate Request Data", sizeof(auth_user_request_t)); + return static_cast(memPoolAlloc(pool)); } @@ -252,36 +274,43 @@ AuthUserRequest::operator delete (void *address) } AuthUserRequest::AuthUserRequest():auth_user(NULL), scheme_data (NULL), message(NULL), - references (0), lastReply (AUTH_ACL_CANNOT_AUTHENTICATE) -{ -} - + references (0), lastReply (AUTH_ACL_CANNOT_AUTHENTICATE) +{} + AuthUserRequest::~AuthUserRequest() { dlink_node *link; debug(29, 5) ("AuthUserRequest::~AuthUserRequest: freeing request %p\n", this); assert(references == 0); + if (auth_user) { - if (scheme_data != NULL) { - /* we MUST know the module */ - assert(auth_user->auth_module > 0); - /* and the module MUST support requestFree if it has created scheme data */ - assert(authscheme_list[auth_user->auth_module - 1].requestFree != NULL); - authscheme_list[auth_user->auth_module - 1].requestFree(this); - } - /* unlink from the auth_user struct */ - link = auth_user->requests.head; - while (link && (link->data != this)) - link = link->next; - assert(link != NULL); - dlinkDelete(link, &auth_user->requests); - dlinkNodeDelete(link); - - /* unlock the request structure's lock */ - authenticateAuthUserUnlock(auth_user); - auth_user = NULL; + if (scheme_data != NULL) { + /* we MUST know the module */ + assert(auth_user->auth_module > 0); + /* and the module MUST support requestFree if it has created scheme data */ + assert(authscheme_list[auth_user->auth_module - 1].requestFree != NULL); + authscheme_list[auth_user->auth_module - 1].requestFree(this); + } + + /* unlink from the auth_user struct */ + link = auth_user->requests.head; + + while (link && (link->data != this)) + link = link->next; + + assert(link != NULL); + + dlinkDelete(link, &auth_user->requests); + + dlinkNodeDelete(link); + + /* unlock the request structure's lock */ + authenticateAuthUserUnlock(auth_user); + + auth_user = NULL; } else - assert(scheme_data == NULL); + assert(scheme_data == NULL); + safe_free (message); } @@ -302,7 +331,8 @@ char const * authenticateAuthUserRequestMessage(auth_user_request_t * auth_user_request) { if (auth_user_request) - return auth_user_request->getDenyMessage(); + return auth_user_request->getDenyMessage(); + return NULL; } @@ -313,6 +343,7 @@ authenticateSetDenyMessage (auth_user_request_t * auth_user_request, char const } static void + authenticateAuthUserRequestSetIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr) { auth_user_ip_t *ipdata, *tempnode; @@ -320,70 +351,91 @@ authenticateAuthUserRequestSetIp(auth_user_request_t * auth_user_request, struct char *ip1; int found = 0; CBDATA_INIT_TYPE(auth_user_ip_t); + if (!auth_user_request->auth_user) - return; + return; + auth_user = auth_user_request->auth_user; + ipdata = (auth_user_ip_t *) auth_user->ip_list.head; + /* * we walk the entire list to prevent the first item in the list * preventing old entries being flushed and locking a user out after * a timeout+reconfigure */ - while (ipdata) { - tempnode = (auth_user_ip_t *) ipdata->node.next; - /* walk the ip list */ - if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { - /* This ip has alreadu been seen. */ - found = 1; - /* update IP ttl */ - ipdata->ip_expiretime = squid_curtime; - } else if (ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) { - /* This IP has expired - remove from the seen list */ - dlinkDelete(&ipdata->node, &auth_user->ip_list); - cbdataFree(ipdata); - /* catch incipient underflow */ - assert(auth_user->ipcount); - auth_user->ipcount--; - } - ipdata = tempnode; + while (ipdata) + { + tempnode = (auth_user_ip_t *) ipdata->node.next; + /* walk the ip list */ + + if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { + /* This ip has alreadu been seen. */ + found = 1; + /* update IP ttl */ + ipdata->ip_expiretime = squid_curtime; + } else if (ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) { + /* This IP has expired - remove from the seen list */ + dlinkDelete(&ipdata->node, &auth_user->ip_list); + cbdataFree(ipdata); + /* catch incipient underflow */ + assert(auth_user->ipcount); + auth_user->ipcount--; + } + + ipdata = tempnode; } if (found) - return; + return; /* This ip is not in the seen list */ ipdata = cbdataAlloc(auth_user_ip_t); + ipdata->ip_expiretime = squid_curtime; + ipdata->ipaddr = ipaddr; + dlinkAddTail(ipdata, &ipdata->node, &auth_user->ip_list); + auth_user->ipcount++; ip1 = xstrdup(inet_ntoa(ipaddr)); + debug(29, 2) ("authenticateAuthUserRequestSetIp: user '%s' has been seen at a new IP address (%s)\n ", auth_user->username(), ip1); + safe_free(ip1); } void + authenticateAuthUserRequestRemoveIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr) { auth_user_ip_t *ipdata; auth_user_t *auth_user; + if (!auth_user_request->auth_user) - return; + return; + auth_user = auth_user_request->auth_user; + ipdata = (auth_user_ip_t *) auth_user->ip_list.head; - while (ipdata) { - /* walk the ip list */ - if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { - /* remove the node */ - dlinkDelete(&ipdata->node, &auth_user->ip_list); - cbdataFree(ipdata); - /* catch incipient underflow */ - assert(auth_user->ipcount); - auth_user->ipcount--; - return; - } - ipdata = (auth_user_ip_t *) ipdata->node.next; + + while (ipdata) + { + /* walk the ip list */ + + if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { + /* remove the node */ + dlinkDelete(&ipdata->node, &auth_user->ip_list); + cbdataFree(ipdata); + /* catch incipient underflow */ + assert(auth_user->ipcount); + auth_user->ipcount--; + return; + } + + ipdata = (auth_user_ip_t *) ipdata->node.next; } } @@ -392,19 +444,23 @@ static void authenticateAuthUserClearIp(auth_user_t * auth_user) { auth_user_ip_t *ipdata, *tempnode; + if (!auth_user) - return; + return; + ipdata = (auth_user_ip_t *) auth_user->ip_list.head; + while (ipdata) { - tempnode = (auth_user_ip_t *) ipdata->node.next; - /* walk the ip list */ - dlinkDelete(&ipdata->node, &auth_user->ip_list); - cbdataFree(ipdata); - /* catch incipient underflow */ - assert(auth_user->ipcount); - auth_user->ipcount--; - ipdata = tempnode; + tempnode = (auth_user_ip_t *) ipdata->node.next; + /* walk the ip list */ + dlinkDelete(&ipdata->node, &auth_user->ip_list); + cbdataFree(ipdata); + /* catch incipient underflow */ + assert(auth_user->ipcount); + auth_user->ipcount--; + ipdata = tempnode; } + /* integrity check */ assert(auth_user->ipcount == 0); } @@ -414,7 +470,7 @@ void authenticateAuthUserRequestClearIp(auth_user_request_t * auth_user_request) { if (auth_user_request) - authenticateAuthUserClearIp(auth_user_request->auth_user); + authenticateAuthUserClearIp(auth_user_request->auth_user); } size_t @@ -435,9 +491,13 @@ AuthUserRequest::createAuthUser(const char *proxy_auth) { auth_user_request_t *result = new auth_user_request_t; /* and lock for the callers instance */ - result->lock(); + + result->lock() + + ; /* The scheme is allowed to provide a cached auth_user or a new one */ result->decodeAuth(proxy_auth); + return result; } @@ -448,11 +508,12 @@ int authenticateUserAuthenticated(auth_user_request_t * auth_user_request) { if (!authenticateValidateUser(auth_user_request)) - return 0; + return 0; + if (auth_user_request->auth_user->auth_module > 0) - return authscheme_list[auth_user_request->auth_user->auth_module - 1].authenticated(auth_user_request); + return authscheme_list[auth_user_request->auth_user->auth_module - 1].authenticated(auth_user_request); else - return 0; + return 0; } /* @@ -465,21 +526,22 @@ static void authenticateAuthenticateUser(auth_user_request_t * auth_user_request, request_t * request, ConnStateData * conn, http_hdr_type type) { assert(auth_user_request != NULL); + if (auth_user_request->auth_user->auth_module > 0) - authscheme_list[auth_user_request->auth_user->auth_module - 1].authAuthenticate(auth_user_request, request, conn, type); + authscheme_list[auth_user_request->auth_user->auth_module - 1].authAuthenticate(auth_user_request, request, conn, type); } static auth_user_request_t * authTryGetUser (auth_user_request_t **auth_user_request, ConnStateData * conn) { if (*auth_user_request) - return *auth_user_request; + return *auth_user_request; else if (conn) - return conn->auth_user_request; + return conn->auth_user_request; else - return NULL; + return NULL; } - + /* returns one of * AUTH_ACL_CHALLENGE, * AUTH_ACL_HELPER, @@ -500,6 +562,7 @@ authTryGetUser (auth_user_request_t **auth_user_request, ConnStateData * conn) * the authenticateStart routine for rv==AUTH_ACL_HELPER */ auth_acl_t + AuthUserRequest::authenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr) { const char *proxy_auth; @@ -513,160 +576,219 @@ AuthUserRequest::authenticate(auth_user_request_t ** auth_user_request, http_hdr * authenticated connection so we test for an authenticated * connection when we recieve no authentication header. */ + if (((proxy_auth == NULL) && (!authenticateUserAuthenticated(authTryGetUser(auth_user_request,conn)))) - || (conn && conn->auth_type == AUTH_BROKEN)) { - /* no header or authentication failed/got corrupted - restart */ - debug(28, 4) ("authenticateAuthenticate: broken auth or no proxy_auth header. Requesting auth header.\n"); - /* something wrong with the AUTH credentials. Force a new attempt */ - if (conn) { - conn->auth_type = AUTH_UNKNOWN; - if (conn->auth_user_request) - conn->auth_user_request->unlock(); - conn->auth_user_request = NULL; - } - if (*auth_user_request) { - /* unlock the ACL lock */ - (*auth_user_request)->unlock(); - auth_user_request = NULL; - } - return AUTH_ACL_CHALLENGE; + || (conn && conn->auth_type == AUTH_BROKEN)) + { + /* no header or authentication failed/got corrupted - restart */ + debug(28, 4) ("authenticateAuthenticate: broken auth or no proxy_auth header. Requesting auth header.\n"); + /* something wrong with the AUTH credentials. Force a new attempt */ + + if (conn) { + conn->auth_type = AUTH_UNKNOWN; + + if (conn->auth_user_request) + conn->auth_user_request->unlock(); + + conn->auth_user_request = NULL; + } + + if (*auth_user_request) { + /* unlock the ACL lock */ + (*auth_user_request)->unlock(); + auth_user_request = NULL; + } + + return AUTH_ACL_CHALLENGE; } - /* + + /* * Is this an already authenticated connection with a new auth header? * No check for function required in the if: its compulsory for conn based * auth modules */ if (proxy_auth && conn && conn->auth_user_request && - authenticateUserAuthenticated(conn->auth_user_request) && - strcmp(proxy_auth, authscheme_list[conn->auth_user_request->auth_user->auth_module - 1].authConnLastHeader(conn->auth_user_request))) { - debug(28, 2) ("authenticateAuthenticate: DUPLICATE AUTH - authentication header on already authenticated connection!. AU %p, Current user '%s' proxy_auth %s\n", conn->auth_user_request, conn->auth_user_request->username(), proxy_auth); - /* remove this request struct - the link is already authed and it can't be to - * reauth. - */ - - /* This should _only_ ever occur on the first pass through - * authenticateAuthenticate - */ - assert(*auth_user_request == NULL); - /* unlock the conn lock on the auth_user_request */ - conn->auth_user_request->unlock(); - /* mark the conn as non-authed. */ - conn->auth_user_request = NULL; - /* Set the connection auth type */ - conn->auth_type = AUTH_UNKNOWN; + authenticateUserAuthenticated(conn->auth_user_request) && + strcmp(proxy_auth, authscheme_list[conn->auth_user_request->auth_user->auth_module - 1].authConnLastHeader(conn->auth_user_request))) + { + debug(28, 2) ("authenticateAuthenticate: DUPLICATE AUTH - authentication header on already authenticated connection!. AU %p, Current user '%s' proxy_auth %s\n", conn->auth_user_request, conn->auth_user_request->username(), proxy_auth); + /* remove this request struct - the link is already authed and it can't be to + * reauth. + */ + + /* This should _only_ ever occur on the first pass through + * authenticateAuthenticate + */ + assert(*auth_user_request == NULL); + /* unlock the conn lock on the auth_user_request */ + conn->auth_user_request->unlock(); + /* mark the conn as non-authed. */ + conn->auth_user_request = NULL; + /* Set the connection auth type */ + conn->auth_type = AUTH_UNKNOWN; } + /* we have a proxy auth header and as far as we know this connection has * not had bungled connection oriented authentication happen on it. */ debug(28, 9) ("authenticateAuthenticate: header %s.\n", proxy_auth); - if (*auth_user_request == NULL) { - debug(28, 9) ("authenticateAuthenticate: This is a new checklist test on FD:%d\n", - conn ? conn->fd : -1); - if ((!request->auth_user_request) - && (!conn || conn->auth_type == AUTH_UNKNOWN)) { - /* beginning of a new request check */ - debug(28, 4) ("authenticateAuthenticate: no connection authentication type\n"); - if (!authenticateValidateUser(*auth_user_request = - createAuthUser(proxy_auth))) { - /* the decode might have left a username for logging, or a message to - * the user */ - if ((*auth_user_request)->username()) { - /* lock the user for the request structure link */ - (*auth_user_request)->lock(); - request->auth_user_request = *auth_user_request; - } - /* unlock the ACL reference granted by ...createAuthUser. */ - (*auth_user_request)->unlock(); - *auth_user_request = NULL; - return AUTH_ACL_CHALLENGE; - } - /* the user_request comes prelocked for the caller to createAuthUser (us) */ - } else if (request->auth_user_request) { - *auth_user_request = request->auth_user_request; - /* lock the user request for this ACL processing */ - (*auth_user_request)->lock(); - } else { - assert (conn); - if (conn->auth_user_request != NULL) { - *auth_user_request = conn->auth_user_request; - /* lock the user request for this ACL processing */ - (*auth_user_request)->lock(); - } else { - /* failed connection based authentication */ - debug(28, 4) ("authenticateAuthenticate: Auth user request %p conn-auth user request %p conn type %d authentication failed.\n", - *auth_user_request, conn->auth_user_request, conn->auth_type); - (*auth_user_request)->unlock(); - *auth_user_request = NULL; - return AUTH_ACL_CHALLENGE; - } - } + + if (*auth_user_request == NULL) + { + debug(28, 9) ("authenticateAuthenticate: This is a new checklist test on FD:%d\n", + conn ? conn->fd : -1); + + if ((!request->auth_user_request) + && (!conn || conn->auth_type == AUTH_UNKNOWN)) { + /* beginning of a new request check */ + debug(28, 4) ("authenticateAuthenticate: no connection authentication type\n"); + + if (!authenticateValidateUser(*auth_user_request = + createAuthUser(proxy_auth))) { + /* the decode might have left a username for logging, or a message to + * the user */ + + if ((*auth_user_request)->username()) { + /* lock the user for the request structure link */ + + (*auth_user_request)->lock() + + ; + request->auth_user_request = *auth_user_request; + } + + /* unlock the ACL reference granted by ...createAuthUser. */ + (*auth_user_request)->unlock(); + + *auth_user_request = NULL; + + return AUTH_ACL_CHALLENGE; + } + + /* the user_request comes prelocked for the caller to createAuthUser (us) */ + } else if (request->auth_user_request) { + *auth_user_request = request->auth_user_request; + /* lock the user request for this ACL processing */ + + (*auth_user_request)->lock() + + ; + } else { + assert (conn); + + if (conn->auth_user_request != NULL) { + *auth_user_request = conn->auth_user_request; + /* lock the user request for this ACL processing */ + + (*auth_user_request)->lock() + + ; + } else { + /* failed connection based authentication */ + debug(28, 4) ("authenticateAuthenticate: Auth user request %p conn-auth user request %p conn type %d authentication failed.\n", + *auth_user_request, conn->auth_user_request, conn->auth_type); + (*auth_user_request)->unlock(); + *auth_user_request = NULL; + return AUTH_ACL_CHALLENGE; + } + } } - if (!authenticateUserAuthenticated(*auth_user_request)) { - /* User not logged in. Log them in */ - authenticateAuthenticateUser(*auth_user_request, request, - conn, headertype); - switch (authenticateDirection(*auth_user_request)) { - case 1: - case -2: - /* this ACL check is finished. Unlock. */ - (*auth_user_request)->unlock(); - *auth_user_request = NULL; - return AUTH_ACL_CHALLENGE; - case -1: - /* we are partway through authentication within squid, - * the *auth_user_request variables stores the auth_user_request - * for the callback to here - Do not Unlock */ - return AUTH_ACL_HELPER; - } - /* on 0 the authentication is finished - fallthrough */ - /* See if user authentication failed for some reason */ - if (!authenticateUserAuthenticated(*auth_user_request)) { - if ((*auth_user_request)->username()) { - if (!request->auth_user_request) { - /* lock the user for the request structure link */ - (*auth_user_request)->lock(); - request->auth_user_request = *auth_user_request; - } - } - /* this ACL check is finished. Unlock. */ - (*auth_user_request)->unlock(); - *auth_user_request = NULL; - return AUTH_ACL_CHALLENGE; - } + + if (!authenticateUserAuthenticated(*auth_user_request)) + { + /* User not logged in. Log them in */ + authenticateAuthenticateUser(*auth_user_request, request, + conn, headertype); + + switch (authenticateDirection(*auth_user_request)) { + + case 1: + + case -2: + /* this ACL check is finished. Unlock. */ + (*auth_user_request)->unlock(); + *auth_user_request = NULL; + return AUTH_ACL_CHALLENGE; + + case -1: + /* we are partway through authentication within squid, + * the *auth_user_request variables stores the auth_user_request + * for the callback to here - Do not Unlock */ + return AUTH_ACL_HELPER; + } + + /* on 0 the authentication is finished - fallthrough */ + /* See if user authentication failed for some reason */ + if (!authenticateUserAuthenticated(*auth_user_request)) { + if ((*auth_user_request)->username()) { + if (!request->auth_user_request) { + /* lock the user for the request structure link */ + + (*auth_user_request)->lock() + + ; + request->auth_user_request = *auth_user_request; + } + } + + /* this ACL check is finished. Unlock. */ + (*auth_user_request)->unlock(); + + *auth_user_request = NULL; + + return AUTH_ACL_CHALLENGE; + } } + /* copy username to request for logging on client-side */ /* the credentials are correct at this point */ - if (!request->auth_user_request) { - /* lock the user for the request structure link */ - (*auth_user_request)->lock(); - request->auth_user_request = *auth_user_request; - authenticateAuthUserRequestSetIp(*auth_user_request, src_addr); + if (!request->auth_user_request) + { + /* lock the user for the request structure link */ + + (*auth_user_request)->lock() + + ; + request->auth_user_request = *auth_user_request; + + authenticateAuthUserRequestSetIp(*auth_user_request, src_addr); } + /* Unlock the request - we've authenticated it */ (*auth_user_request)->unlock(); + return AUTH_AUTHENTICATED; } auth_acl_t + AuthUserRequest::tryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr) { /* If we have already been called, return the cached value */ auth_user_request_t *t = authTryGetUser (auth_user_request, conn); + if (t && t->lastReply != AUTH_ACL_CANNOT_AUTHENTICATE - && t->lastReply != AUTH_ACL_HELPER) { - if (!*auth_user_request) - *auth_user_request = t; - return t->lastReply; + && t->lastReply != AUTH_ACL_HELPER) + { + if (!*auth_user_request) + *auth_user_request = t; + + return t->lastReply; } + /* ok, call the actual authenticator routine. */ auth_acl_t result = authenticate(auth_user_request, headertype, request, conn, src_addr); + t = authTryGetUser (auth_user_request, conn); + if (t && result != AUTH_ACL_CANNOT_AUTHENTICATE && - result != AUTH_ACL_HELPER) - t->lastReply = result; + result != AUTH_ACL_HELPER) + t->lastReply = result; + return result; } auth_acl_t + authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr) { return AuthUserRequest::tryToAuthenticateAndSetAuthUser (auth_user_request, headertype,request, conn, src_addr); @@ -690,11 +812,14 @@ int authenticateDirection(auth_user_request_t * auth_user_request) { if (!auth_user_request) - return -2; + return -2; + if (authenticateUserAuthenticated(auth_user_request)) - return 0; + return 0; + if (auth_user_request->auth_user->auth_module > 0) - return authscheme_list[auth_user_request->auth_user->auth_module - 1].getdirection(auth_user_request); + return authscheme_list[auth_user_request->auth_user->auth_module - 1].getdirection(auth_user_request); + return -2; } @@ -702,10 +827,13 @@ int authenticateActiveSchemeCount(void) { int i = 0, rv = 0; + for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) - if (authscheme_list[i].configured()) - rv++; + if (authscheme_list[i].configured()) + rv++; + debug(29, 9) ("authenticateActiveSchemeCount: %d active.\n", rv); + return rv; } @@ -713,9 +841,12 @@ int authenticateSchemeCount(void) { int i = 0, rv = 0; + for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) - rv++; + rv++; + debug(29, 9) ("authenticateSchemeCount: %d active.\n", rv); + return rv; } @@ -730,16 +861,19 @@ authenticateInit(authConfig * config) { int i; authScheme *scheme; + for (i = 0; i < config->n_configured; i++) { - scheme = config->schemes + i; - if (authscheme_list[scheme->Id].init && authscheme_list[scheme->Id].configured()) { - authscheme_list[scheme->Id].init(scheme); - } + scheme = config->schemes + i; + + if (authscheme_list[scheme->Id].init && authscheme_list[scheme->Id].configured()) { + authscheme_list[scheme->Id].init(scheme); + } } + if (!proxy_auth_username_cache) - AuthUser::cacheInit(); - else - AuthUser::CachedACLsReset(); + AuthUser::cacheInit(); + else + AuthUser::CachedACLsReset(); } void @@ -748,17 +882,19 @@ authenticateShutdown(void) int i; debug(29, 2) ("authenticateShutdown: shutting down auth schemes\n"); /* free the cache if we are shutting down */ + if (shutting_down) - hashFreeItems(proxy_auth_username_cache, AuthUserHashPointer::removeFromCache); + hashFreeItems(proxy_auth_username_cache, AuthUserHashPointer::removeFromCache); /* find the currently known authscheme types */ for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) { - if (authscheme_list[i].donefunc != NULL) - authscheme_list[i].donefunc(); - else - debug(29, 2) ("authenticateShutdown: scheme %s has not registered a shutdown function.\n", authscheme_list[i].typestr); - if (shutting_down) - authscheme_list[i].typestr = NULL; + if (authscheme_list[i].donefunc != NULL) + authscheme_list[i].donefunc(); + else + debug(29, 2) ("authenticateShutdown: scheme %s has not registered a shutdown function.\n", authscheme_list[i].typestr); + + if (shutting_down) + authscheme_list[i].typestr = NULL; } } @@ -767,51 +903,65 @@ AuthUserRequest::addReplyAuthHeader(HttpReply * rep, auth_user_request_t * auth_ /* send the auth types we are configured to support (and have compiled in!) */ { http_hdr_type type; - switch (rep->sline.status) { + + switch (rep->sline.status) + { + case HTTP_PROXY_AUTHENTICATION_REQUIRED: - /* Proxy authorisation needed */ - type = HDR_PROXY_AUTHENTICATE; - break; + /* Proxy authorisation needed */ + type = HDR_PROXY_AUTHENTICATE; + break; + case HTTP_UNAUTHORIZED: - /* WWW Authorisation needed */ - type = HDR_WWW_AUTHENTICATE; - break; + /* WWW Authorisation needed */ + type = HDR_WWW_AUTHENTICATE; + break; + default: - /* Keep GCC happy */ - /* some other HTTP status */ - type = HDR_ENUM_END; - break; + /* Keep GCC happy */ + /* some other HTTP status */ + type = HDR_ENUM_END; + break; } + debug(29, 9) ("authenticateFixHeader: headertype:%d authuser:%p\n", type, auth_user_request); + if (((rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED) - || (rep->sline.status == HTTP_UNAUTHORIZED)) && internal) - /* this is a authenticate-needed response */ + || (rep->sline.status == HTTP_UNAUTHORIZED)) && internal) + /* this is a authenticate-needed response */ { - if ((auth_user_request != NULL) && (auth_user_request->auth_user->auth_module > 0) & !authenticateUserAuthenticated(auth_user_request)) - authscheme_list[auth_user_request->auth_user->auth_module - 1].authFixHeader(auth_user_request, rep, type, request); - else { - int i; - authScheme *scheme; - /* call each configured & running authscheme */ - for (i = 0; i < Config.authConfiguration.n_configured; i++) { - scheme = Config.authConfiguration.schemes + i; - if (authscheme_list[scheme->Id].Active()) - authscheme_list[scheme->Id].authFixHeader(NULL, rep, type, - request); - else - debug(29, 4) ("authenticateFixHeader: Configured scheme %s not Active\n", scheme->typestr); - } - } + + if ((auth_user_request != NULL) && (auth_user_request->auth_user->auth_module > 0) & !authenticateUserAuthenticated(auth_user_request)) + authscheme_list[auth_user_request->auth_user->auth_module - 1].authFixHeader(auth_user_request, rep, type, request); + else + { + int i; + authScheme *scheme; + /* call each configured & running authscheme */ + + for (i = 0; i < Config.authConfiguration.n_configured; i++) { + scheme = Config.authConfiguration.schemes + i; + + if (authscheme_list[scheme->Id].Active()) + authscheme_list[scheme->Id].authFixHeader(NULL, rep, type, + request); + else + debug(29, 4) ("authenticateFixHeader: Configured scheme %s not Active\n", scheme->typestr); + } + } + } - /* + /* * allow protocol specific headers to be _added_ to the existing * response - ie digest auth */ + if ((auth_user_request != NULL) && (auth_user_request->auth_user->auth_module > 0) - && (authscheme_list[auth_user_request->auth_user->auth_module - 1].AddHeader)) - authscheme_list[auth_user_request->auth_user->auth_module - 1].AddHeader(auth_user_request, rep, accelerated); + && (authscheme_list[auth_user_request->auth_user->auth_module - 1].AddHeader)) + authscheme_list[auth_user_request->auth_user->auth_module - 1].AddHeader(auth_user_request, rep, accelerated); + if (auth_user_request != NULL) - auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE; + auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE; } void @@ -819,15 +969,15 @@ authenticateFixHeader(HttpReply * rep, auth_user_request_t * auth_user_request, { AuthUserRequest::addReplyAuthHeader(rep, auth_user_request, request, accelerated, internal); } - + /* call the active auth module and allow it to add a trailer to the request */ void authenticateAddTrailer(HttpReply * rep, auth_user_request_t * auth_user_request, request_t * request, int accelerated) { if ((auth_user_request != NULL) && (auth_user_request->auth_user->auth_module > 0) - && (authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer)) - authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer(auth_user_request, rep, accelerated); + && (authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer)) + authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer(auth_user_request, rep, accelerated); } void @@ -844,17 +994,21 @@ authenticateAuthUserUnlock(auth_user_t * auth_user) { debug(29, 9) ("authenticateAuthUserUnlock auth_user '%p'.\n", auth_user); assert(auth_user != NULL); + if (auth_user->references > 0) { - auth_user->references--; + auth_user->references--; } else { - debug(29, 1) ("Attempt to lower Auth User %p refcount below 0!\n", auth_user); + debug(29, 1) ("Attempt to lower Auth User %p refcount below 0!\n", auth_user); } + debug(29, 9) ("authenticateAuthUserUnlock auth_user '%p' now at '%ld'.\n", auth_user, (long int) auth_user->references); + if (auth_user->references == 0) - delete auth_user; + delete auth_user; } void + AuthUserRequest::lock() { debug(29, 9) ("AuthUserRequest::lock: auth_user request '%p'.\n", this); @@ -868,21 +1022,27 @@ AuthUserRequest::unlock() { debug(29, 9) ("AuthUserRequest::unlock: auth_user request '%p'.\n", this); assert(this != NULL); + if (references > 0) { - --references; + --references; } else { - debug(29, 1) ("Attempt to lower Auth User request %p refcount below 0!\n", this); + debug(29, 1) ("Attempt to lower Auth User request %p refcount below 0!\n", this); } + debug(29, 9) ("AuthUserRequest::unlock: auth_user_request '%p' now at '%ld'.\n", this, (long int) references); + if (references == 0) - /* not locked anymore */ - delete this; + /* not locked anymore */ + delete this; } void authenticateAuthUserRequestLock(auth_user_request_t * auth_user_request) { - auth_user_request->lock(); + + auth_user_request->lock() + + ; } void @@ -890,7 +1050,7 @@ authenticateAuthUserRequestUnlock(auth_user_request_t * auth_user_request) { auth_user_request->unlock(); } - + int authenticateAuthUserInuse(auth_user_t * auth_user) @@ -917,14 +1077,16 @@ AuthUser::absorb (AuthUser *from) */ debug(29, 5) ("authenticateAuthUserMerge auth_user '%p' into auth_user '%p'.\n", from, this); dlink_node *link = from->requests.head; + while (link) { - auth_user_request = static_cast(link->data); - dlink_node *tmplink = link; - link = link->next; - dlinkDelete(tmplink, &from->requests); - dlinkAddTail(auth_user_request, tmplink, &requests); - auth_user_request->auth_user = this; + auth_user_request = static_cast(link->data); + dlink_node *tmplink = link; + link = link->next; + dlinkDelete(tmplink, &from->requests); + dlinkAddTail(auth_user_request, tmplink, &requests); + auth_user_request->auth_user = this; } + references += from->references; from->references = 0; delete from; @@ -932,7 +1094,7 @@ AuthUser::absorb (AuthUser *from) void authenticateAuthUserMerge(auth_user_t * from, auth_user_t * to) -{ +{ to->absorb (from); } @@ -949,32 +1111,39 @@ AuthUser::~AuthUser() debug(29, 5) ("AuthUser::~AuthUser: Freeing auth_user '%p' with refcount '%ld'.\n", this, (long int) references); assert(references == 0); /* were they linked in by username ? */ + if (usernamehash) { - assert(usernamehash->user() == this); - debug(29, 5) ("AuthUser::~AuthUser: removing usernamehash entry '%p'\n", usernamehash); - hash_remove_link(proxy_auth_username_cache, - (hash_link *) usernamehash); - /* don't free the key as we use the same user string as the auth_user - * structure */ - delete usernamehash; + assert(usernamehash->user() == this); + debug(29, 5) ("AuthUser::~AuthUser: removing usernamehash entry '%p'\n", usernamehash); + hash_remove_link(proxy_auth_username_cache, + (hash_link *) usernamehash); + /* don't free the key as we use the same user string as the auth_user + * structure */ + delete usernamehash; } + /* remove any outstanding requests */ link = requests.head; + while (link) { - debug(29, 5) ("AuthUser::~AuthUser: removing request entry '%p'\n", link->data); - auth_user_request = static_cast(link->data); - tmplink = link; - link = link->next; - dlinkDelete(tmplink, &requests); - dlinkNodeDelete(tmplink); - delete auth_user_request; + debug(29, 5) ("AuthUser::~AuthUser: removing request entry '%p'\n", link->data); + auth_user_request = static_cast(link->data); + tmplink = link; + link = link->next; + dlinkDelete(tmplink, &requests); + dlinkNodeDelete(tmplink); + delete auth_user_request; } + /* free cached acl results */ aclCacheMatchFlush(&proxy_match_cache); + /* free seen ip address's */ authenticateAuthUserClearIp(this); + if (scheme_data && auth_module > 0) - authscheme_list[auth_module - 1].FreeUser(this); + authscheme_list[auth_module - 1].FreeUser(this); + /* prevent accidental reuse */ auth_type = AUTH_UNKNOWN; } @@ -983,11 +1152,11 @@ void AuthUser::cacheInit(void) { if (!proxy_auth_username_cache) { - /* First time around, 7921 should be big enough */ - proxy_auth_username_cache = - hash_create((HASHCMP *) strcmp, 7921, hash_string); - assert(proxy_auth_username_cache); - eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1); + /* First time around, 7921 should be big enough */ + proxy_auth_username_cache = + hash_create((HASHCMP *) strcmp, 7921, hash_string); + assert(proxy_auth_username_cache); + eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1); } } @@ -1003,13 +1172,15 @@ AuthUser::CachedACLsReset() char const *username = NULL; debug(29, 3) ("AuthUser::CachedACLsReset: Flushing the ACL caches for all users.\n"); hash_first(proxy_auth_username_cache); + while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) { - auth_user = usernamehash->user(); - username = auth_user->username(); - /* free cached acl results */ - aclCacheMatchFlush(&auth_user->proxy_match_cache); + auth_user = usernamehash->user(); + username = auth_user->username(); + /* free cached acl results */ + aclCacheMatchFlush(&auth_user->proxy_match_cache); } + debug(29, 3) ("AuthUser::CachedACLsReset: Finished.\n"); } @@ -1027,24 +1198,28 @@ AuthUser::cacheCleanup(void *datanotused) debug(29, 3) ("AuthUser::cacheCleanup: Cleaning the user cache now\n"); debug(29, 3) ("AuthUser::cacheCleanup: Current time: %ld\n", (long int) current_time.tv_sec); hash_first(proxy_auth_username_cache); + while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) { - auth_user = usernamehash->user(); - username = auth_user->username(); - - /* if we need to have inpedendent expiry clauses, insert a module call - * here */ - debug(29, 4) ("AuthUser::cacheCleanup: Cache entry:\n\tType: %d\n\tUsername: %s\n\texpires: %ld\n\treferences: %ld\n", auth_user->auth_type, username, (long int) (auth_user->expiretime + Config.authenticateTTL), (long int) auth_user->references); - if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) { - debug(29, 5) ("AuthUser::cacheCleanup: Removing user %s from cache due to timeout.\n", username); - /* the minus 1 accounts for the cache lock */ - if (!(authenticateAuthUserInuse(auth_user) - 1)) - /* we don't warn if we leave the user in the cache, - * because other modules (ie delay pools) may keep - * locks on users, and thats legitimate - */ - authenticateAuthUserUnlock(auth_user); - } + auth_user = usernamehash->user(); + username = auth_user->username(); + + /* if we need to have inpedendent expiry clauses, insert a module call + * here */ + debug(29, 4) ("AuthUser::cacheCleanup: Cache entry:\n\tType: %d\n\tUsername: %s\n\texpires: %ld\n\treferences: %ld\n", auth_user->auth_type, username, (long int) (auth_user->expiretime + Config.authenticateTTL), (long int) auth_user->references); + + if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) { + debug(29, 5) ("AuthUser::cacheCleanup: Removing user %s from cache due to timeout.\n", username); + /* the minus 1 accounts for the cache lock */ + + if (!(authenticateAuthUserInuse(auth_user) - 1)) + /* we don't warn if we leave the user in the cache, + * because other modules (ie delay pools) may keep + * locks on users, and thats legitimate + */ + authenticateAuthUserUnlock(auth_user); + } } + debug(29, 3) ("AuthUser::cacheCleanup: Finished cleaning the user cache.\n"); eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1); } @@ -1061,9 +1236,10 @@ authenticateUserCacheRestart(void) auth_user_t *auth_user; debug(29, 3) ("authenticateUserCacheRestart: Clearing config dependent cache data.\n"); hash_first(proxy_auth_username_cache); + while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) { - auth_user = usernamehash->user(); - debug(29, 5) ("authenticateUserCacheRestat: Clearing cache ACL results for user: %s\n", auth_user->username()); + auth_user = usernamehash->user(); + debug(29, 5) ("authenticateUserCacheRestat: Clearing cache ACL results for user: %s\n", auth_user->username()); } } @@ -1077,14 +1253,20 @@ authSchemeAdd(const char *type, AUTHSSETUP * setup) int i; debug(29, 4) ("authSchemeAdd: adding %s\n", type); /* find the number of currently known authscheme types */ + for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) { - assert(strcmp(authscheme_list[i].typestr, type) != 0); + assert(strcmp(authscheme_list[i].typestr, type) != 0); } + /* add the new type */ authscheme_list = static_cast(xrealloc(authscheme_list, (i + 2) * sizeof(authscheme_entry_t))); + memset(&authscheme_list[i], 0, sizeof(authscheme_entry_t)); + memset(&authscheme_list[i + 1], 0, sizeof(authscheme_entry_t)); + authscheme_list[i].typestr = type; + /* Call the scheme module to set up capabilities and initialize any global data */ setup(&authscheme_list[i]); } @@ -1096,9 +1278,12 @@ AuthUserHashPointer::removeFromCache(void *usernamehash_p) { AuthUserHashPointer *usernamehash = static_cast(usernamehash_p); auth_user_t *auth_user = usernamehash->auth_user; + if ((authenticateAuthUserInuse(auth_user) - 1)) - debug(29, 1) ("AuthUserHashPointer::removeFromCache: entry in use - not freeing\n"); + debug(29, 1) ("AuthUserHashPointer::removeFromCache: entry in use - not freeing\n"); + authenticateAuthUserUnlock(auth_user); + /* TODO: change behaviour - we remove from the auth user list here, and then unlock, and the * delete ourselves. */ @@ -1108,8 +1293,10 @@ void * AuthUserHashPointer::operator new (size_t byteCount) { assert (byteCount == sizeof (AuthUserHashPointer)); + if (!pool) - pool = memPoolCreate("Auth user hash link", sizeof(AuthUserHashPointer)); + pool = memPoolCreate("Auth user hash link", sizeof(AuthUserHashPointer)); + return static_cast(memPoolAlloc(pool)); } @@ -1120,7 +1307,7 @@ AuthUserHashPointer::operator delete (void *address) } AuthUserHashPointer::AuthUserHashPointer (auth_user_t * anAuth_user): -auth_user (anAuth_user) + auth_user (anAuth_user) { key = (void *)anAuth_user->username(); next = NULL; diff --git a/src/authenticate.h b/src/authenticate.h index e9d4219800..b54d1e182f 100644 --- a/src/authenticate.h +++ b/src/authenticate.h @@ -1,6 +1,6 @@ /* - * $Id: authenticate.h,v 1.6 2003/02/13 10:28:01 robertc Exp $ + * $Id: authenticate.h,v 1.7 2003/02/21 22:50:06 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,30 +36,36 @@ class AuthUser; -struct AuthUserHashPointer : public hash_link { +struct AuthUserHashPointer : public hash_link +{ /* first two items must be same as hash_link */ + public: static void removeFromCache (void *anAuthUserHashPointer); - + AuthUserHashPointer (AuthUser *); - + void *operator new (size_t byteCount); void operator delete (void *address); AuthUser *user() const; + private: static MemPool *pool; AuthUser *auth_user; }; -struct AuthUserIP { +struct AuthUserIP +{ dlink_node node; /* IP addr this user authenticated from */ + struct in_addr ipaddr; time_t ip_expiretime; }; -struct AuthUser { +struct AuthUser +{ /* extra fields for proxy_auth */ /* this determines what scheme owns the user data. */ auth_type_t auth_type; @@ -81,30 +87,36 @@ struct AuthUser { /* the auth_user_request structures that link to this. Yes it could be a splaytree * but how many requests will a single username have in parallel? */ dlink_list requests; + public: static void cacheInit (); static void CachedACLsReset(); - + void absorb(auth_user_t *from); AuthUser (const char *); ~AuthUser (); void *operator new (size_t byteCount); void operator delete (void *address); char const *username() const; + private: static void cacheCleanup (void *unused); static MemPool *pool; }; -class AuthUserRequest { - public: +class AuthUserRequest +{ + +public: /* this is the object passed around by client_side and acl functions */ /* it has request specific data, and links to user specific data */ /* the user */ auth_user_t *auth_user; /* any scheme specific request related data */ void *scheme_data; + public: + static auth_acl_t tryToAuthenticateAndSetAuthUser(auth_user_request_t **, http_hdr_type, request_t *, ConnStateData *, struct in_addr); static void addReplyAuthHeader(HttpReply * rep, auth_user_request_t * auth_user_request, request_t * request, int accelerated, int internal); @@ -115,15 +127,24 @@ public: void setDenyMessage (char const *); char const * getDenyMessage (); size_t refCount() const; - void lock (); + + void lock () + + ; void unlock (); + char const *username() const; + private: + static auth_acl_t authenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr); + static auth_user_request_t *createAuthUser (const char *proxy_auth); + static MemPool *pool; AuthUserRequest(); + void decodeAuth (const char *proxy_auth); /* return a message on the 407 error pages */ @@ -131,8 +152,8 @@ private: /* how many 'processes' are working on this data */ size_t references; - - /* We only attempt authentication once per http request. This + + /* We only attempt authentication once per http request. This * is to allow multiple auth acl references from different _access areas * when using connection based authentication */ @@ -163,47 +184,51 @@ typedef void AUTHSSTART(auth_user_request_t *, RH *, void *); typedef void AUTHSSTATS(StoreEntry *); typedef const char *AUTHSCONNLASTHEADER(auth_user_request_t *); -extern "C" { -/* subsumed by the C++ interface */ -extern void authenticateAuthUserMerge(auth_user_t *, auth_user_t *); -extern auth_user_t *authenticateAuthUserNew(const char *); - -/* AuthUserRequest */ -extern void authenticateStart(auth_user_request_t *, RH *, void *); -extern auth_acl_t authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t **, http_hdr_type, request_t *, ConnStateData *, struct in_addr); -extern void authenticateSetDenyMessage (auth_user_request_t *, char const *); -extern size_t authenticateRequestRefCount (auth_user_request_t *); -extern char const *authenticateAuthUserRequestMessage(auth_user_request_t *); - -extern int authenticateAuthSchemeId(const char *typestr); -extern void authenticateSchemeInit(void); -extern void authenticateInit(authConfig *); -extern void authenticateShutdown(void); -extern void authenticateFixHeader(HttpReply *, auth_user_request_t *, request_t *, int, int); -extern void authenticateAddTrailer(HttpReply *, auth_user_request_t *, request_t *, int); -extern void authenticateAuthUserUnlock(auth_user_t * auth_user); -extern void authenticateAuthUserLock(auth_user_t * auth_user); -extern void authenticateAuthUserRequestUnlock(auth_user_request_t *); -extern void authenticateAuthUserRequestLock(auth_user_request_t *); -extern int authenticateAuthUserInuse(auth_user_t * auth_user); -extern void authenticateAuthUserRequestRemoveIp(auth_user_request_t *, struct in_addr); -extern void authenticateAuthUserRequestClearIp(auth_user_request_t *); -extern size_t authenticateAuthUserRequestIPCount(auth_user_request_t *); -extern int authenticateDirection(auth_user_request_t *); -extern void authenticateFreeProxyAuthUserACLResults(void *data); -extern int authenticateActiveSchemeCount(void); -extern int authenticateSchemeCount(void); -extern void authenticateUserNameCacheAdd(auth_user_t * auth_user); -extern int authenticateCheckAuthUserIP(struct in_addr request_src_addr, auth_user_request_t * auth_user); -extern int authenticateUserAuthenticated(auth_user_request_t *); -extern void authenticateUserCacheRestart(void); -extern char const *authenticateUserRequestUsername(auth_user_request_t *); -extern int authenticateValidateUser(auth_user_request_t *); -extern void authenticateOnCloseConnection(ConnStateData * conn); -extern void authSchemeAdd(const char *type, AUTHSSETUP * setup); - -/* AuthUserHashPointer */ -extern auth_user_t* authUserHashPointerUser(auth_user_hash_pointer *); +extern "C" +{ + /* subsumed by the C++ interface */ + extern void authenticateAuthUserMerge(auth_user_t *, auth_user_t *); + extern auth_user_t *authenticateAuthUserNew(const char *); + + /* AuthUserRequest */ + extern void authenticateStart(auth_user_request_t *, RH *, void *); + + extern auth_acl_t authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t **, http_hdr_type, request_t *, ConnStateData *, struct in_addr); + extern void authenticateSetDenyMessage (auth_user_request_t *, char const *); + extern size_t authenticateRequestRefCount (auth_user_request_t *); + extern char const *authenticateAuthUserRequestMessage(auth_user_request_t *); + + extern int authenticateAuthSchemeId(const char *typestr); + extern void authenticateSchemeInit(void); + extern void authenticateInit(authConfig *); + extern void authenticateShutdown(void); + extern void authenticateFixHeader(HttpReply *, auth_user_request_t *, request_t *, int, int); + extern void authenticateAddTrailer(HttpReply *, auth_user_request_t *, request_t *, int); + extern void authenticateAuthUserUnlock(auth_user_t * auth_user); + extern void authenticateAuthUserLock(auth_user_t * auth_user); + extern void authenticateAuthUserRequestUnlock(auth_user_request_t *); + extern void authenticateAuthUserRequestLock(auth_user_request_t *); + extern int authenticateAuthUserInuse(auth_user_t * auth_user); + + extern void authenticateAuthUserRequestRemoveIp(auth_user_request_t *, struct in_addr); + extern void authenticateAuthUserRequestClearIp(auth_user_request_t *); + extern size_t authenticateAuthUserRequestIPCount(auth_user_request_t *); + extern int authenticateDirection(auth_user_request_t *); + extern void authenticateFreeProxyAuthUserACLResults(void *data); + extern int authenticateActiveSchemeCount(void); + extern int authenticateSchemeCount(void); + extern void authenticateUserNameCacheAdd(auth_user_t * auth_user); + + extern int authenticateCheckAuthUserIP(struct in_addr request_src_addr, auth_user_request_t * auth_user); + extern int authenticateUserAuthenticated(auth_user_request_t *); + extern void authenticateUserCacheRestart(void); + extern char const *authenticateUserRequestUsername(auth_user_request_t *); + extern int authenticateValidateUser(auth_user_request_t *); + extern void authenticateOnCloseConnection(ConnStateData * conn); + extern void authSchemeAdd(const char *type, AUTHSSETUP * setup); + + /* AuthUserHashPointer */ + extern auth_user_t* authUserHashPointerUser(auth_user_hash_pointer *); } @@ -214,7 +239,8 @@ SQUIDCEXTERN void authSchemeSetup(void); * This defines an auth scheme module */ -struct _authscheme_entry { +struct _authscheme_entry +{ const char *typestr; AUTHSACTIVE *Active; AUTHSADDHEADER *AddHeader; @@ -238,13 +264,15 @@ struct _authscheme_entry { AUTHSSTART *authStart; AUTHSSTATS *authStats; }; - -/* + +/* * This is a configured auth scheme */ - + /* private data types */ -struct _authScheme { + +struct _authScheme +{ /* pointer to the authscheme_list's string entry */ const char *typestr; /* the scheme id in the authscheme_list */ diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 20b416617e..2b2f56cf69 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.cc,v 1.433 2003/02/21 19:53:01 hno Exp $ + * $Id: cache_cf.cc,v 1.434 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -65,12 +65,14 @@ static void parse_cachedir_option_readonly(SwapDir * sd, const char *option, con static void dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir const * sd); static void parse_cachedir_option_maxsize(SwapDir * sd, const char *option, const char *value, int reconfiguring); static void dump_cachedir_option_maxsize(StoreEntry * e, const char *option, SwapDir const * sd); + static struct cache_dir_option common_cachedir_options[] = -{ - {"read-only", parse_cachedir_option_readonly, dump_cachedir_option_readonly}, - {"max-size", parse_cachedir_option_maxsize, dump_cachedir_option_maxsize}, - {NULL, NULL} -}; + { + {"read-only", parse_cachedir_option_readonly, dump_cachedir_option_readonly}, + + {"max-size", parse_cachedir_option_maxsize, dump_cachedir_option_maxsize}, + {NULL, NULL} + }; static void update_maxobjsize(void); @@ -124,18 +126,20 @@ void self_destruct(void) { fatalf("Bungled %s line %d: %s", - cfg_filename, config_lineno, config_input_line); + cfg_filename, config_lineno, config_input_line); } void wordlistDestroy(wordlist ** list) { wordlist *w = NULL; + while ((w = *list) != NULL) { - *list = w->next; - safe_free(w->key); - memFree(w, MEM_WORDLIST); + *list = w->next; + safe_free(w->key); + memFree(w, MEM_WORDLIST); } + *list = NULL; } @@ -143,10 +147,14 @@ const char * wordlistAdd(wordlist ** list, const char *key) { while (*list) - list = &(*list)->next; + list = &(*list)->next; + *list = static_cast(memAllocate(MEM_WORDLIST)); + (*list)->key = xstrdup(key); + (*list)->next = NULL; + return (*list)->key; } @@ -154,8 +162,10 @@ void wordlistJoin(wordlist ** list, wordlist ** wl) { while (*list) - list = &(*list)->next; + list = &(*list)->next; + *list = *wl; + *wl = NULL; } @@ -163,11 +173,12 @@ void wordlistAddWl(wordlist ** list, wordlist * wl) { while (*list) - list = &(*list)->next; + list = &(*list)->next; + for (; wl; wl = wl->next, list = &(*list)->next) { - *list = static_cast(memAllocate(MEM_WORDLIST)); - (*list)->key = xstrdup(wl->key); - (*list)->next = NULL; + *list = static_cast(memAllocate(MEM_WORDLIST)); + (*list)->key = xstrdup(wl->key); + (*list)->next = NULL; } } @@ -175,8 +186,8 @@ void wordlistCat(const wordlist * w, MemBuf * mb) { while (NULL != w) { - memBufPrintf(mb, "%s\n", w->key); - w = w->next; + memBufPrintf(mb, "%s\n", w->key); + w = w->next; } } @@ -184,10 +195,12 @@ wordlist * wordlistDup(const wordlist * w) { wordlist *D = NULL; + while (NULL != w) { - wordlistAdd(&D, w->key); - w = w->next; + wordlistAdd(&D, w->key); + w = w->next; } + return D; } @@ -196,10 +209,12 @@ intlistDestroy(intlist ** list) { intlist *w = NULL; intlist *n = NULL; + for (w = *list; w; w = n) { - n = w->next; - memFree(w, MEM_INTLIST); + n = w->next; + memFree(w, MEM_INTLIST); } + *list = NULL; } @@ -207,9 +222,11 @@ int intlistFind(intlist * list, int i) { intlist *w = NULL; + for (w = list; w; w = w->next) - if (w->i == i) - return 1; + if (w->i == i) + return 1; + return 0; } @@ -222,8 +239,10 @@ xatol(const char *token) { char *end; long ret = strtol(token, &end, 10); + if (ret == 0 && end == token) - self_destruct(); + self_destruct(); + return ret; } @@ -238,8 +257,10 @@ xatof(const char *token) { char *end; double ret = strtod(token, &end); + if (ret == 0 && end == token) - self_destruct(); + self_destruct(); + return ret; } @@ -248,10 +269,13 @@ GetInteger(void) { char *token = strtok(NULL, w_space); int i; + if (token == NULL) - self_destruct(); + self_destruct(); + if (sscanf(token, "%d", &i) != 1) - self_destruct(); + self_destruct(); + return i; } @@ -262,10 +286,12 @@ update_maxobjsize(void) ssize_t ms = -1; for (i = 0; i < Config.cacheSwap.n_configured; i++) { - assert (Config.cacheSwap.swapDirs[i]); - if (Config.cacheSwap.swapDirs[i]->max_objsize > ms) - ms = Config.cacheSwap.swapDirs[i]->max_objsize; + assert (Config.cacheSwap.swapDirs[i]); + + if (Config.cacheSwap.swapDirs[i]->max_objsize > ms) + ms = Config.cacheSwap.swapDirs[i]->max_objsize; } + store_maxobjsize = ms; } @@ -279,81 +305,113 @@ parseConfigFile(const char *file_name) int is_pipe = 0; configFreeMemory(); default_all(); + if (file_name[0] == '!' || file_name[0] == '|') { - fp = popen(file_name + 1, "r"); - is_pipe = 1; + fp = popen(file_name + 1, "r"); + is_pipe = 1; } else { - fp = fopen(file_name, "r"); + fp = fopen(file_name, "r"); } + if (fp == NULL) - fatalf("Unable to open configuration file: %s: %s", - file_name, xstrerror()); + fatalf("Unable to open configuration file: %s: %s", + file_name, xstrerror()); + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) + setmode(fileno(fp), O_TEXT); + #endif + cfg_filename = file_name; + if (is_pipe) - cfg_filename = file_name + 1; + cfg_filename = file_name + 1; else if ((token = strrchr(cfg_filename, '/'))) - cfg_filename = token + 1; + cfg_filename = token + 1; + memset(config_input_line, '\0', BUFSIZ); + config_lineno = 0; + while (fgets(config_input_line, BUFSIZ, fp)) { - config_lineno++; - if ((token = strchr(config_input_line, '\n'))) - *token = '\0'; - if (strncmp(config_input_line, "#line ", 6) == 0) { - static char new_file_name[1024]; - static char *file; - static char new_lineno; - token = config_input_line + 6; - new_lineno = strtol(token, &file, 0) - 1; - if (file == token) - continue; /* Not a valid #line directive, may be a comment */ - while (*file && isspace((unsigned char) *file)) - file++; - if (*file) { - if (*file != '"') - continue; /* Not a valid #line directive, may be a comment */ - xstrncpy(new_file_name, file + 1, sizeof(new_file_name)); - if ((token = strchr(new_file_name, '"'))) - *token = '\0'; - cfg_filename = new_file_name; + config_lineno++; + + if ((token = strchr(config_input_line, '\n'))) + *token = '\0'; + + if (strncmp(config_input_line, "#line ", 6) == 0) { + static char new_file_name[1024]; + static char *file; + static char new_lineno; + token = config_input_line + 6; + new_lineno = strtol(token, &file, 0) - 1; + + if (file == token) + continue; /* Not a valid #line directive, may be a comment */ + + while (*file && isspace((unsigned char) *file)) + file++; + + if (*file) { + if (*file != '"') + continue; /* Not a valid #line directive, may be a comment */ + + xstrncpy(new_file_name, file + 1, sizeof(new_file_name)); + + if ((token = strchr(new_file_name, '"'))) + *token = '\0'; + + cfg_filename = new_file_name; + #if PROBABLY_NOT_WANTED_HERE - if ((token = strrchr(cfg_filename, '/'))) - cfg_filename = token + 1; + + if ((token = strrchr(cfg_filename, '/'))) + cfg_filename = token + 1; + #endif - } - config_lineno = new_lineno; - } - if (config_input_line[0] == '#') - continue; - if (config_input_line[0] == '\0') - continue; - debug(3, 5) ("Processing: '%s'\n", config_input_line); - tmp_line = xstrdup(config_input_line); - if (!parse_line(tmp_line)) { - debug(3, 0) ("parseConfigFile: '%s' line %d unrecognized: '%s'\n", - cfg_filename, - config_lineno, - config_input_line); - err_count++; - } - safe_free(tmp_line); + + } + + config_lineno = new_lineno; + } + + if (config_input_line[0] == '#') + continue; + + if (config_input_line[0] == '\0') + continue; + + debug(3, 5) ("Processing: '%s'\n", config_input_line); + + tmp_line = xstrdup(config_input_line); + + if (!parse_line(tmp_line)) { + debug(3, 0) ("parseConfigFile: '%s' line %d unrecognized: '%s'\n", + cfg_filename, + config_lineno, + config_input_line); + err_count++; + } + + safe_free(tmp_line); } + if (is_pipe) { - int ret = pclose(fp); - if (ret != 0) - fatalf("parseConfigFile: '%s' failed with exit code %d\n", file_name, ret); + int ret = pclose(fp); + + if (ret != 0) + fatalf("parseConfigFile: '%s' failed with exit code %d\n", file_name, ret); } else { - fclose(fp); + fclose(fp); } + defaults_if_none(); configDoConfigure(); cachemgrRegister("config", - "Current Squid Configuration", - dump_config, - 1, 1); + "Current Squid Configuration", + dump_config, + 1, 1); return err_count; } @@ -364,146 +422,203 @@ configDoConfigure(void) /* init memory as early as possible */ memConfigure(); /* Sanity checks */ + if (Config.cacheSwap.swapDirs == NULL) - fatal("No cache_dir's specified in config file"); + fatal("No cache_dir's specified in config file"); + /* calculate Config.Swap.maxSize */ storeDirConfigure(); + if (0 == Config.Swap.maxSize) - /* people might want a zero-sized cache on purpose */ - (void) 0; + /* people might want a zero-sized cache on purpose */ + (void) 0; else if (Config.Swap.maxSize < (Config.memMaxSize >> 10)) - debug(3, 0) ("WARNING cache_mem is larger than total disk cache space!\n"); + debug(3, 0) ("WARNING cache_mem is larger than total disk cache space!\n"); + if (Config.Announce.period > 0) { - Config.onoff.announce = 1; + Config.onoff.announce = 1; } else if (Config.Announce.period < 1) { - Config.Announce.period = 86400 * 365; /* one year */ - Config.onoff.announce = 0; + Config.Announce.period = 86400 * 365; /* one year */ + Config.onoff.announce = 0; } + #if USE_DNSSERVERS if (Config.dnsChildren < 1) - fatal("No dnsservers allocated"); + fatal("No dnsservers allocated"); + #endif + if (Config.Program.redirect) { - if (Config.redirectChildren < 1) { - Config.redirectChildren = 0; - wordlistDestroy(&Config.Program.redirect); - } + if (Config.redirectChildren < 1) { + Config.redirectChildren = 0; + wordlistDestroy(&Config.Program.redirect); + } } + if (Config.appendDomain) - if (*Config.appendDomain != '.') - fatal("append_domain must begin with a '.'"); + if (*Config.appendDomain != '.') + fatal("append_domain must begin with a '.'"); + if (Config.errHtmlText == NULL) - Config.errHtmlText = xstrdup(null_string); + Config.errHtmlText = xstrdup(null_string); + storeConfigure(); + snprintf(ThisCache, sizeof(ThisCache), "%s (%s)", - uniqueHostname(), - full_appname_string); + uniqueHostname(), + full_appname_string); + /* * the extra space is for loop detection in client_side.c -- we search * for substrings in the Via header. */ snprintf(ThisCache2, sizeof(ThisCache), " %s (%s)", - uniqueHostname(), - full_appname_string); + uniqueHostname(), + full_appname_string); + if (!Config.udpMaxHitObjsz || Config.udpMaxHitObjsz > SQUID_UDP_SO_SNDBUF) - Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF; + Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF; + if (Config.appendDomain) - Config.appendDomainLen = strlen(Config.appendDomain); + Config.appendDomainLen = strlen(Config.appendDomain); else - Config.appendDomainLen = 0; + Config.appendDomainLen = 0; + safe_free(debug_options) - debug_options = xstrdup(Config.debugOptions); + debug_options = xstrdup(Config.debugOptions); + if (Config.retry.timeout < 5) - fatal("minimum_retry_timeout must be at least 5 seconds"); + fatal("minimum_retry_timeout must be at least 5 seconds"); + if (Config.retry.maxtries > 10) - fatal("maximum_single_addr_tries cannot be larger than 10"); + fatal("maximum_single_addr_tries cannot be larger than 10"); + if (Config.retry.maxtries < 1) { - debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n"); - Config.retry.maxtries = 1; + debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n"); + Config.retry.maxtries = 1; } + requirePathnameExists("MIME Config Table", Config.mimeTablePathname); #if USE_DNSSERVERS + requirePathnameExists("cache_dns_program", Config.Program.dnsserver); #endif #if USE_UNLINKD + requirePathnameExists("unlinkd_program", Config.Program.unlinkd); #endif + if (Config.Program.redirect) - requirePathnameExists("redirect_program", Config.Program.redirect->key); + requirePathnameExists("redirect_program", Config.Program.redirect->key); + requirePathnameExists("Icon Directory", Config.icons.directory); + requirePathnameExists("Error Directory", Config.errorDirectory); + #if HTTP_VIOLATIONS + { - const refresh_t *R; - for (R = Config.Refresh; R; R = R->next) { - if (!R->flags.override_expire) - continue; - debug(22, 1) ("WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP\n"); - break; - } - for (R = Config.Refresh; R; R = R->next) { - if (!R->flags.override_lastmod) - continue; - debug(22, 1) ("WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP\n"); - break; - } + const refresh_t *R; + + for (R = Config.Refresh; R; R = R->next) + { + if (!R->flags.override_expire) + continue; + + debug(22, 1) ("WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP\n"); + + break; + } + + for (R = Config.Refresh; R; R = R->next) + { + if (!R->flags.override_lastmod) + continue; + + debug(22, 1) ("WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP\n"); + + break; + } + } #endif #if !HTTP_VIOLATIONS Config.onoff.via = 1; #else + if (!Config.onoff.via) - debug(22, 1) ("WARNING: HTTP requires the use of Via\n"); + debug(22, 1) ("WARNING: HTTP requires the use of Via\n"); + #endif + if (Config.Wais.relayHost) { - if (Config.Wais._peer) - cbdataFree(Config.Wais._peer); - Config.Wais._peer = cbdataAlloc(peer); - Config.Wais._peer->host = xstrdup(Config.Wais.relayHost); - Config.Wais._peer->http_port = Config.Wais.relayPort; + if (Config.Wais._peer) + cbdataFree(Config.Wais._peer); + + Config.Wais._peer = cbdataAlloc(peer); + + Config.Wais._peer->host = xstrdup(Config.Wais.relayHost); + + Config.Wais._peer->http_port = Config.Wais.relayPort; } + if (aclPurgeMethodInUse(Config.accessList.http)) - Config2.onoff.enable_purge = 1; + Config2.onoff.enable_purge = 1; + if (geteuid() == 0) { - if (NULL != Config.effectiveUser) { - struct passwd *pwd = getpwnam(Config.effectiveUser); - if (NULL == pwd) - /* - * Andres Kroonmaa : - * Some getpwnam() implementations (Solaris?) require - * an available FD < 256 for opening a FILE* to the - * passwd file. - * DW: - * This should be safe at startup, but might still fail - * during reconfigure. - */ - fatalf("getpwnam failed to find userid for effective user '%s'", - Config.effectiveUser); - Config2.effectiveUserID = pwd->pw_uid; - Config2.effectiveGroupID = pwd->pw_gid; - } + if (NULL != Config.effectiveUser) { + + struct passwd *pwd = getpwnam(Config.effectiveUser); + + if (NULL == pwd) + /* + * Andres Kroonmaa : + * Some getpwnam() implementations (Solaris?) require + * an available FD < 256 for opening a FILE* to the + * passwd file. + * DW: + * This should be safe at startup, but might still fail + * during reconfigure. + */ + fatalf("getpwnam failed to find userid for effective user '%s'", + Config.effectiveUser); + + Config2.effectiveUserID = pwd->pw_uid; + + Config2.effectiveGroupID = pwd->pw_gid; + } } else { - Config2.effectiveUserID = geteuid(); - Config2.effectiveGroupID = getegid(); + Config2.effectiveUserID = geteuid(); + Config2.effectiveGroupID = getegid(); } + if (NULL != Config.effectiveGroup) { - struct group *grp = getgrnam(Config.effectiveGroup); - if (NULL == grp) - fatalf("getgrnam failed to find groupid for effective group '%s'", - Config.effectiveGroup); - Config2.effectiveGroupID = grp->gr_gid; + + struct group *grp = getgrnam(Config.effectiveGroup); + + if (NULL == grp) + fatalf("getgrnam failed to find groupid for effective group '%s'", + Config.effectiveGroup); + + Config2.effectiveGroupID = grp->gr_gid; } + urlExtMethodConfigure(); + if (0 == Config.onoff.client_db) { - acl *a; - for (a = Config.aclList; a; a = a->next) { - if (ACL_MAXCONN != a->aclType()) - continue; - debug(22, 0) ("WARNING: 'maxconn' ACL (%s) won't work with client_db disabled\n", a->name); - } + acl *a; + + for (a = Config.aclList; a; a = a->next) { + if (ACL_MAXCONN != a->aclType()) + continue; + + debug(22, 0) ("WARNING: 'maxconn' ACL (%s) won't work with client_db disabled\n", a->name); + } } + #if USE_SSL Config.ssl_client.sslContext = sslCreateClientContext(Config.ssl_client.cert, Config.ssl_client.key, Config.ssl_client.version, Config.ssl_client.cipher, Config.ssl_client.options, Config.ssl_client.flags, Config.ssl_client.cafile, Config.ssl_client.capath); + #endif } @@ -516,19 +631,25 @@ parseTimeLine(time_t * tptr, const char *units) double d; time_t m; time_t u; + if ((u = parseTimeUnits(units)) == 0) - self_destruct(); + self_destruct(); + if ((token = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); + d = xatof(token); + m = u; /* default to 'units' if none specified */ + if (0 == d) - (void) 0; + (void) 0; else if ((token = strtok(NULL, w_space)) == NULL) - debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n", - config_input_line, d, units); + debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n", + config_input_line, d, units); else if ((m = parseTimeUnits(token)) == 0) - self_destruct(); + self_destruct(); + *tptr = static_cast (m * d / u); } @@ -536,24 +657,34 @@ static int parseTimeUnits(const char *unit) { if (!strncasecmp(unit, T_SECOND_STR, strlen(T_SECOND_STR))) - return 1; + return 1; + if (!strncasecmp(unit, T_MINUTE_STR, strlen(T_MINUTE_STR))) - return 60; + return 60; + if (!strncasecmp(unit, T_HOUR_STR, strlen(T_HOUR_STR))) - return 3600; + return 3600; + if (!strncasecmp(unit, T_DAY_STR, strlen(T_DAY_STR))) - return 86400; + return 86400; + if (!strncasecmp(unit, T_WEEK_STR, strlen(T_WEEK_STR))) - return 86400 * 7; + return 86400 * 7; + if (!strncasecmp(unit, T_FORTNIGHT_STR, strlen(T_FORTNIGHT_STR))) - return 86400 * 14; + return 86400 * 14; + if (!strncasecmp(unit, T_MONTH_STR, strlen(T_MONTH_STR))) - return 86400 * 30; + return 86400 * 30; + if (!strncasecmp(unit, T_YEAR_STR, strlen(T_YEAR_STR))) - return static_cast(86400 * 365.2522); + return static_cast(86400 * 365.2522); + if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR))) - return static_cast(86400 * 365.2522 * 10); + return static_cast(86400 * 365.2522 * 10); + debug(3, 1) ("parseTimeUnits: unknown time unit '%s'\n", unit); + return 0; } @@ -564,19 +695,25 @@ parseBytesLine(size_t * bptr, const char *units) double d; size_t m; size_t u; + if ((u = parseBytesUnits(units)) == 0) - self_destruct(); + self_destruct(); + if ((token = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); + d = xatof(token); + m = u; /* default to 'units' if none specified */ + if (0.0 == d) - (void) 0; + (void) 0; else if ((token = strtok(NULL, w_space)) == NULL) - debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n", - config_input_line, d, units); + debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n", + config_input_line, d, units); else if ((m = parseBytesUnits(token)) == 0) - self_destruct(); + self_destruct(); + *bptr = static_cast(m * d / u); } @@ -584,14 +721,19 @@ static size_t parseBytesUnits(const char *unit) { if (!strncasecmp(unit, B_BYTES_STR, strlen(B_BYTES_STR))) - return 1; + return 1; + if (!strncasecmp(unit, B_KBYTES_STR, strlen(B_KBYTES_STR))) - return 1 << 10; + return 1 << 10; + if (!strncasecmp(unit, B_MBYTES_STR, strlen(B_MBYTES_STR))) - return 1 << 20; + return 1 << 20; + if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR))) - return 1 << 30; + return 1 << 30; + debug(3, 1) ("parseBytesUnits: unknown bytes unit '%s'\n", unit); + return 0; } @@ -604,21 +746,24 @@ dump_acl(StoreEntry * entry, const char *name, acl * ae) { wordlist *w; wordlist *v; + while (ae != NULL) { - debug(3, 3) ("dump_acl: %s %s\n", name, ae->name); - storeAppendPrintf(entry, "%s %s %s ", - name, - ae->name, - ae->typeString()); - v = w = ae->dumpGeneric(); - while (v != NULL) { - debug(3, 3) ("dump_acl: %s %s %s\n", name, ae->name, v->key); - storeAppendPrintf(entry, "%s ", v->key); - v = v->next; - } - storeAppendPrintf(entry, "\n"); - wordlistDestroy(&w); - ae = ae->next; + debug(3, 3) ("dump_acl: %s %s\n", name, ae->name); + storeAppendPrintf(entry, "%s %s %s ", + name, + ae->name, + ae->typeString()); + v = w = ae->dumpGeneric(); + + while (v != NULL) { + debug(3, 3) ("dump_acl: %s %s %s\n", name, ae->name, v->key); + storeAppendPrintf(entry, "%s ", v->key); + v = v->next; + } + + storeAppendPrintf(entry, "\n"); + wordlistDestroy(&w); + ae = ae->next; } } @@ -638,10 +783,11 @@ static void dump_acl_list(StoreEntry * entry, acl_list * head) { acl_list *l; + for (l = head; l; l = l->next) { - storeAppendPrintf(entry, " %s%s", - l->op ? null_string : "!", - l->_acl->name); + storeAppendPrintf(entry, " %s%s", + l->op ? null_string : "!", + l->_acl->name); } } @@ -649,12 +795,13 @@ void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head) { acl_access *l; + for (l = head; l; l = l->next) { - storeAppendPrintf(entry, "%s %s", - name, - l->allow ? "Allow" : "Deny"); - dump_acl_list(entry, l->aclList); - storeAppendPrintf(entry, "\n"); + storeAppendPrintf(entry, "%s %s", + name, + l->allow ? "Allow" : "Deny"); + dump_acl_list(entry, l->aclList); + storeAppendPrintf(entry, "\n"); } } @@ -671,30 +818,36 @@ free_acl_access(acl_access ** head) } static void + dump_address(StoreEntry * entry, const char *name, struct in_addr addr) { storeAppendPrintf(entry, "%s %s\n", name, inet_ntoa(addr)); } static void + parse_address(struct in_addr *addr) { + const struct hostent *hp; char *token = strtok(NULL, w_space); if (token == NULL) - self_destruct(); + self_destruct(); + if (safe_inet_addr(token, addr) == 1) - (void) 0; + (void) 0; else if ((hp = gethostbyname(token))) /* dont use ipcache */ - *addr = inaddrFromHostent(hp); + *addr = inaddrFromHostent(hp); else - self_destruct(); + self_destruct(); } static void + free_address(struct in_addr *addr) { + memset(addr, '\0', sizeof(struct in_addr)); } @@ -704,13 +857,16 @@ static void dump_acl_address(StoreEntry * entry, const char *name, acl_address * head) { acl_address *l; + for (l = head; l; l = l->next) { - if (l->addr.s_addr != INADDR_ANY) - storeAppendPrintf(entry, "%s %s", name, inet_ntoa(l->addr)); - else - storeAppendPrintf(entry, "%s autoselect", name); - dump_acl_list(entry, l->aclList); - storeAppendPrintf(entry, "\n"); + if (l->addr.s_addr != INADDR_ANY) + storeAppendPrintf(entry, "%s %s", name, inet_ntoa(l->addr)); + else + storeAppendPrintf(entry, "%s autoselect", name); + + dump_acl_list(entry, l->aclList); + + storeAppendPrintf(entry, "\n"); } } @@ -730,8 +886,10 @@ parse_acl_address(acl_address ** head) l = cbdataAlloc(acl_address); parse_address(&l->addr); aclParseAclList(&l->aclList); + while (*tail) - tail = &(*tail)->next; + tail = &(*tail)->next; + *tail = l; } @@ -739,9 +897,9 @@ static void free_acl_address(acl_address ** head) { while (*head) { - acl_address *l = *head; - *head = l->next; - cbdataFree(l); + acl_address *l = *head; + *head = l->next; + cbdataFree(l); } } @@ -751,13 +909,16 @@ static void dump_acl_tos(StoreEntry * entry, const char *name, acl_tos * head) { acl_tos *l; + for (l = head; l; l = l->next) { - if (l->tos > 0) - storeAppendPrintf(entry, "%s 0x%02X", name, l->tos); - else - storeAppendPrintf(entry, "%s none", name); - dump_acl_list(entry, l->aclList); - storeAppendPrintf(entry, "\n"); + if (l->tos > 0) + storeAppendPrintf(entry, "%s 0x%02X", name, l->tos); + else + storeAppendPrintf(entry, "%s none", name); + + dump_acl_list(entry, l->aclList); + + storeAppendPrintf(entry, "\n"); } } @@ -776,18 +937,27 @@ parse_acl_tos(acl_tos ** head) int tos; char junk; char *token = strtok(NULL, w_space); + if (!token) - self_destruct(); + self_destruct(); + if (sscanf(token, "0x%x%c", &tos, &junk) != 1) - self_destruct(); + self_destruct(); + if (tos < 0 || tos > 255) - self_destruct(); + self_destruct(); + CBDATA_INIT_TYPE_FREECB(acl_tos, freed_acl_tos); + l = cbdataAlloc(acl_tos); + l->tos = tos; + aclParseAclList(&l->aclList); + while (*tail) - tail = &(*tail)->next; + tail = &(*tail)->next; + *tail = l; } @@ -795,10 +965,10 @@ static void free_acl_tos(acl_tos ** head) { while (*head) { - acl_tos *l = *head; - *head = l->next; - l->next = NULL; - cbdataFree(l); + acl_tos *l = *head; + *head = l->next; + l->next = NULL; + cbdataFree(l); } } @@ -851,6 +1021,7 @@ parse_delay_pool_access(DelayConfig * cfg) { cfg->parsePoolAccess(); } + #endif #ifdef HTTP_VIOLATIONS @@ -858,12 +1029,13 @@ static void dump_http_header_access(StoreEntry * entry, const char *name, header_mangler header[]) { int i; + for (i = 0; i < HDR_ENUM_END; i++) { - if (header[i].access_list != NULL) { - storeAppendPrintf(entry, "%s ", name); - dump_acl_access(entry, httpHeaderNameById(i), - header[i].access_list); - } + if (header[i].access_list != NULL) { + storeAppendPrintf(entry, "%s ", name); + dump_acl_access(entry, httpHeaderNameById(i), + header[i].access_list); + } } } @@ -872,36 +1044,41 @@ parse_http_header_access(header_mangler header[]) { int id, i; char *t = NULL; + if ((t = strtok(NULL, w_space)) == NULL) { - debug(3, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(3, 0) ("parse_http_header_access: missing header name.\n"); - return; + debug(3, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(3, 0) ("parse_http_header_access: missing header name.\n"); + return; } + /* Now lookup index of header. */ id = httpHeaderIdByNameDef(t, strlen(t)); + if (strcmp(t, "All") == 0) - id = HDR_ENUM_END; + id = HDR_ENUM_END; else if (strcmp(t, "Other") == 0) - id = HDR_OTHER; + id = HDR_OTHER; else if (id == -1) { - debug(3, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(3, 0) ("parse_http_header_access: unknown header name %s.\n", t); - return; + debug(3, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(3, 0) ("parse_http_header_access: unknown header name %s.\n", t); + return; } + if (id != HDR_ENUM_END) { - parse_acl_access(&header[id].access_list); + parse_acl_access(&header[id].access_list); } else { - char *next_string = t + strlen(t) - 1; - *next_string = 'A'; - *(next_string + 1) = ' '; - for (i = 0; i < HDR_ENUM_END; i++) { - char *new_string = xstrdup(next_string); - strtok(new_string, w_space); - parse_acl_access(&header[i].access_list); - safe_free(new_string); - } + char *next_string = t + strlen(t) - 1; + *next_string = 'A'; + *(next_string + 1) = ' '; + + for (i = 0; i < HDR_ENUM_END; i++) { + char *new_string = xstrdup(next_string); + strtok(new_string, w_space); + parse_acl_access(&header[i].access_list); + safe_free(new_string); + } } } @@ -909,21 +1086,24 @@ static void free_http_header_access(header_mangler header[]) { int i; + for (i = 0; i < HDR_ENUM_END; i++) { - free_acl_access(&header[i].access_list); + free_acl_access(&header[i].access_list); } } static void dump_http_header_replace(StoreEntry * entry, const char *name, header_mangler - header[]) + header[]) { int i; + for (i = 0; i < HDR_ENUM_END; i++) { - if (NULL == header[i].replacement) - continue; - storeAppendPrintf(entry, "%s %s %s\n", name, httpHeaderNameById(i), - header[i].replacement); + if (NULL == header[i].replacement) + continue; + + storeAppendPrintf(entry, "%s %s %s\n", name, httpHeaderNameById(i), + header[i].replacement); } } @@ -932,35 +1112,41 @@ parse_http_header_replace(header_mangler header[]) { int id, i; char *t = NULL; + if ((t = strtok(NULL, w_space)) == NULL) { - debug(3, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(3, 0) ("parse_http_header_replace: missing header name.\n"); - return; + debug(3, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(3, 0) ("parse_http_header_replace: missing header name.\n"); + return; } + /* Now lookup index of header. */ id = httpHeaderIdByNameDef(t, strlen(t)); + if (strcmp(t, "All") == 0) - id = HDR_ENUM_END; + id = HDR_ENUM_END; else if (strcmp(t, "Other") == 0) - id = HDR_OTHER; + id = HDR_OTHER; else if (id == -1) { - debug(3, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(3, 0) ("parse_http_header_replace: unknown header name %s.\n", - t); - return; + debug(3, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(3, 0) ("parse_http_header_replace: unknown header name %s.\n", + t); + return; } + if (id != HDR_ENUM_END) { - if (header[id].replacement != NULL) - safe_free(header[id].replacement); - header[id].replacement = xstrdup(t + strlen(t) + 1); + if (header[id].replacement != NULL) + safe_free(header[id].replacement); + + header[id].replacement = xstrdup(t + strlen(t) + 1); } else { - for (i = 0; i < HDR_ENUM_END; i++) { - if (header[i].replacement != NULL) - safe_free(header[i].replacement); - header[i].replacement = xstrdup(t + strlen(t) + 1); - } + for (i = 0; i < HDR_ENUM_END; i++) { + if (header[i].replacement != NULL) + safe_free(header[i].replacement); + + header[i].replacement = xstrdup(t + strlen(t) + 1); + } } } @@ -968,21 +1154,27 @@ static void free_http_header_replace(header_mangler header[]) { int i; + for (i = 0; i < HDR_ENUM_END; i++) { - if (header[i].replacement != NULL) - safe_free(header[i].replacement); + if (header[i].replacement != NULL) + safe_free(header[i].replacement); } } + #endif void + dump_cachedir_options(StoreEntry * entry, struct cache_dir_option *options, SwapDir const * sd) { + struct cache_dir_option *option; + if (!options) - return; + return; + for (option = options; option->name; option++) - option->dump(entry, option->name, sd); + option->dump(entry, option->name, sd); } static void @@ -991,12 +1183,13 @@ dump_cachedir(StoreEntry * entry, const char *name, _SquidConfig::_cacheSwap swa SwapDir *s; int i; assert (entry); + for (i = 0; i < swap.n_configured; i++) { - s = swap.swapDirs[i]; - storeAppendPrintf(entry, "%s %s %s", name, s->type, s->path); - s->dump(*entry); - dump_cachedir_options(entry, common_cachedir_options, s); - storeAppendPrintf(entry, "\n"); + s = swap.swapDirs[i]; + storeAppendPrintf(entry, "%s %s %s", name, s->type, s->path); + s->dump(*entry); + dump_cachedir_options(entry, common_cachedir_options, s); + storeAppendPrintf(entry, "\n"); } } @@ -1016,16 +1209,17 @@ static void allocate_new_authScheme(authConfig * cfg) { if (cfg->schemes == NULL) { - cfg->n_allocated = 4; - cfg->schemes = static_cast(xcalloc(cfg->n_allocated, sizeof(authScheme))); + cfg->n_allocated = 4; + cfg->schemes = static_cast(xcalloc(cfg->n_allocated, sizeof(authScheme))); } + if (cfg->n_allocated == cfg->n_configured) { - authScheme *tmp; - cfg->n_allocated <<= 1; - tmp = static_cast(xcalloc(cfg->n_allocated, sizeof(authScheme))); - xmemcpy(tmp, cfg->schemes, cfg->n_configured * sizeof(authScheme)); - xfree(cfg->schemes); - cfg->schemes = tmp; + authScheme *tmp; + cfg->n_allocated <<= 1; + tmp = static_cast(xcalloc(cfg->n_allocated, sizeof(authScheme))); + xmemcpy(tmp, cfg->schemes, cfg->n_configured * sizeof(authScheme)); + xfree(cfg->schemes); + cfg->schemes = tmp; } } @@ -1038,28 +1232,30 @@ parse_authparam(authConfig * config) int type, i; if ((type_str = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); if ((param_str = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); if ((type = authenticateAuthSchemeId(type_str)) == -1) { - debug(3, 0) ("Parsing Config File: Unknown authentication scheme '%s'.\n", type_str); - return; + debug(3, 0) ("Parsing Config File: Unknown authentication scheme '%s'.\n", type_str); + return; } + for (i = 0; i < config->n_configured; i++) { - if (config->schemes[i].Id == type) { - scheme = config->schemes + i; - } + if (config->schemes[i].Id == type) { + scheme = config->schemes + i; + } } if (scheme == NULL) { - allocate_new_authScheme(config); - scheme = config->schemes + config->n_configured; - config->n_configured++; - scheme->Id = type; - scheme->typestr = authscheme_list[type].typestr; + allocate_new_authScheme(config); + scheme = config->schemes + config->n_configured; + config->n_configured++; + scheme->Id = type; + scheme->typestr = authscheme_list[type].typestr; } + authscheme_list[type].parse(scheme, config->n_configured, param_str); } @@ -1069,12 +1265,15 @@ free_authparam(authConfig * cfg) authScheme *scheme; int i; /* DON'T FREE THESE FOR RECONFIGURE */ + if (reconfiguring) - return; + return; + for (i = 0; i < cfg->n_configured; i++) { - scheme = cfg->schemes + i; - authscheme_list[scheme->Id].freeconfig(scheme); + scheme = cfg->schemes + i; + authscheme_list[scheme->Id].freeconfig(scheme); } + safe_free(cfg->schemes); cfg->schemes = NULL; cfg->n_allocated = 0; @@ -1086,9 +1285,10 @@ dump_authparam(StoreEntry * entry, const char *name, authConfig cfg) { authScheme *scheme; int i; + for (i = 0; i < cfg.n_configured; i++) { - scheme = cfg.schemes + i; - authscheme_list[scheme->Id].dump(entry, name, scheme); + scheme = cfg.schemes + i; + authscheme_list[scheme->Id].dump(entry, name, scheme); } } @@ -1096,16 +1296,17 @@ void allocate_new_swapdir(_SquidConfig::_cacheSwap * swap) { if (swap->swapDirs == NULL) { - swap->n_allocated = 4; - swap->swapDirs = static_cast(xcalloc(swap->n_allocated, sizeof(SwapDir *))); + swap->n_allocated = 4; + swap->swapDirs = static_cast(xcalloc(swap->n_allocated, sizeof(SwapDir *))); } + if (swap->n_allocated == swap->n_configured) { - SwapDir **tmp; - swap->n_allocated <<= 1; - tmp = static_cast(xcalloc(swap->n_allocated, sizeof(SwapDir *))); - xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *)); - xfree(swap->swapDirs); - swap->swapDirs = tmp; + SwapDir **tmp; + swap->n_allocated <<= 1; + tmp = static_cast(xcalloc(swap->n_allocated, sizeof(SwapDir *))); + xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *)); + xfree(swap->swapDirs); + swap->swapDirs = tmp; } } @@ -1113,11 +1314,13 @@ static int find_fstype(char *type) { int i; + for (i = 0; storefs_list[i].typestr != NULL; i++) { - if (strcasecmp(type, storefs_list[i].typestr) == 0) { - return i; - } + if (strcasecmp(type, storefs_list[i].typestr) == 0) { + return i; + } } + return (-1); } @@ -1131,10 +1334,10 @@ parse_cachedir(_SquidConfig::_cacheSwap * swap) int fs; if ((type_str = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); if ((path_str = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); /* * This bit of code is a little strange. @@ -1155,27 +1358,32 @@ parse_cachedir(_SquidConfig::_cacheSwap * swap) */ for (i = 0; i < swap->n_configured; i++) { - assert (swap->swapDirs[i]); - if (0 == strcasecmp(path_str, swap->swapDirs[i]->path)) { - /* This is a little weird, you'll appreciate it later */ - fs = find_fstype(type_str); - if (fs < 0) { - fatalf("Unknown cache_dir type '%s'\n", type_str); - } - sd = swap->swapDirs[i]; - sd->reconfigure (i, path_str); - update_maxobjsize(); - return; - } + assert (swap->swapDirs[i]); + + if (0 == strcasecmp(path_str, swap->swapDirs[i]->path)) { + /* This is a little weird, you'll appreciate it later */ + fs = find_fstype(type_str); + + if (fs < 0) { + fatalf("Unknown cache_dir type '%s'\n", type_str); + } + + sd = swap->swapDirs[i]; + sd->reconfigure (i, path_str); + update_maxobjsize(); + return; + } } assert(swap->n_configured < 63); /* 7 bits, signed */ fs = find_fstype(type_str); + if (fs < 0) { - /* If we get here, we didn't find a matching cache_dir type */ - fatalf("Unknown cache_dir type '%s'\n", type_str); + /* If we get here, we didn't find a matching cache_dir type */ + fatalf("Unknown cache_dir type '%s'\n", type_str); } + allocate_new_swapdir(swap); swap->swapDirs[swap->n_configured] = SwapDir::Factory(storefs_list[fs]); sd = swap->swapDirs[swap->n_configured]; @@ -1190,10 +1398,12 @@ static void parse_cachedir_option_readonly(SwapDir * sd, const char *option, const char *value, int reconfiguring) { int read_only = 0; + if (value) - read_only = xatoi(value); + read_only = xatoi(value); else - read_only = 1; + read_only = 1; + sd->flags.read_only = read_only; } @@ -1201,7 +1411,7 @@ static void dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir const * sd) { if (sd->flags.read_only) - storeAppendPrintf(e, " %s", option); + storeAppendPrintf(e, " %s", option); } static void @@ -1210,12 +1420,12 @@ parse_cachedir_option_maxsize(SwapDir * sd, const char *option, const char *valu ssize_t size; if (!value) - self_destruct(); + self_destruct(); size = xatoi(value); if (reconfiguring && sd->max_objsize != size) - debug(3, 1) ("Cache dir '%s' max object size now %ld\n", sd->path, (long int) size); + debug(3, 1) ("Cache dir '%s' max object size now %ld\n", sd->path, (long int) size); sd->max_objsize = size; } @@ -1224,49 +1434,60 @@ static void dump_cachedir_option_maxsize(StoreEntry * e, const char *option, SwapDir const * sd) { if (sd->max_objsize != -1) - storeAppendPrintf(e, " %s=%ld", option, (long int) sd->max_objsize); + storeAppendPrintf(e, " %s=%ld", option, (long int) sd->max_objsize); } void + parse_cachedir_options(SwapDir * sd, struct cache_dir_option *options, int reconfiguring) { unsigned int old_read_only = sd->flags.read_only; char *name, *value; + struct cache_dir_option *option, *op; - while ((name = strtok(NULL, w_space)) != NULL) { - value = strchr(name, '='); - if (value) - *value++ = '\0'; /* cut on = */ - option = NULL; - if (options) { - for (op = options; !option && op->name; op++) { - if (strcmp(op->name, name) == 0) { - option = op; - break; - } - } - } - for (op = common_cachedir_options; !option && op->name; op++) { - if (strcmp(op->name, name) == 0) { - option = op; - break; - } - } - if (!option || !option->parse) - self_destruct(); - option->parse(sd, name, value, reconfiguring); + while ((name = strtok(NULL, w_space)) != NULL) + { + value = strchr(name, '='); + + if (value) + *value++ = '\0'; /* cut on = */ + + option = NULL; + + if (options) { + for (op = options; !option && op->name; op++) { + if (strcmp(op->name, name) == 0) { + option = op; + break; + } + } + } + + for (op = common_cachedir_options; !option && op->name; op++) { + if (strcmp(op->name, name) == 0) { + option = op; + break; + } + } + + if (!option || !option->parse) + self_destruct(); + + option->parse(sd, name, value, reconfiguring); } + /* * Handle notifications about reconfigured single-options with no value * where the removal of the option cannot be easily detected in the * parsing... */ - if (reconfiguring) { - if (old_read_only != sd->flags.read_only) { - debug(3, 1) ("Cache dir '%s' now %s\n", - sd->path, sd->flags.read_only ? "Read-Only" : "Read-Write"); - } + if (reconfiguring) + { + if (old_read_only != sd->flags.read_only) { + debug(3, 1) ("Cache dir '%s' now %s\n", + sd->path, sd->flags.read_only ? "Read-Only" : "Read-Write"); + } } } @@ -1275,13 +1496,16 @@ free_cachedir(_SquidConfig::_cacheSwap * swap) { int i; /* DON'T FREE THESE FOR RECONFIGURE */ + if (reconfiguring) - return; + return; + for (i = 0; i < swap->n_configured; i++) { - SwapDir * s = swap->swapDirs[i]; - swap->swapDirs[i] = NULL; - delete s; + SwapDir * s = swap->swapDirs[i]; + swap->swapDirs[i] = NULL; + delete s; } + safe_free(swap->swapDirs); swap->swapDirs = NULL; swap->n_allocated = 0; @@ -1292,18 +1516,22 @@ static const char * peer_type_str(const peer_t type) { switch (type) { + case PEER_PARENT: - return "parent"; - break; + return "parent"; + break; + case PEER_SIBLING: - return "sibling"; - break; + return "sibling"; + break; + case PEER_MULTICAST: - return "multicast"; - break; + return "multicast"; + break; + default: - return "unknown"; - break; + return "unknown"; + break; } } @@ -1313,31 +1541,36 @@ dump_peer(StoreEntry * entry, const char *name, peer * p) domain_ping *d; domain_type *t; LOCAL_ARRAY(char, xname, 128); + while (p != NULL) { - storeAppendPrintf(entry, "%s %s %s %d %d", - name, - p->host, - neighborTypeStr(p), - p->http_port, - p->icp.port); - dump_peer_options(entry, p); - for (d = p->peer_domain; d; d = d->next) { - storeAppendPrintf(entry, "cache_peer_domain %s %s%s\n", - p->host, - d->do_ping ? null_string : "!", - d->domain); - } - if (p->access) { - snprintf(xname, 128, "cache_peer_access %s", p->name); - dump_acl_access(entry, xname, p->access); - } - for (t = p->typelist; t; t = t->next) { - storeAppendPrintf(entry, "neighbor_type_domain %s %s %s\n", - p->host, - peer_type_str(t->type), - t->domain); - } - p = p->next; + storeAppendPrintf(entry, "%s %s %s %d %d", + name, + p->host, + neighborTypeStr(p), + p->http_port, + p->icp.port); + dump_peer_options(entry, p); + + for (d = p->peer_domain; d; d = d->next) { + storeAppendPrintf(entry, "cache_peer_domain %s %s%s\n", + p->host, + d->do_ping ? null_string : "!", + d->domain); + } + + if (p->access) { + snprintf(xname, 128, "cache_peer_access %s", p->name); + dump_acl_access(entry, xname, p->access); + } + + for (t = p->typelist; t; t = t->next) { + storeAppendPrintf(entry, "neighbor_type_domain %s %s %s\n", + p->host, + peer_type_str(t->type), + t->domain); + } + + p = p->next; } } @@ -1353,151 +1586,189 @@ parse_peer(peer ** head) p->weight = 1; p->basetime = 0; p->stats.logged_state = PEER_ALIVE; + if ((token = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); + p->host = xstrdup(token); + p->name = xstrdup(token); + if ((token = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); + p->type = parseNeighborType(token); + i = GetInteger(); + p->http_port = (u_short) i; + i = GetInteger(); + p->icp.port = (u_short) i; + while ((token = strtok(NULL, w_space))) { - if (!strcasecmp(token, "proxy-only")) { - p->options.proxy_only = 1; - } else if (!strcasecmp(token, "no-query")) { - p->options.no_query = 1; - } else if (!strcasecmp(token, "background-ping")) { - p->options.background_ping = 1; - } else if (!strcasecmp(token, "no-digest")) { - p->options.no_digest = 1; - } else if (!strcasecmp(token, "multicast-responder")) { - p->options.mcast_responder = 1; - } else if (!strncasecmp(token, "weight=", 7)) { - p->weight = xatoi(token + 7); - } else if (!strncasecmp(token, "basetime=", 9)) { - p->basetime = xatoi(token + 9); - } else if (!strcasecmp(token, "closest-only")) { - p->options.closest_only = 1; - } else if (!strncasecmp(token, "ttl=", 4)) { - p->mcast.ttl = xatoi(token + 4); - if (p->mcast.ttl < 0) - p->mcast.ttl = 0; - if (p->mcast.ttl > 128) - p->mcast.ttl = 128; - } else if (!strcasecmp(token, "default")) { - p->options.default_parent = 1; - } else if (!strcasecmp(token, "round-robin")) { - p->options.roundrobin = 1; - } else if (!strcasecmp(token, "weighted-round-robin")) { - p->options.weighted_roundrobin = 1; + if (!strcasecmp(token, "proxy-only")) { + p->options.proxy_only = 1; + } else if (!strcasecmp(token, "no-query")) { + p->options.no_query = 1; + } else if (!strcasecmp(token, "background-ping")) { + p->options.background_ping = 1; + } else if (!strcasecmp(token, "no-digest")) { + p->options.no_digest = 1; + } else if (!strcasecmp(token, "multicast-responder")) { + p->options.mcast_responder = 1; + } else if (!strncasecmp(token, "weight=", 7)) { + p->weight = xatoi(token + 7); + } else if (!strncasecmp(token, "basetime=", 9)) { + p->basetime = xatoi(token + 9); + } else if (!strcasecmp(token, "closest-only")) { + p->options.closest_only = 1; + } else if (!strncasecmp(token, "ttl=", 4)) { + p->mcast.ttl = xatoi(token + 4); + + if (p->mcast.ttl < 0) + p->mcast.ttl = 0; + + if (p->mcast.ttl > 128) + p->mcast.ttl = 128; + } else if (!strcasecmp(token, "default")) { + p->options.default_parent = 1; + } else if (!strcasecmp(token, "round-robin")) { + p->options.roundrobin = 1; + } else if (!strcasecmp(token, "weighted-round-robin")) { + p->options.weighted_roundrobin = 1; #if USE_HTCP - } else if (!strcasecmp(token, "htcp")) { - p->options.htcp = 1; + + } else if (!strcasecmp(token, "htcp")) { + p->options.htcp = 1; #endif - } else if (!strcasecmp(token, "no-netdb-exchange")) { - p->options.no_netdb_exchange = 1; + + } else if (!strcasecmp(token, "no-netdb-exchange")) { + p->options.no_netdb_exchange = 1; #if USE_CARP - } else if (!strcasecmp(token, "carp")) { - if (p->type != PEER_PARENT) - fatalf("parse_peer: non-parent carp peer %s/%d\n", p->host, p->http_port); - p->options.carp = 1; + + } else if (!strcasecmp(token, "carp")) { + if (p->type != PEER_PARENT) + fatalf("parse_peer: non-parent carp peer %s/%d\n", p->host, p->http_port); + + p->options.carp = 1; + #endif #if DELAY_POOLS - } else if (!strcasecmp(token, "no-delay")) { - p->options.no_delay = 1; + + } else if (!strcasecmp(token, "no-delay")) { + p->options.no_delay = 1; #endif - } else if (!strncasecmp(token, "login=", 6)) { - p->login = xstrdup(token + 6); - rfc1738_unescape(p->login); - } else if (!strncasecmp(token, "connect-timeout=", 16)) { - p->connect_timeout = xatoi(token + 16); + + } else if (!strncasecmp(token, "login=", 6)) { + p->login = xstrdup(token + 6); + rfc1738_unescape(p->login); + } else if (!strncasecmp(token, "connect-timeout=", 16)) { + p->connect_timeout = xatoi(token + 16); #if USE_CACHE_DIGESTS - } else if (!strncasecmp(token, "digest-url=", 11)) { - p->digest_url = xstrdup(token + 11); + + } else if (!strncasecmp(token, "digest-url=", 11)) { + p->digest_url = xstrdup(token + 11); #endif - } else if (!strcasecmp(token, "allow-miss")) { - p->options.allow_miss = 1; - } else if (!strncasecmp(token, "max-conn=", 9)) { - p->max_conn = xatoi(token + 9); - } else if (!strcasecmp(token, "originserver")) { - p->options.originserver = 1; - } else if (!strncasecmp(token, "name=", 5)) { - safe_free(p->name); - if (token[5]) - p->name = xstrdup(token + 5); - } else if (!strncasecmp(token, "forceddomain=", 13)) { - safe_free(p->domain); - if (token[13]) - p->domain = xstrdup(token + 13); + + } else if (!strcasecmp(token, "allow-miss")) { + p->options.allow_miss = 1; + } else if (!strncasecmp(token, "max-conn=", 9)) { + p->max_conn = xatoi(token + 9); + } else if (!strcasecmp(token, "originserver")) { + p->options.originserver = 1; + } else if (!strncasecmp(token, "name=", 5)) { + safe_free(p->name); + + if (token[5]) + p->name = xstrdup(token + 5); + } else if (!strncasecmp(token, "forceddomain=", 13)) { + safe_free(p->domain); + + if (token[13]) + p->domain = xstrdup(token + 13); + #if USE_SSL - } else if (strcmp(token, "ssl") == 0) { - p->use_ssl = 1; - } else if (strncmp(token, "sslcert=", 8) == 0) { - safe_free(p->sslcert); - p->sslcert = xstrdup(token + 8); - } else if (strncmp(token, "sslkey=", 7) == 0) { - safe_free(p->sslkey); - p->sslkey = xstrdup(token + 7); - } else if (strncmp(token, "sslversion=", 11) == 0) { - p->sslversion = atoi(token + 11); - } else if (strncmp(token, "ssloptions=", 11) == 0) { - safe_free(p->ssloptions); - p->ssloptions = xstrdup(token + 11); - } else if (strncmp(token, "sslcipher=", 10) == 0) { - safe_free(p->sslcipher); - p->sslcipher = xstrdup(token + 10); - } else if (strncmp(token, "sslcafile=", 10) == 0) { - safe_free(p->sslcafile); - p->sslcipher = xstrdup(token + 10); - } else if (strncmp(token, "sslcapath=", 10) == 0) { - safe_free(p->sslcapath); - p->sslcipher = xstrdup(token + 10); - } else if (strncmp(token, "sslflags=", 9) == 0) { - safe_free(p->sslflags); - p->sslflags = xstrdup(token + 9); - } else if (strncmp(token, "ssldomain=", 10) == 0) { - safe_free(p->ssldomain); - p->ssldomain = xstrdup(token + 10); + + } else if (strcmp(token, "ssl") == 0) { + p->use_ssl = 1; + } else if (strncmp(token, "sslcert=", 8) == 0) { + safe_free(p->sslcert); + p->sslcert = xstrdup(token + 8); + } else if (strncmp(token, "sslkey=", 7) == 0) { + safe_free(p->sslkey); + p->sslkey = xstrdup(token + 7); + } else if (strncmp(token, "sslversion=", 11) == 0) { + p->sslversion = atoi(token + 11); + } else if (strncmp(token, "ssloptions=", 11) == 0) { + safe_free(p->ssloptions); + p->ssloptions = xstrdup(token + 11); + } else if (strncmp(token, "sslcipher=", 10) == 0) { + safe_free(p->sslcipher); + p->sslcipher = xstrdup(token + 10); + } else if (strncmp(token, "sslcafile=", 10) == 0) { + safe_free(p->sslcafile); + p->sslcipher = xstrdup(token + 10); + } else if (strncmp(token, "sslcapath=", 10) == 0) { + safe_free(p->sslcapath); + p->sslcipher = xstrdup(token + 10); + } else if (strncmp(token, "sslflags=", 9) == 0) { + safe_free(p->sslflags); + p->sslflags = xstrdup(token + 9); + } else if (strncmp(token, "ssldomain=", 10) == 0) { + safe_free(p->ssldomain); + p->ssldomain = xstrdup(token + 10); #endif - } else if (strcmp(token, "front-end-https") == 0) { - p->front_end_https = 1; - } else if (strcmp(token, "front-end-https=on") == 0) { - p->front_end_https = 1; - } else if (strcmp(token, "front-end-https=auto") == 0) { - p->front_end_https = 2; - } else { - debug(3, 0) ("parse_peer: token='%s'\n", token); - self_destruct(); - } + + } else if (strcmp(token, "front-end-https") == 0) { + p->front_end_https = 1; + } else if (strcmp(token, "front-end-https=on") == 0) { + p->front_end_https = 1; + } else if (strcmp(token, "front-end-https=auto") == 0) { + p->front_end_https = 2; + } else { + debug(3, 0) ("parse_peer: token='%s'\n", token); + self_destruct(); + } } + if (peerFindByName(p->name)) - fatalf("ERROR: cache_peer %s specified twice\n", p->name); + fatalf("ERROR: cache_peer %s specified twice\n", p->name); + if (p->weight < 1) - p->weight = 1; + p->weight = 1; + p->icp.version = ICP_VERSION_CURRENT; + p->tcp_up = PEER_TCP_MAGIC_COUNT; + p->test_fd = -1; + #if USE_CACHE_DIGESTS + if (!p->options.no_digest) { - /* XXX This looks odd.. who has the original pointer - * then? - */ - PeerDigest *pd = peerDigestCreate(p); - p->digest = cbdataReference(pd); + /* XXX This looks odd.. who has the original pointer + * then? + */ + PeerDigest *pd = peerDigestCreate(p); + p->digest = cbdataReference(pd); } + #endif #if USE_SSL if (p->use_ssl) { - p->sslContext = sslCreateClientContext(p->sslcert, p->sslkey, p->sslversion, p->sslcipher, p->ssloptions, p->sslflags, p->sslcafile, p->sslcapath); + p->sslContext = sslCreateClientContext(p->sslcert, p->sslkey, p->sslversion, p->sslcipher, p->ssloptions, p->sslflags, p->sslcafile, p->sslcapath); } + #endif while (*head != NULL) - head = &(*head)->next; + head = &(*head)->next; + *head = p; + Config.npeers++; + peerClearRR(p); } @@ -1505,13 +1776,17 @@ static void free_peer(peer ** P) { peer *p; + while ((p = *P) != NULL) { - *P = p->next; + *P = p->next; #if USE_CACHE_DIGESTS - cbdataReferenceDone(p->digest); + + cbdataReferenceDone(p->digest); #endif - cbdataFree(p); + + cbdataFree(p); } + Config.npeers = 0; } @@ -1519,16 +1794,19 @@ static void dump_cachemgrpasswd(StoreEntry * entry, const char *name, cachemgr_passwd * list) { wordlist *w; + while (list != NULL) { - if (strcmp(list->passwd, "none") && strcmp(list->passwd, "disable")) - storeAppendPrintf(entry, "%s XXXXXXXXXX", name); - else - storeAppendPrintf(entry, "%s %s", name, list->passwd); - for (w = list->actions; w != NULL; w = w->next) { - storeAppendPrintf(entry, " %s", w->key); - } - storeAppendPrintf(entry, "\n"); - list = list->next; + if (strcmp(list->passwd, "none") && strcmp(list->passwd, "disable")) + storeAppendPrintf(entry, "%s XXXXXXXXXX", name); + else + storeAppendPrintf(entry, "%s %s", name, list->passwd); + + for (w = list->actions; w != NULL; w = w->next) { + storeAppendPrintf(entry, " %s", w->key); + } + + storeAppendPrintf(entry, "\n"); + list = list->next; } } @@ -1544,26 +1822,30 @@ parse_cachemgrpasswd(cachemgr_passwd ** head) p = static_cast(xcalloc(1, sizeof(cachemgr_passwd))); p->passwd = passwd; p->actions = actions; + for (P = head; *P; P = &(*P)->next) { - /* - * See if any of the actions from this line already have a - * password from previous lines. The password checking - * routines in cache_manager.c take the the password from - * the first cachemgr_passwd struct that contains the - * requested action. Thus, we should warn users who might - * think they can have two passwords for the same action. - */ - wordlist *w; - wordlist *u; - for (w = (*P)->actions; w; w = w->next) { - for (u = actions; u; u = u->next) { - if (strcmp(w->key, u->key)) - continue; - debug(0, 0) ("WARNING: action '%s' (line %d) already has a password\n", - u->key, config_lineno); - } - } + /* + * See if any of the actions from this line already have a + * password from previous lines. The password checking + * routines in cache_manager.c take the the password from + * the first cachemgr_passwd struct that contains the + * requested action. Thus, we should warn users who might + * think they can have two passwords for the same action. + */ + wordlist *w; + wordlist *u; + + for (w = (*P)->actions; w; w = w->next) { + for (u = actions; u; u = u->next) { + if (strcmp(w->key, u->key)) + continue; + + debug(0, 0) ("WARNING: action '%s' (line %d) already has a password\n", + u->key, config_lineno); + } + } } + *P = p; } @@ -1571,11 +1853,12 @@ static void free_cachemgrpasswd(cachemgr_passwd ** head) { cachemgr_passwd *p; + while ((p = *head) != NULL) { - *head = p->next; - xfree(p->passwd); - wordlistDestroy(&p->actions); - xfree(p); + *head = p->next; + xfree(p->passwd); + wordlistDestroy(&p->actions); + xfree(p); } } @@ -1583,12 +1866,16 @@ static void dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var) { acl_name_list *a; + while (var != NULL) { - storeAppendPrintf(entry, "%s %s", name, var->err_page_name); - for (a = var->acl_list; a != NULL; a = a->next) - storeAppendPrintf(entry, " %s", a->name); - storeAppendPrintf(entry, "\n"); - var = var->next; + storeAppendPrintf(entry, "%s %s", name, var->err_page_name); + + for (a = var->acl_list; a != NULL; a = a->next) + storeAppendPrintf(entry, " %s", a->name); + + storeAppendPrintf(entry, "\n"); + + var = var->next; } } @@ -1605,16 +1892,19 @@ free_denyinfo(acl_deny_info_list ** list) acl_deny_info_list *a_next = NULL; acl_name_list *l = NULL; acl_name_list *l_next = NULL; + for (a = *list; a; a = a_next) { - for (l = a->acl_list; l; l = l_next) { - l_next = l->next; - memFree(l, MEM_ACL_NAME_LIST); - l = NULL; - } - a_next = a->next; - memFree(a, MEM_ACL_DENY_INFO_LIST); - a = NULL; + for (l = a->acl_list; l; l = l_next) { + l_next = l->next; + memFree(l, MEM_ACL_NAME_LIST); + l = NULL; + } + + a_next = a->next; + memFree(a, MEM_ACL_DENY_INFO_LIST); + a = NULL; } + *list = NULL; } @@ -1623,13 +1913,16 @@ parse_peer_access(void) { char *host = NULL; peer *p; + if (!(host = strtok(NULL, w_space))) - self_destruct(); + self_destruct(); + if ((p = peerFindByName(host)) == NULL) { - debug(15, 0) ("%s, line %d: No cache_peer '%s'\n", - cfg_filename, config_lineno, host); - return; + debug(15, 0) ("%s, line %d: No cache_peer '%s'\n", + cfg_filename, config_lineno, host); + return; } + aclParseAccessLine(&p->access); } @@ -1638,26 +1931,35 @@ parse_hostdomain(void) { char *host = NULL; char *domain = NULL; + if (!(host = strtok(NULL, w_space))) - self_destruct(); + self_destruct(); + while ((domain = strtok(NULL, list_sep))) { - domain_ping *l = NULL; - domain_ping **L = NULL; - peer *p; - if ((p = peerFindByName(host)) == NULL) { - debug(15, 0) ("%s, line %d: No cache_peer '%s'\n", - cfg_filename, config_lineno, host); - continue; - } - l = static_cast(xcalloc(1, sizeof(domain_ping))); - l->do_ping = 1; - if (*domain == '!') { /* check for !.edu */ - l->do_ping = 0; - domain++; - } - l->domain = xstrdup(domain); - for (L = &(p->peer_domain); *L; L = &((*L)->next)); - *L = l; + domain_ping *l = NULL; + domain_ping **L = NULL; + peer *p; + + if ((p = peerFindByName(host)) == NULL) { + debug(15, 0) ("%s, line %d: No cache_peer '%s'\n", + cfg_filename, config_lineno, host); + continue; + } + + l = static_cast(xcalloc(1, sizeof(domain_ping))); + l->do_ping = 1; + + if (*domain == '!') { /* check for !.edu */ + l->do_ping = 0; + domain++; + } + + l->domain = xstrdup(domain); + + for (L = &(p->peer_domain); *L; L = &((*L)->next)) + + ; + *L = l; } } @@ -1667,24 +1969,32 @@ parse_hostdomaintype(void) char *host = NULL; char *type = NULL; char *domain = NULL; + if (!(host = strtok(NULL, w_space))) - self_destruct(); + self_destruct(); + if (!(type = strtok(NULL, w_space))) - self_destruct(); + self_destruct(); + while ((domain = strtok(NULL, list_sep))) { - domain_type *l = NULL; - domain_type **L = NULL; - peer *p; - if ((p = peerFindByName(host)) == NULL) { - debug(15, 0) ("%s, line %d: No cache_peer '%s'\n", - cfg_filename, config_lineno, host); - return; - } - l = static_cast(xcalloc(1, sizeof(domain_type))); - l->type = parseNeighborType(type); - l->domain = xstrdup(domain); - for (L = &(p->typelist); *L; L = &((*L)->next)); - *L = l; + domain_type *l = NULL; + domain_type **L = NULL; + peer *p; + + if ((p = peerFindByName(host)) == NULL) { + debug(15, 0) ("%s, line %d: No cache_peer '%s'\n", + cfg_filename, config_lineno, host); + return; + } + + l = static_cast(xcalloc(1, sizeof(domain_type))); + l->type = parseNeighborType(type); + l->domain = xstrdup(domain); + + for (L = &(p->typelist); *L; L = &((*L)->next)) + + ; + *L = l; } } @@ -1693,8 +2003,8 @@ static void dump_ushortlist(StoreEntry * entry, const char *name, ushortlist * u) { while (u) { - storeAppendPrintf(entry, "%s %d\n", name, (int) u->i); - u = u->next; + storeAppendPrintf(entry, "%s %d\n", name, (int) u->i); + u = u->next; } } @@ -1711,15 +2021,22 @@ parse_ushortlist(ushortlist ** P) int i; ushortlist *u; ushortlist **U; + while ((token = strtok(NULL, w_space))) { - if (sscanf(token, "%d", &i) != 1) - self_destruct(); - if (i < 0) - i = 0; - u = xcalloc(1, sizeof(ushortlist)); - u->i = (u_short) i; - for (U = P; *U; U = &(*U)->next); - *U = u; + if (sscanf(token, "%d", &i) != 1) + self_destruct(); + + if (i < 0) + i = 0; + + u = xcalloc(1, sizeof(ushortlist)); + + u->i = (u_short) i; + + for (U = P; *U; U = &(*U)->next) + + ; + *U = u; } } @@ -1727,11 +2044,13 @@ static void free_ushortlist(ushortlist ** P) { ushortlist *u; + while ((u = *P) != NULL) { - *P = u->next; - xfree(u); + *P = u->next; + xfree(u); } } + #endif static void @@ -1766,11 +2085,12 @@ parse_onoff(int *var) char *token = strtok(NULL, w_space); if (token == NULL) - self_destruct(); + self_destruct(); + if (!strcasecmp(token, "on") || !strcasecmp(token, "enable")) - *var = 1; + *var = 1; else - *var = 0; + *var = 0; } #define free_onoff free_int @@ -1781,25 +2101,32 @@ static void dump_refreshpattern(StoreEntry * entry, const char *name, refresh_t * head) { while (head != NULL) { - storeAppendPrintf(entry, "%s%s %s %d %d%% %d\n", - name, - head->flags.icase ? " -i" : null_string, - head->pattern, - (int) head->min / 60, - (int) (100.0 * head->pct + 0.5), - (int) head->max / 60); + storeAppendPrintf(entry, "%s%s %s %d %d%% %d\n", + name, + head->flags.icase ? " -i" : null_string, + head->pattern, + (int) head->min / 60, + (int) (100.0 * head->pct + 0.5), + (int) head->max / 60); #if HTTP_VIOLATIONS - if (head->flags.override_expire) - storeAppendPrintf(entry, " override-expire"); - if (head->flags.override_lastmod) - storeAppendPrintf(entry, " override-lastmod"); - if (head->flags.reload_into_ims) - storeAppendPrintf(entry, " reload-into-ims"); - if (head->flags.ignore_reload) - storeAppendPrintf(entry, " ignore-reload"); + + if (head->flags.override_expire) + storeAppendPrintf(entry, " override-expire"); + + if (head->flags.override_lastmod) + storeAppendPrintf(entry, " override-lastmod"); + + if (head->flags.reload_into_ims) + storeAppendPrintf(entry, " reload-into-ims"); + + if (head->flags.ignore_reload) + storeAppendPrintf(entry, " ignore-reload"); + #endif - storeAppendPrintf(entry, "\n"); - head = head->next; + + storeAppendPrintf(entry, "\n"); + + head = head->next; } } @@ -1812,63 +2139,80 @@ parse_refreshpattern(refresh_t ** head) double pct = 0.0; time_t max = 0; #if HTTP_VIOLATIONS + int override_expire = 0; int override_lastmod = 0; int reload_into_ims = 0; int ignore_reload = 0; #endif + int i; refresh_t *t; regex_t comp; int errcode; int flags = REG_EXTENDED | REG_NOSUB; + if ((token = strtok(NULL, w_space)) == NULL) - self_destruct(); + self_destruct(); + if (strcmp(token, "-i") == 0) { - flags |= REG_ICASE; - token = strtok(NULL, w_space); + flags |= REG_ICASE; + token = strtok(NULL, w_space); } else if (strcmp(token, "+i") == 0) { - flags &= ~REG_ICASE; - token = strtok(NULL, w_space); + flags &= ~REG_ICASE; + token = strtok(NULL, w_space); } + if (token == NULL) - self_destruct(); + self_destruct(); + pattern = xstrdup(token); + i = GetInteger(); /* token: min */ + min = (time_t) (i * 60); /* convert minutes to seconds */ + i = GetInteger(); /* token: pct */ + pct = (double) i / 100.0; + i = GetInteger(); /* token: max */ + max = (time_t) (i * 60); /* convert minutes to seconds */ + /* Options */ while ((token = strtok(NULL, w_space)) != NULL) { #if HTTP_VIOLATIONS - if (!strcmp(token, "override-expire")) - override_expire = 1; - else if (!strcmp(token, "override-lastmod")) - override_lastmod = 1; - else if (!strcmp(token, "reload-into-ims")) { - reload_into_ims = 1; - refresh_nocache_hack = 1; - /* tell client_side.c that this is used */ - } else if (!strcmp(token, "ignore-reload")) { - ignore_reload = 1; - refresh_nocache_hack = 1; - /* tell client_side.c that this is used */ - } else + + if (!strcmp(token, "override-expire")) + override_expire = 1; + else if (!strcmp(token, "override-lastmod")) + override_lastmod = 1; + else if (!strcmp(token, "reload-into-ims")) { + reload_into_ims = 1; + refresh_nocache_hack = 1; + /* tell client_side.c that this is used */ + } else if (!strcmp(token, "ignore-reload")) { + ignore_reload = 1; + refresh_nocache_hack = 1; + /* tell client_side.c that this is used */ + } else #endif - debug(22, 0) ("redreshAddToList: Unknown option '%s': %s\n", - pattern, token); + + debug(22, 0) ("redreshAddToList: Unknown option '%s': %s\n", + pattern, token); } + if ((errcode = regcomp(&comp, pattern, flags)) != 0) { - char errbuf[256]; - regerror(errcode, &comp, errbuf, sizeof errbuf); - debug(22, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(22, 0) ("refreshAddToList: Invalid regular expression '%s': %s\n", - pattern, errbuf); - return; + char errbuf[256]; + regerror(errcode, &comp, errbuf, sizeof errbuf); + debug(22, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(22, 0) ("refreshAddToList: Invalid regular expression '%s': %s\n", + pattern, errbuf); + return; } + pct = pct < 0.0 ? 0.0 : pct; max = max < 0 ? 0 : max; t = static_cast(xcalloc(1, sizeof(refresh_t))); @@ -1877,22 +2221,33 @@ parse_refreshpattern(refresh_t ** head) t->min = min; t->pct = pct; t->max = max; + if (flags & REG_ICASE) - t->flags.icase = 1; + t->flags.icase = 1; + #if HTTP_VIOLATIONS + if (override_expire) - t->flags.override_expire = 1; + t->flags.override_expire = 1; + if (override_lastmod) - t->flags.override_lastmod = 1; + t->flags.override_lastmod = 1; + if (reload_into_ims) - t->flags.reload_into_ims = 1; + t->flags.reload_into_ims = 1; + if (ignore_reload) - t->flags.ignore_reload = 1; + t->flags.ignore_reload = 1; + #endif + t->next = NULL; + while (*head) - head = &(*head)->next; + head = &(*head)->next; + *head = t; + safe_free(pattern); } @@ -1902,17 +2257,19 @@ check_null_refreshpattern(refresh_t * data) { return data == NULL; } + #endif static void free_refreshpattern(refresh_t ** head) { refresh_t *t; + while ((t = *head) != NULL) { - *head = t->next; - safe_free(t->pattern); - regfree(&t->compiled_pattern); - safe_free(t); + *head = t->next; + safe_free(t->pattern); + regfree(&t->compiled_pattern); + safe_free(t); } } @@ -1920,7 +2277,7 @@ static void dump_string(StoreEntry * entry, const char *name, char *var) { if (var != NULL) - storeAppendPrintf(entry, "%s %s\n", name, var); + storeAppendPrintf(entry, "%s %s\n", name, var); } static void @@ -1928,8 +2285,10 @@ parse_string(char **var) { char *token = strtok(NULL, w_space); safe_free(*var); + if (token == NULL) - self_destruct(); + self_destruct(); + *var = xstrdup(token); } @@ -1944,12 +2303,16 @@ parse_eol(char *volatile *var) { unsigned char *token = (unsigned char *) strtok(NULL, null_string); safe_free(*var); + if (token == NULL) - self_destruct(); + self_destruct(); + while (*token && isspace(*token)) - token++; + token++; + if (!*token) - self_destruct(); + self_destruct(); + *var = xstrdup((char *) token); } @@ -2022,21 +2385,26 @@ dump_body_size_t(StoreEntry * entry, const char *name, dlink_list bodylist) { body_size *bs; bs = (body_size *) bodylist.head; + while (bs) { - acl_list *l; - acl_access *head = bs->access_list; - while (head != NULL) { - storeAppendPrintf(entry, "%s %ld %s", name, (long int) bs->maxsize, - head->allow ? "Allow" : "Deny"); - for (l = head->aclList; l != NULL; l = l->next) { - storeAppendPrintf(entry, " %s%s", - l->op ? null_string : "!", - l->_acl->name); - } - storeAppendPrintf(entry, "\n"); - head = head->next; - } - bs = (body_size *) bs->node.next; + acl_list *l; + acl_access *head = bs->access_list; + + while (head != NULL) { + storeAppendPrintf(entry, "%s %ld %s", name, (long int) bs->maxsize, + head->allow ? "Allow" : "Deny"); + + for (l = head->aclList; l != NULL; l = l->next) { + storeAppendPrintf(entry, " %s%s", + l->op ? null_string : "!", + l->_acl->name); + } + + storeAppendPrintf(entry, "\n"); + head = head->next; + } + + bs = (body_size *) bs->node.next; } } @@ -2045,13 +2413,14 @@ free_body_size_t(dlink_list * bodylist) { body_size *bs, *tempnode; bs = (body_size *) bodylist->head; + while (bs) { - bs->maxsize = 0; - aclDestroyAccessList(&bs->access_list); - tempnode = (body_size *) bs->node.next; - dlinkDelete(&bs->node, bodylist); - cbdataFree(bs); - bs = tempnode; + bs->maxsize = 0; + aclDestroyAccessList(&bs->access_list); + tempnode = (body_size *) bs->node.next; + dlinkDelete(&bs->node, bodylist); + cbdataFree(bs); + bs = tempnode; } } @@ -2103,8 +2472,10 @@ ConfigParser::ParseUShort(u_short *var) int i; i = GetInteger(); + if (i < 0) - i = 0; + i = 0; + *var = (u_short) i; } @@ -2112,8 +2483,8 @@ static void dump_wordlist(StoreEntry * entry, const char *name, wordlist * list) { while (list != NULL) { - storeAppendPrintf(entry, "%s %s\n", name, list->key); - list = list->next; + storeAppendPrintf(entry, "%s %s\n", name, list->key); + list = list->next; } } @@ -2122,8 +2493,9 @@ parse_wordlist(wordlist ** list) { char *token; char *t = strtok(NULL, ""); + while ((token = strwordtok(NULL, &t))) - wordlistAdd(list, token); + wordlistAdd(list, token); } static int @@ -2146,20 +2518,22 @@ static void parse_uri_whitespace(int *var) { char *token = strtok(NULL, w_space); + if (token == NULL) - self_destruct(); + self_destruct(); + if (!strcasecmp(token, "strip")) - *var = URI_WHITESPACE_STRIP; + *var = URI_WHITESPACE_STRIP; else if (!strcasecmp(token, "deny")) - *var = URI_WHITESPACE_DENY; + *var = URI_WHITESPACE_DENY; else if (!strcasecmp(token, "allow")) - *var = URI_WHITESPACE_ALLOW; + *var = URI_WHITESPACE_ALLOW; else if (!strcasecmp(token, "encode")) - *var = URI_WHITESPACE_ENCODE; + *var = URI_WHITESPACE_ENCODE; else if (!strcasecmp(token, "chop")) - *var = URI_WHITESPACE_CHOP; + *var = URI_WHITESPACE_CHOP; else - self_destruct(); + self_destruct(); } @@ -2167,16 +2541,18 @@ static void dump_uri_whitespace(StoreEntry * entry, const char *name, int var) { const char *s; + if (var == URI_WHITESPACE_ALLOW) - s = "allow"; + s = "allow"; else if (var == URI_WHITESPACE_ENCODE) - s = "encode"; + s = "encode"; else if (var == URI_WHITESPACE_CHOP) - s = "chop"; + s = "chop"; else if (var == URI_WHITESPACE_DENY) - s = "deny"; + s = "deny"; else - s = "strip"; + s = "strip"; + storeAppendPrintf(entry, "%s %s\n", name, s); } @@ -2184,10 +2560,14 @@ static void free_removalpolicy(RemovalPolicySettings ** settings) { if (!*settings) - return; + return; + free_string(&(*settings)->type); + free_wordlist(&(*settings)->args); + xfree(*settings); + *settings = NULL; } @@ -2195,9 +2575,12 @@ static void parse_removalpolicy(RemovalPolicySettings ** settings) { if (*settings) - free_removalpolicy(settings); + free_removalpolicy(settings); + *settings = static_cast(xcalloc(1, sizeof(**settings))); + parse_string(&(*settings)->type); + parse_wordlist(&(*settings)->args); } @@ -2207,10 +2590,12 @@ dump_removalpolicy(StoreEntry * entry, const char *name, RemovalPolicySettings * wordlist *args; storeAppendPrintf(entry, "%s %s", name, settings->type); args = settings->args; + while (args) { - storeAppendPrintf(entry, " %s", args->key); - args = args->next; + storeAppendPrintf(entry, " %s", args->key); + args = args->next; } + storeAppendPrintf(entry, "\n"); } @@ -2221,16 +2606,22 @@ peer_t parseNeighborType(const char *s) { if (!strcasecmp(s, "parent")) - return PEER_PARENT; + return PEER_PARENT; + if (!strcasecmp(s, "neighbor")) - return PEER_SIBLING; + return PEER_SIBLING; + if (!strcasecmp(s, "neighbour")) - return PEER_SIBLING; + return PEER_SIBLING; + if (!strcasecmp(s, "sibling")) - return PEER_SIBLING; + return PEER_SIBLING; + if (!strcasecmp(s, "multicast")) - return PEER_MULTICAST; + return PEER_MULTICAST; + debug(15, 0) ("WARNING: Unknown neighbor type: %s\n", s); + return PEER_SIBLING; } @@ -2243,36 +2634,43 @@ parse_sockaddr_in_list_token(sockaddr_in_list ** head, char *token) { char *t; char *host; + const struct hostent *hp; unsigned short port; sockaddr_in_list *s; host = NULL; port = 0; + if ((t = strchr(token, ':'))) { - /* host:port */ - host = token; - *t = '\0'; - port = (unsigned short) xatoi(t + 1); - if (0 == port) - self_destruct(); + /* host:port */ + host = token; + *t = '\0'; + port = (unsigned short) xatoi(t + 1); + + if (0 == port) + self_destruct(); } else if ((port = xatoi(token)) > 0) { - /* port */ + /* port */ } else { - self_destruct(); + self_destruct(); } + s = static_cast(xcalloc(1, sizeof(*s))); s->s.sin_port = htons(port); + if (NULL == host) - s->s.sin_addr = any_addr; + s->s.sin_addr = any_addr; else if (1 == safe_inet_addr(host, &s->s.sin_addr)) - (void) 0; + (void) 0; else if ((hp = gethostbyname(host))) /* dont use ipcache */ - s->s.sin_addr = inaddrFromHostent(hp); + s->s.sin_addr = inaddrFromHostent(hp); else - self_destruct(); + self_destruct(); + while (*head) - head = &(*head)->next; + head = &(*head)->next; + *head = s; } @@ -2280,8 +2678,9 @@ static void parse_sockaddr_in_list(sockaddr_in_list ** head) { char *token; + while ((token = strtok(NULL, w_space))) { - parse_sockaddr_in_list_token(head, token); + parse_sockaddr_in_list_token(head, token); } } @@ -2289,11 +2688,11 @@ static void dump_sockaddr_in_list(StoreEntry * e, const char *n, const sockaddr_in_list * s) { while (s) { - storeAppendPrintf(e, "%s %s:%d\n", - n, - inet_ntoa(s->s.sin_addr), - ntohs(s->s.sin_port)); - s = s->next; + storeAppendPrintf(e, "%s %s:%d\n", + n, + inet_ntoa(s->s.sin_addr), + ntohs(s->s.sin_port)); + s = s->next; } } @@ -2301,9 +2700,10 @@ static void free_sockaddr_in_list(sockaddr_in_list ** head) { sockaddr_in_list *s; + while ((s = *head) != NULL) { - *head = s->next; - xfree(s); + *head = s->next; + xfree(s); } } @@ -2312,68 +2712,74 @@ check_null_sockaddr_in_list(const sockaddr_in_list * s) { return NULL == s; } + #endif /* CURRENTLY_UNUSED */ static void parse_http_port_specification(http_port_list * s, char *token) { char *host = NULL; + const struct hostent *hp; unsigned short port = 0; char *t; + if ((t = strchr(token, ':'))) { - /* host:port */ - host = token; - *t = '\0'; - port = (unsigned short) atoi(t + 1); - if (0 == port) - self_destruct(); + /* host:port */ + host = token; + *t = '\0'; + port = (unsigned short) atoi(t + 1); + + if (0 == port) + self_destruct(); } else if ((port = atoi(token)) > 0) { - /* port */ + /* port */ } else { - self_destruct(); + self_destruct(); } + s->s.sin_port = htons(port); + if (NULL == host) - s->s.sin_addr = any_addr; + s->s.sin_addr = any_addr; else if (1 == safe_inet_addr(host, &s->s.sin_addr)) - (void) 0; + (void) 0; else if ((hp = gethostbyname(host))) { - /* dont use ipcache */ - s->s.sin_addr = inaddrFromHostent(hp); - s->defaultsite = xstrdup(host); + /* dont use ipcache */ + s->s.sin_addr = inaddrFromHostent(hp); + s->defaultsite = xstrdup(host); } else - self_destruct(); + self_destruct(); } static void parse_http_port_option(http_port_list * s, char *token) { if (strncmp(token, "defaultsite=", 12) == 0) { - safe_free(s->defaultsite); - s->defaultsite = xstrdup(token + 12); - s->accel = 1; + safe_free(s->defaultsite); + s->defaultsite = xstrdup(token + 12); + s->accel = 1; } else if (strncmp(token, "name=", 5) == 0) { - safe_free(s->name); - s->name = xstrdup(token + 5); + safe_free(s->name); + s->name = xstrdup(token + 5); } else if (strcmp(token, "transparent") == 0) { - s->transparent = 1; + s->transparent = 1; } else if (strcmp(token, "vhost") == 0) { - s->vhost = 1; - s->accel = 1; + s->vhost = 1; + s->accel = 1; } else if (strcmp(token, "vport") == 0) { - s->vport = -1; - s->accel = 1; + s->vport = -1; + s->accel = 1; } else if (strncmp(token, "vport=", 6) == 0) { - s->vport = atoi(token + 6); - s->accel = 1; + s->vport = atoi(token + 6); + s->accel = 1; } else if (strncmp(token, "protocol=", 9) == 0) { - s->protocol = xstrdup(token + 9); - s->accel = 1; + s->protocol = xstrdup(token + 9); + s->accel = 1; } else if (strcmp(token, "accel") == 0) { - s->accel = 1; + s->accel = 1; } else { - self_destruct(); + self_destruct(); } } @@ -2415,15 +2821,20 @@ static void parse_http_port_list(http_port_list ** head) { char *token = strtok(NULL, w_space); + if (!token) - self_destruct(); + self_destruct(); + http_port_list *s = create_http_port(token); + /* parse options ... */ while ((token = strtok(NULL, w_space))) { - parse_http_port_option(s, token); + parse_http_port_option(s, token); } + while (*head) - head = &(*head)->next; + head = &(*head)->next; + *head = s; } @@ -2431,25 +2842,30 @@ static void dump_generic_http_port(StoreEntry * e, const char *n, const http_port_list * s) { storeAppendPrintf(e, "%s %s:%d", - n, - inet_ntoa(s->s.sin_addr), - ntohs(s->s.sin_port)); + n, + inet_ntoa(s->s.sin_addr), + ntohs(s->s.sin_port)); + if (s->defaultsite) - storeAppendPrintf(e, " defaultsite=%s", s->defaultsite); + storeAppendPrintf(e, " defaultsite=%s", s->defaultsite); + if (s->transparent) - storeAppendPrintf(e, " transparent"); + storeAppendPrintf(e, " transparent"); + if (s->vhost) - storeAppendPrintf(e, " vhost"); + storeAppendPrintf(e, " vhost"); + if (s->vport) - storeAppendPrintf(e, " vport"); + storeAppendPrintf(e, " vport"); } + static void dump_http_port_list(StoreEntry * e, const char *n, const http_port_list * s) { while (s) { - dump_generic_http_port(e, n, s); - storeAppendPrintf(e, "\n"); - s = s->next; + dump_generic_http_port(e, n, s); + storeAppendPrintf(e, "\n"); + s = s->next; } } @@ -2457,9 +2873,10 @@ static void free_http_port_list(http_port_list ** head) { http_port_list *s; + while ((s = *head) != NULL) { - *head = s->next; - cbdataFree(s); + *head = s->next; + cbdataFree(s); } } @@ -2469,6 +2886,7 @@ check_null_http_port_list(const http_port_list * s) { return NULL == s; } + #endif #if USE_SSL @@ -2489,48 +2907,57 @@ parse_https_port_list(https_port_list ** head) https_port_list *s; CBDATA_INIT_TYPE_FREECB(https_port_list, cbdataFree_https_port); token = strtok(NULL, w_space); + if (!token) - self_destruct(); + self_destruct(); + s = cbdataAlloc(https_port_list); + s->http.protocol = xstrdup("https"); + parse_http_port_specification(&s->http, token); + /* parse options ... */ while ((token = strtok(NULL, w_space))) { - if (strncmp(token, "cert=", 5) == 0) { - safe_free(s->cert); - s->cert = xstrdup(token + 5); - } else if (strncmp(token, "key=", 4) == 0) { - safe_free(s->key); - s->key = xstrdup(token + 4); - } else if (strncmp(token, "version=", 8) == 0) { - s->version = xatoi(token + 8); - } else if (strncmp(token, "options=", 8) == 0) { - safe_free(s->options); - s->options = xstrdup(token + 8); - } else if (strncmp(token, "cipher=", 7) == 0) { - safe_free(s->cipher); - s->cipher = xstrdup(token + 7); - } else if (strncmp(token, "clientca=", 9) == 0) { - safe_free(s->clientca); - s->clientca = xstrdup(token + 9); - } else if (strncmp(token, "cafile=", 7) == 0) { - safe_free(s->cafile); - s->cafile = xstrdup(token + 7); - } else if (strncmp(token, "capath=", 7) == 0) { - safe_free(s->capath); - s->capath = xstrdup(token + 7); - } else if (strncmp(token, "sslflags=", 9) == 0) { - safe_free(s->sslflags); - s->sslflags = xstrdup(token + 9); - } else { - parse_http_port_option(&s->http, token); - } + if (strncmp(token, "cert=", 5) == 0) { + safe_free(s->cert); + s->cert = xstrdup(token + 5); + } else if (strncmp(token, "key=", 4) == 0) { + safe_free(s->key); + s->key = xstrdup(token + 4); + } else if (strncmp(token, "version=", 8) == 0) { + s->version = xatoi(token + 8); + } else if (strncmp(token, "options=", 8) == 0) { + safe_free(s->options); + s->options = xstrdup(token + 8); + } else if (strncmp(token, "cipher=", 7) == 0) { + safe_free(s->cipher); + s->cipher = xstrdup(token + 7); + } else if (strncmp(token, "clientca=", 9) == 0) { + safe_free(s->clientca); + s->clientca = xstrdup(token + 9); + } else if (strncmp(token, "cafile=", 7) == 0) { + safe_free(s->cafile); + s->cafile = xstrdup(token + 7); + } else if (strncmp(token, "capath=", 7) == 0) { + safe_free(s->capath); + s->capath = xstrdup(token + 7); + } else if (strncmp(token, "sslflags=", 9) == 0) { + safe_free(s->sslflags); + s->sslflags = xstrdup(token + 9); + } else { + parse_http_port_option(&s->http, token); + } } + s->sslContext = sslCreateServerContext(s->cert, s->key, s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath); + if (!s->sslContext) - self_destruct(); + self_destruct(); + while (*head) - head = (https_port_list **)&(*head)->http.next; + head = (https_port_list **)&(*head)->http.next; + *head = s; } @@ -2538,25 +2965,35 @@ static void dump_https_port_list(StoreEntry * e, const char *n, const https_port_list * s) { while (s) { - dump_generic_http_port(e, n, &s->http); - if (s->cert) - storeAppendPrintf(e, " cert=%s", s->cert); - if (s->key) - storeAppendPrintf(e, " key=%s", s->cert); - if (s->version) - storeAppendPrintf(e, " version=%d", s->version); - if (s->options) - storeAppendPrintf(e, " options=%s", s->options); - if (s->cipher) - storeAppendPrintf(e, " cipher=%s", s->cipher); - if (s->cafile) - storeAppendPrintf(e, " cafile=%s", s->cafile); - if (s->capath) - storeAppendPrintf(e, " capath=%s", s->capath); - if (s->sslflags) - storeAppendPrintf(e, " sslflags=%s", s->sslflags); - storeAppendPrintf(e, "\n"); - s = (https_port_list *) s->http.next; + dump_generic_http_port(e, n, &s->http); + + if (s->cert) + storeAppendPrintf(e, " cert=%s", s->cert); + + if (s->key) + storeAppendPrintf(e, " key=%s", s->cert); + + if (s->version) + storeAppendPrintf(e, " version=%d", s->version); + + if (s->options) + storeAppendPrintf(e, " options=%s", s->options); + + if (s->cipher) + storeAppendPrintf(e, " cipher=%s", s->cipher); + + if (s->cafile) + storeAppendPrintf(e, " cafile=%s", s->cafile); + + if (s->capath) + storeAppendPrintf(e, " capath=%s", s->capath); + + if (s->sslflags) + storeAppendPrintf(e, " sslflags=%s", s->sslflags); + + storeAppendPrintf(e, "\n"); + + s = (https_port_list *) s->http.next; } } @@ -2564,9 +3001,10 @@ static void free_https_port_list(https_port_list ** head) { https_port_list *s; + while ((s = *head) != NULL) { - *head = (https_port_list *) s->http.next; - cbdataFree(s); + *head = (https_port_list *) s->http.next; + cbdataFree(s); } } @@ -2576,6 +3014,7 @@ check_null_https_port_list(const https_port_list * s) { return NULL == s; } + #endif #endif /* USE_SSL */ @@ -2589,15 +3028,18 @@ configFreeMemory(void) void requirePathnameExists(const char *name, const char *path) { + struct stat sb; char pathbuf[BUFSIZ]; assert(path != NULL); + if (Config.chroot_dir) { - snprintf(pathbuf, BUFSIZ, "%s/%s", Config.chroot_dir, path); - path = pathbuf; + snprintf(pathbuf, BUFSIZ, "%s/%s", Config.chroot_dir, path); + path = pathbuf; } + if (stat(path, &sb) < 0) - fatalf("%s %s: %s", name, path, xstrerror()); + fatalf("%s %s: %s", name, path, xstrerror()); } char * @@ -2609,54 +3051,68 @@ strtokFile(void) char *t, *fn; LOCAL_ARRAY(char, buf, 256); - strtok_again: +strtok_again: + if (!fromFile) { - t = (strtok(NULL, w_space)); - if (!t || *t == '#') { - return NULL; - } else if (*t == '\"' || *t == '\'') { - /* quote found, start reading from file */ - fn = ++t; - while (*t && *t != '\"' && *t != '\'') - t++; - *t = '\0'; - if ((wordFile = fopen(fn, "r")) == NULL) { - debug(28, 0) ("strtokFile: %s not found\n", fn); - return (NULL); - } + t = (strtok(NULL, w_space)); + + if (!t || *t == '#') { + return NULL; + } else if (*t == '\"' || *t == '\'') { + /* quote found, start reading from file */ + fn = ++t; + + while (*t && *t != '\"' && *t != '\'') + t++; + + *t = '\0'; + + if ((wordFile = fopen(fn, "r")) == NULL) { + debug(28, 0) ("strtokFile: %s not found\n", fn); + return (NULL); + } + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - setmode(fileno(wordFile), O_TEXT); + setmode(fileno(wordFile), O_TEXT); + #endif - fromFile = 1; - } else { - return t; - } + + fromFile = 1; + } else { + return t; + } } + /* fromFile */ if (fgets(buf, 256, wordFile) == NULL) { - /* stop reading from file */ - fclose(wordFile); - wordFile = NULL; - fromFile = 0; - goto strtok_again; + /* stop reading from file */ + fclose(wordFile); + wordFile = NULL; + fromFile = 0; + goto strtok_again; } else { - char *t2, *t3; - t = buf; - /* skip leading and trailing white space */ - t += strspn(buf, w_space); - t2 = t + strcspn(t, w_space); - t3 = t2 + strspn(t2, w_space); - while (*t3 && *t3 != '#') { - t2 = t3 + strcspn(t3, w_space); - t3 = t2 + strspn(t2, w_space); - } - *t2 = '\0'; - /* skip comments */ - if (*t == '#') - goto strtok_again; - /* skip blank lines */ - if (!*t) - goto strtok_again; - return t; + char *t2, *t3; + t = buf; + /* skip leading and trailing white space */ + t += strspn(buf, w_space); + t2 = t + strcspn(t, w_space); + t3 = t2 + strspn(t2, w_space); + + while (*t3 && *t3 != '#') { + t2 = t3 + strcspn(t3, w_space); + t3 = t2 + strspn(t2, w_space); + } + + *t2 = '\0'; + /* skip comments */ + + if (*t == '#') + goto strtok_again; + + /* skip blank lines */ + if (!*t) + goto strtok_again; + + return t; } } diff --git a/src/cache_diff.cc b/src/cache_diff.cc index a8682c612e..00ba8800b0 100644 --- a/src/cache_diff.cc +++ b/src/cache_diff.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_diff.cc,v 1.17 2003/01/23 00:37:16 robertc Exp $ + * $Id: cache_diff.cc,v 1.18 2003/02/21 22:50:06 robertc Exp $ * * AUTHOR: Alex Rousskov * @@ -40,36 +40,43 @@ #include "squid.h" -typedef struct { +typedef struct +{ const char *name; hash_table *hash; int count; /* #currently cached entries */ int scanned_count; /* #scanned entries */ int bad_add_count; /* #duplicate adds */ int bad_del_count; /* #dels with no prior add */ -} CacheIndex; +} + +CacheIndex; -typedef struct _CacheEntry { +typedef struct _CacheEntry +{ const cache_key *key; + struct _CacheEntry *next; /* storeSwapLogData s; */ unsigned char key_arr[MD5_DIGEST_CHARS]; -} CacheEntry; +} + +CacheEntry; /* copied from url.c */ const char *RequestMethodStr[] = -{ - "NONE", - "GET", - "POST", - "PUT", - "HEAD", - "CONNECT", - "TRACE", - "PURGE" -}; + { + "NONE", + "GET", + "POST", + "PUT", + "HEAD", + "CONNECT", + "TRACE", + "PURGE" + }; static int cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file); @@ -97,11 +104,14 @@ static CacheIndex * cacheIndexCreate(const char *name) { CacheIndex *idx; + if (!name || !strlen(name)) - return NULL; + return NULL; idx = xcalloc(1, sizeof(CacheIndex)); + idx->name = name; + idx->hash = hash_create(storeKeyHashCmp, 2e6, storeKeyHashHash); return idx; @@ -111,16 +121,20 @@ static void cacheIndexDestroy(CacheIndex * idx) { hash_link *hashr = NULL; + if (idx) { - /* destroy hash list contents */ - hash_first(idx->hash); - while (hashr = hash_next(idx->hash)) { - hash_remove_link(idx->hash, hashr); - cacheEntryDestroy((CacheEntry *) hashr); - } - /* destroy the hash table itself */ - hashFreeMemory(idx->hash); - xfree(idx); + /* destroy hash list contents */ + hash_first(idx->hash); + + while (hashr = hash_next(idx->hash)) { + hash_remove_link(idx->hash, hashr); + cacheEntryDestroy((CacheEntry *) hashr); + } + + /* destroy the hash table itself */ + hashFreeMemory(idx->hash); + + xfree(idx); } } @@ -133,16 +147,21 @@ cacheIndexAddLog(CacheIndex * idx, const char *fname) assert(fname && strlen(fname)); file = fopen(fname, "r"); + if (!file) { - fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno)); - return 0; + fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno)); + return 0; } + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) setmode(fileno(file), O_BINARY); + #endif + scanned_count = cacheIndexScan(idx, fname, file); fclose(file); + return scanned_count; } @@ -151,11 +170,11 @@ cacheIndexInitReport(CacheIndex * idx) { assert(idx); fprintf(stderr, "%s: bad swap_add: %d\n", - idx->name, idx->bad_add_count); + idx->name, idx->bad_add_count); fprintf(stderr, "%s: bad swap_del: %d\n", - idx->name, idx->bad_del_count); + idx->name, idx->bad_del_count); fprintf(stderr, "%s: scanned lines: %d\n", - idx->name, idx->scanned_count); + idx->name, idx->scanned_count); } static int @@ -164,37 +183,42 @@ cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file) int count = 0; storeSwapLogData s; fprintf(stderr, "%s scanning\n", fname); + while (fread(&s, sizeof(s), 1, file) == 1) { - count++; - idx->scanned_count++; - /* if (s.op <= SWAP_LOG_NOP || s.op >= SWAP_LOG_MAX) - * continue; */ - if (s.op == SWAP_LOG_ADD) { - CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); - if (olde) { - idx->bad_add_count++; - } else { - CacheEntry *e = cacheEntryCreate(&s); - hash_join(idx->hash, &e->hash); - idx->count++; - } - } else if (s.op == SWAP_LOG_DEL) { - CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); - if (!olde) - idx->bad_del_count++; - else { - assert(idx->count); - hash_remove_link(idx->hash, (hash_link *) olde); - cacheEntryDestroy(olde); - idx->count--; - } - } else { - fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count); - exit(-3); - } + count++; + idx->scanned_count++; + /* if (s.op <= SWAP_LOG_NOP || s.op >= SWAP_LOG_MAX) + * continue; */ + + if (s.op == SWAP_LOG_ADD) { + CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); + + if (olde) { + idx->bad_add_count++; + } else { + CacheEntry *e = cacheEntryCreate(&s); + hash_join(idx->hash, &e->hash); + idx->count++; + } + } else if (s.op == SWAP_LOG_DEL) { + CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); + + if (!olde) + idx->bad_del_count++; + else { + assert(idx->count); + hash_remove_link(idx->hash, (hash_link *) olde); + cacheEntryDestroy(olde); + idx->count--; + } + } else { + fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count); + exit(-3); + } } + fprintf(stderr, "%s:%d: scanned (size: %d bytes)\n", - fname, count, (int) (count * sizeof(CacheEntry))); + fname, count, (int) (count * sizeof(CacheEntry))); return count; } @@ -204,12 +228,12 @@ cacheIndexCmpReport(CacheIndex * idx, int shared_count) assert(idx && shared_count <= idx->count); printf("%s:\t %7d = %7d + %7d (%7.2f%% + %7.2f%%)\n", - idx->name, - idx->count, - idx->count - shared_count, - shared_count, - xpercent(idx->count - shared_count, idx->count), - xpercent(shared_count, idx->count)); + idx->name, + idx->count, + idx->count - shared_count, + shared_count, + xpercent(idx->count - shared_count, idx->count), + xpercent(shared_count, idx->count)); } static void @@ -223,17 +247,22 @@ cacheIndexCmp(CacheIndex * idx1, CacheIndex * idx2) assert(idx1 && idx2); /* check our guess */ + if (idx1->count > idx2->count) { - small_idx = idx2; - large_idx = idx1; + small_idx = idx2; + large_idx = idx1; } + /* find shared_count */ hash_first(small_idx->hash); + for (hashr = hash_next(small_idx->hash)) { - hashed_count++; - if (hash_lookup(large_idx->hash, hashr->key)) - shared_count++; + hashed_count++; + + if (hash_lookup(large_idx->hash, hashr->key)) + shared_count++; } + assert(hashed_count == small_idx->count); cacheIndexCmpReport(idx1, shared_count); @@ -245,7 +274,7 @@ static int usage(const char *prg_name) { fprintf(stderr, "usage: %s : ... : ...\n", - prg_name); + prg_name); return -1; } @@ -258,34 +287,42 @@ main(int argc, char *argv[]) int i; if (argc < 5) - return usage(argv[0]); + return usage(argv[0]); for (i = 1; i < argc; ++i) { - const int len = strlen(argv[i]); - if (!len) - return usage(argv[0]); - if (argv[i][len - 1] == ':') { - idxCount++; - if (len < 2 || idxCount > 2) - return usage(argv[0]); - idx = cacheIndexCreate(argv[i]); - CacheIdx[idxCount - 1] = idx; - } else { - if (!idx) - return usage(argv[0]); - cacheIndexAddLog(idx, argv[i]); - } + const int len = strlen(argv[i]); + + if (!len) + return usage(argv[0]); + + if (argv[i][len - 1] == ':') { + idxCount++; + + if (len < 2 || idxCount > 2) + return usage(argv[0]); + + idx = cacheIndexCreate(argv[i]); + + CacheIdx[idxCount - 1] = idx; + } else { + if (!idx) + return usage(argv[0]); + + cacheIndexAddLog(idx, argv[i]); + } } if (idxCount != 2) - return usage(argv[0]); + return usage(argv[0]); cacheIndexInitReport(CacheIdx[0]); + cacheIndexInitReport(CacheIdx[1]); cacheIndexCmp(CacheIdx[0], CacheIdx[1]); cacheIndexDestroy(CacheIdx[0]); + cacheIndexDestroy(CacheIdx[1]); return 1; diff --git a/src/cache_manager.cc b/src/cache_manager.cc index 2f054099c6..4ea875b224 100644 --- a/src/cache_manager.cc +++ b/src/cache_manager.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_manager.cc,v 1.28 2003/01/23 00:37:16 robertc Exp $ + * $Id: cache_manager.cc,v 1.29 2003/02/21 22:50:06 robertc Exp $ * * DEBUG: section 16 Cache Manager Objects * AUTHOR: Duane Wessels @@ -41,23 +41,38 @@ #define MGR_PASSWD_SZ 128 -typedef struct { +typedef struct +{ StoreEntry *entry; char *action; char *user_name; char *passwd; -} cachemgrStateData; +} + +cachemgrStateData; -typedef struct _action_table { +typedef struct _action_table +{ char *action; char *desc; OBJH *handler; - struct { - unsigned int pw_req:1; - unsigned int atomic:1; - } flags; + + struct + { + +unsigned int pw_req: + 1; + +unsigned int atomic: + 1; + } + + flags; + struct _action_table *next; -} action_table; +} + +action_table; static action_table *cachemgrFindAction(const char *action); static cachemgrStateData *cachemgrParseUrl(const char *url); @@ -77,10 +92,12 @@ cachemgrRegister(const char *action, const char *desc, OBJH * handler, int pw_re { action_table *a; action_table **A; + if (cachemgrFindAction(action) != NULL) { - debug(16, 3) ("cachemgrRegister: Duplicate '%s'\n", action); - return; + debug(16, 3) ("cachemgrRegister: Duplicate '%s'\n", action); + return; } + assert (strstr (" ", action) == NULL); a = (action_table *)xcalloc(1, sizeof(action_table)); a->action = xstrdup(action); @@ -88,8 +105,12 @@ cachemgrRegister(const char *action, const char *desc, OBJH * handler, int pw_re a->handler = handler; a->flags.pw_req = pw_req_flag; a->flags.atomic = atomic; - for (A = &ActionTable; *A; A = &(*A)->next); + + for (A = &ActionTable; *A; A = &(*A)->next) + + ; *A = a; + debug(16, 3) ("cachemgrRegister: registered %s\n", action); } @@ -97,10 +118,12 @@ static action_table * cachemgrFindAction(const char *action) { action_table *a; + for (a = ActionTable; a != NULL; a = a->next) { - if (0 == strcmp(a->action, action)) - return a; + if (0 == strcmp(a->action, action)) + return a; } + return NULL; } @@ -115,31 +138,39 @@ cachemgrParseUrl(const char *url) cachemgrStateData *mgr = NULL; const char *prot; t = sscanf(url, "cache_object://%[^/]/%[^@]@%s", host, request, password); + if (t < 2) { - xstrncpy(request, "menu", MAX_URL); + xstrncpy(request, "menu", MAX_URL); #ifdef _SQUID_OS2_ - /* - * emx's sscanf insists of returning 2 because it sets request - * to null - */ + /* + * emx's sscanf insists of returning 2 because it sets request + * to null + */ } else if (request[0] == '\0') { - xstrncpy(request, "menu", MAX_URL); + xstrncpy(request, "menu", MAX_URL); #endif + } else if ((a = cachemgrFindAction(request)) == NULL) { - debug(16, 1) ("cachemgrParseUrl: action '%s' not found\n", request); - return NULL; + debug(16, 1) ("cachemgrParseUrl: action '%s' not found\n", request); + return NULL; } else { - prot = cachemgrActionProtection(a); - if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden")) { - debug(16, 1) ("cachemgrParseUrl: action '%s' is %s\n", request, prot); - return NULL; - } + prot = cachemgrActionProtection(a); + + if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden")) { + debug(16, 1) ("cachemgrParseUrl: action '%s' is %s\n", request, prot); + return NULL; + } } + /* set absent entries to NULL so we can test if they are present later */ mgr = (cachemgrStateData *)xcalloc(1, sizeof(cachemgrStateData)); + mgr->user_name = NULL; + mgr->passwd = t == 3 ? xstrdup(password) : NULL; + mgr->action = xstrdup(request); + return mgr; } @@ -150,18 +181,26 @@ cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request) const char *passwd_del; assert(mgr && request); basic_cookie = httpHeaderGetAuth(&request->header, HDR_AUTHORIZATION, "Basic"); + if (!basic_cookie) - return; + return; + if (!(passwd_del = strchr(basic_cookie, ':'))) { - debug(16, 1) ("cachemgrParseHeaders: unknown basic_cookie format '%s'\n", basic_cookie); - return; + debug(16, 1) ("cachemgrParseHeaders: unknown basic_cookie format '%s'\n", basic_cookie); + return; } + /* found user:password pair, reset old values */ safe_free(mgr->user_name); + safe_free(mgr->passwd); + mgr->user_name = xstrdup(basic_cookie); + mgr->user_name[passwd_del - basic_cookie] = '\0'; + mgr->passwd = xstrdup(passwd_del + 1); + /* warning: this prints decoded password which maybe not what you want to do @?@ @?@ */ debug(16, 9) ("cachemgrParseHeaders: got user: '%s' passwd: '%s'\n", mgr->user_name, mgr->passwd); } @@ -175,14 +214,19 @@ cachemgrCheckPassword(cachemgrStateData * mgr) char *pwd = cachemgrPasswdGet(Config.passwd_list, mgr->action); action_table *a = cachemgrFindAction(mgr->action); assert(a != NULL); + if (pwd == NULL) - return a->flags.pw_req; + return a->flags.pw_req; + if (strcmp(pwd, "disable") == 0) - return 1; + return 1; + if (strcmp(pwd, "none") == 0) - return 0; + return 0; + if (!mgr->passwd) - return 1; + return 1; + return strcmp(pwd, mgr->passwd); } @@ -203,77 +247,96 @@ cachemgrStart(int fd, request_t * request, StoreEntry * entry) ErrorState *err = NULL; action_table *a; debug(16, 3) ("objectcacheStart: '%s'\n", storeUrl(entry)); + if ((mgr = cachemgrParseUrl(storeUrl(entry))) == NULL) { - err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND); - err->url = xstrdup(storeUrl(entry)); - errorAppendEntry(entry, err); - entry->expires = squid_curtime; - return; + err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND); + err->url = xstrdup(storeUrl(entry)); + errorAppendEntry(entry, err); + entry->expires = squid_curtime; + return; } + mgr->entry = entry; storeLockObject(entry); entry->expires = squid_curtime; debug(16, 5) ("CACHEMGR: %s requesting '%s'\n", - fd_table[fd].ipaddr, mgr->action); + fd_table[fd].ipaddr, mgr->action); /* get additional info from request headers */ cachemgrParseHeaders(mgr, request); /* Check password */ + if (cachemgrCheckPassword(mgr) != 0) { - /* build error message */ - ErrorState *err; - HttpReply *rep; - err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED); - /* warn if user specified incorrect password */ - if (mgr->passwd) - debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n", - mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); - else - debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n", - mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); - err->request = requestLink(request); - rep = errorBuildReply(err); - errorStateFree(err); - /* - * add Authenticate header, use 'action' as a realm because - * password depends on action - */ - httpHeaderPutAuth(&rep->header, "Basic", mgr->action); - /* store the reply */ - httpReplySwapOut(rep, entry); - entry->expires = squid_curtime; - entry->complete(); - cachemgrStateFree(mgr); - return; + /* build error message */ + ErrorState *err; + HttpReply *rep; + err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED); + /* warn if user specified incorrect password */ + + if (mgr->passwd) + debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n", + mgr->user_name ? mgr->user_name : "", + fd_table[fd].ipaddr, mgr->action); + else + debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n", + mgr->user_name ? mgr->user_name : "", + fd_table[fd].ipaddr, mgr->action); + + err->request = requestLink(request); + + rep = errorBuildReply(err); + + errorStateFree(err); + + /* + * add Authenticate header, use 'action' as a realm because + * password depends on action + */ + httpHeaderPutAuth(&rep->header, "Basic", mgr->action); + + /* store the reply */ + httpReplySwapOut(rep, entry); + + entry->expires = squid_curtime; + + entry->complete(); + + cachemgrStateFree(mgr); + + return; } + debug(16, 1) ("CACHEMGR: %s@%s requesting '%s'\n", - mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); + mgr->user_name ? mgr->user_name : "", + fd_table[fd].ipaddr, mgr->action); /* retrieve object requested */ a = cachemgrFindAction(mgr->action); assert(a != NULL); + if (a->flags.atomic) - storeBuffer(entry); + storeBuffer(entry); + { - http_version_t version; - HttpReply *rep = httpReplyCreate(); - httpBuildVersion(&version, 1, 0); - httpReplySetHeaders(rep, - version, - HTTP_OK, - NULL, - "text/plain", - -1, /* C-Len */ - squid_curtime, /* LMT */ - squid_curtime); - httpReplySwapOut(rep, entry); + http_version_t version; + HttpReply *rep = httpReplyCreate(); + httpBuildVersion(&version, 1, 0); + httpReplySetHeaders(rep, + version, + HTTP_OK, + NULL, + "text/plain", + -1, /* C-Len */ + squid_curtime, /* LMT */ + squid_curtime); + httpReplySwapOut(rep, entry); } + a->handler(entry); + if (a->flags.atomic) { - storeBufferFlush(entry); - entry->complete(); + storeBufferFlush(entry); + entry->complete(); } + cachemgrStateFree(mgr); } @@ -289,9 +352,9 @@ cachemgrOfflineToggle(StoreEntry * sentry) { Config.onoff.offline = !Config.onoff.offline; debug(16, 0) ("offline_mode now %s.\n", - Config.onoff.offline ? "ON" : "OFF"); + Config.onoff.offline ? "ON" : "OFF"); storeAppendPrintf(sentry, "offline_mode is now %s\n", - Config.onoff.offline ? "ON" : "OFF"); + Config.onoff.offline ? "ON" : "OFF"); } static const char * @@ -300,12 +363,16 @@ cachemgrActionProtection(const action_table * at) char *pwd; assert(at); pwd = cachemgrPasswdGet(Config.passwd_list, at->action); + if (!pwd) - return at->flags.pw_req ? "hidden" : "public"; + return at->flags.pw_req ? "hidden" : "public"; + if (!strcmp(pwd, "disable")) - return "disabled"; + return "disabled"; + if (strcmp(pwd, "none") == 0) - return "public"; + return "public"; + return "protected"; } @@ -313,9 +380,10 @@ static void cachemgrMenu(StoreEntry * sentry) { action_table *a; + for (a = ActionTable; a != NULL; a = a->next) { - storeAppendPrintf(sentry, " %-22s\t%s\t%s\n", - a->action, a->desc, cachemgrActionProtection(a)); + storeAppendPrintf(sentry, " %-22s\t%s\t%s\n", + a->action, a->desc, cachemgrActionProtection(a)); } } @@ -323,15 +391,19 @@ static char * cachemgrPasswdGet(cachemgr_passwd * a, const char *action) { wordlist *w; + while (a != NULL) { - for (w = a->actions; w != NULL; w = w->next) { - if (0 == strcmp(w->key, action)) - return a->passwd; - if (0 == strcmp(w->key, "all")) - return a->passwd; - } - a = a->next; + for (w = a->actions; w != NULL; w = w->next) { + if (0 == strcmp(w->key, action)) + return a->passwd; + + if (0 == strcmp(w->key, "all")) + return a->passwd; + } + + a = a->next; } + return NULL; } @@ -339,12 +411,12 @@ void cachemgrInit(void) { cachemgrRegister("menu", - "This Cachemanager Menu", - cachemgrMenu, 0, 1); + "This Cachemanager Menu", + cachemgrMenu, 0, 1); cachemgrRegister("shutdown", - "Shut Down the Squid Process", - cachemgrShutdown, 1, 1); + "Shut Down the Squid Process", + cachemgrShutdown, 1, 1); cachemgrRegister("offline_toggle", - "Toggle offline_mode setting", - cachemgrOfflineToggle, 1, 1); + "Toggle offline_mode setting", + cachemgrOfflineToggle, 1, 1); } diff --git a/src/cachemgr.cc b/src/cachemgr.cc index e56aba7872..1d9bd89e74 100644 --- a/src/cachemgr.cc +++ b/src/cachemgr.cc @@ -1,6 +1,6 @@ /* - * $Id: cachemgr.cc,v 1.103 2003/02/04 21:57:15 robertc Exp $ + * $Id: cachemgr.cc,v 1.104 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 0 CGI Cache Manager * AUTHOR: Duane Wessels @@ -131,14 +131,17 @@ #include "util.h" #include "snprintf.h" -typedef struct { +typedef struct +{ char *hostname; int port; char *action; char *user_name; char *passwd; char *pub_auth; -} cachemgr_request; +} + +cachemgr_request; /* * Debugging macros (info goes to error_log on your web server) @@ -158,6 +161,7 @@ static const time_t passwd_ttl = 60 * 60 * 3; /* in sec */ static const char *script_name = "/cgi-bin/cachemgr.cgi"; static const char *progname = NULL; static time_t now; + static struct in_addr no_addr; /* @@ -193,25 +197,28 @@ int Win32SockInit(void) int err; if (s_iInitCount > 0) { - s_iInitCount++; - return (0); - } - else if (s_iInitCount < 0) - return (s_iInitCount); + s_iInitCount++; + return (0); + } else if (s_iInitCount < 0) + return (s_iInitCount); /* s_iInitCount == 0. Do the initailization */ iVersionRequested = MAKEWORD(2, 0); + err = WSAStartup((WORD) iVersionRequested, &wsaData); + if (err) { - s_iInitCount = -1; - return (s_iInitCount); + s_iInitCount = -1; + return (s_iInitCount); } + if (LOBYTE(wsaData.wVersion) != 2 || - HIBYTE(wsaData.wVersion) != 0) { - s_iInitCount = -2; - WSACleanup(); - return (s_iInitCount); + HIBYTE(wsaData.wVersion) != 0) { + s_iInitCount = -2; + WSACleanup(); + return (s_iInitCount); } + s_iInitCount++; return (s_iInitCount); } @@ -219,9 +226,11 @@ int Win32SockInit(void) void Win32SockCleanup(void) { if (--s_iInitCount == 0) - WSACleanup(); + WSACleanup(); + return; } + #endif /* ifdef _SQUID_MSWIN_ */ static const char * @@ -241,23 +250,28 @@ static const char * xstrtok(char **str, char del) { if (*str) { - char *p = strchr(*str, del); - char *tok = *str; - int len; - if (p) { - *str = p + 1; - *p = '\0'; - } else - *str = NULL; - /* trim */ - len = strlen(tok); - while (len && xisspace(tok[len - 1])) - tok[--len] = '\0'; - while (xisspace(*tok)) - tok++; - return tok; + char *p = strchr(*str, del); + char *tok = *str; + int len; + + if (p) { + *str = p + 1; + *p = '\0'; + } else + *str = NULL; + + /* trim */ + len = strlen(tok); + + while (len && xisspace(tok[len - 1])) + tok[--len] = '\0'; + + while (xisspace(*tok)) + tok++; + + return tok; } else - return ""; + return ""; } static void @@ -266,7 +280,7 @@ print_trailer(void) printf("
\n"); printf("
\n"); printf("Generated %s, by %s/%s@%s\n", - mkrfc1123(now), progname, VERSION, getfullhostname()); + mkrfc1123(now), progname, VERSION, getfullhostname()); printf("
\n"); } @@ -274,30 +288,53 @@ static void auth_html(const char *host, int port, const char *user_name) { if (!user_name) - user_name = ""; + user_name = ""; + if (!host || !strlen(host)) - host = "localhost"; + host = "localhost"; + printf("Content-Type: text/html\r\n\r\n"); + printf("\n"); + printf("Cache Manager Interface\n"); + printf("\n"); + printf("

Cache Manager Interface

\n"); + printf("

This is a WWW interface to the instrumentation interface\n"); + printf("for the Squid object cache.

\n"); + printf("
\n"); + printf("
\n", script_name); + printf("\n"); + printf("\n", host); + printf("\n", port); + printf("\n", user_name); + printf("\n"); + printf("
Cache Host:
Cache Port:
Manager name:
Password:

\n"); + printf("\n"); + printf("
\n"); + print_trailer(); } @@ -318,15 +355,22 @@ static int parse_status_line(const char *sline, const char **statusStr) { const char *sp = strchr(sline, ' '); + if (statusStr) - *statusStr = NULL; + *statusStr = NULL; + if (strncasecmp(sline, "HTTP/", 5) || !sp) - return -1; - while (xisspace(*++sp)); + return -1; + + while (xisspace(*++sp)) + + ; if (!xisdigit(*sp)) - return -1; + return -1; + if (statusStr) - *statusStr = sp; + *statusStr = sp; + return atoi(sp); } @@ -335,12 +379,12 @@ menu_url(cachemgr_request * req, const char *action) { static char url[1024]; snprintf(url, sizeof(url), "%s?host=%s&port=%d&user_name=%s&operation=%s&auth=%s", - script_name, - req->hostname, - req->port, - safe_str(req->user_name), - action, - safe_str(req->pub_auth)); + script_name, + req->hostname, + req->port, + safe_str(req->user_name), + action, + safe_str(req->pub_auth)); return url; } @@ -354,45 +398,57 @@ munge_menu_line(const char *buf, cachemgr_request * req) char *a_url; char *buf_copy; static char html[2 * 1024]; + if (strlen(buf) < 1) - return buf; + return buf; + if (*buf != ' ') - return buf; + return buf; + buf_copy = x = xstrdup(buf); + a = xstrtok(&x, '\t'); + d = xstrtok(&x, '\t'); + p = xstrtok(&x, '\t'); + a_url = xstrdup(menu_url(req, a)); + /* no reason to give a url for a disabled action */ if (!strcmp(p, "disabled")) - snprintf(html, sizeof(html), "
  • %s (disabled).\n", d, a_url); - else - /* disable a hidden action (requires a password, but password is not in squid.conf) */ - if (!strcmp(p, "hidden")) - snprintf(html, sizeof(html), "
  • %s (hidden).\n", d, a_url); + snprintf(html, sizeof(html), "
  • %s (disabled).\n", d, a_url); else - /* disable link if authentication is required and we have no password */ - if (!strcmp(p, "protected") && !req->passwd) - snprintf(html, sizeof(html), "
  • %s (requires authentication).\n", - d, menu_url(req, "authenticate"), a_url); - else - /* highlight protected but probably available entries */ - if (!strcmp(p, "protected")) - snprintf(html, sizeof(html), "
  • %s\n", - a_url, d); + /* disable a hidden action (requires a password, but password is not in squid.conf) */ + if (!strcmp(p, "hidden")) + snprintf(html, sizeof(html), "
  • %s (hidden).\n", d, a_url); + else + /* disable link if authentication is required and we have no password */ + if (!strcmp(p, "protected") && !req->passwd) + snprintf(html, sizeof(html), "
  • %s (requires authentication).\n", + d, menu_url(req, "authenticate"), a_url); + else + /* highlight protected but probably available entries */ + if (!strcmp(p, "protected")) + snprintf(html, sizeof(html), "
  • %s\n", + a_url, d); + /* public entry or unknown type of protection */ - else - snprintf(html, sizeof(html), "
  • %s\n", a_url, d); + else + snprintf(html, sizeof(html), "
  • %s\n", a_url, d); + xfree(a_url); + xfree(buf_copy); + return html; } static const char * munge_other_line(const char *buf, cachemgr_request * req) { - static const char *ttags[] = - {"td", "th"}; + static const char *ttags[] = {"td", "th"}; + static char html[4096]; static int table_line_num = 0; static int next_is_header = 0; @@ -402,39 +458,50 @@ munge_other_line(const char *buf, cachemgr_request * req) char *x, *p; int l = 0; /* does it look like a table? */ + if (!strchr(buf, '\t') || *buf == '\t') { - /* nope, just text */ - snprintf(html, sizeof(html), "%s%s", - table_line_num ? "\n
    " : "", buf);
    -	table_line_num = 0;
    -	return html;
    +        /* nope, just text */
    +        snprintf(html, sizeof(html), "%s%s",
    +                 table_line_num ? "\n
    " : "", buf);
    +        table_line_num = 0;
    +        return html;
         }
    +
         /* start html table */
         if (!table_line_num) {
    -	l += snprintf(html + l, sizeof(html) - l, "
    \n"); - next_is_header = 0; + l += snprintf(html + l, sizeof(html) - l, "
    \n"); + next_is_header = 0; } + /* remove '\n' */ is_header = (!table_line_num || next_is_header) && !strchr(buf, ':') && !is_number(buf); + ttag = ttags[is_header]; + /* record starts */ l += snprintf(html + l, sizeof(html) - l, ""); + /* substitute '\t' */ buf_copy = x = xstrdup(buf); + if ((p = strchr(x, '\n'))) - *p = '\0'; + *p = '\0'; + while (x && strlen(x)) { - int column_span = 1; - const char *cell = xstrtok(&x, '\t'); - while (x && *x == '\t') { - column_span++; - x++; - } - l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s", - ttag, column_span, - is_header ? "center" : is_number(cell) ? "right" : "left", - cell, ttag); + int column_span = 1; + const char *cell = xstrtok(&x, '\t'); + + while (x && *x == '\t') { + column_span++; + x++; + } + + l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s", + ttag, column_span, + is_header ? "center" : is_number(cell) ? "right" : "left", + cell, ttag); } + xfree(buf_copy); /* record ends */ l += snprintf(html + l, sizeof(html) - l, "\n"); @@ -448,116 +515,155 @@ read_reply(int s, cachemgr_request * req) { char buf[4 * 1024]; #ifdef _SQUID_MSWIN_ + int reply; FILE *fp = tmpfile(); #else + FILE *fp = fdopen(s, "r"); #endif /* interpretation states */ enum { - isStatusLine, isHeaders, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError + isStatusLine, isHeaders, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError } istate = isStatusLine; int parse_menu = 0; const char *action = req->action; const char *statusStr = NULL; int status = -1; + if (0 == strlen(req->action)) - parse_menu = 1; + parse_menu = 1; else if (0 == strcasecmp(req->action, "menu")) - parse_menu = 1; + parse_menu = 1; + if (fp == NULL) { - perror("fdopen"); - return 1; + perror("fdopen"); + return 1; } + #ifdef _SQUID_MSWIN_ while ((reply=recv(s,buf,sizeof(buf),0))>0) - fwrite(buf,1,reply,fp); + fwrite(buf,1,reply,fp); + rewind(fp); + #endif + if (parse_menu) - action = "menu"; + action = "menu"; + /* read reply interpreting one line at a time depending on state */ while (istate < isEof) { - if (!fgets(buf, sizeof(buf), fp)) - istate = istate == isForward ? isForwardEof : isEof; - switch (istate) { - case isStatusLine: - /* get HTTP status */ - /* uncomment the following if you want to debug headers */ - /* fputs("\r\n\r\n", stdout); */ - status = parse_status_line(buf, &statusStr); - istate = status == 200 ? isHeaders : isForward; - /* if cache asks for authentication, we have to reset our info */ - if (status == 401 || status == 407) { - reset_auth(req); - status = 403; /* Forbiden, see comments in case isForward: */ - } - /* this is a way to pass HTTP status to the Web server */ - if (statusStr) - printf("Status: %d %s", status, statusStr); /* statusStr has '\n' */ - break; - case isHeaders: - /* forward header field */ - if (!strcmp(buf, "\r\n")) { /* end of headers */ - fputs("Content-Type: text/html\r\n", stdout); /* add our type */ - istate = isBodyStart; - } - if (strncasecmp(buf, "Content-Type:", 13)) /* filter out their type */ - fputs(buf, stdout); - break; - case isBodyStart: - printf("\n"); - printf("CacheMgr@%s: %s\n", - req->hostname, action); - printf("\n"); - printf("\n"); - if (parse_menu) { - printf("

    Cache Manager menu for %s:

    ", - menu_url(req, "authenticate"), req->hostname); - printf("
      \n"); - } else { - printf("

      %s\n


      \n", - menu_url(req, "menu"), "Cache Manager menu"); - printf("
      \n");
      -	    }
      -	    istate = isBody;
      -	    /* yes, fall through, we do not want to loose the first line */
      -	case isBody:
      -	    /* interpret [and reformat] cache response */
      -	    if (parse_menu)
      -		fputs(munge_menu_line(buf, req), stdout);
      -	    else
      -		fputs(munge_other_line(buf, req), stdout);
      -	    break;
      -	case isForward:
      -	    /* forward: no modifications allowed */
      -	    /*
      -	     * Note: we currently do not know any way to get browser.reply to
      -	     * 401 to .cgi because web server filters out all auth info. Thus we
      -	     * disable authentication headers for now.
      -	     */
      -	    if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));	/* skip */
      -	    else
      -		fputs(buf, stdout);
      -	    break;
      -	case isEof:
      -	    /* print trailers */
      -	    if (parse_menu)
      -		printf("
    \n"); - else - printf("
    \n"); - print_trailer(); - istate = isSuccess; - break; - case isForwardEof: - /* indicate that we finished processing an "error" sequence */ - istate = isError; - break; - default: - printf("%s: internal bug: invalid state reached: %d", script_name, istate); - istate = isError; - } + if (!fgets(buf, sizeof(buf), fp)) + istate = istate == isForward ? isForwardEof : isEof; + + switch (istate) { + + case isStatusLine: + /* get HTTP status */ + /* uncomment the following if you want to debug headers */ + /* fputs("\r\n\r\n", stdout); */ + status = parse_status_line(buf, &statusStr); + istate = status == 200 ? isHeaders : isForward; + /* if cache asks for authentication, we have to reset our info */ + + if (status == 401 || status == 407) { + reset_auth(req); + status = 403; /* Forbiden, see comments in case isForward: */ + } + + /* this is a way to pass HTTP status to the Web server */ + if (statusStr) + printf("Status: %d %s", status, statusStr); /* statusStr has '\n' */ + + break; + + case isHeaders: + /* forward header field */ + if (!strcmp(buf, "\r\n")) { /* end of headers */ + fputs("Content-Type: text/html\r\n", stdout); /* add our type */ + istate = isBodyStart; + } + + if (strncasecmp(buf, "Content-Type:", 13)) /* filter out their type */ + fputs(buf, stdout); + + break; + + case isBodyStart: + printf("\n"); + + printf("CacheMgr@%s: %s\n", + req->hostname, action); + + printf("\n"); + + printf("\n"); + + if (parse_menu) { + printf("

    Cache Manager menu for %s:

    ", + menu_url(req, "authenticate"), req->hostname); + printf("
      \n"); + } else { + printf("

      %s\n


      \n", + menu_url(req, "menu"), "Cache Manager menu"); + printf("
      \n");
      +            }
      +
      +            istate = isBody;
      +            /* yes, fall through, we do not want to loose the first line */
      +
      +        case isBody:
      +            /* interpret [and reformat] cache response */
      +
      +            if (parse_menu)
      +                fputs(munge_menu_line(buf, req), stdout);
      +            else
      +                fputs(munge_other_line(buf, req), stdout);
      +
      +            break;
      +
      +        case isForward:
      +            /* forward: no modifications allowed */
      +            /*
      +             * Note: we currently do not know any way to get browser.reply to
      +             * 401 to .cgi because web server filters out all auth info. Thus we
      +             * disable authentication headers for now.
      +             */
      +            if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19))
      +
      +                ;	/* skip */
      +            else
      +                fputs(buf, stdout);
      +
      +            break;
      +
      +        case isEof:
      +            /* print trailers */
      +            if (parse_menu)
      +                printf("
    \n"); + else + printf("\n"); + + print_trailer(); + + istate = isSuccess; + + break; + + case isForwardEof: + /* indicate that we finished processing an "error" sequence */ + istate = isError; + + break; + + default: + printf("%s: internal bug: invalid state reached: %d", script_name, istate); + + istate = isError; + } } + close(s); return 0; } @@ -565,69 +671,86 @@ read_reply(int s, cachemgr_request * req) static int process_request(cachemgr_request * req) { + const struct hostent *hp; + static struct sockaddr_in S; int s; int l; #ifdef _SQUID_MSWIN_ + int answer; #endif + static char buf[2 * 1024]; + if (req == NULL) { - auth_html(CACHEMGR_HOSTNAME, CACHE_HTTP_PORT, ""); - return 1; + auth_html(CACHEMGR_HOSTNAME, CACHE_HTTP_PORT, ""); + return 1; } + if (req->hostname == NULL) { - req->hostname = xstrdup(CACHEMGR_HOSTNAME); + req->hostname = xstrdup(CACHEMGR_HOSTNAME); } + if (req->port == 0) { - req->port = CACHE_HTTP_PORT; + req->port = CACHE_HTTP_PORT; } + if (req->action == NULL) { - req->action = xstrdup(""); + req->action = xstrdup(""); } + if (!strcmp(req->action, "authenticate")) { - auth_html(req->hostname, req->port, req->user_name); - return 0; + auth_html(req->hostname, req->port, req->user_name); + return 0; } + if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - snprintf(buf, 1024, "socket: %s\n", xstrerror()); - error_html(buf); - return 1; + snprintf(buf, 1024, "socket: %s\n", xstrerror()); + error_html(buf); + return 1; } + memset(&S, '\0', sizeof(struct sockaddr_in)); S.sin_family = AF_INET; + if ((hp = gethostbyname(req->hostname)) != NULL) { - assert(hp->h_length >= 0 && (size_t)hp->h_length <= sizeof(S.sin_addr.s_addr)); - xmemcpy(&S.sin_addr.s_addr, hp->h_addr, hp->h_length); + assert(hp->h_length >= 0 && (size_t)hp->h_length <= sizeof(S.sin_addr.s_addr)); + xmemcpy(&S.sin_addr.s_addr, hp->h_addr, hp->h_length); } else if (safe_inet_addr(req->hostname, &S.sin_addr)) - (void) 0; + (void) 0; else { - snprintf(buf, 1024, "Unknown host: %s\n", req->hostname); - error_html(buf); - return 1; + snprintf(buf, 1024, "Unknown host: %s\n", req->hostname); + error_html(buf); + return 1; } + S.sin_port = htons(req->port); + if (connect(s, (struct sockaddr *) &S, sizeof(struct sockaddr_in)) < 0) { - snprintf(buf, 1024, "connect: %s\n", xstrerror()); - error_html(buf); - return 1; + snprintf(buf, 1024, "connect: %s\n", xstrerror()); + error_html(buf); + return 1; } + l = snprintf(buf, sizeof(buf), - "GET cache_object://%s/%s HTTP/1.0\r\n" - "Accept: */*\r\n" - "%s" /* Authentication info or nothing */ - "\r\n", - req->hostname, - req->action, - make_auth_header(req)); + "GET cache_object://%s/%s HTTP/1.0\r\n" + "Accept: */*\r\n" + "%s" /* Authentication info or nothing */ + "\r\n", + req->hostname, + req->action, + make_auth_header(req)); write(s, buf, l); debug(1) fprintf(stderr, "wrote request: '%s'\n", buf); #ifdef _SQUID_MSWIN_ + answer=read_reply(s, req); close(s); return answer; #else + return read_reply(s, req); #endif } @@ -638,29 +761,45 @@ main(int argc, char *argv[]) char *s; cachemgr_request *req; #ifdef _SQUID_MSWIN_ + int answer; #endif + safe_inet_addr("255.255.255.255", &no_addr); now = time(NULL); #ifdef _SQUID_MSWIN_ + Win32SockInit(); + if ((s = strrchr(argv[0], '\\'))) #else + if ((s = strrchr(argv[0], '/'))) #endif - progname = xstrdup(s + 1); + + progname = xstrdup(s + 1); else - progname = xstrdup(argv[0]); + progname = xstrdup(argv[0]); + if ((s = getenv("SCRIPT_NAME")) != NULL) - script_name = xstrdup(s); + script_name = xstrdup(s); + #ifdef _SQUID_MSWIN_ + req = read_request(NULL); + answer=process_request(req); + Win32SockCleanup(); + return answer; + #else + req = read_request(); + return process_request(req); + #endif } @@ -670,17 +809,25 @@ read_post_request(void) char *s; char *buf; int len; + if ((s = getenv("REQUEST_METHOD")) == NULL) - return NULL; + return NULL; + if (0 != strcasecmp(s, "POST")) - return NULL; + return NULL; + if ((s = getenv("CONTENT_LENGTH")) == NULL) - return NULL; + return NULL; + if ((len = atoi(s)) <= 0) - return NULL; + return NULL; + buf = (char *)xmalloc(len + 1); + fread(buf, len, 1, stdin); + buf[len] = '\0'; + return buf; } @@ -688,8 +835,10 @@ static char * read_get_request(void) { char *s; + if ((s = getenv("QUERY_STRING")) == NULL) - return NULL; + return NULL; + return xstrdup(s); } @@ -699,48 +848,59 @@ read_request(char* buf) { #else static cachemgr_request * -read_request(void) -{ +read_request(void) { char *buf; #endif + cachemgr_request *req; char *s; char *t; char *q; + if ((buf = read_post_request()) != NULL) - (void) 0; + (void) 0; else if ((buf = read_get_request()) != NULL) - (void) 0; + (void) 0; else - return NULL; + return NULL; + #ifdef _SQUID_MSWIN_ + if (strlen(buf) == 0 || strlen(buf) == 4000) #else + if (strlen(buf) == 0) #endif - return NULL; + + return NULL; + req = (cachemgr_request *)xcalloc(1, sizeof(cachemgr_request)); + for (s = strtok(buf, "&"); s != NULL; s = strtok(NULL, "&")) { - t = xstrdup(s); - if ((q = strchr(t, '=')) == NULL) - continue; - *q++ = '\0'; - if (0 == strcasecmp(t, "host") && strlen(q)) - req->hostname = xstrdup(q); - else if (0 == strcasecmp(t, "port") && strlen(q)) - req->port = atoi(q); - else if (0 == strcasecmp(t, "user_name") && strlen(q)) - req->user_name = xstrdup(q); - else if (0 == strcasecmp(t, "passwd") && strlen(q)) - req->passwd = xstrdup(q); - else if (0 == strcasecmp(t, "auth") && strlen(q)) - req->pub_auth = xstrdup(q), decode_pub_auth(req); - else if (0 == strcasecmp(t, "operation")) - req->action = xstrdup(q); + t = xstrdup(s); + + if ((q = strchr(t, '=')) == NULL) + continue; + + *q++ = '\0'; + + if (0 == strcasecmp(t, "host") && strlen(q)) + req->hostname = xstrdup(q); + else if (0 == strcasecmp(t, "port") && strlen(q)) + req->port = atoi(q); + else if (0 == strcasecmp(t, "user_name") && strlen(q)) + req->user_name = xstrdup(q); + else if (0 == strcasecmp(t, "passwd") && strlen(q)) + req->passwd = xstrdup(q); + else if (0 == strcasecmp(t, "auth") && strlen(q)) + req->pub_auth = xstrdup(q), decode_pub_auth(req); + else if (0 == strcasecmp(t, "operation")) + req->action = xstrdup(q); } + make_pub_auth(req); debug(1) fprintf(stderr, "cmgr: got req: host: '%s' port: %d uname: '%s' passwd: '%s' auth: '%s' oper: '%s'\n", - safe_str(req->hostname), req->port, safe_str(req->user_name), safe_str(req->passwd), safe_str(req->pub_auth), safe_str(req->action)); + safe_str(req->hostname), req->port, safe_str(req->user_name), safe_str(req->passwd), safe_str(req->pub_auth), safe_str(req->action)); return req; } @@ -752,27 +912,30 @@ read_request(void) * Currently no powerful encryption is used. */ static void -make_pub_auth(cachemgr_request * req) -{ +make_pub_auth(cachemgr_request * req) { static char buf[1024]; safe_free(req->pub_auth); debug(3) fprintf(stderr, "cmgr: encoding for pub...\n"); + if (!req->passwd || !strlen(req->passwd)) - return; + return; + /* host | time | user | passwd */ snprintf(buf, sizeof(buf), "%s|%d|%s|%s", - req->hostname, - (int) now, - req->user_name ? req->user_name : "", - req->passwd); + req->hostname, + (int) now, + req->user_name ? req->user_name : "", + req->passwd); + debug(3) fprintf(stderr, "cmgr: pre-encoded for pub: %s\n", buf); + debug(3) fprintf(stderr, "cmgr: encoded: '%s'\n", base64_encode(buf)); + req->pub_auth = xstrdup(base64_encode(buf)); } static void -decode_pub_auth(cachemgr_request * req) -{ +decode_pub_auth(cachemgr_request * req) { char *buf; const char *host_name; const char *time_str; @@ -781,60 +944,81 @@ decode_pub_auth(cachemgr_request * req) debug(2) fprintf(stderr, "cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth)); safe_free(req->passwd); + if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname))) - return; + return; + buf = xstrdup(base64_decode(req->pub_auth)); + debug(3) fprintf(stderr, "cmgr: length ok\n"); + /* parse ( a lot of memory leaks, but that is cachemgr style :) */ if ((host_name = strtok(buf, "|")) == NULL) - return; + return; + debug(3) fprintf(stderr, "cmgr: decoded host: '%s'\n", host_name); + if ((time_str = strtok(NULL, "|")) == NULL) - return; + return; + debug(3) fprintf(stderr, "cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now); + if ((user_name = strtok(NULL, "|")) == NULL) - return; + return; + debug(3) fprintf(stderr, "cmgr: decoded uname: '%s'\n", user_name); + if ((passwd = strtok(NULL, "|")) == NULL) - return; + return; + debug(2) fprintf(stderr, "cmgr: decoded passwd: '%s'\n", passwd); + /* verify freshness and validity */ if (atoi(time_str) + passwd_ttl < now) - return; + return; + if (strcasecmp(host_name, req->hostname)) - return; + return; + debug(1) fprintf(stderr, "cmgr: verified auth. info.\n"); + /* ok, accept */ xfree(req->user_name); + req->user_name = xstrdup(user_name); + req->passwd = xstrdup(passwd); + xfree(buf); } static void -reset_auth(cachemgr_request * req) -{ +reset_auth(cachemgr_request * req) { safe_free(req->passwd); safe_free(req->pub_auth); } static const char * -make_auth_header(const cachemgr_request * req) -{ +make_auth_header(const cachemgr_request * req) { static char buf[1024]; size_t stringLength = 0; const char *str64; + if (!req->passwd) - return ""; + return ""; snprintf(buf, sizeof(buf), "%s:%s", - req->user_name ? req->user_name : "", - req->passwd); + req->user_name ? req->user_name : "", + req->passwd); str64 = base64_encode(buf); + stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64); + assert(stringLength < sizeof(buf)); + stringLength += snprintf(&buf[stringLength], sizeof(buf) - stringLength, - "Proxy-Authorization: Basic %s\r\n", str64); + "Proxy-Authorization: Basic %s\r\n", str64); + return buf; } diff --git a/src/carp.cc b/src/carp.cc index 56f3cc7c44..5927024584 100644 --- a/src/carp.cc +++ b/src/carp.cc @@ -1,6 +1,6 @@ /* - * $Id: carp.cc,v 1.22 2003/01/23 00:37:17 robertc Exp $ + * $Id: carp.cc,v 1.23 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 39 Cache Array Routing Protocol * AUTHOR: Henrik Nordstrom @@ -64,45 +64,65 @@ carpInit(void) peer **P; char *t; /* Clean up */ + for (k = 0; k < n_carp_peers; k++) { - cbdataReferenceDone(carp_peers[k]); + cbdataReferenceDone(carp_peers[k]); } + safe_free(carp_peers); n_carp_peers = 0; /* find out which peers we have */ + for (p = Config.peers; p; p = p->next) { - if (!p->options.carp) - continue; - assert(p->type == PEER_PARENT); - if (p->weight == 0) - continue; - n_carp_peers++; - W += p->weight; + if (!p->options.carp) + continue; + + assert(p->type == PEER_PARENT); + + if (p->weight == 0) + continue; + + n_carp_peers++; + + W += p->weight; } + if (n_carp_peers == 0) - return; + return; + carp_peers = (peer **)xcalloc(n_carp_peers, sizeof(*carp_peers)); + /* Build a list of the found peers and calculate hashes and load factors */ for (P = carp_peers, p = Config.peers; p; p = p->next) { - if (!p->options.carp) - continue; - if (p->weight == 0) - continue; - /* calculate this peers hash */ - p->carp.hash = 0; - for (t = p->host; *t != 0; t++) - p->carp.hash += ROTATE_LEFT(p->carp.hash, 19) + (unsigned int) *t; - p->carp.hash += p->carp.hash * 0x62531965; - p->carp.hash = ROTATE_LEFT(p->carp.hash, 21); - /* and load factor */ - p->carp.load_factor = ((double) p->weight) / (double) W; - if (floor(p->carp.load_factor * 1000.0) == 0.0) - p->carp.load_factor = 0.0; - /* add it to our list of peers */ - *P++ = cbdataReference(p); + if (!p->options.carp) + continue; + + if (p->weight == 0) + continue; + + /* calculate this peers hash */ + p->carp.hash = 0; + + for (t = p->host; *t != 0; t++) + p->carp.hash += ROTATE_LEFT(p->carp.hash, 19) + (unsigned int) *t; + + p->carp.hash += p->carp.hash * 0x62531965; + + p->carp.hash = ROTATE_LEFT(p->carp.hash, 21); + + /* and load factor */ + p->carp.load_factor = ((double) p->weight) / (double) W; + + if (floor(p->carp.load_factor * 1000.0) == 0.0) + p->carp.load_factor = 0.0; + + /* add it to our list of peers */ + *P++ = cbdataReference(p); } + /* Sort our list on weight */ qsort(carp_peers, n_carp_peers, sizeof(*carp_peers), peerSortWeight); + /* Calculate the load factor multipliers X_k * * X_1 = pow ((K*p_1), (1/K)) @@ -112,19 +132,24 @@ carpInit(void) * simplified to have X_1 part of the loop */ K = n_carp_peers; + P_last = 0.0; /* Empty P_0 */ + Xn = 1.0; /* Empty starting point of X_1 * X_2 * ... * X_{x-1} */ + X_last = 0.0; /* Empty X_0, nullifies the first pow statement */ + for (k = 1; k <= K; k++) { - double Kk1 = (double) (K - k + 1); - p = carp_peers[k - 1]; - p->carp.load_multiplier = (Kk1 * (p->carp.load_factor - P_last)) / Xn; - p->carp.load_multiplier += pow(X_last, Kk1); - p->carp.load_multiplier = pow(p->carp.load_multiplier, 1.0 / Kk1); - Xn *= p->carp.load_multiplier; - X_last = p->carp.load_multiplier; - P_last = p->carp.load_factor; + double Kk1 = (double) (K - k + 1); + p = carp_peers[k - 1]; + p->carp.load_multiplier = (Kk1 * (p->carp.load_factor - P_last)) / Xn; + p->carp.load_multiplier += pow(X_last, Kk1); + p->carp.load_multiplier = pow(p->carp.load_multiplier, 1.0 / Kk1); + Xn *= p->carp.load_multiplier; + X_last = p->carp.load_multiplier; + P_last = p->carp.load_factor; } + cachemgrRegister("carp", "CARP information", carpCachemgr, 0, 1); } @@ -142,30 +167,35 @@ carpSelectParent(request_t * request) const char *key = NULL; if (n_carp_peers == 0) - return NULL; + return NULL; key = urlCanonical(request); /* calculate hash key */ debug(39, 2) ("carpSelectParent: Calculating hash for %s\n", key); + for (c = key; *c != 0; c++) - user_hash += ROTATE_LEFT(user_hash, 19) + *c; + user_hash += ROTATE_LEFT(user_hash, 19) + *c; + /* select peer */ for (k = 0; k < n_carp_peers; k++) { - tp = carp_peers[k]; - combined_hash = (user_hash ^ tp->carp.hash); - combined_hash += combined_hash * 0x62531965; - combined_hash = ROTATE_LEFT(combined_hash, 21); - score = combined_hash * tp->carp.load_multiplier; - debug(39, 3) ("carpSelectParent: %s combined_hash %u score %.0f\n", - tp->host, combined_hash, score); - if ((score > high_score) && peerHTTPOkay(tp, request)) { - p = tp; - high_score = score; - } + tp = carp_peers[k]; + combined_hash = (user_hash ^ tp->carp.hash); + combined_hash += combined_hash * 0x62531965; + combined_hash = ROTATE_LEFT(combined_hash, 21); + score = combined_hash * tp->carp.load_multiplier; + debug(39, 3) ("carpSelectParent: %s combined_hash %u score %.0f\n", + tp->host, combined_hash, score); + + if ((score > high_score) && peerHTTPOkay(tp, request)) { + p = tp; + high_score = score; + } } + if (p) - debug(39, 2) ("carpSelectParent: selected %s\n", p->host); + debug(39, 2) ("carpSelectParent: selected %s\n", p->host); + return p; } @@ -175,19 +205,21 @@ carpCachemgr(StoreEntry * sentry) peer *p; int sumfetches = 0; storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n", - "Hostname", - "Hash", - "Multiplier", - "Factor", - "Actual"); + "Hostname", + "Hash", + "Multiplier", + "Factor", + "Actual"); + for (p = Config.peers; p; p = p->next) - sumfetches += p->stats.fetches; + sumfetches += p->stats.fetches; + for (p = Config.peers; p; p = p->next) { - storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n", - p->host, p->carp.hash, - p->carp.load_multiplier, - p->carp.load_factor, - sumfetches ? (double) p->stats.fetches / sumfetches : -1.0); + storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n", + p->host, p->carp.hash, + p->carp.load_multiplier, + p->carp.load_factor, + sumfetches ? (double) p->stats.fetches / sumfetches : -1.0); } } diff --git a/src/cbdata.cc b/src/cbdata.cc index 2fb04df7f6..4a3677ccae 100644 --- a/src/cbdata.cc +++ b/src/cbdata.cc @@ -1,6 +1,6 @@ /* - * $Id: cbdata.cc,v 1.53 2003/02/12 06:11:00 robertc Exp $ + * $Id: cbdata.cc,v 1.54 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 45 Callback Data Registry * ORIGINAL AUTHOR: Duane Wessels @@ -58,52 +58,68 @@ dlink_list cbdataEntries; #endif #if CBDATA_DEBUG -class CBDataCall { + +class CBDataCall +{ + public: CBDataCall (char const *callLabel, char const *aFile, int aLine) : label(callLabel), file(aFile), line(aLine){} + char const *label; char const *file; int line; }; + #endif -typedef struct _cbdata { +typedef struct _cbdata +{ #if CBDATA_DEBUG void dump(StoreEntry *)const; #endif + void deleteSelf(); int valid; int locks; int type; #if CBDATA_DEBUG + void addHistory(char const *label, char const *file, int line) const - { - if (calls->count > 100) - return; + { + if (calls->count > 100) + return; + stackPush (calls, new CBDataCall(label, file, line)); - } + } + dlink_node link; const char *file; int line; Stack *calls; #endif + long y; /* cookie used while debugging */ union { - void *pointer; - double double_float; - int integer; + void *pointer; + double double_float; + int integer; } data; -} cbdata; +} + +cbdata; static OBJH cbdataDump; #ifdef CBDATA_DEBUG static OBJH cbdataDumpHistory; #endif -struct CBDataIndex { +struct CBDataIndex +{ MemPool *pool; FREE *free_func; -} *cbdata_index = NULL; +} + +*cbdata_index = NULL; int cbdata_types = 0; #define OFFSET_OF(type, member) ((int)(char *)&((type *)0L)->member) @@ -115,13 +131,19 @@ _cbdata::deleteSelf() { #if CBDATA_DEBUG CBDataCall *aCall; + while ((aCall = (CBDataCall *)stackPop(calls))) - delete aCall; + delete aCall; + stackDestroy(calls); + #endif + FREE *free_func = cbdata_index[type].free_func; + if (free_func) - free_func(&data); + free_func(&data); + memPoolFree(cbdata_index[type].pool, this); } @@ -129,18 +151,25 @@ static void cbdataInternalInitType(cbdata_type type, const char *name, int size, FREE * free_func) { char *label; + if (type >= cbdata_types) { - cbdata_index = (CBDataIndex *)xrealloc(cbdata_index, (type + 1) * sizeof(*cbdata_index)); - memset(&cbdata_index[cbdata_types], 0, - (type + 1 - cbdata_types) * sizeof(*cbdata_index)); - cbdata_types = type + 1; + cbdata_index = (CBDataIndex *)xrealloc(cbdata_index, (type + 1) * sizeof(*cbdata_index)); + memset(&cbdata_index[cbdata_types], 0, + (type + 1 - cbdata_types) * sizeof(*cbdata_index)); + cbdata_types = type + 1; } + if (cbdata_index[type].pool) - return; + return; + label = (char *)xmalloc(strlen(name) + 20); + snprintf(label, strlen(name) + 20, "cbdata %s (%d)", name, (int) type); + assert(OFFSET_OF(cbdata, data) == (sizeof(cbdata) - sizeof(((cbdata *) NULL)->data))); + cbdata_index[type].pool = memPoolCreate(label, size + OFFSET_OF(cbdata, data)); + cbdata_index[type].free_func = free_func; } @@ -148,9 +177,12 @@ cbdata_type cbdataInternalAddType(cbdata_type type, const char *name, int size, FREE * free_func) { if (type) - return type; + return type; + type = (cbdata_type)cbdata_types; + cbdataInternalInitType(type, name, size, free_func); + return type; } @@ -159,12 +191,13 @@ cbdataInit(void) { debug(45, 3) ("cbdataInit\n"); cachemgrRegister("cbdata", - "Callback Data Registry Contents", - cbdataDump, 0, 1); + "Callback Data Registry Contents", + cbdataDump, 0, 1); #if CBDATA_DEBUG - cachemgrRegister("cbdatahistory", - "Detailed call history for all current cbdata contents", - cbdataDumpHistory, 0, 1); + + cachemgrRegister("cbdatahistory", + "Detailed call history for all current cbdata contents", + cbdataDumpHistory, 0, 1); #endif #define CREATE_CBDATA(type) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), NULL) #define CREATE_CBDATA_FREE(type, free_func) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), free_func) @@ -202,6 +235,7 @@ cbdataInternalAlloc(cbdata_type type) p->y = (long) p ^ CBDATA_COOKIE; cbdataCount++; #if CBDATA_DEBUG + p->file = file; p->line = line; p->calls = stackCreate(); @@ -209,6 +243,7 @@ cbdataInternalAlloc(cbdata_type type) dlinkAdd(p, &p->link, &cbdataEntries); debug(45, 3) ("cbdataAlloc: %p %s:%d\n", &p->data, file, line); #endif + return (void *) &p->data; } @@ -222,25 +257,33 @@ cbdataInternalFree(void *p) cbdata *c; c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); #if CBDATA_DEBUG + debug(45, 3) ("cbdataFree: %p %s:%d\n", p, file, line); #else + debug(45, 3) ("cbdataFree: %p\n", p); #endif + CBDATA_CHECK(c); c->valid = 0; #if CBDATA_DEBUG + c->addHistory("Free", file, line); #endif + if (c->locks) { - debug(45, 3) ("cbdataFree: %p has %d locks, not freeing\n", - p, c->locks); - return NULL; + debug(45, 3) ("cbdataFree: %p has %d locks, not freeing\n", + p, c->locks); + return NULL; } + cbdataCount--; debug(45, 3) ("cbdataFree: Freeing %p\n", p); #if CBDATA_DEBUG + dlinkDelete(&c->link, &cbdataEntries); #endif + c->deleteSelf(); return NULL; } @@ -253,17 +296,28 @@ cbdataInternalLock(const void *p) #endif { cbdata *c; + if (p == NULL) - return; + return; + c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); + #if CBDATA_DEBUG + debug(45, 3) ("cbdataLock: %p=%d %s:%d\n", p, c ? c->locks + 1 : -1, file, line); + c->addHistory("Reference", file, line); + #else + debug(45, 3) ("cbdataLock: %p=%d\n", p, c ? c->locks + 1 : -1); + #endif + CBDATA_CHECK(c); + assert(c->locks < 65535); + c->locks++; } @@ -275,26 +329,45 @@ cbdataInternalUnlock(const void *p) #endif { cbdata *c; + if (p == NULL) - return; + return; + c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); + #if CBDATA_DEBUG + debug(45, 3) ("cbdataUnlock: %p=%d %s:%d\n", p, c ? c->locks - 1 : -1, file, line); + c->addHistory("Dereference", file, line); + #else + debug(45, 3) ("cbdataUnlock: %p=%d\n", p, c ? c->locks - 1 : -1); + #endif + CBDATA_CHECK(c); + assert(c != NULL); + assert(c->locks > 0); + c->locks--; + if (c->valid || c->locks) - return; + return; + cbdataCount--; + debug(45, 3) ("cbdataUnlock: Freeing %p\n", p); + #if CBDATA_DEBUG + dlinkDelete(&c->link, &cbdataEntries); + #endif + c->deleteSelf(); } @@ -302,12 +375,18 @@ int cbdataReferenceValid(const void *p) { cbdata *c; + if (p == NULL) - return 1; /* A NULL pointer cannot become invalid */ + return 1; /* A NULL pointer cannot become invalid */ + debug(45, 3) ("cbdataReferenceValid: %p\n", p); + c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); + CBDATA_CHECK(c); + assert(c->locks > 0); + return c->valid; } @@ -322,16 +401,19 @@ cbdataInternalReferenceDoneValid(void **pp, void **tp) int valid = cbdataReferenceValid(p); *pp = NULL; #if CBDATA_DEBUG + cbdataInternalUnlockDbg(p, file, line); #else + cbdataInternalUnlock(p); #endif + if (valid) { - *tp = p; - return 1; + *tp = p; + return 1; } else { - *tp = NULL; - return 0; + *tp = NULL; + return 0; } } @@ -340,17 +422,21 @@ void _cbdata::dump(StoreEntry *sentry) const { storeAppendPrintf(sentry, "%c%p\t%d\t%d\t%20s:%-5d\n", valid ? ' ' : - '!', &data, type, locks, file, line); + '!', &data, type, locks, file, line); } struct CBDataDumper : public unary_function<_cbdata, void> { CBDataDumper(StoreEntry *anEntry):where(anEntry){} - void operator()(_cbdata const &x) { - x.dump(where); + + void operator()(_cbdata const &x) + { + x.dump(where); } + StoreEntry *where; }; + #endif static void @@ -358,21 +444,27 @@ cbdataDump(StoreEntry * sentry) { storeAppendPrintf(sentry, "%d cbdata entries\n", cbdataCount); #if CBDATA_DEBUG + storeAppendPrintf(sentry, "Pointer\tType\tLocks\tAllocated by\n"); CBDataDumper dumper(sentry); for_each (cbdataEntries, dumper); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "types\tsize\tallocated\ttotal\n"); + for (int i = 1; i < cbdata_types; i++) { - MemPool *pool = cbdata_index[i].pool; - if (pool) { - int obj_size = pool->obj_size - OFFSET_OF(cbdata, data); - storeAppendPrintf(sentry, "%s\t%d\t%d\t%d\n", pool->label + 7, obj_size, pool->meter.inuse.level, obj_size * pool->meter.inuse.level); - } + MemPool *pool = cbdata_index[i].pool; + + if (pool) { + int obj_size = pool->obj_size - OFFSET_OF(cbdata, data); + storeAppendPrintf(sentry, "%s\t%d\t%d\t%d\n", pool->label + 7, obj_size, pool->meter.inuse.level, obj_size * pool->meter.inuse.level); + } } + #else storeAppendPrintf(sentry, "detailed allocation information only available when compiled with CBDATA_DEBUG\n"); + #endif + storeAppendPrintf(sentry, "\nsee also \"Memory utilization\" for detailed per type statistics\n"); } @@ -382,29 +474,36 @@ template T& for_each(Stack const &collection, T& visitor) { for (size_t index = 0; index < collection.count; ++index) - visitor(*(typename T::argument_type const *)collection.items[index]); + visitor(*(typename T::argument_type const *)collection.items[index]); + return visitor; }; struct CBDataCallDumper : public unary_function { CBDataCallDumper (StoreEntry *anEntry):where(anEntry){} - void operator()(CBDataCall const &x) { - storeAppendPrintf(where, "%s\t%s\t%d\n", x.label, x.file, x.line); + + void operator()(CBDataCall const &x) + { + storeAppendPrintf(where, "%s\t%s\t%d\n", x.label, x.file, x.line); } + StoreEntry *where; }; struct CBDataHistoryDumper : public CBDataDumper { CBDataHistoryDumper(StoreEntry *anEntry):CBDataDumper(anEntry),where(anEntry), callDumper(anEntry){} - void operator()(_cbdata const &x) { - CBDataDumper::operator()(x); - storeAppendPrintf(where, "\n"); - storeAppendPrintf(where, "Action\tFile\tLine\n"); - for_each (*x.calls,callDumper); - storeAppendPrintf(where, "\n"); + + void operator()(_cbdata const &x) + { + CBDataDumper::operator()(x); + storeAppendPrintf(where, "\n"); + storeAppendPrintf(where, "Action\tFile\tLine\n"); + for_each (*x.calls,callDumper); + storeAppendPrintf(where, "\n"); } + StoreEntry *where; CBDataCallDumper callDumper; }; @@ -417,4 +516,5 @@ cbdataDumpHistory(StoreEntry *sentry) CBDataHistoryDumper dumper(sentry); for_each (cbdataEntries, dumper); } + #endif diff --git a/src/cf_gen.cc b/src/cf_gen.cc index c0919c80d9..592d5c4364 100644 --- a/src/cf_gen.cc +++ b/src/cf_gen.cc @@ -1,6 +1,6 @@ /* - * $Id: cf_gen.cc,v 1.49 2003/01/23 00:37:17 robertc Exp $ + * $Id: cf_gen.cc,v 1.50 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: none Generate squid.conf.default and cf_parser.h * AUTHOR: Max Okumoto @@ -87,17 +87,26 @@ enum State { sEXIT }; -typedef struct Line { +typedef struct Line +{ char *data; + struct Line *next; -} Line; +} + +Line; + +typedef struct EntryAlias +{ -typedef struct EntryAlias { struct EntryAlias *next; char *name; -} EntryAlias; +} + +EntryAlias; -typedef struct Entry { +typedef struct Entry +{ char *name; EntryAlias *alias; char *type; @@ -109,8 +118,11 @@ typedef struct Entry { Line *doc; Line *nocomment; int array_flag; + struct Entry *next; -} Entry; +} + +Entry; static const char WS[] = " \t"; @@ -127,8 +139,10 @@ static void lineAdd(Line ** L, const char *str) { while (*L) - L = &(*L)->next; + L = &(*L)->next; + *L = (Line *)xcalloc(1, sizeof(Line)); + (*L)->data = xstrdup(str); } @@ -146,8 +160,10 @@ main(int argc, char *argv[]) int rc = 0; char *ptr = NULL; #ifdef _SQUID_OS2_ + const char *rmode = "rt"; #else + const char *rmode = "r"; #endif @@ -156,182 +172,221 @@ main(int argc, char *argv[]) *-------------------------------------------------------------------*/ /* Open input file */ + if ((fp = fopen(input_filename, rmode)) == NULL) { - perror(input_filename); - exit(1); + perror(input_filename); + exit(1); } + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) setmode(fileno(fp), O_TEXT); + #endif + state = sSTART; + while (feof(fp) == 0 && state != sEXIT) { - char buff[MAX_LINE]; - char *t; - if (NULL == fgets(buff, MAX_LINE, fp)) - break; - linenum++; - if ((t = strchr(buff, '\n'))) - *t = '\0'; - switch (state) { - case sSTART: - if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { - /* ignore empty and comment lines */ - (void) 0; - } else if (!strncmp(buff, "NAME:", 5)) { - char *name, *aliasname; - if ((name = strtok(buff + 5, WS)) == NULL) { - printf("Error in input file\n"); - exit(1); - } - curr = (Entry *)calloc(1, sizeof(Entry)); - curr->name = xstrdup(name); - while ((aliasname = strtok(NULL, WS)) != NULL) { - EntryAlias *alias = (EntryAlias *)calloc(1, sizeof(EntryAlias)); - alias->next = curr->alias; - alias->name = xstrdup(aliasname); - curr->alias = alias; - } - state = s1; - } else if (!strcmp(buff, "EOF")) { - state = sEXIT; - } else if (!strcmp(buff, "COMMENT_START")) { - curr = (Entry *)calloc(1, sizeof(Entry)); - curr->name = xstrdup("comment"); - curr->loc = xstrdup("none"); - state = sDOC; - } else { - printf("Error on line %d\n", linenum); - printf("--> %s\n", buff); - exit(1); - } - break; - - case s1: - if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { - /* ignore empty and comment lines */ - (void) 0; - } else if (!strncmp(buff, "COMMENT:", 8)) { - ptr = buff + 8; - while (xisspace(*ptr)) - ptr++; - curr->comment = xstrdup(ptr); - } else if (!strncmp(buff, "DEFAULT:", 8)) { - ptr = buff + 8; - while (xisspace(*ptr)) - ptr++; - curr->default_value = xstrdup(ptr); - } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { - ptr = buff + 16; - while (xisspace(*ptr)) - ptr++; - lineAdd(&curr->default_if_none, ptr); - } else if (!strncmp(buff, "LOC:", 4)) { - if ((ptr = strtok(buff + 4, WS)) == NULL) { - printf("Error on line %d\n", linenum); - exit(1); - } - curr->loc = xstrdup(ptr); - } else if (!strncmp(buff, "TYPE:", 5)) { - if ((ptr = strtok(buff + 5, WS)) == NULL) { - printf("Error on line %d\n", linenum); - exit(1); - } - /* hack to support arrays, rather than pointers */ - if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) { - curr->array_flag = 1; - *(ptr + strlen(ptr) - 2) = '\0'; - } - curr->type = xstrdup(ptr); - } else if (!strncmp(buff, "IFDEF:", 6)) { - if ((ptr = strtok(buff + 6, WS)) == NULL) { - printf("Error on line %d\n", linenum); - exit(1); - } - curr->ifdef = xstrdup(ptr); - } else if (!strcmp(buff, "DOC_START")) { - state = sDOC; - } else if (!strcmp(buff, "DOC_NONE")) { - /* add to list of entries */ - curr->next = entries; - entries = curr; - state = sSTART; - } else { - printf("Error on line %d\n", linenum); - exit(1); - } - break; - - case sDOC: - if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) { - Line *head = NULL; - Line *line = curr->doc; - /* reverse order of doc lines */ - while (line != NULL) { - Line *tmp; - tmp = line->next; - line->next = head; - head = line; - line = tmp; - } - curr->doc = head; - /* add to list of entries */ - curr->next = entries; - entries = curr; - state = sSTART; - } else if (!strcmp(buff, "NOCOMMENT_START")) { - state = sNOCOMMENT; - } else { - Line *line = (Line *)calloc(1, sizeof(Line)); - line->data = xstrdup(buff); - line->next = curr->doc; - curr->doc = line; - } - break; - - case sNOCOMMENT: - if (!strcmp(buff, "NOCOMMENT_END")) { - Line *head = NULL; - Line *line = curr->nocomment; - /* reverse order of lines */ - while (line != NULL) { - Line *tmp; - tmp = line->next; - line->next = head; - head = line; - line = tmp; - } - curr->nocomment = head; - state = sDOC; - } else { - Line *line = (Line *)calloc(1, sizeof(Line)); - line->data = xstrdup(buff); - line->next = curr->nocomment; - curr->nocomment = line; - } - break; - - case sEXIT: - assert(0); /* should never get here */ - break; - } + char buff[MAX_LINE]; + char *t; + + if (NULL == fgets(buff, MAX_LINE, fp)) + break; + + linenum++; + + if ((t = strchr(buff, '\n'))) + *t = '\0'; + + switch (state) { + + case sSTART: + + if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { + /* ignore empty and comment lines */ + (void) 0; + } else if (!strncmp(buff, "NAME:", 5)) { + char *name, *aliasname; + + if ((name = strtok(buff + 5, WS)) == NULL) { + printf("Error in input file\n"); + exit(1); + } + + curr = (Entry *)calloc(1, sizeof(Entry)); + curr->name = xstrdup(name); + + while ((aliasname = strtok(NULL, WS)) != NULL) { + EntryAlias *alias = (EntryAlias *)calloc(1, sizeof(EntryAlias)); + alias->next = curr->alias; + alias->name = xstrdup(aliasname); + curr->alias = alias; + } + + state = s1; + } else if (!strcmp(buff, "EOF")) { + state = sEXIT; + } else if (!strcmp(buff, "COMMENT_START")) { + curr = (Entry *)calloc(1, sizeof(Entry)); + curr->name = xstrdup("comment"); + curr->loc = xstrdup("none"); + state = sDOC; + } else { + printf("Error on line %d\n", linenum); + printf("--> %s\n", buff); + exit(1); + } + + break; + + case s1: + + if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { + /* ignore empty and comment lines */ + (void) 0; + } else if (!strncmp(buff, "COMMENT:", 8)) { + ptr = buff + 8; + + while (xisspace(*ptr)) + ptr++; + + curr->comment = xstrdup(ptr); + } else if (!strncmp(buff, "DEFAULT:", 8)) { + ptr = buff + 8; + + while (xisspace(*ptr)) + ptr++; + + curr->default_value = xstrdup(ptr); + } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { + ptr = buff + 16; + + while (xisspace(*ptr)) + ptr++; + + lineAdd(&curr->default_if_none, ptr); + } else if (!strncmp(buff, "LOC:", 4)) { + if ((ptr = strtok(buff + 4, WS)) == NULL) { + printf("Error on line %d\n", linenum); + exit(1); + } + + curr->loc = xstrdup(ptr); + } else if (!strncmp(buff, "TYPE:", 5)) { + if ((ptr = strtok(buff + 5, WS)) == NULL) { + printf("Error on line %d\n", linenum); + exit(1); + } + + /* hack to support arrays, rather than pointers */ + if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) { + curr->array_flag = 1; + *(ptr + strlen(ptr) - 2) = '\0'; + } + + curr->type = xstrdup(ptr); + } else if (!strncmp(buff, "IFDEF:", 6)) { + if ((ptr = strtok(buff + 6, WS)) == NULL) { + printf("Error on line %d\n", linenum); + exit(1); + } + + curr->ifdef = xstrdup(ptr); + } else if (!strcmp(buff, "DOC_START")) { + state = sDOC; + } else if (!strcmp(buff, "DOC_NONE")) { + /* add to list of entries */ + curr->next = entries; + entries = curr; + state = sSTART; + } else { + printf("Error on line %d\n", linenum); + exit(1); + } + + break; + + case sDOC: + + if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) { + Line *head = NULL; + Line *line = curr->doc; + /* reverse order of doc lines */ + + while (line != NULL) { + Line *tmp; + tmp = line->next; + line->next = head; + head = line; + line = tmp; + } + + curr->doc = head; + /* add to list of entries */ + curr->next = entries; + entries = curr; + state = sSTART; + } else if (!strcmp(buff, "NOCOMMENT_START")) { + state = sNOCOMMENT; + } else { + Line *line = (Line *)calloc(1, sizeof(Line)); + line->data = xstrdup(buff); + line->next = curr->doc; + curr->doc = line; + } + + break; + + case sNOCOMMENT: + + if (!strcmp(buff, "NOCOMMENT_END")) { + Line *head = NULL; + Line *line = curr->nocomment; + /* reverse order of lines */ + + while (line != NULL) { + Line *tmp; + tmp = line->next; + line->next = head; + head = line; + line = tmp; + } + + curr->nocomment = head; + state = sDOC; + } else { + Line *line = (Line *)calloc(1, sizeof(Line)); + line->data = xstrdup(buff); + line->next = curr->nocomment; + curr->nocomment = line; + } + + break; + + case sEXIT: + assert(0); /* should never get here */ + break; + } } + if (state != sEXIT) { - printf("Error unexpected EOF\n"); - exit(1); + printf("Error unexpected EOF\n"); + exit(1); } else { - /* reverse order of entries */ - Entry *head = NULL; - - while (entries != NULL) { - Entry *tmp; - - tmp = entries->next; - entries->next = head; - head = entries; - entries = tmp; - } - entries = head; + /* reverse order of entries */ + Entry *head = NULL; + + while (entries != NULL) { + Entry *tmp; + + tmp = entries->next; + entries->next = head; + head = entries; + entries = tmp; + } + + entries = head; } + fclose(fp); /*-------------------------------------------------------------------* @@ -343,39 +398,53 @@ main(int argc, char *argv[]) *-------------------------------------------------------------------*/ /* Open output x.c file */ + if ((fp = fopen(output_filename, "w")) == NULL) { - perror(output_filename); - exit(1); + perror(output_filename); + exit(1); } + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) setmode(fileno(fp), O_TEXT); + #endif + fprintf(fp, - "/*\n" - " * Generated automatically from %s by %s\n" - " *\n" - " * Abstract: This file contains routines used to configure the\n" - " * variables in the squid server.\n" - " */\n" - "\n", - input_filename, argv[0] - ); + "/*\n" + " * Generated automatically from %s by %s\n" + " *\n" + " * Abstract: This file contains routines used to configure the\n" + " * variables in the squid server.\n" + " */\n" + "\n", + input_filename, argv[0] + ); + rc = gen_default(entries, fp); + gen_default_if_none(entries, fp); + gen_parse(entries, fp); + gen_dump(entries, fp); + gen_free(entries, fp); + fclose(fp); /* Open output x.conf file */ if ((fp = fopen(conf_filename, "w")) == NULL) { - perror(conf_filename); - exit(1); + perror(conf_filename); + exit(1); } + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) setmode(fileno(fp), O_TEXT); + #endif + gen_conf(entries, fp); + fclose(fp); return (rc); @@ -387,52 +456,60 @@ gen_default(Entry * head, FILE * fp) Entry *entry; int rc = 0; fprintf(fp, - "static void\n" - "default_line(const char *s)\n" - "{\n" - "\tLOCAL_ARRAY(char, tmp_line, BUFSIZ);\n" - "\txstrncpy(tmp_line, s, BUFSIZ);\n" - "\txstrncpy(config_input_line, s, BUFSIZ);\n" - "\tconfig_lineno++;\n" - "\tparse_line(tmp_line);\n" - "}\n" - ); + "static void\n" + "default_line(const char *s)\n" + "{\n" + "\tLOCAL_ARRAY(char, tmp_line, BUFSIZ);\n" + "\txstrncpy(tmp_line, s, BUFSIZ);\n" + "\txstrncpy(config_input_line, s, BUFSIZ);\n" + "\tconfig_lineno++;\n" + "\tparse_line(tmp_line);\n" + "}\n" + ); fprintf(fp, - "static void\n" - "default_all(void)\n" - "{\n" - "\tcfg_filename = \"Default Configuration\";\n" - "\tconfig_lineno = 0;\n" - ); + "static void\n" + "default_all(void)\n" + "{\n" + "\tcfg_filename = \"Default Configuration\";\n" + "\tconfig_lineno = 0;\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->name); - assert(entry != entry->next); - - if (!strcmp(entry->name, "comment")) - continue; - if (entry->loc == NULL) { - fprintf(stderr, "NO LOCATION FOR %s\n", entry->name); - rc |= 1; - continue; - } - if (entry->default_value == NULL) { - fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name); - rc |= 1; - continue; - } - assert(entry->default_value); - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - if (strcmp(entry->default_value, "none") == 0) { - fprintf(fp, "\t/* No default for %s */\n", entry->name); - } else { - fprintf(fp, "\tdefault_line(\"%s %s\");\n", - entry->name, - entry->default_value); - } - if (entry->ifdef) - fprintf(fp, "#endif\n"); + assert(entry->name); + assert(entry != entry->next); + + if (!strcmp(entry->name, "comment")) + continue; + + if (entry->loc == NULL) { + fprintf(stderr, "NO LOCATION FOR %s\n", entry->name); + rc |= 1; + continue; + } + + if (entry->default_value == NULL) { + fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name); + rc |= 1; + continue; + } + + assert(entry->default_value); + + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + + if (strcmp(entry->default_value, "none") == 0) { + fprintf(fp, "\t/* No default for %s */\n", entry->name); + } else { + fprintf(fp, "\tdefault_line(\"%s %s\");\n", + entry->name, + entry->default_value); + } + + if (entry->ifdef) + fprintf(fp, "#endif\n"); } + fprintf(fp, "\tcfg_filename = NULL;\n"); fprintf(fp, "}\n\n"); return rc; @@ -444,99 +521,117 @@ gen_default_if_none(Entry * head, FILE * fp) Entry *entry; Line *line; fprintf(fp, - "static void\n" - "defaults_if_none(void)\n" - "{\n" - ); + "static void\n" + "defaults_if_none(void)\n" + "{\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->name); - assert(entry->loc); - if (entry->default_if_none == NULL) - continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - if (entry->default_if_none) { - fprintf(fp, - "\tif (check_null_%s(%s)) {\n", - entry->type, - entry->loc); - for (line = entry->default_if_none; line; line = line->next) - fprintf(fp, - "\t\tdefault_line(\"%s %s\");\n", - entry->name, - line->data); - fprintf(fp, "\t}\n"); - } - if (entry->ifdef) - fprintf(fp, "#endif\n"); + assert(entry->name); + assert(entry->loc); + + if (entry->default_if_none == NULL) + continue; + + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + + if (entry->default_if_none) { + fprintf(fp, + "\tif (check_null_%s(%s)) {\n", + entry->type, + entry->loc); + + for (line = entry->default_if_none; line; line = line->next) + fprintf(fp, + "\t\tdefault_line(\"%s %s\");\n", + entry->name, + line->data); + + fprintf(fp, "\t}\n"); + } + + if (entry->ifdef) + fprintf(fp, "#endif\n"); } + fprintf(fp, "}\n\n"); } void gen_parse_alias(char *name, EntryAlias *alias, Entry *entry, FILE *fp) { - fprintf(fp, "\tif (!strcmp(token, \"%s\")) {\n", name); - if (strcmp(entry->loc, "none") == 0) { - fprintf(fp, - "\t\tparse_%s();\n", - entry->type - ); - } else { - fprintf(fp, - "\t\tparse_%s(&%s%s);\n", - entry->type, entry->loc, - entry->array_flag ? "[0]" : "" - ); - } - fprintf(fp,"\t\treturn 1;\n"); - fprintf(fp,"\t};\n"); + fprintf(fp, "\tif (!strcmp(token, \"%s\")) {\n", name); + + if (strcmp(entry->loc, "none") == 0) { + fprintf(fp, + "\t\tparse_%s();\n", + entry->type + ); + } else { + fprintf(fp, + "\t\tparse_%s(&%s%s);\n", + entry->type, entry->loc, + entry->array_flag ? "[0]" : "" + ); + } + + fprintf(fp,"\t\treturn 1;\n"); + fprintf(fp,"\t};\n"); } void gen_parse_entry(Entry *entry, FILE *fp) { - if (strcmp(entry->name, "comment") == 0) - return; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - char *name = entry->name; - EntryAlias *alias = entry->alias; - assert (entry->loc); - bool more; - do { - gen_parse_alias (name, alias,entry, fp); - more = false; - if (alias) { - name = alias->name; - alias = alias->next; - more = true; - } - } while (more); - if (entry->ifdef) - fprintf(fp, "#endif\n"); + if (strcmp(entry->name, "comment") == 0) + return; + + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + + char *name = entry->name; + + EntryAlias *alias = entry->alias; + + assert (entry->loc); + + bool more; + + do { + gen_parse_alias (name, alias,entry, fp); + more = false; + + if (alias) { + name = alias->name; + alias = alias->next; + more = true; + } + } while (more); + + if (entry->ifdef) + fprintf(fp, "#endif\n"); } static void gen_parse(Entry * head, FILE * fp) { fprintf(fp, - "static int\n" - "parse_line(char *buff)\n" - "{\n" - "\tchar\t*token;\n" - "\tdebug(0,10)(\"parse_line: %%s\\n\", buff);\n" - "\tif ((token = strtok(buff, w_space)) == NULL) \n" - "\t\treturn 1;\t/* ignore empty lines */\n" - ); + "static int\n" + "parse_line(char *buff)\n" + "{\n" + "\tchar\t*token;\n" + "\tdebug(0,10)(\"parse_line: %%s\\n\", buff);\n" + "\tif ((token = strtok(buff, w_space)) == NULL) \n" + "\t\treturn 1;\t/* ignore empty lines */\n" + ); for (Entry *entry = head; entry != NULL; entry = entry->next) - gen_parse_entry (entry, fp); + gen_parse_entry (entry, fp); fprintf(fp, - "\treturn 0; /* failure */\n" - "}\n\n" - ); + "\treturn 0; /* failure */\n" + "}\n\n" + ); } static void @@ -544,25 +639,32 @@ gen_dump(Entry * head, FILE * fp) { Entry *entry; fprintf(fp, - "static void\n" - "dump_config(StoreEntry *entry)\n" - "{\n" - ); + "static void\n" + "dump_config(StoreEntry *entry)\n" + "{\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->loc); - if (strcmp(entry->loc, "none") == 0) - continue; - if (strcmp(entry->name, "comment") == 0) - continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n", - entry->type, - entry->name, - entry->loc); - if (entry->ifdef) - fprintf(fp, "#endif\n"); + assert(entry->loc); + + if (strcmp(entry->loc, "none") == 0) + continue; + + if (strcmp(entry->name, "comment") == 0) + continue; + + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + + fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n", + entry->type, + entry->name, + entry->loc); + + if (entry->ifdef) + fprintf(fp, "#endif\n"); } + fprintf(fp, "}\n\n"); } @@ -571,24 +673,31 @@ gen_free(Entry * head, FILE * fp) { Entry *entry; fprintf(fp, - "static void\n" - "free_all(void)\n" - "{\n" - ); + "static void\n" + "free_all(void)\n" + "{\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->loc); - if (strcmp(entry->loc, "none") == 0) - continue; - if (strcmp(entry->name, "comment") == 0) - continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - fprintf(fp, "\tfree_%s(&%s%s);\n", - entry->type, entry->loc, - entry->array_flag ? "[0]" : ""); - if (entry->ifdef) - fprintf(fp, "#endif\n"); + assert(entry->loc); + + if (strcmp(entry->loc, "none") == 0) + continue; + + if (strcmp(entry->name, "comment") == 0) + continue; + + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + + fprintf(fp, "\tfree_%s(&%s%s);\n", + entry->type, entry->loc, + entry->array_flag ? "[0]" : ""); + + if (entry->ifdef) + fprintf(fp, "#endif\n"); } + fprintf(fp, "}\n\n"); } @@ -596,11 +705,14 @@ static int defined(char *name) { int i = 0; + if (!name) - return 1; + return 1; + for (i = 0; strcmp(defines[i].name, name) != 0; i++) { - assert(defines[i].name); + assert(defines[i].name); } + return defines[i].defined; } @@ -609,9 +721,11 @@ available_if(char *name) { int i = 0; assert(name); + for (i = 0; strcmp(defines[i].name, name) != 0; i++) { - assert(defines[i].name); + assert(defines[i].name); } + return defines[i].enable; } @@ -623,58 +737,73 @@ gen_conf(Entry * head, FILE * fp) Line *def = NULL; for (entry = head; entry != NULL; entry = entry->next) { - Line *line; - int blank = 1; - - if (!strcmp(entry->name, "comment")) - (void) 0; - else - fprintf(fp, "# TAG: %s", entry->name); - if (entry->comment) - fprintf(fp, "\t%s", entry->comment); - fprintf(fp, "\n"); - if (!defined(entry->ifdef)) { - fprintf(fp, "# Note: This option is only available if Squid is rebuilt with the\n"); - fprintf(fp, "# %s option\n#\n", available_if(entry->ifdef)); - } - for (line = entry->doc; line != NULL; line = line->next) { - fprintf(fp, "#%s\n", line->data); - } - if (entry->default_value && strcmp(entry->default_value, "none") != 0) { - sprintf(buf, "%s %s", entry->name, entry->default_value); - lineAdd(&def, buf); - } - if (entry->default_if_none) { - for (line = entry->default_if_none; line; line = line->next) { - sprintf(buf, "%s %s", entry->name, line->data); - lineAdd(&def, buf); - } - } - if (entry->nocomment) - blank = 0; - if (!def && entry->doc && !entry->nocomment && - strcmp(entry->name, "comment") != 0) - lineAdd(&def, "none"); - if (def && (entry->doc || entry->nocomment)) { - if (blank) - fprintf(fp, "#\n"); - fprintf(fp, "#Default:\n"); - while (def != NULL) { - line = def; - def = line->next; - fprintf(fp, "# %s\n", line->data); - xfree(line->data); - xfree(line); - } - blank = 1; - } - if (entry->nocomment && blank) - fprintf(fp, "#\n"); - for (line = entry->nocomment; line != NULL; line = line->next) { - fprintf(fp, "%s\n", line->data); - } - if (entry->doc != NULL) { - fprintf(fp, "\n"); - } + Line *line; + int blank = 1; + + if (!strcmp(entry->name, "comment")) + (void) 0; + else + fprintf(fp, "# TAG: %s", entry->name); + + if (entry->comment) + fprintf(fp, "\t%s", entry->comment); + + fprintf(fp, "\n"); + + if (!defined(entry->ifdef)) { + fprintf(fp, "# Note: This option is only available if Squid is rebuilt with the\n"); + fprintf(fp, "# %s option\n#\n", available_if(entry->ifdef)); + } + + for (line = entry->doc; line != NULL; line = line->next) { + fprintf(fp, "#%s\n", line->data); + } + + if (entry->default_value && strcmp(entry->default_value, "none") != 0) { + sprintf(buf, "%s %s", entry->name, entry->default_value); + lineAdd(&def, buf); + } + + if (entry->default_if_none) { + for (line = entry->default_if_none; line; line = line->next) { + sprintf(buf, "%s %s", entry->name, line->data); + lineAdd(&def, buf); + } + } + + if (entry->nocomment) + blank = 0; + + if (!def && entry->doc && !entry->nocomment && + strcmp(entry->name, "comment") != 0) + lineAdd(&def, "none"); + + if (def && (entry->doc || entry->nocomment)) { + if (blank) + fprintf(fp, "#\n"); + + fprintf(fp, "#Default:\n"); + + while (def != NULL) { + line = def; + def = line->next; + fprintf(fp, "# %s\n", line->data); + xfree(line->data); + xfree(line); + } + + blank = 1; + } + + if (entry->nocomment && blank) + fprintf(fp, "#\n"); + + for (line = entry->nocomment; line != NULL; line = line->next) { + fprintf(fp, "%s\n", line->data); + } + + if (entry->doc != NULL) { + fprintf(fp, "\n"); + } } } diff --git a/src/client.cc b/src/client.cc index b224014711..04936efb3d 100644 --- a/src/client.cc +++ b/src/client.cc @@ -1,6 +1,6 @@ /* - * $Id: client.cc,v 1.104 2003/02/03 21:33:15 robertc Exp $ + * $Id: client.cc,v 1.105 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 0 WWW Client * AUTHOR: Harvest Derived @@ -41,8 +41,10 @@ /* Local functions */ static int client_comm_bind(int, const char *); + static int client_comm_connect(int, const char *, u_short, struct timeval *); static void usage(const char *progname); + static int Now(struct timeval *); static SIGHDLR catchSignal; static SIGHDLR pipe_handler; @@ -53,6 +55,7 @@ static ssize_t mywrite(int fd, void *buf, size_t len); #endif static int put_fd; static char *put_file = NULL; + static struct stat sb; int total_bytes = 0; int io_timeout = 120; @@ -61,28 +64,28 @@ static void usage(const char *progname) { fprintf(stderr, - "Usage: %s [-arsv] [-i IMS] [-h remote host] [-l local host] [-p port] [-m method] [-t count] [-I ping-interval] [-H 'strings'] [-T timeout] url\n" - "Options:\n" - " -P file PUT request.\n" - " -a Do NOT include Accept: header.\n" - " -r Force cache to reload URL.\n" - " -s Silent. Do not print data to stdout.\n" - " -v Verbose. Print outgoing message to stderr.\n" - " -i IMS If-Modified-Since time (in Epoch seconds).\n" - " -h host Retrieve URL from cache on hostname. Default is localhost.\n" - " -l host Specify a local IP address to bind to. Default is none.\n" - " -p port Port number of cache. Default is %d.\n" - " -m method Request method, default is GET.\n" - " -t count Trace count cache-hops\n" - " -g count Ping mode, \"count\" iterations (0 to loop until interrupted).\n" - " -I interval Ping interval in seconds (default 1 second).\n" - " -H 'string' Extra headers to send. Use '\\n' for new lines.\n" - " -T timeout Timeout value (seconds) for read/write operations.\n" - " -u user Proxy authentication username\n" - " -w password Proxy authentication password\n" - " -U user WWW authentication username\n" - " -W password WWW authentication password\n", - progname, CACHE_HTTP_PORT); + "Usage: %s [-arsv] [-i IMS] [-h remote host] [-l local host] [-p port] [-m method] [-t count] [-I ping-interval] [-H 'strings'] [-T timeout] url\n" + "Options:\n" + " -P file PUT request.\n" + " -a Do NOT include Accept: header.\n" + " -r Force cache to reload URL.\n" + " -s Silent. Do not print data to stdout.\n" + " -v Verbose. Print outgoing message to stderr.\n" + " -i IMS If-Modified-Since time (in Epoch seconds).\n" + " -h host Retrieve URL from cache on hostname. Default is localhost.\n" + " -l host Specify a local IP address to bind to. Default is none.\n" + " -p port Port number of cache. Default is %d.\n" + " -m method Request method, default is GET.\n" + " -t count Trace count cache-hops\n" + " -g count Ping mode, \"count\" iterations (0 to loop until interrupted).\n" + " -I interval Ping interval in seconds (default 1 second).\n" + " -H 'string' Extra headers to send. Use '\\n' for new lines.\n" + " -T timeout Timeout value (seconds) for read/write operations.\n" + " -u user Proxy authentication username\n" + " -w password Proxy authentication password\n" + " -U user WWW authentication username\n" + " -W password WWW authentication password\n", + progname, CACHE_HTTP_PORT); exit(1); } @@ -103,6 +106,7 @@ main(int argc, char *argv[]) extern char *optarg; time_t ims = 0; int max_forwards = -1; + struct timeval tv1, tv2; int i = 0, loops; long ping_int; @@ -124,408 +128,525 @@ main(int argc, char *argv[]) ping_int = 1 * 1000; if (argc < 2) { - usage(argv[0]); /* need URL */ + usage(argv[0]); /* need URL */ } else if (argc >= 2) { - strncpy(url, argv[argc - 1], BUFSIZ); - url[BUFSIZ - 1] = '\0'; - if (url[0] == '-') - usage(argv[0]); - while ((c = getopt(argc, argv, "ah:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1) - switch (c) { - case 'a': - opt_noaccept = 1; - break; - case 'h': /* remote host */ - if (optarg != NULL) - hostname = optarg; - break; - case 'l': /* local host */ - if (optarg != NULL) - localhost = optarg; - break; - case 's': /* silent */ - to_stdout = 0; - break; - case 'k': /* backward compat */ - keep_alive = 1; - break; - case 'r': /* reload */ - reload = 1; - break; - case 'p': /* port number */ - sscanf(optarg, "%d", &port); - if (port < 1) - port = CACHE_HTTP_PORT; /* default */ - break; - case 'P': - put_file = xstrdup(optarg); - break; - case 'i': /* IMS */ - ims = (time_t) atoi(optarg); - break; - case 'm': - method = xstrdup(optarg); - break; - case 't': - method = xstrdup("TRACE"); - max_forwards = atoi(optarg); - break; - case 'g': - ping = 1; - pcount = atoi(optarg); - to_stdout = 0; - break; - case 'I': - if ((ping_int = atoi(optarg) * 1000) <= 0) - usage(argv[0]); - break; - case 'H': - if (strlen(optarg)) { - char *t; - strncpy(extra_hdrs, optarg, sizeof(extra_hdrs)); - while ((t = strstr(extra_hdrs, "\\n"))) - *t = '\r', *(t + 1) = '\n'; - } - break; - case 'T': - io_timeout = atoi(optarg); - break; - case 'u': - proxy_user = optarg; - break; - case 'w': - proxy_password = optarg; - break; - case 'U': - www_user = optarg; - break; - case 'W': - www_password = optarg; - break; - case 'v': - /* undocumented: may increase verb-level by giving more -v's */ - opt_verbose++; - break; - case '?': /* usage */ - default: - usage(argv[0]); - break; - } + strncpy(url, argv[argc - 1], BUFSIZ); + url[BUFSIZ - 1] = '\0'; + + if (url[0] == '-') + usage(argv[0]); + + while ((c = getopt(argc, argv, "ah:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1) + switch (c) { + + case 'a': + opt_noaccept = 1; + break; + + case 'h': /* remote host */ + + if (optarg != NULL) + hostname = optarg; + + break; + + case 'l': /* local host */ + if (optarg != NULL) + localhost = optarg; + + break; + + case 's': /* silent */ + to_stdout = 0; + + break; + + case 'k': /* backward compat */ + keep_alive = 1; + + break; + + case 'r': /* reload */ + reload = 1; + + break; + + case 'p': /* port number */ + sscanf(optarg, "%d", &port); + + if (port < 1) + port = CACHE_HTTP_PORT; /* default */ + + break; + + case 'P': + put_file = xstrdup(optarg); + + break; + + case 'i': /* IMS */ + ims = (time_t) atoi(optarg); + + break; + + case 'm': + method = xstrdup(optarg); + + break; + + case 't': + method = xstrdup("TRACE"); + + max_forwards = atoi(optarg); + + break; + + case 'g': + ping = 1; + + pcount = atoi(optarg); + + to_stdout = 0; + + break; + + case 'I': + if ((ping_int = atoi(optarg) * 1000) <= 0) + usage(argv[0]); + + break; + + case 'H': + if (strlen(optarg)) { + char *t; + strncpy(extra_hdrs, optarg, sizeof(extra_hdrs)); + + while ((t = strstr(extra_hdrs, "\\n"))) + *t = '\r', *(t + 1) = '\n'; + } + + break; + + case 'T': + io_timeout = atoi(optarg); + break; + + case 'u': + proxy_user = optarg; + break; + + case 'w': + proxy_password = optarg; + break; + + case 'U': + www_user = optarg; + break; + + case 'W': + www_password = optarg; + break; + + case 'v': + /* undocumented: may increase verb-level by giving more -v's */ + opt_verbose++; + break; + + case '?': /* usage */ + + default: + usage(argv[0]); + break; + } } + #ifdef _SQUID_MSWIN_ { - WSADATA wsaData; - WSAStartup(2, &wsaData); + WSADATA wsaData; + WSAStartup(2, &wsaData); } #endif /* Build the HTTP request */ if (strncmp(url, "mgr:", 4) == 0) { - char *t = xstrdup(url + 4); - snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t); - xfree(t); + char *t = xstrdup(url + 4); + snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t); + xfree(t); } + if (put_file) { - put_fd = open(put_file, O_RDONLY); - set_our_signal(); - if (put_fd < 0) { - fprintf(stderr, "%s: can't open file (%s)\n", argv[0], - xstrerror()); - exit(-1); - } + put_fd = open(put_file, O_RDONLY); + set_our_signal(); + + if (put_fd < 0) { + fprintf(stderr, "%s: can't open file (%s)\n", argv[0], + xstrerror()); + exit(-1); + } + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - setmode(put_fd, O_BINARY); + setmode(put_fd, O_BINARY); + #endif - fstat(put_fd, &sb); + + fstat(put_fd, &sb); } + snprintf(msg, BUFSIZ, "%s %s HTTP/1.0\r\n", method, url); + if (reload) { - snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n"); - strcat(msg, buf); + snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n"); + strcat(msg, buf); } + if (put_fd > 0) { - snprintf(buf, BUFSIZ, "Content-length: %d\r\n", (int) sb.st_size); - strcat(msg, buf); + snprintf(buf, BUFSIZ, "Content-length: %d\r\n", (int) sb.st_size); + strcat(msg, buf); } + if (opt_noaccept == 0) { - snprintf(buf, BUFSIZ, "Accept: */*\r\n"); - strcat(msg, buf); + snprintf(buf, BUFSIZ, "Accept: */*\r\n"); + strcat(msg, buf); } + if (ims) { - snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims)); - strcat(msg, buf); + snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims)); + strcat(msg, buf); } + if (max_forwards > -1) { - snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards); - strcat(msg, buf); + snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards); + strcat(msg, buf); } + if (proxy_user) { - char *user = proxy_user; - char *password = proxy_password; + char *user = proxy_user; + char *password = proxy_password; #if HAVE_GETPASS - if (!password) - password = getpass("Proxy password: "); + + if (!password) + password = getpass("Proxy password: "); + #endif - if (!password) { - fprintf(stderr, "ERROR: Proxy password missing\n"); - exit(1); - } - snprintf(buf, BUFSIZ, "%s:%s", user, password); - snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\n", base64_encode(buf)); - strcat(msg, buf); + + if (!password) { + fprintf(stderr, "ERROR: Proxy password missing\n"); + exit(1); + } + + snprintf(buf, BUFSIZ, "%s:%s", user, password); + snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\n", base64_encode(buf)); + strcat(msg, buf); } + if (www_user) { - char *user = www_user; - char *password = www_password; + char *user = www_user; + char *password = www_password; #if HAVE_GETPASS - if (!password) - password = getpass("WWW password: "); + + if (!password) + password = getpass("WWW password: "); + #endif - if (!password) { - fprintf(stderr, "ERROR: WWW password missing\n"); - exit(1); - } - snprintf(buf, BUFSIZ, "%s:%s", user, password); - snprintf(buf, BUFSIZ, "Authorization: Basic %s\n", base64_encode(buf)); - strcat(msg, buf); + + if (!password) { + fprintf(stderr, "ERROR: WWW password missing\n"); + exit(1); + } + + snprintf(buf, BUFSIZ, "%s:%s", user, password); + snprintf(buf, BUFSIZ, "Authorization: Basic %s\n", base64_encode(buf)); + strcat(msg, buf); } + if (keep_alive) { - if (port != 80) - snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n"); - else - snprintf(buf, BUFSIZ, "Connection: keep-alive\r\n"); - strcat(msg, buf); + if (port != 80) + snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n"); + else + snprintf(buf, BUFSIZ, "Connection: keep-alive\r\n"); + + strcat(msg, buf); } + strcat(msg, extra_hdrs); snprintf(buf, BUFSIZ, "\r\n"); strcat(msg, buf); if (opt_verbose) - fprintf(stderr, "headers: '%s'\n", msg); + fprintf(stderr, "headers: '%s'\n", msg); if (ping) { #if HAVE_SIGACTION - struct sigaction sa, osa; - if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) { - sa.sa_handler = catchSignal; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - (void) sigaction(SIGINT, &sa, NULL); - } + + struct sigaction sa, osa; + + if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) { + sa.sa_handler = catchSignal; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + (void) sigaction(SIGINT, &sa, NULL); + } + #else - void (*osig) (int); - if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL) - (void) signal(SIGINT, osig); + void (*osig) (int); + + if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL) + (void) signal(SIGINT, osig); + #endif + } + loops = ping ? pcount : 1; + for (i = 0; loops == 0 || i < loops; i++) { - int fsize = 0; - /* Connect to the server */ - if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - perror("client: socket"); - exit(1); - } - if (localhost && client_comm_bind(conn, localhost) < 0) { - perror("client: bind"); - exit(1); - } - if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) { - if (errno == 0) { - fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.\n", hostname, port); - } else { - char tbuf[BUFSIZ]; - snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d", - hostname, port); - perror(tbuf); - } - exit(1); - } - /* Send the HTTP request */ + int fsize = 0; + /* Connect to the server */ + + if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + perror("client: socket"); + exit(1); + } + + if (localhost && client_comm_bind(conn, localhost) < 0) { + perror("client: bind"); + exit(1); + } + + if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) { + if (errno == 0) { + fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.\n", hostname, port); + } else { + char tbuf[BUFSIZ]; + snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d", + hostname, port); + perror(tbuf); + } + + exit(1); + } + + /* Send the HTTP request */ #ifdef _SQUID_MSWIN_ - bytesWritten = send(conn, msg, strlen(msg), 0); + bytesWritten = send(conn, msg, strlen(msg), 0); + #else - bytesWritten = mywrite(conn, msg, strlen(msg)); + + bytesWritten = mywrite(conn, msg, strlen(msg)); + #endif - if (bytesWritten < 0) { - perror("client: ERROR: write"); - exit(1); - } else if ((unsigned) bytesWritten != strlen(msg)) { - fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg); - exit(1); - } - if (put_file) { - int x; - lseek(put_fd, 0, SEEK_SET); + + if (bytesWritten < 0) { + perror("client: ERROR: write"); + exit(1); + } else if ((unsigned) bytesWritten != strlen(msg)) { + fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg); + exit(1); + } + + if (put_file) { + int x; + lseek(put_fd, 0, SEEK_SET); #ifdef _SQUID_MSWIN_ - while ((x = read(put_fd, buf, sizeof(buf))) > 0) { - x = write(conn, buf, x); + + while ((x = read(put_fd, buf, sizeof(buf))) > 0) { + x = write(conn, buf, x); #else - while ((x = myread(put_fd, buf, sizeof(buf))) > 0) { - x = mywrite(conn, buf, x); + + while ((x = myread(put_fd, buf, sizeof(buf))) > 0) { + x = mywrite(conn, buf, x); #endif - total_bytes += x; - if (x <= 0) - break; - } - if (x != 0) - fprintf(stderr, "client: ERROR: Cannot send file.\n"); - } - /* Read the data */ + + total_bytes += x; + + if (x <= 0) + break; + } + + if (x != 0) + fprintf(stderr, "client: ERROR: Cannot send file.\n"); + } + + /* Read the data */ #ifdef _SQUID_MSWIN_ - setmode(1, O_BINARY); - while ((len = recv(conn, buf, sizeof(buf), 0)) > 0) { + setmode(1, O_BINARY); + + while ((len = recv(conn, buf, sizeof(buf), 0)) > 0) { #else - while ((len = myread(conn, buf, sizeof(buf))) > 0) { + + while ((len = myread(conn, buf, sizeof(buf))) > 0) { #endif - fsize += len; - if (to_stdout) - fwrite(buf, len, 1, stdout); - } + fsize += len; + + if (to_stdout) + fwrite(buf, len, 1, stdout); + } + #ifdef _SQUID_MSWIN_ - setmode(1, O_TEXT); + setmode(1, O_TEXT); + #endif - (void) close(conn); /* done with socket */ - - if (interrupted) - break; - - if (ping) { - struct tm *tmp; - time_t t2s; - long elapsed_msec; - - (void) Now(&tv2); - elapsed_msec = tvSubMsec(tv1, tv2); - t2s = tv2.tv_sec; - tmp = localtime(&t2s); - fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs, %f KB/s\n", - tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1, - elapsed_msec / 1000, elapsed_msec % 1000, - elapsed_msec ? (double) fsize / elapsed_msec : -1.0); - if (i == 0 || elapsed_msec < ping_min) - ping_min = elapsed_msec; - if (i == 0 || elapsed_msec > ping_max) - ping_max = elapsed_msec; - ping_sum += elapsed_msec; - /* Delay until next "ping_int" boundary */ - if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) { - struct timeval tvs; - long msec_left = ping_int - elapsed_msec; - - tvs.tv_sec = msec_left / 1000; - tvs.tv_usec = (msec_left % 1000) * 1000; - select(0, NULL, NULL, NULL, &tvs); - } - } + + (void) close(conn); /* done with socket */ + + if (interrupted) + break; + + if (ping) { + + struct tm *tmp; + time_t t2s; + long elapsed_msec; + + (void) Now(&tv2); + elapsed_msec = tvSubMsec(tv1, tv2); + t2s = tv2.tv_sec; + tmp = localtime(&t2s); + fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs, %f KB/s\n", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1, + elapsed_msec / 1000, elapsed_msec % 1000, + elapsed_msec ? (double) fsize / elapsed_msec : -1.0); + + if (i == 0 || elapsed_msec < ping_min) + ping_min = elapsed_msec; + + if (i == 0 || elapsed_msec > ping_max) + ping_max = elapsed_msec; + + ping_sum += elapsed_msec; + + /* Delay until next "ping_int" boundary */ + if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) { + + struct timeval tvs; + long msec_left = ping_int - elapsed_msec; + + tvs.tv_sec = msec_left / 1000; + tvs.tv_usec = (msec_left % 1000) * 1000; + select(0, NULL, NULL, NULL, &tvs); + } + } } if (ping && i) { - ping_mean = ping_sum / i; - fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = " - "%ld.%03ld/%ld.%03ld/%ld.%03ld\n", i, - ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000, - ping_max / 1000, ping_max % 1000); + ping_mean = ping_sum / i; + fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = " + "%ld.%03ld/%ld.%03ld/%ld.%03ld\n", i, + ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000, + ping_max / 1000, ping_max % 1000); } + exit(0); /*NOTREACHED */ return 0; } static int -client_comm_bind(int sock, const char *local_host) -{ +client_comm_bind(int sock, const char *local_host) { + static const struct hostent *hp = NULL; + static struct sockaddr_in from_addr; /* Set up the source socket address from which to send. */ + if (hp == NULL) { - from_addr.sin_family = AF_INET; + from_addr.sin_family = AF_INET; + + if ((hp = gethostbyname(local_host)) == 0) { + return (-1); + } - if ((hp = gethostbyname(local_host)) == 0) { - return (-1); - } - xmemcpy(&from_addr.sin_addr, hp->h_addr, hp->h_length); - from_addr.sin_port = 0; + xmemcpy(&from_addr.sin_addr, hp->h_addr, hp->h_length); + from_addr.sin_port = 0; } + return bind(sock, (struct sockaddr *) &from_addr, sizeof(struct sockaddr_in)); } static int -client_comm_connect(int sock, const char *dest_host, u_short dest_port, struct timeval *tvp) -{ + +client_comm_connect(int sock, const char *dest_host, u_short dest_port, struct timeval *tvp) { + static const struct hostent *hp = NULL; + static struct sockaddr_in to_addr; /* Set up the destination socket address for message to send to. */ - if (hp == NULL) { - to_addr.sin_family = AF_INET; - if ((hp = gethostbyname(dest_host)) == 0) { - return (-1); - } - xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length); - to_addr.sin_port = htons(dest_port); + if (hp == NULL) + { + to_addr.sin_family = AF_INET; + + if ((hp = gethostbyname(dest_host)) == 0) { + return (-1); + } + + xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length); + to_addr.sin_port = htons(dest_port); } + if (tvp) - (void) Now(tvp); + (void) Now(tvp); + return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)); } static int -Now(struct timeval *tp) -{ + +Now(struct timeval *tp) { #if GETTIMEOFDAY_NO_TZP return gettimeofday(tp); #else + return gettimeofday(tp, NULL); #endif } /* ARGSUSED */ static void -catchSignal(int sig) -{ +catchSignal(int sig) { interrupted = 1; fprintf(stderr, "Interrupted.\n"); } static void -pipe_handler(int sig) -{ +pipe_handler(int sig) { fprintf(stderr, "SIGPIPE received.\n"); } static void -set_our_signal(void) -{ +set_our_signal(void) { #if HAVE_SIGACTION + struct sigaction sa; sa.sa_handler = pipe_handler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); + if (sigaction(SIGPIPE, &sa, NULL) < 0) { - fprintf(stderr, "Cannot set PIPE signal.\n"); - exit(-1); + fprintf(stderr, "Cannot set PIPE signal.\n"); + exit(-1); } + #else signal(SIGPIPE, pipe_handler); + #endif } #ifndef _SQUID_MSWIN_ static ssize_t -myread(int fd, void *buf, size_t len) -{ +myread(int fd, void *buf, size_t len) { alarm(io_timeout); return read(fd, buf, len); } static ssize_t -mywrite(int fd, void *buf, size_t len) -{ +mywrite(int fd, void *buf, size_t len) { alarm(io_timeout); return write(fd, buf, len); } + #endif diff --git a/src/clientStream.cc b/src/clientStream.cc index 6578970a4a..c91656d183 100644 --- a/src/clientStream.cc +++ b/src/clientStream.cc @@ -1,6 +1,6 @@ /* - * $Id: clientStream.cc,v 1.4 2003/01/23 00:37:17 robertc Exp $ + * $Id: clientStream.cc,v 1.5 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 87 Client-side Stream routines. * AUTHOR: Robert Collins @@ -107,7 +107,7 @@ static FREE clientStreamFree; clientStreamNode * clientStreamNew(CSR * readfunc, CSCB * callback, CSD * detach, CSS * status, - void *data) + void *data) { clientStreamNode *temp; CBDATA_INIT_TYPE_FREECB(clientStreamNode, clientStreamFree); @@ -129,11 +129,11 @@ clientStreamNew(CSR * readfunc, CSCB * callback, CSD * detach, CSS * status, */ void clientStreamInit(dlink_list * list, CSR * func, CSD * rdetach, CSS * readstatus, - void *readdata, CSCB * callback, CSD * cdetach, void *callbackdata, - StoreIOBuffer tailBuffer) + void *readdata, CSCB * callback, CSD * cdetach, void *callbackdata, + StoreIOBuffer tailBuffer) { clientStreamNode *temp = clientStreamNew(func, NULL, rdetach, readstatus, - readdata); + readdata); dlinkAdd(temp, &temp->node, list); cbdataReference(temp); temp->head = list; @@ -151,7 +151,7 @@ clientStreamInit(dlink_list * list, CSR * func, CSD * rdetach, CSS * readstatus, */ void clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback, - CSD * detach, CSS * status, void *data) + CSD * detach, CSS * status, void *data) { clientStreamNode *temp; @@ -161,8 +161,8 @@ clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback, temp = clientStreamNew(func, callback, detach, status, data); temp->head = list; debug(87, 3) - ("clientStreamInsertHead: Inserted node %p with data %p after head\n", - temp, data); + ("clientStreamInsertHead: Inserted node %p with data %p after head\n", + temp, data); dlinkAddAfter(temp, &temp->node, list->head, list); cbdataReference(temp); } @@ -172,15 +172,15 @@ clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback, */ void clientStreamCallback(clientStreamNode * thisObject, clientHttpRequest * http, - HttpReply * rep, StoreIOBuffer replyBuffer) + HttpReply * rep, StoreIOBuffer replyBuffer) { clientStreamNode *next; assert(thisObject && http && thisObject->node.next); next = thisObject->next(); debug(87, - 3) ("clientStreamCallback: Calling %p with cbdata %p from node %p\n", - next->callback, next->data, thisObject); + 3) ("clientStreamCallback: Calling %p with cbdata %p from node %p\n", + next->callback, next->data, thisObject); next->callback(next, http, rep, replyBuffer); } @@ -189,7 +189,7 @@ clientStreamCallback(clientStreamNode * thisObject, clientHttpRequest * http, */ void clientStreamRead(clientStreamNode * thisObject, clientHttpRequest * http, - StoreIOBuffer readBuffer) + StoreIOBuffer readBuffer) { /* place the parameters on the 'stack' */ clientStreamNode *prev; @@ -197,7 +197,7 @@ clientStreamRead(clientStreamNode * thisObject, clientHttpRequest * http, prev = thisObject->prev(); debug(87, 3) ("clientStreamRead: Calling %p with cbdata %p from node %p\n", - prev->readfunc, prev->data, thisObject); + prev->readfunc, prev->data, thisObject); thisObject->readBuffer = readBuffer; prev->readfunc(prev, http); } @@ -222,10 +222,11 @@ clientStreamDetach(clientStreamNode * thisObject, clientHttpRequest * http) * We do it in thisObject order so that the detaching node is always * at the end of the list */ + if (prev) { - debug(87, 3) ("clientStreamDetach: Calling %p with cbdata %p\n", - prev->detach, prev->data); - prev->detach(prev, http); + debug(87, 3) ("clientStreamDetach: Calling %p with cbdata %p\n", + prev->detach, prev->data); + prev->detach(prev, http); } } @@ -241,9 +242,10 @@ clientStreamAbort(clientStreamNode * thisObject, clientHttpRequest * http) assert(http != NULL); list = thisObject->head; debug(87, 3) ("clientStreamAbort: Aborting stream with tail %p\n", - list->tail); + list->tail); + if (list->tail) { - clientStreamDetach((clientStreamNode *)list->tail->data, http); + clientStreamDetach((clientStreamNode *)list->tail->data, http); } } @@ -266,11 +268,13 @@ clientStreamFree(void *foo) clientStreamNode *thisObject = (clientStreamNode *)foo; debug(87, 3) ("Freeing clientStreamNode %p\n", thisObject); + if (thisObject->data) { - cbdataFree(thisObject->data); + cbdataFree(thisObject->data); } + if (thisObject->node.next || thisObject->node.prev) { - dlinkDelete(&thisObject->node, thisObject->head); + dlinkDelete(&thisObject->node, thisObject->head); } } @@ -278,16 +282,16 @@ _clientStreamNode * _clientStreamNode::prev() const { if (node.prev) - return (_clientStreamNode *)node.prev->data; + return (_clientStreamNode *)node.prev->data; else - return NULL; + return NULL; } _clientStreamNode * _clientStreamNode::next() const { if (node.next) - return (_clientStreamNode *)node.next->data; + return (_clientStreamNode *)node.next->data; else - return NULL; + return NULL; } diff --git a/src/clientStream.h b/src/clientStream.h index b602eb0ee8..7cb4e5615c 100644 --- a/src/clientStream.h +++ b/src/clientStream.h @@ -1,6 +1,6 @@ /* - * $Id: clientStream.h,v 1.3 2003/01/23 00:37:17 robertc Exp $ + * $Id: clientStream.h,v 1.4 2003/02/21 22:50:07 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,6 +37,7 @@ #include "StoreIOBuffer.h" typedef struct _clientStreamNode clientStreamNode; + class ClientHttpRequest; /* client stream read callback */ typedef void CSCB(clientStreamNode *, ClientHttpRequest *, HttpReply *, StoreIOBuffer); @@ -47,12 +48,15 @@ typedef void CSD(clientStreamNode *, ClientHttpRequest *); typedef clientStream_status_t CSS(clientStreamNode *, ClientHttpRequest *); -struct _clientStreamNode { +struct _clientStreamNode +{ #ifdef __cplusplus + public: _clientStreamNode *prev() const; _clientStreamNode *next() const; #endif + dlink_node node; dlink_list *head; /* sucks I know, but hey, the interface is limited */ CSR *readfunc; diff --git a/src/client_db.cc b/src/client_db.cc index c3c0f7cba7..80151b2112 100644 --- a/src/client_db.cc +++ b/src/client_db.cc @@ -1,6 +1,6 @@ /* - * $Id: client_db.cc,v 1.56 2003/01/23 00:37:17 robertc Exp $ + * $Id: client_db.cc,v 1.57 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 0 Client Database * AUTHOR: Duane Wessels @@ -38,10 +38,12 @@ static hash_table *client_table = NULL; + static ClientInfo *clientdbAdd(struct in_addr addr); static FREE clientdbFreeItem; static ClientInfo * + clientdbAdd(struct in_addr addr) { ClientInfo *c; @@ -57,39 +59,52 @@ void clientdbInit(void) { if (client_table) - return; + return; + client_table = hash_create((HASHCMP *) strcmp, 467, hash_string); + cachemgrRegister("client_list", - "Cache Client List", - clientdbDump, - 0, 1); + "Cache Client List", + clientdbDump, + 0, 1); } void + clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, size_t size) { char *key; ClientInfo *c; + if (!Config.onoff.client_db) - return; + return; + key = inet_ntoa(addr); + c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) - c = clientdbAdd(addr); + c = clientdbAdd(addr); + if (c == NULL) - debug_trap("clientdbUpdate: Failed to add entry"); - if (p == PROTO_HTTP) { - c->Http.n_requests++; - c->Http.result_hist[ltype]++; - kb_incr(&c->Http.kbytes_out, size); - if (logTypeIsATcpHit(ltype)) - kb_incr(&c->Http.hit_kbytes_out, size); - } else if (p == PROTO_ICP) { - c->Icp.n_requests++; - c->Icp.result_hist[ltype]++; - kb_incr(&c->Icp.kbytes_out, size); - if (LOG_UDP_HIT == ltype) - kb_incr(&c->Icp.hit_kbytes_out, size); + debug_trap("clientdbUpdate: Failed to add entry"); + + if (p == PROTO_HTTP) + { + c->Http.n_requests++; + c->Http.result_hist[ltype]++; + kb_incr(&c->Http.kbytes_out, size); + + if (logTypeIsATcpHit(ltype)) + kb_incr(&c->Http.hit_kbytes_out, size); + } else if (p == PROTO_ICP) + { + c->Icp.n_requests++; + c->Icp.result_hist[ltype]++; + kb_incr(&c->Icp.kbytes_out, size); + + if (LOG_UDP_HIT == ltype) + kb_incr(&c->Icp.hit_kbytes_out, size); } } @@ -101,24 +116,33 @@ clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, size_t size) * -1. To get the current value, simply call with delta = 0. */ int + clientdbEstablished(struct in_addr addr, int delta) { char *key; ClientInfo *c; + if (!Config.onoff.client_db) - return 0; + return 0; + key = inet_ntoa(addr); + c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) - c = clientdbAdd(addr); + c = clientdbAdd(addr); + if (c == NULL) - debug_trap("clientdbUpdate: Failed to add entry"); + debug_trap("clientdbUpdate: Failed to add entry"); + c->n_established += delta; + return c->n_established; } #define CUTOFF_SECONDS 3600 int + clientdbCutoffDenied(struct in_addr addr) { char *key; @@ -126,35 +150,52 @@ clientdbCutoffDenied(struct in_addr addr) int ND; double p; ClientInfo *c; + if (!Config.onoff.client_db) - return 0; + return 0; + key = inet_ntoa(addr); + c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) - return 0; + return 0; + /* * If we are in a cutoff window, we don't send a reply */ if (squid_curtime - c->cutoff.time < CUTOFF_SECONDS) - return 1; + return 1; + /* * Calculate the percent of DENIED replies since the last * cutoff time. */ NR = c->Icp.n_requests - c->cutoff.n_req; + if (NR < 150) - NR = 150; + NR = 150; + ND = c->Icp.result_hist[LOG_UDP_DENIED] - c->cutoff.n_denied; + p = 100.0 * ND / NR; + if (p < 95.0) - return 0; + return 0; + debug(1, 0) ("WARNING: Probable misconfigured neighbor at %s\n", key); + debug(1, 0) ("WARNING: %d of the last %d ICP replies are DENIED\n", ND, NR); + debug(1, 0) ("WARNING: No replies will be sent for the next %d seconds\n", - CUTOFF_SECONDS); + CUTOFF_SECONDS); + c->cutoff.time = squid_curtime; + c->cutoff.n_req = c->Icp.n_requests; + c->cutoff.n_denied = c->Icp.result_hist[LOG_UDP_DENIED]; + return 1; } @@ -176,46 +217,58 @@ clientdbDump(StoreEntry * sentry) int http_hits = 0; storeAppendPrintf(sentry, "Cache Clients:\n"); hash_first(client_table); + while ((c = (ClientInfo *) hash_next(client_table))) { - storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(&c->hash)); - storeAppendPrintf(sentry, "Name: %s\n", fqdnFromAddr(c->addr)); - storeAppendPrintf(sentry, "Currently established connections: %d\n", - c->n_established); - storeAppendPrintf(sentry, " ICP Requests %d\n", - c->Icp.n_requests); - for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { - if (c->Icp.result_hist[l] == 0) - continue; - icp_total += c->Icp.result_hist[l]; - if (LOG_UDP_HIT == l) - icp_hits += c->Icp.result_hist[l]; - storeAppendPrintf(sentry, - " %-20.20s %7d %3d%%\n", - log_tags[l], - c->Icp.result_hist[l], - percent(c->Icp.result_hist[l], c->Icp.n_requests)); - } - storeAppendPrintf(sentry, " HTTP Requests %d\n", - c->Http.n_requests); - for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { - if (c->Http.result_hist[l] == 0) - continue; - http_total += c->Http.result_hist[l]; - if (logTypeIsATcpHit(l)) - http_hits += c->Http.result_hist[l]; - storeAppendPrintf(sentry, - " %-20.20s %7d %3d%%\n", - log_tags[l], - c->Http.result_hist[l], - percent(c->Http.result_hist[l], c->Http.n_requests)); - } - storeAppendPrintf(sentry, "\n"); + storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(&c->hash)); + storeAppendPrintf(sentry, "Name: %s\n", fqdnFromAddr(c->addr)); + storeAppendPrintf(sentry, "Currently established connections: %d\n", + c->n_established); + storeAppendPrintf(sentry, " ICP Requests %d\n", + c->Icp.n_requests); + + for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { + if (c->Icp.result_hist[l] == 0) + continue; + + icp_total += c->Icp.result_hist[l]; + + if (LOG_UDP_HIT == l) + icp_hits += c->Icp.result_hist[l]; + + storeAppendPrintf(sentry, + " %-20.20s %7d %3d%%\n", + log_tags[l], + c->Icp.result_hist[l], + percent(c->Icp.result_hist[l], c->Icp.n_requests)); + } + + storeAppendPrintf(sentry, " HTTP Requests %d\n", + c->Http.n_requests); + + for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { + if (c->Http.result_hist[l] == 0) + continue; + + http_total += c->Http.result_hist[l]; + + if (logTypeIsATcpHit(l)) + http_hits += c->Http.result_hist[l]; + + storeAppendPrintf(sentry, + " %-20.20s %7d %3d%%\n", + log_tags[l], + c->Http.result_hist[l], + percent(c->Http.result_hist[l], c->Http.n_requests)); + } + + storeAppendPrintf(sentry, "\n"); } + storeAppendPrintf(sentry, "TOTALS\n"); storeAppendPrintf(sentry, "ICP : %d Queries, %d Hits (%3d%%)\n", - icp_total, icp_hits, percent(icp_hits, icp_total)); + icp_total, icp_hits, percent(icp_hits, icp_total)); storeAppendPrintf(sentry, "HTTP: %d Requests, %d Hits (%3d%%)\n", - http_total, http_hits, percent(http_hits, http_total)); + http_total, http_hits, percent(http_hits, http_total)); } static void @@ -235,28 +288,37 @@ clientdbFreeMemory(void) } #if SQUID_SNMP + struct in_addr * -client_entry(struct in_addr *current) + + client_entry(struct in_addr *current) { ClientInfo *c = NULL; char *key; - if (current) { - key = inet_ntoa(*current); - hash_first(client_table); - while ((c = (ClientInfo *) hash_next(client_table))) { - if (!strcmp(key, hashKeyStr(&c->hash))) - break; - } - c = (ClientInfo *) hash_next(client_table); - } else { - hash_first(client_table); - c = (ClientInfo *) hash_next(client_table); + + if (current) + { + key = inet_ntoa(*current); + hash_first(client_table); + + while ((c = (ClientInfo *) hash_next(client_table))) { + if (!strcmp(key, hashKeyStr(&c->hash))) + break; + } + + c = (ClientInfo *) hash_next(client_table); + } else + { + hash_first(client_table); + c = (ClientInfo *) hash_next(client_table); } + hash_last(client_table); + if (c) - return (&c->addr); + return (&c->addr); else - return (NULL); + return (NULL); } @@ -272,71 +334,86 @@ snmp_meshCtblFn(variable_list * Var, snint * ErrP) debug(49, 6) ("snmp_meshCtblFn: Current : \n"); snmpDebugOid(6, Var->name, Var->name_length); snprintf(key, sizeof(key), "%d.%d.%d.%d", Var->name[LEN_SQ_NET + 3], Var->name[LEN_SQ_NET + 4], - Var->name[LEN_SQ_NET + 5], Var->name[LEN_SQ_NET + 6]); + Var->name[LEN_SQ_NET + 5], Var->name[LEN_SQ_NET + 6]); debug(49, 5) ("snmp_meshCtblFn: [%s] requested!\n", key); c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) { - debug(49, 5) ("snmp_meshCtblFn: not found.\n"); - *ErrP = SNMP_ERR_NOSUCHNAME; - return NULL; + debug(49, 5) ("snmp_meshCtblFn: not found.\n"); + *ErrP = SNMP_ERR_NOSUCHNAME; + return NULL; } + switch (Var->name[LEN_SQ_NET + 2]) { + case MESH_CTBL_ADDR: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->addr.s_addr, - SMI_IPADDRESS); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->addr.s_addr, + SMI_IPADDRESS); + break; + case MESH_CTBL_HTBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Http.kbytes_out.kb, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Http.kbytes_out.kb, + SMI_COUNTER32); + break; + case MESH_CTBL_HTREQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Http.n_requests, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Http.n_requests, + SMI_COUNTER32); + break; + case MESH_CTBL_HTHITS: - aggr = 0; - for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { - if (logTypeIsATcpHit(l)) - aggr += c->Http.result_hist[l]; - } - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) aggr, - SMI_COUNTER32); - break; + aggr = 0; + + for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { + if (logTypeIsATcpHit(l)) + aggr += c->Http.result_hist[l]; + } + + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) aggr, + SMI_COUNTER32); + break; + case MESH_CTBL_HTHITBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Http.hit_kbytes_out.kb, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Http.hit_kbytes_out.kb, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Icp.kbytes_out.kb, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Icp.kbytes_out.kb, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPREQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Icp.n_requests, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Icp.n_requests, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPHITS: - aggr = c->Icp.result_hist[LOG_UDP_HIT]; - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) aggr, - SMI_COUNTER32); - break; + aggr = c->Icp.result_hist[LOG_UDP_HIT]; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) aggr, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPHITBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Icp.hit_kbytes_out.kb, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Icp.hit_kbytes_out.kb, + SMI_COUNTER32); + break; + default: - *ErrP = SNMP_ERR_NOSUCHNAME; - debug(49, 5) ("snmp_meshCtblFn: illegal column.\n"); - break; + *ErrP = SNMP_ERR_NOSUCHNAME; + debug(49, 5) ("snmp_meshCtblFn: illegal column.\n"); + break; } + return Answer; } diff --git a/src/client_side.cc b/src/client_side.cc index bce471e69a..ae61366060 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.623 2003/02/21 19:53:01 hno Exp $ + * $Id: client_side.cc,v 1.624 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -33,7 +33,7 @@ * */ -/* Errors and client side +/* Errors and client side * * Problem the first: the store entry is no longer authoritative on the * reply status. EBITTEST (E_ABORT) is no longer a valid test outside @@ -91,25 +91,44 @@ */ /* our socket-related context */ -class ClientSocketContext { + +class ClientSocketContext +{ + public: clientHttpRequest *http; /* we own this */ char reqbuf[HTTP_REQBUF_SZ]; ClientSocketContext *next; - struct { - int deferred:1; /* This is a pipelined request waiting for the - * current object to complete */ - int parsed_ok:1; /* Was this parsed correctly? */ - } flags; + + struct + { + +int deferred: + 1; /* This is a pipelined request waiting for the + * current object to complete */ + +int parsed_ok: + 1; /* Was this parsed correctly? */ + } + + flags; bool mayUseConnection() const {return mayUseConnection_;} - void mayUseConnection(bool aBool) {mayUseConnection_ = aBool; - debug (33,3)("ClientSocketContext::mayUseConnection: This %p marked %d\n", - this, aBool);} - struct { - clientStreamNode *node; - HttpReply *rep; - StoreIOBuffer queuedBuffer; - } deferredparams; + + void mayUseConnection(bool aBool) + { + mayUseConnection_ = aBool; + debug (33,3)("ClientSocketContext::mayUseConnection: This %p marked %d\n", + this, aBool); + } + + struct + { + clientStreamNode *node; + HttpReply *rep; + StoreIOBuffer queuedBuffer; + } + + deferredparams; off_t writtenToSocket; void pullData(); off_t getNextRangeOffset() const; @@ -127,13 +146,14 @@ public: void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer recievedData); bool multipartRangeRequest() const; void packRange(const char **buf, - size_t size, - MemBuf * mb); + size_t size, + MemBuf * mb); + private: void prepareReply(HttpReply * rep); bool mayUseConnection_; /* This request may use the connection - - * don't read anymore requests for now - */ + * don't read anymore requests for now + */ }; CBDATA_TYPE(ClientSocketContext); @@ -150,9 +170,9 @@ static PF connStateFree; static PF requestTimeout; static PF clientLifetimeTimeout; static ClientSocketContext *parseHttpRequestAbort(ConnStateData * conn, - const char *uri); + const char *uri); static ClientSocketContext *parseHttpRequest(ConnStateData *, method_t *, - char **, size_t *); + char **, size_t *); #if USE_IDENT static IDCB clientIdentDone; #endif @@ -194,6 +214,7 @@ static int connFinishedWithConn(ConnStateData * conn, int size); static void connNoteUseOfBuffer(ConnStateData * conn, size_t byteCount); static int connKeepReadingIncompleteRequest(ConnStateData * conn); static void connCancelIncompleteRequests(ConnStateData * conn); + static ConnStateData *connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_port_list *port); static int connAreAllContextsForThisConnection(ConnStateData * connState); static void connFreeAllContexts(ConnStateData * connState); @@ -226,21 +247,25 @@ void clientReadSomeData(ConnStateData *conn) { if (conn->reading) - return; + return; + conn->reading = true; + size_t len; - + debug(33, 4) ("clientReadSomeData: FD %d: reading request...\n", conn->fd); connMakeSpaceAvailable(conn); + len = connGetAvailableBufferLength(conn) - 1; - + /* Make sure we are not still reading from the client side! */ /* XXX this could take a bit of CPU time! aiee! -- adrian */ assert(!comm_has_pending_read(conn->fd)); + comm_read(conn->fd, conn->in.buf + conn->in.notYetUsed, len, clientReadRequest, conn); } - + void ClientSocketContext::removeFromConnectionList(ConnStateData * conn) @@ -250,11 +275,14 @@ ClientSocketContext::removeFromConnectionList(ConnStateData * conn) assert(connGetCurrentContext(conn) != NULL); /* Unlink us from the connection request list */ tempContextPointer = (ClientSocketContext **) & conn->currentobject; + while (*tempContextPointer) { - if (*tempContextPointer == this) - break; - tempContextPointer = &(*tempContextPointer)->next; + if (*tempContextPointer == this) + break; + + tempContextPointer = &(*tempContextPointer)->next; } + assert(*tempContextPointer != NULL); *tempContextPointer = next; next = NULL; @@ -272,8 +300,9 @@ ClientSocketContextFree(void *data) httpRequestFree(context->http); /* clean up connection links to us */ assert(context != context->next); + if (conn) - context->removeFromConnectionList(conn); + context->removeFromConnectionList(conn); } ClientSocketContext * @@ -301,12 +330,14 @@ void clientUpdateStatCounters(log_type logType) { statCounter.client_http.requests++; + if (logTypeIsATcpHit(logType)) - statCounter.client_http.hits++; + statCounter.client_http.hits++; + if (logType == LOG_TCP_HIT) - statCounter.client_http.disk_hits++; + statCounter.client_http.disk_hits++; else if (logType == LOG_TCP_MEM_HIT) - statCounter.client_http.mem_hits++; + statCounter.client_http.mem_hits++; } void @@ -319,25 +350,34 @@ clientUpdateStatHistCounters(log_type logType, int svc_time) * LOG_TCP_REFRESH_FAIL_HIT because its not really a cache hit * (we *tried* to validate it, but failed). */ + switch (logType) { + case LOG_TCP_REFRESH_HIT: - statHistCount(&statCounter.client_http.nh_svc_time, svc_time); - break; + statHistCount(&statCounter.client_http.nh_svc_time, svc_time); + break; + case LOG_TCP_IMS_HIT: - statHistCount(&statCounter.client_http.nm_svc_time, svc_time); - break; + statHistCount(&statCounter.client_http.nm_svc_time, svc_time); + break; + case LOG_TCP_HIT: + case LOG_TCP_MEM_HIT: + case LOG_TCP_OFFLINE_HIT: - statHistCount(&statCounter.client_http.hit_svc_time, svc_time); - break; + statHistCount(&statCounter.client_http.hit_svc_time, svc_time); + break; + case LOG_TCP_MISS: + case LOG_TCP_CLIENT_REFRESH_MISS: - statHistCount(&statCounter.client_http.miss_svc_time, svc_time); - break; + statHistCount(&statCounter.client_http.miss_svc_time, svc_time); + break; + default: - /* make compiler warnings go away */ - break; + /* make compiler warnings go away */ + break; } } @@ -345,7 +385,8 @@ bool clientPingHasFinished(ping_data const *aPing) { if (0 != aPing->stop.tv_sec && 0 != aPing->start.tv_sec) - return true; + return true; + return false; } @@ -353,31 +394,45 @@ void clientUpdateHierCounters(HierarchyLogEntry * someEntry) { ping_data *i; + switch (someEntry->code) { #if USE_CACHE_DIGESTS + case CD_PARENT_HIT: + case CD_SIBLING_HIT: - statCounter.cd.times_used++; - break; + statCounter.cd.times_used++; + break; #endif + case SIBLING_HIT: + case PARENT_HIT: + case FIRST_PARENT_MISS: + case CLOSEST_PARENT_MISS: - statCounter.icp.times_used++; - i = &someEntry->ping; - if (clientPingHasFinished(i)) - statHistCount(&statCounter.icp.query_svc_time, - tvSubUsec(i->start, i->stop)); - if (i->timeout) - statCounter.icp.query_timeouts++; - break; + statCounter.icp.times_used++; + i = &someEntry->ping; + + if (clientPingHasFinished(i)) + statHistCount(&statCounter.icp.query_svc_time, + tvSubUsec(i->start, i->stop)); + + if (i->timeout) + statCounter.icp.query_timeouts++; + + break; + case CLOSEST_PARENT: + case CLOSEST_DIRECT: - statCounter.netdb.times_used++; - break; + statCounter.netdb.times_used++; + + break; + default: - break; + break; } } @@ -385,10 +440,13 @@ void ClientHttpRequest::updateCounters() { clientUpdateStatCounters(logType); + if (request->errType != ERR_NONE) - statCounter.client_http.errors++; + statCounter.client_http.errors++; + clientUpdateStatHistCounters(logType, - tvSubMsec(start, current_time)); + tvSubMsec(start, current_time)); + clientUpdateHierCounters(&request->hier); } @@ -396,7 +454,8 @@ MemObject * ClientHttpRequest::memObject() const { if (entry) - return entry->mem_obj; + return entry->mem_obj; + return NULL; } @@ -414,13 +473,15 @@ clientPrepareLogWithRequestDetails(request_t * request, AccessLogEntry * aLogEnt aLogEntry->http.version = request->http_ver; aLogEntry->headers.request = xstrdup(mb.buf); aLogEntry->hier = request->hier; + if (request->auth_user_request) { - aLogEntry->cache.authuser = - xstrdup(authenticateUserRequestUsername(request-> - auth_user_request)); - authenticateAuthUserRequestUnlock(request->auth_user_request); - request->auth_user_request = NULL; + aLogEntry->cache.authuser = + xstrdup(authenticateUserRequestUsername(request-> + auth_user_request)); + authenticateAuthUserRequestUnlock(request->auth_user_request); + request->auth_user_request = NULL; } + packerClean(&p); memBufClean(&mb); } @@ -429,30 +490,41 @@ void ClientHttpRequest::logRequest() { if (out.size || logType) { - al.icp.opcode = ICP_INVALID; - al.url = log_uri; - debug(33, 9) ("clientLogRequest: al.url='%s'\n", al.url); - if (memObject()) { - al.http.code = memObject()->getReply()->sline.status; - al.http.content_type = memObject()->getReply()->content_type.buf(); - } - al.cache.caddr = conn ? conn->log_addr : no_addr; - al.cache.size = out.size; - al.cache.code = logType; - al.cache.msec = tvSubMsec(start, current_time); - if (request) - clientPrepareLogWithRequestDetails(request, &al); - if (conn && conn->rfc931[0]) - al.cache.rfc931 = conn->rfc931; + al.icp.opcode = ICP_INVALID; + al.url = log_uri; + debug(33, 9) ("clientLogRequest: al.url='%s'\n", al.url); + + if (memObject()) { + al.http.code = memObject()->getReply()->sline.status; + al.http.content_type = memObject()->getReply()->content_type.buf(); + } + + al.cache.caddr = conn ? conn->log_addr : no_addr; + al.cache.size = out.size; + al.cache.code = logType; + al.cache.msec = tvSubMsec(start, current_time); + + if (request) + clientPrepareLogWithRequestDetails(request, &al); + + if (conn && conn->rfc931[0]) + al.cache.rfc931 = conn->rfc931; + #if USE_SSL - if (conn) - al.cache.ssluser = sslGetUserEmail(fd_table[conn->fd].ssl); + + if (conn) + al.cache.ssluser = sslGetUserEmail(fd_table[conn->fd].ssl); + #endif - accessLogLog(&al); - accessLogFreeMemory(&al); - updateCounters(); - if (conn) - clientdbUpdate(conn->peer.sin_addr, logType, PROTO_HTTP, out.size); + + accessLogLog(&al); + + accessLogFreeMemory(&al); + + updateCounters(); + + if (conn) + clientdbUpdate(conn->peer.sin_addr, logType, PROTO_HTTP, out.size); } } @@ -465,8 +537,9 @@ ClientHttpRequest::freeResources() range_iter.boundary.clean(); requestUnlink(request); request = NULL; + if (client_stream.tail) - clientStreamAbort((clientStreamNode *)client_stream.tail->data, this); + clientStreamAbort((clientStreamNode *)client_stream.tail->data, this); } void @@ -483,11 +556,14 @@ connAreAllContextsForThisConnection(ConnStateData * connState) ClientSocketContext *context; assert(connState != NULL); context = connGetCurrentContext(connState); + while (context) { - if (context->http->conn != connState) - return 0; - context = context->next; + if (context->http->conn != connState) + return 0; + + context = context->next; } + return -1; } @@ -495,10 +571,11 @@ void connFreeAllContexts(ConnStateData * connState) { ClientSocketContext *context; + while ((context = connGetCurrentContext(connState)) != NULL) { - assert(connGetCurrentContext(connState) != - connGetCurrentContext(connState)->next); - cbdataFree(context); + assert(connGetCurrentContext(connState) != + connGetCurrentContext(connState)->next); + cbdataFree(context); } } @@ -512,12 +589,18 @@ connStateFree(int fd, void *data) clientdbEstablished(connState->peer.sin_addr, -1); /* decrement */ assert(connAreAllContextsForThisConnection(connState)); connFreeAllContexts(connState); + if (connState->auth_user_request) - authenticateAuthUserRequestUnlock(connState->auth_user_request); + authenticateAuthUserRequestUnlock(connState->auth_user_request); + connState->auth_user_request = NULL; + authenticateOnCloseConnection(connState); + memFreeBuf(connState->in.allocatedSize, connState->in.buf); + pconnHistCount(0, connState->nrequests); + cbdataFree(connState); } @@ -534,17 +617,19 @@ clientSetKeepaliveFlag(clientHttpRequest * http) const HttpHeader *req_hdr = &request->header; debug(33, 3) ("clientSetKeepaliveFlag: http_ver = %d.%d\n", - request->http_ver.major, request->http_ver.minor); + request->http_ver.major, request->http_ver.minor); debug(33, 3) ("clientSetKeepaliveFlag: method = %s\n", - RequestMethodStr[request->method]); + RequestMethodStr[request->method]); + if (!Config.onoff.client_pconns) - request->flags.proxy_keepalive = 0; + request->flags.proxy_keepalive = 0; else { - http_version_t http_ver; - httpBuildVersion(&http_ver, 1, 0); - /* we are HTTP/1.0, no matter what the client requests... */ - if (httpMsgIsPersistent(http_ver, req_hdr)) - request->flags.proxy_keepalive = 1; + http_version_t http_ver; + httpBuildVersion(&http_ver, 1, 0); + /* we are HTTP/1.0, no matter what the client requests... */ + + if (httpMsgIsPersistent(http_ver, req_hdr)) + request->flags.proxy_keepalive = 1; } } @@ -552,18 +637,24 @@ static int clientIsContentLengthValid(request_t * r) { switch (r->method) { + case METHOD_PUT: + case METHOD_POST: - /* PUT/POST requires a request entity */ - return (r->content_length >= 0); + /* PUT/POST requires a request entity */ + return (r->content_length >= 0); + case METHOD_GET: + case METHOD_HEAD: - /* We do not want to see a request entity on GET/HEAD requests */ - return (r->content_length <= 0 || Config.onoff.request_entities); + /* We do not want to see a request entity on GET/HEAD requests */ + return (r->content_length <= 0 || Config.onoff.request_entities); + default: - /* For other types of requests we don't care */ - return 1; + /* For other types of requests we don't care */ + return 1; } + /* NOT REACHED */ } @@ -571,7 +662,8 @@ int clientIsRequestBodyValid(int bodyLength) { if (bodyLength >= 0) - return 1; + return 1; + return 0; } @@ -579,8 +671,9 @@ int clientIsRequestBodyTooLargeForPolicy(size_t bodyLength) { if (Config.maxRequestBodySize && - bodyLength > Config.maxRequestBodySize) - return 1; /* too large */ + bodyLength > Config.maxRequestBodySize) + return 1; /* too large */ + return 0; } @@ -588,7 +681,8 @@ int connIsUsable(ConnStateData * conn) { if (!conn || conn->fd == -1) - return 0; + return 0; + return 1; } @@ -615,7 +709,8 @@ int responseFinishedOrFailed(HttpReply * rep, StoreIOBuffer const & recievedData) { if (rep == NULL && recievedData.data == NULL && recievedData.length == 0) - return 1; + return 1; + return 0; } @@ -629,11 +724,15 @@ size_t ClientSocketContext::lengthToSend(size_t maximum) { if (!http->request->range) - return maximum; + return maximum; + assert (canPackMoreRanges()); + if (http->range_iter.debt() == -1) - return maximum; + return maximum; + assert (http->range_iter.debt() > 0); + return XMIN(http->range_iter.debt(), (ssize_t)maximum); } @@ -641,16 +740,19 @@ void ClientSocketContext::noteSentBodyBytes(size_t bytes) { http->out.offset += bytes; + if (!http->request->range) - return; + return; + if (http->range_iter.debt() != -1) { - http->range_iter.debt(http->range_iter.debt() - bytes); - assert (http->range_iter.debt() >= 0); + http->range_iter.debt(http->range_iter.debt() - bytes); + assert (http->range_iter.debt() >= 0); } + assert (http->range_iter.debt() == -1 || - http->range_iter.debt() >= 0); + http->range_iter.debt() >= 0); } - + bool ClientHttpRequest::multipartRangeRequest() const { @@ -669,11 +771,11 @@ ClientSocketContext::sendBody(HttpReply * rep, StoreIOBuffer bodyData) assert(rep == NULL); if (!multipartRangeRequest()) { - size_t length = lengthToSend(bodyData.length); - noteSentBodyBytes (length); - comm_write(fd(), bodyData.data, length, - clientWriteBodyComplete, this); - return; + size_t length = lengthToSend(bodyData.length); + noteSentBodyBytes (length); + comm_write(fd(), bodyData.data, length, + clientWriteBodyComplete, this); + return; } MemBuf mb; @@ -709,12 +811,18 @@ clientPackRangeHdr(const HttpReply * rep, const HttpHdrRangeSpec * spec, String /* stuff the header with required entries and pack it */ httpHeaderInit(&hdr, hoReply); + if (httpHeaderHas(&rep->header, HDR_CONTENT_TYPE)) - httpHeaderPutStr(&hdr, HDR_CONTENT_TYPE, httpHeaderGetStr(&rep->header, HDR_CONTENT_TYPE)); + httpHeaderPutStr(&hdr, HDR_CONTENT_TYPE, httpHeaderGetStr(&rep->header, HDR_CONTENT_TYPE)); + httpHeaderAddContRange(&hdr, *spec, rep->content_length); + packerToMemInit(&p, mb); + httpHeaderPackInto(&hdr, &p); + packerClean(&p); + httpHeaderClean(&hdr); /* append (we packed a header, not a reply) */ @@ -727,59 +835,75 @@ clientPackRangeHdr(const HttpReply * rep, const HttpHdrRangeSpec * spec, String */ void ClientSocketContext::packRange(const char **buf, - size_t size, - MemBuf * mb) + size_t size, + MemBuf * mb) { HttpHdrRangeIter * i = &http->range_iter; size_t available = size; + while (i->currentSpec() && available) { - const size_t copy_sz = lengthToSend(available); - /* - * intersection of "have" and "need" ranges must not be empty - */ - assert(http->out.offset < i->currentSpec()->offset + i->currentSpec()->length); - assert(http->out.offset + available > (size_t)i->currentSpec()->offset); - - /* - * put boundary and headers at the beginning of a range in a - * multi-range - */ - if (http->multipartRangeRequest() && i->debt() == i->currentSpec()->length) { - assert(http->entry->mem_obj); - clientPackRangeHdr( - http->entry->mem_obj->getReply(), /* original reply */ - i->currentSpec(), /* current range */ - i->boundary, /* boundary, the same for all */ - mb); - } - /* - * append content - */ - debug(33, 3) ("clientPackRange: appending %ld bytes\n", (long int) copy_sz); - noteSentBodyBytes (copy_sz); - memBufAppend(mb, *buf, copy_sz); - /* - * update offsets - */ - available -= copy_sz; - //body_off += copy_sz; - *buf += copy_sz; - /* - * paranoid check - */ - assert(available >= 0 && i->debt() >= 0 || i->debt() == -1); - if (i->debt() == 0) - /* put terminating boundary for multiparts */ - clientPackTermBound(i->boundary, mb); - if (!canPackMoreRanges()) - return; - off_t next = getNextRangeOffset(); - assert (next >= http->out.offset); - size_t skip = next - http->out.offset; - if (available <= skip) - return; - available -= skip; - *buf += skip; + const size_t copy_sz = lengthToSend(available); + /* + * intersection of "have" and "need" ranges must not be empty + */ + assert(http->out.offset < i->currentSpec()->offset + i->currentSpec()->length); + assert(http->out.offset + available > (size_t)i->currentSpec()->offset); + + /* + * put boundary and headers at the beginning of a range in a + * multi-range + */ + + if (http->multipartRangeRequest() && i->debt() == i->currentSpec()->length) { + assert(http->entry->mem_obj); + clientPackRangeHdr( + http->entry->mem_obj->getReply(), /* original reply */ + i->currentSpec(), /* current range */ + i->boundary, /* boundary, the same for all */ + mb); + } + + /* + * append content + */ + debug(33, 3) ("clientPackRange: appending %ld bytes\n", (long int) copy_sz); + + noteSentBodyBytes (copy_sz); + + memBufAppend(mb, *buf, copy_sz); + + /* + * update offsets + */ + available -= copy_sz; + + //body_off += copy_sz; + *buf += copy_sz; + + /* + * paranoid check + */ + assert(available >= 0 && i->debt() >= 0 || i->debt() == -1); + + if (i->debt() == 0) + /* put terminating boundary for multiparts */ + clientPackTermBound(i->boundary, mb); + + if (!canPackMoreRanges()) + return; + + off_t next = getNextRangeOffset(); + + assert (next >= http->out.offset); + + size_t skip = next - http->out.offset; + + if (available <= skip) + return; + + available -= skip; + + *buf += skip; } } @@ -798,26 +922,31 @@ ClientHttpRequest::mRangeCLen() memBufDefInit(&mb); HttpHdrRange::iterator pos = request->range->begin(); + while (pos != request->range->end()) { - /* account for headers for this range */ - memBufReset(&mb); - clientPackRangeHdr(entry->mem_obj->getReply(), - *pos, range_iter.boundary, &mb); - clen += mb.size; + /* account for headers for this range */ + memBufReset(&mb); + clientPackRangeHdr(entry->mem_obj->getReply(), + *pos, range_iter.boundary, &mb); + clen += mb.size; - /* account for range content */ - clen += (*pos)->length; + /* account for range content */ + clen += (*pos)->length; - debug(33, 6) ("clientMRangeCLen: (clen += %ld + %ld) == %d\n", - (long int) mb.size, (long int) (*pos)->length, clen); - ++pos; + debug(33, 6) ("clientMRangeCLen: (clen += %ld + %ld) == %d\n", + (long int) mb.size, (long int) (*pos)->length, clen); + ++pos; } + /* account for the terminating boundary */ memBufReset(&mb); + clientPackTermBound(range_iter.boundary, &mb); + clen += mb.size; memBufClean(&mb); + return clen; } @@ -829,26 +958,33 @@ clientIfRangeMatch(clientHttpRequest * http, HttpReply * rep) { const TimeOrTag spec = httpHeaderGetTimeOrTag(&http->request->header, HDR_IF_RANGE); /* check for parsing falure */ + if (!spec.valid) - return 0; + return 0; + /* got an ETag? */ if (spec.tag.str) { - ETag rep_tag = httpHeaderGetETag(&rep->header, HDR_ETAG); - debug(33, 3) ("clientIfRangeMatch: ETags: %s and %s\n", - spec.tag.str, rep_tag.str ? rep_tag.str : ""); - if (!rep_tag.str) - return 0; /* entity has no etag to compare with! */ - if (spec.tag.weak || rep_tag.weak) { - debug(33, 1) ("clientIfRangeMatch: Weak ETags are not allowed in If-Range: %s ? %s\n", - spec.tag.str, rep_tag.str); - return 0; /* must use strong validator for sub-range requests */ - } - return etagIsEqual(&rep_tag, &spec.tag); + ETag rep_tag = httpHeaderGetETag(&rep->header, HDR_ETAG); + debug(33, 3) ("clientIfRangeMatch: ETags: %s and %s\n", + spec.tag.str, rep_tag.str ? rep_tag.str : ""); + + if (!rep_tag.str) + return 0; /* entity has no etag to compare with! */ + + if (spec.tag.weak || rep_tag.weak) { + debug(33, 1) ("clientIfRangeMatch: Weak ETags are not allowed in If-Range: %s ? %s\n", + spec.tag.str, rep_tag.str); + return 0; /* must use strong validator for sub-range requests */ + } + + return etagIsEqual(&rep_tag, &spec.tag); } + /* got modification time? */ if (spec.time >= 0) { - return http->entry->lastmod <= spec.time; + return http->entry->lastmod <= spec.time; } + assert(0); /* should not happen */ return 0; } @@ -876,80 +1012,95 @@ ClientSocketContext::buildRangeHeader(HttpReply * rep) request_t *request = http->request; assert(request->range); /* check if we still want to do ranges */ + if (!rep) - range_err = "no [parse-able] reply"; + range_err = "no [parse-able] reply"; else if ((rep->sline.status != HTTP_OK) && (rep->sline.status != HTTP_PARTIAL_CONTENT)) - range_err = "wrong status code"; + range_err = "wrong status code"; + #if 0 + else if (httpHeaderHas(hdr, HDR_CONTENT_RANGE)) - range_err = "origin server does ranges"; + range_err = "origin server does ranges"; + #endif + else if (rep->content_length < 0) - range_err = "unknown length"; + range_err = "unknown length"; else if (rep->content_length != http->entry->mem_obj->getReply()->content_length) - range_err = "INCONSISTENT length"; /* a bug? */ + range_err = "INCONSISTENT length"; /* a bug? */ else if (httpHeaderHas(&http->request->header, HDR_IF_RANGE) && !clientIfRangeMatch(http, rep)) - range_err = "If-Range match failed"; + range_err = "If-Range match failed"; else if (!http->request->range->canonize(rep)) - range_err = "canonization failed"; + range_err = "canonization failed"; else if (http->request->range->isComplex()) - range_err = "too complex range header"; + range_err = "too complex range header"; else if (!request->flags.cachable) /* from we_do_ranges in http.c */ - range_err = "non-cachable request"; + range_err = "non-cachable request"; + #if 0 + else if (!logTypeIsATcpHit(http->logType); && http->request->range->offsetLimitExceeded()) - range_err = "range outside range_offset_limit"; + range_err = "range outside range_offset_limit"; + #endif /* get rid of our range specs on error */ if (range_err) { - /* XXX Why do we do this here, and not when parsing the request ? */ - debug(33, 3) ("clientBuildRangeHeader: will not do ranges: %s.\n", range_err); - http->request->range->deleteSelf(); - http->request->range = NULL; + /* XXX Why do we do this here, and not when parsing the request ? */ + debug(33, 3) ("clientBuildRangeHeader: will not do ranges: %s.\n", range_err); + http->request->range->deleteSelf(); + http->request->range = NULL; } else { - const int spec_count = http->request->range->specs.count; - int actual_clen = -1; - - debug(33, 3) ("clientBuildRangeHeader: range spec count: %d virgin clen: %d\n", - spec_count, rep->content_length); - assert(spec_count > 0); - /* ETags should not be returned with Partial Content replies? */ - httpHeaderDelById(hdr, HDR_ETAG); - /* append appropriate header(s) */ - if (spec_count == 1) { - HttpHdrRange::iterator pos = http->request->range->begin(); - assert(*pos); - /* append Content-Range */ - if (!httpHeaderHas(hdr, HDR_CONTENT_RANGE)) { - /* No content range, so this was a full object we are - * sending parts of. - */ - httpHeaderAddContRange(hdr, **pos, rep->content_length); - } - /* set new Content-Length to the actual number of bytes - * transmitted in the message-body */ - actual_clen = (*pos)->length; - } else { - /* multipart! */ - /* generate boundary string */ - http->range_iter.boundary = http->rangeBoundaryStr(); - /* delete old Content-Type, add ours */ - httpHeaderDelById(hdr, HDR_CONTENT_TYPE); - httpHeaderPutStrf(hdr, HDR_CONTENT_TYPE, - "multipart/byteranges; boundary=\"%s\"", - http->range_iter.boundary.buf()); - /* Content-Length is not required in multipart responses - * but it is always nice to have one */ - actual_clen = http->mRangeCLen(); - } - - /* replace Content-Length header */ - assert(actual_clen >= 0); - httpHeaderDelById(hdr, HDR_CONTENT_LENGTH); - httpHeaderPutInt(hdr, HDR_CONTENT_LENGTH, actual_clen); - debug(33, 3) ("clientBuildRangeHeader: actual content length: %d\n", actual_clen); - /* And start the range iter off */ - http->range_iter.updateSpec(); + const int spec_count = http->request->range->specs.count; + int actual_clen = -1; + + debug(33, 3) ("clientBuildRangeHeader: range spec count: %d virgin clen: %d\n", + spec_count, rep->content_length); + assert(spec_count > 0); + /* ETags should not be returned with Partial Content replies? */ + httpHeaderDelById(hdr, HDR_ETAG); + /* append appropriate header(s) */ + + if (spec_count == 1) { + HttpHdrRange::iterator pos = http->request->range->begin(); + assert(*pos); + /* append Content-Range */ + + if (!httpHeaderHas(hdr, HDR_CONTENT_RANGE)) { + /* No content range, so this was a full object we are + * sending parts of. + */ + httpHeaderAddContRange(hdr, **pos, rep->content_length); + } + + /* set new Content-Length to the actual number of bytes + * transmitted in the message-body */ + actual_clen = (*pos)->length; + } else { + /* multipart! */ + /* generate boundary string */ + http->range_iter.boundary = http->rangeBoundaryStr(); + /* delete old Content-Type, add ours */ + httpHeaderDelById(hdr, HDR_CONTENT_TYPE); + httpHeaderPutStrf(hdr, HDR_CONTENT_TYPE, + "multipart/byteranges; boundary=\"%s\"", + http->range_iter.boundary.buf()); + /* Content-Length is not required in multipart responses + * but it is always nice to have one */ + actual_clen = http->mRangeCLen(); + } + + /* replace Content-Length header */ + assert(actual_clen >= 0); + + httpHeaderDelById(hdr, HDR_CONTENT_LENGTH); + + httpHeaderPutInt(hdr, HDR_CONTENT_LENGTH, actual_clen); + + debug(33, 3) ("clientBuildRangeHeader: actual content length: %d\n", actual_clen); + + /* And start the range iter off */ + http->range_iter.updateSpec(); } } @@ -957,7 +1108,7 @@ void ClientSocketContext::prepareReply(HttpReply * rep) { if (http->request->range) - buildRangeHeader(rep); + buildRangeHeader(rep); } void @@ -970,25 +1121,30 @@ ClientSocketContext::sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData) /* Save length of headers for persistent conn checks */ http->out.headers_sz = mb.size; #if HEADERS_LOG + headersLog(0, 0, http->request->method, rep); #endif + httpReplyDestroy(rep); rep = NULL; + if (bodyData.data && bodyData.length) { - if (!multipartRangeRequest()) { - size_t length = lengthToSend(bodyData.length); - noteSentBodyBytes (length); - - memBufAppend(&mb, bodyData.data, length); - } else { - char const *t = bodyData.data; - packRange(&t, - bodyData.length, - &mb); - } + if (!multipartRangeRequest()) { + size_t length = lengthToSend(bodyData.length); + noteSentBodyBytes (length); + + memBufAppend(&mb, bodyData.data, length); + } else { + char const *t = bodyData.data; + packRange(&t, + bodyData.length, + &mb); + } } + /* write */ comm_old_write_mbuf(fd(), mb, clientWriteComplete, this); + /* if we don't do it, who will? */ } @@ -1002,13 +1158,13 @@ ClientSocketContext::sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData) */ static void clientSocketRecipient(clientStreamNode * node, clientHttpRequest * http, - HttpReply * rep, StoreIOBuffer recievedData) + HttpReply * rep, StoreIOBuffer recievedData) { int fd; ClientSocketContext *context; /* Test preconditions */ assert(node != NULL); - /* TODO: handle this rather than asserting + /* TODO: handle this rather than asserting * - it should only ever happen if we cause an abort and * the callback chain loops back to here, so we can simply return. * However, that itself shouldn't happen, so it stays as an assert for now. @@ -1020,21 +1176,24 @@ clientSocketRecipient(clientStreamNode * node, clientHttpRequest * http, assert(connIsUsable(http->conn)); fd = http->conn->fd; /* TODO: check offset is what we asked for */ + if (connGetCurrentContext(http->conn) != context) { - context->deferRecipientForLater(node, rep, recievedData); - return; + context->deferRecipientForLater(node, rep, recievedData); + return; } + if (responseFinishedOrFailed(rep, recievedData)) { - clientWriteComplete(fd, NULL, 0, COMM_OK, context); - return; + clientWriteComplete(fd, NULL, 0, COMM_OK, context); + return; } + if (!contextStartOfOutput(context)) - context->sendBody(rep, recievedData); + context->sendBody(rep, recievedData); else - context->sendStartOfMessage(rep, recievedData); + context->sendStartOfMessage(rep, recievedData); } -/* Called when a downstream node is no longer interested in +/* Called when a downstream node is no longer interested in * our data. As we are a terminal node, this means on aborts * only */ @@ -1044,7 +1203,7 @@ clientSocketDetach(clientStreamNode * node, clientHttpRequest * http) ClientSocketContext *context; /* Test preconditions */ assert(node != NULL); - /* TODO: handle this rather than asserting + /* TODO: handle this rather than asserting * - it should only ever happen if we cause an abort and * the callback chain loops back to here, so we can simply return. * However, that itself shouldn't happen, so it stays as an assert for now. @@ -1070,13 +1229,13 @@ void connReadNextRequest(ConnStateData * conn) { debug(33, 5) ("clientReadNextRequest: FD %d reading next req\n", - conn->fd); + conn->fd); fd_note(conn->fd, "Waiting for next request"); /* * Set the timeout BEFORE calling clientReadRequest(). */ commSetTimeout(conn->fd, Config.Timeout.persistent_request, - requestTimeout, conn); + requestTimeout, conn); conn->defer.until = 0; /* Kick it to read a new request */ clientReadSomeData(conn); /* Please don't do anything with the FD past here! */ @@ -1086,16 +1245,18 @@ void ClientSocketContextPushDeferredIfNeeded(ClientSocketContext * deferredRequest, ConnStateData * conn) { debug(33, 2) ("ClientSocketContextPushDeferredIfNeeded: FD %d Sending next\n", - conn->fd); + conn->fd); /* If the client stream is waiting on a socket write to occur, then */ + if (deferredRequest->flags.deferred) { - /* NO data is allowed to have been sent */ - assert(deferredRequest->http->out.size == 0); - clientSocketRecipient(deferredRequest->deferredparams.node, - deferredRequest->http, - deferredRequest->deferredparams.rep, - deferredRequest->deferredparams.queuedBuffer); + /* NO data is allowed to have been sent */ + assert(deferredRequest->http->out.size == 0); + clientSocketRecipient(deferredRequest->deferredparams.node, + deferredRequest->http, + deferredRequest->deferredparams.rep, + deferredRequest->deferredparams.queuedBuffer); } + /* otherwise, the request is still active in a callbacksomewhere, * and we are done */ @@ -1110,20 +1271,23 @@ clientKeepaliveNextRequest(ClientSocketContext * context) debug(33, 3) ("clientKeepaliveNextRequest: FD %d\n", conn->fd); cbdataFree(context); + if ((deferredRequest = connGetCurrentContext(conn)) == NULL) - connReadNextRequest(conn); + connReadNextRequest(conn); else - ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn); + ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn); } void clientUpdateSocketStats(log_type logType, size_t size) { if (size == 0) - return; + return; + kb_incr(&statCounter.client_http.kbytes_out, size); + if (logTypeIsATcpHit(logType)) - kb_incr(&statCounter.client_http.hit_kbytes_out, size); + kb_incr(&statCounter.client_http.hit_kbytes_out, size); } /* returns true if there is still data available to pack more ranges @@ -1133,12 +1297,16 @@ bool ClientSocketContext::canPackMoreRanges() const { /* first update "i" if needed */ + if (!http->range_iter.debt()) { - debug (33,5)("ClientSocketContext::canPackMoreRanges: At end of current range spec for fd %d\n",fd()); - if (http->range_iter.pos.incrementable()) - ++http->range_iter.pos; - http->range_iter.updateSpec(); + debug (33,5)("ClientSocketContext::canPackMoreRanges: At end of current range spec for fd %d\n",fd()); + + if (http->range_iter.pos.incrementable()) + ++http->range_iter.pos; + + http->range_iter.updateSpec(); } + assert(!http->range_iter.debt() == !http->range_iter.currentSpec()); /* paranoid sync condition */ /* continue condition: need_more_data */ @@ -1150,29 +1318,34 @@ off_t ClientSocketContext::getNextRangeOffset() const { if (http->request->range) { - /* offset in range specs does not count the prefix of an http msg */ - debug (0,0) ("ClientSocketContext::getNextRangeOffset: http offset %lu\n", (long unsigned)http->out.offset); - /* check: reply was parsed and range iterator was initialized */ - assert(http->range_iter.valid); - /* filter out data according to range specs */ - assert (canPackMoreRanges()); - { - off_t start; /* offset of still missing data */ - assert(http->range_iter.currentSpec()); - start = http->range_iter.currentSpec()->offset + http->range_iter.currentSpec()->length - http->range_iter.debt(); - debug(33, 3) ("clientPackMoreRanges: in: offset: %ld\n", - (long int) http->out.offset); - debug(33, 3) ("clientPackMoreRanges: out: start: %ld spec[%ld]: [%ld, %ld), len: %ld debt: %ld\n", - (long int) start, (long int) (http->range_iter.pos - http->request->range->begin()), (long int) http->range_iter.currentSpec()->offset, (long int) (http->range_iter.currentSpec()->offset + http->range_iter.currentSpec()->length), (long int) http->range_iter.currentSpec()->length, (long int) http->range_iter.debt()); - if (http->range_iter.currentSpec()->length != -1) - assert(http->out.offset <= start); /* we did not miss it */ - return start; - } + /* offset in range specs does not count the prefix of an http msg */ + debug (0,0) ("ClientSocketContext::getNextRangeOffset: http offset %lu\n", (long unsigned)http->out.offset); + /* check: reply was parsed and range iterator was initialized */ + assert(http->range_iter.valid); + /* filter out data according to range specs */ + assert (canPackMoreRanges()); + { + off_t start; /* offset of still missing data */ + assert(http->range_iter.currentSpec()); + start = http->range_iter.currentSpec()->offset + http->range_iter.currentSpec()->length - http->range_iter.debt(); + debug(33, 3) ("clientPackMoreRanges: in: offset: %ld\n", + (long int) http->out.offset); + debug(33, 3) ("clientPackMoreRanges: out: start: %ld spec[%ld]: [%ld, %ld), len: %ld debt: %ld\n", + (long int) start, (long int) (http->range_iter.pos - http->request->range->begin()), (long int) http->range_iter.currentSpec()->offset, (long int) (http->range_iter.currentSpec()->offset + http->range_iter.currentSpec()->length), (long int) http->range_iter.currentSpec()->length, (long int) http->range_iter.debt()); + + if (http->range_iter.currentSpec()->length != -1) + assert(http->out.offset <= start); /* we did not miss it */ + + return start; + } + #if 0 + } else if (http->request->range->specs.count > 1) { - /* put terminating boundary for multiparts */ - clientPackTermBound(i->boundary, mb); + /* put terminating boundary for multiparts */ + clientPackTermBound(i->boundary, mb); #endif + } return http->out.offset; @@ -1193,32 +1366,41 @@ ClientSocketContext::pullData() clientStreamRead(getTail(), http, readBuffer); } -clientStream_status_t +clientStream_status_t ClientSocketContext::socketState() { switch (clientStreamStatus(getTail(), http)) { - case STREAM_NONE: + + case STREAM_NONE: /* check for range support ending */ + if (http->request->range) { - /* check: reply was parsed and range iterator was initialized */ - assert(http->range_iter.valid); - /* filter out data according to range specs */ - if (!canPackMoreRanges()) { - debug (33,5)("ClientSocketContext::socketState: Range request has hit end of returnable range sequence on fd %d\n", fd()); - if (http->request->flags.proxy_keepalive) - return STREAM_COMPLETE; - else - return STREAM_UNPLANNED_COMPLETE; - } - } - return STREAM_NONE; - case STREAM_COMPLETE: + /* check: reply was parsed and range iterator was initialized */ + assert(http->range_iter.valid); + /* filter out data according to range specs */ + + if (!canPackMoreRanges()) { + debug (33,5)("ClientSocketContext::socketState: Range request has hit end of returnable range sequence on fd %d\n", fd()); + + if (http->request->flags.proxy_keepalive) + return STREAM_COMPLETE; + else + return STREAM_UNPLANNED_COMPLETE; + } + } + + return STREAM_NONE; + + case STREAM_COMPLETE: return STREAM_COMPLETE; - case STREAM_UNPLANNED_COMPLETE: - return STREAM_UNPLANNED_COMPLETE; - case STREAM_FAILED: - return STREAM_FAILED; + + case STREAM_UNPLANNED_COMPLETE: + return STREAM_UNPLANNED_COMPLETE; + + case STREAM_FAILED: + return STREAM_FAILED; } + fatal ("unreachable code\n"); return STREAM_NONE; } @@ -1235,29 +1417,36 @@ clientWriteComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag, v http->out.size += size; assert(fd > -1); debug(33, 5) ("clientWriteComplete: FD %d, sz %ld, err %d, off %ld, len %d\n", - fd, (long int) size, errflag, (long int) http->out.size, entry ? objectLen(entry) : 0); + fd, (long int) size, errflag, (long int) http->out.size, entry ? objectLen(entry) : 0); clientUpdateSocketStats(http->logType, size); + if (errflag || clientHttpRequestStatus(fd, http)) { - debug (33,5)("clientWriteComplete: FD %d, closing connection due to failure, or true requeststatus\n", fd); - comm_close(fd); - /* Do we leak here ? */ - return; + debug (33,5)("clientWriteComplete: FD %d, closing connection due to failure, or true requeststatus\n", fd); + comm_close(fd); + /* Do we leak here ? */ + return; } + switch (context->socketState()) { + case STREAM_NONE: - context->pullData(); - break; + context->pullData(); + break; + case STREAM_COMPLETE: - debug(33, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd); - clientKeepaliveNextRequest(context); - return; + debug(33, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd); + clientKeepaliveNextRequest(context); + return; + case STREAM_UNPLANNED_COMPLETE: - /* fallthrough */ + /* fallthrough */ + case STREAM_FAILED: - comm_close(fd); - return; + comm_close(fd); + return; + default: - fatal("Hit unreachable code in clientWriteComplete\n"); + fatal("Hit unreachable code in clientWriteComplete\n"); } } @@ -1280,8 +1469,8 @@ parseHttpRequestAbort(ConnStateData * conn, const char *uri) tempBuffer.data = context->reqbuf; tempBuffer.length = HTTP_REQBUF_SZ; clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach, - clientReplyStatus, clientReplyNewContext(http), clientSocketRecipient, - clientSocketDetach, context, tempBuffer); + clientReplyStatus, clientReplyNewContext(http), clientSocketRecipient, + clientSocketDetach, context, tempBuffer); dlinkAdd(http, &http->active, &ClientActiveRequests); return context; } @@ -1290,15 +1479,19 @@ ClientSocketContext * clientParseRequestMethod(char *inbuf, method_t * method_p, ConnStateData * conn) { char *mstr = NULL; + if ((mstr = strtok(inbuf, "\t ")) == NULL) { - debug(33, 1) ("clientParseRequestMethod: Can't get request method\n"); - return parseHttpRequestAbort(conn, "error:invalid-request"); + debug(33, 1) ("clientParseRequestMethod: Can't get request method\n"); + return parseHttpRequestAbort(conn, "error:invalid-request"); } + *method_p = urlParseMethod(mstr); + if (*method_p == METHOD_NONE) { - debug(33, 1) ("clientParseRequestMethod: Unsupported method '%s'\n", mstr); - return parseHttpRequestAbort(conn, "error:unsupported-request-method"); + debug(33, 1) ("clientParseRequestMethod: Unsupported method '%s'\n", mstr); + return parseHttpRequestAbort(conn, "error:unsupported-request-method"); } + debug(33, 5) ("clientParseRequestMethod: Method is '%s'\n", mstr); return NULL; } @@ -1307,8 +1500,10 @@ char * skipLeadingSpace(char *aString) { char *result = aString; + while (xisspace(*aString)) - ++aString; + ++aString; + return result; } @@ -1316,17 +1511,19 @@ static char * findTrailingHTTPVersion(char *uriAndHTTPVersion) { char *token; - + for (token = strchr(uriAndHTTPVersion, '\n'); token > uriAndHTTPVersion; token--) { - if (*token == '\n' || *token == '\r') - continue; - if (xisspace(*token)) { - if (strncasecmp(token + 1, "HTTP/", 5) == 0) - return token + 1; - else - break; - } + if (*token == '\n' || *token == '\r') + continue; + + if (xisspace(*token)) { + if (strncasecmp(token + 1, "HTTP/", 5) == 0) + return token + 1; + else + break; + } } + return NULL; } @@ -1335,62 +1532,73 @@ void trimTrailingSpaces(char *aString, size_t len) { char *endPointer = aString + len; + while (endPointer > aString && xisspace(*endPointer)) - *(endPointer--) = '\0'; + *(endPointer--) = '\0'; } + #endif static ClientSocketContext * parseURIandHTTPVersion(char **url_p, http_version_t * http_ver_p, - ConnStateData * conn, char *http_version_str) + ConnStateData * conn, char *http_version_str) { char *url; char *t; /* look for URL (strtok initiated by clientParseRequestMethod) */ + if ((url = strtok(NULL, "\n")) == NULL) { - debug(33, 1) ("parseHttpRequest: Missing URL\n"); - return parseHttpRequestAbort(conn, "error:missing-url"); + debug(33, 1) ("parseHttpRequest: Missing URL\n"); + return parseHttpRequestAbort(conn, "error:missing-url"); } + url = skipLeadingSpace(url); if (!*url || (http_version_str && http_version_str <= url+1)) { - debug(33, 1) ("parseHttpRequest: Missing URL\n"); - return parseHttpRequestAbort(conn, "error:missing-url"); + debug(33, 1) ("parseHttpRequest: Missing URL\n"); + return parseHttpRequestAbort(conn, "error:missing-url"); } + /* Terminate URL just before HTTP version (or at end of line) */ if (http_version_str) - http_version_str[-1] = '\0'; + http_version_str[-1] = '\0'; else { - t = url + strlen(url) - 1; - while (t > url && *t == '\r') - *t-- = '\0'; + t = url + strlen(url) - 1; + + while (t > url && *t == '\r') + *t-- = '\0'; } + debug(33, 5) ("parseHttpRequest: URI is '%s'\n", url); *url_p = url; + if (http_version_str) { - if (sscanf(http_version_str + 5, "%d.%d", &http_ver_p->major, - &http_ver_p->minor) != 2) { - debug(33, 3) ("parseHttpRequest: Invalid HTTP identifier.\n"); - return parseHttpRequestAbort(conn, "error:invalid-http-ident"); - } - debug(33, 6) ("parseHttpRequest: Client HTTP version %d.%d.\n", - http_ver_p->major, http_ver_p->minor); + if (sscanf(http_version_str + 5, "%d.%d", &http_ver_p->major, + &http_ver_p->minor) != 2) { + debug(33, 3) ("parseHttpRequest: Invalid HTTP identifier.\n"); + return parseHttpRequestAbort(conn, "error:invalid-http-ident"); + } + + debug(33, 6) ("parseHttpRequest: Client HTTP version %d.%d.\n", + http_ver_p->major, http_ver_p->minor); } else { - httpBuildVersion(http_ver_p, 0, 9); /* wild guess */ + httpBuildVersion(http_ver_p, 0, 9); /* wild guess */ } + return NULL; } /* Utility function to perform part of request parsing */ static ClientSocketContext * clientParseHttpRequestLine(char *reqline, ConnStateData * conn, - method_t * method_p, char **url_p, http_version_t * http_ver_p, char * http_version_str) + method_t * method_p, char **url_p, http_version_t * http_ver_p, char * http_version_str) { ClientSocketContext *result = NULL; /* XXX: This sequence relies on strtok() */ + if ((result = clientParseRequestMethod(reqline, method_p, conn)) - || (result = parseURIandHTTPVersion(url_p, http_ver_p, conn, http_version_str))) - return result; + || (result = parseURIandHTTPVersion(url_p, http_ver_p, conn, http_version_str))) + return result; return NULL; } @@ -1399,14 +1607,16 @@ void setLogUri(clientHttpRequest * http, char const *uri) { safe_free(http->log_uri); + if (!stringHasCntl(uri)) - http->log_uri = xstrndup(uri, MAX_URL); + http->log_uri = xstrndup(uri, MAX_URL); else - http->log_uri = xstrndup(rfc1738_escape_unescaped(uri), MAX_URL); + http->log_uri = xstrndup(rfc1738_escape_unescaped(uri), MAX_URL); } static void -prepareAcceleratedURL(ConnStateData * conn, clientHttpRequest *http, char *url, const char *req_hdr) { +prepareAcceleratedURL(ConnStateData * conn, clientHttpRequest *http, char *url, const char *req_hdr) +{ int vhost = conn->port->vhost; int vport = conn->port->vport; char *host; @@ -1416,90 +1626,97 @@ prepareAcceleratedURL(ConnStateData * conn, clientHttpRequest *http, char *url, /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */ if (*url != '/') { - if (conn->port->vhost) - return; /* already in good shape */ - /* else we need to ignore the host name */ - url = strstr(url, "//"); + if (conn->port->vhost) + return; /* already in good shape */ + + /* else we need to ignore the host name */ + url = strstr(url, "//"); + #if SHOULD_REJECT_UNKNOWN_URLS - if (!url) - return parseHttpRequestAbort(conn, "error:invalid-request"); + + if (!url) + return parseHttpRequestAbort(conn, "error:invalid-request"); + #endif - if (url) - url = strchr(url + 2, '/'); - if (!url) - url = (char *) "/"; + + if (url) + url = strchr(url + 2, '/'); + + if (!url) + url = (char *) "/"; } if (internalCheck(url)) { - /* prepend our name & port */ - http->uri = xstrdup(internalLocalUri(NULL, url)); - http->flags.internal = 1; + /* prepend our name & port */ + http->uri = xstrdup(internalLocalUri(NULL, url)); + http->flags.internal = 1; } else if (vhost && (host = mime_get_header(req_hdr, "Host")) != NULL) { - int url_sz = strlen(url) + 32 + Config.appendDomainLen + - strlen(host); - http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s%s", - conn->port->protocol, host, url); - debug(33, 5) ("ACCEL VHOST REWRITE: '%s'\n", http->uri); + int url_sz = strlen(url) + 32 + Config.appendDomainLen + + strlen(host); + http->uri = (char *)xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "%s://%s%s", + conn->port->protocol, host, url); + debug(33, 5) ("ACCEL VHOST REWRITE: '%s'\n", http->uri); } else if (conn->port->defaultsite) { - int url_sz = strlen(url) + 32 + Config.appendDomainLen + - strlen(conn->port->defaultsite); - http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s%s", - conn->port->protocol, conn->port->defaultsite, url); - debug(33, 5) ("ACCEL DEFAULTSITE REWRITE: '%s'\n", http->uri); + int url_sz = strlen(url) + 32 + Config.appendDomainLen + + strlen(conn->port->defaultsite); + http->uri = (char *)xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "%s://%s%s", + conn->port->protocol, conn->port->defaultsite, url); + debug(33, 5) ("ACCEL DEFAULTSITE REWRITE: '%s'\n", http->uri); } else if (vport == -1) { - /* Put the local socket IP address as the hostname. */ - int url_sz = strlen(url) + 32 + Config.appendDomainLen; - http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s:%d%s", - http->conn->port->protocol, - inet_ntoa(http->conn->me.sin_addr), - ntohs(http->conn->me.sin_port), url); - debug(33, 5) ("ACCEL VPORT REWRITE: '%s'\n", http->uri); + /* Put the local socket IP address as the hostname. */ + int url_sz = strlen(url) + 32 + Config.appendDomainLen; + http->uri = (char *)xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "%s://%s:%d%s", + http->conn->port->protocol, + inet_ntoa(http->conn->me.sin_addr), + ntohs(http->conn->me.sin_port), url); + debug(33, 5) ("ACCEL VPORT REWRITE: '%s'\n", http->uri); } else if (vport > 0) { - /* Put the local socket IP address as the hostname, but static port */ - int url_sz = strlen(url) + 32 + Config.appendDomainLen; - http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s:%d%s", - http->conn->port->protocol, - inet_ntoa(http->conn->me.sin_addr), - vport, url); - debug(33, 5) ("ACCEL VPORT REWRITE: '%s'\n", http->uri); + /* Put the local socket IP address as the hostname, but static port */ + int url_sz = strlen(url) + 32 + Config.appendDomainLen; + http->uri = (char *)xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "%s://%s:%d%s", + http->conn->port->protocol, + inet_ntoa(http->conn->me.sin_addr), + vport, url); + debug(33, 5) ("ACCEL VPORT REWRITE: '%s'\n", http->uri); } } static void -prepareTransparentURL(ConnStateData * conn, clientHttpRequest *http, char *url, const char *req_hdr) { +prepareTransparentURL(ConnStateData * conn, clientHttpRequest *http, char *url, const char *req_hdr) +{ char *host; http->flags.accel = 1; if (*url != '/') - return; /* already in good shape */ + return; /* already in good shape */ /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */ if (internalCheck(url)) { - /* prepend our name & port */ - http->uri = xstrdup(internalLocalUri(NULL, url)); - http->flags.internal = 1; + /* prepend our name & port */ + http->uri = xstrdup(internalLocalUri(NULL, url)); + http->flags.internal = 1; } else if ((host = mime_get_header(req_hdr, "Host")) != NULL) { - int url_sz = strlen(url) + 32 + Config.appendDomainLen + - strlen(host); - http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s%s", - conn->port->protocol, host, url); - debug(33, 5) ("TRANSPARENT HOST REWRITE: '%s'\n", http->uri); + int url_sz = strlen(url) + 32 + Config.appendDomainLen + + strlen(host); + http->uri = (char *)xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "%s://%s%s", + conn->port->protocol, host, url); + debug(33, 5) ("TRANSPARENT HOST REWRITE: '%s'\n", http->uri); } else { - /* Put the local socket IP address as the hostname. */ - int url_sz = strlen(url) + 32 + Config.appendDomainLen; - http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s:%d%s", - http->conn->port->protocol, - inet_ntoa(http->conn->me.sin_addr), - ntohs(http->conn->me.sin_port), url); - debug(33, 5) ("TRANSPARENT REWRITE: '%s'\n", http->uri); + /* Put the local socket IP address as the hostname. */ + int url_sz = strlen(url) + 32 + Config.appendDomainLen; + http->uri = (char *)xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "%s://%s:%d%s", + http->conn->port->protocol, + inet_ntoa(http->conn->me.sin_addr), + ntohs(http->conn->me.sin_port), url); + debug(33, 5) ("TRANSPARENT REWRITE: '%s'\n", http->uri); } } @@ -1514,7 +1731,7 @@ prepareTransparentURL(ConnStateData * conn, clientHttpRequest *http, char *url, */ static ClientSocketContext * parseHttpRequest(ConnStateData * conn, method_t * method_p, - char **prefix_p, size_t * req_line_sz_p) + char **prefix_p, size_t * req_line_sz_p) { char *inbuf = NULL; char *url = NULL; @@ -1535,20 +1752,23 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, *method_p = METHOD_NONE; /* Read the HTTP message. HTTP/0.9 is detected by the absence of a HTTP signature */ + if ((t = (char *)memchr(conn->in.buf, '\n', conn->in.notYetUsed)) == NULL) { - debug(33, 5) ("Incomplete request, waiting for end of request line\n"); - return NULL; + debug(33, 5) ("Incomplete request, waiting for end of request line\n"); + return NULL; } + *req_line_sz_p = t - conn->in.buf + 1; http_version = findTrailingHTTPVersion(conn->in.buf); + if (http_version) { - if ((req_sz = headersEnd(conn->in.buf, conn->in.notYetUsed)) == 0) { - debug(33, 5) ("Incomplete request, waiting for end of headers\n"); - return NULL; - } + if ((req_sz = headersEnd(conn->in.buf, conn->in.notYetUsed)) == 0) { + debug(33, 5) ("Incomplete request, waiting for end of headers\n"); + return NULL; + } } else { - debug(33, 3) ("parseHttpRequest: Missing HTTP identifier\n"); - req_sz = t - conn->in.buf + 1; /* HTTP/0.9 requests */ + debug(33, 3) ("parseHttpRequest: Missing HTTP identifier\n"); + req_sz = t - conn->in.buf + 1; /* HTTP/0.9 requests */ } assert(req_sz <= conn->in.notYetUsed); @@ -1557,78 +1777,101 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, xmemcpy(inbuf, conn->in.buf, req_sz); *(inbuf + req_sz) = '\0'; /* and adjust http_version to point into the new copy */ + if (http_version) - http_version = inbuf + (http_version - conn->in.buf); + http_version = inbuf + (http_version - conn->in.buf); /* Barf on NULL characters in the headers */ if (strlen(inbuf) != req_sz) { - debug(33, 1) ("parseHttpRequest: Requestheader contains NULL characters\n"); + debug(33, 1) ("parseHttpRequest: Requestheader contains NULL characters\n"); #if TRY_TO_IGNORE_THIS - return parseHttpRequestAbort(conn, "error:invalid-request"); + + return parseHttpRequestAbort(conn, "error:invalid-request"); #endif + } /* Is there a legitimate first line to the headers ? */ if ((result = clientParseHttpRequestLine(inbuf, conn, method_p, &url, - &http_ver, http_version))) { - /* something wrong, abort */ - xfree(inbuf); - return result; + &http_ver, http_version))) { + /* something wrong, abort */ + xfree(inbuf); + return result; } + /* * Process headers after request line * TODO: Use httpRequestParse here. */ req_hdr = inbuf + *req_line_sz_p; + header_sz = req_sz - *req_line_sz_p; + debug(33, 3) ("parseHttpRequest: req_hdr = {%s}\n", req_hdr); + end = req_hdr + header_sz; + debug(33, 3) ("parseHttpRequest: end = {%s}\n", end); prefix_sz = end - inbuf; + debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n", - (int) prefix_sz, (int) *req_line_sz_p); + (int) prefix_sz, (int) *req_line_sz_p); + assert(prefix_sz <= conn->in.notYetUsed); /* Ok, all headers are received */ http = new ClientHttpRequest; + http->http_ver = http_ver; + http->conn = conn; + http->req_sz = prefix_sz; + result = ClientSocketContextNew(http); + tempBuffer.data = result->reqbuf; + tempBuffer.length = HTTP_REQBUF_SZ; + clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach, - clientReplyStatus, clientReplyNewContext(http), clientSocketRecipient, - clientSocketDetach, result, tempBuffer); + clientReplyStatus, clientReplyNewContext(http), clientSocketRecipient, + clientSocketDetach, result, tempBuffer); + *prefix_p = (char *)xmalloc(prefix_sz + 1); + xmemcpy(*prefix_p, conn->in.buf, prefix_sz); + *(*prefix_p + prefix_sz) = '\0'; + dlinkAdd(http, &http->active, &ClientActiveRequests); debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", - (*prefix_p) + *req_line_sz_p); + (*prefix_p) + *req_line_sz_p); #if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION + if ((t = strchr(url, '#'))) /* remove HTML anchors */ - *t = '\0'; + *t = '\0'; + #endif /* Rewrite the URL in transparent or accelerator mode */ if (conn->transparent) { - prepareTransparentURL(conn, http, url, req_hdr); + prepareTransparentURL(conn, http, url, req_hdr); } else if (conn->port->accel) { - prepareAcceleratedURL(conn, http, url, req_hdr); + prepareAcceleratedURL(conn, http, url, req_hdr); } if (!http->uri) { - /* No special rewrites have been applied above, use the - * requested url. may be rewritten later, so make extra room */ - int url_sz = strlen(url) + Config.appendDomainLen + 5; - http->uri = (char *)xcalloc(url_sz, 1); - strcpy(http->uri, url); + /* No special rewrites have been applied above, use the + * requested url. may be rewritten later, so make extra room */ + int url_sz = strlen(url) + Config.appendDomainLen + 5; + http->uri = (char *)xcalloc(url_sz, 1); + strcpy(http->uri, url); } - + setLogUri(http, http->uri); debug(33, 5) ("parseHttpRequest: Complete request received\n"); xfree(inbuf); @@ -1641,10 +1884,11 @@ static int clientReadDefer(int fdnotused, void *data) { ConnStateData *conn = (ConnStateData *)data; + if (conn->body.size_left) - return conn->in.notYetUsed >= conn->in.allocatedSize - 1; + return conn->in.notYetUsed >= conn->in.allocatedSize - 1; else - return conn->defer.until > squid_curtime; + return conn->defer.until > squid_curtime; } int @@ -1657,9 +1901,9 @@ void connMakeSpaceAvailable(ConnStateData * conn) { if (connGetAvailableBufferLength(conn) < 2) { - conn->in.buf = (char *)memReallocBuf(conn->in.buf, conn->in.allocatedSize * 2, &conn->in.allocatedSize); - debug(33, 2) ("growing request buffer: notYetUsed=%ld size=%ld\n", - (long) conn->in.notYetUsed, (long) conn->in.allocatedSize); + conn->in.buf = (char *)memReallocBuf(conn->in.buf, conn->in.allocatedSize * 2, &conn->in.allocatedSize); + debug(33, 2) ("growing request buffer: notYetUsed=%ld size=%ld\n", + (long) conn->in.notYetUsed, (long) conn->in.allocatedSize); } } @@ -1667,9 +1911,13 @@ void connAddContextToQueue(ConnStateData * conn, ClientSocketContext * context) { ClientSocketContext **S; + for (S = (ClientSocketContext **) & conn->currentobject; *S; - S = &(*S)->next); + S = &(*S)->next) + + ; *S = context; + ++conn->nrequests; } @@ -1678,8 +1926,11 @@ connGetConcurrentRequestCount(ConnStateData * conn) { int result = 0; ClientSocketContext **T; + for (T = (ClientSocketContext **) & conn->currentobject; - *T; T = &(*T)->next, ++result); + *T; T = &(*T)->next, ++result) + + ; return result; } @@ -1687,18 +1938,20 @@ int connReadWasError(ConnStateData * conn, comm_err_t flag, int size) { if (flag != COMM_OK) { - debug(50, 2) ("connReadWasError: FD %d: got flag %d\n", conn->fd, flag); - return 1; + debug(50, 2) ("connReadWasError: FD %d: got flag %d\n", conn->fd, flag); + return 1; } + if (size < 0) { - if (!ignoreErrno(errno)) { - debug(50, 2) ("connReadWasError: FD %d: %s\n", conn->fd, xstrerror()); - return 1; - } else if (conn->in.notYetUsed == 0) { - debug(50, 2) ("connReadWasError: FD %d: no data to process (%s)\n", - conn->fd, xstrerror()); - } + if (!ignoreErrno(errno)) { + debug(50, 2) ("connReadWasError: FD %d: %s\n", conn->fd, xstrerror()); + return 1; + } else if (conn->in.notYetUsed == 0) { + debug(50, 2) ("connReadWasError: FD %d: no data to process (%s)\n", + conn->fd, xstrerror()); + } } + return 0; } @@ -1706,16 +1959,17 @@ int connFinishedWithConn(ConnStateData * conn, int size) { if (size == 0) { - if (connGetConcurrentRequestCount(conn) == 0 && conn->in.notYetUsed == 0) { - /* no current or pending requests */ - debug(33, 4) ("connFinishedWithConn: FD %d closed\n", conn->fd); - return 1; - } else if (!Config.onoff.half_closed_clients) { - /* admin doesn't want to support half-closed client sockets */ - debug(33, 3) ("connFinishedWithConn: FD %d aborted (half_closed_clients disabled)\n", conn->fd); - return 1; - } + if (connGetConcurrentRequestCount(conn) == 0 && conn->in.notYetUsed == 0) { + /* no current or pending requests */ + debug(33, 4) ("connFinishedWithConn: FD %d closed\n", conn->fd); + return 1; + } else if (!Config.onoff.half_closed_clients) { + /* admin doesn't want to support half-closed client sockets */ + debug(33, 3) ("connFinishedWithConn: FD %d aborted (half_closed_clients disabled)\n", conn->fd); + return 1; + } } + return 0; } @@ -1729,9 +1983,10 @@ connNoteUseOfBuffer(ConnStateData * conn, size_t byteCount) * If there is still data that will be used, * move it to the beginning. */ + if (conn->in.notYetUsed > 0) - xmemmove(conn->in.buf, conn->in.buf + byteCount, - conn->in.notYetUsed); + xmemmove(conn->in.buf, conn->in.buf + byteCount, + conn->in.notYetUsed); } int @@ -1747,12 +2002,12 @@ connCancelIncompleteRequests(ConnStateData * conn) clientStreamNode *node = context->getClientReplyContext(); assert(!connKeepReadingIncompleteRequest(conn)); debug(33, 1) ("Request header is too large (%u bytes)\n", - (unsigned) conn->in.notYetUsed); + (unsigned) conn->in.notYetUsed); debug(33, 1) ("Config 'request_header_max_size'= %ld bytes.\n", - (long int) Config.maxRequestHeaderSize); + (long int) Config.maxRequestHeaderSize); clientSetReplyToError(node->data, ERR_TOO_BIG, - HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, - &conn->peer.sin_addr, NULL, NULL, NULL); + HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, + &conn->peer.sin_addr, NULL, NULL, NULL); connAddContextToQueue(conn, context); context->pullData(); } @@ -1761,8 +2016,8 @@ static void clientMaybeReadData(ConnStateData *conn, int do_next_read) { if (do_next_read) { - conn->flags.readMoreRequests = 1; - clientReadSomeData(conn); + conn->flags.readMoreRequests = 1; + clientReadSomeData(conn); } } @@ -1772,14 +2027,15 @@ clientAfterReadingRequests(int fd, ConnStateData *conn, int do_next_read) fde *F = &fd_table[fd]; /* Check if a half-closed connection was aborted in the middle */ + if (F->flags.socket_eof) { - if (conn->in.notYetUsed != conn->body.size_left) { - /* != 0 when no request body */ - /* Partial request received. Abort client connection! */ - debug(33, 3) ("clientReadRequest: FD %d aborted, partial request\n",+ fd); - comm_close(fd); - return; - } + if (conn->in.notYetUsed != conn->body.size_left) { + /* != 0 when no request body */ + /* Partial request received. Abort client connection! */ + debug(33, 3) ("clientReadRequest: FD %d aborted, partial request\n",+ fd); + comm_close(fd); + return; + } } clientMaybeReadData (conn, do_next_read); @@ -1797,50 +2053,52 @@ clientProcessRequest(ConnStateData *conn, ClientSocketContext *context, method_t connAddContextToQueue(conn, context); if (context->flags.parsed_ok == 0) { - clientStreamNode *node = context->getClientReplyContext(); - debug(33, 1) ("clientReadRequest: Invalid Request\n"); - clientSetReplyToError(node->data, - ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, NULL, - &conn->peer.sin_addr, NULL, conn->in.buf, NULL); - assert(context->http->out.offset == 0); - context->pullData(); - conn->flags.readMoreRequests = 0; - return; + clientStreamNode *node = context->getClientReplyContext(); + debug(33, 1) ("clientReadRequest: Invalid Request\n"); + clientSetReplyToError(node->data, + ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, NULL, + &conn->peer.sin_addr, NULL, conn->in.buf, NULL); + assert(context->http->out.offset == 0); + context->pullData(); + conn->flags.readMoreRequests = 0; + return; } if ((request = urlParse(method, http->uri)) == NULL) { - clientStreamNode *node = context->getClientReplyContext(); - debug(33, 5) ("Invalid URL: %s\n", http->uri); - clientSetReplyToError(node->data, - ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, - &conn->peer.sin_addr, NULL, NULL, NULL); - assert(context->http->out.offset == 0); - context->pullData(); - conn->flags.readMoreRequests = 0; - return; - } + clientStreamNode *node = context->getClientReplyContext(); + debug(33, 5) ("Invalid URL: %s\n", http->uri); + clientSetReplyToError(node->data, + ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, + &conn->peer.sin_addr, NULL, NULL, NULL); + assert(context->http->out.offset == 0); + context->pullData(); + conn->flags.readMoreRequests = 0; + return; + } /* compile headers */ /* we should skip request line! */ if (!httpRequestParseHeader(request, prefix + req_line_sz)) - if (http->http_ver.major >= 1) - debug(33, 1) ("Failed to parse request headers: %s\n%s\n", - http->uri, prefix); + if (http->http_ver.major >= 1) + debug(33, 1) ("Failed to parse request headers: %s\n%s\n", + http->uri, prefix); + /* continue anyway? */ request->flags.accelerated = http->flags.accel; + if (!http->flags.internal) { - if (internalCheck(request->urlpath.buf())) { - if (internalHostnameIs(request->host) && - request->port == getMyPort()) { - http->flags.internal = 1; - } else if (internalStaticCheck(request->urlpath.buf())) { - xstrncpy(request->host, internalHostname(), - SQUIDHOSTNAMELEN); - request->port = getMyPort(); - http->flags.internal = 1; - } - } + if (internalCheck(request->urlpath.buf())) { + if (internalHostnameIs(request->host) && + request->port == getMyPort()) { + http->flags.internal = 1; + } else if (internalStaticCheck(request->urlpath.buf())) { + xstrncpy(request->host, internalHostname(), + SQUIDHOSTNAMELEN); + request->port = getMyPort(); + http->flags.internal = 1; + } + } } request->flags.internal = http->flags.internal; @@ -1849,54 +2107,59 @@ clientProcessRequest(ConnStateData *conn, ClientSocketContext *context, method_t request->my_addr = conn->me.sin_addr; request->my_port = ntohs(conn->me.sin_port); request->http_ver = http->http_ver; + if (!urlCheckRequest(request) || - httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) { - clientStreamNode *node = context->getClientReplyContext(); - clientSetReplyToError(node->data, ERR_UNSUP_REQ, - HTTP_NOT_IMPLEMENTED, request->method, NULL, - &conn->peer.sin_addr, request, NULL, NULL); - assert(context->http->out.offset == 0); - context->pullData(); - conn->flags.readMoreRequests = 0; - return; + httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) { + clientStreamNode *node = context->getClientReplyContext(); + clientSetReplyToError(node->data, ERR_UNSUP_REQ, + HTTP_NOT_IMPLEMENTED, request->method, NULL, + &conn->peer.sin_addr, request, NULL, NULL); + assert(context->http->out.offset == 0); + context->pullData(); + conn->flags.readMoreRequests = 0; + return; } if (!clientIsContentLengthValid(request)) { - clientStreamNode *node = context->getClientReplyContext(); - clientSetReplyToError(node->data, ERR_INVALID_REQ, - HTTP_LENGTH_REQUIRED, request->method, NULL, - &conn->peer.sin_addr, request, NULL, NULL); - assert(context->http->out.offset == 0); - context->pullData(); - conn->flags.readMoreRequests = 0; - return; + clientStreamNode *node = context->getClientReplyContext(); + clientSetReplyToError(node->data, ERR_INVALID_REQ, + HTTP_LENGTH_REQUIRED, request->method, NULL, + &conn->peer.sin_addr, request, NULL, NULL); + assert(context->http->out.offset == 0); + context->pullData(); + conn->flags.readMoreRequests = 0; + return; } http->request = requestLink(request); clientSetKeepaliveFlag(http); /* Do we expect a request-body? */ + if (request->content_length > 0) { - conn->body.size_left = request->content_length; - request->body_connection = conn; - /* Is it too large? */ - if (!clientIsRequestBodyValid(request->content_length) || - clientIsRequestBodyTooLargeForPolicy(request->content_length)) { - clientStreamNode *node = context->getClientReplyContext(); - clientSetReplyToError(node->data, ERR_TOO_BIG, - HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, - &conn->peer.sin_addr, http->request, NULL, NULL); - assert(context->http->out.offset == 0); - context->pullData(); - conn->flags.readMoreRequests = 0; - return; - } - context->mayUseConnection(true); + conn->body.size_left = request->content_length; + request->body_connection = conn; + /* Is it too large? */ + + if (!clientIsRequestBodyValid(request->content_length) || + clientIsRequestBodyTooLargeForPolicy(request->content_length)) { + clientStreamNode *node = context->getClientReplyContext(); + clientSetReplyToError(node->data, ERR_TOO_BIG, + HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, + &conn->peer.sin_addr, http->request, NULL, NULL); + assert(context->http->out.offset == 0); + context->pullData(); + conn->flags.readMoreRequests = 0; + return; + } + + context->mayUseConnection(true); } /* If this is a CONNECT, don't schedule a read - ssl.c will handle it */ if (http->request->method == METHOD_CONNECT) - context->mayUseConnection(true); + context->mayUseConnection(true); + clientAccessCheck(http); } @@ -1904,8 +2167,8 @@ static void connStripBufferWhitespace (ConnStateData *conn) { while (conn->in.notYetUsed > 0 && xisspace(conn->in.buf[0])) { - xmemmove(conn->in.buf, conn->in.buf + 1, conn->in.notYetUsed - 1); - --conn->in.notYetUsed; + xmemmove(conn->in.buf, conn->in.buf + 1, conn->in.notYetUsed - 1); + --conn->in.notYetUsed; } } @@ -1913,12 +2176,14 @@ static int connOkToAddRequest(ConnStateData *conn) { int result = connGetConcurrentRequestCount(conn) < (Config.onoff.pipeline_prefetch ? 2 : 1); + if (!result) { - debug(33, 3) ("clientReadRequest: FD %d max concurrent requests reached\n", - conn->fd); - debug(33, 5) ("clientReadRequest: FD %d defering new request until one is done\n", - conn->fd); + debug(33, 3) ("clientReadRequest: FD %d max concurrent requests reached\n", + conn->fd); + debug(33, 5) ("clientReadRequest: FD %d defering new request until one is done\n", + conn->fd); } + return result; } @@ -1931,7 +2196,7 @@ connSetDefer (ConnStateData *conn, size_t milliSeconds) static void clientReadRequest(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, -void *data) + void *data) { ConnStateData *conn = (ConnStateData *)data; assert (conn->reading); @@ -1944,9 +2209,11 @@ void *data) assert (fd == conn->fd); /* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */ + if (flag == COMM_ERR_CLOSING) { return; } + /* * Don't reset the timeout value here. The timeout value will be * set to Config.Timeout.request by httpAccept() and @@ -1955,107 +2222,126 @@ void *data) * lame half-close detection */ if (connReadWasError(conn, flag, size)) { - comm_close(fd); - return; + comm_close(fd); + return; } if (flag == COMM_OK) { - if (size > 0) { - kb_incr(&statCounter.client_http.kbytes_in, size); - conn->in.notYetUsed += size; - conn->in.buf[conn->in.notYetUsed] = '\0'; /* Terminate the string -*/ - } else if (size == 0) { - debug(33, 5) ("clientReadRequest: FD %d closed?\n", fd); - if (connFinishedWithConn(conn, size)) { - comm_close(fd); - return; - } - /* It might be half-closed, we can't tell */ - fd_table[fd].flags.socket_eof = 1; - connSetDefer (conn, 1); - fd_note(fd, "half-closed"); - /* There is one more close check at the end, to detect aborted - * (partial) requests. At this point we can't tell if the request - * is partial. - */ - /* Continue to process previously read data */ - } + if (size > 0) { + kb_incr(&statCounter.client_http.kbytes_in, size); + conn->in.notYetUsed += size; + conn->in.buf[conn->in.notYetUsed] = '\0'; /* Terminate the string + */ + } else if (size == 0) { + debug(33, 5) ("clientReadRequest: FD %d closed?\n", fd); + + if (connFinishedWithConn(conn, size)) { + comm_close(fd); + return; + } + + /* It might be half-closed, we can't tell */ + fd_table[fd].flags.socket_eof = 1; + + connSetDefer (conn, 1); + + fd_note(fd, "half-closed"); + + /* There is one more close check at the end, to detect aborted + * (partial) requests. At this point we can't tell if the request + * is partial. + */ + /* Continue to process previously read data */ + } } /* Process request body if any */ if (conn->in.notYetUsed > 0 && conn->body.callback != NULL) - clientProcessBody(conn); + clientProcessBody(conn); + /* Process next request */ if (connGetConcurrentRequestCount(conn) == 0) - fd_note(conn->fd, "Reading next request"); + fd_note(conn->fd, "Reading next request"); while (conn->in.notYetUsed > 0 && conn->body.size_left == 0) { - size_t req_line_sz; - connStripBufferWhitespace (conn); - if (conn->in.notYetUsed == 0) { - clientAfterReadingRequests(fd, conn, do_next_read); - return; - } - /* Limit the number of concurrent requests to 2 */ - if (!connOkToAddRequest(conn)) { - /* Reset when a request is complete */ - connSetDefer (conn, 100); - clientMaybeReadData (conn, do_next_read); - return; - } - /* Should not be needed anymore */ - /* Terminate the string */ - conn->in.buf[conn->in.notYetUsed] = '\0'; - /* Process request */ - context = parseHttpRequest(conn, - &method, &prefix, &req_line_sz); - /* partial or incomplete request */ - if (!context) { - safe_free(prefix); - if (!connKeepReadingIncompleteRequest(conn)) - connCancelIncompleteRequests(conn); - break; /* conn->in.notYetUsed > 0 && conn->body.size_left == 0 */ - } - - /* status -1 or 1 */ - if (context) { - commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout, - context->http); - - clientProcessRequest(conn, context, method, prefix, req_line_sz); - - safe_free(prefix); - if (context->mayUseConnection()) { - debug (33, 3) ("clientReadRequest: Not reading, as this request may need the connection\n"); - do_next_read = 0; - break; - } + size_t req_line_sz; + connStripBufferWhitespace (conn); + + if (conn->in.notYetUsed == 0) { + clientAfterReadingRequests(fd, conn, do_next_read); + return; + } + + /* Limit the number of concurrent requests to 2 */ + if (!connOkToAddRequest(conn)) { + /* Reset when a request is complete */ + connSetDefer (conn, 100); + clientMaybeReadData (conn, do_next_read); + return; + } + + /* Should not be needed anymore */ + /* Terminate the string */ + conn->in.buf[conn->in.notYetUsed] = '\0'; + + /* Process request */ + context = parseHttpRequest(conn, + &method, &prefix, &req_line_sz); + + /* partial or incomplete request */ + if (!context) { + safe_free(prefix); + + if (!connKeepReadingIncompleteRequest(conn)) + connCancelIncompleteRequests(conn); + + break; /* conn->in.notYetUsed > 0 && conn->body.size_left == 0 */ + } + + /* status -1 or 1 */ + if (context) { + commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout, + context->http); + + clientProcessRequest(conn, context, method, prefix, req_line_sz); + + safe_free(prefix); + + if (context->mayUseConnection()) { + debug (33, 3) ("clientReadRequest: Not reading, as this request may need the connection\n"); + do_next_read = 0; + break; + } + if (!conn->flags.readMoreRequests) { conn->flags.readMoreRequests = 1; - break; - } - continue; /* while offset > 0 && body.size_left == 0 */ - } + break; + } + + continue; /* while offset > 0 && body.size_left == 0 */ + } } /* while offset > 0 && conn->body.size_left == 0 */ + clientAfterReadingRequests(fd, conn, do_next_read); } /* file_read like function, for reading body content */ void clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, - void *cbdata) + void *cbdata) { ConnStateData *conn = request->body_connection; + if (!conn) { - debug(33, 5) ("clientReadBody: no body to read, request=%p\n", request); - callback(buf, 0, cbdata); /* Signal end of body */ - return; + debug(33, 5) ("clientReadBody: no body to read, request=%p\n", request); + callback(buf, 0, cbdata); /* Signal end of body */ + return; } + debug(33, 2) ("clientReadBody: start fd=%d body_size=%lu in.notYetUsed=%ld cb=%p req=%p\n", - conn->fd, (unsigned long int) conn->body.size_left, - (unsigned long int) conn->in.notYetUsed, callback, request); + conn->fd, (unsigned long int) conn->body.size_left, + (unsigned long int) conn->in.notYetUsed, callback, request); conn->body.callback = callback; conn->body.cbdata = cbdata; conn->body.buf = buf; @@ -2075,48 +2361,64 @@ clientProcessBody(ConnStateData * conn) request_t *request = conn->body.request; /* Note: request is null while eating "aborted" transfers */ debug(33, 2) ("clientProcessBody: start fd=%d body_size=%lu in.notYetUsed=%lu cb=%p req=%p\n", - conn->fd, (unsigned long int) conn->body.size_left, - (unsigned long int) conn->in.notYetUsed, callback, request); + conn->fd, (unsigned long int) conn->body.size_left, + (unsigned long int) conn->in.notYetUsed, callback, request); + if (conn->in.notYetUsed) { - /* Some sanity checks... */ - assert(conn->body.size_left > 0); - assert(conn->in.notYetUsed > 0); - assert(callback != NULL); - assert(buf != NULL); - /* How much do we have to process? */ - size = conn->in.notYetUsed; - if (size > conn->body.size_left) /* only process the body part */ - size = conn->body.size_left; - if (size > conn->body.bufsize) /* don't copy more than requested */ - size = conn->body.bufsize; - xmemcpy(buf, conn->in.buf, size); - conn->body.size_left -= size; - /* Move any remaining data */ - conn->in.notYetUsed -= size; - if (conn->in.notYetUsed > 0) - xmemmove(conn->in.buf, conn->in.buf + size, conn->in.notYetUsed); - /* Remove request link if this is the last part of the body, as - * clientReadRequest automatically continues to process next request */ - if (conn->body.size_left <= 0 && request != NULL) - request->body_connection = NULL; - /* Remove clientReadBody arguments (the call is completed) */ - conn->body.request = NULL; - conn->body.callback = NULL; - conn->body.buf = NULL; - conn->body.bufsize = 0; - /* Remember that we have touched the body, not restartable */ - if (request != NULL) { - request->flags.body_sent = 1; - conn->body.request = NULL; - } - /* Invoke callback function */ - callback(buf, size, cbdata); - if (request != NULL) { - requestUnlink(request); /* Linked in clientReadBody */ - } - debug(33, 2) ("clientProcessBody: end fd=%d size=%lu body_size=%lu in.notYetUsed=%lu cb=%p req=%p\n", - conn->fd, (unsigned long int)size, (unsigned long int) conn->body.size_left, - (unsigned long) conn->in.notYetUsed, callback, request); + /* Some sanity checks... */ + assert(conn->body.size_left > 0); + assert(conn->in.notYetUsed > 0); + assert(callback != NULL); + assert(buf != NULL); + /* How much do we have to process? */ + size = conn->in.notYetUsed; + + if (size > conn->body.size_left) /* only process the body part */ + size = conn->body.size_left; + + if (size > conn->body.bufsize) /* don't copy more than requested */ + size = conn->body.bufsize; + + xmemcpy(buf, conn->in.buf, size); + + conn->body.size_left -= size; + + /* Move any remaining data */ + conn->in.notYetUsed -= size; + + if (conn->in.notYetUsed > 0) + xmemmove(conn->in.buf, conn->in.buf + size, conn->in.notYetUsed); + + /* Remove request link if this is the last part of the body, as + * clientReadRequest automatically continues to process next request */ + if (conn->body.size_left <= 0 && request != NULL) + request->body_connection = NULL; + + /* Remove clientReadBody arguments (the call is completed) */ + conn->body.request = NULL; + + conn->body.callback = NULL; + + conn->body.buf = NULL; + + conn->body.bufsize = 0; + + /* Remember that we have touched the body, not restartable */ + if (request != NULL) { + request->flags.body_sent = 1; + conn->body.request = NULL; + } + + /* Invoke callback function */ + callback(buf, size, cbdata); + + if (request != NULL) { + requestUnlink(request); /* Linked in clientReadBody */ + } + + debug(33, 2) ("clientProcessBody: end fd=%d size=%lu body_size=%lu in.notYetUsed=%lu cb=%p req=%p\n", + conn->fd, (unsigned long int)size, (unsigned long int) conn->body.size_left, + (unsigned long) conn->in.notYetUsed, callback, request); } } @@ -2127,15 +2429,16 @@ clientReadBodyAbortHandler(char *buf, ssize_t size, void *data) static char bodyAbortBuf[SQUID_TCP_SO_RCVBUF]; ConnStateData *conn = (ConnStateData *) data; debug(33, 2) ("clientReadBodyAbortHandler: fd=%d body_size=%lu in.notYetUsed=%lu\n", - conn->fd, (unsigned long int) conn->body.size_left, - (unsigned long) conn->in.notYetUsed); + conn->fd, (unsigned long int) conn->body.size_left, + (unsigned long) conn->in.notYetUsed); + if (size != 0 && conn->body.size_left != 0) { - debug(33, 3) ("clientReadBodyAbortHandler: fd=%d shedule next read\n", - conn->fd); - conn->body.callback = clientReadBodyAbortHandler; - conn->body.buf = bodyAbortBuf; - conn->body.bufsize = sizeof(bodyAbortBuf); - conn->body.cbdata = data; + debug(33, 3) ("clientReadBodyAbortHandler: fd=%d shedule next read\n", + conn->fd); + conn->body.callback = clientReadBodyAbortHandler; + conn->body.buf = bodyAbortBuf; + conn->body.bufsize = sizeof(bodyAbortBuf); + conn->body.cbdata = data; } } @@ -2148,20 +2451,23 @@ clientAbortBody(request_t * request) CBCB *callback; void *cbdata; request->body_connection = NULL; + if (!conn || conn->body.size_left <= 0) - return 0; /* No body to abort */ + return 0; /* No body to abort */ + if (conn->body.callback != NULL) { - buf = conn->body.buf; - callback = conn->body.callback; - cbdata = conn->body.cbdata; - assert(request == conn->body.request); - conn->body.buf = NULL; - conn->body.callback = NULL; - conn->body.cbdata = NULL; - conn->body.request = NULL; - callback(buf, -1, cbdata); /* Signal abort to clientReadBody caller */ - requestUnlink(request); + buf = conn->body.buf; + callback = conn->body.callback; + cbdata = conn->body.cbdata; + assert(request == conn->body.request); + conn->body.buf = NULL; + conn->body.callback = NULL; + conn->body.cbdata = NULL; + conn->body.request = NULL; + callback(buf, -1, cbdata); /* Signal abort to clientReadBody caller */ + requestUnlink(request); } + clientReadBodyAbortHandler(NULL, -1, conn); /* Install abort handler */ /* clientProcessBody() */ return 1; /* Aborted */ @@ -2174,55 +2480,65 @@ requestTimeout(int fd, void *data) #if THIS_CONFUSES_PERSISTENT_CONNECTION_AWARE_BROWSERS_AND_USERS ConnStateData *conn = data; debug(33, 3) ("requestTimeout: FD %d: lifetime is expired.\n", fd); + if (fd_table[fd].rwstate) { - /* - * Some data has been sent to the client, just close the FD - */ - comm_close(fd); + /* + * Some data has been sent to the client, just close the FD + */ + comm_close(fd); } else if (conn->nrequests) { - /* - * assume its a persistent connection; just close it - */ - comm_close(fd); + /* + * assume its a persistent connection; just close it + */ + comm_close(fd); } else { - /* - * Generate an error - */ - clientHttpRequest **H; - clientStreamNode *node; - clientHttpRequest *http = - parseHttpRequestAbort(conn, "error:Connection%20lifetime%20expired"); - node = http->client_stream.tail->prev->data; - clientSetReplyToError(node->data, ERR_LIFETIME_EXP, - HTTP_REQUEST_TIMEOUT, METHOD_NONE, "N/A", &conn->peer.sin_addr, - NULL, NULL, NULL); - /* No requests can be outstanded */ - assert(conn->chr == NULL); - /* add to the client request queue */ - for (H = &conn->chr; *H; H = &(*H)->next); - *H = http; - clientStreamRead(http->client_stream.tail->data, http, 0, - HTTP_REQBUF_SZ, context->reqbuf); - /* - * if we don't close() here, we still need a timeout handler! - */ - commSetTimeout(fd, 30, requestTimeout, conn); - /* - * Aha, but we don't want a read handler! - */ - commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); + /* + * Generate an error + */ + clientHttpRequest **H; + clientStreamNode *node; + clientHttpRequest *http = + parseHttpRequestAbort(conn, "error:Connection%20lifetime%20expired"); + node = http->client_stream.tail->prev->data; + clientSetReplyToError(node->data, ERR_LIFETIME_EXP, + HTTP_REQUEST_TIMEOUT, METHOD_NONE, "N/A", &conn->peer.sin_addr, + NULL, NULL, NULL); + /* No requests can be outstanded */ + assert(conn->chr == NULL); + /* add to the client request queue */ + + for (H = &conn->chr; *H; H = &(*H)->next) + + ; + *H = http; + + clientStreamRead(http->client_stream.tail->data, http, 0, + HTTP_REQBUF_SZ, context->reqbuf); + + /* + * if we don't close() here, we still need a timeout handler! + */ + commSetTimeout(fd, 30, requestTimeout, conn); + + /* + * Aha, but we don't want a read handler! + */ + commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); } + #else /* - * Just close the connection to not confuse browsers - * using persistent connections. Some browsers opens - * an connection and then does not use it until much - * later (presumeably because the request triggering - * the open has already been completed on another - * connection) - */ + * Just close the connection to not confuse browsers + * using persistent connections. Some browsers opens + * an connection and then does not use it until much + * later (presumeably because the request triggering + * the open has already been completed on another + * connection) + */ debug(33, 3) ("requestTimeout: FD %d: lifetime is expired.\n", fd); + comm_close(fd); + #endif } @@ -2232,8 +2548,8 @@ clientLifetimeTimeout(int fd, void *data) clientHttpRequest *http = (clientHttpRequest *)data; ConnStateData *conn = http->conn; debug(33, - 1) ("WARNING: Closing client %s connection due to lifetime timeout\n", - inet_ntoa(conn->peer.sin_addr)); + 1) ("WARNING: Closing client %s connection due to lifetime timeout\n", + inet_ntoa(conn->peer.sin_addr)); debug(33, 1) ("\t%s\n", http->uri); comm_close(fd); } @@ -2242,16 +2558,20 @@ static int httpAcceptDefer(int fdunused, void *dataunused) { static time_t last_warn = 0; + if (fdNFree() >= RESERVED_FD) - return 0; + return 0; + if (last_warn + 15 < squid_curtime) { - debug(33, 0) ("WARNING! Your cache is running out of filedescriptors\n"); - last_warn = squid_curtime; + debug(33, 0) ("WARNING! Your cache is running out of filedescriptors\n"); + last_warn = squid_curtime; } + return 1; } ConnStateData * + connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_port_list *port) { ConnStateData *result = cbdataAlloc(ConnStateData); @@ -2262,13 +2582,18 @@ connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_p result->fd = fd; result->in.buf = (char *)memAllocBuf(CLIENT_REQ_BUF_SZ, &result->in.allocatedSize); result->port = cbdataReference(port); - if (port->transparent) { - struct sockaddr_in dst; - if (clientNatLookup(fd, *me, *peer, &dst) == 0) { - result->me = dst; /* XXX This should be moved to another field */ - result->transparent = 1; - } + + if (port->transparent) + { + + struct sockaddr_in dst; + + if (clientNatLookup(fd, *me, *peer, &dst) == 0) { + result->me = dst; /* XXX This should be moved to another field */ + result->transparent = 1; + } } + result->flags.readMoreRequests = 1; return result; } @@ -2276,7 +2601,7 @@ connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_p /* Handle a new connection on HTTP socket. */ void httpAccept(int sock, int newfd, ConnectionDetail *details, - comm_err_t flag, int xerrno, void *data) + comm_err_t flag, int xerrno, void *data) { http_port_list *s = (http_port_list *)data; ConnStateData *connState = NULL; @@ -2290,33 +2615,46 @@ httpAccept(int sock, int newfd, ConnectionDetail *details, /* XXX we're not considering httpAcceptDefer yet! */ - if (flag != COMM_OK) { - errno = xerrno; - debug(50, 1) ("httpAccept: FD %d: accept failure: %s\n", - sock, xstrerror()); - return; - } - - debug(33, 4) ("httpAccept: FD %d: accepted\n", newfd); - fd_note(newfd, "client http connect"); - connState = connStateCreate(&details->peer, &details->me, newfd, s); - connState->port = cbdataReference(s); - comm_add_close_handler(newfd, connStateFree, connState); - if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS); - commSetTimeout(newfd, Config.Timeout.request, requestTimeout, connState); + if (flag != COMM_OK) { + errno = xerrno; + debug(50, 1) ("httpAccept: FD %d: accept failure: %s\n", + sock, xstrerror()); + return; + } + + debug(33, 4) ("httpAccept: FD %d: accepted\n", newfd); + fd_note(newfd, "client http connect"); + connState = connStateCreate(&details->peer, &details->me, newfd, s); + connState->port = cbdataReference(s); + comm_add_close_handler(newfd, connStateFree, connState); + + if (Config.onoff.log_fqdn) + fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS); + + commSetTimeout(newfd, Config.Timeout.request, requestTimeout, connState); + #if USE_IDENT - ACLChecklist identChecklist; - identChecklist.src_addr = details->peer.sin_addr; - identChecklist.my_addr = details->me.sin_addr; - identChecklist.my_port = ntohs(details->me.sin_port); - if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) - identStart(&details->me, &details->peer, clientIdentDone, connState); + + ACLChecklist identChecklist; + + identChecklist.src_addr = details->peer.sin_addr; + + identChecklist.my_addr = details->me.sin_addr; + + identChecklist.my_port = ntohs(details->me.sin_port); + + if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) + identStart(&details->me, &details->peer, clientIdentDone, connState); + #endif - clientReadSomeData(connState); - commSetDefer(newfd, clientReadDefer, connState); - clientdbEstablished(details->peer.sin_addr, 1); - incoming_sockets_accepted++; + + clientReadSomeData(connState); + + commSetDefer(newfd, clientReadDefer, connState); + + clientdbEstablished(details->peer.sin_addr, 1); + + incoming_sockets_accepted++; } #if USE_SSL @@ -2331,36 +2669,43 @@ clientNegotiateSSL(int fd, void *data) int ret; if ((ret = SSL_accept(ssl)) <= 0) { - int ssl_error = SSL_get_error(ssl, ret); - switch (ssl_error) { - case SSL_ERROR_WANT_READ: - commSetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, conn, 0); - return; - case SSL_ERROR_WANT_WRITE: - commSetSelect(fd, COMM_SELECT_WRITE, clientNegotiateSSL, conn, 0); - return; - default: - debug(81, 1) ("clientNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n", - fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret); - comm_close(fd); - return; - } - /* NOTREACHED */ + int ssl_error = SSL_get_error(ssl, ret); + + switch (ssl_error) { + + case SSL_ERROR_WANT_READ: + commSetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, conn, 0); + return; + + case SSL_ERROR_WANT_WRITE: + commSetSelect(fd, COMM_SELECT_WRITE, clientNegotiateSSL, conn, 0); + return; + + default: + debug(81, 1) ("clientNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n", + fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret); + comm_close(fd); + return; + } + + /* NOTREACHED */ } + debug(83, 5) ("clientNegotiateSSL: FD %d negotiated cipher %s\n", fd, - SSL_get_cipher(fd_table[fd].ssl)); + SSL_get_cipher(fd_table[fd].ssl)); client_cert = SSL_get_peer_certificate(fd_table[fd].ssl); + if (client_cert != NULL) { - debug(83, 5) ("clientNegotiateSSL: FD %d client certificate: subject: %s\n", - fd, X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0)); + debug(83, 5) ("clientNegotiateSSL: FD %d client certificate: subject: %s\n", + fd, X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0)); - debug(83, 5) ("clientNegotiateSSL: FD %d client certificate: issuer: %s\n", - fd, X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0)); + debug(83, 5) ("clientNegotiateSSL: FD %d client certificate: issuer: %s\n", + fd, X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0)); - X509_free(client_cert); + X509_free(client_cert); } else { - debug(83, 5) ("clientNegotiateSSL: FD %d has no certificate.\n", fd); + debug(83, 5) ("clientNegotiateSSL: FD %d has no certificate.\n", fd); } clientReadSomeData(conn); @@ -2369,7 +2714,7 @@ clientNegotiateSSL(int fd, void *data) /* handle a new HTTPS connection */ static void httpsAccept(int sock, int newfd, ConnectionDetail *details, - comm_err_t flag, int xerrno, void *data) + comm_err_t flag, int xerrno, void *data) { https_port_list *s = (https_port_list *)data; SSL_CTX *sslContext = s->sslContext; @@ -2382,17 +2727,17 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details, } if (flag != COMM_OK) { - errno = xerrno; - debug(50, 1) ("httpsAccept: FD %d: accept failure: %s\n", - sock, xstrerror()); - return; + errno = xerrno; + debug(50, 1) ("httpsAccept: FD %d: accept failure: %s\n", + sock, xstrerror()); + return; } - + if ((ssl = SSL_new(sslContext)) == NULL) { - ssl_error = ERR_get_error(); - debug(83, 1) ("httpsAccept: Error allocating handle: %s\n", - ERR_error_string(ssl_error, NULL)); - return; + ssl_error = ERR_get_error(); + debug(83, 1) ("httpsAccept: Error allocating handle: %s\n", + ERR_error_string(ssl_error, NULL)); + return; } SSL_set_fd(ssl, newfd); @@ -2401,24 +2746,37 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details, fd_table[newfd].write_method = &ssl_write_method; debug(50, 5) ("httpsAccept: FD %d accepted, starting SSL negotiation.\n", newfd); fd_note(newfd, "client https connect"); - + connState = connStateCreate(&details->peer, &details->me, newfd, (http_port_list *)s); connState->port = (http_port_list *)cbdataReference(s); comm_add_close_handler(newfd, connStateFree, connState); + if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS); + fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS); + commSetTimeout(newfd, Config.Timeout.request, requestTimeout, connState); + #if USE_IDENT + ACLChecklist identChecklist; + identChecklist.src_addr = details->peer.sin_addr; + identChecklist.my_addr = details->me.sin_addr; + identChecklist.my_port = ntohs(details->me.sin_port); + if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) - identStart(&details->me, &details->peer, clientIdentDone, connState); + identStart(&details->me, &details->peer, clientIdentDone, connState); + #endif + commSetSelect(newfd, COMM_SELECT_READ, clientNegotiateSSL, connState, 0); + commSetDefer(newfd, clientReadDefer, connState); + clientdbEstablished(details->peer.sin_addr, 1); + incoming_sockets_accepted++; } @@ -2430,30 +2788,38 @@ clientHttpConnectionsOpen(void) { http_port_list *s; int fd; + for (s = Config.Sockaddr.http; s; s = s->next) { - if (MAXHTTPPORTS == NHttpSockets) { - debug(1, 1) ("WARNING: You have too many 'http_port' lines.\n"); - debug(1, 1) (" The limit is %d\n", MAXHTTPPORTS); - continue; - } - enter_suid(); - fd = comm_open(SOCK_STREAM, - 0, - s->s.sin_addr, - ntohs(s->s.sin_port), COMM_NONBLOCKING, "HTTP Socket"); - leave_suid(); - if (fd < 0) - continue; - comm_listen(fd); - comm_accept(fd, httpAccept, s); - /* - * We need to set a defer handler here so that we don't - * peg the CPU with select() when we hit the FD limit. - */ - commSetDefer(fd, httpAcceptDefer, NULL); - debug(1, 1) ("Accepting HTTP connections at %s, port %d, FD %d.\n", - inet_ntoa(s->s.sin_addr), (int) ntohs(s->s.sin_port), fd); - HttpSockets[NHttpSockets++] = fd; + if (MAXHTTPPORTS == NHttpSockets) { + debug(1, 1) ("WARNING: You have too many 'http_port' lines.\n"); + debug(1, 1) (" The limit is %d\n", MAXHTTPPORTS); + continue; + } + + enter_suid(); + fd = comm_open(SOCK_STREAM, + 0, + s->s.sin_addr, + ntohs(s->s.sin_port), COMM_NONBLOCKING, "HTTP Socket"); + leave_suid(); + + if (fd < 0) + continue; + + comm_listen(fd); + + comm_accept(fd, httpAccept, s); + + /* + * We need to set a defer handler here so that we don't + * peg the CPU with select() when we hit the FD limit. + */ + commSetDefer(fd, httpAcceptDefer, NULL); + + debug(1, 1) ("Accepting HTTP connections at %s, port %d, FD %d.\n", + inet_ntoa(s->s.sin_addr), (int) ntohs(s->s.sin_port), fd); + + HttpSockets[NHttpSockets++] = fd; } } @@ -2463,26 +2829,34 @@ clientHttpsConnectionsOpen(void) { https_port_list *s; int fd; + for (s = Config.Sockaddr.https; s; s = (https_port_list *)s->http.next) { - if (MAXHTTPPORTS == NHttpSockets) { - debug(1, 1) ("WARNING: You have too many 'https_port' lines.\n"); - debug(1, 1) (" The limit is %d\n", MAXHTTPPORTS); - continue; - } - enter_suid(); - fd = comm_open(SOCK_STREAM, - 0, - s->http.s.sin_addr, - ntohs(s->http.s.sin_port), COMM_NONBLOCKING, "HTTPS Socket"); - leave_suid(); - if (fd < 0) - continue; - comm_listen(fd); - comm_accept(fd, httpsAccept, s); - commSetDefer(fd, httpAcceptDefer, NULL); - debug(1, 1) ("Accepting HTTPS connections at %s, port %d, FD %d.\n", - inet_ntoa(s->http.s.sin_addr), (int) ntohs(s->http.s.sin_port), fd); - HttpSockets[NHttpSockets++] = fd; + if (MAXHTTPPORTS == NHttpSockets) { + debug(1, 1) ("WARNING: You have too many 'https_port' lines.\n"); + debug(1, 1) (" The limit is %d\n", MAXHTTPPORTS); + continue; + } + + enter_suid(); + fd = comm_open(SOCK_STREAM, + 0, + s->http.s.sin_addr, + ntohs(s->http.s.sin_port), COMM_NONBLOCKING, "HTTPS Socket"); + leave_suid(); + + if (fd < 0) + continue; + + comm_listen(fd); + + comm_accept(fd, httpsAccept, s); + + commSetDefer(fd, httpAcceptDefer, NULL); + + debug(1, 1) ("Accepting HTTPS connections at %s, port %d, FD %d.\n", + inet_ntoa(s->http.s.sin_addr), (int) ntohs(s->http.s.sin_port), fd); + + HttpSockets[NHttpSockets++] = fd; } } @@ -2493,23 +2867,27 @@ clientOpenListenSockets(void) { clientHttpConnectionsOpen(); #if USE_SSL + clientHttpsConnectionsOpen(); #endif + if (NHttpSockets < 1) - fatal("Cannot open HTTP Port"); + fatal("Cannot open HTTP Port"); } void clientHttpConnectionsClose(void) { int i; + for (i = 0; i < NHttpSockets; i++) { - if (HttpSockets[i] >= 0) { - debug(1, 1) ("FD %d Closing HTTP connection\n", HttpSockets[i]); - comm_close(HttpSockets[i]); - HttpSockets[i] = -1; - } + if (HttpSockets[i] >= 0) { + debug(1, 1) ("FD %d Closing HTTP connection\n", HttpSockets[i]); + comm_close(HttpSockets[i]); + HttpSockets[i] = -1; + } } + NHttpSockets = 0; } @@ -2519,55 +2897,62 @@ varyEvaluateMatch(StoreEntry * entry, request_t * request) const char *vary = request->vary_headers; int has_vary = httpHeaderHas(&entry->getReply()->header, HDR_VARY); #if X_ACCELERATOR_VARY + has_vary |= - httpHeaderHas(&entry->getReply()->header, HDR_X_ACCELERATOR_VARY); + httpHeaderHas(&entry->getReply()->header, HDR_X_ACCELERATOR_VARY); #endif + if (!has_vary || !entry->mem_obj->vary_headers) { - if (vary) { - /* Oops... something odd is going on here.. */ - debug(33, - 1) - ("varyEvaluateMatch: Oops. Not a Vary object on second attempt, '%s' '%s'\n", - entry->mem_obj->url, vary); - safe_free(request->vary_headers); - return VARY_CANCEL; - } - if (!has_vary) { - /* This is not a varying object */ - return VARY_NONE; - } - /* virtual "vary" object found. Calculate the vary key and - * continue the search - */ - vary = httpMakeVaryMark(request, entry->getReply()); - if (vary) { - request->vary_headers = xstrdup(vary); - return VARY_OTHER; - } else { - /* Ouch.. we cannot handle this kind of variance */ - /* XXX This cannot really happen, but just to be complete */ - return VARY_CANCEL; - } + if (vary) { + /* Oops... something odd is going on here.. */ + debug(33, + 1) + ("varyEvaluateMatch: Oops. Not a Vary object on second attempt, '%s' '%s'\n", + entry->mem_obj->url, vary); + safe_free(request->vary_headers); + return VARY_CANCEL; + } + + if (!has_vary) { + /* This is not a varying object */ + return VARY_NONE; + } + + /* virtual "vary" object found. Calculate the vary key and + * continue the search + */ + vary = httpMakeVaryMark(request, entry->getReply()); + + if (vary) { + request->vary_headers = xstrdup(vary); + return VARY_OTHER; + } else { + /* Ouch.. we cannot handle this kind of variance */ + /* XXX This cannot really happen, but just to be complete */ + return VARY_CANCEL; + } } else { - if (!vary) { - vary = httpMakeVaryMark(request, entry->getReply()); - if (vary) - request->vary_headers = xstrdup(vary); - } - if (!vary) { - /* Ouch.. we cannot handle this kind of variance */ - /* XXX This cannot really happen, but just to be complete */ - return VARY_CANCEL; - } else if (strcmp(vary, entry->mem_obj->vary_headers) == 0) { - return VARY_MATCH; - } else { - /* Oops.. we have already been here and still haven't - * found the requested variant. Bail out - */ - debug(33, 1) ("varyEvaluateMatch: Oops. Not a Vary match on second attempt, '%s' '%s'\n", - entry->mem_obj->url, vary); - return VARY_CANCEL; - } + if (!vary) { + vary = httpMakeVaryMark(request, entry->getReply()); + + if (vary) + request->vary_headers = xstrdup(vary); + } + + if (!vary) { + /* Ouch.. we cannot handle this kind of variance */ + /* XXX This cannot really happen, but just to be complete */ + return VARY_CANCEL; + } else if (strcmp(vary, entry->mem_obj->vary_headers) == 0) { + return VARY_MATCH; + } else { + /* Oops.. we have already been here and still haven't + * found the requested variant. Bail out + */ + debug(33, 1) ("varyEvaluateMatch: Oops. Not a Vary match on second attempt, '%s' '%s'\n", + entry->mem_obj->url, vary); + return VARY_CANCEL; + } } } @@ -2589,8 +2974,9 @@ clientAclChecklistCreate(const acl_access * acl, const clientHttpRequest * http) * connection B) they are internal - any limiting on them should be done on * the server end. */ + if (conn) - ch->conn(cbdataReference(conn)); /* unreferenced in acl.cc */ + ch->conn(cbdataReference(conn)); /* unreferenced in acl.cc */ return ch; } diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index 971dc81fc7..5317832707 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side_reply.cc,v 1.40 2003/02/19 21:23:51 robertc Exp $ + * $Id: client_side_reply.cc,v 1.41 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 88 Client-side Reply Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -50,11 +50,14 @@ static STCB clientHandleIMSReply; static STCB clientSendMoreData; -class clientReplyContext : public StoreClient { + +class clientReplyContext : public StoreClient +{ + public: void *operator new (size_t byteCount); void operator delete (void *address); - + void saveState(clientHttpRequest *); void restoreState(clientHttpRequest *); void purgeRequest (); @@ -71,13 +74,13 @@ public: void identifyFoundObject(StoreEntry *entry); int storeOKTransferDone() const; int storeNotOKTransferDone() const; - + http_status purgeStatus; /* state variable - replace with class to handle storeentries at some point */ int lookingforstore; virtual void created (StoreEntry *newEntry); - + clientHttpRequest *http; int headers_sz; store_client *sc; /* The store_client we're using */ @@ -88,14 +91,24 @@ public: off_t reqofs; char tempbuf[HTTP_REQBUF_SZ]; /* a temporary buffer if we need working storage */ #if USE_CACHE_DIGESTS + const char *lookup_type; /* temporary hack: storeGet() result: HIT/MISS/NONE */ #endif - struct { - int storelogiccomplete:1; - int complete:1; /* we have read all we can from upstream */ - bool headersSent; - } flags; + + struct + { + +int storelogiccomplete: + 1; + +int complete: + 1; /* we have read all we can from upstream */ + bool headersSent; + } + + flags; clientStreamNode *ourNode; /* This will go away if/when this file gets refactored some more */ + private: friend void clientSendMoreData(void *data, StoreIOBuffer result); friend void clientHandleIMSReply(void *data, StoreIOBuffer result); @@ -127,18 +140,19 @@ static void clientProcessMiss(clientReplyContext *); static STCB clientCacheHit; static void clientProcessOnlyIfCachedMiss(clientReplyContext *); static int clientGetsOldEntry(StoreEntry *, StoreEntry * old, - request_t * request); + request_t * request); static int modifiedSince(StoreEntry *, request_t *); static void clientTraceReply(clientStreamNode *, clientReplyContext *); static StoreEntry *clientCreateStoreEntry(clientReplyContext *, method_t, - request_flags); + request_flags); static void clientRemoveStoreReference(clientReplyContext *, store_client **, - StoreEntry **); + StoreEntry **); extern "C" CSS clientReplyStatus; extern ErrorState *clientBuildError(err_type, http_status, char const *, - struct in_addr *, request_t *); + + struct in_addr *, request_t *); static void startError(clientReplyContext * context, clientHttpRequest * http, ErrorState * err); static void triggerInitialStoreReadWithClientParameters(clientReplyContext * context, clientHttpRequest * http); @@ -172,27 +186,33 @@ clientReplyNewContext(clientHttpRequest * clientContext) /* create an error in the store awaiting the client side to read it. */ void clientSetReplyToError(void *data, - err_type err, http_status status, method_t method, char const *uri, - struct in_addr *addr, request_t * failedrequest, char *unparsedrequest, - auth_user_request_t * auth_user_request) + err_type err, http_status status, method_t method, char const *uri, + + struct in_addr *addr, request_t * failedrequest, char *unparsedrequest, + auth_user_request_t * auth_user_request) { clientReplyContext *context = (clientReplyContext *)data; ErrorState *errstate = - clientBuildError(err, status, uri, addr, failedrequest); + clientBuildError(err, status, uri, addr, failedrequest); + if (unparsedrequest) - errstate->request_hdrs = xstrdup(unparsedrequest); + errstate->request_hdrs = xstrdup(unparsedrequest); if (status == HTTP_NOT_IMPLEMENTED && context->http->request) - /* prevent confusion over whether we default to persistent or not */ - context->http->request->flags.proxy_keepalive = 0; + /* prevent confusion over whether we default to persistent or not */ + context->http->request->flags.proxy_keepalive = 0; + context->http->al.http.code = errstate->httpStatus; context->http->entry = - clientCreateStoreEntry(context, method, request_flags()); - if (auth_user_request) { - errstate->auth_user_request = auth_user_request; - authenticateAuthUserRequestLock(errstate->auth_user_request); + clientCreateStoreEntry(context, method, request_flags()); + + if (auth_user_request) + { + errstate->auth_user_request = auth_user_request; + authenticateAuthUserRequestLock(errstate->auth_user_request); } + assert(errstate->callback_data == NULL); errorAppendEntry(context->http->entry, errstate); /* Now the caller reads to get this */ @@ -200,15 +220,16 @@ clientSetReplyToError(void *data, void clientRemoveStoreReference(clientReplyContext * context, store_client ** scp, - StoreEntry ** ep) + StoreEntry ** ep) { StoreEntry *e; store_client *sc = *scp; + if ((e = *ep) != NULL) { - *ep = NULL; - storeUnregister(sc, e, context); - *scp = NULL; - storeUnlockObject(e); + *ep = NULL; + storeUnregister(sc, e, context); + *scp = NULL; + storeUnlockObject(e); } } @@ -271,10 +292,10 @@ startError(clientReplyContext * context, clientHttpRequest * http, ErrorState * clientStreamNode * clientReplyContext::getNextNode() const { - return (clientStreamNode *)ourNode->node.next->data; + return (clientStreamNode *)ourNode->node.next->data; } -/* This function is wrong - the client parameters don't include the +/* This function is wrong - the client parameters don't include the * header offset */ void @@ -310,10 +331,12 @@ clientProcessExpired(clientReplyContext * context) * @?@: Instead of a 504 (Gateway Timeout) reply, we may want to return * a stale entry *if* it matches client requirements */ + if (clientOnlyIfCached(http)) { - clientProcessOnlyIfCachedMiss(context); - return; + clientProcessOnlyIfCachedMiss(context); + return; } + http->request->flags.refresh = 1; #if STORE_CLIENT_LIST_DEBUG /* Prevent a race with the store client memory free routines @@ -323,30 +346,33 @@ clientProcessExpired(clientReplyContext * context) /* Prepare to make a new temporary request */ context->saveState(http); entry = storeCreateEntry(url, - http->log_uri, http->request->flags, http->request->method); + http->log_uri, http->request->flags, http->request->method); /* NOTE, don't call storeLockObject(), storeCreateEntry() does it */ context->sc = storeClientListAdd(entry, context); #if DELAY_POOLS /* delay_id is already set on original store client */ context->sc->setDelayId(DelayId::DelayClient(http)); #endif + http->request->lastmod = http->old_entry->lastmod; debug(88, 5)("clientProcessExpired : lastmod %ld", - (long int) entry->lastmod); + (long int) entry->lastmod); http->entry = entry; assert(http->out.offset == 0); fwdStart(http->conn ? http->conn->fd : -1, http->entry, http->request); /* Register with storage manager to receive updates when data comes in. */ + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) - debug(88, 0) ("clientProcessExpired: Found ENTRY_ABORTED object"); + debug(88, 0) ("clientProcessExpired: Found ENTRY_ABORTED object"); + { - StoreIOBuffer tempBuffer; - /* start counting the length from 0 */ - tempBuffer.offset = 0; - tempBuffer.length = HTTP_REQBUF_SZ; - tempBuffer.data = context->tempbuf; - storeClientCopy(context->sc, entry, - tempBuffer, clientHandleIMSReply, context); + StoreIOBuffer tempBuffer; + /* start counting the length from 0 */ + tempBuffer.offset = 0; + tempBuffer.length = HTTP_REQBUF_SZ; + tempBuffer.data = context->tempbuf; + storeClientCopy(context->sc, entry, + tempBuffer, clientHandleIMSReply, context); } } @@ -356,61 +382,72 @@ modifiedSince(StoreEntry * entry, request_t * request) int object_length; time_t mod_time = entry->lastmod; debug(88, 3) ("modifiedSince: '%s'\n", storeUrl(entry)); + if (mod_time < 0) - mod_time = entry->timestamp; + mod_time = entry->timestamp; + debug(88, 3) ("modifiedSince: mod_time = %ld\n", (long int) mod_time); + if (mod_time < 0) - return 1; + return 1; + /* Find size of the object */ object_length = entry->getReply()->content_length; + if (object_length < 0) - object_length = contentLen(entry); + object_length = contentLen(entry); + if (mod_time > request->ims) { - debug(88, 3) ("--> YES: entry newer than client\n"); - return 1; + debug(88, 3) ("--> YES: entry newer than client\n"); + return 1; } else if (mod_time < request->ims) { - debug(88, 3) ("--> NO: entry older than client\n"); - return 0; + debug(88, 3) ("--> NO: entry older than client\n"); + return 0; } else if (request->imslen < 0) { - debug(88, 3) ("--> NO: same LMT, no client length\n"); - return 0; + debug(88, 3) ("--> NO: same LMT, no client length\n"); + return 0; } else if (request->imslen == object_length) { - debug(88, 3) ("--> NO: same LMT, same length\n"); - return 0; + debug(88, 3) ("--> NO: same LMT, same length\n"); + return 0; } else { - debug(88, 3) ("--> YES: same LMT, different length\n"); - return 1; + debug(88, 3) ("--> YES: same LMT, different length\n"); + return 1; } } static int clientGetsOldEntry(StoreEntry * new_entry, StoreEntry * old_entry, - request_t * request) + request_t * request) { const http_status status = new_entry->getReply()->sline.status; + if (0 == status) { - debug(88, 5) ("clientGetsOldEntry: YES, broken HTTP reply\n"); - return 1; + debug(88, 5) ("clientGetsOldEntry: YES, broken HTTP reply\n"); + return 1; } + /* If the reply is a failure then send the old object as a last * resort */ if (status >= 500 && status < 600) { - debug(88, 3) ("clientGetsOldEntry: YES, failure reply=%d\n", status); - return 1; + debug(88, 3) ("clientGetsOldEntry: YES, failure reply=%d\n", status); + return 1; } + /* If the reply is anything but "Not Modified" then * we must forward it to the client */ if (HTTP_NOT_MODIFIED != status) { - debug(88, 5) ("clientGetsOldEntry: NO, reply=%d\n", status); - return 0; + debug(88, 5) ("clientGetsOldEntry: NO, reply=%d\n", status); + return 0; } + /* If the client did not send IMS in the request, then it * must get the old object, not this "Not Modified" reply * REGARDLESS of validation */ if (!request->flags.ims) { - debug(88, 5) ("clientGetsOldEntry: YES, no client IMS\n"); - return 1; + debug(88, 5) ("clientGetsOldEntry: YES, no client IMS\n"); + return 1; } + /* If key metadata in the reply are not consistent with the * old entry, we must use the new reply. * Note: this means that the server is sending garbage replies @@ -420,18 +457,20 @@ clientGetsOldEntry(StoreEntry * new_entry, StoreEntry * old_entry, * Can we guarantee we don't need it elsewhere? */ if (!httpReplyValidatorsMatch(new_entry->getReply(), - old_entry->getReply())) { - debug(88, 5) ("clientGetsOldEntry: NO, Old object has been invalidated" - "by the new one\n"); - return 0; + old_entry->getReply())) { + debug(88, 5) ("clientGetsOldEntry: NO, Old object has been invalidated" + "by the new one\n"); + return 0; } + /* If the client IMS time is prior to the entry LASTMOD time we * need to send the old object */ if (modifiedSince(old_entry, request)) { - debug(88, 5) ("clientGetsOldEntry: YES, modified since %ld\n", - (long int) request->ims); - return 1; + debug(88, 5) ("clientGetsOldEntry: YES, modified since %ld\n", + (long int) request->ims); + return 1; } + debug(88, 5) ("clientGetsOldEntry: NO, new one is fine\n"); return 0; } @@ -466,142 +505,167 @@ clientHandleIMSReply(void *data, StoreIOBuffer result) StoreEntry *oldentry; http_status status; debug(88, 3) ("clientHandleIMSReply: %s, %lu bytes\n", url, - (long unsigned) result.length); + (long unsigned) result.length); + if (entry == NULL) { - return; + return; } + if (result.flags.error && !EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - return; + return; } + /* update size of the request */ context->reqsize = result.length + context->reqofs; + status = entry->getReply()->sline.status; + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - debug(88, 3) ("clientHandleIMSReply: ABORTED '%s'\n", url); - /* We have an existing entry, but failed to validate it */ - /* Its okay to send the old one anyway */ - http->logType = LOG_TCP_REFRESH_FAIL_HIT; - clientRemoveStoreReference(context, &context->sc, &entry); - /* Get the old request back */ - context->restoreState(http); - entry = http->entry; - return; + debug(88, 3) ("clientHandleIMSReply: ABORTED '%s'\n", url); + /* We have an existing entry, but failed to validate it */ + /* Its okay to send the old one anyway */ + http->logType = LOG_TCP_REFRESH_FAIL_HIT; + clientRemoveStoreReference(context, &context->sc, &entry); + /* Get the old request back */ + context->restoreState(http); + entry = http->entry; + return; } + if (STORE_PENDING == entry->store_status && 0 == status) { - /* more headers needed to decide */ - debug(88, 3) ("clientHandleIMSReply: Incomplete headers for '%s'\n", - url); - if (result.length + context->reqsize >= HTTP_REQBUF_SZ) { - /* will not get any bigger than that */ - debug(88, 3) - ("clientHandleIMSReply: Reply is too large '%s', using old entry\n", - url); - /* use old entry, this repeats the code abovez */ - http->logType = LOG_TCP_REFRESH_FAIL_HIT; - clientRemoveStoreReference(context, &context->sc, &entry); - entry = http->entry = http->old_entry; - /* Get the old request back */ - context->restoreState(http); - entry = http->entry; - } else { - context->reqofs += result.length; - context->waitForMoreData(result); - } - return; + /* more headers needed to decide */ + debug(88, 3) ("clientHandleIMSReply: Incomplete headers for '%s'\n", + url); + + if (result.length + context->reqsize >= HTTP_REQBUF_SZ) { + /* will not get any bigger than that */ + debug(88, 3) + ("clientHandleIMSReply: Reply is too large '%s', using old entry\n", + url); + /* use old entry, this repeats the code abovez */ + http->logType = LOG_TCP_REFRESH_FAIL_HIT; + clientRemoveStoreReference(context, &context->sc, &entry); + entry = http->entry = http->old_entry; + /* Get the old request back */ + context->restoreState(http); + entry = http->entry; + } else { + context->reqofs += result.length; + context->waitForMoreData(result); + } + + return; } + if (clientGetsOldEntry(entry, http->old_entry, http->request)) { - /* We initiated the IMS request and the IMS is compatible with - * our object. As the client is not expecting - * 304, so put the good one back. First, make sure the old entry - * headers have been loaded from disk. */ - clientStreamNode *next = (clientStreamNode *)context->http->client_stream.head->next->data; - StoreIOBuffer tempresult; - oldentry = http->old_entry; - http->logType = LOG_TCP_REFRESH_HIT; - if (httpReplyValidatorsMatch(entry->getReply(), - http->old_entry->getReply())) { - if (oldentry->mem_obj->request == NULL) { - oldentry->mem_obj->request = requestLink(entry->mem_obj->request); - unlink_request = 1; - } - /* Don't memcpy() the whole reply structure here. For example, - * www.thegist.com (Netscape/1.13) returns a content-length for - * 304's which seems to be the length of the 304 HEADERS!!! and - * not the body they refer to. */ - httpReplyUpdateOnNotModified((HttpReply *)oldentry->getReply(), entry->getReply()); - storeTimestampsSet(oldentry); - clientRemoveStoreReference(context, &context->sc, &entry); - oldentry->timestamp = squid_curtime; - if (unlink_request) { - requestUnlink(oldentry->mem_obj->request); - oldentry->mem_obj->request = NULL; - } - } - /* Get the old request back */ - context->restoreState(http); - entry = http->entry; - /* here the data to send is in the next nodes buffers already */ - assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED)); - tempresult.length = context->reqsize; - tempresult.data = next->readBuffer.data; - clientSendMoreData(context, tempresult); - return; + /* We initiated the IMS request and the IMS is compatible with + * our object. As the client is not expecting + * 304, so put the good one back. First, make sure the old entry + * headers have been loaded from disk. */ + clientStreamNode *next = (clientStreamNode *)context->http->client_stream.head->next->data; + StoreIOBuffer tempresult; + oldentry = http->old_entry; + http->logType = LOG_TCP_REFRESH_HIT; + + if (httpReplyValidatorsMatch(entry->getReply(), + http->old_entry->getReply())) { + if (oldentry->mem_obj->request == NULL) { + oldentry->mem_obj->request = requestLink(entry->mem_obj->request); + unlink_request = 1; + } + + /* Don't memcpy() the whole reply structure here. For example, + * www.thegist.com (Netscape/1.13) returns a content-length for + * 304's which seems to be the length of the 304 HEADERS!!! and + * not the body they refer to. */ + httpReplyUpdateOnNotModified((HttpReply *)oldentry->getReply(), entry->getReply()); + + storeTimestampsSet(oldentry); + + clientRemoveStoreReference(context, &context->sc, &entry); + + oldentry->timestamp = squid_curtime; + + if (unlink_request) { + requestUnlink(oldentry->mem_obj->request); + oldentry->mem_obj->request = NULL; + } + } + + /* Get the old request back */ + context->restoreState(http); + + entry = http->entry; + + /* here the data to send is in the next nodes buffers already */ + assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED)); + + tempresult.length = context->reqsize; + + tempresult.data = next->readBuffer.data; + + clientSendMoreData(context, tempresult); + + return; } else { - /* The client gets the new entry, - * either as a 304 (they initiated the IMS) or - * as a full request from the upstream - * The new entry is *not* a 304 reply, or - * is a 304 that is incompatible with our cached entities. - */ - if (http->request->flags.ims) { - /* The client asked for a IMS, and can deal - * with any reply - * XXX TODO: invalidate our object if it's not valid any more. - * Send the IMS reply to the client. - */ - context->sendClientUpstreamResponse(); - } else if (httpReplyValidatorsMatch (entry->getReply(), - http->old_entry->getReply())) { - /* Our object is usable once updated */ - /* the client did not ask for IMS, send the whole object - */ - /* the client needs to get this reply */ - StoreIOBuffer tempresult; - http->logType = LOG_TCP_REFRESH_MISS; - if (HTTP_NOT_MODIFIED == entry->getReply()->sline.status) { - httpReplyUpdateOnNotModified((HttpReply *)http->old_entry->getReply(), - entry->getReply()); - storeTimestampsSet(http->old_entry); - http->logType = LOG_TCP_REFRESH_HIT; - } - clientRemoveStoreReference(context, &context->old_sc, &http->old_entry); - /* here the data to send is the data we just recieved */ - context->tempBuffer.offset = 0; - context->old_reqsize = 0; - /* clientSendMoreData tracks the offset as well. - * Force it back to zero */ - context->reqofs = 0; - assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED)); - /* TODO: provide SendMoreData with the ready parsed reply */ - tempresult.length = context->reqsize; - tempresult.data = context->tempbuf; - clientSendMoreData(context, tempresult); - } else { - /* the client asked for the whole object, and - * 1) our object was stale - * 2) our internally generated IMS failed to validate - * 3) the server sent incompatible headers in it's reply - */ - http->logType = LOG_TCP_REFRESH_MISS; - clientProcessMiss(context); - /* We start over for everything except IMS because: - * 1) HEAD requests will go straight through now - * 2) GET requests will go straight through now - * 3) IMS requests are a corner case. If the server - * decided to give us different data, we should give - * that to the client, which means returning our IMS request. - */ - } + /* The client gets the new entry, + * either as a 304 (they initiated the IMS) or + * as a full request from the upstream + * The new entry is *not* a 304 reply, or + * is a 304 that is incompatible with our cached entities. + */ + + if (http->request->flags.ims) { + /* The client asked for a IMS, and can deal + * with any reply + * XXX TODO: invalidate our object if it's not valid any more. + * Send the IMS reply to the client. + */ + context->sendClientUpstreamResponse(); + } else if (httpReplyValidatorsMatch (entry->getReply(), + http->old_entry->getReply())) { + /* Our object is usable once updated */ + /* the client did not ask for IMS, send the whole object + */ + /* the client needs to get this reply */ + StoreIOBuffer tempresult; + http->logType = LOG_TCP_REFRESH_MISS; + + if (HTTP_NOT_MODIFIED == entry->getReply()->sline.status) { + httpReplyUpdateOnNotModified((HttpReply *)http->old_entry->getReply(), + entry->getReply()); + storeTimestampsSet(http->old_entry); + http->logType = LOG_TCP_REFRESH_HIT; + } + + clientRemoveStoreReference(context, &context->old_sc, &http->old_entry); + /* here the data to send is the data we just recieved */ + context->tempBuffer.offset = 0; + context->old_reqsize = 0; + /* clientSendMoreData tracks the offset as well. + * Force it back to zero */ + context->reqofs = 0; + assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED)); + /* TODO: provide SendMoreData with the ready parsed reply */ + tempresult.length = context->reqsize; + tempresult.data = context->tempbuf; + clientSendMoreData(context, tempresult); + } else { + /* the client asked for the whole object, and + * 1) our object was stale + * 2) our internally generated IMS failed to validate + * 3) the server sent incompatible headers in it's reply + */ + http->logType = LOG_TCP_REFRESH_MISS; + clientProcessMiss(context); + /* We start over for everything except IMS because: + * 1) HEAD requests will go straight through now + * 2) GET requests will go straight through now + * 3) IMS requests are a corner case. If the server + * decided to give us different data, we should give + * that to the client, which means returning our IMS request. + */ + } } } @@ -623,180 +687,198 @@ clientCacheHit(void *data, StoreIOBuffer result) StoreEntry *e = http->entry; request_t *r = http->request; debug(88, 3) ("clientCacheHit: %s, %ud bytes\n", http->uri, (unsigned int)result.length); + if (http->entry == NULL) { - debug(88, 3) ("clientCacheHit: request aborted\n"); - return; + debug(88, 3) ("clientCacheHit: request aborted\n"); + return; } else if (result.flags.error) { - /* swap in failure */ - debug(88, 3) ("clientCacheHit: swapin failure for %s\n", http->uri); - http->logType = LOG_TCP_SWAPFAIL_MISS; - clientRemoveStoreReference(context, &context->sc, &http->entry); - clientProcessMiss(context); - return; + /* swap in failure */ + debug(88, 3) ("clientCacheHit: swapin failure for %s\n", http->uri); + http->logType = LOG_TCP_SWAPFAIL_MISS; + clientRemoveStoreReference(context, &context->sc, &http->entry); + clientProcessMiss(context); + return; } + if (result.length == 0) { - /* the store couldn't get enough data from the file for us to id the - * object - */ - /* treat as a miss */ - http->logType = LOG_TCP_MISS; - clientProcessMiss(context); - return; + /* the store couldn't get enough data from the file for us to id the + * object + */ + /* treat as a miss */ + http->logType = LOG_TCP_MISS; + clientProcessMiss(context); + return; } + assert(!EBIT_TEST(e->flags, ENTRY_ABORTED)); /* update size of the request */ context->reqsize = result.length + context->reqofs; + if (e->getReply()->sline.status == 0) { - /* - * we don't have full reply headers yet; either wait for more or - * punt to clientProcessMiss. - */ - if (e->mem_status == IN_MEMORY || e->store_status == STORE_OK) { - clientProcessMiss(context); - } else if (result.length + context->reqofs >= HTTP_REQBUF_SZ - && http->out.offset == 0) { - clientProcessMiss(context); - } else { - clientStreamNode *next; - StoreIOBuffer tempBuffer; - debug(88, 3) ("clientCacheHit: waiting for HTTP reply headers\n"); - context->reqofs += result.length; - assert(context->reqofs <= HTTP_REQBUF_SZ); - /* get the next users' buffer */ - /* FIXME: HTTP_REQBUF_SZ must be wrong here ??! - */ - next = (clientStreamNode *)context->http->client_stream.head->next->data; - tempBuffer.offset = http->out.offset + context->reqofs; - tempBuffer.length = HTTP_REQBUF_SZ; - tempBuffer.data = next->readBuffer.data + context->reqofs; - storeClientCopy(context->sc, e, - tempBuffer, clientCacheHit, context); - } - return; + /* + * we don't have full reply headers yet; either wait for more or + * punt to clientProcessMiss. + */ + + if (e->mem_status == IN_MEMORY || e->store_status == STORE_OK) { + clientProcessMiss(context); + } else if (result.length + context->reqofs >= HTTP_REQBUF_SZ + && http->out.offset == 0) { + clientProcessMiss(context); + } else { + clientStreamNode *next; + StoreIOBuffer tempBuffer; + debug(88, 3) ("clientCacheHit: waiting for HTTP reply headers\n"); + context->reqofs += result.length; + assert(context->reqofs <= HTTP_REQBUF_SZ); + /* get the next users' buffer */ + /* FIXME: HTTP_REQBUF_SZ must be wrong here ??! + */ + next = (clientStreamNode *)context->http->client_stream.head->next->data; + tempBuffer.offset = http->out.offset + context->reqofs; + tempBuffer.length = HTTP_REQBUF_SZ; + tempBuffer.data = next->readBuffer.data + context->reqofs; + storeClientCopy(context->sc, e, + tempBuffer, clientCacheHit, context); + } + + return; } + /* * Got the headers, now grok them */ assert(http->logType == LOG_TCP_HIT); + switch (varyEvaluateMatch(e, r)) { + case VARY_NONE: - /* No variance detected. Continue as normal */ - break; + /* No variance detected. Continue as normal */ + break; + case VARY_MATCH: - /* This is the correct entity for this request. Continue */ - debug(88, 2) ("clientProcessHit: Vary MATCH!\n"); - break; + /* This is the correct entity for this request. Continue */ + debug(88, 2) ("clientProcessHit: Vary MATCH!\n"); + break; + case VARY_OTHER: - /* This is not the correct entity for this request. We need - * to requery the cache. - */ - clientRemoveStoreReference(context, &context->sc, &http->entry); - e = NULL; - /* Note: varyEvalyateMatch updates the request with vary information - * so we only get here once. (it also takes care of cancelling loops) - */ - debug(88, 2) ("clientProcessHit: Vary detected!\n"); - clientGetMoreData(context->ourNode, http); - return; + /* This is not the correct entity for this request. We need + * to requery the cache. + */ + clientRemoveStoreReference(context, &context->sc, &http->entry); + e = NULL; + /* Note: varyEvalyateMatch updates the request with vary information + * so we only get here once. (it also takes care of cancelling loops) + */ + debug(88, 2) ("clientProcessHit: Vary detected!\n"); + clientGetMoreData(context->ourNode, http); + return; + case VARY_CANCEL: - /* varyEvaluateMatch found a object loop. Process as miss */ - debug(88, 1) ("clientProcessHit: Vary object loop!\n"); - clientProcessMiss(context); - return; + /* varyEvaluateMatch found a object loop. Process as miss */ + debug(88, 1) ("clientProcessHit: Vary object loop!\n"); + clientProcessMiss(context); + return; } + if (r->method == METHOD_PURGE) { - clientRemoveStoreReference(context, &context->sc, &http->entry); - e = NULL; - context->purgeRequest(); - return; + clientRemoveStoreReference(context, &context->sc, &http->entry); + e = NULL; + context->purgeRequest(); + return; } + if (storeCheckNegativeHit(e)) { - http->logType = LOG_TCP_NEGATIVE_HIT; - clientSendMoreData(context, result); + http->logType = LOG_TCP_NEGATIVE_HIT; + clientSendMoreData(context, result); } else if (!Config.onoff.offline && refreshCheckHTTP(e, r) && !http->flags.internal) { - debug(88, 5) ("clientCacheHit: in refreshCheck() block\n"); - /* - * We hold a stale copy; it needs to be validated - */ - /* - * The 'need_validation' flag is used to prevent forwarding - * loops between siblings. If our copy of the object is stale, - * then we should probably only use parents for the validation - * request. Otherwise two siblings could generate a loop if - * both have a stale version of the object. - */ - r->flags.need_validation = 1; - if (e->lastmod < 0) { - /* - * Previous reply didn't have a Last-Modified header, - * we cannot revalidate it. - */ - http->logType = LOG_TCP_MISS; - clientProcessMiss(context); - } else if (r->flags.nocache) { - /* - * This did not match a refresh pattern that overrides no-cache - * we should honour the client no-cache header. - */ - http->logType = LOG_TCP_CLIENT_REFRESH_MISS; - clientProcessMiss(context); - } else if (r->protocol == PROTO_HTTP) { - /* - * Object needs to be revalidated - * XXX This could apply to FTP as well, if Last-Modified is known. - */ - http->logType = LOG_TCP_REFRESH_MISS; - clientProcessExpired(context); - } else { - /* - * We don't know how to re-validate other protocols. Handle - * them as if the object has expired. - */ - http->logType = LOG_TCP_MISS; - clientProcessMiss(context); - } + debug(88, 5) ("clientCacheHit: in refreshCheck() block\n"); + /* + * We hold a stale copy; it needs to be validated + */ + /* + * The 'need_validation' flag is used to prevent forwarding + * loops between siblings. If our copy of the object is stale, + * then we should probably only use parents for the validation + * request. Otherwise two siblings could generate a loop if + * both have a stale version of the object. + */ + r->flags.need_validation = 1; + + if (e->lastmod < 0) { + /* + * Previous reply didn't have a Last-Modified header, + * we cannot revalidate it. + */ + http->logType = LOG_TCP_MISS; + clientProcessMiss(context); + } else if (r->flags.nocache) { + /* + * This did not match a refresh pattern that overrides no-cache + * we should honour the client no-cache header. + */ + http->logType = LOG_TCP_CLIENT_REFRESH_MISS; + clientProcessMiss(context); + } else if (r->protocol == PROTO_HTTP) { + /* + * Object needs to be revalidated + * XXX This could apply to FTP as well, if Last-Modified is known. + */ + http->logType = LOG_TCP_REFRESH_MISS; + clientProcessExpired(context); + } else { + /* + * We don't know how to re-validate other protocols. Handle + * them as if the object has expired. + */ + http->logType = LOG_TCP_MISS; + clientProcessMiss(context); + } } else if (r->flags.ims) { - /* - * Handle If-Modified-Since requests from the client - */ - if (e->getReply()->sline.status != HTTP_OK) { - debug(88, 4) ("clientCacheHit: Reply code %d != 200\n", - e->getReply()->sline.status); - http->logType = LOG_TCP_MISS; - clientProcessMiss(context); - } else if (modifiedSince(e, http->request)) { - http->logType = LOG_TCP_IMS_HIT; - clientSendMoreData(context, result); - } else { - time_t timestamp = e->timestamp; - HttpReply *temprep = httpReplyMake304 (e->getReply()); - http->logType = LOG_TCP_IMS_HIT; - clientRemoveStoreReference(context, &context->sc, &http->entry); - http->entry = e = - clientCreateStoreEntry(context, http->request->method, - request_flags()); - /* - * Copy timestamp from the original entry so the 304 - * reply has a meaningful Age: header. - */ - e->timestamp = timestamp; - httpReplySwapOut (temprep, e); - e->complete(); - /* TODO: why put this in the store and then serialise it and then parse it again. - * Simply mark the request complete in our context and - * write the reply struct to the client side - */ - triggerInitialStoreReadWithClientParameters(context, http); - } + /* + * Handle If-Modified-Since requests from the client + */ + + if (e->getReply()->sline.status != HTTP_OK) { + debug(88, 4) ("clientCacheHit: Reply code %d != 200\n", + e->getReply()->sline.status); + http->logType = LOG_TCP_MISS; + clientProcessMiss(context); + } else if (modifiedSince(e, http->request)) { + http->logType = LOG_TCP_IMS_HIT; + clientSendMoreData(context, result); + } else { + time_t timestamp = e->timestamp; + HttpReply *temprep = httpReplyMake304 (e->getReply()); + http->logType = LOG_TCP_IMS_HIT; + clientRemoveStoreReference(context, &context->sc, &http->entry); + http->entry = e = + clientCreateStoreEntry(context, http->request->method, + request_flags()); + /* + * Copy timestamp from the original entry so the 304 + * reply has a meaningful Age: header. + */ + e->timestamp = timestamp; + httpReplySwapOut (temprep, e); + e->complete(); + /* TODO: why put this in the store and then serialise it and then parse it again. + * Simply mark the request complete in our context and + * write the reply struct to the client side + */ + triggerInitialStoreReadWithClientParameters(context, http); + } } else { - /* - * plain ol' cache hit - */ - if (e->mem_status == IN_MEMORY) - http->logType = LOG_TCP_MEM_HIT; - else if (Config.onoff.offline) - http->logType = LOG_TCP_OFFLINE_HIT; - clientSendMoreData(context, result); + /* + * plain ol' cache hit + */ + + if (e->mem_status == IN_MEMORY) + http->logType = LOG_TCP_MEM_HIT; + else if (Config.onoff.offline) + http->logType = LOG_TCP_OFFLINE_HIT; + + clientSendMoreData(context, result); } } @@ -811,60 +893,70 @@ clientProcessMiss(clientReplyContext * context) request_t *r = http->request; ErrorState *err = NULL; debug(88, 4) ("clientProcessMiss: '%s %s'\n", - RequestMethodStr[r->method], url); + RequestMethodStr[r->method], url); /* * We might have a left-over StoreEntry from a failed cache hit * or IMS request. */ + if (http->entry) { - if (EBIT_TEST(http->entry->flags, ENTRY_SPECIAL)) { - debug(88, 0) ("clientProcessMiss: miss on a special object (%s).\n", - url); - debug(88, 0) ("\tlog_type = %s\n", log_tags[http->logType]); - storeEntryDump(http->entry, 1); - } - clientRemoveStoreReference(context, &context->sc, &http->entry); + if (EBIT_TEST(http->entry->flags, ENTRY_SPECIAL)) { + debug(88, 0) ("clientProcessMiss: miss on a special object (%s).\n", + url); + debug(88, 0) ("\tlog_type = %s\n", log_tags[http->logType]); + storeEntryDump(http->entry, 1); + } + + clientRemoveStoreReference(context, &context->sc, &http->entry); } + if (r->method == METHOD_PURGE) { - context->purgeRequest(); - return; + context->purgeRequest(); + return; } + if (clientOnlyIfCached(http)) { - clientProcessOnlyIfCachedMiss(context); - return; + clientProcessOnlyIfCachedMiss(context); + return; } + /* * Deny loops when running in accelerator/transproxy mode. */ if (http->flags.accel && r->flags.loopdetect) { - http->al.http.code = HTTP_FORBIDDEN; - err = - clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, - &http->conn->peer.sin_addr, http->request); - http->entry = - clientCreateStoreEntry(context, r->method, request_flags()); - errorAppendEntry(http->entry, err); - triggerInitialStoreReadWithClientParameters(context, http); - return; + http->al.http.code = HTTP_FORBIDDEN; + err = + clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, + &http->conn->peer.sin_addr, http->request); + http->entry = + clientCreateStoreEntry(context, r->method, request_flags()); + errorAppendEntry(http->entry, err); + triggerInitialStoreReadWithClientParameters(context, http); + return; } else { - assert(http->out.offset == 0); - http->entry = clientCreateStoreEntry(context, r->method, r->flags); - triggerInitialStoreReadWithClientParameters(context, http); - if (http->redirect.status) { - HttpReply *rep = httpReplyCreate(); + assert(http->out.offset == 0); + http->entry = clientCreateStoreEntry(context, r->method, r->flags); + triggerInitialStoreReadWithClientParameters(context, http); + + if (http->redirect.status) { + HttpReply *rep = httpReplyCreate(); #if LOG_TCP_REDIRECTS - http->logType = LOG_TCP_REDIRECT; + + http->logType = LOG_TCP_REDIRECT; #endif - storeReleaseRequest(http->entry); - httpRedirectReply(rep, http->redirect.status, - http->redirect.location); - httpReplySwapOut(rep, http->entry); - http->entry->complete(); - return; - } - if (http->flags.internal) - r->protocol = PROTO_INTERNAL; - fwdStart(http->conn ? http->conn->fd : -1, http->entry, r); + + storeReleaseRequest(http->entry); + httpRedirectReply(rep, http->redirect.status, + http->redirect.location); + httpReplySwapOut(rep, http->entry); + http->entry->complete(); + return; + } + + if (http->flags.internal) + r->protocol = PROTO_INTERNAL; + + fwdStart(http->conn ? http->conn->fd : -1, http->entry, r); } } @@ -882,10 +974,10 @@ clientProcessOnlyIfCachedMiss(clientReplyContext * context) request_t *r = http->request; ErrorState *err = NULL; debug(88, 4) ("clientProcessOnlyIfCachedMiss: '%s %s'\n", - RequestMethodStr[r->method], url); + RequestMethodStr[r->method], url); http->al.http.code = HTTP_GATEWAY_TIMEOUT; err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, NULL, - &http->conn->peer.sin_addr, http->request); + &http->conn->peer.sin_addr, http->request); clientRemoveStoreReference(context, &context->sc, &http->entry); startError(context, http, err); } @@ -903,77 +995,79 @@ void clientReplyContext::created(StoreEntry *newEntry) { if (lookingforstore == 1) - purgeFoundGet(newEntry); + purgeFoundGet(newEntry); else if (lookingforstore == 2) - purgeFoundHead(newEntry); + purgeFoundHead(newEntry); else if (lookingforstore == 3) - purgeDoPurgeGet(newEntry); + purgeDoPurgeGet(newEntry); else if (lookingforstore == 4) - purgeDoPurgeHead(newEntry); + purgeDoPurgeHead(newEntry); else if (lookingforstore == 5) - identifyFoundObject(newEntry); + identifyFoundObject(newEntry); } void clientReplyContext::purgeFoundGet(StoreEntry *newEntry) { if (newEntry->isNull()) { - lookingforstore = 2; - StoreEntry::getPublicByRequestMethod(this, http->request, METHOD_HEAD); + lookingforstore = 2; + StoreEntry::getPublicByRequestMethod(this, http->request, METHOD_HEAD); } else - purgeFoundObject (newEntry); + purgeFoundObject (newEntry); } void clientReplyContext::purgeFoundHead(StoreEntry *newEntry) { if (newEntry->isNull()) - purgeDoMissPurge(); + purgeDoMissPurge(); else - purgeFoundObject (newEntry); + purgeFoundObject (newEntry); } - + void clientReplyContext::purgeFoundObject(StoreEntry *entry) { assert (entry && !entry->isNull()); - StoreIOBuffer tempBuffer; - /* Swap in the metadata */ - http->entry = entry; - storeLockObject(http->entry); - storeCreateMemObject(http->entry, http->uri, http->log_uri); - http->entry->mem_obj->method = http->request->method; - sc = storeClientListAdd(http->entry, this); - http->logType = LOG_TCP_HIT; - reqofs = 0; - tempBuffer.offset = http->out.offset; - clientStreamNode *next = (clientStreamNode *)http->client_stream.head->next->data; - tempBuffer.length = next->readBuffer.length; - tempBuffer.data = next->readBuffer.data; - storeClientCopy(sc, http->entry, - tempBuffer, clientCacheHit, this); + StoreIOBuffer tempBuffer; + /* Swap in the metadata */ + http->entry = entry; + storeLockObject(http->entry); + storeCreateMemObject(http->entry, http->uri, http->log_uri); + http->entry->mem_obj->method = http->request->method; + sc = storeClientListAdd(http->entry, this); + http->logType = LOG_TCP_HIT; + reqofs = 0; + tempBuffer.offset = http->out.offset; + clientStreamNode *next = (clientStreamNode *)http->client_stream.head->next->data; + tempBuffer.length = next->readBuffer.length; + tempBuffer.data = next->readBuffer.data; + storeClientCopy(sc, http->entry, + tempBuffer, clientCacheHit, this); } void clientReplyContext::purgeRequest() { debug(88, 3) ("Config2.onoff.enable_purge = %d\n", - Config2.onoff.enable_purge); + Config2.onoff.enable_purge); + if (!Config2.onoff.enable_purge) { - http->logType = LOG_TCP_DENIED; - ErrorState *err = - clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, - &http->conn->peer.sin_addr, http->request); - startError(this, http, err); - return; + http->logType = LOG_TCP_DENIED; + ErrorState *err = + clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, + &http->conn->peer.sin_addr, http->request); + startError(this, http, err); + return; } + /* Release both IP cache */ ipcacheInvalidate(http->request->host); if (!http->flags.purging) - purgeRequestFindObjectToPurge(); + purgeRequestFindObjectToPurge(); else - purgeDoMissPurge(); + purgeDoMissPurge(); } void @@ -992,11 +1086,12 @@ clientReplyContext::purgeDoPurgeGet(StoreEntry *newEntry) purgeStatus = HTTP_NOT_FOUND; if (!newEntry->isNull()) { - /* Release the cached URI */ - debug(88, 4) ("clientPurgeRequest: GET '%s'\n", storeUrl(newEntry)); - storeRelease(newEntry); - purgeStatus = HTTP_OK; + /* Release the cached URI */ + debug(88, 4) ("clientPurgeRequest: GET '%s'\n", storeUrl(newEntry)); + storeRelease(newEntry); + purgeStatus = HTTP_OK; } + lookingforstore = 4; StoreEntry::getPublicByRequestMethod(this, http->request, METHOD_HEAD); } @@ -1005,31 +1100,37 @@ void clientReplyContext::purgeDoPurgeHead(StoreEntry *newEntry) { if (newEntry) { - debug(88, 4) ("clientPurgeRequest: HEAD '%s'\n", storeUrl(newEntry)); - storeRelease(newEntry); - purgeStatus = HTTP_OK; + debug(88, 4) ("clientPurgeRequest: HEAD '%s'\n", storeUrl(newEntry)); + storeRelease(newEntry); + purgeStatus = HTTP_OK; } + HttpReply *r; http_version_t version; - + /* And for Vary, release the base URI if none of the headers was included in the request */ + if (http->request->vary_headers - && !strstr(http->request->vary_headers, "=")) { - StoreEntry *entry = storeGetPublic(urlCanonical(http->request), METHOD_GET); - if (entry) { - debug(88, 4) ("clientPurgeRequest: Vary GET '%s'\n", - storeUrl(entry)); - storeRelease(entry); - purgeStatus = HTTP_OK; - } - entry = storeGetPublic(urlCanonical(http->request), METHOD_HEAD); - if (entry) { - debug(88, 4) ("clientPurgeRequest: Vary HEAD '%s'\n", - storeUrl(entry)); - storeRelease(entry); - purgeStatus = HTTP_OK; - } + && !strstr(http->request->vary_headers, "=")) { + StoreEntry *entry = storeGetPublic(urlCanonical(http->request), METHOD_GET); + + if (entry) { + debug(88, 4) ("clientPurgeRequest: Vary GET '%s'\n", + storeUrl(entry)); + storeRelease(entry); + purgeStatus = HTTP_OK; + } + + entry = storeGetPublic(urlCanonical(http->request), METHOD_HEAD); + + if (entry) { + debug(88, 4) ("clientPurgeRequest: Vary HEAD '%s'\n", + storeUrl(entry)); + storeRelease(entry); + purgeStatus = HTTP_OK; + } } + /* * Make a new entry to hold the reply to be written * to the client. @@ -1038,13 +1139,19 @@ clientReplyContext::purgeDoPurgeHead(StoreEntry *newEntry) * push down the client chain */ http->entry = - clientCreateStoreEntry(this, http->request->method, - request_flags()); + clientCreateStoreEntry(this, http->request->method, + request_flags()); + triggerInitialStoreReadWithClientParameters(this, http); + r = httpReplyCreate(); + httpBuildVersion(&version, 1, 0); + httpReplySetHeaders(r, version, purgeStatus, NULL, NULL, 0, 0, -1); + httpReplySwapOut(r, http->entry); + http->entry->complete(); } @@ -1057,19 +1164,19 @@ clientTraceReply(clientStreamNode * node, clientReplyContext * context) StoreIOBuffer tempBuffer; assert(context->http->request->max_forwards == 0); context->http->entry = - clientCreateStoreEntry(context, context->http->request->method, - request_flags()); + clientCreateStoreEntry(context, context->http->request->method, + request_flags()); tempBuffer.offset = next->readBuffer.offset + context->headers_sz; tempBuffer.length = next->readBuffer.length; tempBuffer.data = next->readBuffer.data; storeClientCopy(context->sc, context->http->entry, - tempBuffer, clientSendMoreData, context); + tempBuffer, clientSendMoreData, context); storeReleaseRequest(context->http->entry); storeBuffer(context->http->entry); rep = httpReplyCreate(); httpBuildVersion(&version, 1, 0); httpReplySetHeaders(rep, version, HTTP_OK, NULL, "text/plain", - httpRequestPrefixLen(context->http->request), 0, squid_curtime); + httpRequestPrefixLen(context->http->request), 0, squid_curtime); httpReplySwapOut(rep, context->http->entry); httpRequestSwapOut(context->http->request, context->http->entry); context->http->entry->complete(); @@ -1081,14 +1188,17 @@ int clientCheckTransferDone(clientReplyContext * context) { StoreEntry *entry = context->http->entry; + if (entry == NULL) - return 0; - /* + return 0; + + /* * For now, 'done_copying' is used for special cases like * Range and HEAD requests. */ if (context->http->flags.done_copying) - return 1; + return 1; + /* * Handle STORE_OK objects. * objectLen(entry) will be set proprely. @@ -1096,9 +1206,9 @@ clientCheckTransferDone(clientReplyContext * context) * RC: Yes. */ if (entry->store_status == STORE_OK) { - return context->storeOKTransferDone(); + return context->storeOKTransferDone(); } else { - return context->storeNotOKTransferDone(); + return context->storeNotOKTransferDone(); } } @@ -1106,7 +1216,8 @@ int clientReplyContext::storeOKTransferDone() const { if (http->out.offset >= objectLen(http->entry) - headers_sz) - return 1; + return 1; + return 0; } @@ -1121,29 +1232,33 @@ clientReplyContext::storeNotOKTransferDone() const assert(http->request != NULL); /* mem->reply was wrong because it uses the UPSTREAM header length!!! */ http_reply const *reply = mem->getReply(); + if (headers_sz == 0) - /* haven't found end of headers yet */ - return 0; + /* haven't found end of headers yet */ + return 0; int sending = SENDING_BODY; + if (reply->sline.status == HTTP_NO_CONTENT || - reply->sline.status == HTTP_NOT_MODIFIED || - reply->sline.status < HTTP_OK || - http->request->method == METHOD_HEAD) - sending = SENDING_HDRSONLY; + reply->sline.status == HTTP_NOT_MODIFIED || + reply->sline.status < HTTP_OK || + http->request->method == METHOD_HEAD) + sending = SENDING_HDRSONLY; + /* * Figure out how much data we are supposed to send. * If we are sending a body and we don't have a content-length, * then we must wait for the object to become STORE_OK. */ if (reply->content_length < 0) - return 0; + return 0; size_t expectedLength = http->out.headers_sz + reply->content_length; + if (http->out.size < expectedLength) - return 0; + return 0; else - return 1; + return 1; } @@ -1152,10 +1267,12 @@ int clientGotNotEnough(clientHttpRequest const *http) { int cl = - httpReplyBodySize(http->request->method, http->entry->mem_obj->getReply()); + httpReplyBodySize(http->request->method, http->entry->mem_obj->getReply()); assert(cl >= 0); + if (http->out.offset < cl) - return 1; + return 1; + return 0; } @@ -1170,32 +1287,35 @@ int clientHttpRequestStatus(int fd, clientHttpRequest const *http) { #if SIZEOF_SIZE_T == 4 + if (http->out.size > 0x7FFF0000) { - debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", - fd); - debug(88, 1) ("\tclient %s\n", - inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); - debug(88, 1) ("\treceived %d bytes\n", (int) http->out.size); - debug(88, 1) ("\tURI %s\n", http->log_uri); - return 1; + debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", + fd); + debug(88, 1) ("\tclient %s\n", + inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); + debug(88, 1) ("\treceived %d bytes\n", (int) http->out.size); + debug(88, 1) ("\tURI %s\n", http->log_uri); + return 1; } + #endif #if SIZEOF_OFF_T == 4 if (http->out.offset > 0x7FFF0000) { - debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", - fd); - debug(88, 1) ("\tclient %s\n", - inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); - debug(88, 1) ("\treceived %d bytes (offset %d)\n", (int) http->out.size, - (int) http->out.offset); - debug(88, 1) ("\tURI %s\n", http->log_uri); - return 1; + debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", + fd); + debug(88, 1) ("\tclient %s\n", + inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); + debug(88, 1) ("\treceived %d bytes (offset %d)\n", (int) http->out.size, + (int) http->out.offset); + debug(88, 1) ("\tURI %s\n", http->log_uri); + return 1; } + #endif return 0; } -/* Preconditions: +/* Preconditions: * *http is a valid structure. * fd is either -1, or an open fd. * @@ -1210,45 +1330,55 @@ clientReplyStatus(clientStreamNode * aNode, clientHttpRequest * http) clientReplyContext *context = (clientReplyContext *)aNode->data; int done; /* Here because lower nodes don't need it */ + if (http->entry == NULL) - return STREAM_FAILED; /* yuck, but what can we do? */ + return STREAM_FAILED; /* yuck, but what can we do? */ + if (EBIT_TEST(http->entry->flags, ENTRY_ABORTED)) - /* TODO: Could upstream read errors (result.flags.error) be - * lost, and result in undersize requests being considered - * complete. Should we tcp reset such connections ? - */ - return STREAM_FAILED; + /* TODO: Could upstream read errors (result.flags.error) be + * lost, and result in undersize requests being considered + * complete. Should we tcp reset such connections ? + */ + return STREAM_FAILED; + if ((done = clientCheckTransferDone(context)) != 0 || context->flags.complete) { - debug(88, 5) ("clientReplyStatus: transfer is DONE\n"); - /* Ok we're finished, but how? */ - if (httpReplyBodySize(http->request->method, - http->entry->getReply()) < 0) { - debug(88, 5) ("clientReplyStatus: closing, content_length < 0\n"); - return STREAM_FAILED; - } - if (!done) { - debug(88, 5) ("clientReplyStatus: closing, !done, but read 0 bytes\n"); - return STREAM_FAILED; - } - if (clientGotNotEnough(http)) { - debug(88, 5) ("clientReplyStatus: client didn't get all it expected\n"); - return STREAM_UNPLANNED_COMPLETE; - } - if (http->request->flags.proxy_keepalive) { - debug(88, 5) ("clientReplyStatus: stream complete and can keepalive\n"); - return STREAM_COMPLETE; - } - debug(88, 5) ("clientReplyStatus: stream was not expected to complete!\n"); - return STREAM_UNPLANNED_COMPLETE; + debug(88, 5) ("clientReplyStatus: transfer is DONE\n"); + /* Ok we're finished, but how? */ + + if (httpReplyBodySize(http->request->method, + http->entry->getReply()) < 0) { + debug(88, 5) ("clientReplyStatus: closing, content_length < 0\n"); + return STREAM_FAILED; + } + + if (!done) { + debug(88, 5) ("clientReplyStatus: closing, !done, but read 0 bytes\n"); + return STREAM_FAILED; + } + + if (clientGotNotEnough(http)) { + debug(88, 5) ("clientReplyStatus: client didn't get all it expected\n"); + return STREAM_UNPLANNED_COMPLETE; + } + + if (http->request->flags.proxy_keepalive) { + debug(88, 5) ("clientReplyStatus: stream complete and can keepalive\n"); + return STREAM_COMPLETE; + } + + debug(88, 5) ("clientReplyStatus: stream was not expected to complete!\n"); + return STREAM_UNPLANNED_COMPLETE; } + if (clientReplyBodyTooLarge(http->entry->getReply(), http->out.offset)) { - debug(88, 5) ("clientReplyStatus: client reply body is too large\n"); - return STREAM_FAILED; + debug(88, 5) ("clientReplyStatus: client reply body is too large\n"); + return STREAM_FAILED; } + return STREAM_NONE; } -/* Responses with no body will not have a content-type header, +/* Responses with no body will not have a content-type header, * which breaks the rep_mime_type acl, which * coincidentally, is the most common acl for reply access lists. * A better long term fix for this is to allow acl matchs on the various @@ -1261,16 +1391,22 @@ static int clientAlwaysAllowResponse(http_status sline) { switch (sline) { + case HTTP_CONTINUE: + case HTTP_SWITCHING_PROTOCOLS: + case HTTP_PROCESSING: + case HTTP_NO_CONTENT: + case HTTP_NOT_MODIFIED: - return 1; - /* unreached */ - break; + return 1; + /* unreached */ + break; + default: - return 0; + return 0; } } @@ -1278,25 +1414,28 @@ void clientObeyConnectionHeader(clientHttpRequest * http, HttpReply * rep) { HttpHeader *hdr = &rep->header; + if (httpHeaderHas(hdr, HDR_CONNECTION)) { - /* anything that matches Connection list member will be deleted */ - String strConnection = httpHeaderGetList(hdr, HDR_CONNECTION); - const HttpHeaderEntry *e; - HttpHeaderPos pos = HttpHeaderInitPos; - /* - * think: on-average-best nesting of the two loops (hdrEntry - * and strListItem) @?@ - */ - /* - * maybe we should delete standard stuff ("keep-alive","close") - * from strConnection first? - */ - while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (strListIsMember(&strConnection, e->name.buf(), ',')) - httpHeaderDelAt(hdr, pos); - } - httpHeaderDelById(hdr, HDR_CONNECTION); - strConnection.clean(); + /* anything that matches Connection list member will be deleted */ + String strConnection = httpHeaderGetList(hdr, HDR_CONNECTION); + const HttpHeaderEntry *e; + HttpHeaderPos pos = HttpHeaderInitPos; + /* + * think: on-average-best nesting of the two loops (hdrEntry + * and strListItem) @?@ + */ + /* + * maybe we should delete standard stuff ("keep-alive","close") + * from strConnection first? + */ + + while ((e = httpHeaderGetEntry(hdr, &pos))) { + if (strListIsMember(&strConnection, e->name.buf(), ',')) + httpHeaderDelAt(hdr, pos); + } + + httpHeaderDelById(hdr, HDR_CONNECTION); + strConnection.clean(); } } @@ -1317,114 +1456,130 @@ clientBuildReplyHeader(clientReplyContext *context, HttpReply * rep) /* httpHeaderDelById(hdr, HDR_ACCEPT_RANGES); */ httpHeaderDelById(hdr, HDR_ETAG); #endif + httpHeaderDelById(hdr, HDR_PROXY_CONNECTION); /* here: Keep-Alive is a field-name, not a connection directive! */ httpHeaderDelByName(hdr, "Keep-Alive"); /* remove Set-Cookie if a hit */ + if (is_hit) - httpHeaderDelById(hdr, HDR_SET_COOKIE); + httpHeaderDelById(hdr, HDR_SET_COOKIE); + clientObeyConnectionHeader(http, rep); -// if (request->range) -// clientBuildRangeHeader(http, rep); + + // if (request->range) + // clientBuildRangeHeader(http, rep); /* * Add a estimated Age header on cache hits. */ if (is_hit) { - /* - * Remove any existing Age header sent by upstream caches - * (note that the existing header is passed along unmodified - * on cache misses) - */ - httpHeaderDelById(hdr, HDR_AGE); - /* - * This adds the calculated object age. Note that the details of the - * age calculation is performed by adjusting the timestamp in - * storeTimestampsSet(), not here. - * - * BROWSER WORKAROUND: IE sometimes hangs when receiving a 0 Age - * header, so don't use it unless there is a age to report. Please - * note that Age is only used to make a conservative estimation of - * the objects age, so a Age: 0 header does not add any useful - * information to the reply in any case. - */ - if (NULL == http->entry) - (void) 0; - else if (http->entry->timestamp < 0) - (void) 0; - else if (http->entry->timestamp < squid_curtime) { - httpHeaderPutInt(hdr, HDR_AGE, - squid_curtime - http->entry->timestamp); - /* Signal old objects. NB: rfc 2616 is not clear, - * by implication, on whether we should do this to all - * responses, or only cache hits. - * 14.46 states it ONLY applys for heuristically caclulated - * freshness values, 13.2.4 doesn't specify the same limitation. - * We interpret RFC 2616 under the combination. - */ - /* TODO: if maxage or s-maxage is present, don't do this */ - if (squid_curtime - http->entry->timestamp >= 86400) { - char tempbuf[512]; - snprintf (tempbuf, sizeof(tempbuf), "%s %s %s", - "113", ThisCache, - "This cache hit is still fresh and more than 1 day old"); - httpHeaderPutStr(hdr, HDR_WARNING, tempbuf); - } - } + /* + * Remove any existing Age header sent by upstream caches + * (note that the existing header is passed along unmodified + * on cache misses) + */ + httpHeaderDelById(hdr, HDR_AGE); + /* + * This adds the calculated object age. Note that the details of the + * age calculation is performed by adjusting the timestamp in + * storeTimestampsSet(), not here. + * + * BROWSER WORKAROUND: IE sometimes hangs when receiving a 0 Age + * header, so don't use it unless there is a age to report. Please + * note that Age is only used to make a conservative estimation of + * the objects age, so a Age: 0 header does not add any useful + * information to the reply in any case. + */ + + if (NULL == http->entry) + (void) 0; + else if (http->entry->timestamp < 0) + (void) 0; + else if (http->entry->timestamp < squid_curtime) { + httpHeaderPutInt(hdr, HDR_AGE, + squid_curtime - http->entry->timestamp); + /* Signal old objects. NB: rfc 2616 is not clear, + * by implication, on whether we should do this to all + * responses, or only cache hits. + * 14.46 states it ONLY applys for heuristically caclulated + * freshness values, 13.2.4 doesn't specify the same limitation. + * We interpret RFC 2616 under the combination. + */ + /* TODO: if maxage or s-maxage is present, don't do this */ + + if (squid_curtime - http->entry->timestamp >= 86400) { + char tempbuf[512]; + snprintf (tempbuf, sizeof(tempbuf), "%s %s %s", + "113", ThisCache, + "This cache hit is still fresh and more than 1 day old"); + httpHeaderPutStr(hdr, HDR_WARNING, tempbuf); + } + } } + /* Filter unproxyable authentication types */ if (http->logType != LOG_TCP_DENIED && - (httpHeaderHas(hdr, HDR_WWW_AUTHENTICATE) || httpHeaderHas(hdr, HDR_PROXY_AUTHENTICATE))) { - HttpHeaderPos pos = HttpHeaderInitPos; - HttpHeaderEntry *e; - while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (e->id == HDR_WWW_AUTHENTICATE || e->id == HDR_PROXY_AUTHENTICATE) { - const char *value = e->value.buf(); - if ((strncasecmp(value, "NTLM", 4) == 0 && - (value[4] == '\0' || value[4] == ' ')) - || - (strncasecmp(value, "Negotiate", 9) == 0 && - (value[9] == '\0' || value[9] == ' '))) - httpHeaderDelAt(hdr, pos); - } - } + (httpHeaderHas(hdr, HDR_WWW_AUTHENTICATE) || httpHeaderHas(hdr, HDR_PROXY_AUTHENTICATE))) { + HttpHeaderPos pos = HttpHeaderInitPos; + HttpHeaderEntry *e; + + while ((e = httpHeaderGetEntry(hdr, &pos))) { + if (e->id == HDR_WWW_AUTHENTICATE || e->id == HDR_PROXY_AUTHENTICATE) { + const char *value = e->value.buf(); + + if ((strncasecmp(value, "NTLM", 4) == 0 && + (value[4] == '\0' || value[4] == ' ')) + || + (strncasecmp(value, "Negotiate", 9) == 0 && + (value[9] == '\0' || value[9] == ' '))) + httpHeaderDelAt(hdr, pos); + } + } } + /* Handle authentication headers */ if (request->auth_user_request) - authenticateFixHeader(rep, request->auth_user_request, request, - http->flags.accel, 0); + authenticateFixHeader(rep, request->auth_user_request, request, + http->flags.accel, 0); + /* Append X-Cache */ httpHeaderPutStrf(hdr, HDR_X_CACHE, "%s from %s", - is_hit ? "HIT" : "MISS", getMyHostname()); + is_hit ? "HIT" : "MISS", getMyHostname()); + #if USE_CACHE_DIGESTS /* Append X-Cache-Lookup: -- temporary hack, to be removed @?@ @?@ */ httpHeaderPutStrf(hdr, HDR_X_CACHE_LOOKUP, "%s from %s:%d", - context->lookup_type ? context->lookup_type : "NONE", - getMyHostname(), getMyPort()); + context->lookup_type ? context->lookup_type : "NONE", + getMyHostname(), getMyPort()); + #endif + if (httpReplyBodySize(request->method, rep) < 0) { - debug(88, - 3) - ("clientBuildReplyHeader: can't keep-alive, unknown body size\n"); - request->flags.proxy_keepalive = 0; + debug(88, + 3) + ("clientBuildReplyHeader: can't keep-alive, unknown body size\n"); + request->flags.proxy_keepalive = 0; } + /* Append VIA */ { - LOCAL_ARRAY(char, bbuf, MAX_URL + 32); - String strVia = httpHeaderGetList(hdr, HDR_VIA); - snprintf(bbuf, sizeof(bbuf), "%d.%d %s", - rep->sline.version.major, - rep->sline.version.minor, - ThisCache); - strListAdd(&strVia, bbuf, ','); - httpHeaderDelById(hdr, HDR_VIA); - httpHeaderPutStr(hdr, HDR_VIA, strVia.buf()); - strVia.clean(); + LOCAL_ARRAY(char, bbuf, MAX_URL + 32); + String strVia = httpHeaderGetList(hdr, HDR_VIA); + snprintf(bbuf, sizeof(bbuf), "%d.%d %s", + rep->sline.version.major, + rep->sline.version.minor, + ThisCache); + strListAdd(&strVia, bbuf, ','); + httpHeaderDelById(hdr, HDR_VIA); + httpHeaderPutStr(hdr, HDR_VIA, strVia.buf()); + strVia.clean(); } /* Signal keep-alive if needed */ httpHeaderPutStr(hdr, - http->flags.accel ? HDR_CONNECTION : HDR_PROXY_CONNECTION, - request->flags.proxy_keepalive ? "keep-alive" : "close"); + http->flags.accel ? HDR_CONNECTION : HDR_PROXY_CONNECTION, + request->flags.proxy_keepalive ? "keep-alive" : "close"); + #if ADD_X_REQUEST_URI /* * Knowing the URI of the request is useful when debugging persistent @@ -1433,8 +1588,10 @@ clientBuildReplyHeader(clientReplyContext *context, HttpReply * rep) * debugger [hdr->entries.count-1]. */ httpHeaderPutStr(hdr, HDR_X_REQUEST_URI, - http->entry->mem_obj->url ? http->entry->mem_obj->url : http->uri); + http->entry->mem_obj->url ? http->entry->mem_obj->url : http->uri); + #endif + httpHdrMangleList(hdr, request); } @@ -1444,23 +1601,26 @@ clientBuildReply(clientReplyContext *context, const char *buf, size_t size) { HttpReply *rep = httpReplyCreate(); size_t k = headersEnd(buf, size); + if (k && httpReplyParse(rep, buf, k)) { - /* enforce 1.0 reply version */ - httpBuildVersion(&rep->sline.version, 1, 0); - /* do header conversions */ - clientBuildReplyHeader(context, rep); + /* enforce 1.0 reply version */ + httpBuildVersion(&rep->sline.version, 1, 0); + /* do header conversions */ + clientBuildReplyHeader(context, rep); } else { - /* parsing failure, get rid of the invalid reply */ - httpReplyDestroy(rep); - rep = NULL; - /* This is wrong. httpReplyDestroy should to the rep - * for us, and we can destroy our own range info - */ - if (context->http->request->range) { - /* this will fail and destroy request->range */ -// clientBuildRangeHeader(context->http, rep); - } + /* parsing failure, get rid of the invalid reply */ + httpReplyDestroy(rep); + rep = NULL; + /* This is wrong. httpReplyDestroy should to the rep + * for us, and we can destroy our own range info + */ + + if (context->http->request->range) { + /* this will fail and destroy request->range */ + // clientBuildRangeHeader(context->http, rep); + } } + return rep; } @@ -1468,11 +1628,12 @@ void clientReplyContext::identifyStoreObject() { request_t *r = http->request; + if (r->flags.cachable || r->flags.internal) { - lookingforstore = 5; - StoreEntry::getPublicByRequest (this, r); + lookingforstore = 5; + StoreEntry::getPublicByRequest (this, r); } else - identifyFoundObject (NullStoreEntry::getInstance()); + identifyFoundObject (NullStoreEntry::getInstance()); } void @@ -1480,86 +1641,103 @@ clientReplyContext::identifyFoundObject(StoreEntry *newEntry) { StoreEntry *e = newEntry; request_t *r = http->request; + if (e->isNull()) { - http->entry = NULL; + http->entry = NULL; } else { - http->entry = e; + http->entry = e; } + e = http->entry; /* Release negatively cached IP-cache entries on reload */ + if (r->flags.nocache) - ipcacheInvalidate(r->host); + ipcacheInvalidate(r->host); + #if HTTP_VIOLATIONS + else if (r->flags.nocache_hack) - ipcacheInvalidate(r->host); + ipcacheInvalidate(r->host); + #endif #if USE_CACHE_DIGESTS + lookup_type = http->entry ? "HIT" : "MISS"; + #endif + if (NULL == http->entry) { - /* this object isn't in the cache */ - debug(85, 3) ("clientProcessRequest2: storeGet() MISS\n"); - http->logType = LOG_TCP_MISS; - doGetMoreData(); - return; + /* this object isn't in the cache */ + debug(85, 3) ("clientProcessRequest2: storeGet() MISS\n"); + http->logType = LOG_TCP_MISS; + doGetMoreData(); + return; } + if (Config.onoff.offline) { - debug(85, 3) ("clientProcessRequest2: offline HIT\n"); - http->logType = LOG_TCP_HIT; - doGetMoreData(); - return; + debug(85, 3) ("clientProcessRequest2: offline HIT\n"); + http->logType = LOG_TCP_HIT; + doGetMoreData(); + return; } + if (http->redirect.status) { - /* force this to be a miss */ - http->entry = NULL; - http->logType = LOG_TCP_MISS; - doGetMoreData(); - return; + /* force this to be a miss */ + http->entry = NULL; + http->logType = LOG_TCP_MISS; + doGetMoreData(); + return; } + if (!storeEntryValidToSend(e)) { - debug(85, 3) ("clientProcessRequest2: !storeEntryValidToSend MISS\n"); - http->entry = NULL; - http->logType = LOG_TCP_MISS; - doGetMoreData(); - return; + debug(85, 3) ("clientProcessRequest2: !storeEntryValidToSend MISS\n"); + http->entry = NULL; + http->logType = LOG_TCP_MISS; + doGetMoreData(); + return; } + if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) { - /* Special entries are always hits, no matter what the client says */ - debug(85, 3) ("clientProcessRequest2: ENTRY_SPECIAL HIT\n"); - http->logType = LOG_TCP_HIT; - doGetMoreData(); - return; + /* Special entries are always hits, no matter what the client says */ + debug(85, 3) ("clientProcessRequest2: ENTRY_SPECIAL HIT\n"); + http->logType = LOG_TCP_HIT; + doGetMoreData(); + return; } + #if HTTP_VIOLATIONS if (http->entry->store_status == STORE_PENDING) { - if (r->flags.nocache || r->flags.nocache_hack) { - debug(85, 3) ("Clearing no-cache for STORE_PENDING request\n\t%s\n", - storeUrl(http->entry)); - r->flags.nocache = 0; - r->flags.nocache_hack = 0; - } + if (r->flags.nocache || r->flags.nocache_hack) { + debug(85, 3) ("Clearing no-cache for STORE_PENDING request\n\t%s\n", + storeUrl(http->entry)); + r->flags.nocache = 0; + r->flags.nocache_hack = 0; + } } + #endif if (r->flags.nocache) { - debug(85, 3) ("clientProcessRequest2: no-cache REFRESH MISS\n"); - http->entry = NULL; - http->logType = LOG_TCP_CLIENT_REFRESH_MISS; - doGetMoreData(); - return; + debug(85, 3) ("clientProcessRequest2: no-cache REFRESH MISS\n"); + http->entry = NULL; + http->logType = LOG_TCP_CLIENT_REFRESH_MISS; + doGetMoreData(); + return; } + /* We don't cache any range requests (for now!) -- adrian */ /* RBC - and we won't until the store supports sparse objects. * I suspec this test is incorrect though, as we can extract ranges from * a fully cached object */ if (r->flags.range) { - /* XXX: test to see if we can satisfy the range with the cached object */ + /* XXX: test to see if we can satisfy the range with the cached object */ debug(85, 3) ("clientProcessRequest2: force MISS due to range presence\n"); - http->entry = NULL; - http->logType = LOG_TCP_MISS; - doGetMoreData(); - return; + http->entry = NULL; + http->logType = LOG_TCP_MISS; + doGetMoreData(); + return; } + debug(85, 3) ("clientProcessRequest2: default HIT\n"); http->logType = LOG_TCP_HIT; doGetMoreData(); @@ -1588,73 +1766,84 @@ clientGetMoreData(clientStreamNode * aNode, clientHttpRequest * http) assert(context->http == http); next = ( clientStreamNode *)aNode->node.next->data; + if (!context->ourNode) - context->ourNode = aNode; + context->ourNode = aNode; + /* no cbdatareference, this is only used once, and safely */ if (context->flags.storelogiccomplete) { - StoreIOBuffer tempBuffer; - tempBuffer.offset = next->readBuffer.offset + context->headers_sz; - tempBuffer.length = next->readBuffer.length; - tempBuffer.data = next->readBuffer.data; - - storeClientCopy(context->sc, http->entry, - tempBuffer, clientSendMoreData, context); - return; + StoreIOBuffer tempBuffer; + tempBuffer.offset = next->readBuffer.offset + context->headers_sz; + tempBuffer.length = next->readBuffer.length; + tempBuffer.data = next->readBuffer.data; + + storeClientCopy(context->sc, http->entry, + tempBuffer, clientSendMoreData, context); + return; } + if (context->http->request->method == METHOD_PURGE) { - context->purgeRequest(); - return; + context->purgeRequest(); + return; } + if (context->http->request->method == METHOD_TRACE) { - if (context->http->request->max_forwards == 0) { - clientTraceReply(aNode, context); - return; - } - /* continue forwarding, not finished yet. */ - http->logType = LOG_TCP_MISS; - context->doGetMoreData(); + if (context->http->request->max_forwards == 0) { + clientTraceReply(aNode, context); + return; + } + + /* continue forwarding, not finished yet. */ + http->logType = LOG_TCP_MISS; + + context->doGetMoreData(); } else - context->identifyStoreObject(); + context->identifyStoreObject(); } void clientReplyContext::doGetMoreData() { /* We still have to do store logic processing - vary, cache hit etc */ + if (http->entry != NULL) { - /* someone found the object in the cache for us */ - StoreIOBuffer tempBuffer; - storeLockObject(http->entry); - if (http->entry->mem_obj == NULL) { - /* - * This if-block exists because we don't want to clobber - * a preexiting mem_obj->method value if the mem_obj - * already exists. For example, when a HEAD request - * is a cache hit for a GET response, we want to keep - * the method as GET. - */ - storeCreateMemObject(http->entry, http->uri, - http->log_uri); - http->entry->mem_obj->method = - http->request->method; - } - sc = storeClientListAdd(http->entry, this); + /* someone found the object in the cache for us */ + StoreIOBuffer tempBuffer; + storeLockObject(http->entry); + + if (http->entry->mem_obj == NULL) { + /* + * This if-block exists because we don't want to clobber + * a preexiting mem_obj->method value if the mem_obj + * already exists. For example, when a HEAD request + * is a cache hit for a GET response, we want to keep + * the method as GET. + */ + storeCreateMemObject(http->entry, http->uri, + http->log_uri); + http->entry->mem_obj->method = + http->request->method; + } + + sc = storeClientListAdd(http->entry, this); #if DELAY_POOLS - sc->setDelayId(DelayId::DelayClient(http)); + + sc->setDelayId(DelayId::DelayClient(http)); #endif - assert(http->logType == LOG_TCP_HIT); - reqofs = 0; - /* guarantee nothing has been sent yet! */ - assert(http->out.size == 0); - assert(http->out.offset == 0); - tempBuffer.offset = reqofs; - tempBuffer.length = getNextNode()->readBuffer.length; - tempBuffer.data = getNextNode()->readBuffer.data; - storeClientCopy(sc, http->entry, - tempBuffer, clientCacheHit, this); + + assert(http->logType == LOG_TCP_HIT); + reqofs = 0; + /* guarantee nothing has been sent yet! */ + assert(http->out.size == 0); + assert(http->out.offset == 0); + tempBuffer.offset = reqofs; + tempBuffer.length = getNextNode()->readBuffer.length; + tempBuffer.data = getNextNode()->readBuffer.data; + storeClientCopy(sc, http->entry, + tempBuffer, clientCacheHit, this); } else { - /* MISS CASE, http->logType is already set! */ - clientProcessMiss(this); + /* MISS CASE, http->logType is already set! */ + clientProcessMiss(this); } } @@ -1699,9 +1888,9 @@ bool clientReplyContext::errorInStream(StoreIOBuffer const &result, size_t const &sizeToProcess)const { return /* aborted request */ - (http->entry && EBIT_TEST(http->entry->flags, ENTRY_ABORTED)) || - /* Upstream read error */ (result.flags.error) || - /* Upstream EOF */ (sizeToProcess == 0); + (http->entry && EBIT_TEST(http->entry->flags, ENTRY_ABORTED)) || + /* Upstream read error */ (result.flags.error) || + /* Upstream EOF */ (sizeToProcess == 0); } void @@ -1716,24 +1905,30 @@ clientReplyContext::sendStreamError(StoreIOBuffer const &result) flags.complete = 1; tempBuffer.flags.error = result.flags.error; clientStreamCallback((clientStreamNode*)http->client_stream.head->data, http, NULL, - tempBuffer); + tempBuffer); } void clientReplyContext::pushStreamData(StoreIOBuffer const &result, char *source) { StoreIOBuffer tempBuffer; + if (result.length == 0) { - debug (88,5)("clientReplyContext::pushStreamData: marking request as complete due to 0 length store result\n"); - flags.complete = 1; + debug (88,5)("clientReplyContext::pushStreamData: marking request as complete due to 0 length store result\n"); + flags.complete = 1; } + /* REMOVE ME: Only useful for two node streams */ assert(result.offset - headers_sz == ((clientStreamNode *) http->client_stream.tail->data)->readBuffer.offset); + tempBuffer.offset = result.offset - headers_sz; + tempBuffer.length = result.length; + tempBuffer.data = source; + clientStreamCallback((clientStreamNode*)http->client_stream.head->data, http, NULL, - tempBuffer); + tempBuffer); } clientStreamNode * @@ -1766,7 +1961,7 @@ clientReplyContext::startSendProcess() tempBuffer.length = next()->readBuffer.length - reqofs; tempBuffer.data = next()->readBuffer.data + reqofs; storeClientCopy(sc, http->entry, - tempBuffer, clientSendMoreData, this); + tempBuffer, clientSendMoreData, this); } void @@ -1774,23 +1969,25 @@ clientReplyContext::processReplyAccess () { HttpReply *rep = holdingReply; holdingReply = NULL; - httpReplyBodyBuildSize(http->request, rep, &Config.ReplyBodySize); - if (clientReplyBodyTooLarge(rep, rep->content_length)) { - ErrorState *err = - clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL, - http->conn ? &http->conn->peer.sin_addr : &no_addr, - http->request); - clientRemoveStoreReference(this, &sc, &http->entry); - startError(this, http, err); - httpReplyDestroy(rep); - return; - } - headers_sz = rep->hdr_sz; - ACLChecklist *replyChecklist; - replyChecklist = clientAclChecklistCreate(Config.accessList.reply, http); - replyChecklist->reply = rep; - holdingReply = rep; - replyChecklist->nonBlockingCheck(ProcessReply, this); + httpReplyBodyBuildSize(http->request, rep, &Config.ReplyBodySize); + + if (clientReplyBodyTooLarge(rep, rep->content_length)) { + ErrorState *err = + clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL, + http->conn ? &http->conn->peer.sin_addr : &no_addr, + http->request); + clientRemoveStoreReference(this, &sc, &http->entry); + startError(this, http, err); + httpReplyDestroy(rep); + return; + } + + headers_sz = rep->hdr_sz; + ACLChecklist *replyChecklist; + replyChecklist = clientAclChecklistCreate(Config.accessList.reply, http); + replyChecklist->reply = rep; + holdingReply = rep; + replyChecklist->nonBlockingCheck(ProcessReply, this); } void @@ -1803,61 +2000,68 @@ clientReplyContext::ProcessReply (int rv, void *voidMe) void clientReplyContext::processReply(bool accessAllowed) { - debug(88, 2) ("The reply for %s %s is %s, because it matched '%s'\n", - RequestMethodStr[http->request->method], http->uri, - accessAllowed ? "ALLOWED" : "DENIED", - AclMatchedName ? AclMatchedName : "NO ACL's"); - HttpReply *rep = holdingReply; + debug(88, 2) ("The reply for %s %s is %s, because it matched '%s'\n", + RequestMethodStr[http->request->method], http->uri, + accessAllowed ? "ALLOWED" : "DENIED", + AclMatchedName ? AclMatchedName : "NO ACL's"); + HttpReply *rep = holdingReply; holdingReply = NULL; - if (!accessAllowed && rep->sline.status != HTTP_FORBIDDEN - && !clientAlwaysAllowResponse(rep->sline.status)) { - /* the if above is slightly broken, but there is no way - * to tell if this is a squid generated error page, or one from - * upstream at this point. */ - ErrorState *err; - err = - clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, - http->conn ? &http->conn->peer.sin_addr : &no_addr, - http->request); - clientRemoveStoreReference(this, &sc, &http->entry); - startError(this, http, err); - httpReplyDestroy(rep); - return; - } - ssize_t body_size = reqofs - rep->hdr_sz; - assert(body_size >= 0); - debug(88,3) - ("clientSendMoreData: Appending %d bytes after %d bytes of headers\n", - (int) body_size, rep->hdr_sz); - if (http->request->method == METHOD_HEAD) { - /* do not forward body for HEAD replies */ - body_size = 0; - http->flags.done_copying = 1; - flags.complete = 1; - } - assert (!flags.headersSent); - flags.headersSent = true; - - StoreIOBuffer tempBuffer; - char *buf = next()->readBuffer.data; - char *body_buf = buf + rep->hdr_sz; - if (next()->readBuffer.offset != 0) { - if (next()->readBuffer.offset > body_size) { - /* Can't use any of the body we recieved. send nothing */ - tempBuffer.length = 0; - tempBuffer.data = NULL; - } else { - tempBuffer.length = body_size - next()->readBuffer.offset; - tempBuffer.data = body_buf + next()->readBuffer.offset; - } - } else { - tempBuffer.length = body_size; - tempBuffer.data = body_buf; - } - /* TODO: move the data in the buffer back by the request header size */ - clientStreamCallback((clientStreamNode *)http->client_stream.head->data, - http, rep, tempBuffer); - return; + + if (!accessAllowed && rep->sline.status != HTTP_FORBIDDEN + && !clientAlwaysAllowResponse(rep->sline.status)) { + /* the if above is slightly broken, but there is no way + * to tell if this is a squid generated error page, or one from + * upstream at this point. */ + ErrorState *err; + err = + clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, + http->conn ? &http->conn->peer.sin_addr : &no_addr, + http->request); + clientRemoveStoreReference(this, &sc, &http->entry); + startError(this, http, err); + httpReplyDestroy(rep); + return; + } + + ssize_t body_size = reqofs - rep->hdr_sz; + assert(body_size >= 0); + debug(88,3) + ("clientSendMoreData: Appending %d bytes after %d bytes of headers\n", + (int) body_size, rep->hdr_sz); + + if (http->request->method == METHOD_HEAD) { + /* do not forward body for HEAD replies */ + body_size = 0; + http->flags.done_copying = 1; + flags.complete = 1; + } + + assert (!flags.headersSent); + flags.headersSent = true; + + StoreIOBuffer tempBuffer; + char *buf = next()->readBuffer.data; + char *body_buf = buf + rep->hdr_sz; + + if (next()->readBuffer.offset != 0) { + if (next()->readBuffer.offset > body_size) { + /* Can't use any of the body we recieved. send nothing */ + tempBuffer.length = 0; + tempBuffer.data = NULL; + } else { + tempBuffer.length = body_size - next()->readBuffer.offset; + tempBuffer.data = body_buf + next()->readBuffer.offset; + } + } else { + tempBuffer.length = body_size; + tempBuffer.data = body_buf; + } + + /* TODO: move the data in the buffer back by the request header size */ + clientStreamCallback((clientStreamNode *)http->client_stream.head->data, + http, rep, tempBuffer); + + return; } void @@ -1870,115 +2074,127 @@ clientReplyContext::sendMoreData (StoreIOBuffer result) char *buf = next()->readBuffer.data; char *body_buf = buf; - /* This is always valid until we get the headers as metadata from + /* This is always valid until we get the headers as metadata from * storeClientCopy. * Then it becomes reqofs == next->readBuffer.offset() */ assert(reqofs == 0 || flags.storelogiccomplete); if (flags.headersSent && buf != result.data) { - /* we've got to copy some data */ - assert(result.length <= next()->readBuffer.length); - xmemcpy(buf, result.data, result.length); - body_buf = buf; + /* we've got to copy some data */ + assert(result.length <= next()->readBuffer.length); + xmemcpy(buf, result.data, result.length); + body_buf = buf; } else if (!flags.headersSent && - buf + reqofs !=result.data) { - /* we've got to copy some data */ - assert(result.length + reqofs <= next()->readBuffer.length); - xmemcpy(buf + reqofs, result.data, result.length); - body_buf = buf; + buf + reqofs !=result.data) { + /* we've got to copy some data */ + assert(result.length + reqofs <= next()->readBuffer.length); + xmemcpy(buf + reqofs, result.data, result.length); + body_buf = buf; } + /* We've got the final data to start pushing... */ flags.storelogiccomplete = 1; reqofs += result.length; assert(reqofs <= HTTP_REQBUF_SZ || flags.headersSent); + assert(http->request != NULL); + /* ESI TODO: remove this assert once everything is stable */ assert(http->client_stream.head->data - && cbdataReferenceValid(http->client_stream.head->data)); + && cbdataReferenceValid(http->client_stream.head->data)); makeThisHead(); + debug(88, 5) ("clientSendMoreData: %s, %d bytes (%u new bytes)\n", - http->uri, (int) reqofs, (unsigned int)result.length); + http->uri, (int) reqofs, (unsigned int)result.length); + debug(88, 5) ("clientSendMoreData: FD %d '%s', out.offset=%ld \n", - fd, storeUrl(entry), (long int) http->out.offset); + fd, storeUrl(entry), (long int) http->out.offset); /* update size of the request */ reqsize = reqofs; - + if (http->request->flags.resetTCP()) { - /* yuck. FIXME: move to client_side.c */ - if (fd != -1) - comm_reset_close(fd); - return; + /* yuck. FIXME: move to client_side.c */ + + if (fd != -1) + comm_reset_close(fd); + + return; } - + if (errorInStream(result, reqofs)) { - sendStreamError(result); - return; + sendStreamError(result); + return; } if (flags.headersSent) { - pushStreamData (result, buf); - return; + pushStreamData (result, buf); + return; } + /* handle headers */ if (Config.onoff.log_mime_hdrs) { - size_t k; - if ((k = headersEnd(buf, reqofs))) { - safe_free(http->al.headers.reply); - http->al.headers.reply = (char *)xcalloc(k + 1, 1); - xstrncpy(http->al.headers.reply, buf, k); - } + size_t k; + + if ((k = headersEnd(buf, reqofs))) { + safe_free(http->al.headers.reply); + http->al.headers.reply = (char *)xcalloc(k + 1, 1); + xstrncpy(http->al.headers.reply, buf, k); + } } + rep = clientBuildReply(this, buf, reqofs); ssize_t body_size = reqofs; + if (rep) { - holdingReply = rep; - holdingBuffer = result; - processReplyAccess (); - return; + holdingReply = rep; + holdingBuffer = result; + processReplyAccess (); + return; } else if (reqofs < HTTP_REQBUF_SZ && entry->store_status == STORE_PENDING) { - waitForMoreData(result); - return; + waitForMoreData(result); + return; } else if (http->request->method == METHOD_HEAD) { - /* - * If we are here, then store_status == STORE_OK and it - * seems we have a HEAD repsponse which is missing the - * empty end-of-headers line (home.mira.net, phttpd/0.99.72 - * does this). Because clientBuildReply() fails we just - * call this reply a body, set the done_copying flag and - * continue... - */ - /* RBC: Note that this is seriously broken, as we *need* the - * metadata to allow further client modules to work. As such - * webservers are seriously broken, this is probably not - * going to get fixed.. perhapos we should remove it? - */ - debug (88,0)("Broken head response - probably phttpd/0.99.72\n"); - http->flags.done_copying = 1; - flags.complete = 1; - /* - * And as this is a malformed HTTP reply we cannot keep - * the connection persistent - */ - http->request->flags.proxy_keepalive = 0; - - StoreIOBuffer tempBuffer; - assert(body_buf && body_size); - tempBuffer.length = body_size; - tempBuffer.data = body_buf; - clientStreamCallback((clientStreamNode *)http->client_stream.head->data, - http, NULL, tempBuffer); + /* + * If we are here, then store_status == STORE_OK and it + * seems we have a HEAD repsponse which is missing the + * empty end-of-headers line (home.mira.net, phttpd/0.99.72 + * does this). Because clientBuildReply() fails we just + * call this reply a body, set the done_copying flag and + * continue... + */ + /* RBC: Note that this is seriously broken, as we *need* the + * metadata to allow further client modules to work. As such + * webservers are seriously broken, this is probably not + * going to get fixed.. perhapos we should remove it? + */ + debug (88,0)("Broken head response - probably phttpd/0.99.72\n"); + http->flags.done_copying = 1; + flags.complete = 1; + /* + * And as this is a malformed HTTP reply we cannot keep + * the connection persistent + */ + http->request->flags.proxy_keepalive = 0; + + StoreIOBuffer tempBuffer; + assert(body_buf && body_size); + tempBuffer.length = body_size; + tempBuffer.data = body_buf; + clientStreamCallback((clientStreamNode *)http->client_stream.head->data, + http, NULL, tempBuffer); } else { - debug (88,0)("clientReplyContext::sendMoreData: Unable to parse reply headers within a single HTTP_REQBUF_SZ length buffer\n"); - StoreIOBuffer tempBuffer; - tempBuffer.flags.error = 1; - sendStreamError(tempBuffer); - return; + debug (88,0)("clientReplyContext::sendMoreData: Unable to parse reply headers within a single HTTP_REQBUF_SZ length buffer\n"); + StoreIOBuffer tempBuffer; + tempBuffer.flags.error = 1; + sendStreamError(tempBuffer); + return; } + fatal ("clientReplyContext::sendMoreData: Unreachable code reached \n"); } @@ -1986,11 +2202,14 @@ int clientReplyBodyTooLarge(HttpReply const * rep, ssize_t clen) { if (0 == rep->maxBodySize) - return 0; /* disabled */ + return 0; /* disabled */ + if (clen < 0) - return 0; /* unknown */ + return 0; /* unknown */ + if ((unsigned int)clen > rep->maxBodySize) - return 1; /* too large */ + return 1; /* too large */ + return 0; } @@ -2004,14 +2223,14 @@ clientOnlyIfCached(clientHttpRequest * http) const request_t *r = http->request; assert(r); return r->cache_control && - EBIT_TEST(r->cache_control->mask, CC_ONLY_IF_CACHED); + EBIT_TEST(r->cache_control->mask, CC_ONLY_IF_CACHED); } /* Using this breaks the client layering just a little! */ StoreEntry * clientCreateStoreEntry(clientReplyContext * context, method_t m, - request_flags flags) + request_flags flags) { clientHttpRequest *h = context->http; StoreEntry *e; @@ -2020,27 +2239,37 @@ clientCreateStoreEntry(clientReplyContext * context, method_t m, * For erroneous requests, we might not have a h->request, * so make a fake one. */ + if (h->request == NULL) - h->request = requestLink(requestCreate(m, PROTO_NONE, null_string)); + h->request = requestLink(requestCreate(m, PROTO_NONE, null_string)); + e = storeCreateEntry(h->uri, h->log_uri, flags, m); + context->sc = storeClientListAdd(e, context); + #if DELAY_POOLS + context->sc->setDelayId(DelayId::DelayClient(h)); + #endif + context->reqofs = 0; + context->reqsize = 0; + /* I don't think this is actually needed! -- adrian */ /* h->reqbuf = h->norm_reqbuf; */ -// assert(h->reqbuf == h->norm_reqbuf); + // assert(h->reqbuf == h->norm_reqbuf); /* The next line is illegal because we don't know if the client stream * buffers have been set up */ -// storeClientCopy(h->sc, e, 0, HTTP_REQBUF_SZ, h->reqbuf, + // storeClientCopy(h->sc, e, 0, HTTP_REQBUF_SZ, h->reqbuf, // clientSendMoreData, context); /* So, we mark the store logic as complete */ context->flags.storelogiccomplete = 1; + /* and get the caller to request a read, from whereever they are */ - /* NOTE: after ANY data flows down the pipe, even one step, + /* NOTE: after ANY data flows down the pipe, even one step, * this function CAN NOT be used to manage errors */ return e; @@ -2048,13 +2277,17 @@ clientCreateStoreEntry(clientReplyContext * context, method_t m, ErrorState * clientBuildError(err_type page_id, http_status status, char const *url, - struct in_addr * src_addr, request_t * request) + + struct in_addr * src_addr, request_t * request) { ErrorState *err = errorCon(page_id, status); err->src_addr = *src_addr; + if (url) - err->url = xstrdup(url); + err->url = xstrdup(url); + if (request) - err->request = requestLink(request); + err->request = requestLink(request); + return err; } diff --git a/src/client_side_request.cc b/src/client_side_request.cc index f3ed03b4ae..89a8e7e504 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side_request.cc,v 1.17 2003/02/21 19:53:01 hno Exp $ + * $Id: client_side_request.cc,v 1.18 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 85 Client-side Request Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -55,8 +55,10 @@ static const char *const crlf = "\r\n"; -class ClientRequestContext { - public: +class ClientRequestContext +{ + +public: void *operator new(size_t); void operator delete(void *); void deleteSelf() const; @@ -64,13 +66,14 @@ class ClientRequestContext { ClientRequestContext(); ClientRequestContext(ClientHttpRequest *); ~ClientRequestContext(); - + void checkNoCache(); ACLChecklist *acl_checklist; /* need ptr back so we can unreg if needed */ int redirect_state; clientHttpRequest *http; - private: + +private: CBDATA_CLASS(ClientRequestContext); static void CheckNoCacheDone(int answer, void *data); void checkNoCacheDone(int answer); @@ -89,7 +92,7 @@ ClientRequestContext::operator new (size_t size) cbdataReference(result); return result; } - + void ClientRequestContext::operator delete (void *address) { @@ -120,14 +123,14 @@ static void checkFailureRatio(err_type, hier_code); ClientRequestContext::~ClientRequestContext() { if (http) - cbdataReferenceDone(http); + cbdataReferenceDone(http); + if (acl_checklist) - delete acl_checklist; + delete acl_checklist; } ClientRequestContext::ClientRequestContext() : acl_checklist (NULL), redirect_state (REDIRECT_NONE), http(NULL) -{ -} +{} ClientRequestContext::ClientRequestContext(ClientHttpRequest *newHttp) : acl_checklist (NULL), redirect_state (REDIRECT_NONE), http(cbdataReference(newHttp)) { @@ -148,7 +151,7 @@ ClientHttpRequest::operator new (size_t size) return result; } -void +void ClientHttpRequest::operator delete (void *address) { ClientHttpRequest *temp = static_cast(address); @@ -190,28 +193,43 @@ checkFailureRatio(err_type etype, hier_code hcode) static double magic_factor = 100.0; double n_good; double n_bad; + if (hcode == HIER_NONE) - return; + return; + n_good = magic_factor / (1.0 + request_failure_ratio); + n_bad = magic_factor - n_good; + switch (etype) { + case ERR_DNS_FAIL: + case ERR_CONNECT_FAIL: + case ERR_READ_ERROR: - n_bad++; - break; + n_bad++; + break; + default: - n_good++; + n_good++; } + request_failure_ratio = n_bad / n_good; + if (hit_only_mode_until > squid_curtime) - return; + return; + if (request_failure_ratio < 1.0) - return; + return; + debug(33, 0) ("Failure Ratio at %4.2f\n", request_failure_ratio); + debug(33, 0) ("Going into hit-only-mode for %d minutes...\n", - FAILURE_MODE_TIME / 60); + FAILURE_MODE_TIME / 60); + hit_only_mode_until = squid_curtime + FAILURE_MODE_TIME; + request_failure_ratio = 0.8; /* reset to something less than 1.0 */ } @@ -221,20 +239,26 @@ ClientHttpRequest::~ClientHttpRequest() /* if body_connection !NULL, then ProcessBody has not * found the end of the body yet */ + if (request && request->body_connection) - clientAbortBody(request); /* abort body transter */ + clientAbortBody(request); /* abort body transter */ + /* the ICP check here was erroneous * - storeReleaseRequest was always called if entry was valid */ assert(logType < LOG_TYPE_MAX); + logRequest(); + if (request) - checkFailureRatio(request->errType, al.hier.code); + checkFailureRatio(request->errType, al.hier.code); + freeResources(); + /* moving to the next connection is handled by the context free */ dlinkDelete(&active, &ClientActiveRequests); } - + /* Create a request and kick it off */ /* * TODO: Pass in the buffers to be used in the inital Read request, as they are @@ -242,12 +266,12 @@ ClientHttpRequest::~ClientHttpRequest() */ int /* returns nonzero on failure */ clientBeginRequest(method_t method, char const *url, CSCB * streamcallback, - CSD * streamdetach, void *streamdata, HttpHeader const *header, - char *tailbuf, size_t taillen) + CSD * streamdetach, void *streamdata, HttpHeader const *header, + char *tailbuf, size_t taillen) { size_t url_sz; http_version_t http_ver = - {1, 0}; + {1, 0}; clientHttpRequest *http = new ClientHttpRequest; request_t *request; StoreIOBuffer tempBuffer; @@ -260,39 +284,44 @@ clientBeginRequest(method_t method, char const *url, CSCB * streamcallback, tempBuffer.data = tailbuf; /* client stream setup */ clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach, - clientReplyStatus, clientReplyNewContext(http), streamcallback, - streamdetach, streamdata, tempBuffer); + clientReplyStatus, clientReplyNewContext(http), streamcallback, + streamdetach, streamdata, tempBuffer); /* make it visible in the 'current acctive requests list' */ dlinkAdd(http, &http->active, &ClientActiveRequests); /* Set flags */ http->flags.accel = 1; /* internal requests only makes sense in an - * accelerator today. TODO: accept flags ? */ + * accelerator today. TODO: accept flags ? */ /* allow size for url rewriting */ url_sz = strlen(url) + Config.appendDomainLen + 5; http->uri = (char *)xcalloc(url_sz, 1); strcpy(http->uri, url); if ((request = urlParse(method, http->uri)) == NULL) { - debug(85, 5) ("Invalid URL: %s\n", http->uri); - return -1; + debug(85, 5) ("Invalid URL: %s\n", http->uri); + return -1; } + /* * now update the headers in request with our supplied headers. urLParse * should return a blank header set, but we use Update to be sure of * correctness. */ if (header) - httpHeaderUpdate(&request->header, header, NULL); + httpHeaderUpdate(&request->header, header, NULL); + http->log_uri = xstrdup(urlCanonicalClean(request)); + /* http struct now ready */ /* * build new header list *? TODO */ request->flags.accelerated = http->flags.accel; + request->flags.internalclient = 1; /* this is an internally created - * request, not subject to acceleration - * target overrides */ + + * request, not subject to acceleration + * target overrides */ /* * FIXME? Do we want to detect and handle internal requests of internal * objects ? @@ -300,14 +329,20 @@ clientBeginRequest(method_t method, char const *url, CSCB * streamcallback, /* Internally created requests cannot have bodies today */ request->content_length = 0; + request->client_addr = no_addr; + request->my_addr = no_addr; /* undefined for internal requests */ + request->my_port = 0; + request->http_ver = http_ver; + http->request = requestLink(request); /* optional - skip the access check ? */ clientAccessCheck(http); + return 0; } @@ -317,7 +352,7 @@ clientAccessCheck(ClientHttpRequest *http) { ClientRequestContext *context = new ClientRequestContext(http); context->acl_checklist = - clientAclChecklistCreate(Config.accessList.http, http); + clientAclChecklistCreate(Config.accessList.http, http); context->acl_checklist->nonBlockingCheck(clientAccessCheckDone, context); } @@ -325,72 +360,77 @@ void clientAccessCheckDone(int answer, void *data) { ClientRequestContext *context = (ClientRequestContext *)data; - + clientHttpRequest *http_ = context->http; if (!cbdataReferenceValid (http_)) { - context->deleteSelf(); - return; + context->deleteSelf(); + return; } - + clientHttpRequest *http = context->http; err_type page_id; http_status status; char const *proxy_auth_msg = NULL; debug(85, 2) ("The request %s %s is %s, because it matched '%s'\n", - RequestMethodStr[http->request->method], http->uri, - answer == ACCESS_ALLOWED ? "ALLOWED" : "DENIED", - AclMatchedName ? AclMatchedName : "NO ACL's"); + RequestMethodStr[http->request->method], http->uri, + answer == ACCESS_ALLOWED ? "ALLOWED" : "DENIED", + AclMatchedName ? AclMatchedName : "NO ACL's"); proxy_auth_msg = authenticateAuthUserRequestMessage((http->conn - && http->conn->auth_user_request) ? http->conn-> - auth_user_request : http->request->auth_user_request); + && http->conn->auth_user_request) ? http->conn-> + auth_user_request : http->request->auth_user_request); context->acl_checklist = NULL; + if (answer == ACCESS_ALLOWED) { - safe_free(http->uri); - http->uri = xstrdup(urlCanonical(http->request)); - assert(context->redirect_state == REDIRECT_NONE); - context->redirect_state = REDIRECT_PENDING; - redirectStart(http, clientRedirectDone, context); + safe_free(http->uri); + http->uri = xstrdup(urlCanonical(http->request)); + assert(context->redirect_state == REDIRECT_NONE); + context->redirect_state = REDIRECT_PENDING; + redirectStart(http, clientRedirectDone, context); } else { - /* Send an error */ - clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data; - context->deleteSelf(); - debug(85, 5) ("Access Denied: %s\n", http->uri); - debug(85, 5) ("AclMatchedName = %s\n", - AclMatchedName ? AclMatchedName : ""); - debug(85, 5) ("Proxy Auth Message = %s\n", - proxy_auth_msg ? proxy_auth_msg : ""); - /* - * NOTE: get page_id here, based on AclMatchedName because if - * USE_DELAY_POOLS is enabled, then AclMatchedName gets clobbered in - * the clientCreateStoreEntry() call just below. Pedro Ribeiro - * - */ - page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName); - http->logType = LOG_TCP_DENIED; - if (answer == ACCESS_REQ_PROXY_AUTH || aclIsProxyAuth(AclMatchedName)) { - if (!http->flags.accel) { - /* Proxy authorisation needed */ - status = HTTP_PROXY_AUTHENTICATION_REQUIRED; - } else { - /* WWW authorisation needed */ - status = HTTP_UNAUTHORIZED; - } - if (page_id == ERR_NONE) - page_id = ERR_CACHE_ACCESS_DENIED; - } else { - status = HTTP_FORBIDDEN; - if (page_id == ERR_NONE) - page_id = ERR_ACCESS_DENIED; - } - clientSetReplyToError(node->data, page_id, status, - http->request->method, NULL, - http->conn ? &http->conn->peer.sin_addr : &no_addr, http->request, - NULL, http->conn - && http->conn->auth_user_request ? http->conn-> - auth_user_request : http->request->auth_user_request); - node = (clientStreamNode *)http->client_stream.tail->data; - clientStreamRead(node, http, node->readBuffer); + /* Send an error */ + clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data; + context->deleteSelf(); + debug(85, 5) ("Access Denied: %s\n", http->uri); + debug(85, 5) ("AclMatchedName = %s\n", + AclMatchedName ? AclMatchedName : ""); + debug(85, 5) ("Proxy Auth Message = %s\n", + proxy_auth_msg ? proxy_auth_msg : ""); + /* + * NOTE: get page_id here, based on AclMatchedName because if + * USE_DELAY_POOLS is enabled, then AclMatchedName gets clobbered in + * the clientCreateStoreEntry() call just below. Pedro Ribeiro + * + */ + page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName); + http->logType = LOG_TCP_DENIED; + + if (answer == ACCESS_REQ_PROXY_AUTH || aclIsProxyAuth(AclMatchedName)) { + if (!http->flags.accel) { + /* Proxy authorisation needed */ + status = HTTP_PROXY_AUTHENTICATION_REQUIRED; + } else { + /* WWW authorisation needed */ + status = HTTP_UNAUTHORIZED; + } + + if (page_id == ERR_NONE) + page_id = ERR_CACHE_ACCESS_DENIED; + } else { + status = HTTP_FORBIDDEN; + + if (page_id == ERR_NONE) + page_id = ERR_ACCESS_DENIED; + } + + clientSetReplyToError(node->data, page_id, status, + http->request->method, NULL, + http->conn ? &http->conn->peer.sin_addr : &no_addr, http->request, + NULL, http->conn + && http->conn->auth_user_request ? http->conn-> + auth_user_request : http->request->auth_user_request); + node = (clientStreamNode *)http->client_stream.tail->data; + clientStreamRead(node, http, node->readBuffer); } } @@ -399,28 +439,37 @@ clientCachable(clientHttpRequest * http) { request_t *req = http->request; method_t method = req->method; + if (req->protocol == PROTO_HTTP) - return httpCachable(method); + return httpCachable(method); + /* FTP is always cachable */ if (req->protocol == PROTO_WAIS) - return 0; + return 0; + /* * The below looks questionable: what non HTTP protocols use connect, * trace, put and post? RC */ if (method == METHOD_CONNECT) - return 0; + return 0; + if (method == METHOD_TRACE) - return 0; + return 0; + if (method == METHOD_PUT) - return 0; + return 0; + if (method == METHOD_POST) - return 0; /* XXX POST may be cached sometimes.. ignored - * for now */ + return 0; /* XXX POST may be cached sometimes.. ignored + + * for now */ if (req->protocol == PROTO_GOPHER) - return gopherCachable(req); + return gopherCachable(req); + if (req->protocol == PROTO_CACHEOBJ) - return 0; + return 0; + return 1; } @@ -436,32 +485,43 @@ clientHierarchical(clientHttpRequest * http) * IMS needs a private key, so we can use the hierarchy for IMS only if our * neighbors support private keys */ + if (request->flags.ims && !neighbors_do_private_keys) - return 0; + return 0; + /* * This is incorrect: authenticating requests can be sent via a hierarchy * (they can even be cached if the correct headers are set on the reply */ if (request->flags.auth) - return 0; + return 0; + if (method == METHOD_TRACE) - return 1; + return 1; + if (method != METHOD_GET) - return 0; + return 0; + /* scan hierarchy_stoplist */ for (p = Config.hierarchy_stoplist; p; p = p->next) - if (strstr(url, p->key)) - return 0; + if (strstr(url, p->key)) + return 0; + if (request->flags.loopdetect) - return 0; + return 0; + if (request->protocol == PROTO_HTTP) - return httpCachable(method); + return httpCachable(method); + if (request->protocol == PROTO_GOPHER) - return gopherCachable(request); + return gopherCachable(request); + if (request->protocol == PROTO_WAIS) - return 0; + return 0; + if (request->protocol == PROTO_CACHEOBJ) - return 0; + return 0; + return 1; } @@ -473,127 +533,160 @@ clientInterpretRequestHeaders(clientHttpRequest * http) const HttpHeader *req_hdr = &request->header; int no_cache = 0; #if !defined(ESI) || defined(USE_USERAGENT_LOG) || defined(USE_REFERER_LOG) + const char *str; #endif + request->imslen = -1; request->ims = httpHeaderGetTime(req_hdr, HDR_IF_MODIFIED_SINCE); + if (request->ims > 0) - request->flags.ims = 1; + request->flags.ims = 1; + #if ESI /* * We ignore Cache-Control as per the Edge Architecture Section 3. See * www.esi.org for more information. */ #else + if (httpHeaderHas(req_hdr, HDR_PRAGMA)) { - String s = httpHeaderGetList(req_hdr, HDR_PRAGMA); - if (strListIsMember(&s, "no-cache", ',')) - no_cache++; - s.clean(); + String s = httpHeaderGetList(req_hdr, HDR_PRAGMA); + + if (strListIsMember(&s, "no-cache", ',')) + no_cache++; + + s.clean(); } + request->cache_control = httpHeaderGetCc(req_hdr); + if (request->cache_control) - if (EBIT_TEST(request->cache_control->mask, CC_NO_CACHE)) - no_cache++; + if (EBIT_TEST(request->cache_control->mask, CC_NO_CACHE)) + no_cache++; + /* - * Work around for supporting the Reload button in IE browsers when Squid - * is used as an accelerator or transparent proxy, by turning accelerated - * IMS request to no-cache requests. Now knows about IE 5.5 fix (is - * actually only fixed in SP1, but we can't tell whether we are talking to - * SP1 or not so all 5.5 versions are treated 'normally'). - */ + * Work around for supporting the Reload button in IE browsers when Squid + * is used as an accelerator or transparent proxy, by turning accelerated + * IMS request to no-cache requests. Now knows about IE 5.5 fix (is + * actually only fixed in SP1, but we can't tell whether we are talking to + * SP1 or not so all 5.5 versions are treated 'normally'). + */ if (Config.onoff.ie_refresh) { - if (http->flags.accel && request->flags.ims) { - if ((str = httpHeaderGetStr(req_hdr, HDR_USER_AGENT))) { - if (strstr(str, "MSIE 5.01") != NULL) - no_cache++; - else if (strstr(str, "MSIE 5.0") != NULL) - no_cache++; - else if (strstr(str, "MSIE 4.") != NULL) - no_cache++; - else if (strstr(str, "MSIE 3.") != NULL) - no_cache++; - } - } + if (http->flags.accel && request->flags.ims) { + if ((str = httpHeaderGetStr(req_hdr, HDR_USER_AGENT))) { + if (strstr(str, "MSIE 5.01") != NULL) + no_cache++; + else if (strstr(str, "MSIE 5.0") != NULL) + no_cache++; + else if (strstr(str, "MSIE 4.") != NULL) + no_cache++; + else if (strstr(str, "MSIE 3.") != NULL) + no_cache++; + } + } } + #endif if (no_cache) { #if HTTP_VIOLATIONS - if (Config.onoff.reload_into_ims) - request->flags.nocache_hack = 1; - else if (refresh_nocache_hack) - request->flags.nocache_hack = 1; - else + + if (Config.onoff.reload_into_ims) + request->flags.nocache_hack = 1; + else if (refresh_nocache_hack) + request->flags.nocache_hack = 1; + else #endif - request->flags.nocache = 1; + + request->flags.nocache = 1; } + /* ignore range header in non-GETs */ if (request->method == METHOD_GET) { - request->range = httpHeaderGetRange(req_hdr); - if (request->range) { - request->flags.range = 1; - clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->data; - /* XXX: This is suboptimal. We should give the stream the range set, - * and thereby let the top of the stream set the offset when the - * size becomes known. As it is, we will end up requesting from 0 - * for evey -X range specification. - * RBC - this may be somewhat wrong. We should probably set the range - * iter up at this point. - */ - node->readBuffer.offset = request->range->lowestOffset(0); - http->range_iter.pos = request->range->begin(); - http->range_iter.valid = true; - } + request->range = httpHeaderGetRange(req_hdr); + + if (request->range) { + request->flags.range = 1; + clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->data; + /* XXX: This is suboptimal. We should give the stream the range set, + * and thereby let the top of the stream set the offset when the + * size becomes known. As it is, we will end up requesting from 0 + * for evey -X range specification. + * RBC - this may be somewhat wrong. We should probably set the range + * iter up at this point. + */ + node->readBuffer.offset = request->range->lowestOffset(0); + http->range_iter.pos = request->range->begin(); + http->range_iter.valid = true; + } } + if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION)) - request->flags.auth = 1; + request->flags.auth = 1; + if (request->login[0] != '\0') - request->flags.auth = 1; + request->flags.auth = 1; + if (httpHeaderHas(req_hdr, HDR_VIA)) { - String s = httpHeaderGetList(req_hdr, HDR_VIA); - /* - * ThisCache cannot be a member of Via header, "1.0 ThisCache" can. - * Note ThisCache2 has a space prepended to the hostname so we don't - * accidentally match super-domains. - */ - if (strListIsSubstr(&s, ThisCache2, ',')) { - debugObj(33, 1, "WARNING: Forwarding loop detected for:\n", - request, (ObjPackMethod) & httpRequestPack); - request->flags.loopdetect = 1; - } + String s = httpHeaderGetList(req_hdr, HDR_VIA); + /* + * ThisCache cannot be a member of Via header, "1.0 ThisCache" can. + * Note ThisCache2 has a space prepended to the hostname so we don't + * accidentally match super-domains. + */ + + if (strListIsSubstr(&s, ThisCache2, ',')) { + debugObj(33, 1, "WARNING: Forwarding loop detected for:\n", + request, (ObjPackMethod) & httpRequestPack); + request->flags.loopdetect = 1; + } + #if FORW_VIA_DB - fvdbCountVia(s.buf()); + fvdbCountVia(s.buf()); + #endif - s.clean(); + + s.clean(); } + #if USE_USERAGENT_LOG if ((str = httpHeaderGetStr(req_hdr, HDR_USER_AGENT))) - logUserAgent(fqdnFromAddr(http->conn ? http->conn->log_addr : no_addr), str); + logUserAgent(fqdnFromAddr(http->conn ? http->conn->log_addr : no_addr), str); + #endif #if USE_REFERER_LOG + if ((str = httpHeaderGetStr(req_hdr, HDR_REFERER))) - logReferer(fqdnFromAddr(http->conn ? http->conn->log_addr : no_addr), str, http->log_uri); + logReferer(fqdnFromAddr(http->conn ? http->conn->log_addr : no_addr), str, http->log_uri); + #endif #if FORW_VIA_DB + if (httpHeaderHas(req_hdr, HDR_X_FORWARDED_FOR)) { - String s = httpHeaderGetList(req_hdr, HDR_X_FORWARDED_FOR); - fvdbCountForw(s.buf()); - s.clean(); + String s = httpHeaderGetList(req_hdr, HDR_X_FORWARDED_FOR); + fvdbCountForw(s.buf()); + s.clean(); } + #endif if (request->method == METHOD_TRACE) { - request->max_forwards = httpHeaderGetInt(req_hdr, HDR_MAX_FORWARDS); + request->max_forwards = httpHeaderGetInt(req_hdr, HDR_MAX_FORWARDS); } + if (clientCachable(http)) - request->flags.cachable = 1; + request->flags.cachable = 1; + if (clientHierarchical(http)) - request->flags.hierarchical = 1; + request->flags.hierarchical = 1; + debug(85, 5) ("clientInterpretRequestHeaders: REQ_NOCACHE = %s\n", - request->flags.nocache ? "SET" : "NOT SET"); + request->flags.nocache ? "SET" : "NOT SET"); + debug(85, 5) ("clientInterpretRequestHeaders: REQ_CACHABLE = %s\n", - request->flags.cachable ? "SET" : "NOT SET"); + request->flags.cachable ? "SET" : "NOT SET"); + debug(85, 5) ("clientInterpretRequestHeaders: REQ_HIERARCHICAL = %s\n", - request->flags.hierarchical ? "SET" : "NOT SET"); + request->flags.hierarchical ? "SET" : "NOT SET"); } void @@ -603,64 +696,77 @@ clientRedirectDone(void *data, char *result) clientHttpRequest *http_ = context->http; if (!cbdataReferenceValid (http_)) { - context->deleteSelf(); - return; + context->deleteSelf(); + return; } - + clientHttpRequest *http = context->http; request_t *new_request = NULL; request_t *old_request = http->request; debug(85, 5) ("clientRedirectDone: '%s' result=%s\n", http->uri, - result ? result : "NULL"); + result ? result : "NULL"); assert(context->redirect_state == REDIRECT_PENDING); context->redirect_state = REDIRECT_DONE; + if (result) { - http_status status = (http_status) atoi(result); - if (status == HTTP_MOVED_PERMANENTLY - || status == HTTP_MOVED_TEMPORARILY - || status == HTTP_SEE_OTHER - || status == HTTP_TEMPORARY_REDIRECT) { - char *t = result; - if ((t = strchr(result, ':')) != NULL) { - http->redirect.status = status; - http->redirect.location = xstrdup(t + 1); - } else { - debug(85, 1) ("clientRedirectDone: bad input: %s\n", result); - } - } - if (strcmp(result, http->uri)) - new_request = urlParse(old_request->method, result); + http_status status = (http_status) atoi(result); + + if (status == HTTP_MOVED_PERMANENTLY + || status == HTTP_MOVED_TEMPORARILY + || status == HTTP_SEE_OTHER + || status == HTTP_TEMPORARY_REDIRECT) { + char *t = result; + + if ((t = strchr(result, ':')) != NULL) { + http->redirect.status = status; + http->redirect.location = xstrdup(t + 1); + } else { + debug(85, 1) ("clientRedirectDone: bad input: %s\n", result); + } + } + + if (strcmp(result, http->uri)) + new_request = urlParse(old_request->method, result); } + if (new_request) { - safe_free(http->uri); - http->uri = xstrdup(urlCanonical(new_request)); - new_request->http_ver = old_request->http_ver; - httpHeaderAppend(&new_request->header, &old_request->header); - new_request->client_addr = old_request->client_addr; - new_request->my_addr = old_request->my_addr; - new_request->my_port = old_request->my_port; - new_request->flags = old_request->flags; - if (old_request->auth_user_request) { - new_request->auth_user_request = old_request->auth_user_request; - authenticateAuthUserRequestLock(new_request->auth_user_request); - } - if (old_request->body_connection) { - new_request->body_connection = old_request->body_connection; - old_request->body_connection = NULL; - } - new_request->content_length = old_request->content_length; - new_request->flags.proxy_keepalive = old_request->flags.proxy_keepalive; - requestUnlink(old_request); - http->request = requestLink(new_request); + safe_free(http->uri); + http->uri = xstrdup(urlCanonical(new_request)); + new_request->http_ver = old_request->http_ver; + httpHeaderAppend(&new_request->header, &old_request->header); + new_request->client_addr = old_request->client_addr; + new_request->my_addr = old_request->my_addr; + new_request->my_port = old_request->my_port; + new_request->flags = old_request->flags; + + if (old_request->auth_user_request) { + new_request->auth_user_request = old_request->auth_user_request; + authenticateAuthUserRequestLock(new_request->auth_user_request); + } + + if (old_request->body_connection) { + new_request->body_connection = old_request->body_connection; + old_request->body_connection = NULL; + } + + new_request->content_length = old_request->content_length; + new_request->flags.proxy_keepalive = old_request->flags.proxy_keepalive; + requestUnlink(old_request); + http->request = requestLink(new_request); } + clientInterpretRequestHeaders(http); #if HEADERS_LOG + headersLog(0, 1, request->method, request); #endif /* FIXME PIPELINE: This is innacurate during pipelining */ + if (http->conn) - fd_note(http->conn->fd, http->uri); + fd_note(http->conn->fd, http->uri); + assert(http->uri); + context->checkNoCache(); } @@ -668,11 +774,11 @@ void ClientRequestContext::checkNoCache() { if (Config.accessList.noCache && http->request->flags.cachable) { - acl_checklist = - clientAclChecklistCreate(Config.accessList.noCache, http); - acl_checklist->nonBlockingCheck(CheckNoCacheDone, cbdataReference(this)); + acl_checklist = + clientAclChecklistCreate(Config.accessList.noCache, http); + acl_checklist->nonBlockingCheck(CheckNoCacheDone, cbdataReference(this)); } else { - CheckNoCacheDone(http->request->flags.cachable, cbdataReference(this)); + CheckNoCacheDone(http->request->flags.cachable, cbdataReference(this)); } } @@ -689,15 +795,15 @@ ClientRequestContext::CheckNoCacheDone(int answer, void *data) void ClientRequestContext::checkNoCacheDone(int answer) -{ +{ acl_checklist = NULL; clientHttpRequest *http_ = http; if (!cbdataReferenceValid (http_)) { - deleteSelf(); - return; + deleteSelf(); + return; } - + deleteSelf(); http_->request->flags.cachable = answer; http_->processRequest(); @@ -712,12 +818,14 @@ void ClientHttpRequest::processRequest() { debug(85, 4) ("clientProcessRequest: %s '%s'\n", - RequestMethodStr[request->method], uri); + RequestMethodStr[request->method], uri); + if (request->method == METHOD_CONNECT) { - logType = LOG_TCP_MISS; - sslStart(this, &out.size, &al.http.code); - return; + logType = LOG_TCP_MISS; + sslStart(this, &out.size, &al.http.code); + return; } + httpStart(); } @@ -726,7 +834,7 @@ ClientHttpRequest::httpStart() { logType = LOG_TAG_NONE; debug(85, 4) ("ClientHttpRequest::httpStart: %s for '%s'\n", - log_tags[logType], uri); + log_tags[logType], uri); /* no one should have touched this */ assert(out.offset == 0); /* Use the Stream Luke */ diff --git a/src/client_side_request.h b/src/client_side_request.h index 05d514e727..33805c6931 100644 --- a/src/client_side_request.h +++ b/src/client_side_request.h @@ -1,6 +1,6 @@ /* - * $Id: client_side_request.h,v 1.6 2003/02/05 10:36:50 robertc Exp $ + * $Id: client_side_request.h,v 1.7 2003/02/21 22:50:07 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -41,9 +41,12 @@ extern int clientBeginRequest(method_t, char const *, CSCB *, CSD *, void *, HttpHeader const *, char *, size_t); class MemObject; + typedef class ClientHttpRequest clientHttpRequest; -class ClientHttpRequest { +class ClientHttpRequest +{ + public: void *operator new (size_t); void operator delete (void *); @@ -54,7 +57,7 @@ public: /* Not implemented - present to prevent synthetic operations */ ClientHttpRequest(ClientHttpRequest const &); ClientHttpRequest& operator=(ClientHttpRequest const &); - + String rangeBoundaryStr() const; void freeResources(); void updateCounters(); @@ -67,32 +70,54 @@ public: request_t *request; /* Parsed URL ... */ char *uri; char *log_uri; - struct { - off_t offset; - size_t size; - size_t headers_sz; - } out; + + struct + { + off_t offset; + size_t size; + size_t headers_sz; + } + + out; HttpHdrRangeIter range_iter; /* data for iterating thru range specs */ size_t req_sz; /* raw request size on input, not current request size */ StoreEntry *entry; StoreEntry *old_entry; log_type logType; + struct timeval start; http_version_t http_ver; AccessLogEntry al; - struct { - unsigned int accel:1; - unsigned int internal:1; - unsigned int done_copying:1; - unsigned int purging:1; - } flags; - struct { - http_status status; - char *location; - } redirect; + + struct + { + +unsigned int accel: + 1; + +unsigned int internal: + 1; + +unsigned int done_copying: + 1; + +unsigned int purging: + 1; + } + + flags; + + struct + { + http_status status; + char *location; + } + + redirect; dlink_node active; dlink_list client_stream; int mRangeCLen(); + private: CBDATA_CLASS(ClientHttpRequest); }; diff --git a/src/comm.cc b/src/comm.cc index 25863e49e8..b0a111eecd 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1,6 +1,6 @@ /* - * $Id: comm.cc,v 1.365 2003/02/14 13:59:49 robertc Exp $ + * $Id: comm.cc,v 1.366 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -52,21 +52,27 @@ */ #define MAX_ACCEPT_PER_LOOP 10 -typedef struct { +typedef struct +{ char *host; u_short port; + struct sockaddr_in S; CNCB *callback; void *data; + struct in_addr in_addr; int locks; int fd; int tries; int addrcount; int connstart; -} ConnectStateData; +} + +ConnectStateData; /* STATIC */ + static comm_err_t commBind(int s, struct in_addr, u_short port); static void commSetReuseAddr(int); static void commSetNoLinger(int); @@ -86,81 +92,108 @@ CBDATA_TYPE(ConnectStateData); static PF comm_accept_try; -class AcceptFD { - public: +class AcceptFD +{ + +public: int check_delay; IOACB *handler; void *handler_data; }; -struct _fdc_t { - int active; - int fd; - dlink_list CommCallbackList; - struct { - char *buf; - int size; - IOCB *handler; - void *handler_data; - } read; - struct { - const char *buf; - int size; - int curofs; - IOCB *handler; - void *handler_data; - } write; - struct { - /* how often (in msec) to re-check if we're out of fds on an accept() */ - struct sockaddr_in & me() {return connDetails.me;} - struct sockaddr_in & pn() {return connDetails.peer;} - AcceptFD accept; - ConnectionDetail connDetails; - } accept; - struct CommFiller { - StoreIOBuffer requestedData; - size_t amountDone; - IOFCB *handler; - void *handler_data; - } fill; +struct _fdc_t +{ + int active; + int fd; + dlink_list CommCallbackList; + + struct + { + char *buf; + int size; + IOCB *handler; + void *handler_data; + } + + read; + + struct + { + const char *buf; + int size; + int curofs; + IOCB *handler; + void *handler_data; + } + + write; + + struct + { + /* how often (in msec) to re-check if we're out of fds on an accept() */ + + struct sockaddr_in & me() {return connDetails.me;} + + struct sockaddr_in & pn() {return connDetails.peer;} + + AcceptFD accept; + ConnectionDetail connDetails; + } + + accept; + + struct CommFiller + { + StoreIOBuffer requestedData; + size_t amountDone; + IOFCB *handler; + void *handler_data; + } + + fill; }; + typedef struct _fdc_t fdc_t; typedef enum { - COMM_CB_READ = 1, - COMM_CB_WRITE, - COMM_CB_ACCEPT, - COMM_CB_FILL + COMM_CB_READ = 1, + COMM_CB_WRITE, + COMM_CB_ACCEPT, + COMM_CB_FILL } comm_callback_t; -struct _CommCallbackData { - comm_callback_t type; - dlink_node fd_node; - dlink_node h_node; - int fd; - int newfd; /* for accept() */ - char *buf; - int retval; - union { - IOCB *r_callback; - IOACB *a_callback; - IOFCB *f_callback; - IOWCB *w_callback; - } c; - void *callback_data; - comm_err_t errcode; - int xerrno; - int seqnum; - ConnectionDetail details; - StoreIOBuffer sb; +struct _CommCallbackData +{ + comm_callback_t type; + dlink_node fd_node; + dlink_node h_node; + int fd; + int newfd; /* for accept() */ + char *buf; + int retval; + union { + IOCB *r_callback; + IOACB *a_callback; + IOFCB *f_callback; + IOWCB *w_callback; + } c; + void *callback_data; + comm_err_t errcode; + int xerrno; + int seqnum; + ConnectionDetail details; + StoreIOBuffer sb; }; + typedef struct _CommCallbackData CommCallbackData; -struct _fd_debug_t { - char *close_file; - int close_line; +struct _fd_debug_t +{ + char *close_file; + int close_line; }; + typedef struct _fd_debug_t fd_debug_t; static MemPool *comm_write_pool = NULL; @@ -180,7 +213,7 @@ static int CommCallbackSeqnum = 1; int comm_existsiocallback(void) { - return CommCallbackList.head == NULL; + return CommCallbackList.head == NULL; } /* @@ -192,31 +225,31 @@ comm_existsiocallback(void) */ static void comm_addreadcallback(int fd, IOCB *callback, char *buf, size_t retval, comm_err_t errcode, - int xerrno, void *callback_data) + int xerrno, void *callback_data) { - CommCallbackData *cio; + CommCallbackData *cio; - assert(fdc_table[fd].active == 1); + assert(fdc_table[fd].active == 1); - /* Allocate a new struct */ - cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); + /* Allocate a new struct */ + cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); - /* Throw our data into it */ - cio->fd = fd; - cio->retval = retval; - cio->xerrno = xerrno; - cio->errcode = errcode; - cio->c.r_callback = callback; - cio->callback_data = callback_data; - cio->seqnum = CommCallbackSeqnum; - cio->buf = buf; - cio->type = COMM_CB_READ; + /* Throw our data into it */ + cio->fd = fd; + cio->retval = retval; + cio->xerrno = xerrno; + cio->errcode = errcode; + cio->c.r_callback = callback; + cio->callback_data = callback_data; + cio->seqnum = CommCallbackSeqnum; + cio->buf = buf; + cio->type = COMM_CB_READ; - /* Add it to the end of the list */ - dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); + /* Add it to the end of the list */ + dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); - /* and add it to the end of the fd list */ - dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); + /* and add it to the end of the fd list */ + dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); } @@ -225,94 +258,94 @@ comm_addreadcallback(int fd, IOCB *callback, char *buf, size_t retval, comm_err_ static void comm_addacceptcallback(int fd, int newfd, IOACB *callback, ConnectionDetail details, comm_err_t errcode, int xerrno, void *callback_data) { - CommCallbackData *cio; + CommCallbackData *cio; - assert(fdc_table[fd].active == 1); + assert(fdc_table[fd].active == 1); - /* Allocate a new struct */ - cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); + /* Allocate a new struct */ + cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); - /* Throw our data into it */ - cio->fd = fd; - cio->xerrno = xerrno; - cio->errcode = errcode; - cio->c.a_callback = callback; - cio->callback_data = callback_data; - cio->seqnum = CommCallbackSeqnum; - cio->type = COMM_CB_ACCEPT; - cio->newfd = newfd; - cio->details = details; + /* Throw our data into it */ + cio->fd = fd; + cio->xerrno = xerrno; + cio->errcode = errcode; + cio->c.a_callback = callback; + cio->callback_data = callback_data; + cio->seqnum = CommCallbackSeqnum; + cio->type = COMM_CB_ACCEPT; + cio->newfd = newfd; + cio->details = details; - /* Add it to the end of the list */ - dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); + /* Add it to the end of the list */ + dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); - /* and add it to the end of the fd list */ - dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); + /* and add it to the end of the fd list */ + dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); } static void comm_add_fill_callback(int fd, size_t retval, comm_err_t errcode, int xerrno) { - CommCallbackData *cio; + CommCallbackData *cio; - assert(fdc_table[fd].active == 1); + assert(fdc_table[fd].active == 1); - /* Allocate a new struct */ - cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); + /* Allocate a new struct */ + cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); - /* Throw our data into it */ - cio->fd = fd; - cio->xerrno = xerrno; - cio->errcode = errcode; - cio->c.f_callback = fdc_table[fd].fill.handler; - cio->callback_data = fdc_table[fd].fill.handler_data; - cio->seqnum = CommCallbackSeqnum; - cio->type = COMM_CB_FILL; - /* retval not used */ - cio->retval = -1; - cio->sb = fdc_table[fd].fill.requestedData; - cio->sb.length = retval; - /* Clear out fd state */ - fdc_table[fd].fill.handler = NULL; - fdc_table[fd].fill.handler_data = NULL; + /* Throw our data into it */ + cio->fd = fd; + cio->xerrno = xerrno; + cio->errcode = errcode; + cio->c.f_callback = fdc_table[fd].fill.handler; + cio->callback_data = fdc_table[fd].fill.handler_data; + cio->seqnum = CommCallbackSeqnum; + cio->type = COMM_CB_FILL; + /* retval not used */ + cio->retval = -1; + cio->sb = fdc_table[fd].fill.requestedData; + cio->sb.length = retval; + /* Clear out fd state */ + fdc_table[fd].fill.handler = NULL; + fdc_table[fd].fill.handler_data = NULL; - /* Add it to the end of the list */ - dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); + /* Add it to the end of the list */ + dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); - /* and add it to the end of the fd list */ - dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); + /* and add it to the end of the fd list */ + dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); } static void comm_add_write_callback(int fd, size_t retval, comm_err_t errcode, int xerrno) { - CommCallbackData *cio; + CommCallbackData *cio; - assert(fdc_table[fd].active == 1); + assert(fdc_table[fd].active == 1); - /* Allocate a new struct */ - cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); + /* Allocate a new struct */ + cio = (CommCallbackData *)memPoolAlloc(comm_callback_pool); - /* Throw our data into it */ - cio->fd = fd; - cio->xerrno = xerrno; - cio->errcode = errcode; - cio->c.w_callback = fdc_table[fd].write.handler; - cio->callback_data = fdc_table[fd].write.handler_data; - cio->seqnum = CommCallbackSeqnum; - cio->type = COMM_CB_WRITE; - cio->retval = retval; + /* Throw our data into it */ + cio->fd = fd; + cio->xerrno = xerrno; + cio->errcode = errcode; + cio->c.w_callback = fdc_table[fd].write.handler; + cio->callback_data = fdc_table[fd].write.handler_data; + cio->seqnum = CommCallbackSeqnum; + cio->type = COMM_CB_WRITE; + cio->retval = retval; - /* Clear out fd state */ - fdc_table[fd].write.handler = NULL; - fdc_table[fd].write.handler_data = NULL; + /* Clear out fd state */ + fdc_table[fd].write.handler = NULL; + fdc_table[fd].write.handler_data = NULL; - /* Add it to the end of the list */ - dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); + /* Add it to the end of the list */ + dlinkAddTail(cio, &(cio->h_node), &CommCallbackList); - /* and add it to the end of the fd list */ - dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); + /* and add it to the end of the fd list */ + dlinkAddTail(cio, &(cio->fd_node), &(fdc_table[fd].CommCallbackList)); } @@ -320,27 +353,32 @@ comm_add_write_callback(int fd, size_t retval, comm_err_t errcode, int xerrno) static void comm_call_io_callback(CommCallbackData *cio) { - switch(cio->type) { - case COMM_CB_READ: - cio->c.r_callback(cio->fd, cio->buf, cio->retval, cio->errcode, cio->xerrno, - cio->callback_data); - break; - case COMM_CB_WRITE: - cio->c.w_callback(cio->fd, cio->buf, cio->retval, cio->errcode, cio->xerrno, - cio->callback_data); - break; - case COMM_CB_ACCEPT: - cio->c.a_callback(cio->fd, cio->newfd, &cio->details, cio->errcode, - cio->xerrno, cio->callback_data); - break; - case COMM_CB_FILL: - cio->c.f_callback(cio->fd, cio->sb, cio->errcode, - cio->xerrno, cio->callback_data); - break; - default: - fatal("unknown comm io callback type!"); - break; - }; + switch(cio->type) { + + case COMM_CB_READ: + cio->c.r_callback(cio->fd, cio->buf, cio->retval, cio->errcode, cio->xerrno, + cio->callback_data); + break; + + case COMM_CB_WRITE: + cio->c.w_callback(cio->fd, cio->buf, cio->retval, cio->errcode, cio->xerrno, + cio->callback_data); + break; + + case COMM_CB_ACCEPT: + cio->c.a_callback(cio->fd, cio->newfd, &cio->details, cio->errcode, + cio->xerrno, cio->callback_data); + break; + + case COMM_CB_FILL: + cio->c.f_callback(cio->fd, cio->sb, cio->errcode, + cio->xerrno, cio->callback_data); + break; + + default: + fatal("unknown comm io callback type!"); + break; + }; } @@ -359,26 +397,31 @@ comm_call_io_callback(CommCallbackData *cio) void comm_calliocallback(void) { - CommCallbackData *cio; - dlink_node *node; - int oldseqnum = CommCallbackSeqnum; + CommCallbackData *cio; + dlink_node *node; + int oldseqnum = CommCallbackSeqnum; + + /* Call our callbacks until we hit NULL or the seqnum changes */ + + while (CommCallbackList.head != NULL) { + node = (dlink_node *)CommCallbackList.head; + cio = (CommCallbackData *)node->data; + + /* If seqnum isn't the same, its time to die */ + + if (cio->seqnum != oldseqnum) + break; /* we've hit newly-added events */ + + assert(fdc_table[cio->fd].active == 1); - /* Call our callbacks until we hit NULL or the seqnum changes */ - while (CommCallbackList.head != NULL) { - node = (dlink_node *)CommCallbackList.head; - cio = (CommCallbackData *)node->data; + dlinkDelete(&cio->h_node, &CommCallbackList); - /* If seqnum isn't the same, its time to die */ - if (cio->seqnum != oldseqnum) - break; /* we've hit newly-added events */ + dlinkDelete(&cio->fd_node, &(fdc_table[cio->fd].CommCallbackList)); - assert(fdc_table[cio->fd].active == 1); + comm_call_io_callback(cio); - dlinkDelete(&cio->h_node, &CommCallbackList); - dlinkDelete(&cio->fd_node, &(fdc_table[cio->fd].CommCallbackList)); - comm_call_io_callback(cio); - memPoolFree(comm_callback_pool, cio); - } + memPoolFree(comm_callback_pool, cio); + } } @@ -388,14 +431,14 @@ comm_calliocallback(void) static void comm_read_callback(int fd, int retval, comm_err_t errcode, int xerrno) { - fdc_t *Fc = &fdc_table[fd]; + fdc_t *Fc = &fdc_table[fd]; - assert(Fc->read.handler != NULL); + assert(Fc->read.handler != NULL); - comm_addreadcallback(fd, Fc->read.handler, Fc->read.buf, retval, errcode, xerrno, - Fc->read.handler_data); - Fc->read.handler = NULL; - Fc->read.handler_data = NULL; + comm_addreadcallback(fd, Fc->read.handler, Fc->read.buf, retval, errcode, xerrno, + Fc->read.handler_data); + Fc->read.handler = NULL; + Fc->read.handler_data = NULL; } /* @@ -407,34 +450,35 @@ comm_read_callback(int fd, int retval, comm_err_t errcode, int xerrno) static void comm_read_try(int fd, void *data) { - fdc_t *Fc = &fdc_table[fd]; - int retval; - - /* make sure we actually have a callback */ - assert(Fc->read.handler != NULL); + fdc_t *Fc = &fdc_table[fd]; + int retval; - /* Attempt a read */ - statCounter.syscalls.sock.reads++; - errno = 0; - retval = FD_READ_METHOD(fd, Fc->read.buf, Fc->read.size); - debug(5, 3) ("comm_read_try: fd %d, size %d, retval %d, errno %d\n", - fd, Fc->read.size, retval, errno); - if (retval < 0 && !ignoreErrno(errno)) { - debug(5, 3) ("comm_read_try: scheduling COMM_ERROR\n"); - comm_read_callback(fd, -1, COMM_ERROR, errno); - return; - }; + /* make sure we actually have a callback */ + assert(Fc->read.handler != NULL); - /* See if we read anything */ - /* Note - read 0 == socket EOF, which is a valid read */ - if (retval >= 0) { - fd_bytes(fd, retval, FD_READ); - comm_read_callback(fd, retval, COMM_OK, 0); - return; - } + /* Attempt a read */ + statCounter.syscalls.sock.reads++; + errno = 0; + retval = FD_READ_METHOD(fd, Fc->read.buf, Fc->read.size); + debug(5, 3) ("comm_read_try: fd %d, size %d, retval %d, errno %d\n", + fd, Fc->read.size, retval, errno); + + if (retval < 0 && !ignoreErrno(errno)) { + debug(5, 3) ("comm_read_try: scheduling COMM_ERROR\n"); + comm_read_callback(fd, -1, COMM_ERROR, errno); + return; + }; + + /* See if we read anything */ + /* Note - read 0 == socket EOF, which is a valid read */ + if (retval >= 0) { + fd_bytes(fd, retval, FD_READ); + comm_read_callback(fd, retval, COMM_OK, 0); + return; + } - /* Nope, register for some more IO */ - commSetSelect(fd, COMM_SELECT_READ, comm_read_try, NULL, 0); + /* Nope, register for some more IO */ + commSetSelect(fd, COMM_SELECT_READ, comm_read_try, NULL, 0); } /* @@ -444,24 +488,25 @@ comm_read_try(int fd, void *data) void comm_read(int fd, char *buf, int size, IOCB *handler, void *handler_data) { - /* Make sure we're not reading anything and we're not closing */ - assert(fdc_table[fd].active == 1); - assert(fdc_table[fd].read.handler == NULL); - assert(!fd_table[fd].flags.closing); + /* Make sure we're not reading anything and we're not closing */ + assert(fdc_table[fd].active == 1); + assert(fdc_table[fd].read.handler == NULL); + assert(!fd_table[fd].flags.closing); - debug(5,4)("comm_read, queueing read for FD %d\n",fd); + debug(5,4)("comm_read, queueing read for FD %d\n",fd); - /* Queue a read */ - fdc_table[fd].read.buf = buf; - fdc_table[fd].read.size = size; - fdc_table[fd].read.handler = handler; - fdc_table[fd].read.handler_data = handler_data; + /* Queue a read */ + fdc_table[fd].read.buf = buf; + fdc_table[fd].read.size = size; + fdc_table[fd].read.handler = handler; + fdc_table[fd].read.handler_data = handler_data; #if OPTIMISTIC_IO - comm_read_try(fd, NULL); + + comm_read_try(fd, NULL); #else - /* Register intrest in a FD read */ - commSetSelect(fd, COMM_SELECT_READ, comm_read_try, NULL, 0); + /* Register intrest in a FD read */ + commSetSelect(fd, COMM_SELECT_READ, comm_read_try, NULL, 0); #endif } @@ -475,18 +520,23 @@ comm_fill_read(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void if (flag != COMM_OK) { /* Error! */ - /* XXX This was -1 below, but -1 can't be used for size_t parameters. - * The callback should set -1 to the client if needed based on the flags - */ - comm_add_fill_callback(fd, 0, flag, xerrno); - return; + /* XXX This was -1 below, but -1 can't be used for size_t parameters. + * The callback should set -1 to the client if needed based on the flags + */ + comm_add_fill_callback(fd, 0, flag, xerrno); + return; } + /* flag is COMM_OK */ /* We handle EOFs as read lengths of 0! Its eww, but its consistent */ fill = &fdc_table[fd].fill; + fill->amountDone += len; + sb = &fdc_table[fd].fill.requestedData; + assert(fill->amountDone <= sb->length); + comm_add_fill_callback(fd, fill->amountDone, COMM_OK, 0); } @@ -524,8 +574,11 @@ comm_empty_os_read_buffers(int fd) #ifdef _SQUID_LINUX_ /* prevent those nasty RST packets */ char buf[SQUID_TCP_SO_RCVBUF]; + if (fd_table[fd].flags.nonblocking == 1) - while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0); + while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0) + + ; #endif } @@ -552,11 +605,14 @@ comm_has_pending_read_callback(int fd) * - adrian */ node = fdc_table[fd].CommCallbackList.head; + while (node != NULL) { - cd = (CommCallbackData *)node->data; - if (cd->type == COMM_CB_READ) - return 1; - node = node->next; + cd = (CommCallbackData *)node->data; + + if (cd->type == COMM_CB_READ) + return 1; + + node = node->next; } /* Not found */ @@ -572,10 +628,10 @@ comm_has_pending_read_callback(int fd) bool comm_has_pending_read(int fd) { - assert(fd_table[fd].flags.open == 1); - assert(fdc_table[fd].active == 1); + assert(fd_table[fd].flags.open == 1); + assert(fdc_table[fd].active == 1); - return (fdc_table[fd].read.handler != NULL); + return (fdc_table[fd].read.handler != NULL); } /* @@ -600,7 +656,7 @@ comm_read_cancel(int fd, IOCB *callback, void *data) fdc_table[fd].read.handler_data = NULL; /* And the IO event */ - commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); + commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); } @@ -611,12 +667,12 @@ comm_read_cancel(int fd, IOCB *callback, void *data) void fdc_open(int fd, unsigned int type, char *desc) { - assert(fdc_table[fd].active == 0); + assert(fdc_table[fd].active == 0); - fdc_table[fd].active = 1; - fdc_table[fd].fd = fd; - comm_accept_setcheckperiod(fd, 250); - fd_open(fd, type, desc); + fdc_table[fd].active = 1; + fdc_table[fd].fd = fd; + comm_accept_setcheckperiod(fd, 250); + fd_open(fd, type, desc); } @@ -626,22 +682,23 @@ fdc_open(int fd, unsigned int type, char *desc) int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) + + struct sockaddr *from, socklen_t *fromlen) { - statCounter.syscalls.sock.recvfroms++; - return recvfrom(fd, buf, len, flags, from, fromlen); + statCounter.syscalls.sock.recvfroms++; + return recvfrom(fd, buf, len, flags, from, fromlen); } int comm_udp_recv(int fd, void *buf, size_t len, int flags) { - return comm_udp_recvfrom(fd, buf, len, flags, NULL, 0); + return comm_udp_recvfrom(fd, buf, len, flags, NULL, 0); } ssize_t comm_udp_send(int s, const void *buf, size_t len, int flags) { - return send(s, buf, len, flags); + return send(s, buf, len, flags); } @@ -657,38 +714,39 @@ comm_udp_send(int s, const void *buf, size_t len, int flags) static void comm_write_try(int fd, void *data) { - fdc_t *Fc = &fdc_table[fd]; - int retval; + fdc_t *Fc = &fdc_table[fd]; + int retval; - /* make sure we actually have a callback */ - assert(Fc->write.handler != NULL); + /* make sure we actually have a callback */ + assert(Fc->write.handler != NULL); - /* Attempt a write */ - statCounter.syscalls.sock.reads++; - errno = 0; - retval = FD_WRITE_METHOD(fd, Fc->write.buf + Fc->write.curofs, Fc->write.size - Fc->write.curofs); - debug(5, 3) ("comm_write_try: fd %d: tried to write %d bytes, retval %d, errno %d\n", - fd, Fc->write.size - Fc->write.curofs, retval, errno); + /* Attempt a write */ + statCounter.syscalls.sock.reads++; + errno = 0; + retval = FD_WRITE_METHOD(fd, Fc->write.buf + Fc->write.curofs, Fc->write.size - Fc->write.curofs); + debug(5, 3) ("comm_write_try: fd %d: tried to write %d bytes, retval %d, errno %d\n", + fd, Fc->write.size - Fc->write.curofs, retval, errno); + + if (retval < 0 && !ignoreErrno(errno)) { + debug(5, 3) ("comm_write_try: can't ignore error: scheduling COMM_ERROR callback\n"); + comm_add_write_callback(fd, 0, COMM_ERROR, errno); + return; + } - if (retval < 0 && !ignoreErrno(errno)) { - debug(5, 3) ("comm_write_try: can't ignore error: scheduling COMM_ERROR callback\n"); - comm_add_write_callback(fd, 0, COMM_ERROR, errno); - return; - } + if (retval >= 0) { + fd_bytes(fd, retval, FD_WRITE); + Fc->write.curofs += retval; + assert(Fc->write.curofs <= Fc->write.size); + /* All? */ - if (retval >= 0) { - fd_bytes(fd, retval, FD_WRITE); - Fc->write.curofs += retval; - assert(Fc->write.curofs <= Fc->write.size); - /* All? */ - if (Fc->write.curofs == Fc->write.size) { - comm_add_write_callback(fd, Fc->write.size, COMM_OK, 0); - return; - } - } + if (Fc->write.curofs == Fc->write.size) { + comm_add_write_callback(fd, Fc->write.size, COMM_OK, 0); + return; + } + } - /* if we get here, we need to write more! */ - commSetSelect(fd, COMM_SELECT_WRITE, comm_write_try, NULL, 0); + /* if we get here, we need to write more! */ + commSetSelect(fd, COMM_SELECT_WRITE, comm_write_try, NULL, 0); } /* @@ -698,23 +756,24 @@ comm_write_try(int fd, void *data) void comm_write(int fd, const char *buf, size_t size, IOWCB *handler, void *handler_data) { - /* Make sure we're not writing anything and we're not closing */ - assert(fdc_table[fd].active == 1); - assert(fdc_table[fd].write.handler == NULL); - assert(!fd_table[fd].flags.closing); + /* Make sure we're not writing anything and we're not closing */ + assert(fdc_table[fd].active == 1); + assert(fdc_table[fd].write.handler == NULL); + assert(!fd_table[fd].flags.closing); - /* Queue a read */ - fdc_table[fd].write.buf = buf; - fdc_table[fd].write.size = size; - fdc_table[fd].write.handler = handler; - fdc_table[fd].write.handler_data = handler_data; - fdc_table[fd].write.curofs = 0; + /* Queue a read */ + fdc_table[fd].write.buf = buf; + fdc_table[fd].write.size = size; + fdc_table[fd].write.handler = handler; + fdc_table[fd].write.handler_data = handler_data; + fdc_table[fd].write.curofs = 0; #if OPTIMISTIC_IO - comm_write_try(fd, NULL); + + comm_write_try(fd, NULL); #else - /* Register intrest in a FD read */ - commSetSelect(fd, COMM_SELECT_WRITE, comm_write_try, NULL, 0); + /* Register intrest in a FD read */ + commSetSelect(fd, COMM_SELECT_WRITE, comm_write_try, NULL, 0); #endif } @@ -735,9 +794,9 @@ comm_write(int fd, const char *buf, size_t size, IOWCB *handler, void *handler_d void comm_accept_setcheckperiod(int fd, int mdelay) { - assert(fdc_table[fd].active == 1); - assert(mdelay != 0); - fdc_table[fd].accept.accept.check_delay = mdelay; + assert(fdc_table[fd].active == 1); + assert(mdelay != 0); + fdc_table[fd].accept.accept.check_delay = mdelay; } /* @@ -746,19 +805,21 @@ comm_accept_setcheckperiod(int fd, int mdelay) static void comm_accept_check_event(void *data) { - static time_t last_warn = 0; - int fd = ((fdc_t *)(data))->fd; + static time_t last_warn = 0; + int fd = ((fdc_t *)(data))->fd; - if (fdNFree() < RESERVED_FD) { - commSetSelect(fd, COMM_SELECT_READ, comm_accept_try, NULL, 0); - return; - } - if (last_warn + 15 < squid_curtime) { - debug(33, 0) ("WARNING! Your cache is running out of filedescriptors\n"); - last_warn = squid_curtime; - } - eventAdd("comm_accept_check_event", comm_accept_check_event, &fdc_table[fd], - 1000.0 / (double)(fdc_table[fd].accept.accept.check_delay), 1); + if (fdNFree() < RESERVED_FD) { + commSetSelect(fd, COMM_SELECT_READ, comm_accept_try, NULL, 0); + return; + } + + if (last_warn + 15 < squid_curtime) { + debug(33, 0) ("WARNING! Your cache is running out of filedescriptors\n"); + last_warn = squid_curtime; + } + + eventAdd("comm_accept_check_event", comm_accept_check_event, &fdc_table[fd], + 1000.0 / (double)(fdc_table[fd].accept.accept.check_delay), 1); } @@ -772,19 +833,24 @@ CommWriteStateCallbackAndFree(int fd, comm_err_t code) CWCB *callback = NULL; void *cbdata; fd_table[fd].rwstate = NULL; + if (CommWriteState == NULL) - return; + return; + if (CommWriteState->free_func) { - FREE *free_func = CommWriteState->free_func; - void *free_buf = CommWriteState->buf; - CommWriteState->free_func = NULL; - CommWriteState->buf = NULL; - free_func(free_buf); + FREE *free_func = CommWriteState->free_func; + void *free_buf = CommWriteState->buf; + CommWriteState->free_func = NULL; + CommWriteState->buf = NULL; + free_func(free_buf); } + callback = CommWriteState->handler; CommWriteState->handler = NULL; + if (callback && cbdataReferenceValidDone(CommWriteState->handler_data, &cbdata)) - callback(fd, CommWriteState->buf, CommWriteState->offset, code, cbdata); + callback(fd, CommWriteState->buf, CommWriteState->offset, code, cbdata); + memPoolFree(comm_write_pool, CommWriteState); } @@ -792,30 +858,38 @@ CommWriteStateCallbackAndFree(int fd, comm_err_t code) u_short comm_local_port(int fd) { + struct sockaddr_in addr; socklen_t addr_len = 0; fde *F = &fd_table[fd]; /* If the fd is closed already, just return */ + if (!F->flags.open) { - debug(5, 0) ("comm_local_port: FD %d has been closed.\n", fd); - return 0; + debug(5, 0) ("comm_local_port: FD %d has been closed.\n", fd); + return 0; } + if (F->local_port) - return F->local_port; + return F->local_port; + addr_len = sizeof(addr); + if (getsockname(fd, (struct sockaddr *) &addr, &addr_len)) { - debug(50, 1) ("comm_local_port: Failed to retrieve TCP/UDP port number for socket: FD %d: %s\n", fd, xstrerror()); - return 0; + debug(50, 1) ("comm_local_port: Failed to retrieve TCP/UDP port number for socket: FD %d: %s\n", fd, xstrerror()); + return 0; } + F->local_port = ntohs(addr.sin_port); debug(5, 6) ("comm_local_port: FD %d: port %d\n", fd, (int) F->local_port); return F->local_port; } static comm_err_t + commBind(int s, struct in_addr in_addr, u_short port) { + struct sockaddr_in S; memset(&S, '\0', sizeof(S)); @@ -823,13 +897,16 @@ commBind(int s, struct in_addr in_addr, u_short port) S.sin_port = htons(port); S.sin_addr = in_addr; statCounter.syscalls.sock.binds++; + if (bind(s, (struct sockaddr *) &S, sizeof(S)) == 0) - return COMM_OK; + return COMM_OK; + debug(50, 0) ("commBind: Cannot bind socket FD %d to %s:%d: %s\n", - s, - S.sin_addr.s_addr == INADDR_ANY ? "*" : inet_ntoa(S.sin_addr), - (int) port, - xstrerror()); + s, + S.sin_addr.s_addr == INADDR_ANY ? "*" : inet_ntoa(S.sin_addr), + (int) port, + xstrerror()); + return COMM_ERROR; } @@ -837,11 +914,12 @@ commBind(int s, struct in_addr in_addr, u_short port) * is OR of flags specified in comm.h. Defaults TOS */ int comm_open(int sock_type, - int proto, - struct in_addr addr, - u_short port, - int flags, - const char *note) + int proto, + + struct in_addr addr, + u_short port, + int flags, + const char *note) { return comm_openex(sock_type, proto, addr, port, flags, 0, note); } @@ -851,12 +929,13 @@ comm_open(int sock_type, * is OR of flags specified in defines.h:COMM_* */ int comm_openex(int sock_type, - int proto, - struct in_addr addr, - u_short port, - int flags, - unsigned char TOS, - const char *note) + int proto, + + struct in_addr addr, + u_short port, + int flags, + unsigned char TOS, + const char *note) { int new_socket; int tos = 0; @@ -865,73 +944,110 @@ comm_openex(int sock_type, PROF_start(comm_open); /* Create socket for accepting new connections. */ statCounter.syscalls.sock.sockets++; - if ((new_socket = socket(AF_INET, sock_type, proto)) < 0) { - /* Increase the number of reserved fd's if calls to socket() - * are failing because the open file table is full. This - * limits the number of simultaneous clients */ - switch (errno) { - case ENFILE: - case EMFILE: - debug(50, 1) ("comm_open: socket failure: %s\n", xstrerror()); - fdAdjustReserved(); - break; - default: - debug(50, 0) ("comm_open: socket failure: %s\n", xstrerror()); - } - PROF_stop(comm_open); - return -1; + + if ((new_socket = socket(AF_INET, sock_type, proto)) < 0) + { + /* Increase the number of reserved fd's if calls to socket() + * are failing because the open file table is full. This + * limits the number of simultaneous clients */ + + switch (errno) { + + case ENFILE: + + case EMFILE: + debug(50, 1) ("comm_open: socket failure: %s\n", xstrerror()); + fdAdjustReserved(); + break; + + default: + debug(50, 0) ("comm_open: socket failure: %s\n", xstrerror()); + } + + PROF_stop(comm_open); + return -1; } + /* set TOS if needed */ - if (TOS) { + if (TOS) + { #ifdef IP_TOS - tos = TOS; - if (setsockopt(new_socket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) - debug(50, 1) ("comm_open: setsockopt(IP_TOS) on FD %d: %s\n", - new_socket, xstrerror()); + tos = TOS; + + if (setsockopt(new_socket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) + debug(50, 1) ("comm_open: setsockopt(IP_TOS) on FD %d: %s\n", + new_socket, xstrerror()); + #else - debug(50, 0) ("comm_open: setsockopt(IP_TOS) not supported on this platform\n"); + + debug(50, 0) ("comm_open: setsockopt(IP_TOS) not supported on this platform\n"); + #endif + } + /* update fdstat */ debug(5, 5) ("comm_open: FD %d is a new socket\n", new_socket); + fd_open(new_socket, FD_SOCKET, note); + fdd_table[new_socket].close_file = NULL; + fdd_table[new_socket].close_line = 0; + assert(fdc_table[new_socket].active == 0); + fdc_table[new_socket].active = 1; + F = &fd_table[new_socket]; + F->local_addr = addr; + F->tos = tos; + if (!(flags & COMM_NOCLOEXEC)) - commSetCloseOnExec(new_socket); + commSetCloseOnExec(new_socket); + if ((flags & COMM_REUSEADDR)) - commSetReuseAddr(new_socket); - if (port > (u_short) 0) { - commSetNoLinger(new_socket); - if (opt_reuseaddr) - commSetReuseAddr(new_socket); + commSetReuseAddr(new_socket); + + if (port > (u_short) 0) + { + commSetNoLinger(new_socket); + + if (opt_reuseaddr) + commSetReuseAddr(new_socket); } - if (addr.s_addr != no_addr.s_addr) { - if (commBind(new_socket, addr, port) != COMM_OK) { - comm_close(new_socket); - return -1; - PROF_stop(comm_open); - } + + if (addr.s_addr != no_addr.s_addr) + { + if (commBind(new_socket, addr, port) != COMM_OK) { + comm_close(new_socket); + return -1; + PROF_stop(comm_open); + } } + F->local_port = port; if (flags & COMM_NONBLOCKING) - if (commSetNonBlocking(new_socket) == COMM_ERROR) { - return -1; - PROF_stop(comm_open); - } + if (commSetNonBlocking(new_socket) == COMM_ERROR) + { + return -1; + PROF_stop(comm_open); + } + #ifdef TCP_NODELAY if (sock_type == SOCK_STREAM) - commSetTcpNoDelay(new_socket); + commSetTcpNoDelay(new_socket); + #endif + if (Config.tcpRcvBufsz > 0 && sock_type == SOCK_STREAM) - commSetTcpRcvbuf(new_socket, Config.tcpRcvBufsz); + commSetTcpRcvbuf(new_socket, Config.tcpRcvBufsz); + PROF_stop(comm_open); + return new_socket; } @@ -957,16 +1073,20 @@ commConnectDnsHandle(const ipcache_addrs * ia, void *data) ConnectStateData *cs = (ConnectStateData *)data; assert(cs->locks == 1); cs->locks--; + if (ia == NULL) { - debug(5, 3) ("commConnectDnsHandle: Unknown host: %s\n", cs->host); - if (!dns_error_message) { - dns_error_message = "Unknown DNS error"; - debug(5, 1) ("commConnectDnsHandle: Bad dns_error_message\n"); - } - assert(dns_error_message != NULL); - commConnectCallback(cs, COMM_ERR_DNS); - return; + debug(5, 3) ("commConnectDnsHandle: Unknown host: %s\n", cs->host); + + if (!dns_error_message) { + dns_error_message = "Unknown DNS error"; + debug(5, 1) ("commConnectDnsHandle: Bad dns_error_message\n"); + } + + assert(dns_error_message != NULL); + commConnectCallback(cs, COMM_ERR_DNS); + return; } + assert(ia->cur < ia->count); cs->in_addr = ia->in_addrs[ia->cur]; ipcacheCycleAddr(cs->host, NULL); @@ -987,8 +1107,10 @@ commConnectCallback(ConnectStateData * cs, comm_err_t status) cs->data = NULL; commSetTimeout(fd, -1, NULL, NULL); commConnectFree(fd, cs); + if (cbdataReferenceValid(cbdata)) - callback(fd, status, cbdata); + callback(fd, status, cbdata); + cbdataReferenceDone(cbdata); } @@ -1008,24 +1130,36 @@ commResetFD(ConnectStateData * cs) { int fd2; fde *F; + if (!cbdataReferenceValid(cs->data)) - return 0; + return 0; + statCounter.syscalls.sock.sockets++; + fd2 = socket(AF_INET, SOCK_STREAM, 0); + statCounter.syscalls.sock.sockets++; + if (fd2 < 0) { - debug(5, 0) ("commResetFD: socket: %s\n", xstrerror()); - if (ENFILE == errno || EMFILE == errno) - fdAdjustReserved(); - return 0; + debug(5, 0) ("commResetFD: socket: %s\n", xstrerror()); + + if (ENFILE == errno || EMFILE == errno) + fdAdjustReserved(); + + return 0; } + if (dup2(fd2, cs->fd) < 0) { - debug(5, 0) ("commResetFD: dup2: %s\n", xstrerror()); - if (ENFILE == errno || EMFILE == errno) - fdAdjustReserved(); - close(fd2); - return 0; + debug(5, 0) ("commResetFD: dup2: %s\n", xstrerror()); + + if (ENFILE == errno || EMFILE == errno) + fdAdjustReserved(); + + close(fd2); + + return 0; } + close(fd2); F = &fd_table[cs->fd]; fd_table[cs->fd].flags.called_connect = 0; @@ -1033,27 +1167,37 @@ commResetFD(ConnectStateData * cs) * yuck, this has assumptions about comm_open() arguments for * the original socket */ + if (commBind(cs->fd, F->local_addr, F->local_port) != COMM_OK) { - debug(5, 0) ("commResetFD: bind: %s\n", xstrerror()); - return 0; + debug(5, 0) ("commResetFD: bind: %s\n", xstrerror()); + return 0; } + #ifdef IP_TOS if (F->tos) { - int tos = F->tos; - if (setsockopt(cs->fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) - debug(50, 1) ("commResetFD: setsockopt(IP_TOS) on FD %d: %s\n", cs->fd, xstrerror()); + int tos = F->tos; + + if (setsockopt(cs->fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) + debug(50, 1) ("commResetFD: setsockopt(IP_TOS) on FD %d: %s\n", cs->fd, xstrerror()); } + #endif if (F->flags.close_on_exec) - commSetCloseOnExec(cs->fd); + commSetCloseOnExec(cs->fd); + if (F->flags.nonblocking) - commSetNonBlocking(cs->fd); + commSetNonBlocking(cs->fd); + #ifdef TCP_NODELAY + if (F->flags.nodelay) - commSetTcpNoDelay(cs->fd); + commSetTcpNoDelay(cs->fd); + #endif + if (Config.tcpRcvBufsz > 0) - commSetTcpRcvbuf(cs->fd, Config.tcpRcvBufsz); + commSetTcpRcvbuf(cs->fd, Config.tcpRcvBufsz); + return 1; } @@ -1061,15 +1205,18 @@ static int commRetryConnect(ConnectStateData * cs) { assert(cs->addrcount > 0); + if (cs->addrcount == 1) { - if (cs->tries >= Config.retry.maxtries) - return 0; - if (squid_curtime - cs->connstart > Config.Timeout.connect) - return 0; + if (cs->tries >= Config.retry.maxtries) + return 0; + + if (squid_curtime - cs->connstart > Config.Timeout.connect) + return 0; } else { - if (cs->tries > cs->addrcount) - return 0; + if (cs->tries > cs->addrcount) + return 0; } + return commResetFD(cs); } @@ -1078,34 +1225,43 @@ static void commConnectHandle(int fd, void *data) { ConnectStateData *cs = (ConnectStateData *)data; + if (cs->S.sin_addr.s_addr == 0) { - cs->S.sin_family = AF_INET; - cs->S.sin_addr = cs->in_addr; - cs->S.sin_port = htons(cs->port); - if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(cs->S.sin_addr, FQDN_LOOKUP_IF_MISS); + cs->S.sin_family = AF_INET; + cs->S.sin_addr = cs->in_addr; + cs->S.sin_port = htons(cs->port); + + if (Config.onoff.log_fqdn) + fqdncache_gethostbyaddr(cs->S.sin_addr, FQDN_LOOKUP_IF_MISS); } + switch (comm_connect_addr(fd, &cs->S)) { + case COMM_INPROGRESS: - debug(5, 5) ("commConnectHandle: FD %d: COMM_INPROGRESS\n", fd); - commSetSelect(fd, COMM_SELECT_WRITE, commConnectHandle, cs, 0); - break; + debug(5, 5) ("commConnectHandle: FD %d: COMM_INPROGRESS\n", fd); + commSetSelect(fd, COMM_SELECT_WRITE, commConnectHandle, cs, 0); + break; + case COMM_OK: - ipcacheMarkGoodAddr(cs->host, cs->S.sin_addr); - commConnectCallback(cs, COMM_OK); - break; + ipcacheMarkGoodAddr(cs->host, cs->S.sin_addr); + commConnectCallback(cs, COMM_OK); + break; + default: - cs->tries++; - ipcacheMarkBadAddr(cs->host, cs->S.sin_addr); - if (Config.onoff.test_reachability) - netdbDeleteAddrNetwork(cs->S.sin_addr); - if (commRetryConnect(cs)) { - cs->locks++; - ipcache_nbgethostbyname(cs->host, commConnectDnsHandle, cs); - } else { - commConnectCallback(cs, COMM_ERR_CONNECT); - } - break; + cs->tries++; + ipcacheMarkBadAddr(cs->host, cs->S.sin_addr); + + if (Config.onoff.test_reachability) + netdbDeleteAddrNetwork(cs->S.sin_addr); + + if (commRetryConnect(cs)) { + cs->locks++; + ipcache_nbgethostbyname(cs->host, commConnectDnsHandle, cs); + } else { + commConnectCallback(cs, COMM_ERR_CONNECT); + } + + break; } } @@ -1118,23 +1274,28 @@ commSetTimeout(int fd, int timeout, PF * handler, void *data) assert(fd < Squid_MaxFD); F = &fd_table[fd]; assert(F->flags.open); + if (timeout < 0) { - cbdataReferenceDone(F->timeout_data); - F->timeout_handler = NULL; - F->timeout = 0; + cbdataReferenceDone(F->timeout_data); + F->timeout_handler = NULL; + F->timeout = 0; } else { - assert(handler || F->timeout_handler); - if (handler) { - cbdataReferenceDone(F->timeout_data); - F->timeout_handler = handler; - F->timeout_data = cbdataReference(data); - } - F->timeout = squid_curtime + (time_t) timeout; + assert(handler || F->timeout_handler); + + if (handler) { + cbdataReferenceDone(F->timeout_data); + F->timeout_handler = handler; + F->timeout_data = cbdataReference(data); + } + + F->timeout = squid_curtime + (time_t) timeout; } + return F->timeout; } int + comm_connect_addr(int sock, const struct sockaddr_in *address) { comm_err_t status = COMM_OK; @@ -1146,54 +1307,76 @@ comm_connect_addr(int sock, const struct sockaddr_in *address) PROF_start(comm_connect_addr); /* Establish connection. */ errno = 0; - if (!F->flags.called_connect) { - F->flags.called_connect = 1; - statCounter.syscalls.sock.connects++; - x = connect(sock, (struct sockaddr *) address, sizeof(*address)); - if (x < 0) - debug(5, 9) ("connect FD %d: %s\n", sock, xstrerror()); - } else { + + if (!F->flags.called_connect) + { + F->flags.called_connect = 1; + statCounter.syscalls.sock.connects++; + + x = connect(sock, (struct sockaddr *) address, sizeof(*address)); + + if (x < 0) + debug(5, 9) ("connect FD %d: %s\n", sock, xstrerror()); + } else + { #if defined(_SQUID_NEWSOS6_) - /* Makoto MATSUSHITA */ - connect(sock, (struct sockaddr *) address, sizeof(*address)); - if (errno == EINVAL) { - errlen = sizeof(err); - x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen); - if (x >= 0) - errno = x; - } + /* Makoto MATSUSHITA */ + + connect(sock, (struct sockaddr *) address, sizeof(*address)); + + if (errno == EINVAL) { + errlen = sizeof(err); + x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen); + + if (x >= 0) + errno = x; + } + #else - errlen = sizeof(err); - x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen); - if (x == 0) - errno = err; + errlen = sizeof(err); + + x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen); + + if (x == 0) + errno = err; + #if defined(_SQUID_SOLARIS_) - /* - * Solaris 2.4's socket emulation doesn't allow you - * to determine the error from a failed non-blocking - * connect and just returns EPIPE. Create a fake - * error message for connect. -- fenner@parc.xerox.com - */ - if (x < 0 && errno == EPIPE) - errno = ENOTCONN; + /* + * Solaris 2.4's socket emulation doesn't allow you + * to determine the error from a failed non-blocking + * connect and just returns EPIPE. Create a fake + * error message for connect. -- fenner@parc.xerox.com + */ + if (x < 0 && errno == EPIPE) + errno = ENOTCONN; + #endif #endif + } + PROF_stop(comm_connect_addr); + if (errno == 0 || errno == EISCONN) - status = COMM_OK; + status = COMM_OK; else if (ignoreErrno(errno)) - status = COMM_INPROGRESS; + status = COMM_INPROGRESS; else - return COMM_ERROR; + return COMM_ERROR; + xstrncpy(F->ipaddr, inet_ntoa(address->sin_addr), 16); + F->remote_port = ntohs(address->sin_port); - if (status == COMM_OK) { - debug(5, 10) ("comm_connect_addr: FD %d connected to %s:%d\n", - sock, F->ipaddr, F->remote_port); - } else if (status == COMM_INPROGRESS) { - debug(5, 10) ("comm_connect_addr: FD %d connection pending\n", sock); + + if (status == COMM_OK) + { + debug(5, 10) ("comm_connect_addr: FD %d connected to %s:%d\n", + sock, F->ipaddr, F->remote_port); + } else if (status == COMM_INPROGRESS) + { + debug(5, 10) ("comm_connect_addr: FD %d connection pending\n", sock); } + return status; } @@ -1206,21 +1389,28 @@ comm_old_accept(int fd, ConnectionDetail &details) statCounter.syscalls.sock.accepts++; int sock; socklen_t Slen = sizeof(details.peer); + if ((sock = accept(fd, (struct sockaddr *) &details.peer, &Slen)) < 0) { - PROF_stop(comm_accept); - if (ignoreErrno(errno)) { - debug(50, 5) ("comm_old_accept: FD %d: %s\n", fd, xstrerror()); - return COMM_NOMESSAGE; - } else if (ENFILE == errno || EMFILE == errno) { - debug(50, 3) ("comm_old_accept: FD %d: %s\n", fd, xstrerror()); - return COMM_ERROR; - } else { - debug(50, 1) ("comm_old_accept: FD %d: %s\n", fd, xstrerror()); - return COMM_ERROR; - } + PROF_stop(comm_accept); + + if (ignoreErrno(errno)) + { + debug(50, 5) ("comm_old_accept: FD %d: %s\n", fd, xstrerror()); + return COMM_NOMESSAGE; + } else if (ENFILE == errno || EMFILE == errno) + { + debug(50, 3) ("comm_old_accept: FD %d: %s\n", fd, xstrerror()); + return COMM_ERROR; + } else + { + debug(50, 1) ("comm_old_accept: FD %d: %s\n", fd, xstrerror()); + return COMM_ERROR; + } } + Slen = sizeof(details.me); memset(&details.me, '\0', Slen); + getsockname(sock, (struct sockaddr *) &details.me, &Slen); commSetCloseOnExec(sock); /* fdstat update */ @@ -1242,15 +1432,18 @@ commCallCloseHandlers(int fd) { fde *F = &fd_table[fd]; debug(5, 5) ("commCallCloseHandlers: FD %d\n", fd); + while (F->closeHandler != NULL) { - close_handler ch = *F->closeHandler; - memPoolFree(conn_close_pool, F->closeHandler); /* AAA */ - F->closeHandler = ch.next; - ch.next = NULL; - debug(5, 5) ("commCallCloseHandlers: ch->handler=%p data=%p\n", ch.handler, ch.data); - if (cbdataReferenceValid(ch.data)) - ch.handler(fd, ch.data); - cbdataReferenceDone(ch.data); + close_handler ch = *F->closeHandler; + memPoolFree(conn_close_pool, F->closeHandler); /* AAA */ + F->closeHandler = ch.next; + ch.next = NULL; + debug(5, 5) ("commCallCloseHandlers: ch->handler=%p data=%p\n", ch.handler, ch.data); + + if (cbdataReferenceValid(ch.data)) + ch.handler(fd, ch.data); + + cbdataReferenceDone(ch.data); } } @@ -1261,8 +1454,10 @@ commLingerClose(int fd, void *unused) LOCAL_ARRAY(char, buf, 1024); int n; n = FD_READ_METHOD(fd, buf, 1024); + if (n < 0) - debug(5, 3) ("commLingerClose: FD %d read: %s\n", fd, xstrerror()); + debug(5, 3) ("commLingerClose: FD %d read: %s\n", fd, xstrerror()); + comm_close(fd); } @@ -1280,17 +1475,22 @@ void comm_lingering_close(int fd) { #if USE_SSL + if (fd_table[fd].ssl) - ssl_shutdown_method(fd); + ssl_shutdown_method(fd); + #endif + if (shutdown(fd, 1) < 0) { - comm_close(fd); - return; + comm_close(fd); + return; } + fd_note(fd, "lingering close"); commSetTimeout(fd, 10, commLingerTimeout, NULL); commSetSelect(fd, COMM_SELECT_READ, commLingerClose, NULL, 0); } + #endif /* @@ -1300,11 +1500,14 @@ comm_lingering_close(int fd) void comm_reset_close(int fd) { + struct linger L; L.l_onoff = 1; L.l_linger = 0; + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0) - debug(50, 0) ("commResetTCPClose: FD %d: %s\n", fd, xstrerror()); + debug(50, 0) ("commResetTCPClose: FD %d: %s\n", fd, xstrerror()); + comm_close(fd); } @@ -1331,20 +1534,31 @@ _comm_close(int fd, char *file, int line) fdd_table[fd].close_line = line; if (F->flags.closing) - return; + return; + if (shutting_down && (!F->flags.open || F->type == FD_FILE)) - return; + return; + assert(F->flags.open); + /* The following fails because ipc.c is doing calls to pipe() to create sockets! */ - assert(fdc_table[fd].active == 1); + assert(fdc_table[fd].active == 1); + assert(F->type != FD_FILE); + PROF_start(comm_close); + F->flags.closing = 1; + #if USE_SSL + if (F->ssl) - ssl_shutdown_method(fd); + ssl_shutdown_method(fd); + #endif + commSetTimeout(fd, -1, NULL, NULL); + CommWriteStateCallbackAndFree(fd, COMM_ERR_CLOSING); /* Delete any accept check */ @@ -1355,74 +1569,95 @@ _comm_close(int fd, char *file, int line) /* Do callbacks for read/accept/fill routines, if any */ if (fdc_table[fd].read.handler) { fdc_table[fd].read.handler(fd, fdc_table[fd].read.buf, 0, - COMM_ERR_CLOSING, 0, fdc_table[fd].read.handler_data); - fdc_table[fd].read.handler = NULL; + COMM_ERR_CLOSING, 0, fdc_table[fd].read.handler_data); + fdc_table[fd].read.handler = NULL; } + if (fdc_table[fd].accept.accept.handler) { fdc_table[fd].accept.accept.handler(fd, -1, NULL, COMM_ERR_CLOSING, - 0, fdc_table[fd].accept.accept.handler_data); - fdc_table[fd].accept.accept.handler = NULL; + 0, fdc_table[fd].accept.accept.handler_data); + fdc_table[fd].accept.accept.handler = NULL; } + if (fdc_table[fd].fill.handler) { fdc_table[fd].fill.handler(fd, fdc_table[fd].fill.requestedData, COMM_ERR_CLOSING, 0, - fdc_table[fd].fill.handler_data); - fdc_table[fd].fill.handler = NULL; + fdc_table[fd].fill.handler_data); + fdc_table[fd].fill.handler = NULL; } + /* Complete (w/ COMM_ERR_CLOSING!) any pending io callbacks */ while (fdc_table[fd].CommCallbackList.head != NULL) { - node = fdc_table[fd].CommCallbackList.head; - cio = (CommCallbackData *)node->data; - assert(fd == cio->fd); /* just paranoid */ - dlinkDelete(&cio->h_node, &CommCallbackList); - dlinkDelete(&cio->fd_node, &(fdc_table[cio->fd].CommCallbackList)); - /* We're closing! */ - cio->errcode = COMM_ERR_CLOSING; - comm_call_io_callback(cio); - memPoolFree(comm_callback_pool, cio); + node = fdc_table[fd].CommCallbackList.head; + cio = (CommCallbackData *)node->data; + assert(fd == cio->fd); /* just paranoid */ + dlinkDelete(&cio->h_node, &CommCallbackList); + dlinkDelete(&cio->fd_node, &(fdc_table[cio->fd].CommCallbackList)); + /* We're closing! */ + cio->errcode = COMM_ERR_CLOSING; + comm_call_io_callback(cio); + memPoolFree(comm_callback_pool, cio); } commCallCloseHandlers(fd); + if (F->uses) /* assume persistent connect count */ - pconnHistCount(1, F->uses); + pconnHistCount(1, F->uses); + comm_empty_os_read_buffers(fd); + #if USE_SSL + if (F->ssl) { - SSL_free(F->ssl); - F->ssl = NULL; + SSL_free(F->ssl); + F->ssl = NULL; } + #endif fd_close(fd); /* update fdstat */ + close(fd); + fdc_table[fd].active = 0; + bzero(&fdc_table[fd], sizeof(fdc_t)); + statCounter.syscalls.sock.closes++; + PROF_stop(comm_close); } /* Send a udp datagram to specified TO_ADDR. */ int comm_udp_sendto(int fd, - const struct sockaddr_in *to_addr, - int addr_len, - const void *buf, - int len) + + const struct sockaddr_in *to_addr, + int addr_len, + const void *buf, + int len) { int x; PROF_start(comm_udp_sendto); statCounter.syscalls.sock.sendtos++; + x = sendto(fd, buf, len, 0, (struct sockaddr *) to_addr, addr_len); PROF_stop(comm_udp_sendto); - if (x < 0) { + + if (x < 0) + { #ifdef _SQUID_LINUX_ - if (ECONNREFUSED != errno) + + if (ECONNREFUSED != errno) #endif - debug(50, 1) ("comm_udp_sendto: FD %d, %s, port %d: %s\n", - fd, - inet_ntoa(to_addr->sin_addr), - (int) htons(to_addr->sin_port), - xstrerror()); - return COMM_ERROR; + + debug(50, 1) ("comm_udp_sendto: FD %d, %s, port %d: %s\n", + fd, + inet_ntoa(to_addr->sin_addr), + (int) htons(to_addr->sin_port), + xstrerror()); + + return COMM_ERROR; } + return x; } @@ -1440,12 +1675,17 @@ comm_add_close_handler(int fd, PF * handler, void *data) close_handler *newHandler = (close_handler *)memPoolAlloc(conn_close_pool); /* AAA */ close_handler *c; debug(5, 5) ("comm_add_close_handler: FD %d, handler=%p, data=%p\n", - fd, handler, data); + fd, handler, data); + for (c = fd_table[fd].closeHandler; c; c = c->next) - assert(c->handler != handler || c->data != data); + assert(c->handler != handler || c->data != data); + newHandler->handler = handler; + newHandler->data = cbdataReference(data); + newHandler->next = fd_table[fd].closeHandler; + fd_table[fd].closeHandler = newHandler; } @@ -1456,28 +1696,36 @@ comm_remove_close_handler(int fd, PF * handler, void *data) close_handler *last = NULL; /* Find handler in list */ debug(5, 5) ("comm_remove_close_handler: FD %d, handler=%p, data=%p\n", - fd, handler, data); + fd, handler, data); + for (p = fd_table[fd].closeHandler; p != NULL; last = p, p = p->next) - if (p->handler == handler && p->data == data) - break; /* This is our handler */ + if (p->handler == handler && p->data == data) + break; /* This is our handler */ + assert(p != NULL); + /* Remove list entry */ if (last) - last->next = p->next; + last->next = p->next; else - fd_table[fd].closeHandler = p->next; + fd_table[fd].closeHandler = p->next; + cbdataReferenceDone(p->data); + memPoolFree(conn_close_pool, p); } static void commSetNoLinger(int fd) { + struct linger L; L.l_onoff = 0; /* off */ L.l_linger = 0; + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0) - debug(50, 0) ("commSetNoLinger: FD %d: %s\n", fd, xstrerror()); + debug(50, 0) ("commSetNoLinger: FD %d: %s\n", fd, xstrerror()); + fd_table[fd].flags.nolinger = 1; } @@ -1485,16 +1733,17 @@ static void commSetReuseAddr(int fd) { int on = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0) - debug(50, 1) ("commSetReuseAddr: FD %d: %s\n", fd, xstrerror()); + debug(50, 1) ("commSetReuseAddr: FD %d: %s\n", fd, xstrerror()); } static void commSetTcpRcvbuf(int fd, int size) { if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size)) < 0) - debug(50, 1) ("commSetTcpRcvbuf: FD %d, SIZE %d: %s\n", - fd, size, xstrerror()); + debug(50, 1) ("commSetTcpRcvbuf: FD %d, SIZE %d: %s\n", + fd, size, xstrerror()); } int @@ -1503,26 +1752,34 @@ commSetNonBlocking(int fd) int flags; int dummy = 0; #ifdef _SQUID_CYGWIN_ + int nonblocking = TRUE; + if (fd_table[fd].type != FD_PIPE) { - if (ioctl(fd, FIONBIO, &nonblocking) < 0) { - debug(50, 0) ("commSetNonBlocking: FD %d: %s %D\n", fd, xstrerror(), fd_table[fd].type); - return COMM_ERROR; - } + if (ioctl(fd, FIONBIO, &nonblocking) < 0) { + debug(50, 0) ("commSetNonBlocking: FD %d: %s %D\n", fd, xstrerror(), fd_table[fd].type); + return COMM_ERROR; + } } else { #endif - if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) { - debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); - return COMM_ERROR; - } - if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) { - debug(50, 0) ("commSetNonBlocking: FD %d: %s\n", fd, xstrerror()); - return COMM_ERROR; - } + + if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) { + debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); + return COMM_ERROR; + } + + if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) { + debug(50, 0) ("commSetNonBlocking: FD %d: %s\n", fd, xstrerror()); + return COMM_ERROR; + } + #ifdef _SQUID_CYGWIN_ + } + #endif fd_table[fd].flags.nonblocking = 1; + return 0; } @@ -1531,14 +1788,17 @@ commUnsetNonBlocking(int fd) { int flags; int dummy = 0; + if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) { - debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); - return COMM_ERROR; + debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); + return COMM_ERROR; } + if (fcntl(fd, F_SETFL, flags & (~SQUID_NONBLOCK)) < 0) { - debug(50, 0) ("commUnsetNonBlocking: FD %d: %s\n", fd, xstrerror()); - return COMM_ERROR; + debug(50, 0) ("commUnsetNonBlocking: FD %d: %s\n", fd, xstrerror()); + return COMM_ERROR; } + fd_table[fd].flags.nonblocking = 0; return 0; } @@ -1549,13 +1809,17 @@ commSetCloseOnExec(int fd) #ifdef FD_CLOEXEC int flags; int dummy = 0; + if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) { - debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); - return; + debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); + return; } + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) - debug(50, 0) ("FD %d: set close-on-exec failed: %s\n", fd, xstrerror()); + debug(50, 0) ("FD %d: set close-on-exec failed: %s\n", fd, xstrerror()); + fd_table[fd].flags.close_on_exec = 1; + #endif } @@ -1564,10 +1828,13 @@ static void commSetTcpNoDelay(int fd) { int on = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) - debug(50, 1) ("commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror()); + debug(50, 1) ("commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror()); + fd_table[fd].flags.nodelay = 1; } + #endif @@ -1599,7 +1866,7 @@ commHandleWrite(int fd, void *data) PROF_start(commHandleWrite); debug(5, 5) ("commHandleWrite: FD %d: off %ld, sz %ld.\n", - fd, (long int) state->offset, (long int) state->size); + fd, (long int) state->offset, (long int) state->size); nleft = state->size - state->offset; len = FD_WRITE_METHOD(fd, state->buf + state->offset, nleft); @@ -1608,44 +1875,49 @@ commHandleWrite(int fd, void *data) statCounter.syscalls.sock.writes++; if (len == 0) { - /* Note we even call write if nleft == 0 */ - /* We're done */ - if (nleft != 0) - debug(5, 1) ("commHandleWrite: FD %d: write failure: connection closed with %d bytes remaining.\n", fd, nleft); - CommWriteStateCallbackAndFree(fd, nleft ? COMM_ERROR : COMM_OK); + /* Note we even call write if nleft == 0 */ + /* We're done */ + + if (nleft != 0) + debug(5, 1) ("commHandleWrite: FD %d: write failure: connection closed with %d bytes remaining.\n", fd, nleft); + + CommWriteStateCallbackAndFree(fd, nleft ? COMM_ERROR : COMM_OK); } else if (len < 0) { - /* An error */ - if (fd_table[fd].flags.socket_eof) { - debug(50, 2) ("commHandleWrite: FD %d: write failure: %s.\n", - fd, xstrerror()); - CommWriteStateCallbackAndFree(fd, COMM_ERROR); - } else if (ignoreErrno(errno)) { - debug(50, 10) ("commHandleWrite: FD %d: write failure: %s.\n", - fd, xstrerror()); - commSetSelect(fd, - COMM_SELECT_WRITE, - commHandleWrite, - state, - 0); - } else { - debug(50, 2) ("commHandleWrite: FD %d: write failure: %s.\n", - fd, xstrerror()); - CommWriteStateCallbackAndFree(fd, COMM_ERROR); - } + /* An error */ + + if (fd_table[fd].flags.socket_eof) { + debug(50, 2) ("commHandleWrite: FD %d: write failure: %s.\n", + fd, xstrerror()); + CommWriteStateCallbackAndFree(fd, COMM_ERROR); + } else if (ignoreErrno(errno)) { + debug(50, 10) ("commHandleWrite: FD %d: write failure: %s.\n", + fd, xstrerror()); + commSetSelect(fd, + COMM_SELECT_WRITE, + commHandleWrite, + state, + 0); + } else { + debug(50, 2) ("commHandleWrite: FD %d: write failure: %s.\n", + fd, xstrerror()); + CommWriteStateCallbackAndFree(fd, COMM_ERROR); + } } else { - /* A successful write, continue */ - state->offset += len; - if (state->offset < (off_t)state->size) { - /* Not done, reinstall the write handler and write some more */ - commSetSelect(fd, - COMM_SELECT_WRITE, - commHandleWrite, - state, - 0); - } else { - CommWriteStateCallbackAndFree(fd, COMM_OK); - } + /* A successful write, continue */ + state->offset += len; + + if (state->offset < (off_t)state->size) { + /* Not done, reinstall the write handler and write some more */ + commSetSelect(fd, + COMM_SELECT_WRITE, + commHandleWrite, + state, + 0); + } else { + CommWriteStateCallbackAndFree(fd, COMM_OK); + } } + PROF_stop(commHandleWrite); } @@ -1665,12 +1937,14 @@ comm_old_write(int fd, const char *buf, int size, CWCB * handler, void *handler_ assert(!fd_table[fd].flags.closing); debug(5, 5) ("comm_write: FD %d: sz %d: hndl %p: data %p.\n", - fd, size, handler, handler_data); + fd, size, handler, handler_data); + if (NULL != state) { - debug(5, 1) ("comm_write: fd_table[%d].rwstate != NULL\n", fd); - memPoolFree(comm_write_pool, state); - fd_table[fd].rwstate = NULL; + debug(5, 1) ("comm_write: fd_table[%d].rwstate != NULL\n", fd); + memPoolFree(comm_write_pool, state); + fd_table[fd].rwstate = NULL; } + fd_table[fd].rwstate = state = (CommWriteStateData *)memPoolAlloc(comm_write_pool); state->buf = (char *) buf; state->size = size; @@ -1697,20 +1971,29 @@ int ignoreErrno(int ierrno) { switch (ierrno) { + case EINPROGRESS: + case EWOULDBLOCK: #if EAGAIN != EWOULDBLOCK + case EAGAIN: #endif + case EALREADY: + case EINTR: #ifdef ERESTART + case ERESTART: #endif - return 1; + + return 1; + default: - return 0; + return 0; } + /* NOTREACHED */ } @@ -1719,26 +2002,32 @@ commCloseAllSockets(void) { int fd; fde *F = NULL; + for (fd = 0; fd <= Biggest_FD; fd++) { - F = &fd_table[fd]; - if (!F->flags.open) - continue; - if (F->type != FD_SOCKET) - continue; - if (F->flags.ipc) /* don't close inter-process sockets */ - continue; - if (F->timeout_handler) { - PF *callback = F->timeout_handler; - void *cbdata = NULL; - F->timeout_handler = NULL; - debug(5, 5) ("commCloseAllSockets: FD %d: Calling timeout handler\n", - fd); - if (cbdataReferenceValidDone(F->timeout_data, &cbdata)) - callback(fd, cbdata); - } else { - debug(5, 5) ("commCloseAllSockets: FD %d: calling comm_close()\n", fd); - comm_close(fd); - } + F = &fd_table[fd]; + + if (!F->flags.open) + continue; + + if (F->type != FD_SOCKET) + continue; + + if (F->flags.ipc) /* don't close inter-process sockets */ + continue; + + if (F->timeout_handler) { + PF *callback = F->timeout_handler; + void *cbdata = NULL; + F->timeout_handler = NULL; + debug(5, 5) ("commCloseAllSockets: FD %d: Calling timeout handler\n", + fd); + + if (cbdataReferenceValidDone(F->timeout_data, &cbdata)) + callback(fd, cbdata); + } else { + debug(5, 5) ("commCloseAllSockets: FD %d: calling comm_close()\n", fd); + comm_close(fd); + } } } @@ -1748,24 +2037,30 @@ checkTimeouts(void) int fd; fde *F = NULL; PF *callback; + for (fd = 0; fd <= Biggest_FD; fd++) { - F = &fd_table[fd]; - if (!F->flags.open) - continue; - if (F->timeout == 0) - continue; - if (F->timeout > squid_curtime) - continue; - debug(5, 5) ("checkTimeouts: FD %d Expired\n", fd); - if (F->timeout_handler) { - debug(5, 5) ("checkTimeouts: FD %d: Call timeout handler\n", fd); - callback = F->timeout_handler; - F->timeout_handler = NULL; - callback(fd, F->timeout_data); - } else { - debug(5, 5) ("checkTimeouts: FD %d: Forcing comm_close()\n", fd); - comm_close(fd); - } + F = &fd_table[fd]; + + if (!F->flags.open) + continue; + + if (F->timeout == 0) + continue; + + if (F->timeout > squid_curtime) + continue; + + debug(5, 5) ("checkTimeouts: FD %d Expired\n", fd); + + if (F->timeout_handler) { + debug(5, 5) ("checkTimeouts: FD %d: Call timeout handler\n", fd); + callback = F->timeout_handler; + F->timeout_handler = NULL; + callback(fd, F->timeout_data); + } else { + debug(5, 5) ("checkTimeouts: FD %d: Forcing comm_close()\n", fd); + comm_close(fd); + } } } @@ -1774,8 +2069,10 @@ int commDeferRead(int fd) { fde *F = &fd_table[fd]; + if (F->defer_check == NULL) - return 0; + return 0; + return F->defer_check(fd, F->defer_data); } @@ -1791,12 +2088,14 @@ int comm_listen(int sock) { int x; + if ((x = listen(sock, Squid_MaxFD >> 2)) < 0) { - debug(50, 0) ("comm_listen: listen(%d, %d): %s\n", - Squid_MaxFD >> 2, - sock, xstrerror()); - return x; + debug(50, 0) ("comm_listen: listen(%d, %d): %s\n", + Squid_MaxFD >> 2, + sock, xstrerror()); + return x; } + return sock; } @@ -1808,48 +2107,57 @@ comm_listen(int sock) static void comm_accept_try(int fd, void *data) { - int newfd; - fdc_t *Fc; - int count; - IOACB *hdl; - - assert(fdc_table[fd].active == 1); - - Fc = &(fdc_table[fd]); - - for (count = 0; count < MAX_ACCEPT_PER_LOOP; count++) { - /* If we're out of fds, register an event and return now */ - if (fdNFree() < RESERVED_FD) { - debug(5, 3) ("comm_accept_try: we're out of fds - deferring io!\n"); - eventAdd("comm_accept_check_event", comm_accept_check_event, &fdc_table[fd], - 1000.0 / (double)(fdc_table[fd].accept.accept.check_delay), 1); - return; - } - /* Accept a new connection */ - newfd = comm_old_accept(fd, Fc->accept.connDetails); - /* Check for errors */ - if (newfd < 0) { - if (newfd == COMM_NOMESSAGE) { - /* register interest again */ - commSetSelect(fd, COMM_SELECT_READ, comm_accept_try, NULL, 0); - return; - } - /* A non-recoverable error - register an error callback */ - comm_addacceptcallback(fd, -1, Fc->accept.accept.handler, Fc->accept.connDetails, COMM_ERROR, errno, Fc->accept.accept.handler_data); - Fc->accept.accept.handler = NULL; - Fc->accept.accept.handler_data = NULL; - return; - } - - /* Try the callback! */ - hdl = Fc->accept.accept.handler; - Fc->accept.accept.handler = NULL; - hdl(fd, newfd, &Fc->accept.connDetails, COMM_OK, 0, Fc->accept.accept.handler_data); - - /* If we weren't re-registed, don't bother trying again! */ - if (Fc->accept.accept.handler == NULL) - return; - } + int newfd; + fdc_t *Fc; + int count; + IOACB *hdl; + + assert(fdc_table[fd].active == 1); + + Fc = &(fdc_table[fd]); + + for (count = 0; count < MAX_ACCEPT_PER_LOOP; count++) { + /* If we're out of fds, register an event and return now */ + + if (fdNFree() < RESERVED_FD) { + debug(5, 3) ("comm_accept_try: we're out of fds - deferring io!\n"); + eventAdd("comm_accept_check_event", comm_accept_check_event, &fdc_table[fd], + 1000.0 / (double)(fdc_table[fd].accept.accept.check_delay), 1); + return; + } + + /* Accept a new connection */ + newfd = comm_old_accept(fd, Fc->accept.connDetails); + + /* Check for errors */ + if (newfd < 0) { + if (newfd == COMM_NOMESSAGE) { + /* register interest again */ + commSetSelect(fd, COMM_SELECT_READ, comm_accept_try, NULL, 0); + return; + } + + /* A non-recoverable error - register an error callback */ + comm_addacceptcallback(fd, -1, Fc->accept.accept.handler, Fc->accept.connDetails, COMM_ERROR, errno, Fc->accept.accept.handler_data); + + Fc->accept.accept.handler = NULL; + + Fc->accept.accept.handler_data = NULL; + + return; + } + + /* Try the callback! */ + hdl = Fc->accept.accept.handler; + + Fc->accept.accept.handler = NULL; + + hdl(fd, newfd, &Fc->accept.connDetails, COMM_OK, 0, Fc->accept.accept.handler_data); + + /* If we weren't re-registed, don't bother trying again! */ + if (Fc->accept.accept.handler == NULL) + return; + } } @@ -1861,24 +2169,26 @@ comm_accept_try(int fd, void *data) void comm_accept(int fd, IOACB *handler, void *handler_data) { - fdc_t *Fc; + fdc_t *Fc; - assert(fd_table[fd].flags.open == 1); - assert(fdc_table[fd].active == 1); + assert(fd_table[fd].flags.open == 1); + assert(fdc_table[fd].active == 1); - /* make sure we're not pending! */ - assert(fdc_table[fd].accept.accept.handler == NULL); + /* make sure we're not pending! */ + assert(fdc_table[fd].accept.accept.handler == NULL); - /* Record our details */ - Fc = &fdc_table[fd]; - Fc->accept.accept.handler = handler; - Fc->accept.accept.handler_data = handler_data; + /* Record our details */ + Fc = &fdc_table[fd]; + Fc->accept.accept.handler = handler; + Fc->accept.accept.handler_data = handler_data; - /* Kick off the accept */ + /* Kick off the accept */ #if OPTIMISTIC_IO - comm_accept_try(fd, NULL); + + comm_accept_try(fd, NULL); #else - commSetSelect(fd, COMM_SELECT_READ, comm_accept_try, NULL, 0); + + commSetSelect(fd, COMM_SELECT_READ, comm_accept_try, NULL, 0); #endif } @@ -1917,10 +2227,10 @@ CommIO::NULLFDHandler(int fd, void *data) } void -CommIO::ResetNotifications() +CommIO::ResetNotifications() { if (DoneSignalled) { - FlushPipe(); - DoneSignalled = false; + FlushPipe(); + DoneSignalled = false; } } diff --git a/src/comm.h b/src/comm.h index 67702c5469..9542ae74cf 100644 --- a/src/comm.h +++ b/src/comm.h @@ -17,7 +17,8 @@ extern bool comm_has_pending_read(int fd); extern void comm_read_cancel(int fd, IOCB *callback, void *data); extern void fdc_open(int fd, unsigned int type, char *desc); extern int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); + + struct sockaddr *from, socklen_t *fromlen); extern int comm_udp_recv(int fd, void *buf, size_t len, int flags); extern ssize_t comm_udp_send(int s, const void *buf, size_t len, int flags); extern void comm_accept_setcheckperiod(int fd, int mdelay); @@ -25,28 +26,34 @@ extern void comm_accept_setcheckperiod(int fd, int mdelay); extern void comm_write(int s, const char *buf, size_t len, IOWCB *callback, void *callback_data); /* Where should this belong? */ -class CommIO { + +class CommIO +{ + public: - static inline void NotifyIOCompleted(); - static void ResetNotifications(); - static void Initialise(); + static inline void NotifyIOCompleted(); + static void ResetNotifications(); + static void Initialise(); + private: - static void NULLFDHandler(int, void *); - static void FlushPipe(); - static bool Initialised; - static bool DoneSignalled; - static int DoneFD; - static int DoneReadFD; + static void NULLFDHandler(int, void *); + static void FlushPipe(); + static bool Initialised; + static bool DoneSignalled; + static int DoneFD; + static int DoneReadFD; }; /* Inline code. TODO: make structued approach to inlining */ void -CommIO::NotifyIOCompleted() { +CommIO::NotifyIOCompleted() +{ if (!Initialised) - Initialise(); + Initialise(); + if (!DoneSignalled) { - DoneSignalled = true; - write(DoneFD, "!", 1); + DoneSignalled = true; + write(DoneFD, "!", 1); } }; diff --git a/src/comm_kqueue.cc b/src/comm_kqueue.cc index 04ee0f3d92..0507aa630f 100644 --- a/src/comm_kqueue.cc +++ b/src/comm_kqueue.cc @@ -1,6 +1,6 @@ /* - * $Id: comm_kqueue.cc,v 1.7 2003/01/23 00:37:19 robertc Exp $ + * $Id: comm_kqueue.cc,v 1.8 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 5 Socket functions * @@ -78,6 +78,7 @@ static void kq_update_events(int, short, PF *); static int kq; + static struct timespec zero_timespec; static struct kevent *kqlst; /* kevent buffer */ @@ -96,16 +97,20 @@ kq_update_events(int fd, short filter, PF * handler) int kep_flags; #if 0 + int retval; #endif switch (filter) { + case EVFILT_READ: cur_handler = fd_table[fd].read_handler; break; + case EVFILT_WRITE: cur_handler = fd_table[fd].write_handler; break; + default: /* XXX bad! -- adrian */ return; @@ -113,7 +118,8 @@ kq_update_events(int fd, short filter, PF * handler) } if ((cur_handler == NULL && handler != NULL) - || (cur_handler != NULL && handler == NULL)) { + || (cur_handler != NULL && handler == NULL)) { + struct kevent *kep; kep = kqlst + kqoff; @@ -131,22 +137,28 @@ kq_update_events(int fd, short filter, PF * handler) ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec); /* jdc -- someone needs to do error checking... */ + if (ret == -1) { perror("kq_update_events(): kevent()"); return; } + kqoff = 0; } else { kqoff++; } + #if 0 if (retval < 0) { /* Error! */ + if (ke.flags & EV_ERROR) { errno = ke.data; } } + #endif + } } @@ -166,10 +178,13 @@ void comm_select_init(void) { kq = kqueue(); + if (kq < 0) { fatal("comm_select_init: Couldn't open kqueue fd!\n"); } + kqmax = getdtablesize(); + kqlst = (struct kevent *)xmalloc(sizeof(*kqlst) * kqmax); zero_timespec.tv_sec = 0; zero_timespec.tv_nsec = 0; @@ -183,7 +198,7 @@ comm_select_init(void) */ void commSetSelect(int fd, unsigned int type, PF * handler, - void *client_data, time_t timeout) + void *client_data, time_t timeout) { fde *F = &fd_table[fd]; assert(fd >= 0); @@ -194,11 +209,13 @@ commSetSelect(int fd, unsigned int type, PF * handler, F->read_handler = handler; F->read_data = client_data; } + if (type & COMM_SELECT_WRITE) { kq_update_events(fd, EVFILT_WRITE, handler); F->write_handler = handler; F->write_data = client_data; } + if (timeout) F->timeout = squid_curtime + timeout; @@ -223,7 +240,9 @@ comm_err_t comm_select(int msec) { int num, i; + static struct kevent ke[KE_LENGTH]; + struct timespec poll_time; /* @@ -231,24 +250,34 @@ comm_select(int msec) * why jlemon used a timespec, but hey, he wrote the interface, not I * -- Adrian */ + if (msec > max_poll_time) msec = max_poll_time; + poll_time.tv_sec = msec / 1000; + poll_time.tv_nsec = (msec % 1000) * 1000000; + for (;;) { num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time); statCounter.select_loops++; kqoff = 0; + if (num >= 0) break; + if (ignoreErrno(errno)) break; + getCurrentTime(); + return COMM_ERROR; + /* NOTREACHED */ } getCurrentTime(); + if (num == 0) return COMM_OK; /* No error.. */ @@ -262,25 +291,34 @@ comm_select(int msec) /* XXX error == bad! -- adrian */ continue; /* XXX! */ } + switch (ke[i].filter) { - case EVFILT_READ: - if ((hdl = F->read_handler) != NULL) { - F->read_handler = NULL; - hdl(fd, F->read_data); - } - break; - case EVFILT_WRITE: - if ((hdl = F->write_handler) != NULL) { - F->write_handler = NULL; - hdl(fd, F->write_data); - } - break; - default: - /* Bad! -- adrian */ - debug(5, 1) ("comm_select: kevent returned %d!\n", ke[i].filter); - break; + + case EVFILT_READ: + + if ((hdl = F->read_handler) != NULL) { + F->read_handler = NULL; + hdl(fd, F->read_data); + } + + break; + + case EVFILT_WRITE: + + if ((hdl = F->write_handler) != NULL) { + F->write_handler = NULL; + hdl(fd, F->write_data); + } + + break; + + default: + /* Bad! -- adrian */ + debug(5, 1) ("comm_select: kevent returned %d!\n", ke[i].filter); + break; } } + return COMM_OK; } diff --git a/src/comm_poll.cc b/src/comm_poll.cc index 441e62b8d8..6ab97648a7 100644 --- a/src/comm_poll.cc +++ b/src/comm_poll.cc @@ -1,6 +1,6 @@ /* - * $Id: comm_poll.cc,v 1.9 2003/01/23 00:37:19 robertc Exp $ + * $Id: comm_poll.cc,v 1.10 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 5 Socket Functions * @@ -128,33 +128,38 @@ static int incoming_http_interval = 16 << INCOMING_FACTOR; void commSetSelect(int fd, unsigned int type, PF * handler, void *client_data, - time_t timeout) + time_t timeout) { fde *F = &fd_table[fd]; assert(fd >= 0); assert(F->flags.open); debug(5, 5) ("commSetSelect: FD %d type %d\n", fd, type); + if (type & COMM_SELECT_READ) { - F->read_handler = handler; - F->read_data = client_data; - commUpdateReadBits(fd, handler); + F->read_handler = handler; + F->read_data = client_data; + commUpdateReadBits(fd, handler); } + if (type & COMM_SELECT_WRITE) { - F->write_handler = handler; - F->write_data = client_data; - commUpdateWriteBits(fd, handler); + F->write_handler = handler; + F->write_data = client_data; + commUpdateWriteBits(fd, handler); } + if (timeout) - F->timeout = squid_curtime + timeout; + F->timeout = squid_curtime + timeout; } static int fdIsIcp(int fd) { if (fd == theInIcpConnection) - return 1; + return 1; + if (fd == theOutIcpConnection) - return 1; + return 1; + return 0; } @@ -162,7 +167,8 @@ static int fdIsDns(int fd) { if (fd == DnsSocket) - return 1; + return 1; + return 0; } @@ -170,10 +176,12 @@ static int fdIsHttp(int fd) { int j; + for (j = 0; j < NHttpSockets; j++) { - if (fd == HttpSockets[j]) - return 1; + if (fd == HttpSockets[j]) + return 1; } + return 0; } @@ -194,12 +202,17 @@ commGetSlowFd(void) int whichfd, retfd; if (!slowfdcnt) - return -1; + return -1; + whichfd = squid_random() % slowfdcnt; + retfd = slowfdarr[whichfd]; + slowfdarr[whichfd] = slowfdarr[--slowfdcnt]; + return retfd; } + #endif static int @@ -209,55 +222,68 @@ comm_check_incoming_poll_handlers(int nfds, int *fds) int fd; PF *hdl = NULL; int npfds; + struct pollfd pfds[3 + MAXHTTPPORTS]; PROF_start(comm_check_incoming); incoming_sockets_accepted = 0; + for (i = npfds = 0; i < nfds; i++) { - int events; - fd = fds[i]; - events = 0; - if (fd_table[fd].read_handler) - events |= POLLRDNORM; - if (fd_table[fd].write_handler) - events |= POLLWRNORM; - if (events) { - pfds[npfds].fd = fd; - pfds[npfds].events = events; - pfds[npfds].revents = 0; - npfds++; - } + int events; + fd = fds[i]; + events = 0; + + if (fd_table[fd].read_handler) + events |= POLLRDNORM; + + if (fd_table[fd].write_handler) + events |= POLLWRNORM; + + if (events) { + pfds[npfds].fd = fd; + pfds[npfds].events = events; + pfds[npfds].revents = 0; + npfds++; + } } + if (!nfds) { - PROF_stop(comm_check_incoming); - return -1; + PROF_stop(comm_check_incoming); + return -1; } + getCurrentTime(); statCounter.syscalls.polls++; + if (poll(pfds, npfds, 0) < 1) { - PROF_stop(comm_check_incoming); - return incoming_sockets_accepted; + PROF_stop(comm_check_incoming); + return incoming_sockets_accepted; } + for (i = 0; i < npfds; i++) { - int revents; - if (((revents = pfds[i].revents) == 0) || ((fd = pfds[i].fd) == -1)) - continue; - if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { - if ((hdl = fd_table[fd].read_handler)) { - fd_table[fd].read_handler = NULL; - hdl(fd, fd_table[fd].read_data); - } else if (pfds[i].events & POLLRDNORM) - debug(5, 1) ("comm_poll_incoming: FD %d NULL read handler\n", - fd); - } - if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { - if ((hdl = fd_table[fd].write_handler)) { - fd_table[fd].write_handler = NULL; - hdl(fd, fd_table[fd].write_data); - } else if (pfds[i].events & POLLWRNORM) - debug(5, 1) ("comm_poll_incoming: FD %d NULL write_handler\n", - fd); - } + int revents; + + if (((revents = pfds[i].revents) == 0) || ((fd = pfds[i].fd) == -1)) + continue; + + if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { + if ((hdl = fd_table[fd].read_handler)) { + fd_table[fd].read_handler = NULL; + hdl(fd, fd_table[fd].read_data); + } else if (pfds[i].events & POLLRDNORM) + debug(5, 1) ("comm_poll_incoming: FD %d NULL read handler\n", + fd); + } + + if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { + if ((hdl = fd_table[fd].write_handler)) { + fd_table[fd].write_handler = NULL; + hdl(fd, fd_table[fd].write_data); + } else if (pfds[i].events & POLLWRNORM) + debug(5, 1) ("comm_poll_incoming: FD %d NULL write_handler\n", + fd); + } } + PROF_stop(comm_check_incoming); return incoming_sockets_accepted; } @@ -269,21 +295,30 @@ comm_poll_icp_incoming(void) int fds[2]; int nevents; icp_io_events = 0; + if (theInIcpConnection >= 0) - fds[nfds++] = theInIcpConnection; + fds[nfds++] = theInIcpConnection; + if (theInIcpConnection != theOutIcpConnection) - if (theOutIcpConnection >= 0) - fds[nfds++] = theOutIcpConnection; + if (theOutIcpConnection >= 0) + fds[nfds++] = theOutIcpConnection; + if (nfds == 0) - return; + return; + nevents = comm_check_incoming_poll_handlers(nfds, fds); + incoming_icp_interval += Config.comm_incoming.icp_average - nevents; + if (incoming_icp_interval < Config.comm_incoming.icp_min_poll) - incoming_icp_interval = Config.comm_incoming.icp_min_poll; + incoming_icp_interval = Config.comm_incoming.icp_min_poll; + if (incoming_icp_interval > MAX_INCOMING_INTERVAL) - incoming_icp_interval = MAX_INCOMING_INTERVAL; + incoming_icp_interval = MAX_INCOMING_INTERVAL; + if (nevents > INCOMING_ICP_MAX) - nevents = INCOMING_ICP_MAX; + nevents = INCOMING_ICP_MAX; + statHistCount(&statCounter.comm_icp_incoming, nevents); } @@ -295,22 +330,30 @@ comm_poll_http_incoming(void) int j; int nevents; http_io_events = 0; + for (j = 0; j < NHttpSockets; j++) { - if (HttpSockets[j] < 0) - continue; - if (commDeferRead(HttpSockets[j])) - continue; - fds[nfds++] = HttpSockets[j]; + if (HttpSockets[j] < 0) + continue; + + if (commDeferRead(HttpSockets[j])) + continue; + + fds[nfds++] = HttpSockets[j]; } + nevents = comm_check_incoming_poll_handlers(nfds, fds); incoming_http_interval = incoming_http_interval - + Config.comm_incoming.http_average - nevents; + + Config.comm_incoming.http_average - nevents; + if (incoming_http_interval < Config.comm_incoming.http_min_poll) - incoming_http_interval = Config.comm_incoming.http_min_poll; + incoming_http_interval = Config.comm_incoming.http_min_poll; + if (incoming_http_interval > MAX_INCOMING_INTERVAL) - incoming_http_interval = MAX_INCOMING_INTERVAL; + incoming_http_interval = MAX_INCOMING_INTERVAL; + if (nevents > INCOMING_HTTP_MAX) - nevents = INCOMING_HTTP_MAX; + nevents = INCOMING_HTTP_MAX; + statHistCount(&statCounter.comm_http_incoming, nevents); } @@ -318,10 +361,13 @@ comm_poll_http_incoming(void) comm_err_t comm_select(int msec) { + struct pollfd pfds[SQUID_MAXFD]; #if DELAY_POOLS + fd_set slowfds; #endif + PF *hdl = NULL; int fd; int maxfd; @@ -332,209 +378,284 @@ comm_select(int msec) int calldns = 0; static time_t last_timeout = 0; double timeout = current_dtime + (msec / 1000.0); + do { - double start; - getCurrentTime(); - start = current_dtime; + double start; + getCurrentTime(); + start = current_dtime; #if DELAY_POOLS - FD_ZERO(&slowfds); + + FD_ZERO(&slowfds); #endif - if (commCheckICPIncoming) - comm_poll_icp_incoming(); - if (commCheckDNSIncoming) - comm_poll_dns_incoming(); - if (commCheckHTTPIncoming) - comm_poll_http_incoming(); - PROF_start(comm_poll_prep_pfds); - callicp = calldns = callhttp = 0; - nfds = 0; - npending = 0; - maxfd = Biggest_FD + 1; - for (int i = 0; i < maxfd; i++) { - int events; - events = 0; - /* Check each open socket for a handler. */ - if (fd_table[i].read_handler) { - switch (commDeferRead(i)) { - case 0: - events |= POLLRDNORM; - break; - case 1: - break; + + if (commCheckICPIncoming) + comm_poll_icp_incoming(); + + if (commCheckDNSIncoming) + comm_poll_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_poll_http_incoming(); + + PROF_start(comm_poll_prep_pfds); + + callicp = calldns = callhttp = 0; + + nfds = 0; + + npending = 0; + + maxfd = Biggest_FD + 1; + + for (int i = 0; i < maxfd; i++) { + int events; + events = 0; + /* Check each open socket for a handler. */ + + if (fd_table[i].read_handler) { + switch (commDeferRead(i)) { + + case 0: + events |= POLLRDNORM; + break; + + case 1: + break; #if DELAY_POOLS - case -1: - events |= POLLRDNORM; - FD_SET(i, &slowfds); - break; + + case -1: + events |= POLLRDNORM; + FD_SET(i, &slowfds); + break; #endif - default: - fatalf("bad return value from commDeferRead(FD %d)\n", i); - } - } - if (fd_table[i].write_handler) - events |= POLLWRNORM; - if (events) { - pfds[nfds].fd = i; - pfds[nfds].events = events; - pfds[nfds].revents = 0; - nfds++; - if ((events & POLLRDNORM) && fd_table[i].flags.read_pending) - npending++; - } - } - PROF_stop(comm_poll_prep_pfds); - if (nfds == 0) { - assert(shutting_down); - return COMM_SHUTDOWN; - } - if (npending) - msec = 0; - if (msec > MAX_POLL_TIME) - msec = MAX_POLL_TIME; - for (;;) { - PROF_start(comm_poll_normal); - statCounter.syscalls.polls++; - num = poll(pfds, nfds, msec); - statCounter.select_loops++; - PROF_stop(comm_poll_normal); - if (num >= 0 || npending >= 0) - break; - if (ignoreErrno(errno)) - continue; - debug(5, 0) ("comm_poll: poll failure: %s\n", xstrerror()); - assert(errno != EINVAL); - return COMM_ERROR; - /* NOTREACHED */ - } - debug(5, num ? 5 : 8) ("comm_poll: %d+%ld FDs ready\n", num, npending); - statHistCount(&statCounter.select_fds_hist, num); - /* Check timeout handlers ONCE each second. */ - if (squid_curtime > last_timeout) { - last_timeout = squid_curtime; - checkTimeouts(); - } - if (num == 0 && npending == 0) - continue; - /* scan each socket but the accept socket. Poll this - * more frequently to minimize losses due to the 5 connect - * limit in SunOS */ - PROF_start(comm_handle_ready_fd); - for (size_t loopIndex = 0; loopIndex < nfds; loopIndex++) { - fde *F; - int revents = pfds[loopIndex].revents; - fd = pfds[loopIndex].fd; - if (fd == -1) - continue; - if (fd_table[fd].flags.read_pending) - revents |= POLLIN; - if (revents == 0) - continue; - if (fdIsIcp(fd)) { - callicp = 1; - continue; - } - if (fdIsDns(fd)) { - calldns = 1; - continue; - } - if (fdIsHttp(fd)) { - callhttp = 1; - continue; - } - F = &fd_table[fd]; - if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { - debug(5, 6) ("comm_poll: FD %d ready for reading\n", fd); - if (NULL == (hdl = F->read_handler)) - (void) 0; + + default: + fatalf("bad return value from commDeferRead(FD %d)\n", i); + } + } + + if (fd_table[i].write_handler) + events |= POLLWRNORM; + + if (events) { + pfds[nfds].fd = i; + pfds[nfds].events = events; + pfds[nfds].revents = 0; + nfds++; + + if ((events & POLLRDNORM) && fd_table[i].flags.read_pending) + npending++; + } + } + + PROF_stop(comm_poll_prep_pfds); + + if (nfds == 0) { + assert(shutting_down); + return COMM_SHUTDOWN; + } + + if (npending) + msec = 0; + + if (msec > MAX_POLL_TIME) + msec = MAX_POLL_TIME; + + for (;;) { + PROF_start(comm_poll_normal); + statCounter.syscalls.polls++; + num = poll(pfds, nfds, msec); + statCounter.select_loops++; + PROF_stop(comm_poll_normal); + + if (num >= 0 || npending >= 0) + break; + + if (ignoreErrno(errno)) + continue; + + debug(5, 0) ("comm_poll: poll failure: %s\n", xstrerror()); + + assert(errno != EINVAL); + + return COMM_ERROR; + + /* NOTREACHED */ + } + + debug(5, num ? 5 : 8) ("comm_poll: %d+%ld FDs ready\n", num, npending); + statHistCount(&statCounter.select_fds_hist, num); + /* Check timeout handlers ONCE each second. */ + + if (squid_curtime > last_timeout) { + last_timeout = squid_curtime; + checkTimeouts(); + } + + if (num == 0 && npending == 0) + continue; + + /* scan each socket but the accept socket. Poll this + * more frequently to minimize losses due to the 5 connect + * limit in SunOS */ + PROF_start(comm_handle_ready_fd); + + for (size_t loopIndex = 0; loopIndex < nfds; loopIndex++) { + fde *F; + int revents = pfds[loopIndex].revents; + fd = pfds[loopIndex].fd; + + if (fd == -1) + continue; + + if (fd_table[fd].flags.read_pending) + revents |= POLLIN; + + if (revents == 0) + continue; + + if (fdIsIcp(fd)) { + callicp = 1; + continue; + } + + if (fdIsDns(fd)) { + calldns = 1; + continue; + } + + if (fdIsHttp(fd)) { + callhttp = 1; + continue; + } + + F = &fd_table[fd]; + + if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { + debug(5, 6) ("comm_poll: FD %d ready for reading\n", fd); + + if (NULL == (hdl = F->read_handler)) + (void) 0; + #if DELAY_POOLS - else if (FD_ISSET(fd, &slowfds)) - commAddSlowFd(fd); + + else if (FD_ISSET(fd, &slowfds)) + commAddSlowFd(fd); + #endif - else { - PROF_start(comm_read_handler); - F->read_handler = NULL; - hdl(fd, F->read_data); - PROF_stop(comm_read_handler); - statCounter.select_fds++; - if (commCheckICPIncoming) - comm_poll_icp_incoming(); - if (commCheckDNSIncoming) - comm_poll_dns_incoming(); - if (commCheckHTTPIncoming) - comm_poll_http_incoming(); - } - } - if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { - debug(5, 5) ("comm_poll: FD %d ready for writing\n", fd); - if ((hdl = F->write_handler)) { - PROF_start(comm_write_handler); - F->write_handler = NULL; - hdl(fd, F->write_data); - PROF_stop(comm_write_handler); - statCounter.select_fds++; - if (commCheckICPIncoming) - comm_poll_icp_incoming(); - if (commCheckDNSIncoming) - comm_poll_dns_incoming(); - if (commCheckHTTPIncoming) - comm_poll_http_incoming(); - } - } - if (revents & POLLNVAL) { - close_handler *ch; - debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd); - debug(5, 0) ("FD %d is a %s\n", fd, fdTypeStr[F->type]); - debug(5, 0) ("--> %s\n", F->desc); - debug(5, 0) ("tmout:%p read:%p write:%p\n", - F->timeout_handler, - F->read_handler, - F->write_handler); - for (ch = F->closeHandler; ch; ch = ch->next) - debug(5, 0) (" close handler: %p\n", ch->handler); - if (F->closeHandler) { - commCallCloseHandlers(fd); - } else if (F->timeout_handler) { - debug(5, 0) ("comm_poll: Calling Timeout Handler\n"); - F->timeout_handler(fd, F->timeout_data); - } - F->closeHandler = NULL; - F->timeout_handler = NULL; - F->read_handler = NULL; - F->write_handler = NULL; - if (F->flags.open) - fd_close(fd); - } - } - PROF_stop(comm_handle_ready_fd); - if (callicp) - comm_poll_icp_incoming(); - if (calldns) - comm_poll_dns_incoming(); - if (callhttp) - comm_poll_http_incoming(); + + else { + PROF_start(comm_read_handler); + F->read_handler = NULL; + hdl(fd, F->read_data); + PROF_stop(comm_read_handler); + statCounter.select_fds++; + + if (commCheckICPIncoming) + comm_poll_icp_incoming(); + + if (commCheckDNSIncoming) + comm_poll_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_poll_http_incoming(); + } + } + + if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { + debug(5, 5) ("comm_poll: FD %d ready for writing\n", fd); + + if ((hdl = F->write_handler)) { + PROF_start(comm_write_handler); + F->write_handler = NULL; + hdl(fd, F->write_data); + PROF_stop(comm_write_handler); + statCounter.select_fds++; + + if (commCheckICPIncoming) + comm_poll_icp_incoming(); + + if (commCheckDNSIncoming) + comm_poll_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_poll_http_incoming(); + } + } + + if (revents & POLLNVAL) { + close_handler *ch; + debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd); + debug(5, 0) ("FD %d is a %s\n", fd, fdTypeStr[F->type]); + debug(5, 0) ("--> %s\n", F->desc); + debug(5, 0) ("tmout:%p read:%p write:%p\n", + F->timeout_handler, + F->read_handler, + F->write_handler); + + for (ch = F->closeHandler; ch; ch = ch->next) + debug(5, 0) (" close handler: %p\n", ch->handler); + + if (F->closeHandler) { + commCallCloseHandlers(fd); + } else if (F->timeout_handler) { + debug(5, 0) ("comm_poll: Calling Timeout Handler\n"); + F->timeout_handler(fd, F->timeout_data); + } + + F->closeHandler = NULL; + F->timeout_handler = NULL; + F->read_handler = NULL; + F->write_handler = NULL; + + if (F->flags.open) + fd_close(fd); + } + } + + PROF_stop(comm_handle_ready_fd); + + if (callicp) + comm_poll_icp_incoming(); + + if (calldns) + comm_poll_dns_incoming(); + + if (callhttp) + comm_poll_http_incoming(); + #if DELAY_POOLS - while ((fd = commGetSlowFd()) != -1) { - fde *F = &fd_table[fd]; - debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd); - if ((hdl = F->read_handler)) { - F->read_handler = NULL; - hdl(fd, F->read_data); - statCounter.select_fds++; - if (commCheckICPIncoming) - comm_poll_icp_incoming(); - if (commCheckDNSIncoming) - comm_poll_dns_incoming(); - if (commCheckHTTPIncoming) - comm_poll_http_incoming(); - } - } + + while ((fd = commGetSlowFd()) != -1) { + fde *F = &fd_table[fd]; + debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd); + + if ((hdl = F->read_handler)) { + F->read_handler = NULL; + hdl(fd, F->read_data); + statCounter.select_fds++; + + if (commCheckICPIncoming) + comm_poll_icp_incoming(); + + if (commCheckDNSIncoming) + comm_poll_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_poll_http_incoming(); + } + } + #endif - getCurrentTime(); - statCounter.select_time += (current_dtime - start); - return COMM_OK; - } - while (timeout > current_dtime); + getCurrentTime(); + + statCounter.select_time += (current_dtime - start); + + return COMM_OK; + } while (timeout > current_dtime); + debug(5, 8) ("comm_poll: time out: %ld.\n", (long int) squid_curtime); + return COMM_TIMEOUT; } @@ -546,19 +667,28 @@ comm_poll_dns_incoming(void) int fds[2]; int nevents; dns_io_events = 0; + if (DnsSocket < 0) - return; + return; + fds[nfds++] = DnsSocket; + nevents = comm_check_incoming_poll_handlers(nfds, fds); + if (nevents < 0) - return; + return; + incoming_dns_interval += Config.comm_incoming.dns_average - nevents; + if (incoming_dns_interval < Config.comm_incoming.dns_min_poll) - incoming_dns_interval = Config.comm_incoming.dns_min_poll; + incoming_dns_interval = Config.comm_incoming.dns_min_poll; + if (incoming_dns_interval > MAX_INCOMING_INTERVAL) - incoming_dns_interval = MAX_INCOMING_INTERVAL; + incoming_dns_interval = MAX_INCOMING_INTERVAL; + if (nevents > INCOMING_DNS_MAX) - nevents = INCOMING_DNS_MAX; + nevents = INCOMING_DNS_MAX; + statHistCount(&statCounter.comm_dns_incoming, nevents); } @@ -566,8 +696,8 @@ void comm_select_init(void) { cachemgrRegister("comm_incoming", - "comm_incoming() stats", - commIncomingStats, 0, 1); + "comm_incoming() stats", + commIncomingStats, 0, 1); FD_ZERO(&global_readfds); FD_ZERO(&global_writefds); nreadfds = nwritefds = 0; @@ -579,11 +709,11 @@ commIncomingStats(StoreEntry * sentry) { StatCounters *f = &statCounter; storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n", - incoming_icp_interval >> INCOMING_FACTOR); + incoming_icp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", - incoming_dns_interval >> INCOMING_FACTOR); + incoming_dns_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n", - incoming_http_interval >> INCOMING_FACTOR); + incoming_http_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); storeAppendPrintf(sentry, "ICP Messages handled per comm_poll_icp_incoming() call:\n"); @@ -598,11 +728,11 @@ void commUpdateReadBits(int fd, PF * handler) { if (handler && !FD_ISSET(fd, &global_readfds)) { - FD_SET(fd, &global_readfds); - nreadfds++; + FD_SET(fd, &global_readfds); + nreadfds++; } else if (!handler && FD_ISSET(fd, &global_readfds)) { - FD_CLR(fd, &global_readfds); - nreadfds--; + FD_CLR(fd, &global_readfds); + nreadfds--; } } @@ -610,11 +740,11 @@ void commUpdateWriteBits(int fd, PF * handler) { if (handler && !FD_ISSET(fd, &global_writefds)) { - FD_SET(fd, &global_writefds); - nwritefds++; + FD_SET(fd, &global_writefds); + nwritefds++; } else if (!handler && FD_ISSET(fd, &global_writefds)) { - FD_CLR(fd, &global_writefds); - nwritefds--; + FD_CLR(fd, &global_writefds); + nwritefds--; } } diff --git a/src/comm_select.cc b/src/comm_select.cc index b63f801b6a..725d4fa320 100644 --- a/src/comm_select.cc +++ b/src/comm_select.cc @@ -1,6 +1,6 @@ /* - * $Id: comm_select.cc,v 1.67 2003/02/02 12:55:23 robertc Exp $ + * $Id: comm_select.cc,v 1.68 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 5 Socket Functions * @@ -130,24 +130,27 @@ static int incoming_http_interval = 16 << INCOMING_FACTOR; void commSetSelect(int fd, unsigned int type, PF * handler, void *client_data, - time_t timeout) + time_t timeout) { fde *F = &fd_table[fd]; assert(fd >= 0); assert(F->flags.open); debug(5, 5) ("commSetSelect: FD %d type %d\n", fd, type); + if (type & COMM_SELECT_READ) { - F->read_handler = handler; - F->read_data = client_data; - commUpdateReadBits(fd, handler); + F->read_handler = handler; + F->read_data = client_data; + commUpdateReadBits(fd, handler); } + if (type & COMM_SELECT_WRITE) { - F->write_handler = handler; - F->write_data = client_data; - commUpdateWriteBits(fd, handler); + F->write_handler = handler; + F->write_data = client_data; + commUpdateWriteBits(fd, handler); } + if (timeout) - F->timeout = squid_curtime + timeout; + F->timeout = squid_curtime + timeout; } @@ -155,9 +158,11 @@ static int fdIsIcp(int fd) { if (fd == theInIcpConnection) - return 1; + return 1; + if (fd == theOutIcpConnection) - return 1; + return 1; + return 0; } @@ -165,7 +170,8 @@ static int fdIsDns(int fd) { if (fd == DnsSocket) - return 1; + return 1; + return 0; } @@ -173,10 +179,12 @@ static int fdIsHttp(int fd) { int j; + for (j = 0; j < NHttpSockets; j++) { - if (fd == HttpSockets[j]) - return 1; + if (fd == HttpSockets[j]) + return 1; } + return 0; } @@ -197,12 +205,17 @@ commGetSlowFd(void) int whichfd, retfd; if (!slowfdcnt) - return -1; + return -1; + whichfd = squid_random() % slowfdcnt; + retfd = slowfdarr[whichfd]; + slowfdarr[whichfd] = slowfdarr[--slowfdcnt]; + return retfd; } + #endif static int @@ -217,48 +230,61 @@ comm_check_incoming_select_handlers(int nfds, int *fds) FD_ZERO(&read_mask); FD_ZERO(&write_mask); incoming_sockets_accepted = 0; + for (i = 0; i < nfds; i++) { - fd = fds[i]; - if (fd_table[fd].read_handler) { - FD_SET(fd, &read_mask); - if (fd > maxfd) - maxfd = fd; - } - if (fd_table[fd].write_handler) { - FD_SET(fd, &write_mask); - if (fd > maxfd) - maxfd = fd; - } + fd = fds[i]; + + if (fd_table[fd].read_handler) { + FD_SET(fd, &read_mask); + + if (fd > maxfd) + maxfd = fd; + } + + if (fd_table[fd].write_handler) { + FD_SET(fd, &write_mask); + + if (fd > maxfd) + maxfd = fd; + } } + if (maxfd++ == 0) - return -1; + return -1; + getCurrentTime(); + statCounter.syscalls.selects++; + if (select(maxfd, &read_mask, &write_mask, NULL, &zero_tv) < 1) - return incoming_sockets_accepted; + return incoming_sockets_accepted; + for (i = 0; i < nfds; i++) { - fd = fds[i]; - if (FD_ISSET(fd, &read_mask)) { - if ((hdl = fd_table[fd].read_handler) != NULL) { - fd_table[fd].read_handler = NULL; - commUpdateReadBits(fd, NULL); - hdl(fd, fd_table[fd].read_data); - } else { - debug(5, 1) ("comm_select_incoming: FD %d NULL read handler\n", - fd); - } - } - if (FD_ISSET(fd, &write_mask)) { - if ((hdl = fd_table[fd].write_handler) != NULL) { - fd_table[fd].write_handler = NULL; - commUpdateWriteBits(fd, NULL); - hdl(fd, fd_table[fd].write_data); - } else { - debug(5, 1) ("comm_select_incoming: FD %d NULL write handler\n", - fd); - } - } + fd = fds[i]; + + if (FD_ISSET(fd, &read_mask)) { + if ((hdl = fd_table[fd].read_handler) != NULL) { + fd_table[fd].read_handler = NULL; + commUpdateReadBits(fd, NULL); + hdl(fd, fd_table[fd].read_data); + } else { + debug(5, 1) ("comm_select_incoming: FD %d NULL read handler\n", + fd); + } + } + + if (FD_ISSET(fd, &write_mask)) { + if ((hdl = fd_table[fd].write_handler) != NULL) { + fd_table[fd].write_handler = NULL; + commUpdateWriteBits(fd, NULL); + hdl(fd, fd_table[fd].write_data); + } else { + debug(5, 1) ("comm_select_incoming: FD %d NULL write handler\n", + fd); + } + } } + return incoming_sockets_accepted; } @@ -269,21 +295,30 @@ comm_select_icp_incoming(void) int fds[2]; int nevents; icp_io_events = 0; + if (theInIcpConnection >= 0) - fds[nfds++] = theInIcpConnection; + fds[nfds++] = theInIcpConnection; + if (theInIcpConnection != theOutIcpConnection) - if (theOutIcpConnection >= 0) - fds[nfds++] = theOutIcpConnection; + if (theOutIcpConnection >= 0) + fds[nfds++] = theOutIcpConnection; + if (nfds == 0) - return; + return; + nevents = comm_check_incoming_select_handlers(nfds, fds); + incoming_icp_interval += Config.comm_incoming.icp_average - nevents; + if (incoming_icp_interval < 0) - incoming_icp_interval = 0; + incoming_icp_interval = 0; + if (incoming_icp_interval > MAX_INCOMING_INTERVAL) - incoming_icp_interval = MAX_INCOMING_INTERVAL; + incoming_icp_interval = MAX_INCOMING_INTERVAL; + if (nevents > INCOMING_ICP_MAX) - nevents = INCOMING_ICP_MAX; + nevents = INCOMING_ICP_MAX; + statHistCount(&statCounter.comm_icp_incoming, nevents); } @@ -295,21 +330,29 @@ comm_select_http_incoming(void) int j; int nevents; http_io_events = 0; + for (j = 0; j < NHttpSockets; j++) { - if (HttpSockets[j] < 0) - continue; - if (commDeferRead(HttpSockets[j])) - continue; - fds[nfds++] = HttpSockets[j]; + if (HttpSockets[j] < 0) + continue; + + if (commDeferRead(HttpSockets[j])) + continue; + + fds[nfds++] = HttpSockets[j]; } + nevents = comm_check_incoming_select_handlers(nfds, fds); incoming_http_interval += Config.comm_incoming.http_average - nevents; + if (incoming_http_interval < 0) - incoming_http_interval = 0; + incoming_http_interval = 0; + if (incoming_http_interval > MAX_INCOMING_INTERVAL) - incoming_http_interval = MAX_INCOMING_INTERVAL; + incoming_http_interval = MAX_INCOMING_INTERVAL; + if (nevents > INCOMING_HTTP_MAX) - nevents = INCOMING_HTTP_MAX; + nevents = INCOMING_HTTP_MAX; + statHistCount(&statCounter.comm_http_incoming, nevents); } @@ -322,8 +365,10 @@ comm_select(int msec) fd_set pendingfds; fd_set writefds; #if DELAY_POOLS + fd_set slowfds; #endif + PF *hdl = NULL; int fd; int maxfd; @@ -335,280 +380,389 @@ comm_select(int msec) unsigned int k; int j; #if DEBUG_FDBITS + int i; #endif + fd_mask *fdsp; fd_mask *pfdsp; fd_mask tmask; static time_t last_timeout = 0; + struct timeval poll_time; double timeout = current_dtime + (msec / 1000.0); fde *F; + do { - double start; - getCurrentTime(); - start = current_dtime; + double start; + getCurrentTime(); + start = current_dtime; #if DELAY_POOLS - FD_ZERO(&slowfds); + + FD_ZERO(&slowfds); #endif - if (commCheckICPIncoming) - comm_select_icp_incoming(); - if (commCheckDNSIncoming) - comm_select_dns_incoming(); - if (commCheckHTTPIncoming) - comm_select_http_incoming(); - callicp = calldns = callhttp = 0; - maxfd = Biggest_FD + 1; - xmemcpy(&readfds, &global_readfds, - howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES); - xmemcpy(&writefds, &global_writefds, - howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES); - /* remove stalled FDs, and deal with pending descriptors */ - pending = 0; - FD_ZERO(&pendingfds); - maxindex = howmany(maxfd, FD_MASK_BITS); - fdsp = (fd_mask *) & readfds; - for (j = 0; j < maxindex; j++) { - if ((tmask = fdsp[j]) == 0) - continue; /* no bits here */ - for (k = 0; k < FD_MASK_BITS; k++) { - if (!EBIT_TEST(tmask, k)) - continue; - /* Found a set bit */ - fd = (j * FD_MASK_BITS) + k; - switch (commDeferRead(fd)) { - case 0: - break; - case 1: - FD_CLR(fd, &readfds); - break; + + if (commCheckICPIncoming) + comm_select_icp_incoming(); + + if (commCheckDNSIncoming) + comm_select_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_select_http_incoming(); + + callicp = calldns = callhttp = 0; + + maxfd = Biggest_FD + 1; + + xmemcpy(&readfds, &global_readfds, + howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES); + + xmemcpy(&writefds, &global_writefds, + howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES); + + /* remove stalled FDs, and deal with pending descriptors */ + pending = 0; + + FD_ZERO(&pendingfds); + + maxindex = howmany(maxfd, FD_MASK_BITS); + + fdsp = (fd_mask *) & readfds; + + for (j = 0; j < maxindex; j++) { + if ((tmask = fdsp[j]) == 0) + continue; /* no bits here */ + + for (k = 0; k < FD_MASK_BITS; k++) { + if (!EBIT_TEST(tmask, k)) + continue; + + /* Found a set bit */ + fd = (j * FD_MASK_BITS) + k; + + switch (commDeferRead(fd)) { + + case 0: + break; + + case 1: + FD_CLR(fd, &readfds); + break; #if DELAY_POOLS - case -1: - FD_SET(fd, &slowfds); - break; + + case -1: + FD_SET(fd, &slowfds); + break; #endif - default: - fatalf("bad return value from commDeferRead(FD %d)\n", fd); - } - if (FD_ISSET(fd, &readfds) && fd_table[fd].flags.read_pending) { - FD_SET(fd, &pendingfds); - pending++; - } - } - } + + default: + fatalf("bad return value from commDeferRead(FD %d)\n", fd); + } + + if (FD_ISSET(fd, &readfds) && fd_table[fd].flags.read_pending) { + FD_SET(fd, &pendingfds); + pending++; + } + } + } + #if DEBUG_FDBITS - for (i = 0; i < maxfd; i++) { - /* Check each open socket for a handler. */ + for (i = 0; i < maxfd; i++) { + /* Check each open socket for a handler. */ #if DELAY_POOLS - if (fd_table[i].read_handler && commDeferRead(i) != 1) { + + if (fd_table[i].read_handler && commDeferRead(i) != 1) { #else - if (fd_table[i].read_handler && !commDeferRead(i)) { + + if (fd_table[i].read_handler && !commDeferRead(i)) { #endif - assert(FD_ISSET(i, &readfds)); - } - if (fd_table[i].write_handler) { - assert(FD_ISSET(i, &writefds)); - } - } + assert(FD_ISSET(i, &readfds)); + } + + if (fd_table[i].write_handler) { + assert(FD_ISSET(i, &writefds)); + } + } + #endif - if (nreadfds + nwritefds == 0) { - assert(shutting_down); - return COMM_SHUTDOWN; - } - if (msec > MAX_POLL_TIME) - msec = MAX_POLL_TIME; - if (pending) - msec = 0; - for (;;) { - poll_time.tv_sec = msec / 1000; - poll_time.tv_usec = (msec % 1000) * 1000; - statCounter.syscalls.selects++; - num = select(maxfd, &readfds, &writefds, NULL, &poll_time); - statCounter.select_loops++; - if (num >= 0 || pending > 0) - break; - if (ignoreErrno(errno)) - break; - debug(50, 0) ("comm_select: select failure: %s\n", - xstrerror()); - examine_select(&readfds, &writefds); - return COMM_ERROR; - /* NOTREACHED */ - } - if (num < 0 && !pending) - continue; - debug(5, num ? 5 : 8) ("comm_select: %d+%d FDs ready at %d\n", - num, pending, (int) squid_curtime); - statHistCount(&statCounter.select_fds_hist, num); - /* Check lifetime and timeout handlers ONCE each second. - * Replaces brain-dead check every time through the loop! */ - if (squid_curtime > last_timeout) { - last_timeout = squid_curtime; - checkTimeouts(); - } - if (num == 0 && pending == 0) - continue; - /* Scan return fd masks for ready descriptors */ - fdsp = (fd_mask *) & readfds; - pfdsp = (fd_mask *) & pendingfds; - maxindex = howmany(maxfd, FD_MASK_BITS); - for (j = 0; j < maxindex; j++) { - if ((tmask = (fdsp[j] | pfdsp[j])) == 0) - continue; /* no bits here */ - for (k = 0; k < FD_MASK_BITS; k++) { - if (tmask == 0) - break; /* no more bits left */ - if (!EBIT_TEST(tmask, k)) - continue; - /* Found a set bit */ - fd = (j * FD_MASK_BITS) + k; - EBIT_CLR(tmask, k); /* this will be done */ + if (nreadfds + nwritefds == 0) { + assert(shutting_down); + return COMM_SHUTDOWN; + } + + if (msec > MAX_POLL_TIME) + msec = MAX_POLL_TIME; + + if (pending) + msec = 0; + + for (;;) { + poll_time.tv_sec = msec / 1000; + poll_time.tv_usec = (msec % 1000) * 1000; + statCounter.syscalls.selects++; + num = select(maxfd, &readfds, &writefds, NULL, &poll_time); + statCounter.select_loops++; + + if (num >= 0 || pending > 0) + break; + + if (ignoreErrno(errno)) + break; + + debug(50, 0) ("comm_select: select failure: %s\n", + xstrerror()); + + examine_select(&readfds, &writefds); + + return COMM_ERROR; + + /* NOTREACHED */ + } + + if (num < 0 && !pending) + continue; + + debug(5, num ? 5 : 8) ("comm_select: %d+%d FDs ready at %d\n", + num, pending, (int) squid_curtime); + + statHistCount(&statCounter.select_fds_hist, num); + + /* Check lifetime and timeout handlers ONCE each second. + * Replaces brain-dead check every time through the loop! */ + if (squid_curtime > last_timeout) { + last_timeout = squid_curtime; + checkTimeouts(); + } + + if (num == 0 && pending == 0) + continue; + + /* Scan return fd masks for ready descriptors */ + fdsp = (fd_mask *) & readfds; + + pfdsp = (fd_mask *) & pendingfds; + + maxindex = howmany(maxfd, FD_MASK_BITS); + + for (j = 0; j < maxindex; j++) { + if ((tmask = (fdsp[j] | pfdsp[j])) == 0) + continue; /* no bits here */ + + for (k = 0; k < FD_MASK_BITS; k++) { + if (tmask == 0) + break; /* no more bits left */ + + if (!EBIT_TEST(tmask, k)) + continue; + + /* Found a set bit */ + fd = (j * FD_MASK_BITS) + k; + + EBIT_CLR(tmask, k); /* this will be done */ + #if DEBUG_FDBITS - debug(5, 9) ("FD %d bit set for reading\n", fd); - assert(FD_ISSET(fd, &readfds)); + + debug(5, 9) ("FD %d bit set for reading\n", fd); + + assert(FD_ISSET(fd, &readfds)); + #endif - if (fdIsIcp(fd)) { - callicp = 1; - continue; - } - if (fdIsDns(fd)) { - calldns = 1; - continue; - } - if (fdIsHttp(fd)) { - callhttp = 1; - continue; - } - F = &fd_table[fd]; - debug(5, 6) ("comm_select: FD %d ready for reading\n", fd); - if (NULL == (hdl = F->read_handler)) - (void) 0; + + if (fdIsIcp(fd)) { + callicp = 1; + continue; + } + + if (fdIsDns(fd)) { + calldns = 1; + continue; + } + + if (fdIsHttp(fd)) { + callhttp = 1; + continue; + } + + F = &fd_table[fd]; + debug(5, 6) ("comm_select: FD %d ready for reading\n", fd); + + if (NULL == (hdl = F->read_handler)) + (void) 0; + #if DELAY_POOLS - else if (FD_ISSET(fd, &slowfds)) - commAddSlowFd(fd); + + else if (FD_ISSET(fd, &slowfds)) + commAddSlowFd(fd); + #endif - else { - F->read_handler = NULL; - commUpdateReadBits(fd, NULL); - hdl(fd, F->read_data); - statCounter.select_fds++; - if (commCheckICPIncoming) - comm_select_icp_incoming(); - if (commCheckDNSIncoming) - comm_select_dns_incoming(); - if (commCheckHTTPIncoming) - comm_select_http_incoming(); - } - } - } - fdsp = (fd_mask *) & writefds; - for (j = 0; j < maxindex; j++) { - if ((tmask = fdsp[j]) == 0) - continue; /* no bits here */ - for (k = 0; k < FD_MASK_BITS; k++) { - if (tmask == 0) - break; /* no more bits left */ - if (!EBIT_TEST(tmask, k)) - continue; - /* Found a set bit */ - fd = (j * FD_MASK_BITS) + k; - EBIT_CLR(tmask, k); /* this will be done */ + + else { + F->read_handler = NULL; + commUpdateReadBits(fd, NULL); + hdl(fd, F->read_data); + statCounter.select_fds++; + + if (commCheckICPIncoming) + comm_select_icp_incoming(); + + if (commCheckDNSIncoming) + comm_select_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_select_http_incoming(); + } + } + } + + fdsp = (fd_mask *) & writefds; + + for (j = 0; j < maxindex; j++) { + if ((tmask = fdsp[j]) == 0) + continue; /* no bits here */ + + for (k = 0; k < FD_MASK_BITS; k++) { + if (tmask == 0) + break; /* no more bits left */ + + if (!EBIT_TEST(tmask, k)) + continue; + + /* Found a set bit */ + fd = (j * FD_MASK_BITS) + k; + + EBIT_CLR(tmask, k); /* this will be done */ + #if DEBUG_FDBITS - debug(5, 9) ("FD %d bit set for writing\n", fd); - assert(FD_ISSET(fd, &writefds)); + + debug(5, 9) ("FD %d bit set for writing\n", fd); + + assert(FD_ISSET(fd, &writefds)); + #endif - if (fdIsIcp(fd)) { - callicp = 1; - continue; - } - if (fdIsDns(fd)) { - calldns = 1; - continue; - } - if (fdIsHttp(fd)) { - callhttp = 1; - continue; - } - F = &fd_table[fd]; - debug(5, 5) ("comm_select: FD %d ready for writing\n", fd); - if ((hdl = F->write_handler)) { - F->write_handler = NULL; - commUpdateWriteBits(fd, NULL); - hdl(fd, F->write_data); - statCounter.select_fds++; - if (commCheckICPIncoming) - comm_select_icp_incoming(); - if (commCheckDNSIncoming) - comm_select_dns_incoming(); - if (commCheckHTTPIncoming) - comm_select_http_incoming(); - } - } - } - if (callicp) - comm_select_icp_incoming(); - if (calldns) - comm_select_dns_incoming(); - if (callhttp) - comm_select_http_incoming(); + + if (fdIsIcp(fd)) { + callicp = 1; + continue; + } + + if (fdIsDns(fd)) { + calldns = 1; + continue; + } + + if (fdIsHttp(fd)) { + callhttp = 1; + continue; + } + + F = &fd_table[fd]; + debug(5, 5) ("comm_select: FD %d ready for writing\n", fd); + + if ((hdl = F->write_handler)) { + F->write_handler = NULL; + commUpdateWriteBits(fd, NULL); + hdl(fd, F->write_data); + statCounter.select_fds++; + + if (commCheckICPIncoming) + comm_select_icp_incoming(); + + if (commCheckDNSIncoming) + comm_select_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_select_http_incoming(); + } + } + } + + if (callicp) + comm_select_icp_incoming(); + + if (calldns) + comm_select_dns_incoming(); + + if (callhttp) + comm_select_http_incoming(); + #if DELAY_POOLS - while ((fd = commGetSlowFd()) != -1) { - F = &fd_table[fd]; - debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd); - if ((hdl = F->read_handler)) { - F->read_handler = NULL; - commUpdateReadBits(fd, NULL); - hdl(fd, F->read_data); - statCounter.select_fds++; - if (commCheckICPIncoming) - comm_select_icp_incoming(); - if (commCheckDNSIncoming) - comm_select_dns_incoming(); - if (commCheckHTTPIncoming) - comm_select_http_incoming(); - } - } + + while ((fd = commGetSlowFd()) != -1) { + F = &fd_table[fd]; + debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd); + + if ((hdl = F->read_handler)) { + F->read_handler = NULL; + commUpdateReadBits(fd, NULL); + hdl(fd, F->read_data); + statCounter.select_fds++; + + if (commCheckICPIncoming) + comm_select_icp_incoming(); + + if (commCheckDNSIncoming) + comm_select_dns_incoming(); + + if (commCheckHTTPIncoming) + comm_select_http_incoming(); + } + } + #endif - getCurrentTime(); - statCounter.select_time += (current_dtime - start); - return COMM_OK; + getCurrentTime(); + + statCounter.select_time += (current_dtime - start); + + return COMM_OK; } - while (timeout > current_dtime); + + while (timeout > current_dtime) + + ; debug(5, 8) ("comm_select: time out: %d\n", (int) squid_curtime); + return COMM_TIMEOUT; } static void -comm_select_dns_incoming(void) -{ +comm_select_dns_incoming(void) { int nfds = 0; int fds[2]; int nevents; dns_io_events = 0; + if (DnsSocket < 0) - return; + return; + fds[nfds++] = DnsSocket; + nevents = comm_check_incoming_select_handlers(nfds, fds); + if (nevents < 0) - return; + return; + incoming_dns_interval += Config.comm_incoming.dns_average - nevents; + if (incoming_dns_interval < Config.comm_incoming.dns_min_poll) - incoming_dns_interval = Config.comm_incoming.dns_min_poll; + incoming_dns_interval = Config.comm_incoming.dns_min_poll; + if (incoming_dns_interval > MAX_INCOMING_INTERVAL) - incoming_dns_interval = MAX_INCOMING_INTERVAL; + incoming_dns_interval = MAX_INCOMING_INTERVAL; + if (nevents > INCOMING_DNS_MAX) - nevents = INCOMING_DNS_MAX; + nevents = INCOMING_DNS_MAX; + statHistCount(&statCounter.comm_dns_incoming, nevents); } void -comm_select_init(void) -{ +comm_select_init(void) { zero_tv.tv_sec = 0; zero_tv.tv_usec = 0; cachemgrRegister("comm_incoming", - "comm_incoming() stats", - commIncomingStats, 0, 1); + "comm_incoming() stats", + commIncomingStats, 0, 1); FD_ZERO(&global_readfds); FD_ZERO(&global_writefds); nreadfds = nwritefds = 0; @@ -625,72 +779,82 @@ comm_select_init(void) * Call this from where the select loop fails. */ static int -examine_select(fd_set * readfds, fd_set * writefds) -{ +examine_select(fd_set * readfds, fd_set * writefds) { int fd = 0; fd_set read_x; fd_set write_x; + struct timeval tv; close_handler *ch = NULL; fde *F = NULL; + struct stat sb; debug(5, 0) ("examine_select: Examining open file descriptors...\n"); + for (fd = 0; fd < Squid_MaxFD; fd++) { - FD_ZERO(&read_x); - FD_ZERO(&write_x); - tv.tv_sec = tv.tv_usec = 0; - if (FD_ISSET(fd, readfds)) - FD_SET(fd, &read_x); - else if (FD_ISSET(fd, writefds)) - FD_SET(fd, &write_x); - else - continue; - statCounter.syscalls.selects++; - errno = 0; - if (!fstat(fd, &sb)) { - debug(5, 5) ("FD %d is valid.\n", fd); - continue; - } - F = &fd_table[fd]; - debug(5, 0) ("FD %d: %s\n", fd, xstrerror()); - debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd); - debug(5, 0) ("FD %d is a %s called '%s'\n", - fd, - fdTypeStr[F->type], - F->desc); - debug(5, 0) ("tmout:%p read:%p write:%p\n", - F->timeout_handler, - F->read_handler, - F->write_handler); - for (ch = F->closeHandler; ch; ch = ch->next) - debug(5, 0) (" close handler: %p\n", ch->handler); - if (F->closeHandler) { - commCallCloseHandlers(fd); - } else if (F->timeout_handler) { - debug(5, 0) ("examine_select: Calling Timeout Handler\n"); - F->timeout_handler(fd, F->timeout_data); - } - F->closeHandler = NULL; - F->timeout_handler = NULL; - F->read_handler = NULL; - F->write_handler = NULL; - FD_CLR(fd, readfds); - FD_CLR(fd, writefds); + FD_ZERO(&read_x); + FD_ZERO(&write_x); + tv.tv_sec = tv.tv_usec = 0; + + if (FD_ISSET(fd, readfds)) + FD_SET(fd, &read_x); + else if (FD_ISSET(fd, writefds)) + FD_SET(fd, &write_x); + else + continue; + + statCounter.syscalls.selects++; + + errno = 0; + + if (!fstat(fd, &sb)) { + debug(5, 5) ("FD %d is valid.\n", fd); + continue; + } + + F = &fd_table[fd]; + debug(5, 0) ("FD %d: %s\n", fd, xstrerror()); + debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd); + debug(5, 0) ("FD %d is a %s called '%s'\n", + fd, + fdTypeStr[F->type], + F->desc); + debug(5, 0) ("tmout:%p read:%p write:%p\n", + F->timeout_handler, + F->read_handler, + F->write_handler); + + for (ch = F->closeHandler; ch; ch = ch->next) + debug(5, 0) (" close handler: %p\n", ch->handler); + + if (F->closeHandler) { + commCallCloseHandlers(fd); + } else if (F->timeout_handler) { + debug(5, 0) ("examine_select: Calling Timeout Handler\n"); + F->timeout_handler(fd, F->timeout_data); + } + + F->closeHandler = NULL; + F->timeout_handler = NULL; + F->read_handler = NULL; + F->write_handler = NULL; + FD_CLR(fd, readfds); + FD_CLR(fd, writefds); } + return 0; } static void -commIncomingStats(StoreEntry * sentry) -{ +commIncomingStats(StoreEntry * sentry) { StatCounters *f = &statCounter; storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n", - incoming_icp_interval >> INCOMING_FACTOR); + incoming_icp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", - incoming_dns_interval >> INCOMING_FACTOR); + incoming_dns_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n", - incoming_http_interval >> INCOMING_FACTOR); + incoming_http_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n"); @@ -702,33 +866,30 @@ commIncomingStats(StoreEntry * sentry) } void -commUpdateReadBits(int fd, PF * handler) -{ +commUpdateReadBits(int fd, PF * handler) { if (handler && !FD_ISSET(fd, &global_readfds)) { - FD_SET(fd, &global_readfds); - nreadfds++; + FD_SET(fd, &global_readfds); + nreadfds++; } else if (!handler && FD_ISSET(fd, &global_readfds)) { - FD_CLR(fd, &global_readfds); - nreadfds--; + FD_CLR(fd, &global_readfds); + nreadfds--; } } void -commUpdateWriteBits(int fd, PF * handler) -{ +commUpdateWriteBits(int fd, PF * handler) { if (handler && !FD_ISSET(fd, &global_writefds)) { - FD_SET(fd, &global_writefds); - nwritefds++; + FD_SET(fd, &global_writefds); + nwritefds++; } else if (!handler && FD_ISSET(fd, &global_writefds)) { - FD_CLR(fd, &global_writefds); - nwritefds--; + FD_CLR(fd, &global_writefds); + nwritefds--; } } /* Called by async-io or diskd to speed up the polling */ void -comm_quick_poll_required(void) -{ +comm_quick_poll_required(void) { MAX_POLL_TIME = 10; } diff --git a/src/debug.cc b/src/debug.cc index 56c41d225a..37498b74d8 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -1,6 +1,6 @@ /* - * $Id: debug.cc,v 1.88 2003/02/03 21:33:15 robertc Exp $ + * $Id: debug.cc,v 1.89 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 0 Debug Routines * AUTHOR: Harvest Derived @@ -55,13 +55,15 @@ _db_print(const char *format,...) { #else _db_print(va_alist) - va_dcl +va_dcl { const char *format = NULL; #endif + LOCAL_ARRAY(char, f, BUFSIZ); va_list args1; #if STDC_HEADERS + va_list args2; va_list args3; #else @@ -69,164 +71,213 @@ _db_print(va_alist) #define args3 args1 #endif /* give a chance to context-based debugging to print current context */ + if (!Ctx_Lock) - ctx_print(); + ctx_print(); + #if STDC_HEADERS + va_start(args1, format); + va_start(args2, format); + va_start(args3, format); + #else + format = va_arg(args1, const char *); + #endif + snprintf(f, BUFSIZ, "%s| %s", - debugLogTime(squid_curtime), - format); + debugLogTime(squid_curtime), + format); + _db_print_file(f, args1); + _db_print_stderr(f, args2); + #if HAVE_SYSLOG + _db_print_syslog(format, args3); + #endif + va_end(args1); + #if STDC_HEADERS + va_end(args2); + va_end(args3); + #endif } static void -_db_print_file(const char *format, va_list args) -{ +_db_print_file(const char *format, va_list args) { if (debug_log == NULL) - return; + return; + /* give a chance to context-based debugging to print current context */ if (!Ctx_Lock) - ctx_print(); + ctx_print(); + vfprintf(debug_log, format, args); + if (!Config.onoff.buffered_logs) - fflush(debug_log); + fflush(debug_log); } static void -_db_print_stderr(const char *format, va_list args) -{ +_db_print_stderr(const char *format, va_list args) { if (opt_debug_stderr < Debug::level) - return; + return; + if (debug_log == stderr) - return; + return; + vfprintf(stderr, format, args); } #if HAVE_SYSLOG static void -_db_print_syslog(const char *format, va_list args) -{ +_db_print_syslog(const char *format, va_list args) { LOCAL_ARRAY(char, tmpbuf, BUFSIZ); /* level 0,1 go to syslog */ + if (Debug::level > 1) - return; + return; + if (0 == opt_syslog_enable) - return; + return; + tmpbuf[0] = '\0'; + vsnprintf(tmpbuf, BUFSIZ, format, args); + tmpbuf[BUFSIZ - 1] = '\0'; + syslog(Debug::level == 0 ? LOG_WARNING : LOG_NOTICE, "%s", tmpbuf); } + #endif /* HAVE_SYSLOG */ static void -debugArg(const char *arg) -{ +debugArg(const char *arg) { int s = 0; int l = 0; int i; + if (!strncasecmp(arg, "ALL", 3)) { - s = -1; - arg += 4; + s = -1; + arg += 4; } else { - s = atoi(arg); - while (*arg && *arg++ != ','); + s = atoi(arg); + + while (*arg && *arg++ != ',') + + ; } + l = atoi(arg); assert(s >= -1); assert(s < MAX_DEBUG_SECTIONS); + if (l < 0) - l = 0; + l = 0; + if (l > 10) - l = 10; + l = 10; + if (s >= 0) { - Debug::Levels[s] = l; - return; + Debug::Levels[s] = l; + return; } + for (i = 0; i < MAX_DEBUG_SECTIONS; i++) - Debug::Levels[i] = l; + Debug::Levels[i] = l; } static void -debugOpenLog(const char *logfile) -{ +debugOpenLog(const char *logfile) { if (logfile == NULL) { - debug_log = stderr; - return; + debug_log = stderr; + return; } + if (debug_log_file) - xfree(debug_log_file); + xfree(debug_log_file); + debug_log_file = xstrdup(logfile); /* keep a static copy */ + if (debug_log && debug_log != stderr) - fclose(debug_log); + fclose(debug_log); + debug_log = fopen(logfile, "a+"); + if (!debug_log) { - fprintf(stderr, "WARNING: Cannot write log file: %s\n", logfile); - perror(logfile); - fprintf(stderr, " messages will be sent to 'stderr'.\n"); - fflush(stderr); - debug_log = stderr; + fprintf(stderr, "WARNING: Cannot write log file: %s\n", logfile); + perror(logfile); + fprintf(stderr, " messages will be sent to 'stderr'.\n"); + fflush(stderr); + debug_log = stderr; } + #if defined(_SQUID_CYGWIN_)||defined(_SQUID_MSWIN_) setmode(fileno(debug_log), O_TEXT); + #endif } void -_db_init(const char *logfile, const char *options) -{ +_db_init(const char *logfile, const char *options) { int i; char *p = NULL; char *s = NULL; for (i = 0; i < MAX_DEBUG_SECTIONS; i++) - Debug::Levels[i] = -1; + Debug::Levels[i] = -1; if (options) { - p = xstrdup(options); - for (s = strtok(p, w_space); s; s = strtok(NULL, w_space)) - debugArg(s); - xfree(p); + p = xstrdup(options); + + for (s = strtok(p, w_space); s; s = strtok(NULL, w_space)) + debugArg(s); + + xfree(p); } + debugOpenLog(logfile); #if HAVE_SYSLOG && defined(LOG_LOCAL4) + if (opt_syslog_enable) - openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4); + openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4); + #endif /* HAVE_SYSLOG */ } void -_db_rotate_log(void) -{ +_db_rotate_log(void) { int i; LOCAL_ARRAY(char, from, MAXPATHLEN); LOCAL_ARRAY(char, to, MAXPATHLEN); #ifdef S_ISREG + struct stat sb; #endif if (debug_log_file == NULL) - return; + return; + #ifdef S_ISREG + if (stat(debug_log_file, &sb) == 0) - if (S_ISREG(sb.st_mode) == 0) - return; + if (S_ISREG(sb.st_mode) == 0) + return; + #endif /* @@ -236,56 +287,69 @@ _db_rotate_log(void) */ /* Rotate numbers 0 through N up one */ for (i = Config.Log.rotateNumber; i > 1;) { - i--; - snprintf(from, MAXPATHLEN, "%s.%d", debug_log_file, i - 1); - snprintf(to, MAXPATHLEN, "%s.%d", debug_log_file, i); + i--; + snprintf(from, MAXPATHLEN, "%s.%d", debug_log_file, i - 1); + snprintf(to, MAXPATHLEN, "%s.%d", debug_log_file, i); #ifdef _SQUID_MSWIN_ - remove(to); + + remove + (to); + #endif - rename(from, to); + + rename(from, to); } -/* - * You can't rename open files on Microsoft "operating systems" - * so we close before renaming. - */ + + /* + * You can't rename open files on Microsoft "operating systems" + * so we close before renaming. + */ #ifdef _SQUID_MSWIN_ if (debug_log != stderr) - fclose(debug_log); + fclose(debug_log); + #endif /* Rotate the current log to .0 */ if (Config.Log.rotateNumber > 0) { - snprintf(to, MAXPATHLEN, "%s.%d", debug_log_file, 0); + snprintf(to, MAXPATHLEN, "%s.%d", debug_log_file, 0); #ifdef _SQUID_MSWIN_ - remove(to); + + remove + (to); + #endif - rename(debug_log_file, to); + + rename(debug_log_file, to); } + /* Close and reopen the log. It may have been renamed "manually" * before HUP'ing us. */ if (debug_log != stderr) - debugOpenLog(Config.Log.log); + debugOpenLog(Config.Log.log); } static const char * -debugLogTime(time_t t) -{ +debugLogTime(time_t t) { + struct tm *tm; static char buf[128]; static time_t last_t = 0; + if (t != last_t) { - tm = localtime(&t); - strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); - last_t = t; + tm = localtime(&t); + strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); + last_t = t; } + return buf; } void -xassert(const char *msg, const char *file, int line) -{ +xassert(const char *msg, const char *file, int line) { debug(0, 0) ("assertion failed: %s:%d: \"%s\"\n", file, line, msg); + if (!shutting_down) - abort(); + abort(); } /* @@ -383,27 +447,27 @@ static const char *ctx_get_descr(Ctx ctx); Ctx -ctx_enter(const char *descr) -{ +ctx_enter(const char *descr) { Ctx_Current_Level++; if (Ctx_Current_Level <= CTX_MAX_LEVEL) - Ctx_Descrs[Ctx_Current_Level] = descr; + Ctx_Descrs[Ctx_Current_Level] = descr; if (Ctx_Current_Level == Ctx_Warn_Level) { - debug(0, 0) ("# ctx: suspiciously deep (%d) nesting:\n", Ctx_Warn_Level); - Ctx_Warn_Level *= 2; + debug(0, 0) ("# ctx: suspiciously deep (%d) nesting:\n", Ctx_Warn_Level); + Ctx_Warn_Level *= 2; } + return Ctx_Current_Level; } void -ctx_exit(Ctx ctx) -{ +ctx_exit(Ctx ctx) { assert(ctx >= 0); Ctx_Current_Level = (ctx >= 0) ? ctx - 1 : -1; + if (Ctx_Valid_Level > Ctx_Current_Level) - Ctx_Valid_Level = Ctx_Current_Level; + Ctx_Valid_Level = Ctx_Current_Level; } /* @@ -411,36 +475,39 @@ ctx_exit(Ctx ctx) * info for deducing the current execution stack */ static void -ctx_print(void) -{ +ctx_print(void) { /* lock so _db_print will not call us recursively */ Ctx_Lock++; /* ok, user saw [0,Ctx_Reported_Level] descriptions */ /* first inform about entries popped since user saw them */ + if (Ctx_Valid_Level < Ctx_Reported_Level) { - if (Ctx_Reported_Level != Ctx_Valid_Level + 1) - _db_print("ctx: exit levels from %2d down to %2d\n", - Ctx_Reported_Level, Ctx_Valid_Level + 1); - else - _db_print("ctx: exit level %2d\n", Ctx_Reported_Level); - Ctx_Reported_Level = Ctx_Valid_Level; + if (Ctx_Reported_Level != Ctx_Valid_Level + 1) + _db_print("ctx: exit levels from %2d down to %2d\n", + Ctx_Reported_Level, Ctx_Valid_Level + 1); + else + _db_print("ctx: exit level %2d\n", Ctx_Reported_Level); + + Ctx_Reported_Level = Ctx_Valid_Level; } + /* report new contexts that were pushed since last report */ while (Ctx_Reported_Level < Ctx_Current_Level) { - Ctx_Reported_Level++; - Ctx_Valid_Level++; - _db_print("ctx: enter level %2d: '%s'\n", Ctx_Reported_Level, - ctx_get_descr(Ctx_Reported_Level)); + Ctx_Reported_Level++; + Ctx_Valid_Level++; + _db_print("ctx: enter level %2d: '%s'\n", Ctx_Reported_Level, + ctx_get_descr(Ctx_Reported_Level)); } + /* unlock */ Ctx_Lock--; } /* checks for nulls and overflows */ static const char * -ctx_get_descr(Ctx ctx) -{ +ctx_get_descr(Ctx ctx) { if (ctx < 0 || ctx > CTX_MAX_LEVEL) - return ""; + return ""; + return Ctx_Descrs[ctx] ? Ctx_Descrs[ctx] : ""; } diff --git a/src/delay_pools.cc b/src/delay_pools.cc index 3dd17764ee..2b94ff5235 100644 --- a/src/delay_pools.cc +++ b/src/delay_pools.cc @@ -1,6 +1,6 @@ /* - * $Id: delay_pools.cc,v 1.33 2003/02/05 10:36:50 robertc Exp $ + * $Id: delay_pools.cc,v 1.34 2003/02/21 22:50:07 robertc Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -76,8 +76,10 @@ long DelayPools::MemoryUsed = 0; -class Aggregate : public CompositePoolNode { - public: +class Aggregate : public CompositePoolNode +{ + +public: typedef RefCount Pointer; void *operator new(size_t); void operator delete (void *); @@ -85,101 +87,137 @@ class Aggregate : public CompositePoolNode { Aggregate(); ~Aggregate(); virtual DelaySpec *rate() {return &spec;} + virtual DelaySpec const *rate() const {return &spec;} + virtual void stats(StoreEntry * sentry); virtual void dump(StoreEntry *entry) const; virtual void update(int incr); virtual void parse(); + virtual DelayIdComposite::Pointer id(struct in_addr &src_addr, AuthUserRequest *); - private: - class AggregateId:public DelayIdComposite { - public: - void *operator new(size_t); - void operator delete (void *); - virtual void deleteSelf() const; - AggregateId (Aggregate::Pointer); - virtual int bytesWanted (int min, int max) const; - virtual void bytesIn(int qty); - private: - Aggregate::Pointer theAggregate; + +private: + +class AggregateId:public DelayIdComposite + { + + public: + void *operator new(size_t); + void operator delete (void *); + virtual void deleteSelf() const; + AggregateId (Aggregate::Pointer); + virtual int bytesWanted (int min, int max) const; + virtual void bytesIn(int qty); + + private: + Aggregate::Pointer theAggregate; }; + DelayBucket theBucket; DelaySpec spec; }; template -class VectorMap { - public: + +class VectorMap +{ + +public: VectorMap(); unsigned int size() const; unsigned char findKeyIndex (Key const key) const; bool indexUsed (unsigned char const index) const; unsigned int insert (Key const key); - + #define IND_MAP_SZ 256 + Key key_map[IND_MAP_SZ]; Value values[IND_MAP_SZ]; - private: + +private: unsigned int nextMapPosition; }; -class VectorPool : public CompositePoolNode { - public: +class VectorPool : public CompositePoolNode +{ + +public: typedef RefCount Pointer; virtual void dump(StoreEntry *entry) const; virtual void parse(); virtual void update(int incr); virtual void stats(StoreEntry * sentry); + virtual DelayIdComposite::Pointer id(struct in_addr &src_addr, AuthUserRequest *); VectorMap buckets; VectorPool(); ~VectorPool(); - protected: + +protected: bool keyAllocated (unsigned char const key) const; virtual DelaySpec *rate() {return &spec;} + virtual DelaySpec const *rate() const {return &spec;} + virtual char const *label() const = 0; + virtual unsigned int const makeKey (struct in_addr &src_addr) const = 0; DelaySpec spec; - class Id:public DelayIdComposite { - public: - void *operator new(size_t); - void operator delete (void *); - virtual void deleteSelf() const; - Id (VectorPool::Pointer, int); - virtual int bytesWanted (int min, int max) const; - virtual void bytesIn(int qty); - private: - VectorPool::Pointer theVector; - int theIndex; + +class Id:public DelayIdComposite + { + + public: + void *operator new(size_t); + void operator delete (void *); + virtual void deleteSelf() const; + Id (VectorPool::Pointer, int); + virtual int bytesWanted (int min, int max) const; + virtual void bytesIn(int qty); + + private: + VectorPool::Pointer theVector; + int theIndex; }; }; -class IndividualPool : public VectorPool { - public: +class IndividualPool : public VectorPool +{ + +public: void *operator new(size_t); void operator delete (void *); virtual void deleteSelf() const; - protected: + +protected: virtual char const *label() const {return "Individual";} + virtual unsigned int const makeKey (struct in_addr &src_addr) const; }; -class ClassCNetPool : public VectorPool { - public: +class ClassCNetPool : public VectorPool +{ + +public: void *operator new(size_t); void operator delete (void *); virtual void deleteSelf() const; - protected: + +protected: virtual char const *label() const {return "Network";} + virtual unsigned int const makeKey (struct in_addr &src_addr) const; }; /* don't use remote storage for these */ -class ClassCBucket { - public: + +class ClassCBucket +{ + +public: bool individualUsed (unsigned int index)const; unsigned char findHostMapPosition (unsigned char const host) const; bool individualAllocated (unsigned char host) const; @@ -187,43 +225,55 @@ class ClassCBucket { void initHostIndex (DelaySpec &rate, unsigned char index, unsigned char host); void update (DelaySpec const &, int incr); void stats(StoreEntry *)const; - + DelayBucket net; VectorMap individuals; }; -class ClassCHostPool : public CompositePoolNode { - public: +class ClassCHostPool : public CompositePoolNode +{ + +public: typedef RefCount Pointer; virtual void dump(StoreEntry *entry) const; virtual void parse(); virtual void update(int incr); virtual void stats(StoreEntry * sentry); + virtual DelayIdComposite::Pointer id(struct in_addr &src_addr, AuthUserRequest *); ClassCHostPool(); ~ClassCHostPool(); - protected: + +protected: bool keyAllocated (unsigned char const key) const; virtual DelaySpec *rate() {return &spec;} + virtual DelaySpec const *rate() const {return &spec;} + virtual char const *label() const {return "Individual";} + virtual unsigned int const makeKey (struct in_addr &src_addr) const; + unsigned char const makeHostKey (struct in_addr &src_addr) const; DelaySpec spec; VectorMap buckets; - class Id:public DelayIdComposite { - public: - void *operator new(size_t); - void operator delete (void *); - virtual void deleteSelf() const; - Id (ClassCHostPool::Pointer, unsigned char, unsigned char); - virtual int bytesWanted (int min, int max) const; - virtual void bytesIn(int qty); - private: - ClassCHostPool::Pointer theClassCHost; - unsigned char theNet; - unsigned char theHost; + +class Id:public DelayIdComposite + { + + public: + void *operator new(size_t); + void operator delete (void *); + virtual void deleteSelf() const; + Id (ClassCHostPool::Pointer, unsigned char, unsigned char); + virtual int bytesWanted (int min, int max) const; + virtual void bytesIn(int qty); + + private: + ClassCHostPool::Pointer theClassCHost; + unsigned char theNet; + unsigned char theHost; }; }; @@ -252,54 +302,63 @@ CommonPool * CommonPool::Factory(unsigned char _class, CompositePoolNode::Pointer& compositeCopy) { CommonPool *result = new CommonPool; + switch (_class) { - case 0: - break; - case 1: - compositeCopy = new Aggregate; - result->typeLabel = "1"; - break; - case 2: - result->typeLabel = "2"; - { - DelayVector::Pointer temp = new DelayVector; - compositeCopy = temp.getRaw(); - temp->push_back (new Aggregate); - temp->push_back(new IndividualPool); - } - break; - case 3: - result->typeLabel = "3"; - { - DelayVector::Pointer temp = new DelayVector; - compositeCopy = temp.getRaw(); - temp->push_back (new Aggregate); - temp->push_back (new ClassCNetPool); - temp->push_back (new ClassCHostPool); - } - break; - case 4: - result->typeLabel = "4"; - { - DelayVector::Pointer temp = new DelayVector; - compositeCopy = temp.getRaw(); - temp->push_back (new Aggregate); - temp->push_back (new ClassCNetPool); - temp->push_back (new ClassCHostPool); - temp->push_back (new DelayUser); - } - break; - default: + + case 0: + break; + + case 1: + compositeCopy = new Aggregate; + result->typeLabel = "1"; + break; + + case 2: + result->typeLabel = "2"; + { + DelayVector::Pointer temp = new DelayVector; + compositeCopy = temp.getRaw(); + temp->push_back (new Aggregate); + temp->push_back(new IndividualPool); + } + + break; + + case 3: + result->typeLabel = "3"; + { + DelayVector::Pointer temp = new DelayVector; + compositeCopy = temp.getRaw(); + temp->push_back (new Aggregate); + temp->push_back (new ClassCNetPool); + temp->push_back (new ClassCHostPool); + } + + break; + + case 4: + result->typeLabel = "4"; + { + DelayVector::Pointer temp = new DelayVector; + compositeCopy = temp.getRaw(); + temp->push_back (new Aggregate); + temp->push_back (new ClassCNetPool); + temp->push_back (new ClassCHostPool); + temp->push_back (new DelayUser); + } + + break; + + default: fatal ("unknown delay pool class"); - return NULL; + return NULL; }; return result; } -CommonPool::CommonPool() -{ -} +CommonPool::CommonPool() +{} void ClassCBucket::update (DelaySpec const &rate, int incr) @@ -308,16 +367,16 @@ ClassCBucket::update (DelaySpec const &rate, int incr) assert (rate.restore_bps != -1); for (unsigned char j = 0; j < individuals.size(); ++j) - individuals.values[j].update (rate, incr); + individuals.values[j].update (rate, incr); } void ClassCBucket::stats(StoreEntry *sentry)const { for (unsigned int j = 0; j < individuals.size(); ++j) { - assert (individualUsed (j)); - storeAppendPrintf(sentry, " %d:",individuals.key_map[j]); - individuals.values[j].stats (sentry); + assert (individualUsed (j)); + storeAppendPrintf(sentry, " %d:",individuals.key_map[j]); + individuals.values[j].stats (sentry); } } @@ -343,11 +402,14 @@ unsigned char ClassCBucket::hostPosition (DelaySpec &rate, unsigned char const host) { if (individualAllocated (host)) - return findHostMapPosition(host); + return findHostMapPosition(host); assert (!individualUsed (findHostMapPosition(host))); + unsigned char result = findHostMapPosition(host); + initHostIndex (rate, result, host); + return result; } @@ -355,7 +417,7 @@ void ClassCBucket::initHostIndex (DelaySpec &rate, unsigned char index, unsigned char host) { assert (!individualUsed(index)); - + unsigned char const newIndex = individuals.insert (host); /* give the bucket a default value */ @@ -417,10 +479,14 @@ void Aggregate::stats(StoreEntry * sentry) { rate()->stats (sentry, "Aggregate"); + if (rate()->restore_bps == -1) - return; + return; + storeAppendPrintf(sentry, "\t\tCurrent: "); + theBucket.stats(sentry); + storeAppendPrintf(sentry, "\n\n"); } @@ -443,12 +509,13 @@ Aggregate::parse() } DelayIdComposite::Pointer + Aggregate::id(struct in_addr &src_addr, AuthUserRequest *) { if (rate()->restore_bps != -1) - return new AggregateId (this); + return new AggregateId (this); else - return new NullDelayId; + return new NullDelayId; } void * @@ -472,8 +539,7 @@ Aggregate::AggregateId::deleteSelf() const } Aggregate::AggregateId::AggregateId(Aggregate::Pointer anAggregate) : theAggregate(anAggregate) -{ -} +{} int Aggregate::AggregateId::bytesWanted (int min, int max) const @@ -504,9 +570,12 @@ void DelayPools::InitDelayData() { if (!pools()) - return; + return; + DelayPools::delay_data = new DelayPool[pools()]; + DelayPools::MemoryUsed += pools() * sizeof(DelayPool); + eventAdd("DelayPools::Update", DelayPools::Update, NULL, 1.0, 1); } @@ -540,16 +609,22 @@ void DelayPools::Update(void *unused) { if (!pools()) - return; + return; + eventAdd("DelayPools::Update", Update, NULL, 1.0, 1); + int incr = squid_curtime - LastUpdate; + if (incr < 1) - return; + return; + LastUpdate = squid_curtime; + Vector::iterator pos = toUpdate.begin(); + while (pos != toUpdate.end()) { - (*pos)->update(incr); - ++pos; + (*pos)->update(incr); + ++pos; } } @@ -564,19 +639,23 @@ void DelayPools::deregisterForUpdates (Updateable *anObject) { Vector::iterator pos = toUpdate.begin(); + while (pos != toUpdate.end() && *pos != anObject) { - ++pos; + ++pos; } + if (pos != toUpdate.end()) { - /* move all objects down one */ - Vector::iterator temp = pos; - ++pos; - while (pos != toUpdate.end()) { - *temp = *pos; - ++temp; - ++pos; - } - toUpdate.pop_back(); + /* move all objects down one */ + Vector::iterator temp = pos; + ++pos; + + while (pos != toUpdate.end()) { + *temp = *pos; + ++temp; + ++pos; + } + + toUpdate.pop_back(); } } @@ -588,13 +667,15 @@ DelayPools::Stats(StoreEntry * sentry) unsigned short i; storeAppendPrintf(sentry, "Delay pools configured: %d\n\n", DelayPools::pools()); + for (i = 0; i < DelayPools::pools(); ++i) { - if (DelayPools::delay_data[i].theComposite().getRaw()) { - storeAppendPrintf(sentry, "Pool: %d\n\tClass: %s\n\n", i + 1, DelayPools::delay_data[i].pool->theClassTypeLabel()); - DelayPools::delay_data[i].theComposite()->stats (sentry); - } else - storeAppendPrintf(sentry, "\tMisconfigured pool.\n\n"); + if (DelayPools::delay_data[i].theComposite().getRaw()) { + storeAppendPrintf(sentry, "Pool: %d\n\tClass: %s\n\n", i + 1, DelayPools::delay_data[i].pool->theClassTypeLabel()); + DelayPools::delay_data[i].theComposite()->stats (sentry); + } else + storeAppendPrintf(sentry, "\tMisconfigured pool.\n\n"); } + storeAppendPrintf(sentry, "Memory Used: %d bytes\n", (int) DelayPools::MemoryUsed); } @@ -602,12 +683,13 @@ void DelayPools::FreePools() { if (!DelayPools::pools()) - return; + return; + FreeDelayData(); } unsigned short -DelayPools::pools() +DelayPools::pools() { return pools_; } @@ -616,26 +698,27 @@ void DelayPools::pools (u_short newPools) { if (pools()) { - debug(3, 0) ("parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config\n"); - FreePools(); + debug(3, 0) ("parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config\n"); + FreePools(); } + pools_ = newPools; + if (pools()) - InitDelayData(); + InitDelayData(); } template VectorMap::VectorMap() : nextMapPosition(0) -{ -} +{} template -unsigned int +unsigned int VectorMap::size() const { return nextMapPosition; } - + template unsigned int VectorMap::insert (Key const key) @@ -684,17 +767,22 @@ void VectorPool::stats(StoreEntry * sentry) { rate()->stats (sentry, label()); + if (rate()->restore_bps == -1) { - storeAppendPrintf(sentry, "\n\n"); - return; + storeAppendPrintf(sentry, "\n\n"); + return; } + storeAppendPrintf(sentry, "\t\tCurrent:"); + for (unsigned int i = 0; i < buckets.size(); i++) { - storeAppendPrintf(sentry, " %d:", buckets.key_map[i]); - buckets.values[i].stats(sentry); + storeAppendPrintf(sentry, " %d:", buckets.key_map[i]); + buckets.values[i].stats(sentry); } + if (!buckets.size()) - storeAppendPrintf(sentry, " Not used yet."); + storeAppendPrintf(sentry, " Not used yet."); + storeAppendPrintf(sentry, "\n\n"); } @@ -708,9 +796,10 @@ void VectorPool::update(int incr) { if (rate()->restore_bps == -1) - return; + return; + for (unsigned int i = 0; i< buckets.size(); ++i) - buckets.values[i].update (*rate(), incr); + buckets.values[i].update (*rate(), incr); } void @@ -739,27 +828,32 @@ unsigned char VectorMap::findKeyIndex (Key const key) const { for (unsigned int index = 0; index < size(); ++index) { - assert (indexUsed (index)); - if (key_map[index] == key) - return index; + assert (indexUsed (index)); + + if (key_map[index] == key) + return index; } + /* not in map */ return size(); } DelayIdComposite::Pointer + VectorPool::id(struct in_addr &src_addr, AuthUserRequest *) { if (rate()->restore_bps == -1) - return new NullDelayId; + return new NullDelayId; unsigned int key = makeKey (src_addr); if (keyAllocated (key)) - return new Id (this, buckets.findKeyIndex(key)); - + return new Id (this, buckets.findKeyIndex(key)); + unsigned char const resultIndex = buckets.insert(key); + buckets.values[resultIndex].init (*rate()); + return new Id(this, resultIndex); } @@ -784,8 +878,7 @@ VectorPool::Id::deleteSelf() const } VectorPool::Id::Id (VectorPool::Pointer aPool, int anIndex) : theVector (aPool), theIndex (anIndex) -{ -} +{} int VectorPool::Id::bytesWanted (int min, int max) const @@ -800,6 +893,7 @@ VectorPool::Id::bytesIn(int qty) } unsigned int const + IndividualPool::makeKey (struct in_addr &src_addr) const { unsigned int host; @@ -828,6 +922,7 @@ ClassCNetPool::deleteSelf() const } unsigned int const + ClassCNetPool::makeKey (struct in_addr &src_addr) const { unsigned int net; @@ -850,19 +945,20 @@ void ClassCHostPool::stats(StoreEntry * sentry) { rate()->stats (sentry, label()); + if (rate()->restore_bps == -1) { - storeAppendPrintf(sentry, "\n\n"); - return; + storeAppendPrintf(sentry, "\n\n"); + return; } for (unsigned int index = 0; index < buckets.size(); ++index) { - storeAppendPrintf(sentry, "\t\tCurrent [Network %d]:", buckets.key_map[index]); - buckets.values[index].stats (sentry); - storeAppendPrintf(sentry, "\n"); + storeAppendPrintf(sentry, "\t\tCurrent [Network %d]:", buckets.key_map[index]); + buckets.values[index].stats (sentry); + storeAppendPrintf(sentry, "\n"); } if (!buckets.size()) - storeAppendPrintf(sentry, "\t\tCurrent [All networks]: Not used yet.\n"); + storeAppendPrintf(sentry, "\t\tCurrent [All networks]: Not used yet.\n"); storeAppendPrintf(sentry, "\n\n"); } @@ -877,9 +973,10 @@ void ClassCHostPool::update(int incr) { if (rate()->restore_bps == -1) - return; + return; + for (unsigned int i = 0; i< buckets.size(); ++i) - buckets.values[i].update (*rate(), incr); + buckets.values[i].update (*rate(), incr); } void @@ -895,6 +992,7 @@ ClassCHostPool::keyAllocated (unsigned char const key) const } unsigned char const + ClassCHostPool::makeHostKey (struct in_addr &src_addr) const { unsigned int host; @@ -903,30 +1001,36 @@ ClassCHostPool::makeHostKey (struct in_addr &src_addr) const } unsigned int const + ClassCHostPool::makeKey (struct in_addr &src_addr) const { unsigned int net; net = (ntohl(src_addr.s_addr) >> 8) & 0xff; return net; } + DelayIdComposite::Pointer + ClassCHostPool::id(struct in_addr &src_addr, AuthUserRequest *) { if (rate()->restore_bps == -1) - return new NullDelayId; + return new NullDelayId; unsigned int key = makeKey (src_addr); + unsigned char host = makeHostKey (src_addr); unsigned char hostIndex; + unsigned char netIndex; + if (keyAllocated (key)) - netIndex = buckets.findKeyIndex(key); + netIndex = buckets.findKeyIndex(key); else - netIndex = buckets.insert (key); + netIndex = buckets.insert (key); hostIndex = buckets.values[netIndex].hostPosition (*rate(), host); - + return new Id (this, netIndex, hostIndex); } @@ -951,8 +1055,7 @@ ClassCHostPool::Id::deleteSelf() const } ClassCHostPool::Id::Id (ClassCHostPool::Pointer aPool, unsigned char aNet, unsigned char aHost) : theClassCHost (aPool), theNet (aNet), theHost (aHost) -{ -} +{} int ClassCHostPool::Id::bytesWanted (int min, int max) const diff --git a/src/disk.cc b/src/disk.cc index 9be90b15e8..815f220b3b 100644 --- a/src/disk.cc +++ b/src/disk.cc @@ -1,6 +1,6 @@ /* - * $Id: disk.cc,v 1.163 2003/01/23 00:37:19 robertc Exp $ + * $Id: disk.cc,v 1.164 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 6 Disk I/O Routines * AUTHOR: Harvest Derived @@ -45,6 +45,7 @@ diskWriteIsComplete(int fd) { return fd_table[fd].disk.write_q ? 0 : 1; } + #endif void @@ -62,21 +63,28 @@ file_open(const char *path, int mode) { int fd; PROF_start(file_open); + if (FILE_MODE(mode) == O_WRONLY) - mode |= O_APPEND; + mode |= O_APPEND; + mode |= SQUID_NONBLOCK; + errno = 0; + fd = open(path, mode, 0644); + statCounter.syscalls.disk.opens++; + if (fd < 0) { - debug(50, 3) ("file_open: error opening file %s: %s\n", path, - xstrerror()); - fd = DISK_ERROR; + debug(50, 3) ("file_open: error opening file %s: %s\n", path, + xstrerror()); + fd = DISK_ERROR; } else { - debug(6, 5) ("file_open: FD %d\n", fd); - commSetCloseOnExec(fd); - fd_open(fd, FD_FILE, path); + debug(6, 5) ("file_open: FD %d\n", fd); + commSetCloseOnExec(fd); + fd_open(fd, FD_FILE, path); } + PROF_stop(file_open); return fd; } @@ -91,39 +99,59 @@ file_close(int fd) PROF_start(file_close); assert(fd >= 0); assert(F->flags.open); + if ((read_callback = F->read_handler)) { - F->read_handler = NULL; - read_callback(-1, F->read_data); + F->read_handler = NULL; + read_callback(-1, F->read_data); } + if (F->flags.write_daemon) { #if defined(_SQUID_MSWIN_) || defined(_SQUID_OS2_) || defined(_SQUID_CYGWIN_) - /* - * on some operating systems, you can not delete or rename - * open files, so we won't allow delayed close. - */ - while (!diskWriteIsComplete(fd)) - diskHandleWrite(fd, NULL); + /* + * on some operating systems, you can not delete or rename + * open files, so we won't allow delayed close. + */ + + while (!diskWriteIsComplete(fd)) + diskHandleWrite(fd, NULL); + #else - F->flags.close_request = 1; - debug(6, 2) ("file_close: FD %d, delaying close\n", fd); - PROF_stop(file_close); - return; + + F->flags.close_request = 1; + + debug(6, 2) ("file_close: FD %d, delaying close\n", fd); + + PROF_stop(file_close); + + return; + #endif + } + /* * Assert there is no write callback. Otherwise we might be * leaking write state data by closing the descriptor */ assert(F->write_handler == NULL); + F->flags.closing = 1; + #if CALL_FSYNC_BEFORE_CLOSE + fsync(fd); + #endif + close(fd); + debug(6, F->flags.close_request ? 2 : 5) - ("file_close: FD %d, really closing\n", fd); + ("file_close: FD %d, really closing\n", fd); + fd_close(fd); + statCounter.syscalls.disk.closes++; + PROF_stop(file_close); } @@ -138,6 +166,7 @@ file_close(int fd) * select() loop. --SLF */ static void + diskCombineWrites(struct _fde_disk *fdd) { int len = 0; @@ -148,31 +177,45 @@ diskCombineWrites(struct _fde_disk *fdd) * queue But only if we don't need to seek() in between them, ugh! * XXX This currently ignores any seeks (file_offset) */ - if (fdd->write_q != NULL && fdd->write_q->next != NULL) { - len = 0; - for (q = fdd->write_q; q != NULL; q = q->next) - len += q->len - q->buf_offset; - wq = (dwrite_q *)memAllocate(MEM_DWRITE_Q); - wq->buf = (char *)xmalloc(len); - wq->len = 0; - wq->buf_offset = 0; - wq->next = NULL; - wq->free_func = xfree; - do { - q = fdd->write_q; - len = q->len - q->buf_offset; - xmemcpy(wq->buf + wq->len, q->buf + q->buf_offset, len); - wq->len += len; - fdd->write_q = q->next; - if (q->free_func) - (q->free_func) (q->buf); - if (q) { - memFree(q, MEM_DWRITE_Q); - q = NULL; - } - } while (fdd->write_q != NULL); - fdd->write_q_tail = wq; - fdd->write_q = wq; + + if (fdd->write_q != NULL && fdd->write_q->next != NULL) + { + len = 0; + + for (q = fdd->write_q; q != NULL; q = q->next) + len += q->len - q->buf_offset; + + wq = (dwrite_q *)memAllocate(MEM_DWRITE_Q); + + wq->buf = (char *)xmalloc(len); + + wq->len = 0; + + wq->buf_offset = 0; + + wq->next = NULL; + + wq->free_func = xfree; + + do { + q = fdd->write_q; + len = q->len - q->buf_offset; + xmemcpy(wq->buf + wq->len, q->buf + q->buf_offset, len); + wq->len += len; + fdd->write_q = q->next; + + if (q->free_func) + (q->free_func) (q->buf); + + if (q) { + memFree(q, MEM_DWRITE_Q); + q = NULL; + } + } while (fdd->write_q != NULL); + + fdd->write_q_tail = wq; + + fdd->write_q = wq; } } @@ -182,110 +225,142 @@ diskHandleWrite(int fd, void *notused) { int len = 0; fde *F = &fd_table[fd]; + struct _fde_disk *fdd = &F->disk; dwrite_q *q = fdd->write_q; int status = DISK_OK; int do_close; + if (NULL == q) - return; + return; + PROF_start(diskHandleWrite); + debug(6, 3) ("diskHandleWrite: FD %d\n", fd); + F->flags.write_daemon = 0; + assert(fdd->write_q != NULL); + assert(fdd->write_q->len > fdd->write_q->buf_offset); + debug(6, 3) ("diskHandleWrite: FD %d writing %d bytes\n", - fd, (int) (fdd->write_q->len - fdd->write_q->buf_offset)); + fd, (int) (fdd->write_q->len - fdd->write_q->buf_offset)); + errno = 0; + if (fdd->write_q->file_offset != -1) - lseek(fd, fdd->write_q->file_offset, SEEK_SET); + lseek(fd, fdd->write_q->file_offset, SEEK_SET); + len = FD_WRITE_METHOD(fd, - fdd->write_q->buf + fdd->write_q->buf_offset, - fdd->write_q->len - fdd->write_q->buf_offset); + fdd->write_q->buf + fdd->write_q->buf_offset, + fdd->write_q->len - fdd->write_q->buf_offset); + debug(6, 3) ("diskHandleWrite: FD %d len = %d\n", fd, len); + statCounter.syscalls.disk.writes++; + fd_bytes(fd, len, FD_WRITE); + if (len < 0) { - if (!ignoreErrno(errno)) { - status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; - debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n", - fd, xstrerror()); - /* - * If there is no write callback, then this file is - * most likely something important like a log file, or - * an interprocess pipe. Its not a swapfile. We feel - * that a write failure on a log file is rather important, - * and Squid doesn't otherwise deal with this condition. - * So to get the administrators attention, we exit with - * a fatal message. - */ - if (fdd->wrt_handle == NULL) - fatal("Write failure -- check your disk space and cache.log"); - /* - * If there is a write failure, then we notify the - * upper layer via the callback, at the end of this - * function. Meanwhile, flush all pending buffers - * here. Let the upper layer decide how to handle the - * failure. This will prevent experiencing multiple, - * repeated write failures for the same FD because of - * the queued data. - */ - do { - fdd->write_q = q->next; - if (q->free_func) - (q->free_func) (q->buf); - if (q) { - memFree(q, MEM_DWRITE_Q); - q = NULL; - } - } while ((q = fdd->write_q)); - } - len = 0; + if (!ignoreErrno(errno)) { + status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; + debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n", + fd, xstrerror()); + /* + * If there is no write callback, then this file is + * most likely something important like a log file, or + * an interprocess pipe. Its not a swapfile. We feel + * that a write failure on a log file is rather important, + * and Squid doesn't otherwise deal with this condition. + * So to get the administrators attention, we exit with + * a fatal message. + */ + + if (fdd->wrt_handle == NULL) + fatal("Write failure -- check your disk space and cache.log"); + + /* + * If there is a write failure, then we notify the + * upper layer via the callback, at the end of this + * function. Meanwhile, flush all pending buffers + * here. Let the upper layer decide how to handle the + * failure. This will prevent experiencing multiple, + * repeated write failures for the same FD because of + * the queued data. + */ + do { + fdd->write_q = q->next; + + if (q->free_func) + (q->free_func) (q->buf); + + if (q) { + memFree(q, MEM_DWRITE_Q); + q = NULL; + } + } while ((q = fdd->write_q)); + } + + len = 0; } + if (q != NULL) { - /* q might become NULL from write failure above */ - q->buf_offset += len; - if (q->buf_offset > q->len) - debug(50, 1) ("diskHandleWriteComplete: q->buf_offset > q->len (%p,%d, %d, %d FD %d)\n", - q, (int) q->buf_offset, q->len, len, fd); - assert(q->buf_offset <= q->len); - if (q->buf_offset == q->len) { - /* complete write */ - fdd->write_q = q->next; - if (q->free_func) - (q->free_func) (q->buf); - if (q) { - memFree(q, MEM_DWRITE_Q); - q = NULL; - } - } + /* q might become NULL from write failure above */ + q->buf_offset += len; + + if (q->buf_offset > q->len) + debug(50, 1) ("diskHandleWriteComplete: q->buf_offset > q->len (%p,%d, %d, %d FD %d)\n", + q, (int) q->buf_offset, q->len, len, fd); + + assert(q->buf_offset <= q->len); + + if (q->buf_offset == q->len) { + /* complete write */ + fdd->write_q = q->next; + + if (q->free_func) + (q->free_func) (q->buf); + + if (q) { + memFree(q, MEM_DWRITE_Q); + q = NULL; + } + } } + if (fdd->write_q == NULL) { - /* no more data */ - fdd->write_q_tail = NULL; + /* no more data */ + fdd->write_q_tail = NULL; } else { - /* another block is queued */ - diskCombineWrites(fdd); - commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0); - F->flags.write_daemon = 1; + /* another block is queued */ + diskCombineWrites(fdd); + commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0); + F->flags.write_daemon = 1; } + do_close = F->flags.close_request; + if (fdd->wrt_handle) { - DWCB *callback = fdd->wrt_handle; - void *cbdata; - fdd->wrt_handle = NULL; - if (cbdataReferenceValidDone(fdd->wrt_handle_data, &cbdata)) { - callback(fd, status, len, cbdata); - /* - * NOTE, this callback can close the FD, so we must - * not touch 'F', 'fdd', etc. after this. - */ - PROF_stop(diskHandleWrite); - return; - /* XXX But what about close_request??? */ - } + DWCB *callback = fdd->wrt_handle; + void *cbdata; + fdd->wrt_handle = NULL; + + if (cbdataReferenceValidDone(fdd->wrt_handle_data, &cbdata)) { + callback(fd, status, len, cbdata); + /* + * NOTE, this callback can close the FD, so we must + * not touch 'F', 'fdd', etc. after this. + */ + PROF_stop(diskHandleWrite); + return; + /* XXX But what about close_request??? */ + } } + if (do_close) - file_close(fd); + file_close(fd); + PROF_stop(diskHandleWrite); } @@ -295,12 +370,12 @@ diskHandleWrite(int fd, void *notused) /* call a handle when writing is complete. */ void file_write(int fd, - off_t file_offset, - void const *ptr_to_buf, - int len, - DWCB * handle, - void *handle_data, - FREE * free_func) + off_t file_offset, + void const *ptr_to_buf, + int len, + DWCB * handle, + void *handle_data, + FREE * free_func) { dwrite_q *wq = NULL; fde *F = &fd_table[fd]; @@ -315,24 +390,28 @@ file_write(int fd, wq->buf_offset = 0; wq->next = NULL; wq->free_func = free_func; + if (!F->disk.wrt_handle_data) { - F->disk.wrt_handle = handle; - F->disk.wrt_handle_data = cbdataReference(handle_data); + F->disk.wrt_handle = handle; + F->disk.wrt_handle_data = cbdataReference(handle_data); } else { - /* Detect if there is multiple concurrent users of this fd.. we only support one callback */ - assert(F->disk.wrt_handle_data == handle_data && F->disk.wrt_handle == handle); + /* Detect if there is multiple concurrent users of this fd.. we only support one callback */ + assert(F->disk.wrt_handle_data == handle_data && F->disk.wrt_handle == handle); } + /* add to queue */ if (F->disk.write_q == NULL) { - /* empty queue */ - F->disk.write_q = F->disk.write_q_tail = wq; + /* empty queue */ + F->disk.write_q = F->disk.write_q_tail = wq; } else { - F->disk.write_q_tail->next = wq; - F->disk.write_q_tail = wq; + F->disk.write_q_tail->next = wq; + F->disk.write_q_tail = wq; } + if (!F->flags.write_daemon) { - diskHandleWrite(fd, NULL); + diskHandleWrite(fd, NULL); } + PROF_stop(file_write); } @@ -358,46 +437,59 @@ diskHandleRead(int fd, void *data) * FD < 0 indicates premature close; we just have to free * the state data. */ + if (fd < 0) { - memFree(ctrl_dat, MEM_DREAD_CTRL); - return; + memFree(ctrl_dat, MEM_DREAD_CTRL); + return; } + PROF_start(diskHandleRead); + if (F->disk.offset != ctrl_dat->offset) { - debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n", - fd, (int) ctrl_dat->offset); - lseek(fd, ctrl_dat->offset, SEEK_SET); /* XXX ignore return? */ - statCounter.syscalls.disk.seeks++; - F->disk.offset = ctrl_dat->offset; + debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n", + fd, (int) ctrl_dat->offset); + lseek(fd, ctrl_dat->offset, SEEK_SET); /* XXX ignore return? */ + statCounter.syscalls.disk.seeks++; + F->disk.offset = ctrl_dat->offset; } + errno = 0; len = FD_READ_METHOD(fd, ctrl_dat->buf, ctrl_dat->req_len); + if (len > 0) - F->disk.offset += len; + F->disk.offset += len; + statCounter.syscalls.disk.reads++; + fd_bytes(fd, len, FD_READ); + if (len < 0) { - if (ignoreErrno(errno)) { - commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); - PROF_stop(diskHandleRead); - return; - } - debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror()); - len = 0; - rc = DISK_ERROR; + if (ignoreErrno(errno)) { + commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); + PROF_stop(diskHandleRead); + return; + } + + debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror()); + len = 0; + rc = DISK_ERROR; } else if (len == 0) { - rc = DISK_EOF; + rc = DISK_EOF; } + if (cbdataReferenceValid(ctrl_dat->client_data)) - ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data); + ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data); + cbdataReferenceDone(ctrl_dat->client_data); + memFree(ctrl_dat, MEM_DREAD_CTRL); + PROF_stop(diskHandleRead); } /* start read operation */ -/* buffer must be allocated from the caller. +/* buffer must be allocated from the caller. * It must have at least req_len space in there. * call handler when a reading is complete. */ void diff --git a/src/dns.cc b/src/dns.cc index 30b92b91da..a6ba23cba4 100644 --- a/src/dns.cc +++ b/src/dns.cc @@ -1,6 +1,6 @@ /* - * $Id: dns.cc,v 1.90 2003/01/23 00:37:19 robertc Exp $ + * $Id: dns.cc,v 1.91 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 34 Dnsserver interface * AUTHOR: Harvest Derived @@ -50,26 +50,36 @@ dnsInit(void) { static int init = 0; wordlist *w; + if (!Config.Program.dnsserver) - return; + return; + if (dnsservers == NULL) - dnsservers = helperCreate("dnsserver"); + dnsservers = helperCreate("dnsserver"); + dnsservers->n_to_start = Config.dnsChildren; + dnsservers->ipc_type = IPC_STREAM; + assert(dnsservers->cmdline == NULL); + wordlistAdd(&dnsservers->cmdline, Config.Program.dnsserver); + if (Config.onoff.res_defnames) - wordlistAdd(&dnsservers->cmdline, "-D"); + wordlistAdd(&dnsservers->cmdline, "-D"); + for (w = Config.dns_nameservers; w != NULL; w = w->next) { - wordlistAdd(&dnsservers->cmdline, "-s"); - wordlistAdd(&dnsservers->cmdline, w->key); + wordlistAdd(&dnsservers->cmdline, "-s"); + wordlistAdd(&dnsservers->cmdline, w->key); } + helperOpenServers(dnsservers); + if (!init) { - cachemgrRegister("dns", - "Dnsserver Statistics", - dnsStats, 0, 1); - init = 1; + cachemgrRegister("dns", + "Dnsserver Statistics", + dnsStats, 0, 1); + init = 1; } } @@ -77,12 +87,17 @@ void dnsShutdown(void) { if (!dnsservers) - return; + return; + helperShutdown(dnsservers); + wordlistDestroy(&dnsservers->cmdline); + if (!shutting_down) - return; + return; + helperFree(dnsservers); + dnsservers = NULL; } @@ -92,15 +107,21 @@ dnsSubmit(const char *lookup, HLPCB * callback, void *data) char buf[256]; static time_t first_warn = 0; snprintf(buf, 256, "%s\n", lookup); + if (dnsservers->stats.queue_size >= dnsservers->n_running * 2) { - if (first_warn == 0) - first_warn = squid_curtime; - if (squid_curtime - first_warn > 3 * 60) - fatal("DNS servers not responding for 3 minutes"); - debug(34, 1) ("dnsSubmit: queue overload, rejecting %s\n", lookup); - callback(data, "$fail Temporary network problem, please retry later"); - return; + if (first_warn == 0) + first_warn = squid_curtime; + + if (squid_curtime - first_warn > 3 * 60) + fatal("DNS servers not responding for 3 minutes"); + + debug(34, 1) ("dnsSubmit: queue overload, rejecting %s\n", lookup); + + callback(data, "$fail Temporary network problem, please retry later"); + + return; } + first_warn = 0; helperSubmit(dnsservers, buf, callback, data); } @@ -116,26 +137,33 @@ snmp_netDnsFn(variable_list * Var, snint * ErrP) debug(49, 5) ("snmp_netDnsFn: Processing request:\n", Var->name[LEN_SQ_NET + 1]); snmpDebugOid(5, Var->name, Var->name_length); *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_NET + 1]) { + case DNS_REQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - dnsservers->stats.requests, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + dnsservers->stats.requests, + SMI_COUNTER32); + break; + case DNS_REP: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - dnsservers->stats.replies, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + dnsservers->stats.replies, + SMI_COUNTER32); + break; + case DNS_SERVERS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - dnsservers->n_running, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + dnsservers->n_running, + SMI_COUNTER32); + break; + default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; + *ErrP = SNMP_ERR_NOSUCHNAME; + break; } + return Answer; } + #endif /*SQUID_SNMP */ diff --git a/src/dns_internal.cc b/src/dns_internal.cc index 8643ced7c8..3101f7b083 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -1,6 +1,6 @@ /* - * $Id: dns_internal.cc,v 1.52 2003/01/23 00:37:20 robertc Exp $ + * $Id: dns_internal.cc,v 1.53 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 78 DNS lookups; interacts with lib/rfc1035.c * AUTHOR: Duane Wessels @@ -53,14 +53,18 @@ static int RcodeMatrix[MAX_RCODE][MAX_ATTEMPT]; typedef struct _idns_query idns_query; + typedef struct _ns ns; -struct _idns_query { +struct _idns_query +{ char buf[512]; size_t sz; unsigned short id; int nsends; + struct timeval start_t; + struct timeval sent_t; dlink_node lru; IDNSCB *callback; @@ -68,7 +72,9 @@ struct _idns_query { int attempt; }; -struct _ns { +struct _ns +{ + struct sockaddr_in S; int nqueries; int nreplies; @@ -90,6 +96,7 @@ static void idnsParseResolvConf(void); static void idnsParseWIN32Registry(void); #endif static void idnsSendQuery(idns_query * q); + static int idnsFromKnownNameserver(struct sockaddr_in *from); static idns_query *idnsFindQuery(unsigned short id); static void idnsGrokReply(const char *buf, size_t sz); @@ -101,35 +108,44 @@ static void idnsRcodeCount(int, int); static void idnsAddNameserver(const char *buf) { + struct in_addr A; + if (!safe_inet_addr(buf, &A)) { - debug(78, 0) ("WARNING: rejecting '%s' as a name server, because it is not a numeric IP address\n", buf); - return; + debug(78, 0) ("WARNING: rejecting '%s' as a name server, because it is not a numeric IP address\n", buf); + return; } + if (A.s_addr == 0) { - debug(78, 0) ("WARNING: Squid does not accept 0.0.0.0 in DNS server specifications.\n"); - debug(78, 0) ("Will be using 127.0.0.1 instead, assuming you meant that DNS is running on the same machine\n"); - safe_inet_addr("127.0.0.1", &A); + debug(78, 0) ("WARNING: Squid does not accept 0.0.0.0 in DNS server specifications.\n"); + debug(78, 0) ("Will be using 127.0.0.1 instead, assuming you meant that DNS is running on the same machine\n"); + safe_inet_addr("127.0.0.1", &A); } + if (nns == nns_alloc) { - int oldalloc = nns_alloc; - ns *oldptr = nameservers; - if (nns_alloc == 0) - nns_alloc = 2; - else - nns_alloc <<= 1; - nameservers = (ns *)xcalloc(nns_alloc, sizeof(*nameservers)); - if (oldptr && oldalloc) - xmemcpy(nameservers, oldptr, oldalloc * sizeof(*nameservers)); - if (oldptr) - safe_free(oldptr); + int oldalloc = nns_alloc; + ns *oldptr = nameservers; + + if (nns_alloc == 0) + nns_alloc = 2; + else + nns_alloc <<= 1; + + nameservers = (ns *)xcalloc(nns_alloc, sizeof(*nameservers)); + + if (oldptr && oldalloc) + xmemcpy(nameservers, oldptr, oldalloc * sizeof(*nameservers)); + + if (oldptr) + safe_free(oldptr); } + assert(nns < nns_alloc); nameservers[nns].S.sin_family = AF_INET; nameservers[nns].S.sin_port = htons(DOMAIN_PORT); nameservers[nns].S.sin_addr.s_addr = A.s_addr; debug(78, 3) ("idnsAddNameserver: Added nameserver #%d: %s\n", - nns, inet_ntoa(nameservers[nns].S.sin_addr)); + nns, inet_ntoa(nameservers[nns].S.sin_addr)); nns++; } @@ -144,9 +160,10 @@ static void idnsParseNameservers(void) { wordlist *w; + for (w = Config.dns_nameservers; w; w = w->next) { - debug(78, 1) ("Adding nameserver %s from squid.conf\n", w->key); - idnsAddNameserver(w->key); + debug(78, 1) ("Adding nameserver %s from squid.conf\n", w->key); + idnsAddNameserver(w->key); } } @@ -157,25 +174,36 @@ idnsParseResolvConf(void) char buf[512]; char *t; fp = fopen(_PATH_RESOLV_CONF, "r"); + if (fp == NULL) { - debug(78, 1) ("%s: %s\n", _PATH_RESOLV_CONF, xstrerror()); - return; + debug(78, 1) ("%s: %s\n", _PATH_RESOLV_CONF, xstrerror()); + return; } + #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) setmode(fileno(fp), O_TEXT); + #endif + while (fgets(buf, 512, fp)) { - t = strtok(buf, w_space); - if (NULL == t) - continue; - if (strcasecmp(t, "nameserver")) - continue; - t = strtok(NULL, w_space); - if (t == NULL) - continue; - debug(78, 1) ("Adding nameserver %s from %s\n", t, _PATH_RESOLV_CONF); - idnsAddNameserver(t); + t = strtok(buf, w_space); + + if (NULL == t) + continue; + + if (strcasecmp(t, "nameserver")) + continue; + + t = strtok(NULL, w_space); + + if (t == NULL) + continue; + + debug(78, 1) ("Adding nameserver %s from %s\n", t, _PATH_RESOLV_CONF); + + idnsAddNameserver(t); } + fclose(fp); } @@ -188,140 +216,173 @@ idnsParseWIN32Registry(void) HKEY hndKey, hndKey2; idnsFreeNameservers(); + switch (WIN32_OS_version) { + case _WIN_OS_WINNT: - /* get nameservers from the Windows NT registry */ - if (RegOpenKey(HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", - &hndKey) == ERROR_SUCCESS) { - DWORD Type = 0; - DWORD Size = 0; - LONG Result; - Result = - RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, NULL, - &Size); - if (Result == ERROR_SUCCESS && Size) { - t = (unsigned char *) xmalloc(Size); - RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, t, - &Size); - token = strtok((char *) t, ", "); - while (token) { - idnsAddNameserver(token); - debug(78, 1) ("Adding DHCP nameserver %s from Registry\n", - token); - token = strtok(NULL, ", "); - } - } - Result = - RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size); - if (Result == ERROR_SUCCESS && Size) { - t = (unsigned char *) xmalloc(Size); - RegQueryValueEx(hndKey, "NameServer", NULL, &Type, t, &Size); - token = strtok((char *) t, ", "); - while (token) { - debug(78, 1) ("Adding nameserver %s from Registry\n", - token); - idnsAddNameserver(token); - token = strtok(NULL, ", "); - } - } - RegCloseKey(hndKey); - } - break; + /* get nameservers from the Windows NT registry */ + + if (RegOpenKey(HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + &hndKey) == ERROR_SUCCESS) { + DWORD Type = 0; + DWORD Size = 0; + LONG Result; + Result = + RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, NULL, + &Size); + + if (Result == ERROR_SUCCESS && Size) { + t = (unsigned char *) xmalloc(Size); + RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, t, + &Size); + token = strtok((char *) t, ", "); + + while (token) { + idnsAddNameserver(token); + debug(78, 1) ("Adding DHCP nameserver %s from Registry\n", + token); + token = strtok(NULL, ", "); + } + } + + Result = + RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size); + + if (Result == ERROR_SUCCESS && Size) { + t = (unsigned char *) xmalloc(Size); + RegQueryValueEx(hndKey, "NameServer", NULL, &Type, t, &Size); + token = strtok((char *) t, ", "); + + while (token) { + debug(78, 1) ("Adding nameserver %s from Registry\n", + token); + idnsAddNameserver(token); + token = strtok(NULL, ", "); + } + } + + RegCloseKey(hndKey); + } + + break; + case _WIN_OS_WIN2K: + case _WIN_OS_WINXP: + case _WIN_OS_WINNET: - /* get nameservers from the Windows 2000 registry */ - /* search all interfaces for DNS server addresses */ - if (RegOpenKey(HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", - &hndKey) == ERROR_SUCCESS) { - int i; - char keyname[255]; - - for (i = 0; i < 10; i++) { - if (RegEnumKey(hndKey, i, (char *) &keyname, - 255) == ERROR_SUCCESS) { - char newkeyname[255]; - strcpy(newkeyname, - "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"); - strcat(newkeyname, keyname); - if (RegOpenKey(HKEY_LOCAL_MACHINE, newkeyname, - &hndKey2) == ERROR_SUCCESS) { - DWORD Type = 0; - DWORD Size = 0; - LONG Result; - Result = - RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, - &Type, NULL, &Size); - if (Result == ERROR_SUCCESS && Size) { - t = (unsigned char *) xmalloc(Size); - RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, - &Type, t, &Size); - token = strtok((char *) t, ", "); - while (token) { - debug(78, 1) - ("Adding DHCP nameserver %s from Registry\n", - token); - idnsAddNameserver(token); - token = strtok(NULL, ", "); - } - } - Result = - RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, - NULL, &Size); - if (Result == ERROR_SUCCESS && Size) { - t = (unsigned char *) xmalloc(Size); - RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, - t, &Size); - token = strtok((char *) t, ", "); - while (token) { - debug(78, - 1) ("Adding nameserver %s from Registry\n", - token); - idnsAddNameserver(token); - token = strtok(NULL, ", "); - } - } - RegCloseKey(hndKey2); - } - } - } - RegCloseKey(hndKey); - } - break; + /* get nameservers from the Windows 2000 registry */ + /* search all interfaces for DNS server addresses */ + + if (RegOpenKey(HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", + &hndKey) == ERROR_SUCCESS) { + int i; + char keyname[255]; + + for (i = 0; i < 10; i++) { + if (RegEnumKey(hndKey, i, (char *) &keyname, + 255) == ERROR_SUCCESS) { + char newkeyname[255]; + strcpy(newkeyname, + "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"); + strcat(newkeyname, keyname); + + if (RegOpenKey(HKEY_LOCAL_MACHINE, newkeyname, + &hndKey2) == ERROR_SUCCESS) { + DWORD Type = 0; + DWORD Size = 0; + LONG Result; + Result = + RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, + &Type, NULL, &Size); + + if (Result == ERROR_SUCCESS && Size) { + t = (unsigned char *) xmalloc(Size); + RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, + &Type, t, &Size); + token = strtok((char *) t, ", "); + + while (token) { + debug(78, 1) + ("Adding DHCP nameserver %s from Registry\n", + token); + idnsAddNameserver(token); + token = strtok(NULL, ", "); + } + } + + Result = + RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, + NULL, &Size); + + if (Result == ERROR_SUCCESS && Size) { + t = (unsigned char *) xmalloc(Size); + RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, + t, &Size); + token = strtok((char *) t, ", "); + + while (token) { + debug(78, + 1) ("Adding nameserver %s from Registry\n", + token); + idnsAddNameserver(token); + token = strtok(NULL, ", "); + } + } + + RegCloseKey(hndKey2); + } + } + } + + RegCloseKey(hndKey); + } + + break; + case _WIN_OS_WIN95: + case _WIN_OS_WIN98: + case _WIN_OS_WINME: - /* get nameservers from the Windows 9X registry */ - if (RegOpenKey(HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", - &hndKey) == ERROR_SUCCESS) { - DWORD Type = 0; - DWORD Size = 0; - LONG Result; - Result = - RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size); - if (Result == ERROR_SUCCESS && Size) { - t = (unsigned char *) xmalloc(Size); - RegQueryValueEx(hndKey, "NameServer", NULL, &Type, t, &Size); - token = strtok((char *) t, ", "); - while (token) { - debug(78, 1) ("Adding nameserver %s from Registry\n", - token); - idnsAddNameserver(token); - token = strtok(NULL, ", "); - } - } - RegCloseKey(hndKey); - } - break; + /* get nameservers from the Windows 9X registry */ + + if (RegOpenKey(HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", + &hndKey) == ERROR_SUCCESS) { + DWORD Type = 0; + DWORD Size = 0; + LONG Result; + Result = + RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size); + + if (Result == ERROR_SUCCESS && Size) { + t = (unsigned char *) xmalloc(Size); + RegQueryValueEx(hndKey, "NameServer", NULL, &Type, t, &Size); + token = strtok((char *) t, ", "); + + while (token) { + debug(78, 1) ("Adding nameserver %s from Registry\n", + token); + idnsAddNameserver(token); + token = strtok(NULL, ", "); + } + } + + RegCloseKey(hndKey); + } + + break; + default: - debug(78, 1) - ("Failed to read nameserver from Registry: Unknown System Type.\n"); - return; + debug(78, 1) + ("Failed to read nameserver from Registry: Unknown System Type.\n"); + return; } } + #endif static void @@ -336,32 +397,41 @@ idnsStats(StoreEntry * sentry) storeAppendPrintf(sentry, " DELAY SINCE\n"); storeAppendPrintf(sentry, " ID SIZE SENDS FIRST SEND LAST SEND\n"); storeAppendPrintf(sentry, "------ ---- ----- ---------- ---------\n"); + for (n = lru_list.head; n; n = n->next) { - q = (idns_query *)n->data; - storeAppendPrintf(sentry, "%#06x %4d %5d %10.3f %9.3f\n", - (int) q->id, (int) q->sz, q->nsends, - tvSubDsec(q->start_t, current_time), - tvSubDsec(q->sent_t, current_time)); + q = (idns_query *)n->data; + storeAppendPrintf(sentry, "%#06x %4d %5d %10.3f %9.3f\n", + (int) q->id, (int) q->sz, q->nsends, + tvSubDsec(q->start_t, current_time), + tvSubDsec(q->sent_t, current_time)); } + storeAppendPrintf(sentry, "\nNameservers:\n"); storeAppendPrintf(sentry, "IP ADDRESS # QUERIES # REPLIES\n"); storeAppendPrintf(sentry, "--------------- --------- ---------\n"); + for (i = 0; i < nns; i++) { - storeAppendPrintf(sentry, "%-15s %9d %9d\n", - inet_ntoa(nameservers[i].S.sin_addr), - nameservers[i].nqueries, - nameservers[i].nreplies); + storeAppendPrintf(sentry, "%-15s %9d %9d\n", + inet_ntoa(nameservers[i].S.sin_addr), + nameservers[i].nqueries, + nameservers[i].nreplies); } + storeAppendPrintf(sentry, "\nRcode Matrix:\n"); storeAppendPrintf(sentry, "RCODE"); + for (i = 0; i < MAX_ATTEMPT; i++) - storeAppendPrintf(sentry, " ATTEMPT%d", i + 1); + storeAppendPrintf(sentry, " ATTEMPT%d", i + 1); + storeAppendPrintf(sentry, "\n"); + for (j = 0; j < MAX_RCODE; j++) { - storeAppendPrintf(sentry, "%5d", j); - for (i = 0; i < MAX_ATTEMPT; i++) - storeAppendPrintf(sentry, " %8d", RcodeMatrix[j][i]); - storeAppendPrintf(sentry, "\n"); + storeAppendPrintf(sentry, "%5d", j); + + for (i = 0; i < MAX_ATTEMPT; i++) + storeAppendPrintf(sentry, " %8d", RcodeMatrix[j][i]); + + storeAppendPrintf(sentry, "\n"); } } @@ -369,10 +439,13 @@ static void idnsTickleQueue(void) { if (event_queued) - return; + return; + if (NULL == lru_list.tail) - return; + return; + eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, 1.0, 1); + event_queued = 1; } @@ -381,48 +454,65 @@ idnsSendQuery(idns_query * q) { int x; int ns; + if (DnsSocket < 0) { - debug(78, 1) ("idnsSendQuery: Can't send query, no DNS socket!\n"); - return; + debug(78, 1) ("idnsSendQuery: Can't send query, no DNS socket!\n"); + return; } + /* XXX Select nameserver */ assert(nns > 0); + assert(q->lru.next == NULL); + assert(q->lru.prev == NULL); - try_again: + +try_again: ns = q->nsends % nns; + x = comm_udp_sendto(DnsSocket, - &nameservers[ns].S, - sizeof(nameservers[ns].S), - q->buf, - q->sz); + &nameservers[ns].S, + sizeof(nameservers[ns].S), + q->buf, + q->sz); + q->nsends++; + q->sent_t = current_time; + if (x < 0) { - debug(50, 1) ("idnsSendQuery: FD %d: sendto: %s\n", - DnsSocket, xstrerror()); - if (q->nsends % nns != 0) - goto try_again; + debug(50, 1) ("idnsSendQuery: FD %d: sendto: %s\n", + DnsSocket, xstrerror()); + + if (q->nsends % nns != 0) + goto try_again; } else { - fd_bytes(DnsSocket, x, FD_WRITE); - commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0); + fd_bytes(DnsSocket, x, FD_WRITE); + commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0); } + nameservers[ns].nqueries++; dlinkAdd(q, &q->lru, &lru_list); idnsTickleQueue(); } static int + idnsFromKnownNameserver(struct sockaddr_in *from) { int i; - for (i = 0; i < nns; i++) { - if (nameservers[i].S.sin_addr.s_addr != from->sin_addr.s_addr) - continue; - if (nameservers[i].S.sin_port != from->sin_port) - continue; - return i; + + for (i = 0; i < nns; i++) + { + if (nameservers[i].S.sin_addr.s_addr != from->sin_addr.s_addr) + continue; + + if (nameservers[i].S.sin_port != from->sin_port) + continue; + + return i; } + return -1; } @@ -431,11 +521,14 @@ idnsFindQuery(unsigned short id) { dlink_node *n; idns_query *q; + for (n = lru_list.tail; n; n = n->prev) { - q = (idns_query*)n->data; - if (q->id == id) - return q; + q = (idns_query*)n->data; + + if (q->id == id) + return q; } + return NULL; } @@ -449,43 +542,53 @@ idnsGrokReply(const char *buf, size_t sz) IDNSCB *callback; void *cbdata; n = rfc1035AnswersUnpack(buf, - sz, - &answers, - &rid); + sz, + &answers, + &rid); debug(78, 3) ("idnsGrokReply: ID %#hx, %d answers\n", rid, n); + if (rid == 0xFFFF) { - debug(78, 1) ("idnsGrokReply: Unknown error\n"); - /* XXX leak answers? */ - return; + debug(78, 1) ("idnsGrokReply: Unknown error\n"); + /* XXX leak answers? */ + return; } + q = idnsFindQuery(rid); + if (q == NULL) { - debug(78, 3) ("idnsGrokReply: Late response\n"); - rfc1035RRDestroy(answers, n); - return; + debug(78, 3) ("idnsGrokReply: Late response\n"); + rfc1035RRDestroy(answers, n); + return; } + dlinkDelete(&q->lru, &lru_list); idnsRcodeCount(n, q->attempt); + if (n < 0) { - debug(78, 3) ("idnsGrokReply: error %d\n", rfc1035_errno); - if (-2 == n && ++q->attempt < MAX_ATTEMPT) { - /* - * RCODE 2 is "Server failure - The name server was - * unable to process this query due to a problem with - * the name server." - */ - assert(NULL == answers); - q->start_t = current_time; - q->id = rfc1035RetryQuery(q->buf); - idnsSendQuery(q); - return; - } + debug(78, 3) ("idnsGrokReply: error %d\n", rfc1035_errno); + + if (-2 == n && ++q->attempt < MAX_ATTEMPT) { + /* + * RCODE 2 is "Server failure - The name server was + * unable to process this query due to a problem with + * the name server." + */ + assert(NULL == answers); + q->start_t = current_time; + q->id = rfc1035RetryQuery(q->buf); + idnsSendQuery(q); + return; + } } + callback = q->callback; q->callback = NULL; + if (cbdataReferenceValidDone(q->callback_data, &cbdata)) - callback(cbdata, answers, n); + callback(cbdata, answers, n); + rfc1035RRDestroy(answers, n); + memFree(q, MEM_IDNS_QUERY); } @@ -494,71 +597,88 @@ idnsRead(int fd, void *data) { int *N = &incoming_sockets_accepted; ssize_t len; + struct sockaddr_in from; socklen_t from_len; int max = INCOMING_DNS_MAX; static char rbuf[SQUID_UDP_SO_RCVBUF]; int ns; + while (max--) { - from_len = sizeof(from); - memset(&from, '\0', from_len); - len = comm_udp_recvfrom(fd, rbuf, 512, 0, (struct sockaddr *) &from, &from_len); - if (len == 0) - break; - if (len < 0) { - if (ignoreErrno(errno)) - break; + from_len = sizeof(from); + memset(&from, '\0', from_len); + + len = comm_udp_recvfrom(fd, rbuf, 512, 0, (struct sockaddr *) &from, &from_len); + + if (len == 0) + break; + + if (len < 0) { + if (ignoreErrno(errno)) + break; + #ifdef _SQUID_LINUX_ - /* Some Linux systems seem to set the FD for reading and then - * return ECONNREFUSED when sendto() fails and generates an ICMP - * port unreachable message. */ - /* or maybe an EHOSTUNREACH "No route to host" message */ - if (errno != ECONNREFUSED && errno != EHOSTUNREACH) + /* Some Linux systems seem to set the FD for reading and then + * return ECONNREFUSED when sendto() fails and generates an ICMP + * port unreachable message. */ + /* or maybe an EHOSTUNREACH "No route to host" message */ + if (errno != ECONNREFUSED && errno != EHOSTUNREACH) #endif - debug(50, 1) ("idnsRead: FD %d recvfrom: %s\n", - fd, xstrerror()); - break; - } - fd_bytes(DnsSocket, len, FD_READ); - assert(N); - (*N)++; - debug(78, 3) ("idnsRead: FD %d: received %d bytes from %s.\n", - fd, - (int) len, - inet_ntoa(from.sin_addr)); - ns = idnsFromKnownNameserver(&from); - if (ns >= 0) { - nameservers[ns].nreplies++; - } else if (Config.onoff.ignore_unknown_nameservers) { - static time_t last_warning = 0; - if (squid_curtime - last_warning > 60) { - debug(78, 1) ("WARNING: Reply from unknown nameserver [%s]\n", - inet_ntoa(from.sin_addr)); - last_warning = squid_curtime; - } - continue; - } - if (len > 512) { - /* - * Check for non-conforming replies. RFC 1035 says - * DNS/UDP messages must be 512 octets or less. If we - * get one that is too large, we generate a warning - * and then pretend that we only got 512 octets. This - * should prevent the rfc1035.c code from reading past - * the end of our buffer. - */ - static int other_large_pkts = 0; - int x; - x = (ns < 0) ? ++other_large_pkts : ++nameservers[ns].large_pkts; - if (isPowTen(x)) - debug(78, 1) ("WARNING: Got %d large DNS replies from %s\n", - x, inet_ntoa(from.sin_addr)); - len = 512; - } - idnsGrokReply(rbuf, len); + + debug(50, 1) ("idnsRead: FD %d recvfrom: %s\n", + fd, xstrerror()); + + break; + } + + fd_bytes(DnsSocket, len, FD_READ); + assert(N); + (*N)++; + debug(78, 3) ("idnsRead: FD %d: received %d bytes from %s.\n", + fd, + (int) len, + inet_ntoa(from.sin_addr)); + ns = idnsFromKnownNameserver(&from); + + if (ns >= 0) { + nameservers[ns].nreplies++; + } else if (Config.onoff.ignore_unknown_nameservers) { + static time_t last_warning = 0; + + if (squid_curtime - last_warning > 60) { + debug(78, 1) ("WARNING: Reply from unknown nameserver [%s]\n", + inet_ntoa(from.sin_addr)); + last_warning = squid_curtime; + } + + continue; + } + + if (len > 512) { + /* + * Check for non-conforming replies. RFC 1035 says + * DNS/UDP messages must be 512 octets or less. If we + * get one that is too large, we generate a warning + * and then pretend that we only got 512 octets. This + * should prevent the rfc1035.c code from reading past + * the end of our buffer. + */ + static int other_large_pkts = 0; + int x; + x = (ns < 0) ? ++other_large_pkts : ++nameservers[ns].large_pkts; + + if (isPowTen(x)) + debug(78, 1) ("WARNING: Got %d large DNS replies from %s\n", + x, inet_ntoa(from.sin_addr)); + + len = 512; + } + + idnsGrokReply(rbuf, len); } + if (lru_list.head) - commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0); + commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0); } static void @@ -568,32 +688,42 @@ idnsCheckQueue(void *unused) dlink_node *p = NULL; idns_query *q; event_queued = 0; + for (n = lru_list.tail; n; n = p) { - if (0 == nns) - /* name servers went away; reconfiguring or shutting down */ - break; - q = (idns_query *)n->data; - if (tvSubDsec(q->sent_t, current_time) < Config.Timeout.idns_retransmit * (1 << q->nsends % nns)) - break; - debug(78, 3) ("idnsCheckQueue: ID %#04x timeout\n", - q->id); - p = n->prev; - dlinkDelete(&q->lru, &lru_list); - if (tvSubDsec(q->start_t, current_time) < Config.Timeout.idns_query) { - idnsSendQuery(q); - } else { - IDNSCB *callback; - void *cbdata; - debug(78, 2) ("idnsCheckQueue: ID %x: giving up after %d tries and %5.1f seconds\n", - (int) q->id, q->nsends, - tvSubDsec(q->start_t, current_time)); - callback = q->callback; - q->callback = NULL; - if (cbdataReferenceValidDone(q->callback_data, &cbdata)) - callback(cbdata, NULL, 0); - memFree(q, MEM_IDNS_QUERY); - } + if (0 == nns) + /* name servers went away; reconfiguring or shutting down */ + break; + + q = (idns_query *)n->data; + + if (tvSubDsec(q->sent_t, current_time) < Config.Timeout.idns_retransmit * (1 << q->nsends % nns)) + break; + + debug(78, 3) ("idnsCheckQueue: ID %#04x timeout\n", + q->id); + + p = n->prev; + + dlinkDelete(&q->lru, &lru_list); + + if (tvSubDsec(q->start_t, current_time) < Config.Timeout.idns_query) { + idnsSendQuery(q); + } else { + IDNSCB *callback; + void *cbdata; + debug(78, 2) ("idnsCheckQueue: ID %x: giving up after %d tries and %5.1f seconds\n", + (int) q->id, q->nsends, + tvSubDsec(q->start_t, current_time)); + callback = q->callback; + q->callback = NULL; + + if (cbdataReferenceValidDone(q->callback_data, &cbdata)) + callback(cbdata, NULL, 0); + + memFree(q, MEM_IDNS_QUERY); + } } + idnsTickleQueue(); } @@ -604,12 +734,13 @@ static void idnsRcodeCount(int rcode, int attempt) { if (rcode > 0) - rcode = 0; + rcode = 0; else if (rcode < 0) - rcode = -rcode; + rcode = -rcode; + if (rcode < MAX_RCODE) - if (attempt < MAX_ATTEMPT) - RcodeMatrix[rcode][attempt]++; + if (attempt < MAX_ATTEMPT) + RcodeMatrix[rcode][attempt]++; } /* ====================================================================== */ @@ -618,54 +749,68 @@ void idnsInit(void) { static int init = 0; + if (DnsSocket < 0) { - int port; - struct in_addr addr; - if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) - addr = Config.Addrs.udp_outgoing; - else - addr = Config.Addrs.udp_incoming; - DnsSocket = comm_open(SOCK_DGRAM, - 0, - addr, - 0, - COMM_NONBLOCKING, - "DNS Socket"); - if (DnsSocket < 0) - fatal("Could not create a DNS socket"); - /* Ouch... we can't call functions using debug from a debug - * statement. Doing so messes up the internal Debug::level - */ - port = comm_local_port(DnsSocket); - debug(78, 1) ("DNS Socket created at %s, port %d, FD %d\n", - inet_ntoa(addr), - port, DnsSocket); + int port; + + struct in_addr addr; + + if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) + addr = Config.Addrs.udp_outgoing; + else + addr = Config.Addrs.udp_incoming; + + DnsSocket = comm_open(SOCK_DGRAM, + 0, + addr, + 0, + COMM_NONBLOCKING, + "DNS Socket"); + + if (DnsSocket < 0) + fatal("Could not create a DNS socket"); + + /* Ouch... we can't call functions using debug from a debug + * statement. Doing so messes up the internal Debug::level + */ + port = comm_local_port(DnsSocket); + + debug(78, 1) ("DNS Socket created at %s, port %d, FD %d\n", + inet_ntoa(addr), + port, DnsSocket); } + assert(0 == nns); idnsParseNameservers(); #ifndef _SQUID_MSWIN_ + if (0 == nns) - idnsParseResolvConf(); + idnsParseResolvConf(); + #endif #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) + if (0 == nns) - idnsParseWIN32Registry(); + idnsParseWIN32Registry(); + #endif + if (0 == nns) - fatal("Could not find any nameservers.\n" + fatal("Could not find any nameservers.\n" #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - " Please check your TCP-IP settings or /etc/resolv.conf file\n" + " Please check your TCP-IP settings or /etc/resolv.conf file\n" #else - " Please check your /etc/resolv.conf file\n" + " Please check your /etc/resolv.conf file\n" #endif - " or use the 'dns_nameservers' option in squid.conf."); + " or use the 'dns_nameservers' option in squid.conf."); + if (!init) { - memDataInit(MEM_IDNS_QUERY, "idns_query", sizeof(idns_query), 0); - cachemgrRegister("idns", - "Internal DNS Statistics", - idnsStats, 0, 1); - memset(RcodeMatrix, '\0', sizeof(RcodeMatrix)); - init++; + memDataInit(MEM_IDNS_QUERY, "idns_query", sizeof(idns_query), 0); + cachemgrRegister("idns", + "Internal DNS Statistics", + idnsStats, 0, 1); + memset(RcodeMatrix, '\0', sizeof(RcodeMatrix)); + init++; } } @@ -673,9 +818,12 @@ void idnsShutdown(void) { if (DnsSocket < 0) - return; + return; + comm_close(DnsSocket); + DnsSocket = -1; + idnsFreeNameservers(); } @@ -685,14 +833,16 @@ idnsALookup(const char *name, IDNSCB * callback, void *data) idns_query *q = (idns_query *)memAllocate(MEM_IDNS_QUERY); q->sz = sizeof(q->buf); q->id = rfc1035BuildAQuery(name, q->buf, &q->sz); + if (0 == q->id) { - /* problem with query data -- query not sent */ - callback(data, NULL, 0); - memFree(q, MEM_IDNS_QUERY); - return; + /* problem with query data -- query not sent */ + callback(data, NULL, 0); + memFree(q, MEM_IDNS_QUERY); + return; } + debug(78, 3) ("idnsALookup: buf is %d bytes for %s, id = %#hx\n", - (int) q->sz, name, q->id); + (int) q->sz, name, q->id); q->callback = callback; q->callback_data = cbdataReference(data); q->start_t = current_time; @@ -700,13 +850,14 @@ idnsALookup(const char *name, IDNSCB * callback, void *data) } void + idnsPTRLookup(const struct in_addr addr, IDNSCB * callback, void *data) { idns_query *q = (idns_query *)memAllocate(MEM_IDNS_QUERY); q->sz = sizeof(q->buf); q->id = rfc1035BuildPTRQuery(addr, q->buf, &q->sz); debug(78, 3) ("idnsPTRLookup: buf is %d bytes for %s, id = %#hx\n", - (int) q->sz, inet_ntoa(addr), q->id); + (int) q->sz, inet_ntoa(addr), q->id); q->callback = callback; q->callback_data = cbdataReference(data); q->start_t = current_time; @@ -725,30 +876,44 @@ snmp_netIdnsFn(variable_list * Var, snint * ErrP) debug(49, 5) ("snmp_netDnsFn: Processing request: \n"); snmpDebugOid(5, Var->name, Var->name_length); *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_NET + 1]) { + case DNS_REQ: - for (i = 0; i < nns; i++) - n += nameservers[i].nqueries; - Answer = snmp_var_new_integer(Var->name, Var->name_length, - n, - SMI_COUNTER32); - break; + + for (i = 0; i < nns; i++) + n += nameservers[i].nqueries; + + Answer = snmp_var_new_integer(Var->name, Var->name_length, + n, + SMI_COUNTER32); + + break; + case DNS_REP: - for (i = 0; i < nns; i++) - n += nameservers[i].nreplies; - Answer = snmp_var_new_integer(Var->name, Var->name_length, - n, - SMI_COUNTER32); - break; + for (i = 0; i < nns; i++) + n += nameservers[i].nreplies; + + Answer = snmp_var_new_integer(Var->name, Var->name_length, + n, + SMI_COUNTER32); + + break; + case DNS_SERVERS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - 0, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + 0, + SMI_COUNTER32); + + break; + default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; + *ErrP = SNMP_ERR_NOSUCHNAME; + + break; } + return Answer; } + #endif /*SQUID_SNMP */ diff --git a/src/dnsserver.cc b/src/dnsserver.cc index c353d2ef7a..c7919790c9 100644 --- a/src/dnsserver.cc +++ b/src/dnsserver.cc @@ -1,6 +1,6 @@ /* - * $Id: dnsserver.cc,v 1.63 2003/02/04 21:57:15 robertc Exp $ + * $Id: dnsserver.cc,v 1.64 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 0 DNS Resolver * AUTHOR: Harvest Derived @@ -155,6 +155,7 @@ extern int _dns_ttl_; /* this is a really *dirty* hack - bne */ * Workaround bug in gethostbyname which sets h_errno wrong * WARNING: This hack queries only the resolver and not NetInfo or YP */ + struct hostent *_res_gethostbyname(char *name); #define gethostbyname _res_gethostbyname #endif /* _SQUID_NEXT_ */ @@ -162,8 +163,11 @@ struct hostent *_res_gethostbyname(char *name); static struct in_addr no_addr; #ifdef _SQUID_OS2_ + struct state _res = -{0}; /* it's not in any of the libraries */ + {0} + + ; /* it's not in any of the libraries */ #endif /* error messages from gethostbyname() */ @@ -171,15 +175,15 @@ static char * my_h_msgs(int x) { if (x == HOST_NOT_FOUND) - return "Host not found (authoritative)"; + return "Host not found (authoritative)"; else if (x == TRY_AGAIN) - return "Host not found (non-authoritative)"; + return "Host not found (non-authoritative)"; else if (x == NO_RECOVERY) - return "Non recoverable errors"; + return "Non recoverable errors"; else if (x == NO_DATA || x == NO_ADDRESS) - return "Valid name, no data record of requested type"; + return "Valid name, no data record of requested type"; else - return "Unknown DNS problem"; + return "Unknown DNS problem"; } #define REQ_SZ 512 @@ -187,61 +191,80 @@ my_h_msgs(int x) static void lookup(const char *buf) { + const struct hostent *result = NULL; int reverse = 0; int ttl = 0; int retry = 0; int i; + struct in_addr addr; + if (0 == strcmp(buf, "$shutdown")) - exit(0); + exit(0); + if (0 == strcmp(buf, "$hello")) { - printf("$alive\n"); - return; + printf("$alive\n"); + return; } + /* check if it's already an IP address in text form. */ for (;;) { - if (safe_inet_addr(buf, &addr)) { - reverse = 1; - result = gethostbyaddr((char *) &addr.s_addr, 4, AF_INET); - } else { - result = gethostbyname(buf); - } - if (NULL != result) - break; - if (h_errno != TRY_AGAIN) - break; - if (++retry == 3) - break; - sleep(1); + if (safe_inet_addr(buf, &addr)) { + reverse = 1; + result = gethostbyaddr((char *) &addr.s_addr, 4, AF_INET); + } else { + result = gethostbyname(buf); + } + + if (NULL != result) + break; + + if (h_errno != TRY_AGAIN) + break; + + if (++retry == 3) + break; + + sleep(1); } + if (NULL == result) { - if (h_errno == TRY_AGAIN) { - printf("$fail Name Server for domain '%s' is unavailable.\n", buf); - } else { - printf("$fail DNS Domain '%s' is invalid: %s.\n", - buf, my_h_msgs(h_errno)); - } - return; + if (h_errno == TRY_AGAIN) { + printf("$fail Name Server for domain '%s' is unavailable.\n", buf); + } else { + printf("$fail DNS Domain '%s' is invalid: %s.\n", + buf, my_h_msgs(h_errno)); + } + + return; } + #if LIBRESOLV_DNS_TTL_HACK /* DNS TTL handling - bne@CareNet.hu * for first try it's a dirty hack, by hacking getanswer * to place the ttl in a global variable */ if (_dns_ttl_ > -1) - ttl = _dns_ttl_; + ttl = _dns_ttl_; + #endif + if (reverse) { - printf("$name %d %s\n", ttl, result->h_name); - return; + printf("$name %d %s\n", ttl, result->h_name); + return; } + printf("$addr %d", ttl); + for (i = 0; NULL != result->h_addr_list[i]; i++) { - if (32 == i) - break; - xmemcpy(&addr, result->h_addr_list[i], sizeof(addr)); - printf(" %s", inet_ntoa(addr)); + if (32 == i) + break; + + xmemcpy(&addr, result->h_addr_list[i], sizeof(addr)); + + printf(" %s", inet_ntoa(addr)); } + printf("\n"); } @@ -249,11 +272,11 @@ static void usage(void) { fprintf(stderr, "usage: dnsserver -Dhv -s nameserver\n" - "\t-D Enable resolver RES_DEFNAMES and RES_DNSRCH options\n" - "\t-h Help\n" - "\t-v Version\n" - "\t-s nameserver Specify alternate name server(s). 'nameserver'\n" - "\t must be an IP address, -s option may be repeated\n"); + "\t-D Enable resolver RES_DEFNAMES and RES_DNSRCH options\n" + "\t-h Help\n" + "\t-v Version\n" + "\t-s nameserver Specify alternate name server(s). 'nameserver'\n" + "\t must be an IP address, -s option may be repeated\n"); } int @@ -263,8 +286,10 @@ main(int argc, char *argv[]) char *t = NULL; int c; #if HAVE_RES_INIT + int opt_s = 0; #if HAVE_RES_NSADDR_LIST || HAVE_RES_NS_LIST + extern char *optarg; #endif #endif @@ -272,95 +297,135 @@ main(int argc, char *argv[]) safe_inet_addr("255.255.255.255", &no_addr); #if HAVE_RES_INIT + res_init(); #ifdef RES_DEFAULT + _res.options = RES_DEFAULT; #endif #ifdef RES_DEFNAMES + _res.options &= ~RES_DEFNAMES; #endif #ifdef RES_DNSRCH + _res.options &= ~RES_DNSRCH; #endif #endif while ((c = getopt(argc, argv, "Dhs:v")) != -1) { - switch (c) { - case 'D': + switch (c) { + + case 'D': #ifdef RES_DEFNAMES - _res.options |= RES_DEFNAMES; + + _res.options |= RES_DEFNAMES; #endif #ifdef RES_DNSRCH - _res.options |= RES_DNSRCH; + + _res.options |= RES_DNSRCH; #endif - break; - case 's': + + break; + + case 's': #if HAVE_RES_INIT - if (opt_s == 0) { - _res.nscount = 0; - /* - * Setting RES_INIT here causes coredumps when -s is - * used with -D option. It looks to me like setting - * RES_INIT is wrong. The resolver code sets RES_INIT - * after calling res_init(). When we change the _res - * structure and set RES_INIT, some internal resolver - * structures get confused. -DW 2.1.p1 - */ + + if (opt_s == 0) { + _res.nscount = 0; + /* + * Setting RES_INIT here causes coredumps when -s is + * used with -D option. It looks to me like setting + * RES_INIT is wrong. The resolver code sets RES_INIT + * after calling res_init(). When we change the _res + * structure and set RES_INIT, some internal resolver + * structures get confused. -DW 2.1.p1 + */ #if SEEMS_WRONG - _res.options |= RES_INIT; -#endif - opt_s = 1; - } else if (_res.nscount == MAXNS) { - fprintf(stderr, "Too many -s options, only %d are allowed\n", - MAXNS); - break; - } + + _res.options |= RES_INIT; +#endif + + opt_s = 1; + } else if (_res.nscount == MAXNS) { + fprintf(stderr, "Too many -s options, only %d are allowed\n", + MAXNS); + break; + } + #if HAVE_RES_NSADDR_LIST - _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0]; - safe_inet_addr(optarg, &_res.nsaddr_list[_res.nscount++].sin_addr); + _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0]; + + safe_inet_addr(optarg, &_res.nsaddr_list[_res.nscount++].sin_addr); + #elif HAVE_RES_NS_LIST - _res.ns_list[_res.nscount] = _res.ns_list[0]; - safe_inet_addr(optarg, &_res.ns_list[_res.nscount++].addr.sin_addr); + + _res.ns_list[_res.nscount] = _res.ns_list[0]; + + safe_inet_addr(optarg, &_res.ns_list[_res.nscount++].addr.sin_addr); + #else /* Unknown NS list format */ - fprintf(stderr, "-s is not supported on this resolver\n"); + + fprintf(stderr, "-s is not supported on this resolver\n"); + #endif #else /* !HAVE_RES_INIT */ - fprintf(stderr, "-s is not supported on this resolver\n"); + + fprintf(stderr, "-s is not supported on this resolver\n"); + #endif /* HAVE_RES_INIT */ - break; - case 'v': - printf("dnsserver version %s\n", VERSION); - exit(0); - break; - case 'h': - default: - usage(); - exit(1); - break; - } + + break; + + case 'v': + printf("dnsserver version %s\n", VERSION); + + exit(0); + + break; + + case 'h': + + default: + usage(); + + exit(1); + + break; + } } #ifdef _SQUID_MSWIN_ { - WSADATA wsaData; + WSADATA wsaData; - WSAStartup(2, &wsaData); + WSAStartup(2, &wsaData); } + fflush(stderr); #endif + for (;;) { - memset(request, '\0', REQ_SZ); - if (fgets(request, REQ_SZ, stdin) == NULL) - exit(1); - t = strrchr(request, '\n'); - if (t == NULL) /* Ignore if no newline */ - continue; - *t = '\0'; /* strip NL */ - if ((t = strrchr(request, '\r')) != NULL) - *t = '\0'; /* strip CR */ - lookup(request); - fflush(stdout); + memset(request, '\0', REQ_SZ); + + if (fgets(request, REQ_SZ, stdin) == NULL) + exit(1); + + t = strrchr(request, '\n'); + + if (t == NULL) /* Ignore if no newline */ + continue; + + *t = '\0'; /* strip NL */ + + if ((t = strrchr(request, '\r')) != NULL) + *t = '\0'; /* strip CR */ + + lookup(request); + + fflush(stdout); } + /* NOTREACHED */ return 0; } diff --git a/src/enums.h b/src/enums.h index bce5cd95ca..dfaebf8794 100644 --- a/src/enums.h +++ b/src/enums.h @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.226 2003/02/17 07:01:36 robertc Exp $ + * $Id: enums.h,v 1.227 2003/02/21 22:50:08 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -499,13 +499,13 @@ typedef enum { STREAM_NONE, /* No particular status */ STREAM_COMPLETE, /* All data has been flushed, no more reads allowed */ STREAM_UNPLANNED_COMPLETE, /* an unpredicted end has occured, no more - * reads occured, but no need to tell - * downstream that an error occured - */ + * reads occured, but no need to tell + * downstream that an error occured + */ STREAM_FAILED /* An error has occured in this node or an above one, - * and the node is not generating an error body / it's - * midstream - */ + * and the node is not generating an error body / it's + * midstream + */ } clientStream_status_t; typedef enum { diff --git a/src/errorpage.cc b/src/errorpage.cc index 1bb72e8e06..cd89d5cd41 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -1,6 +1,6 @@ /* - * $Id: errorpage.cc,v 1.184 2003/02/09 20:12:19 hno Exp $ + * $Id: errorpage.cc,v 1.185 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels @@ -50,10 +50,13 @@ /* local types */ -typedef struct { +typedef struct +{ int id; char *page_name; -} ErrorDynamicPageInfo; +} + +ErrorDynamicPageInfo; /* local constant and vars */ @@ -61,25 +64,29 @@ typedef struct { * note: hard coded error messages are not appended with %S automagically * to give you more control on the format */ -static const struct { + +static const struct +{ int type; /* and page_id */ const char *text; -} error_hard_text[] = { - - { - ERR_SQUID_SIGNATURE, - "\n
    \n" - "
    \n" - "
    \n" - "Generated %T by %h (%s)\n" - "
    \n" - "\n" - }, - { - TCP_RESET, - "reset" - } -}; +} + +error_hard_text[] = { + + { + ERR_SQUID_SIGNATURE, + "\n
    \n" + "
    \n" + "
    \n" + "Generated %T by %h (%s)\n" + "
    \n" + "\n" + }, + { + TCP_RESET, + "reset" + } + }; static Vector ErrorDynamicPages; @@ -106,7 +113,8 @@ err_type &operator++ (err_type &anErr) return anErr; } -int operator - (err_type const &anErr, err_type const &anErr2) { +int operator - (err_type const &anErr, err_type const &anErr2) +{ return (int)anErr - (int)anErr2; } @@ -126,23 +134,26 @@ errorInitialize(void) const char *text; error_page_count = ERR_MAX + ErrorDynamicPages.size(); error_text = static_cast(xcalloc(error_page_count, sizeof(char *))); + for (i = ERR_NONE, ++i; i < error_page_count; ++i) { - safe_free(error_text[i]); - /* hard-coded ? */ - if ((text = errorFindHardText(i))) - error_text[i] = xstrdup(text); - else if (i < ERR_MAX) { - /* precompiled ? */ - error_text[i] = errorLoadText(err_type_str[i]); - } else { - /* dynamic */ - ErrorDynamicPageInfo *info = ErrorDynamicPages.items[i - ERR_MAX]; - assert(info && info->id == i && info->page_name); - if (strchr(info->page_name, ':') == NULL) { - /* Not on redirected errors... */ - error_text[i] = errorLoadText(info->page_name); - } - } + safe_free(error_text[i]); + /* hard-coded ? */ + + if ((text = errorFindHardText(i))) + error_text[i] = xstrdup(text); + else if (i < ERR_MAX) { + /* precompiled ? */ + error_text[i] = errorLoadText(err_type_str[i]); + } else { + /* dynamic */ + ErrorDynamicPageInfo *info = ErrorDynamicPages.items[i - ERR_MAX]; + assert(info && info->id == i && info->page_name); + + if (strchr(info->page_name, ':') == NULL) { + /* Not on redirected errors... */ + error_text[i] = errorLoadText(info->page_name); + } + } } } @@ -150,13 +161,17 @@ void errorClean(void) { if (error_text) { - int i; - for (i = ERR_NONE + 1; i < error_page_count; i++) - safe_free(error_text[i]); - safe_free(error_text); + int i; + + for (i = ERR_NONE + 1; i < error_page_count; i++) + safe_free(error_text[i]); + + safe_free(error_text); } + while (ErrorDynamicPages.size()) - errorDynamicPageInfoDestroy(ErrorDynamicPages.pop_back()); + errorDynamicPageInfoDestroy(ErrorDynamicPages.pop_back()); + error_page_count = 0; } @@ -164,9 +179,11 @@ static const char * errorFindHardText(err_type type) { int i; + for (i = 0; i < error_hard_text_count; i++) - if (error_hard_text[i].type == type) - return error_hard_text[i].text; + if (error_hard_text[i].type == type) + return error_hard_text[i].text; + return NULL; } @@ -177,11 +194,14 @@ errorLoadText(const char *page_name) /* test configured location */ char *text = errorTryLoadText(page_name, Config.errorDirectory); /* test default location if failed */ + if (!text && strcmp(Config.errorDirectory, DEFAULT_SQUID_ERROR_DIR)) - text = errorTryLoadText(page_name, DEFAULT_SQUID_ERROR_DIR); + text = errorTryLoadText(page_name, DEFAULT_SQUID_ERROR_DIR); + /* giving up if failed */ if (!text) - fatal("failed to find or read error text file."); + fatal("failed to find or read error text file."); + return text; } @@ -199,29 +219,35 @@ errorTryLoadText(const char *page_name, const char *dir) fd = file_open(path, O_RDONLY | O_TEXT); if (fd < 0) { - debug(4, 0) ("errorTryLoadText: '%s': %s\n", path, xstrerror()); - return NULL; + debug(4, 0) ("errorTryLoadText: '%s': %s\n", path, xstrerror()); + return NULL; } + memBufDefInit(&textbuf); + while((len = FD_READ_METHOD(fd, buf, sizeof(buf))) > 0) { - memBufAppend(&textbuf, buf, len); + memBufAppend(&textbuf, buf, len); } + if (len < 0) { - debug(4, 0) ("errorTryLoadText: failed to fully read: '%s': %s\n", - path, xstrerror()); - memBufClean(&textbuf); - text = NULL; + debug(4, 0) ("errorTryLoadText: failed to fully read: '%s': %s\n", + path, xstrerror()); + memBufClean(&textbuf); + text = NULL; } + file_close(fd); if (strstr(textbuf.buf, "%s") == NULL) - memBufAppend(&textbuf, "%S", 2); /* add signature */ + memBufAppend(&textbuf, "%S", 2); /* add signature */ /* Shrink memory size down to exact size. MemBuf has a tencendy * to be rather large.. */ text = xstrdup(textbuf.buf); + memBufClean(&textbuf); + return text; } @@ -246,13 +272,15 @@ static int errorPageId(const char *page_name) { for (int i = 0; i < ERR_MAX; i++) { - if (strcmp(err_type_str[i], page_name) == 0) - return i; + if (strcmp(err_type_str[i], page_name) == 0) + return i; } + for (size_t i = 0; i < ErrorDynamicPages.size(); i++) { - if (strcmp(ErrorDynamicPages.items[i]->page_name, page_name) == 0) - return i + ERR_MAX; + if (strcmp(ErrorDynamicPages.items[i]->page_name, page_name) == 0) + return i + ERR_MAX; } + return ERR_NONE; } @@ -261,11 +289,13 @@ errorReservePageId(const char *page_name) { ErrorDynamicPageInfo *info; int id = errorPageId(page_name); + if (id == ERR_NONE) { - info = errorDynamicPageInfoCreate(ERR_MAX + ErrorDynamicPages.size(), page_name); - ErrorDynamicPages.push_back(info); - id = info->id; + info = errorDynamicPageInfoCreate(ERR_MAX + ErrorDynamicPages.size(), page_name); + ErrorDynamicPages.push_back(info); + id = info->id; } + return (err_type)id; } @@ -273,9 +303,11 @@ static const char * errorPageName(int pageId) { if (pageId >= ERR_NONE && pageId < ERR_MAX) /* common case */ - return err_type_str[pageId]; + return err_type_str[pageId]; + if (pageId >= ERR_MAX && pageId - ERR_MAX < (ssize_t)ErrorDynamicPages.size()) - return ErrorDynamicPages.items[pageId - ERR_MAX]->page_name; + return ErrorDynamicPages.items[pageId - ERR_MAX]->page_name; + return "ERR_UNKNOWN"; /* should not happen */ } @@ -316,23 +348,26 @@ errorAppendEntry(StoreEntry * entry, ErrorState * err) MemObject *mem = entry->mem_obj; assert(mem != NULL); assert (entry->isEmpty()); + if (entry->store_status != STORE_PENDING) { - /* - * If the entry is not STORE_PENDING, then no clients - * care about it, and we don't need to generate an - * error message - */ - assert(EBIT_TEST(entry->flags, ENTRY_ABORTED)); - assert(mem->nclients == 0); - errorStateFree(err); - return; + /* + * If the entry is not STORE_PENDING, then no clients + * care about it, and we don't need to generate an + * error message + */ + assert(EBIT_TEST(entry->flags, ENTRY_ABORTED)); + assert(mem->nclients == 0); + errorStateFree(err); + return; } + if (err->page_id == TCP_RESET) { - if (err->request) { - debug(4, 2) ("RSTing this reply\n"); - err->request->flags.setResetTCP(); - } + if (err->request) { + debug(4, 2) ("RSTing this reply\n"); + err->request->flags.setResetTCP(); + } } + storeLockObject(entry); storeBuffer(entry); rep = errorBuildReply(err); @@ -381,12 +416,17 @@ errorSend(int fd, ErrorState * err) * ugh, this is how we make sure error codes get back to * the client side for logging and error tracking. */ + if (err->request) - err->request->errType = err->type; + err->request->errType = err->type; + /* moved in front of errorBuildBuf @?@ */ err->flags.flag_cbdata = 1; + rep = errorBuildReply(err); + comm_old_write_mbuf(fd, httpReplyPack(rep), errorSendComplete, err); + httpReplyDestroy(rep); } @@ -404,15 +444,17 @@ errorSendComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag, voi { ErrorState *err = static_cast(data); debug(4, 3) ("errorSendComplete: FD %d, size=%ld\n", fd, (long int) size); + if (errflag != COMM_ERR_CLOSING) { - if (err->callback) { - debug(4, 3) ("errorSendComplete: callback\n"); - err->callback(fd, err->callback_data, size); - } else { - comm_close(fd); - debug(4, 3) ("errorSendComplete: comm_close\n"); - } + if (err->callback) { + debug(4, 3) ("errorSendComplete: callback\n"); + err->callback(fd, err->callback_data, size); + } else { + comm_close(fd); + debug(4, 3) ("errorSendComplete: comm_close\n"); + } } + errorStateFree(err); } @@ -428,9 +470,12 @@ errorStateFree(ErrorState * err) wordlistDestroy(&err->ftp.server_msg); safe_free(err->ftp.request); safe_free(err->ftp.reply); + if (err->auth_user_request) - authenticateAuthUserRequestUnlock(err->auth_user_request); + authenticateAuthUserRequestUnlock(err->auth_user_request); + err->auth_user_request = NULL; + cbdataFree(err); } @@ -449,50 +494,61 @@ errorDump(ErrorState * err, MemBuf * mb) memBufPrintf(&str, "CacheHost: %s\r\n", getMyHostname()); /* - Err Msgs */ memBufPrintf(&str, "ErrPage: %s\r\n", errorPageName(err->type)); + if (err->xerrno) { - memBufPrintf(&str, "Err: (%d) %s\r\n", err->xerrno, strerror(err->xerrno)); + memBufPrintf(&str, "Err: (%d) %s\r\n", err->xerrno, strerror(err->xerrno)); } else { - memBufPrintf(&str, "Err: [none]\r\n"); + memBufPrintf(&str, "Err: [none]\r\n"); } + if (authenticateAuthUserRequestMessage(err->auth_user_request)) { - memBufPrintf(&str, "extAuth ErrMsg: %s\r\n", authenticateAuthUserRequestMessage(err->auth_user_request)); + memBufPrintf(&str, "extAuth ErrMsg: %s\r\n", authenticateAuthUserRequestMessage(err->auth_user_request)); } + if (err->dnsserver_msg) { - memBufPrintf(&str, "DNS Server ErrMsg: %s\r\n", err->dnsserver_msg); + memBufPrintf(&str, "DNS Server ErrMsg: %s\r\n", err->dnsserver_msg); } + /* - TimeStamp */ memBufPrintf(&str, "TimeStamp: %s\r\n\r\n", mkrfc1123(squid_curtime)); + /* - IP stuff */ memBufPrintf(&str, "ClientIP: %s\r\n", inet_ntoa(err->src_addr)); + if (err->host) { - memBufPrintf(&str, "ServerIP: %s\r\n", err->host); + memBufPrintf(&str, "ServerIP: %s\r\n", err->host); } + memBufPrintf(&str, "\r\n"); /* - HTTP stuff */ memBufPrintf(&str, "HTTP Request:\r\n"); + if (NULL != r) { - Packer p; - memBufPrintf(&str, "%s %s HTTP/%d.%d\n", - RequestMethodStr[r->method], - r->urlpath.size() ? r->urlpath.buf() : "/", - r->http_ver.major, r->http_ver.minor); - packerToMemInit(&p, &str); - httpHeaderPackInto(&r->header, &p); - packerClean(&p); + Packer p; + memBufPrintf(&str, "%s %s HTTP/%d.%d\n", + RequestMethodStr[r->method], + r->urlpath.size() ? r->urlpath.buf() : "/", + r->http_ver.major, r->http_ver.minor); + packerToMemInit(&p, &str); + httpHeaderPackInto(&r->header, &p); + packerClean(&p); } else if (err->request_hdrs) { - p = err->request_hdrs; + p = err->request_hdrs; } else { - p = "[none]"; + p = "[none]"; } + memBufPrintf(&str, "\r\n"); /* - FTP stuff */ + if (err->ftp.request) { - memBufPrintf(&str, "FTP Request: %s\r\n", err->ftp.request); - memBufPrintf(&str, "FTP Reply: %s\r\n", err->ftp.reply); - memBufPrintf(&str, "FTP Msg: "); - wordlistCat(err->ftp.server_msg, &str); - memBufPrintf(&str, "\r\n"); + memBufPrintf(&str, "FTP Request: %s\r\n", err->ftp.request); + memBufPrintf(&str, "FTP Reply: %s\r\n", err->ftp.reply); + memBufPrintf(&str, "FTP Msg: "); + wordlistCat(err->ftp.server_msg, &str); + memBufPrintf(&str, "\r\n"); } + memBufPrintf(&str, "\r\n"); memBufPrintf(mb, "&body=%s", rfc1738_escape_part(str.buf)); memBufClean(&str); @@ -540,154 +596,211 @@ errorConvert(char token, ErrorState * err) int do_quote = 1; memBufReset(&mb); + switch (token) { + case 'B': - p = r ? ftpUrlWith2f(r) : "[no URL]"; - break; + p = r ? ftpUrlWith2f(r) : "[no URL]"; + break; + case 'c': - p = errorPageName(err->type); - break; + p = errorPageName(err->type); + break; + case 'e': - memBufPrintf(&mb, "%d", err->xerrno); - break; + memBufPrintf(&mb, "%d", err->xerrno); + break; + case 'E': - if (err->xerrno) - memBufPrintf(&mb, "(%d) %s", err->xerrno, strerror(err->xerrno)); - else - memBufPrintf(&mb, "[No Error]"); - break; + + if (err->xerrno) + memBufPrintf(&mb, "(%d) %s", err->xerrno, strerror(err->xerrno)); + else + memBufPrintf(&mb, "[No Error]"); + + break; + case 'f': - /* FTP REQUEST LINE */ - if (err->ftp.request) - p = err->ftp.request; - else - p = "nothing"; - break; + /* FTP REQUEST LINE */ + if (err->ftp.request) + p = err->ftp.request; + else + p = "nothing"; + + break; + case 'F': - /* FTP REPLY LINE */ - if (err->ftp.request) - p = err->ftp.reply; - else - p = "nothing"; - break; + /* FTP REPLY LINE */ + if (err->ftp.request) + p = err->ftp.reply; + else + p = "nothing"; + + break; + case 'g': - /* FTP SERVER MESSAGE */ - wordlistCat(err->ftp.server_msg, &mb); - break; + /* FTP SERVER MESSAGE */ + wordlistCat(err->ftp.server_msg, &mb); + + break; + case 'h': - memBufPrintf(&mb, "%s", getMyHostname()); - break; + memBufPrintf(&mb, "%s", getMyHostname()); + + break; + case 'H': - p = r ? r->host : "[unknown host]"; - break; + p = r ? r->host : "[unknown host]"; + + break; + case 'i': - memBufPrintf(&mb, "%s", inet_ntoa(err->src_addr)); - break; + memBufPrintf(&mb, "%s", inet_ntoa(err->src_addr)); + + break; + case 'I': - if (err->host) { - memBufPrintf(&mb, "%s", err->host); - } else - p = "[unknown]"; - break; + if (err->host) { + memBufPrintf(&mb, "%s", err->host); + } else + p = "[unknown]"; + + break; + case 'L': - if (Config.errHtmlText) { - memBufPrintf(&mb, "%s", Config.errHtmlText); - do_quote = 0; - } else - p = "[not available]"; - break; + if (Config.errHtmlText) { + memBufPrintf(&mb, "%s", Config.errHtmlText); + do_quote = 0; + } else + p = "[not available]"; + + break; + case 'm': - p = authenticateAuthUserRequestMessage(err->auth_user_request) ? authenticateAuthUserRequestMessage(err->auth_user_request) : "[not available]"; - break; + p = authenticateAuthUserRequestMessage(err->auth_user_request) ? authenticateAuthUserRequestMessage(err->auth_user_request) : "[not available]"; + + break; + case 'M': - p = r ? RequestMethodStr[r->method] : "[unkown method]"; - break; + p = r ? RequestMethodStr[r->method] : "[unkown method]"; + + break; + case 'p': - if (r) { - memBufPrintf(&mb, "%d", (int) r->port); - } else { - p = "[unknown port]"; - } - break; + if (r) { + memBufPrintf(&mb, "%d", (int) r->port); + } else { + p = "[unknown port]"; + } + + break; + case 'P': - p = r ? ProtocolStr[r->protocol] : "[unkown protocol]"; - break; + p = r ? ProtocolStr[r->protocol] : "[unkown protocol]"; + break; + case 'R': - if (NULL != r) { - Packer p; - memBufPrintf(&mb, "%s %s HTTP/%d.%d\n", - RequestMethodStr[r->method], - r->urlpath.size() ? r->urlpath.buf() : "/", - r->http_ver.major, r->http_ver.minor); - packerToMemInit(&p, &mb); - httpHeaderPackInto(&r->header, &p); - packerClean(&p); - } else if (err->request_hdrs) { - p = err->request_hdrs; - } else { - p = "[no request]"; - } - break; + + if (NULL != r) { + Packer p; + memBufPrintf(&mb, "%s %s HTTP/%d.%d\n", + RequestMethodStr[r->method], + r->urlpath.size() ? r->urlpath.buf() : "/", + r->http_ver.major, r->http_ver.minor); + packerToMemInit(&p, &mb); + httpHeaderPackInto(&r->header, &p); + packerClean(&p); + } else if (err->request_hdrs) { + p = err->request_hdrs; + } else { + p = "[no request]"; + } + + break; + case 's': - p = full_appname_string; - break; + p = full_appname_string; + break; + case 'S': - /* signature may contain %-escapes, recursion */ - if (err->page_id != ERR_SQUID_SIGNATURE) { - const int saved_id = err->page_id; - MemBuf sign_mb; - err->page_id = ERR_SQUID_SIGNATURE; - sign_mb = errorBuildContent(err); - memBufPrintf(&mb, "%s", sign_mb.buf); - memBufClean(&sign_mb); - err->page_id = saved_id; - do_quote = 0; - } else { - /* wow, somebody put %S into ERR_SIGNATURE, stop recursion */ - p = "[%S]"; - } - break; + /* signature may contain %-escapes, recursion */ + + if (err->page_id != ERR_SQUID_SIGNATURE) { + const int saved_id = err->page_id; + MemBuf sign_mb; + err->page_id = ERR_SQUID_SIGNATURE; + sign_mb = errorBuildContent(err); + memBufPrintf(&mb, "%s", sign_mb.buf); + memBufClean(&sign_mb); + err->page_id = saved_id; + do_quote = 0; + } else { + /* wow, somebody put %S into ERR_SIGNATURE, stop recursion */ + p = "[%S]"; + } + + break; + case 't': - memBufPrintf(&mb, "%s", mkhttpdlogtime(&squid_curtime)); - break; + memBufPrintf(&mb, "%s", mkhttpdlogtime(&squid_curtime)); + break; + case 'T': - memBufPrintf(&mb, "%s", mkrfc1123(squid_curtime)); - break; + memBufPrintf(&mb, "%s", mkrfc1123(squid_curtime)); + break; + case 'U': - p = r ? urlCanonicalClean(r) : err->url ? err->url : "[no URL]"; - break; + p = r ? urlCanonicalClean(r) : err->url ? err->url : "[no URL]"; + break; + case 'u': - p = r ? urlCanonical(r) : err->url ? err->url : "[no URL]"; - break; + p = r ? urlCanonical(r) : err->url ? err->url : "[no URL]"; + break; + case 'w': - if (Config.adminEmail) - memBufPrintf(&mb, "%s", Config.adminEmail); - else - p = "[unknown]"; - break; + + if (Config.adminEmail) + memBufPrintf(&mb, "%s", Config.adminEmail); + else + p = "[unknown]"; + + break; + case 'W': - if (Config.adminEmail && Config.onoff.emailErrData) - errorDump(err, &mb); - break; + if (Config.adminEmail && Config.onoff.emailErrData) + errorDump(err, &mb); + + break; + case 'z': - if (err->dnsserver_msg) - p = err->dnsserver_msg; - else - p = "[unknown]"; - break; + if (err->dnsserver_msg) + p = err->dnsserver_msg; + else + p = "[unknown]"; + + break; + case '%': - p = "%"; - break; + p = "%"; + + break; + default: - memBufPrintf(&mb, "%%%c", token); - break; + memBufPrintf(&mb, "%%%c", token); + + break; } + if (!p) - p = mb.buf; /* do not use mb after this assignment! */ + p = mb.buf; /* do not use mb after this assignment! */ + assert(p); + debug(4, 3) ("errorConvert: %%%c --> '%s'\n", token, p); + if (do_quote) - p = html_quote(p); + p = html_quote(p); + return p; } @@ -700,28 +813,30 @@ errorBuildReply(ErrorState * err) http_version_t version; /* no LMT for error pages; error pages expire immediately */ httpBuildVersion(&version, 1, 0); + if (strchr(name, ':')) { - /* Redirection */ - char *quoted_url = rfc1738_escape_part(errorConvert('u', err)); - httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, 0, squid_curtime); - httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url); - httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s\n", err->httpStatus, "Access Denied"); + /* Redirection */ + char *quoted_url = rfc1738_escape_part(errorConvert('u', err)); + httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, 0, squid_curtime); + httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url); + httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s\n", err->httpStatus, "Access Denied"); } else { - MemBuf content = errorBuildContent(err); - httpReplySetHeaders(rep, version, err->httpStatus, NULL, "text/html", content.size, 0, squid_curtime); - /* - * include some information for downstream caches. Implicit - * replaceable content. This isn't quite sufficient. xerrno is not - * necessarily meaningful to another system, so we really should - * expand it. Additionally, we should identify ourselves. Someone - * might want to know. Someone _will_ want to know OTOH, the first - * X-CACHE-MISS entry should tell us who. - */ - httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%s %d", - name, err->xerrno); - httpBodySet(&rep->body, &content); - /* do not memBufClean() the content, it was absorbed by httpBody */ + MemBuf content = errorBuildContent(err); + httpReplySetHeaders(rep, version, err->httpStatus, NULL, "text/html", content.size, 0, squid_curtime); + /* + * include some information for downstream caches. Implicit + * replaceable content. This isn't quite sufficient. xerrno is not + * necessarily meaningful to another system, so we really should + * expand it. Additionally, we should identify ourselves. Someone + * might want to know. Someone _will_ want to know OTOH, the first + * X-CACHE-MISS entry should tell us who. + */ + httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%s %d", + name, err->xerrno); + httpBodySet(&rep->body, &content); + /* do not memBufClean() the content, it was absorbed by httpBody */ } + return rep; } @@ -737,14 +852,18 @@ errorBuildContent(ErrorState * err) memBufDefInit(&content); m = error_text[err->page_id]; assert(m); + while ((p = strchr(m, '%'))) { - memBufAppend(&content, m, p - m); /* copy */ - t = errorConvert(*++p, err); /* convert */ - memBufPrintf(&content, "%s", t); /* copy */ - m = p + 1; /* advance */ + memBufAppend(&content, m, p - m); /* copy */ + t = errorConvert(*++p, err); /* convert */ + memBufPrintf(&content, "%s", t); /* copy */ + m = p + 1; /* advance */ } + if (*m) - memBufPrintf(&content, "%s", m); /* copy tail */ + memBufPrintf(&content, "%s", m); /* copy tail */ + assert((size_t)content.size == strlen(content.buf)); + return content; } diff --git a/src/event.cc b/src/event.cc index 418d0efa15..20aef02b19 100644 --- a/src/event.cc +++ b/src/event.cc @@ -1,6 +1,6 @@ /* - * $Id: event.cc,v 1.35 2003/01/23 00:37:20 robertc Exp $ + * $Id: event.cc,v 1.36 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 41 Event Processing * AUTHOR: Henrik Nordstrom @@ -37,11 +37,14 @@ #include "Store.h" /* The list of event processes */ -struct ev_entry { + +struct ev_entry +{ EVH *func; void *arg; const char *name; double when; + struct ev_entry *next; int weight; int id; @@ -55,7 +58,9 @@ static const char *last_event_ran = NULL; void eventAdd(const char *name, EVH * func, void *arg, double when, int weight) { + struct ev_entry *event = (ev_entry *)memAllocate(MEM_EVENT); + struct ev_entry **E; event->func = func; event->arg = cbdataReference(arg); @@ -65,10 +70,12 @@ eventAdd(const char *name, EVH * func, void *arg, double when, int weight) event->id = run_id; debug(41, 7) ("eventAdd: Adding '%s', in %f seconds\n", name, when); /* Insert after the last event with the same or earlier time */ + for (E = &tasks; *E; E = &(*E)->next) { - if ((*E)->when > event->when) - break; + if ((*E)->when > event->when) + break; } + event->next = *E; *E = event; } @@ -78,66 +85,90 @@ void eventAddIsh(const char *name, EVH * func, void *arg, double delta_ish, int weight) { if (delta_ish >= 3.0) { - const double two_third = (2.0 * delta_ish) / 3.0; - delta_ish = two_third + (drand48() * two_third); - /* - * I'm sure drand48() isn't portable. Tell me what function - * you have that returns a random double value in the range 0,1. - */ + const double two_third = (2.0 * delta_ish) / 3.0; + delta_ish = two_third + (drand48() * two_third); + /* + * I'm sure drand48() isn't portable. Tell me what function + * you have that returns a random double value in the range 0,1. + */ } + eventAdd(name, func, arg, delta_ish, weight); } void eventDelete(EVH * func, void *arg) { + struct ev_entry **E; + struct ev_entry *event; + for (E = &tasks; (event = *E) != NULL; E = &(*E)->next) { - if (event->func != func) - continue; - if (event->arg != arg) - continue; - *E = event->next; - cbdataReferenceDone(event->arg); - memFree(event, MEM_EVENT); - return; + if (event->func != func) + continue; + + if (event->arg != arg) + continue; + + *E = event->next; + + cbdataReferenceDone(event->arg); + + memFree(event, MEM_EVENT); + + return; } + debug_trap("eventDelete: event not found"); } void eventRun(void) { + struct ev_entry *event = NULL; int weight = 0; + if (NULL == tasks) - return; + return; + if (tasks->when > current_dtime) - return; + return; + run_id++; + debug(41, 5) ("eventRun: RUN ID %d\n", run_id); + while ((event = tasks)) { - EVH *callback; - void *cbdata; - if (event->when > current_dtime) - break; - if (event->id == run_id) /* was added during this run */ - break; - if (weight) - break; - tasks = event->next; - callback = event->func; - event->func = NULL; - if (cbdataReferenceValidDone(event->arg, &cbdata)) { - weight += event->weight; - /* XXX assumes ->name is static memory! */ - last_event_ran = event->name; - debug(41, 5) ("eventRun: Running '%s', id %d\n", - event->name, event->id); - callback(cbdata); - } - memFree(event, MEM_EVENT); + EVH *callback; + void *cbdata; + + if (event->when > current_dtime) + break; + + if (event->id == run_id) /* was added during this run */ + break; + + if (weight) + break; + + tasks = event->next; + + callback = event->func; + + event->func = NULL; + + if (cbdataReferenceValidDone(event->arg, &cbdata)) { + weight += event->weight; + /* XXX assumes ->name is static memory! */ + last_event_ran = event->name; + debug(41, 5) ("eventRun: Running '%s', id %d\n", + event->name, event->id); + callback(cbdata); + } + + memFree(event, MEM_EVENT); } } @@ -145,57 +176,69 @@ int eventNextTime(void) { if (!tasks) - return (int) 10; + return (int) 10; + return (int) ((tasks->when - current_dtime) * 1000); } void eventInit(void) { + memDataInit(MEM_EVENT, "event", sizeof(struct ev_entry), 0); cachemgrRegister("events", - "Event Queue", - eventDump, 0, 1); + "Event Queue", + eventDump, 0, 1); } static void eventDump(StoreEntry * sentry) { + struct ev_entry *e = tasks; + if (last_event_ran) - storeAppendPrintf(sentry, "Last event to run: %s\n\n", last_event_ran); + storeAppendPrintf(sentry, "Last event to run: %s\n\n", last_event_ran); + storeAppendPrintf(sentry, "%s\t%s\t%s\t%s\n", - "Operation", - "Next Execution", - "Weight", - "Callback Valid?"); + "Operation", + "Next Execution", + "Weight", + "Callback Valid?"); + while (e != NULL) { - storeAppendPrintf(sentry, "%s\t%f seconds\t%d\t%s\n", - e->name, e->when - current_dtime, e->weight, - e->arg ? cbdataReferenceValid(e->arg) ? "yes" : "no" : "N/A"); - e = e->next; + storeAppendPrintf(sentry, "%s\t%f seconds\t%d\t%s\n", + e->name, e->when - current_dtime, e->weight, + e->arg ? cbdataReferenceValid(e->arg) ? "yes" : "no" : "N/A"); + e = e->next; } } void eventFreeMemory(void) { + struct ev_entry *event; + while ((event = tasks)) { - tasks = event->next; - cbdataReferenceDone(event->arg); - memFree(event, MEM_EVENT); + tasks = event->next; + cbdataReferenceDone(event->arg); + memFree(event, MEM_EVENT); } + tasks = NULL; } int eventFind(EVH * func, void *arg) { + struct ev_entry *event; + for (event = tasks; event != NULL; event = event->next) { - if (event->func == func && event->arg == arg) - return 1; + if (event->func == func && event->arg == arg) + return 1; } + return 0; } diff --git a/src/external_acl.cc b/src/external_acl.cc index 77e7fbae65..fd5af2af1d 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -1,6 +1,6 @@ /* - * $Id: external_acl.cc,v 1.28 2003/02/16 02:23:19 robertc Exp $ + * $Id: external_acl.cc,v 1.29 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 82 External ACL * AUTHOR: Henrik Nordstrom, MARA Systems AB @@ -59,6 +59,7 @@ #endif typedef struct _external_acl_format external_acl_format; + typedef struct _external_acl_data external_acl_data; static char *makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data); @@ -70,7 +71,9 @@ static void external_acl_cache_touch(external_acl * def, external_acl_entry * en * external_acl cache entry * Used opaqueue in the interface */ -struct _external_acl_entry: public hash_link { + +struct _external_acl_entry: public hash_link +{ dlink_node lru; int result; time_t date; @@ -82,7 +85,9 @@ struct _external_acl_entry: public hash_link { /****************************************************************** * external_acl directive */ -struct _external_acl { + +struct _external_acl +{ external_acl *next; int ttl; int negative_ttl; @@ -99,28 +104,29 @@ struct _external_acl { int require_auth; }; -struct _external_acl_format { +struct _external_acl_format +{ enum { - EXT_ACL_UNKNOWN, - EXT_ACL_LOGIN, + EXT_ACL_UNKNOWN, + EXT_ACL_LOGIN, #if USE_IDENT - EXT_ACL_IDENT, + EXT_ACL_IDENT, #endif - EXT_ACL_SRC, - EXT_ACL_DST, - EXT_ACL_PROTO, - EXT_ACL_PORT, - EXT_ACL_PATH, - EXT_ACL_METHOD, - EXT_ACL_HEADER, - EXT_ACL_HEADER_MEMBER, - EXT_ACL_HEADER_ID, - EXT_ACL_HEADER_ID_MEMBER, + EXT_ACL_SRC, + EXT_ACL_DST, + EXT_ACL_PROTO, + EXT_ACL_PORT, + EXT_ACL_PATH, + EXT_ACL_METHOD, + EXT_ACL_HEADER, + EXT_ACL_HEADER_MEMBER, + EXT_ACL_HEADER_ID, + EXT_ACL_HEADER_ID_MEMBER, #if USE_SSL - EXT_ACL_USER_CERT, - EXT_ACL_CA_CERT, + EXT_ACL_USER_CERT, + EXT_ACL_CA_CERT, #endif - EXT_ACL_END + EXT_ACL_END } type; external_acl_format *next; char *header; @@ -147,21 +153,25 @@ free_external_acl(void *data) { external_acl *p = static_cast(data); safe_free(p->name); + while (p->format) { - external_acl_format *f = p->format; - p->format = f->next; - cbdataFree(f); + external_acl_format *f = p->format; + p->format = f->next; + cbdataFree(f); } + wordlistDestroy(&p->cmdline); + if (p->theHelper) { - helperShutdown(p->theHelper); - helperFree(p->theHelper); - p->theHelper = NULL; + helperShutdown(p->theHelper); + helperFree(p->theHelper); + p->theHelper = NULL; } + while (p->lru_list.tail) - external_acl_cache_delete(p, static_cast(p->lru_list.tail->data)); + external_acl_cache_delete(p, static_cast(p->lru_list.tail->data)); if (p->cache) - hashFreeMemory(p->cache); + hashFreeMemory(p->cache); } void @@ -181,124 +191,146 @@ parse_externalAclHelper(external_acl ** list) a->children = DEFAULT_EXTERNAL_ACL_CONCURRENCY; token = strtok(NULL, w_space); + if (!token) - self_destruct(); + self_destruct(); + a->name = xstrdup(token); token = strtok(NULL, w_space); + /* Parse options */ while (token) { - if (strncmp(token, "ttl=", 4) == 0) { - a->ttl = atoi(token + 4); - } else if (strncmp(token, "negative_ttl=", 13) == 0) { - a->negative_ttl = atoi(token + 13); - } else if (strncmp(token, "concurrency=", 12) == 0) { - a->children = atoi(token + 12); - } else if (strncmp(token, "cache=", 6) == 0) { - a->cache_size = atoi(token + 6); - } else { - break; - } - - token = strtok(NULL, w_space); + if (strncmp(token, "ttl=", 4) == 0) { + a->ttl = atoi(token + 4); + } else if (strncmp(token, "negative_ttl=", 13) == 0) { + a->negative_ttl = atoi(token + 13); + } else if (strncmp(token, "concurrency=", 12) == 0) { + a->children = atoi(token + 12); + } else if (strncmp(token, "cache=", 6) == 0) { + a->cache_size = atoi(token + 6); + } else { + break; + } + + token = strtok(NULL, w_space); } + if (a->negative_ttl == -1) - a->negative_ttl = a->ttl; + a->negative_ttl = a->ttl; /* Parse format */ p = &a->format; + while (token) { - external_acl_format *format; - - /* stop on first non-format token found */ - if (*token != '%') - break; - - format = cbdataAlloc(external_acl_format); - - if (strncmp(token, "%{", 2) == 0) { - /* header format */ - char *header, *member, *end; - header = token + 2; - end = strchr(header, '}'); - /* cut away the closing brace */ - if (end && strlen(end) == 1) - *end = '\0'; - else - self_destruct(); - - member = strchr(header, ':'); - if (member) { - /* Split in header and member */ - *member++ = '\0'; - if (!isalnum(*member)) - format->separator = *member++; - else - format->separator = ','; - format->member = xstrdup(member); - format->type = _external_acl_format::EXT_ACL_HEADER_MEMBER; - } else { - format->type = _external_acl_format::EXT_ACL_HEADER; - } - format->header = xstrdup(header); - format->header_id = httpHeaderIdByNameDef(header, strlen(header)); - if (format->header_id != -1) { - if (member) - format->type = _external_acl_format::EXT_ACL_HEADER_ID_MEMBER; - else - format->type = _external_acl_format::EXT_ACL_HEADER_ID; - } - } else if (strcmp(token, "%LOGIN") == 0) { - format->type = _external_acl_format::EXT_ACL_LOGIN; - a->require_auth = 1; - } + external_acl_format *format; + + /* stop on first non-format token found */ + + if (*token != '%') + break; + + format = cbdataAlloc(external_acl_format); + + if (strncmp(token, "%{", 2) == 0) { + /* header format */ + char *header, *member, *end; + header = token + 2; + end = strchr(header, '}'); + /* cut away the closing brace */ + + if (end && strlen(end) == 1) + *end = '\0'; + else + self_destruct(); + + member = strchr(header, ':'); + + if (member) { + /* Split in header and member */ + *member++ = '\0'; + + if (!isalnum(*member)) + format->separator = *member++; + else + format->separator = ','; + + format->member = xstrdup(member); + + format->type = _external_acl_format::EXT_ACL_HEADER_MEMBER; + } else { + format->type = _external_acl_format::EXT_ACL_HEADER; + } + + format->header = xstrdup(header); + format->header_id = httpHeaderIdByNameDef(header, strlen(header)); + + if (format->header_id != -1) { + if (member) + format->type = _external_acl_format::EXT_ACL_HEADER_ID_MEMBER; + else + format->type = _external_acl_format::EXT_ACL_HEADER_ID; + } + } else if (strcmp(token, "%LOGIN") == 0) { + format->type = _external_acl_format::EXT_ACL_LOGIN; + a->require_auth = 1; + } + #if USE_IDENT - else if (strcmp(token, "%IDENT") == 0) - format->type = _external_acl_format::EXT_ACL_IDENT; + else if (strcmp(token, "%IDENT") == 0) + format->type = _external_acl_format::EXT_ACL_IDENT; + #endif - else if (strcmp(token, "%SRC") == 0) - format->type = _external_acl_format::EXT_ACL_SRC; - else if (strcmp(token, "%DST") == 0) - format->type = _external_acl_format::EXT_ACL_DST; - else if (strcmp(token, "%PROTO") == 0) - format->type = _external_acl_format::EXT_ACL_PROTO; - else if (strcmp(token, "%PORT") == 0) - format->type = _external_acl_format::EXT_ACL_PORT; - else if (strcmp(token, "%PATH") == 0) - format->type = _external_acl_format::EXT_ACL_PATH; - else if (strcmp(token, "%METHOD") == 0) - format->type = _external_acl_format::EXT_ACL_METHOD; + + else if (strcmp(token, "%SRC") == 0) + format->type = _external_acl_format::EXT_ACL_SRC; + else if (strcmp(token, "%DST") == 0) + format->type = _external_acl_format::EXT_ACL_DST; + else if (strcmp(token, "%PROTO") == 0) + format->type = _external_acl_format::EXT_ACL_PROTO; + else if (strcmp(token, "%PORT") == 0) + format->type = _external_acl_format::EXT_ACL_PORT; + else if (strcmp(token, "%PATH") == 0) + format->type = _external_acl_format::EXT_ACL_PATH; + else if (strcmp(token, "%METHOD") == 0) + format->type = _external_acl_format::EXT_ACL_METHOD; + #if USE_SSL - else if (strncmp(token, "%USER_CERT_", 11)) { - format->type = _external_acl_format::EXT_ACL_USER_CERT; - format->header = xstrdup(token + 11); - } else if (strncmp(token, "%CA_CERT_", 11)) { - format->type = _external_acl_format::EXT_ACL_USER_CERT; - format->header = xstrdup(token + 11); - } + + else if (strncmp(token, "%USER_CERT_", 11)) { + format->type = _external_acl_format::EXT_ACL_USER_CERT; + format->header = xstrdup(token + 11); + } else if (strncmp(token, "%CA_CERT_", 11)) { + format->type = _external_acl_format::EXT_ACL_USER_CERT; + format->header = xstrdup(token + 11); + } + #endif - else { - self_destruct(); - } - *p = format; - p = &format->next; - token = strtok(NULL, w_space); + else { + self_destruct(); + } + + *p = format; + p = &format->next; + token = strtok(NULL, w_space); } /* There must be at least one format token */ if (!a->format) - self_destruct(); + self_destruct(); /* helper */ if (!token) - self_destruct(); + self_destruct(); + wordlistAdd(&a->cmdline, token); /* arguments */ parse_wordlist(&a->cmdline); while (*list) - list = &(*list)->next; + list = &(*list)->next; + *list = a; } @@ -308,55 +340,73 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl const external_acl *node; const external_acl_format *format; const wordlist *word; + for (node = list; node; node = node->next) { - storeAppendPrintf(sentry, "%s %s", name, node->name); - if (node->ttl != DEFAULT_EXTERNAL_ACL_TTL) - storeAppendPrintf(sentry, " ttl=%d", node->ttl); - if (node->negative_ttl != node->ttl) - storeAppendPrintf(sentry, " negative_ttl=%d", node->negative_ttl); - if (node->children != DEFAULT_EXTERNAL_ACL_CONCURRENCY) - storeAppendPrintf(sentry, " concurrency=%d", node->children); - for (format = node->format; format; format = format->next) { - switch (format->type) { - case _external_acl_format::EXT_ACL_HEADER: - case _external_acl_format::EXT_ACL_HEADER_ID: - storeAppendPrintf(sentry, " %%{%s}", format->header); - break; - case _external_acl_format::EXT_ACL_HEADER_MEMBER: - case _external_acl_format::EXT_ACL_HEADER_ID_MEMBER: - storeAppendPrintf(sentry, " %%{%s:%s}", format->header, format->member); - break; + storeAppendPrintf(sentry, "%s %s", name, node->name); + + if (node->ttl != DEFAULT_EXTERNAL_ACL_TTL) + storeAppendPrintf(sentry, " ttl=%d", node->ttl); + + if (node->negative_ttl != node->ttl) + storeAppendPrintf(sentry, " negative_ttl=%d", node->negative_ttl); + + if (node->children != DEFAULT_EXTERNAL_ACL_CONCURRENCY) + storeAppendPrintf(sentry, " concurrency=%d", node->children); + + for (format = node->format; format; format = format->next) { + switch (format->type) { + + case _external_acl_format::EXT_ACL_HEADER: + + case _external_acl_format::EXT_ACL_HEADER_ID: + storeAppendPrintf(sentry, " %%{%s}", format->header); + break; + + case _external_acl_format::EXT_ACL_HEADER_MEMBER: + + case _external_acl_format::EXT_ACL_HEADER_ID_MEMBER: + storeAppendPrintf(sentry, " %%{%s:%s}", format->header, format->member); + break; #define DUMP_EXT_ACL_TYPE(a) \ case _external_acl_format::EXT_ACL_##a: \ storeAppendPrintf(sentry, " %%%s", #a); \ break - DUMP_EXT_ACL_TYPE(LOGIN); + + DUMP_EXT_ACL_TYPE(LOGIN); #if USE_IDENT - DUMP_EXT_ACL_TYPE(IDENT); + + DUMP_EXT_ACL_TYPE(IDENT); #endif - DUMP_EXT_ACL_TYPE(SRC); - DUMP_EXT_ACL_TYPE(DST); - DUMP_EXT_ACL_TYPE(PROTO); - DUMP_EXT_ACL_TYPE(PORT); - DUMP_EXT_ACL_TYPE(PATH); - DUMP_EXT_ACL_TYPE(METHOD); + + DUMP_EXT_ACL_TYPE(SRC); + DUMP_EXT_ACL_TYPE(DST); + DUMP_EXT_ACL_TYPE(PROTO); + DUMP_EXT_ACL_TYPE(PORT); + DUMP_EXT_ACL_TYPE(PATH); + DUMP_EXT_ACL_TYPE(METHOD); #if USE_SSL - case _external_acl_format::EXT_ACL_USER_CERT: - storeAppendPrintf(sentry, " %%USER_CERT_%s", format->header); - break; - case _external_acl_format::EXT_ACL_CA_CERT: - storeAppendPrintf(sentry, " %%USER_CERT_%s", format->header); - break; + + case _external_acl_format::EXT_ACL_USER_CERT: + storeAppendPrintf(sentry, " %%USER_CERT_%s", format->header); + break; + + case _external_acl_format::EXT_ACL_CA_CERT: + storeAppendPrintf(sentry, " %%USER_CERT_%s", format->header); + break; #endif - case _external_acl_format::EXT_ACL_UNKNOWN: - case _external_acl_format::EXT_ACL_END: - fatal("unknown external_acl format error"); - break; - } - } - for (word = node->cmdline; word; word = word->next) - storeAppendPrintf(sentry, " %s", word->key); - storeAppendPrintf(sentry, "\n"); + + case _external_acl_format::EXT_ACL_UNKNOWN: + + case _external_acl_format::EXT_ACL_END: + fatal("unknown external_acl format error"); + break; + } + } + + for (word = node->cmdline; word; word = word->next) + storeAppendPrintf(sentry, " %s", word->key); + + storeAppendPrintf(sentry, "\n"); } } @@ -364,10 +414,10 @@ void free_externalAclHelper(external_acl ** list) { while (*list) { - external_acl *node = *list; - *list = node->next; - node->next = NULL; - cbdataFree(node); + external_acl *node = *list; + *list = node->next; + node->next = NULL; + cbdataFree(node); } } @@ -377,9 +427,10 @@ find_externalAclHelper(const char *name) external_acl *node; for (node = Config.externalAclHelperList; node; node = node->next) { - if (strcmp(node->name, name) == 0) - return node; + if (strcmp(node->name, name) == 0) + return node; } + return NULL; } @@ -388,7 +439,8 @@ find_externalAclHelper(const char *name) * external acl type */ -struct _external_acl_data { +struct _external_acl_data +{ external_acl *def; wordlist *arguments; }; @@ -408,19 +460,28 @@ aclParseExternal(void *dataptr) external_acl_data **datap = static_cast(dataptr); external_acl_data *data; char *token; + if (*datap) - self_destruct(); + self_destruct(); + CBDATA_INIT_TYPE_FREECB(external_acl_data, free_external_acl_data); + data = cbdataAlloc(external_acl_data); + token = strtok(NULL, w_space); + if (!token) - self_destruct(); + self_destruct(); + data->def = cbdataReference(find_externalAclHelper(token)); + if (!data->def) - self_destruct(); + self_destruct(); + while ((token = strtokFile())) { - wordlistAdd(&data->arguments, token); + wordlistAdd(&data->arguments, token); } + *datap = data; } @@ -439,40 +500,48 @@ aclMatchExternal(void *data, ACLChecklist * ch) const char *key = ""; debug(82, 9) ("aclMatchExternal: acl=\"%s\"\n", acl->def->name); entry = ch->extacl_entry; + if (entry) { - if (cbdataReferenceValid(entry) && entry->def == acl->def && - strcmp((char *)entry->key, key) == 0) { - /* Ours, use it.. */ - } else { - /* Not valid, or not ours.. get rid of it */ - cbdataReferenceDone(ch->extacl_entry); - entry = NULL; - } + if (cbdataReferenceValid(entry) && entry->def == acl->def && + strcmp((char *)entry->key, key) == 0) { + /* Ours, use it.. */ + } else { + /* Not valid, or not ours.. get rid of it */ + cbdataReferenceDone(ch->extacl_entry); + entry = NULL; + } } + if (!entry) { - if (acl->def->require_auth) { - int ti; - /* Make sure the user is authenticated */ - if ((ti = ch->authenticated()) != 1) { - debug(82, 2) ("aclMatchExternal: %s user not authenticated (%d)\n", acl->def->name, ti); - return ti; - } - } - key = makeExternalAclKey(ch, acl); - entry = static_cast(hash_lookup(acl->def->cache, key)); - if (entry && external_acl_entry_expired(acl->def, entry)) { - /* Expired entry, ignore */ - debug(82, 2) ("external_acl_cache_lookup: '%s' = expired\n", key); - entry = NULL; - } - ch->auth_user_request = NULL; + if (acl->def->require_auth) { + int ti; + /* Make sure the user is authenticated */ + + if ((ti = ch->authenticated()) != 1) { + debug(82, 2) ("aclMatchExternal: %s user not authenticated (%d)\n", acl->def->name, ti); + return ti; + } + } + + key = makeExternalAclKey(ch, acl); + entry = static_cast(hash_lookup(acl->def->cache, key)); + + if (entry && external_acl_entry_expired(acl->def, entry)) { + /* Expired entry, ignore */ + debug(82, 2) ("external_acl_cache_lookup: '%s' = expired\n", key); + entry = NULL; + } + + ch->auth_user_request = NULL; } + if (!entry) { - debug(82, 2) ("aclMatchExternal: %s(\"%s\") = lookup needed\n", acl->def->name, key); - ch->state[ACL_EXTERNAL] = ACL_LOOKUP_NEEDED; - ch->changeState (ExternalACLLookup::Instance()); - return 0; + debug(82, 2) ("aclMatchExternal: %s(\"%s\") = lookup needed\n", acl->def->name, key); + ch->state[ACL_EXTERNAL] = ACL_LOOKUP_NEEDED; + ch->changeState (ExternalACLLookup::Instance()); + return 0; } + external_acl_cache_touch(acl->def, entry); result = entry->result; debug(82, 2) ("aclMatchExternal: %s = %d\n", acl->def->name, result); @@ -480,8 +549,10 @@ aclMatchExternal(void *data, ACLChecklist * ch) * piggy backs on ident, and may fail if there is child proxies.. * Register the username for logging purposes */ + if (entry->user && cbdataReferenceValid(ch->conn()) && !ch->conn()->rfc931[0]) - xstrncpy(ch->conn()->rfc931, entry->user, USER_IDENT_SZ); + xstrncpy(ch->conn()->rfc931, entry->user, USER_IDENT_SZ); + return result; } @@ -494,9 +565,11 @@ aclDumpExternal(void *data) MemBuf mb; memBufDefInit(&mb); memBufPrintf(&mb, "%s", acl->def->name); + for (arg = acl->arguments; arg; arg = arg->next) { - memBufPrintf(&mb, " %s", arg->key); + memBufPrintf(&mb, " %s", arg->key); } + wordlistAdd(&result, mb.buf); memBufClean(&mb); return result; @@ -526,94 +599,130 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data) request_t *request = ch->request; String sb = StringNull; memBufReset(&mb); + for (format = acl_data->def->format; format; format = format->next) { - const char *str = NULL; - switch (format->type) { - case _external_acl_format::EXT_ACL_LOGIN: - str = authenticateUserRequestUsername(request->auth_user_request); - break; + const char *str = NULL; + + switch (format->type) { + + case _external_acl_format::EXT_ACL_LOGIN: + str = authenticateUserRequestUsername(request->auth_user_request); + break; #if USE_IDENT - case _external_acl_format::EXT_ACL_IDENT: - str = ch->rfc931; - if (!str) { - ch->changeState(IdentLookup::Instance()); - return NULL; - } - break; + + case _external_acl_format::EXT_ACL_IDENT: + str = ch->rfc931; + + if (!str) { + ch->changeState(IdentLookup::Instance()); + return NULL; + } + + break; #endif - case _external_acl_format::EXT_ACL_SRC: - str = inet_ntoa(ch->src_addr); - break; - case _external_acl_format::EXT_ACL_DST: - str = request->host; - break; - case _external_acl_format::EXT_ACL_PROTO: - str = ProtocolStr[request->protocol]; - break; - case _external_acl_format::EXT_ACL_PORT: - snprintf(buf, sizeof(buf), "%d", request->port); - str = buf; - break; - case _external_acl_format::EXT_ACL_PATH: - str = request->urlpath.buf(); - break; - case _external_acl_format::EXT_ACL_METHOD: - str = RequestMethodStr[request->method]; - break; - case _external_acl_format::EXT_ACL_HEADER: - sb = httpHeaderGetByName(&request->header, format->header); - str = sb.buf(); - break; - case _external_acl_format::EXT_ACL_HEADER_ID: - sb = httpHeaderGetStrOrList(&request->header, format->header_id); - str = sb.buf(); - break; - case _external_acl_format::EXT_ACL_HEADER_MEMBER: - sb = httpHeaderGetByNameListMember(&request->header, format->header, format->member, format->separator); - str = sb.buf(); - break; - case _external_acl_format::EXT_ACL_HEADER_ID_MEMBER: - sb = httpHeaderGetListMember(&request->header, format->header_id, format->member, format->separator); - str = sb.buf(); - break; + + case _external_acl_format::EXT_ACL_SRC: + str = inet_ntoa(ch->src_addr); + break; + + case _external_acl_format::EXT_ACL_DST: + str = request->host; + break; + + case _external_acl_format::EXT_ACL_PROTO: + str = ProtocolStr[request->protocol]; + break; + + case _external_acl_format::EXT_ACL_PORT: + snprintf(buf, sizeof(buf), "%d", request->port); + str = buf; + break; + + case _external_acl_format::EXT_ACL_PATH: + str = request->urlpath.buf(); + break; + + case _external_acl_format::EXT_ACL_METHOD: + str = RequestMethodStr[request->method]; + break; + + case _external_acl_format::EXT_ACL_HEADER: + sb = httpHeaderGetByName(&request->header, format->header); + str = sb.buf(); + break; + + case _external_acl_format::EXT_ACL_HEADER_ID: + sb = httpHeaderGetStrOrList(&request->header, format->header_id); + str = sb.buf(); + break; + + case _external_acl_format::EXT_ACL_HEADER_MEMBER: + sb = httpHeaderGetByNameListMember(&request->header, format->header, format->member, format->separator); + str = sb.buf(); + break; + + case _external_acl_format::EXT_ACL_HEADER_ID_MEMBER: + sb = httpHeaderGetListMember(&request->header, format->header_id, format->member, format->separator); + str = sb.buf(); + break; #if USE_SSL - case _external_acl_format::EXT_ACL_USER_CERT: - if (cbdataReferenceValid(ch->conn())) { - SSL *ssl = fd_table[ch->conn()->fd].ssl; - if (ssl) - str = sslGetUserAttribute(ssl, format->header); - } - break; - case _external_acl_format::EXT_ACL_CA_CERT: - if (cbdataReferenceValid(ch->conn())) { - SSL *ssl = fd_table[ch->conn()->fd].ssl; - if (ssl) - str = sslGetCAAttribute(ssl, format->header); - } - break; + + case _external_acl_format::EXT_ACL_USER_CERT: + + if (cbdataReferenceValid(ch->conn())) { + SSL *ssl = fd_table[ch->conn()->fd].ssl; + + if (ssl) + str = sslGetUserAttribute(ssl, format->header); + } + + break; + + case _external_acl_format::EXT_ACL_CA_CERT: + + if (cbdataReferenceValid(ch->conn())) { + SSL *ssl = fd_table[ch->conn()->fd].ssl; + + if (ssl) + str = sslGetCAAttribute(ssl, format->header); + } + + break; #endif - case _external_acl_format::EXT_ACL_UNKNOWN: - case _external_acl_format::EXT_ACL_END: - fatal("unknown external_acl format error"); - break; - } - if (str) - if (!*str) - str = NULL; - if (!str) - str = "-"; - if (!first) - memBufAppend(&mb, " ", 1); - strwordquote(&mb, str); - sb.clean(); - first = 0; + + case _external_acl_format::EXT_ACL_UNKNOWN: + + case _external_acl_format::EXT_ACL_END: + fatal("unknown external_acl format error"); + break; + } + + if (str) + if (!*str) + str = NULL; + + if (!str) + str = "-"; + + if (!first) + memBufAppend(&mb, " ", 1); + + strwordquote(&mb, str); + + sb.clean(); + + first = 0; } + for (arg = acl_data->arguments; arg; arg = arg->next) { - if (!first) - memBufAppend(&mb, " ", 1); - strwordquote(&mb, arg->key); - first = 0; + if (!first) + memBufAppend(&mb, " ", 1); + + strwordquote(&mb, arg->key); + + first = 0; } + return mb.buf; } @@ -621,11 +730,11 @@ static int external_acl_entry_expired(external_acl * def, external_acl_entry * entry) { if (entry->date + (entry->result == 1 ? def->ttl : def->negative_ttl) < squid_curtime) - return 1; + return 1; else - return 0; + return 0; } - + static void free_external_acl_entry(void *data) { @@ -640,31 +749,38 @@ external_acl_cache_add(external_acl * def, const char *key, int result, char *us { external_acl_entry *entry = static_cast(hash_lookup(def->cache, key)); debug(82, 2) ("external_acl_cache_add: Adding '%s' = %d\n", key, result); + if (entry) { - debug(82, 3) ("external_acl_cache_add: updating existing entry\n"); - entry->date = squid_curtime; - entry->result = result; - safe_free(entry->user); - safe_free(entry->error); - if (user) - entry->user = xstrdup(user); - if (error) - entry->error = xstrdup(error); - external_acl_cache_touch(def, entry); - return entry; + debug(82, 3) ("external_acl_cache_add: updating existing entry\n"); + entry->date = squid_curtime; + entry->result = result; + safe_free(entry->user); + safe_free(entry->error); + + if (user) + entry->user = xstrdup(user); + + if (error) + entry->error = xstrdup(error); + + external_acl_cache_touch(def, entry); + + return entry; } + CBDATA_INIT_TYPE_FREECB(external_acl_entry, free_external_acl_entry); /* Maintain cache size */ + if (def->cache_size && def->cache_entries >= def->cache_size) - external_acl_cache_delete(def, static_cast(def->lru_list.tail->data)); + external_acl_cache_delete(def, static_cast(def->lru_list.tail->data)); entry = cbdataAlloc(external_acl_entry); entry->key = xstrdup(key); entry->date = squid_curtime; entry->result = result; if (user) - entry->user = xstrdup(user); + entry->user = xstrdup(user); if (error) - entry->error = xstrdup(error); + entry->error = xstrdup(error); entry->def = def; hash_join(def->cache, entry); dlinkAdd(entry, &entry->lru, &def->lru_list); @@ -686,7 +802,9 @@ external_acl_cache_delete(external_acl * def, external_acl_entry * entry) */ typedef struct _externalAclState externalAclState; -struct _externalAclState { + +struct _externalAclState +{ EAH *callback; void *callback_data; char *key; @@ -746,43 +864,51 @@ externalAclHandleReply(void *data, char *reply) debug(82, 2) ("externalAclHandleReply: reply=\"%s\"\n", reply); if (reply) { - status = strwordtok(reply, &t); - if (status && strcmp(status, "OK") == 0) - result = 1; - - while ((token = strwordtok(NULL, &t))) { - value = strchr(token, '='); - if (value) { - *value++ = '\0'; /* terminate the token, and move up to the value */ - if (strcmp(token, "user") == 0) - user = value; - else if (strcmp(token, "error") == 0) - error = value; - } - } + status = strwordtok(reply, &t); + + if (status && strcmp(status, "OK") == 0) + result = 1; + + while ((token = strwordtok(NULL, &t))) { + value = strchr(token, '='); + + if (value) { + *value++ = '\0'; /* terminate the token, and move up to the value */ + + if (strcmp(token, "user") == 0) + user = value; + else if (strcmp(token, "error") == 0) + error = value; + } + } } + dlinkDelete(&state->list, &state->def->queue); + if (cbdataReferenceValid(state->def)) { - if (reply) - entry = external_acl_cache_add(state->def, state->key, result, user, error); - else { - entry = (external_acl_entry *)hash_lookup(state->def->cache, state->key); - if (entry) - external_acl_cache_delete(state->def, entry); - } + if (reply) + entry = external_acl_cache_add(state->def, state->key, result, user, error); + else { + entry = (external_acl_entry *)hash_lookup(state->def->cache, state->key); + + if (entry) + external_acl_cache_delete(state->def, entry); + } } else - entry = NULL; + entry = NULL; do { - void *cbdata; - cbdataReferenceDone(state->def); + void *cbdata; + cbdataReferenceDone(state->def); + + if (cbdataReferenceValidDone(state->callback_data, &cbdata)) + state->callback(cbdata, entry); + + next = state->queue; - if (cbdataReferenceValidDone(state->callback_data, &cbdata)) - state->callback(cbdata, entry); + cbdataFree(state); - next = state->queue; - cbdataFree(state); - state = next; + state = next; } while (state); } @@ -796,53 +922,69 @@ ACL::ExternalAclLookup(ACLChecklist * ch, ACL * me, EAH * callback, void *callba external_acl_entry *entry = static_cast(hash_lookup(def->cache, key)); externalAclState *state; debug(82, 2) ("externalAclLookup: lookup in '%s' for '%s'\n", def->name, key); + if (!key) { - debug(82, 1) ("externalAclLookup: lookup in '%s', prerequisit failure\n", def->name); - callback(callback_data, NULL); - return; + debug(82, 1) ("externalAclLookup: lookup in '%s', prerequisit failure\n", def->name); + callback(callback_data, NULL); + return; } + state = cbdataAlloc(externalAclState); state->def = cbdataReference(def); state->callback = callback; state->callback_data = cbdataReference(callback_data); state->key = xstrdup(key); + if (entry && !external_acl_entry_expired(def, entry)) { - if (entry->result == -1) { - /* There is a pending lookup. Hook into it */ - dlink_node *node; - for (node = def->queue.head; node; node = node->next) { - externalAclState *oldstate = static_cast(node->data); - if (strcmp(state->key, oldstate->key) == 0) { - state->queue = oldstate->queue; - oldstate->queue = state; - return; - } - } - } else { - /* There is a cached valid result.. use it */ - /* This should not really happen, but what the heck.. */ - callback(callback_data, entry); - cbdataFree(state); - return; - } + if (entry->result == -1) { + /* There is a pending lookup. Hook into it */ + dlink_node *node; + + for (node = def->queue.head; node; node = node->next) { + externalAclState *oldstate = static_cast(node->data); + + if (strcmp(state->key, oldstate->key) == 0) { + state->queue = oldstate->queue; + oldstate->queue = state; + return; + } + } + } else { + /* There is a cached valid result.. use it */ + /* This should not really happen, but what the heck.. */ + callback(callback_data, entry); + cbdataFree(state); + return; + } } + /* Check for queue overload */ if (def->theHelper->stats.queue_size >= def->theHelper->n_running) { - int result = -1; - external_acl_entry *entry = static_cast(hash_lookup(def->cache, key)); - debug(82, 1) ("externalAclLookup: '%s' queue overload\n", def->name); - if (entry) - result = entry->result; - cbdataFree(state); - callback(callback_data, entry); - return; + int result = -1; + external_acl_entry *entry = static_cast(hash_lookup(def->cache, key)); + debug(82, 1) ("externalAclLookup: '%s' queue overload\n", def->name); + + if (entry) + result = entry->result; + + cbdataFree(state); + + callback(callback_data, entry); + + return; } + /* Send it off to the helper */ memBufDefInit(&buf); + memBufPrintf(&buf, "%s\n", key); + helperSubmit(def->theHelper, buf.buf, externalAclHandleReply, state); + external_acl_cache_add(def, key, -1, NULL, NULL); + dlinkAdd(state, &state->list, &def->queue); + memBufClean(&buf); } @@ -852,10 +994,10 @@ externalAclStats(StoreEntry * sentry) external_acl *p; for (p = Config.externalAclHelperList; p; p = p->next) { - storeAppendPrintf(sentry, "External ACL Statistics: %s\n", p->name); - storeAppendPrintf(sentry, "Cache size: %d\n", p->cache->count); - helperStats(sentry, p->theHelper); - storeAppendPrintf(sentry, "\n"); + storeAppendPrintf(sentry, "External ACL Statistics: %s\n", p->name); + storeAppendPrintf(sentry, "Cache size: %d\n", p->cache->count); + helperStats(sentry, p->theHelper); + storeAppendPrintf(sentry, "\n"); } } @@ -866,21 +1008,27 @@ externalAclInit(void) external_acl *p; for (p = Config.externalAclHelperList; p; p = p->next) { - if (!p->cache) - p->cache = hash_create((HASHCMP *) strcmp, hashPrime(1024), hash4); - if (!p->theHelper) - p->theHelper = helperCreate(p->name); - p->theHelper->cmdline = p->cmdline; - p->theHelper->n_to_start = p->children; - p->theHelper->ipc_type = IPC_TCP_SOCKET; - helperOpenServers(p->theHelper); + if (!p->cache) + p->cache = hash_create((HASHCMP *) strcmp, hashPrime(1024), hash4); + + if (!p->theHelper) + p->theHelper = helperCreate(p->name); + + p->theHelper->cmdline = p->cmdline; + + p->theHelper->n_to_start = p->children; + + p->theHelper->ipc_type = IPC_TCP_SOCKET; + + helperOpenServers(p->theHelper); } + if (firstTimeInit) { - firstTimeInit = 0; - cachemgrRegister("external_acl", - "External ACL stats", - externalAclStats, 0, 1); - CBDATA_INIT_TYPE_FREECB(externalAclState, free_externalAclState); + firstTimeInit = 0; + cachemgrRegister("external_acl", + "External ACL stats", + externalAclStats, 0, 1); + CBDATA_INIT_TYPE_FREECB(externalAclState, free_externalAclState); } } @@ -888,8 +1036,9 @@ void externalAclShutdown(void) { external_acl *p; + for (p = Config.externalAclHelperList; p; p = p->next) { - helperShutdown(p->theHelper); + helperShutdown(p->theHelper); } } diff --git a/src/fd.cc b/src/fd.cc index c3cbe32b1e..a9042981dc 100644 --- a/src/fd.cc +++ b/src/fd.cc @@ -1,6 +1,6 @@ /* - * $Id: fd.cc,v 1.47 2003/02/02 13:27:43 robertc Exp $ + * $Id: fd.cc,v 1.48 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 51 Filedescriptor Functions * AUTHOR: Duane Wessels @@ -46,14 +46,14 @@ int file_write_method(int, const char *, int); #endif const char *fdTypeStr[] = -{ - "None", - "Log", - "File", - "Socket", - "Pipe", - "Unknown" -}; + { + "None", + "Log", + "File", + "Socket", + "Pipe", + "Unknown" + }; static void fdUpdateBiggest(int fd, int); @@ -61,35 +61,41 @@ static void fdUpdateBiggest(int fd, int opening) { if (fd < Biggest_FD) - return; + return; + assert(fd < Squid_MaxFD); + if (fd > Biggest_FD) { - /* - * assert that we are not closing a FD bigger than - * our known biggest FD - */ - assert(opening); - Biggest_FD = fd; - return; + /* + * assert that we are not closing a FD bigger than + * our known biggest FD + */ + assert(opening); + Biggest_FD = fd; + return; } + /* if we are here, then fd == Biggest_FD */ /* * assert that we are closing the biggest FD; we can't be * re-opening it */ assert(!opening); + while (!fd_table[Biggest_FD].flags.open) - Biggest_FD--; + Biggest_FD--; } void fd_close(int fd) { fde *F = &fd_table[fd]; + if (F->type == FD_FILE) { - assert(F->read_handler == NULL); - assert(F->write_handler == NULL); + assert(F->read_handler == NULL); + assert(F->write_handler == NULL); } + debug(51, 3) ("fd_close FD %d %s\n", fd, F->desc); commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0); @@ -125,6 +131,7 @@ file_write_method(int fd, const char *buf, int len) { return (_write(fd, buf, len)); } + #else int default_read_method(int fd, char *buf, int len) @@ -137,6 +144,7 @@ default_write_method(int fd, const char *buf, int len) { return (write(fd, buf, len)); } + #endif void @@ -145,36 +153,50 @@ fd_open(int fd, unsigned int type, const char *desc) fde *F; assert(fd >= 0); F = &fd_table[fd]; + if (F->flags.open) { - debug(51, 1) ("WARNING: Closing open FD %4d\n", fd); - fd_close(fd); + debug(51, 1) ("WARNING: Closing open FD %4d\n", fd); + fd_close(fd); } + assert(!F->flags.open); debug(51, 3) ("fd_open FD %d %s\n", fd, desc); F->type = type; F->flags.open = 1; #ifdef _SQUID_MSWIN_ + switch (type) { + case FD_SOCKET: + case FD_PIPE: - F->read_method = &socket_read_method; - F->write_method = &socket_write_method; - break; + F->read_method = &socket_read_method; + F->write_method = &socket_write_method; + break; + case FD_FILE: + case FD_LOG: - F->read_method = &file_read_method; - F->write_method = &file_write_method; - break; + F->read_method = &file_read_method; + F->write_method = &file_write_method; + break; + default: - fatalf("fd_open(): unknown FD type - FD#: %i, type: %u, desc %s\n", fd, type, desc); + fatalf("fd_open(): unknown FD type - FD#: %i, type: %u, desc %s\n", fd, type, desc); } + #else F->read_method = &default_read_method; + F->write_method = &default_write_method; + #endif + fdUpdateBiggest(fd, 1); + if (desc) - xstrncpy(F->desc, desc, FD_DESC_SZ); + xstrncpy(F->desc, desc, FD_DESC_SZ); + Number_FD++; } @@ -189,13 +211,16 @@ void fd_bytes(int fd, int len, unsigned int type) { fde *F = &fd_table[fd]; + if (len < 0) - return; + return; + assert(type == FD_READ || type == FD_WRITE); + if (type == FD_READ) - F->bytes_read += len; + F->bytes_read += len; else - F->bytes_written += len; + F->bytes_written += len; } void @@ -209,17 +234,21 @@ fdDumpOpen(void) { int i; fde *F; + for (i = 0; i < Squid_MaxFD; i++) { - F = &fd_table[i]; - if (!F->flags.open) - continue; - if (i == fileno(debug_log)) - continue; - debug(51, 1) ("Open FD %-10s %4d %s\n", - F->bytes_read && F->bytes_written ? "READ/WRITE" : - F->bytes_read ? "READING" : - F->bytes_written ? "WRITING" : null_string, - i, F->desc); + F = &fd_table[i]; + + if (!F->flags.open) + continue; + + if (i == fileno(debug_log)) + continue; + + debug(51, 1) ("Open FD %-10s %4d %s\n", + F->bytes_read && F->bytes_written ? "READ/WRITE" : + F->bytes_read ? "READING" : + F->bytes_written ? "WRITING" : null_string, + i, F->desc); } } @@ -239,21 +268,27 @@ fdAdjustReserved(void) /* * don't update too frequently */ + if (last + 5 > squid_curtime) - return; + return; + /* * Calculate a new reserve, based on current usage and a small extra */ newReserve = Squid_MaxFD - Number_FD + XMIN(25, Squid_MaxFD / 16); + if (newReserve <= RESERVED_FD) - return; + return; + x = Squid_MaxFD - 20 - XMIN(25, Squid_MaxFD / 16); + if (newReserve > x) { - /* perhaps this should be fatal()? -DW */ - debug(51, 0) ("WARNING: This machine has a serious shortage of filedescriptors.\n"); - newReserve = x; + /* perhaps this should be fatal()? -DW */ + debug(51, 0) ("WARNING: This machine has a serious shortage of filedescriptors.\n"); + newReserve = x; } + debug(51, 0) ("Reserved FD adjusted from %d to %d due to failures\n", - RESERVED_FD, newReserve); + RESERVED_FD, newReserve); RESERVED_FD = newReserve; } diff --git a/src/fde.cc b/src/fde.cc index dc27ddb988..5f025ef0eb 100644 --- a/src/fde.cc +++ b/src/fde.cc @@ -1,6 +1,6 @@ /* - * $Id: fde.cc,v 1.1 2003/01/23 00:37:20 robertc Exp $ + * $Id: fde.cc,v 1.2 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section ?? FDE * AUTHOR: Robert Collins @@ -42,7 +42,8 @@ bool fde::readPending(int fdNumber) { if (type == FD_SOCKET) - return comm_has_pending_read(fdNumber); + return comm_has_pending_read(fdNumber); + return read_handler ? true : false ; } @@ -50,17 +51,18 @@ void fde::dumpStats (StoreEntry &dumpEntry, int fdNumber) { if (!flags.open) - return; + return; + storeAppendPrintf(&dumpEntry, "%4d %-6.6s %4d %7d%c %7d%c %-21s %s\n", - fdNumber, - fdTypeStr[type], - timeout_handler ? (int) (timeout - squid_curtime) / 60 : 0, - bytes_read, - readPending(fdNumber) ? '*' : ' ', - bytes_written, - write_handler ? '*' : ' ', - remoteAddr(), - desc); + fdNumber, + fdTypeStr[type], + timeout_handler ? (int) (timeout - squid_curtime) / 60 : 0, + bytes_read, + readPending(fdNumber) ? '*' : ' ', + bytes_written, + write_handler ? '*' : ' ', + remoteAddr(), + desc); } void @@ -69,14 +71,15 @@ fde::DumpStats (StoreEntry *dumpEntry) int i; storeAppendPrintf(dumpEntry, "Active file descriptors:\n"); storeAppendPrintf(dumpEntry, "%-4s %-6s %-4s %-7s* %-7s* %-21s %s\n", - "File", - "Type", - "Tout", - "Nread", - "Nwrite", - "Remote Address", - "Description"); + "File", + "Type", + "Tout", + "Nread", + "Nwrite", + "Remote Address", + "Description"); storeAppendPrintf(dumpEntry, "---- ------ ---- -------- -------- --------------------- ------------------------------\n"); + for (i = 0; i < Squid_MaxFD; i++) { fd_table[i].dumpStats(*dumpEntry, i); } @@ -86,9 +89,12 @@ char const * fde::remoteAddr() const { LOCAL_ARRAY(char, buf, 32); + if (type != FD_SOCKET) - return null_string; + return null_string; + snprintf(buf, 32, "%s.%d", ipaddr, (int) remote_port); + return buf; } diff --git a/src/fde.h b/src/fde.h index 058ef5b556..a19630ade5 100644 --- a/src/fde.h +++ b/src/fde.h @@ -1,6 +1,6 @@ /* - * $Id: fde.h,v 1.1 2003/01/23 00:37:20 robertc Exp $ + * $Id: fde.h,v 1.2 2003/02/21 22:50:08 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -34,10 +34,12 @@ #ifndef SQUID_FDE_H #define SQUID_FDE_H -class fde { +class fde +{ + public: static void DumpStats (StoreEntry *); - + char const *remoteAddr() const; void dumpStats (StoreEntry &, int); bool readPending(int); @@ -45,27 +47,57 @@ public: unsigned int type; u_short local_port; u_short remote_port; + struct in_addr local_addr; unsigned char tos; char ipaddr[16]; /* dotted decimal address of peer */ char desc[FD_DESC_SZ]; - struct { - unsigned int open:1; - unsigned int close_request:1; - unsigned int write_daemon:1; - unsigned int closing:1; - unsigned int socket_eof:1; - unsigned int nolinger:1; - unsigned int nonblocking:1; - unsigned int ipc:1; - unsigned int called_connect:1; - unsigned int nodelay:1; - unsigned int close_on_exec:1; - unsigned int read_pending:1; - } flags; + + struct + { + +unsigned int open: + 1; + +unsigned int close_request: + 1; + +unsigned int write_daemon: + 1; + +unsigned int closing: + 1; + +unsigned int socket_eof: + 1; + +unsigned int nolinger: + 1; + +unsigned int nonblocking: + 1; + +unsigned int ipc: + 1; + +unsigned int called_connect: + 1; + +unsigned int nodelay: + 1; + +unsigned int close_on_exec: + 1; + +unsigned int read_pending: + 1; + } + + flags; int bytes_read; int bytes_written; int uses; /* ie # req's over persistent conn */ + struct _fde_disk disk; PF *read_handler; void *read_data; @@ -82,8 +114,11 @@ public: READ_HANDLER *read_method; WRITE_HANDLER *write_method; #if USE_SSL + SSL *ssl; - int ssl_shutdown:1; + +int ssl_shutdown: + 1; #endif }; diff --git a/src/filemap.cc b/src/filemap.cc index 3c1c55c69d..df35446973 100644 --- a/src/filemap.cc +++ b/src/filemap.cc @@ -1,6 +1,6 @@ /* - * $Id: filemap.cc,v 1.41 2003/01/23 00:37:20 robertc Exp $ + * $Id: filemap.cc,v 1.42 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 8 Swap File Bitmap * AUTHOR: Harvest Derived @@ -63,7 +63,7 @@ file_map_create(void) fm->nwords = fm->max_n_files >> LONG_BIT_SHIFT; debug(8, 3) ("file_map_create: creating space for %d files\n", fm->max_n_files); debug(8, 5) ("--> %d words of %d bytes each\n", - fm->nwords, (int) sizeof(*fm->file_map)); + fm->nwords, (int) sizeof(*fm->file_map)); fm->file_map = (unsigned long *)xcalloc(fm->nwords, sizeof(*fm->file_map)); /* XXX account fm->file_map */ return fm; @@ -89,10 +89,14 @@ int file_map_bit_set(fileMap * fm, int file_number) { unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); + while (file_number >= fm->max_n_files) - file_map_grow(fm); + file_map_grow(fm); + fm->file_map[file_number >> LONG_BIT_SHIFT] |= bitmask; + fm->n_files_in_map++; + return file_number; } @@ -114,8 +118,10 @@ int file_map_bit_test(fileMap * fm, int file_number) { unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); + if (file_number >= fm->max_n_files) - return 0; + return 0; + /* be sure the return value is an int, not a u_long */ return (fm->file_map[file_number >> LONG_BIT_SHIFT] & bitmask ? 1 : 0); } @@ -126,22 +132,30 @@ file_map_allocate(fileMap * fm, int suggestion) int word; int bit; int count; + if (suggestion >= fm->max_n_files) - suggestion = 0; + suggestion = 0; + if (!file_map_bit_test(fm, suggestion)) - return suggestion; + return suggestion; + word = suggestion >> LONG_BIT_SHIFT; + for (count = 0; count < fm->nwords; count++) { - if (fm->file_map[word] != ALL_ONES) - break; - word = (word + 1) % fm->nwords; + if (fm->file_map[word] != ALL_ONES) + break; + + word = (word + 1) % fm->nwords; } + for (bit = 0; bit < BITS_IN_A_LONG; bit++) { - suggestion = ((unsigned long) word << LONG_BIT_SHIFT) | bit; - if (!file_map_bit_test(fm, suggestion)) { - return suggestion; - } + suggestion = ((unsigned long) word << LONG_BIT_SHIFT) | bit; + + if (!file_map_bit_test(fm, suggestion)) { + return suggestion; + } } + debug(8, 3) ("growing from file_map_allocate\n"); file_map_grow(fm); return file_map_allocate(fm, fm->max_n_files >> 1); @@ -164,9 +178,10 @@ main(argc, argv) fm = file_map_create(TEST_SIZE); for (i = 0; i < TEST_SIZE; ++i) { - file_map_bit_set(i); - assert(file_map_bit_test(i)); - file_map_bit_reset(i); + file_map_bit_set(i); + assert(file_map_bit_test(i)); + file_map_bit_reset(i); } } + #endif diff --git a/src/forward.cc b/src/forward.cc index 4258505661..ad3e257fc1 100644 --- a/src/forward.cc +++ b/src/forward.cc @@ -1,6 +1,6 @@ /* - * $Id: forward.cc,v 1.96 2003/02/21 19:53:01 hno Exp $ + * $Id: forward.cc,v 1.97 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -69,9 +69,11 @@ static peer * fwdStateServerPeer(FwdState * fwdState) { if (NULL == fwdState) - return NULL; + return NULL; + if (NULL == fwdState->servers) - return NULL; + return NULL; + return fwdState->servers->_peer; } @@ -91,42 +93,58 @@ fwdStateFree(FwdState * fwdState) debug(17, 3) ("fwdStateFree: %p\n", fwdState); assert(e->mem_obj); #if URL_CHECKSUM_DEBUG + e->mem_obj->checkUrlChecksum(); #endif #if WIP_FWD_LOG + fwdLog(fwdState); #endif + if (e->store_status == STORE_PENDING) { - if (e->isEmpty()) { - assert(fwdState->err); - errorAppendEntry(e, fwdState->err); - fwdState->err = NULL; - } else { - EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); - e->complete(); - storeReleaseRequest(e); - } + if (e->isEmpty()) { + assert(fwdState->err); + errorAppendEntry(e, fwdState->err); + fwdState->err = NULL; + } else { + EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); + e->complete(); + storeReleaseRequest(e); + } } + if (storePendingNClients(e) > 0) - assert(!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)); + assert(!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)); + p = fwdStateServerPeer(fwdState); + fwdServersFree(&fwdState->servers); + requestUnlink(fwdState->request); + fwdState->request = NULL; + if (fwdState->err) - errorStateFree(fwdState->err); + errorStateFree(fwdState->err); + storeUnregisterAbort(e); + storeUnlockObject(e); + fwdState->entry = NULL; + sfd = fwdState->server_fd; + if (sfd > -1) { - comm_remove_close_handler(sfd, fwdServerClosed, fwdState); - fwdState->server_fd = -1; - debug(17, 3) ("fwdStateFree: closing FD %d\n", sfd); - comm_close(sfd); - if (p) - p->stats.conn_open--; + comm_remove_close_handler(sfd, fwdServerClosed, fwdState); + fwdState->server_fd = -1; + debug(17, 3) ("fwdStateFree: closing FD %d\n", sfd); + comm_close(sfd); + + if (p) + p->stats.conn_open--; } + cbdataFree(fwdState); } @@ -134,19 +152,26 @@ static int fwdCheckRetry(FwdState * fwdState) { if (shutting_down) - return 0; + return 0; + if (fwdState->entry->store_status != STORE_PENDING) - return 0; + return 0; + if (!fwdState->entry->isEmpty()) - return 0; + return 0; + if (fwdState->n_tries > 10) - return 0; + return 0; + if (squid_curtime - fwdState->start > Config.Timeout.connect) - return 0; + return 0; + if (fwdState->flags.dont_retry) - return 0; + return 0; + if (fwdState->request->flags.body_sent) - return 0; + return 0; + return 1; } @@ -157,34 +182,43 @@ fwdServerClosed(int fd, void *data) debug(17, 2) ("fwdServerClosed: FD %d %s\n", fd, storeUrl(fwdState->entry)); assert(fwdState->server_fd == fd); fwdState->server_fd = -1; + if (fwdCheckRetry(fwdState)) { - debug(17, 3) ("fwdServerClosed: re-forwarding (%d tries, %d secs)\n", - fwdState->n_tries, - (int) (squid_curtime - fwdState->start)); - if (fwdState->servers->next) { - /* use next, or cycle if origin server isn't last */ - FwdServer *fs = fwdState->servers; - FwdServer **T, *T2 = NULL; - fwdState->servers = fs->next; - for (T = &fwdState->servers; *T; T2 = *T, T = &(*T)->next); - if (T2 && T2->_peer) { - /* cycle */ - *T = fs; - fs->next = NULL; - } else { - /* Use next. The last "direct" entry is retried multiple times */ - fwdState->servers = fs->next; - fwdServerFree(fs); - } - } - /* use eventAdd to break potential call sequence loops */ - eventAdd("fwdConnectStart", fwdConnectStart, fwdState, 0.0, 0); - return; + debug(17, 3) ("fwdServerClosed: re-forwarding (%d tries, %d secs)\n", + fwdState->n_tries, + (int) (squid_curtime - fwdState->start)); + + if (fwdState->servers->next) { + /* use next, or cycle if origin server isn't last */ + FwdServer *fs = fwdState->servers; + FwdServer **T, *T2 = NULL; + fwdState->servers = fs->next; + + for (T = &fwdState->servers; *T; T2 = *T, T = &(*T)->next) + + ; + if (T2 && T2->_peer) { + /* cycle */ + *T = fs; + fs->next = NULL; + } else { + /* Use next. The last "direct" entry is retried multiple times */ + fwdState->servers = fs->next; + fwdServerFree(fs); + } + } + + /* use eventAdd to break potential call sequence loops */ + eventAdd("fwdConnectStart", fwdConnectStart, fwdState, 0.0, 0); + + return; } + if (!fwdState->err && shutting_down) { - fwdState->err =errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE); - fwdState->err->request = requestLink(fwdState->request); + fwdState->err =errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE); + fwdState->err->request = requestLink(fwdState->request); } + fwdStateFree(fwdState); } @@ -198,40 +232,52 @@ fwdNegotiateSSL(int fd, void *data) int ret; ErrorState *err; request_t *request = fwdState->request; + if ((ret = SSL_connect(ssl)) <= 0) { - int ssl_error = SSL_get_error(ssl, ret); - switch (ssl_error) { - case SSL_ERROR_WANT_READ: - commSetSelect(fd, COMM_SELECT_READ, fwdNegotiateSSL, fwdState, 0); - return; - case SSL_ERROR_WANT_WRITE: - commSetSelect(fd, COMM_SELECT_WRITE, fwdNegotiateSSL, fwdState, 0); - return; - default: - debug(81, 1) ("fwdNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret); - err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); + int ssl_error = SSL_get_error(ssl, ret); + + switch (ssl_error) { + + case SSL_ERROR_WANT_READ: + commSetSelect(fd, COMM_SELECT_READ, fwdNegotiateSSL, fwdState, 0); + return; + + case SSL_ERROR_WANT_WRITE: + commSetSelect(fd, COMM_SELECT_WRITE, fwdNegotiateSSL, fwdState, 0); + return; + + default: + debug(81, 1) ("fwdNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret); + err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); #ifdef EPROTO - err->xerrno = EPROTO; + + err->xerrno = EPROTO; #else - err->xerrno = EACCES; + + err->xerrno = EACCES; #endif - if (fs->_peer) { - err->host = xstrdup(fs->_peer->host); - err->port = fs->_peer->http_port; - } else { - err->host = xstrdup(request->host); - err->port = request->port; - } - err->request = requestLink(request); - fwdFail(fwdState, err); - if (fs->_peer) { - peerConnectFailed(fs->_peer); - fs->_peer->stats.conn_open--; - } - comm_close(fd); - return; - } + + if (fs->_peer) { + err->host = xstrdup(fs->_peer->host); + err->port = fs->_peer->http_port; + } else { + err->host = xstrdup(request->host); + err->port = request->port; + } + + err->request = requestLink(request); + fwdFail(fwdState, err); + + if (fs->_peer) { + peerConnectFailed(fs->_peer); + fs->_peer->stats.conn_open--; + } + + comm_close(fd); + return; + } } + fwdDispatch(fwdState); } @@ -243,42 +289,53 @@ fwdInitiateSSL(FwdState * fwdState) SSL *ssl; SSL_CTX *sslContext = NULL; peer *peer = fs->_peer; + if (peer) { - assert(peer->use_ssl); - sslContext = peer->sslContext; + assert(peer->use_ssl); + sslContext = peer->sslContext; } else { - sslContext = Config.ssl_client.sslContext; + sslContext = Config.ssl_client.sslContext; } + assert(sslContext); + if ((ssl = SSL_new(sslContext)) == NULL) { - ErrorState *err; - debug(83, 1) ("fwdInitiateSSL: Error allocating handle: %s\n", - ERR_error_string(ERR_get_error(), NULL)); - err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); - err->xerrno = errno; - err->request = requestLink(fwdState->request); - fwdFail(fwdState, err); - fwdStateFree(fwdState); - return; + ErrorState *err; + debug(83, 1) ("fwdInitiateSSL: Error allocating handle: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); + err->xerrno = errno; + err->request = requestLink(fwdState->request); + fwdFail(fwdState, err); + fwdStateFree(fwdState); + return; } + SSL_set_fd(ssl, fd); + if (peer) { - if (peer->ssldomain) - SSL_set_ex_data(ssl, ssl_ex_index_server, peer->ssldomain); + if (peer->ssldomain) + SSL_set_ex_data(ssl, ssl_ex_index_server, peer->ssldomain); + #if NOT_YET - else if (peer->name) - SSL_set_ex_data(ssl, ssl_ex_index_server, peer->name); + + else if (peer->name) + SSL_set_ex_data(ssl, ssl_ex_index_server, peer->name); + #endif - else - SSL_set_ex_data(ssl, ssl_ex_index_server, peer->host); + + else + SSL_set_ex_data(ssl, ssl_ex_index_server, peer->host); } else { - SSL_set_ex_data(ssl, ssl_ex_index_server, fwdState->request->host); + SSL_set_ex_data(ssl, ssl_ex_index_server, fwdState->request->host); } + fd_table[fd].ssl = ssl; fd_table[fd].read_method = &ssl_read_method; fd_table[fd].write_method = &ssl_write_method; fwdNegotiateSSL(fd, fwdState); } + #endif static void @@ -289,53 +346,70 @@ fwdConnectDone(int server_fd, comm_err_t status, void *data) ErrorState *err; request_t *request = fwdState->request; assert(fwdState->server_fd == server_fd); + if (status == COMM_ERR_DNS) { - /* - * Only set the dont_retry flag if the DNS lookup fails on - * a direct connection. If DNS lookup fails when trying - * a neighbor cache, we may want to retry another option. - */ - if (NULL == fs->_peer) - fwdState->flags.dont_retry = 1; - debug(17, 4) ("fwdConnectDone: Unknown host: %s\n", - request->host); - err = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE); - err->dnsserver_msg = xstrdup(dns_error_message); - err->request = requestLink(request); - fwdFail(fwdState, err); - if (fs->_peer) - fs->_peer->stats.conn_open--; - comm_close(server_fd); + /* + * Only set the dont_retry flag if the DNS lookup fails on + * a direct connection. If DNS lookup fails when trying + * a neighbor cache, we may want to retry another option. + */ + + if (NULL == fs->_peer) + fwdState->flags.dont_retry = 1; + + debug(17, 4) ("fwdConnectDone: Unknown host: %s\n", + request->host); + + err = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE); + + err->dnsserver_msg = xstrdup(dns_error_message); + + err->request = requestLink(request); + + fwdFail(fwdState, err); + + if (fs->_peer) + fs->_peer->stats.conn_open--; + + comm_close(server_fd); } else if (status != COMM_OK) { - assert(fs); - err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); - err->xerrno = errno; - if (fs->_peer) { - err->host = xstrdup(fs->_peer->host); - err->port = fs->_peer->http_port; - } else { - err->host = xstrdup(request->host); - err->port = request->port; - } - err->request = requestLink(request); - fwdFail(fwdState, err); - if (fs->_peer) { - peerConnectFailed(fs->_peer); - fs->_peer->stats.conn_open--; - } - comm_close(server_fd); + assert(fs); + err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); + err->xerrno = errno; + + if (fs->_peer) { + err->host = xstrdup(fs->_peer->host); + err->port = fs->_peer->http_port; + } else { + err->host = xstrdup(request->host); + err->port = request->port; + } + + err->request = requestLink(request); + fwdFail(fwdState, err); + + if (fs->_peer) { + peerConnectFailed(fs->_peer); + fs->_peer->stats.conn_open--; + } + + comm_close(server_fd); } else { - debug(17, 3) ("fwdConnectDone: FD %d: '%s'\n", server_fd, storeUrl(fwdState->entry)); - if (fs->_peer) - peerConnectSucceded(fs->_peer); + debug(17, 3) ("fwdConnectDone: FD %d: '%s'\n", server_fd, storeUrl(fwdState->entry)); + + if (fs->_peer) + peerConnectSucceded(fs->_peer); + #if USE_SSL - if ((fs->_peer && fs->_peer->use_ssl) || - (!fs->_peer && request->protocol == PROTO_HTTPS)) { - fwdInitiateSSL(fwdState); - return; - } + + if ((fs->_peer && fs->_peer->use_ssl) || + (!fs->_peer && request->protocol == PROTO_HTTPS)) { + fwdInitiateSSL(fwdState); + return; + } + #endif - fwdDispatch(fwdState); + fwdDispatch(fwdState); } } @@ -348,32 +422,40 @@ fwdConnectTimeout(int fd, void *data) peer *p = fwdStateServerPeer(fwdState); debug(17, 2) ("fwdConnectTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); assert(fd == fwdState->server_fd); + if (entry->isEmpty()) { - err = errorCon(ERR_CONNECT_FAIL, HTTP_GATEWAY_TIMEOUT); - err->request = requestLink(fwdState->request); - err->xerrno = ETIMEDOUT; - fwdFail(fwdState, err); - /* - * This marks the peer DOWN ... - */ - if (fwdState->servers) - if (fwdState->servers->_peer) - peerConnectFailed(fwdState->servers->_peer); + err = errorCon(ERR_CONNECT_FAIL, HTTP_GATEWAY_TIMEOUT); + err->request = requestLink(fwdState->request); + err->xerrno = ETIMEDOUT; + fwdFail(fwdState, err); + /* + * This marks the peer DOWN ... + */ + + if (fwdState->servers) + if (fwdState->servers->_peer) + peerConnectFailed(fwdState->servers->_peer); } + if (p) - p->stats.conn_open--; + p->stats.conn_open--; + comm_close(fd); } static struct in_addr -aclMapAddr(acl_address * head, ACLChecklist * ch) + aclMapAddr(acl_address * head, ACLChecklist * ch) { acl_address *l; + struct in_addr addr; - for (l = head; l; l = l->next) { - if (ch->matchAclList(l->aclList)) - return l->addr; + + for (l = head; l; l = l->next) + { + if (ch->matchAclList(l->aclList)) + return l->addr; } + addr.s_addr = INADDR_ANY; return addr; } @@ -382,23 +464,28 @@ static int aclMapTOS(acl_tos * head, ACLChecklist * ch) { acl_tos *l; + for (l = head; l; l = l->next) { - if (ch->matchAclList(l->aclList)) - return l->tos; + if (ch->matchAclList(l->aclList)) + return l->tos; } + return 0; } struct in_addr -getOutgoingAddr(request_t * request) + getOutgoingAddr(request_t * request) { ACLChecklist ch; - if (request) { - ch.src_addr = request->client_addr; - ch.my_addr = request->my_addr; - ch.my_port = request->my_port; - ch.request = requestLink(request); + + if (request) + { + ch.src_addr = request->client_addr; + ch.my_addr = request->my_addr; + ch.my_port = request->my_port; + ch.request = requestLink(request); } + return aclMapAddr(Config.accessList.outgoing_address, &ch); } @@ -406,12 +493,14 @@ unsigned long getOutgoingTOS(request_t * request) { ACLChecklist ch; + if (request) { - ch.src_addr = request->client_addr; - ch.my_addr = request->my_addr; - ch.my_port = request->my_port; - ch.request = requestLink(request); + ch.src_addr = request->client_addr; + ch.my_addr = request->my_addr; + ch.my_port = request->my_port; + ch.request = requestLink(request); } + return aclMapTOS(Config.accessList.outgoing_tos, &ch); } @@ -426,53 +515,63 @@ fwdConnectStart(void *data) const char *host; unsigned short port; time_t ctimeout; + struct in_addr outgoing; unsigned short tos; assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); + if (fs->_peer) { - host = fs->_peer->host; - port = fs->_peer->http_port; - ctimeout = fs->_peer->connect_timeout > 0 ? fs->_peer->connect_timeout - : Config.Timeout.peer_connect; + host = fs->_peer->host; + port = fs->_peer->http_port; + ctimeout = fs->_peer->connect_timeout > 0 ? fs->_peer->connect_timeout + : Config.Timeout.peer_connect; } else { - host = fwdState->request->host; - port = fwdState->request->port; - ctimeout = Config.Timeout.connect; + host = fwdState->request->host; + port = fwdState->request->port; + ctimeout = Config.Timeout.connect; } + if ((fd = pconnPop(host, port)) >= 0) { - debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); - fwdState->server_fd = fd; - fwdState->n_tries++; - comm_add_close_handler(fd, fwdServerClosed, fwdState); - fwdDispatch(fwdState); - return; + debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); + fwdState->server_fd = fd; + fwdState->n_tries++; + comm_add_close_handler(fd, fwdServerClosed, fwdState); + fwdDispatch(fwdState); + return; } + #if URL_CHECKSUM_DEBUG fwdState->entry->mem_obj->checkUrlChecksum(); + #endif + outgoing = getOutgoingAddr(fwdState->request); + tos = getOutgoingTOS(fwdState->request); debug(17, 3) ("fwdConnectStart: got addr %s, tos %d\n", - inet_ntoa(outgoing), tos); + inet_ntoa(outgoing), tos); + fd = comm_openex(SOCK_STREAM, - 0, - outgoing, - 0, - COMM_NONBLOCKING, - tos, - url); + 0, + outgoing, + 0, + COMM_NONBLOCKING, + tos, + url); + if (fd < 0) { - debug(50, 4) ("fwdConnectStart: %s\n", xstrerror()); - err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); - err->xerrno = errno; - err->request = requestLink(fwdState->request); - fwdFail(fwdState, err); - fwdStateFree(fwdState); - return; + debug(50, 4) ("fwdConnectStart: %s\n", xstrerror()); + err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); + err->xerrno = errno; + err->request = requestLink(fwdState->request); + fwdFail(fwdState, err); + fwdStateFree(fwdState); + return; } + fwdState->server_fd = fd; fwdState->n_tries++; /* @@ -481,13 +580,17 @@ fwdConnectStart(void *data) * based on the max-conn option. We need to increment here, * even if the connection may fail. */ + if (fs->_peer) - fs->_peer->stats.conn_open++; + fs->_peer->stats.conn_open++; + comm_add_close_handler(fd, fwdServerClosed, fwdState); + commSetTimeout(fd, - ctimeout, - fwdConnectTimeout, - fwdState); + ctimeout, + fwdConnectTimeout, + fwdState); + commConnectStart(fd, host, port, fwdConnectDone, fwdState); } @@ -496,11 +599,12 @@ fwdStartComplete(FwdServer * servers, void *data) { FwdState *fwdState = (FwdState *)data; debug(17, 3) ("fwdStartComplete: %s\n", storeUrl(fwdState->entry)); + if (servers != NULL) { - fwdState->servers = servers; - fwdConnectStart(fwdState); + fwdState->servers = servers; + fwdConnectStart(fwdState); } else { - fwdStartFail(fwdState); + fwdStartFail(fwdState); } } @@ -526,87 +630,106 @@ fwdDispatch(FwdState * fwdState) FwdServer *fs = fwdState->servers; int server_fd = fwdState->server_fd; debug(17, 3) ("fwdDispatch: FD %d: Fetching '%s %s'\n", - fwdState->client_fd, - RequestMethodStr[request->method], - storeUrl(entry)); + fwdState->client_fd, + RequestMethodStr[request->method], + storeUrl(entry)); /* * Assert that server_fd is set. This is to guarantee that fwdState * is attached to something and will be deallocated when server_fd * is closed. */ assert(server_fd > -1); + if (fs->_peer) - hierarchyNote(&fwdState->request->hier, fs->code, fs->_peer->host); + hierarchyNote(&fwdState->request->hier, fs->code, fs->_peer->host); else if (Config.onoff.log_ip_on_direct) - hierarchyNote(&fwdState->request->hier, fs->code, fd_table[server_fd].ipaddr); + hierarchyNote(&fwdState->request->hier, fs->code, fd_table[server_fd].ipaddr); else - hierarchyNote(&fwdState->request->hier, fs->code, request->host); + hierarchyNote(&fwdState->request->hier, fs->code, request->host); + fd_note(server_fd, storeUrl(fwdState->entry)); + fd_table[server_fd].uses++; + /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */ assert(entry->ping_status != PING_WAITING); + assert(entry->lock_count); + EBIT_SET(entry->flags, ENTRY_DISPATCHED); + netdbPingSite(request->host); + if (fwdState->servers && (p = fwdState->servers->_peer)) { - p->stats.fetches++; - fwdState->request->peer_login = p->login; - fwdState->request->peer_domain = p->domain; - httpStart(fwdState); + p->stats.fetches++; + fwdState->request->peer_login = p->login; + fwdState->request->peer_domain = p->domain; + httpStart(fwdState); } else { - fwdState->request->peer_login = NULL; - fwdState->request->peer_domain = NULL; - switch (request->protocol) { + fwdState->request->peer_login = NULL; + fwdState->request->peer_domain = NULL; + + switch (request->protocol) { #if USE_SSL - case PROTO_HTTPS: - httpStart(fwdState); - break; + + case PROTO_HTTPS: + httpStart(fwdState); + break; #endif - case PROTO_HTTP: - httpStart(fwdState); - break; - case PROTO_GOPHER: - gopherStart(fwdState); - break; - case PROTO_FTP: - ftpStart(fwdState); - break; - case PROTO_WAIS: - waisStart(fwdState); - break; - case PROTO_CACHEOBJ: - case PROTO_INTERNAL: - case PROTO_URN: - fatal_dump("Should never get here"); - break; - case PROTO_WHOIS: - whoisStart(fwdState); - break; - default: - debug(17, 1) ("fwdDispatch: Cannot retrieve '%s'\n", - storeUrl(entry)); - err = errorCon(ERR_UNSUP_REQ, HTTP_BAD_REQUEST); - err->request = requestLink(request); - fwdFail(fwdState, err); - /* - * Force a persistent connection to be closed because - * some Netscape browsers have a bug that sends CONNECT - * requests as GET's over persistent connections. - */ - request->flags.proxy_keepalive = 0; - /* - * Set the dont_retry flag becuase this is not a - * transient (network) error; its a bug. - */ - fwdState->flags.dont_retry = 1; - /* - * this assertion exists because if we are connected to - * a peer, then we need to decrement p->stats.conn_open. - */ - assert(NULL == p); - comm_close(fwdState->server_fd); - break; - } + + case PROTO_HTTP: + httpStart(fwdState); + break; + + case PROTO_GOPHER: + gopherStart(fwdState); + break; + + case PROTO_FTP: + ftpStart(fwdState); + break; + + case PROTO_WAIS: + waisStart(fwdState); + break; + + case PROTO_CACHEOBJ: + + case PROTO_INTERNAL: + + case PROTO_URN: + fatal_dump("Should never get here"); + break; + + case PROTO_WHOIS: + whoisStart(fwdState); + break; + + default: + debug(17, 1) ("fwdDispatch: Cannot retrieve '%s'\n", + storeUrl(entry)); + err = errorCon(ERR_UNSUP_REQ, HTTP_BAD_REQUEST); + err->request = requestLink(request); + fwdFail(fwdState, err); + /* + * Force a persistent connection to be closed because + * some Netscape browsers have a bug that sends CONNECT + * requests as GET's over persistent connections. + */ + request->flags.proxy_keepalive = 0; + /* + * Set the dont_retry flag becuase this is not a + * transient (network) error; its a bug. + */ + fwdState->flags.dont_retry = 1; + /* + * this assertion exists because if we are connected to + * a peer, then we need to decrement p->stats.conn_open. + */ + assert(NULL == p); + comm_close(fwdState->server_fd); + break; + } } } @@ -619,24 +742,34 @@ fwdReforward(FwdState * fwdState) assert(e->store_status == STORE_PENDING); assert(e->mem_obj); #if URL_CHECKSUM_DEBUG + e->mem_obj->checkUrlChecksum(); #endif + debug(17, 3) ("fwdReforward: %s?\n", storeUrl(e)); + if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { - debug(17, 3) ("fwdReforward: No, ENTRY_FWD_HDR_WAIT isn't set\n"); - return 0; + debug(17, 3) ("fwdReforward: No, ENTRY_FWD_HDR_WAIT isn't set\n"); + return 0; } + if (fwdState->n_tries > 9) - return 0; + return 0; + if (fwdState->request->flags.body_sent) - return 0; + return 0; + assert(fs); + fwdState->servers = fs->next; + fwdServerFree(fs); + if (fwdState->servers == NULL) { - debug(17, 3) ("fwdReforward: No forward-servers left\n"); - return 0; + debug(17, 3) ("fwdReforward: No forward-servers left\n"); + return 0; } + s = e->getReply()->sline.status; debug(17, 3) ("fwdReforward: status %d\n", (int) s); return fwdReforwardableStatus(s); @@ -648,9 +781,10 @@ void fwdServersFree(FwdServer ** FS) { FwdServer *fs; + while ((fs = *FS)) { - *FS = fs->next; - fwdServerFree(fs); + *FS = fs->next; + fwdServerFree(fs); } } @@ -665,53 +799,64 @@ fwdStart(int fd, StoreEntry * e, request_t * r) * from peer_digest.c, asn.c, netdb.c, etc and should always * be allowed. yuck, I know. */ + if (r->client_addr.s_addr != no_addr.s_addr) { - /* - * Check if this host is allowed to fetch MISSES from us (miss_access) - */ - ACLChecklist ch; - ch.src_addr = r->client_addr; - ch.my_addr = r->my_addr; - ch.my_port = r->my_port; - ch.request = requestLink(r); - answer = aclCheckFast(Config.accessList.miss, &ch); - if (answer == 0) { - err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN); - err->request = requestLink(r); - err->src_addr = r->client_addr; - errorAppendEntry(e, err); - return; - } + /* + * Check if this host is allowed to fetch MISSES from us (miss_access) + */ + ACLChecklist ch; + ch.src_addr = r->client_addr; + ch.my_addr = r->my_addr; + ch.my_port = r->my_port; + ch.request = requestLink(r); + answer = aclCheckFast(Config.accessList.miss, &ch); + + if (answer == 0) { + err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN); + err->request = requestLink(r); + err->src_addr = r->client_addr; + errorAppendEntry(e, err); + return; + } } + debug(17, 3) ("fwdStart: '%s'\n", storeUrl(e)); e->mem_obj->request = requestLink(r); e->mem_obj->fd = fd; #if URL_CHECKSUM_DEBUG + e->mem_obj->checkUrlChecksum(); #endif + if (shutting_down) { - /* more yuck */ - err = errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE); - err->request = requestLink(r); - errorAppendEntry(e, err); - return; + /* more yuck */ + err = errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE); + err->request = requestLink(r); + errorAppendEntry(e, err); + return; } + switch (r->protocol) { - /* - * Note, don't create fwdState for these requests - */ + /* + * Note, don't create fwdState for these requests + */ + case PROTO_INTERNAL: - internalStart(r, e); - return; + internalStart(r, e); + return; + case PROTO_CACHEOBJ: - cachemgrStart(fd, r, e); - return; + cachemgrStart(fd, r, e); + return; + case PROTO_URN: - urnStart(r, e); - return; + urnStart(r, e); + return; + default: - break; + break; } + fwdState = cbdataAlloc(FwdState); fwdState->entry = e; fwdState->client_fd = fd; @@ -729,11 +874,13 @@ fwdFail(FwdState * fwdState, ErrorState * errorState) { assert(EBIT_TEST(fwdState->entry->flags, ENTRY_FWD_HDR_WAIT)); debug(17, 3) ("fwdFail: %s \"%s\"\n\t%s\n", - err_type_str[errorState->type], - httpStatusString(errorState->httpStatus), - storeUrl(fwdState->entry)); + err_type_str[errorState->type], + httpStatusString(errorState->httpStatus), + storeUrl(fwdState->entry)); + if (fwdState->err) - errorStateFree(fwdState->err); + errorStateFree(fwdState->err); + fwdState->err = errorState; } @@ -773,30 +920,37 @@ fwdComplete(FwdState * fwdState) StoreEntry *e = fwdState->entry; assert(e->store_status == STORE_PENDING); debug(17, 3) ("fwdComplete: %s\n\tstatus %d\n", storeUrl(e), - e->getReply()->sline.status); + e->getReply()->sline.status); #if URL_CHECKSUM_DEBUG + e->mem_obj->checkUrlChecksum(); #endif + fwdLogReplyStatus(fwdState->n_tries, e->getReply()->sline.status); + if (fwdReforward(fwdState)) { - debug(17, 3) ("fwdComplete: re-forwarding %d %s\n", - e->getReply()->sline.status, - storeUrl(e)); - if (fwdState->server_fd > -1) - fwdUnregister(fwdState->server_fd, fwdState); - storeEntryReset(e); - fwdStartComplete(fwdState->servers, fwdState); + debug(17, 3) ("fwdComplete: re-forwarding %d %s\n", + e->getReply()->sline.status, + storeUrl(e)); + + if (fwdState->server_fd > -1) + fwdUnregister(fwdState->server_fd, fwdState); + + storeEntryReset(e); + + fwdStartComplete(fwdState->servers, fwdState); } else { - debug(17, 3) ("fwdComplete: not re-forwarding status %d\n", - e->getReply()->sline.status); - EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); - e->complete(); - /* - * If fwdState isn't associated with a server FD, it - * won't get freed unless we do it here. - */ - if (fwdState->server_fd < 0) - fwdStateFree(fwdState); + debug(17, 3) ("fwdComplete: not re-forwarding status %d\n", + e->getReply()->sline.status); + EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); + e->complete(); + /* + * If fwdState isn't associated with a server FD, it + * won't get freed unless we do it here. + */ + + if (fwdState->server_fd < 0) + fwdStateFree(fwdState); } } @@ -804,15 +958,17 @@ void fwdInit(void) { cachemgrRegister("forward", - "Request Forwarding Statistics", - fwdStats, 0, 1); + "Request Forwarding Statistics", + fwdStats, 0, 1); #if WIP_FWD_LOG + if (logfile) - (void) 0; + (void) 0; else if (NULL == Config.Log.forward) - (void) 0; + (void) 0; else - logfile = logfileOpen(Config.Log.forward, 0, 1); + logfile = logfileOpen(Config.Log.forward, 0, 1); + #endif } @@ -820,11 +976,15 @@ static void fwdLogReplyStatus(int tries, http_status status) { if (status > HTTP_INVALID_HEADER) - return; + return; + assert(tries); + tries--; + if (tries > MAX_FWD_STATS_IDX) - tries = MAX_FWD_STATS_IDX; + tries = MAX_FWD_STATS_IDX; + FwdReplyCodes[tries][status]++; } @@ -834,18 +994,24 @@ fwdStats(StoreEntry * s) int i; int j; storeAppendPrintf(s, "Status"); + for (j = 0; j <= MAX_FWD_STATS_IDX; j++) { - storeAppendPrintf(s, "\ttry#%d", j + 1); + storeAppendPrintf(s, "\ttry#%d", j + 1); } + storeAppendPrintf(s, "\n"); + for (i = 0; i <= (int) HTTP_INVALID_HEADER; i++) { - if (FwdReplyCodes[0][i] == 0) - continue; - storeAppendPrintf(s, "%3d", i); - for (j = 0; j <= MAX_FWD_STATS_IDX; j++) { - storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]); - } - storeAppendPrintf(s, "\n"); + if (FwdReplyCodes[0][i] == 0) + continue; + + storeAppendPrintf(s, "%3d", i); + + for (j = 0; j <= MAX_FWD_STATS_IDX; j++) { + storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]); + } + + storeAppendPrintf(s, "\n"); } } @@ -853,16 +1019,24 @@ int fwdReforwardableStatus(http_status s) { switch (s) { + case HTTP_FORBIDDEN: + case HTTP_INTERNAL_SERVER_ERROR: + case HTTP_NOT_IMPLEMENTED: + case HTTP_BAD_GATEWAY: + case HTTP_SERVICE_UNAVAILABLE: + case HTTP_GATEWAY_TIMEOUT: - return 1; + return 1; + default: - return 0; + return 0; } + /* NOTREACHED */ } @@ -871,8 +1045,10 @@ void fwdUninit(void) { if (NULL == logfile) - return; + return; + logfileClose(logfile); + logfile = NULL; } @@ -880,20 +1056,21 @@ void fwdLogRotate(void) { if (logfile) - logfileRotate(logfile); + logfileRotate(logfile); } static void fwdLog(FwdState * fwdState) { if (NULL == logfile) - return; + return; + logfilePrintf(logfile, "%9d.%03d %03d %s %s\n", - (int) current_time.tv_sec, - (int) current_time.tv_usec / 1000, - fwdState->last_status, - RequestMethodStr[fwdState->request->method], - fwdState->request->canonical); + (int) current_time.tv_sec, + (int) current_time.tv_usec / 1000, + fwdState->last_status, + RequestMethodStr[fwdState->request->method], + fwdState->request->canonical); } void diff --git a/src/fqdncache.cc b/src/fqdncache.cc index c9fc294880..61e69cb729 100644 --- a/src/fqdncache.cc +++ b/src/fqdncache.cc @@ -1,6 +1,6 @@ /* - * $Id: fqdncache.cc,v 1.154 2003/02/13 20:47:53 wessels Exp $ + * $Id: fqdncache.cc,v 1.155 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 35 FQDN Cache * AUTHOR: Harvest Derived @@ -41,7 +41,8 @@ typedef struct _fqdncache_entry fqdncache_entry; -struct _fqdncache_entry { +struct _fqdncache_entry +{ hash_link hash; /* must be first */ time_t lastref; time_t expires; @@ -50,22 +51,34 @@ struct _fqdncache_entry { FQDNH *handler; void *handlerData; char *error_message; + struct timeval request_time; dlink_node lru; unsigned short locks; - struct { - unsigned int negcached:1; - unsigned int fromhosts:1; - } flags; + + struct + { + +unsigned int negcached: + 1; + +unsigned int fromhosts: + 1; + } + + flags; }; -static struct { +static struct +{ int requests; int replies; int hits; int misses; int negative_hits; -} FqdncacheStats; +} + +FqdncacheStats; static dlink_list lru_list; @@ -98,13 +111,19 @@ fqdncacheRelease(fqdncache_entry * f) { int k; hash_remove_link(fqdn_table, (hash_link *) f); + for (k = 0; k < (int) f->name_count; k++) - safe_free(f->names[k]); + safe_free(f->names[k]); + debug(35, 5) ("fqdncacheRelease: Released FQDN record for '%s'.\n", - hashKeyStr(&f->hash)); + hashKeyStr(&f->hash)); + dlinkDelete(&f->lru, &lru_list); + safe_free(f->hash.key); + safe_free(f->error_message); + memFree(f, MEM_FQDNCACHE_ENTRY); } @@ -115,10 +134,12 @@ fqdncache_get(const char *name) hash_link *e; static fqdncache_entry *f; f = NULL; + if (fqdn_table) { - if ((e = (hash_link *)hash_lookup(fqdn_table, name)) != NULL) - f = (fqdncache_entry *) e; + if ((e = (hash_link *)hash_lookup(fqdn_table, name)) != NULL) + f = (fqdncache_entry *) e; } + return f; } @@ -126,10 +147,13 @@ static int fqdncacheExpiredEntry(const fqdncache_entry * f) { /* all static entries are locked, so this takes care of them too */ + if (f->locks != 0) - return 0; + return 0; + if (f->expires > squid_curtime) - return 0; + return 0; + return 1; } @@ -141,16 +165,23 @@ fqdncache_purgelru(void *notused) fqdncache_entry *f; int removed = 0; eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 10.0, 1); + for (m = lru_list.tail; m; m = prev) { - if (memInUse(MEM_FQDNCACHE_ENTRY) < fqdncache_low) - break; - prev = m->prev; - f = (fqdncache_entry *)m->data; - if (f->locks != 0) - continue; - fqdncacheRelease(f); - removed++; + if (memInUse(MEM_FQDNCACHE_ENTRY) < fqdncache_low) + break; + + prev = m->prev; + + f = (fqdncache_entry *)m->data; + + if (f->locks != 0) + continue; + + fqdncacheRelease(f); + + removed++; } + debug(35, 9) ("fqdncache_purgelru: removed %d entries\n", removed); } @@ -160,18 +191,23 @@ purge_entries_fromhosts(void) dlink_node *m = lru_list.head; fqdncache_entry *i = NULL; fqdncache_entry *t; + while (m) { - if (i != NULL) { /* need to delay deletion */ - fqdncacheRelease(i); /* we just override locks */ - i = NULL; - } - t = (fqdncache_entry *)m->data; - if (t->flags.fromhosts) - i = t; - m = m->next; + if (i != NULL) { /* need to delay deletion */ + fqdncacheRelease(i); /* we just override locks */ + i = NULL; + } + + t = (fqdncache_entry *)m->data; + + if (t->flags.fromhosts) + i = t; + + m = m->next; } + if (i != NULL) - fqdncacheRelease(i); + fqdncacheRelease(i); } /* create blank fqdncache_entry */ @@ -189,11 +225,13 @@ static void fqdncacheAddEntry(fqdncache_entry * f) { hash_link *e = (hash_link *)hash_lookup(fqdn_table, f->hash.key); + if (NULL != e) { - /* avoid colission */ - fqdncache_entry *q = (fqdncache_entry *) e; - fqdncacheRelease(q); + /* avoid colission */ + fqdncache_entry *q = (fqdncache_entry *) e; + fqdncacheRelease(q); } + hash_join(fqdn_table, &f->hash); dlinkAdd(f, &f->lru, &lru_list); f->lastref = squid_curtime; @@ -206,15 +244,21 @@ fqdncacheCallback(fqdncache_entry * f) FQDNH *callback; void *cbdata; f->lastref = squid_curtime; + if (!f->handler) - return; + return; + fqdncacheLockEntry(f); + callback = f->handler; + f->handler = NULL; + if (cbdataReferenceValidDone(f->handlerData, &cbdata)) { - dns_error_message = f->error_message; - callback(f->flags.negcached ? NULL : f->names[0], cbdata); + dns_error_message = f->error_message; + callback(f->flags.negcached ? NULL : f->names[0], cbdata); } + fqdncacheUnlockEntry(f); } @@ -229,46 +273,59 @@ fqdncacheParse(const char *inbuf) memset(&f, '\0', sizeof(f)); f.expires = squid_curtime; f.flags.negcached = 1; + if (inbuf == NULL) { - debug(35, 1) ("fqdncacheParse: Got reply\n"); - return &f; + debug(35, 1) ("fqdncacheParse: Got reply\n"); + return &f; } + xstrncpy(buf, inbuf, DNS_INBUF_SZ); debug(35, 5) ("fqdncacheParse: parsing: {%s}\n", buf); token = strtok(buf, w_space); + if (NULL == token) { - debug(35, 1) ("fqdncacheParse: Got , expecting '$name'\n"); - return &f; + debug(35, 1) ("fqdncacheParse: Got , expecting '$name'\n"); + return &f; } + if (0 == strcmp(token, "$fail")) { - f.expires = squid_curtime + Config.negativeDnsTtl; - token = strtok(NULL, "\n"); - assert(NULL != token); - f.error_message = xstrdup(token); - return &f; + f.expires = squid_curtime + Config.negativeDnsTtl; + token = strtok(NULL, "\n"); + assert(NULL != token); + f.error_message = xstrdup(token); + return &f; } + if (0 != strcmp(token, "$name")) { - debug(35, 1) ("fqdncacheParse: Got '%s', expecting '$name'\n", token); - return &f; + debug(35, 1) ("fqdncacheParse: Got '%s', expecting '$name'\n", token); + return &f; } + token = strtok(NULL, w_space); + if (NULL == token) { - debug(35, 1) ("fqdncacheParse: Got , expecting TTL\n"); - return &f; + debug(35, 1) ("fqdncacheParse: Got , expecting TTL\n"); + return &f; } + f.flags.negcached = 0; ttl = atoi(token); + if (ttl > 0) - f.expires = squid_curtime + ttl; + f.expires = squid_curtime + ttl; else - f.expires = squid_curtime + Config.positiveDnsTtl; + f.expires = squid_curtime + Config.positiveDnsTtl; + token = strtok(NULL, w_space); + if (NULL != token) { - f.names[0] = xstrdup(token); - f.name_count = 1; + f.names[0] = xstrdup(token); + f.name_count = 1; } + return &f; } + #else fqdncacheParse(rfc1035_rr * answers, int nr) { @@ -278,36 +335,49 @@ fqdncacheParse(rfc1035_rr * answers, int nr) memset(&f, '\0', sizeof(f)); f.expires = squid_curtime; f.flags.negcached = 1; + if (nr < 0) { - debug(35, 3) ("fqdncacheParse: Lookup failed (error %d)\n", - rfc1035_errno); - assert(rfc1035_error_message); - f.error_message = xstrdup(rfc1035_error_message); - return &f; + debug(35, 3) ("fqdncacheParse: Lookup failed (error %d)\n", + rfc1035_errno); + assert(rfc1035_error_message); + f.error_message = xstrdup(rfc1035_error_message); + return &f; } + if (nr == 0) { - debug(35, 3) ("fqdncacheParse: No DNS records\n"); - f.error_message = xstrdup("No DNS records"); - return &f; + debug(35, 3) ("fqdncacheParse: No DNS records\n"); + f.error_message = xstrdup("No DNS records"); + return &f; } + debug(35, 3) ("fqdncacheParse: %d answers\n", nr); assert(answers); + for (k = 0; k < nr; k++) { - if (answers[k].type != RFC1035_TYPE_PTR) - continue; - if (answers[k]._class != RFC1035_CLASS_IN) - continue; - na++; - f.flags.negcached = 0; - f.names[0] = xstrdup(answers[k].rdata); - f.name_count = 1; - f.expires = squid_curtime + answers[k].ttl; - return &f; + if (answers[k].type != RFC1035_TYPE_PTR) + continue; + + if (answers[k]._class != RFC1035_CLASS_IN) + continue; + + na++; + + f.flags.negcached = 0; + + f.names[0] = xstrdup(answers[k].rdata); + + f.name_count = 1; + + f.expires = squid_curtime + answers[k].ttl; + + return &f; } + debug(35, 1) ("fqdncacheParse: No PTR record\n"); f.error_message = xstrdup("No PTR record"); return &f; } + #endif static void @@ -325,24 +395,34 @@ fqdncacheHandleReply(void *data, rfc1035_rr * answers, int na) c = NULL; n = ++FqdncacheStats.replies; statHistCount(&statCounter.dns.svc_time, - tvSubMsec(f->request_time, current_time)); + tvSubMsec(f->request_time, current_time)); #if USE_DNSSERVERS + x = fqdncacheParse(reply); #else + x = fqdncacheParse(answers, na); #endif + assert(x); f->name_count = x->name_count; + for (n = 0; n < (int) f->name_count; n++) - f->names[n] = x->names[n]; + f->names[n] = x->names[n]; + f->error_message = x->error_message; + f->expires = x->expires; + f->flags = x->flags; + fqdncacheAddEntry(f); + fqdncacheCallback(f); } void + fqdncache_nbgethostbyaddr(struct in_addr addr, FQDNH * handler, void *handlerData) { fqdncache_entry *f = NULL; @@ -351,30 +431,42 @@ fqdncache_nbgethostbyaddr(struct in_addr addr, FQDNH * handler, void *handlerDat assert(handler); debug(35, 4) ("fqdncache_nbgethostbyaddr: Name '%s'.\n", name); FqdncacheStats.requests++; - if (name == NULL || name[0] == '\0') { - debug(35, 4) ("fqdncache_nbgethostbyaddr: Invalid name!\n"); - handler(NULL, handlerData); - return; + + if (name == NULL || name[0] == '\0') + { + debug(35, 4) ("fqdncache_nbgethostbyaddr: Invalid name!\n"); + handler(NULL, handlerData); + return; } + f = fqdncache_get(name); - if (NULL == f) { - /* miss */ - (void) 0; - } else if (fqdncacheExpiredEntry(f)) { - /* hit, but expired -- bummer */ - fqdncacheRelease(f); - f = NULL; - } else { - /* hit */ - debug(35, 4) ("fqdncache_nbgethostbyaddr: HIT for '%s'\n", name); - if (f->flags.negcached) - FqdncacheStats.negative_hits++; - else - FqdncacheStats.hits++; - f->handler = handler; - f->handlerData = cbdataReference(handlerData); - fqdncacheCallback(f); - return; + + if (NULL == f) + { + /* miss */ + (void) 0; + } else if (fqdncacheExpiredEntry(f)) + { + /* hit, but expired -- bummer */ + fqdncacheRelease(f); + f = NULL; + } else + { + /* hit */ + debug(35, 4) ("fqdncache_nbgethostbyaddr: HIT for '%s'\n", name); + + if (f->flags.negcached) + FqdncacheStats.negative_hits++; + else + FqdncacheStats.hits++; + + f->handler = handler; + + f->handlerData = cbdataReference(handlerData); + + fqdncacheCallback(f); + + return; } debug(35, 5) ("fqdncache_nbgethostbyaddr: MISS for '%s'\n", name); @@ -386,8 +478,10 @@ fqdncache_nbgethostbyaddr(struct in_addr addr, FQDNH * handler, void *handlerDat c = cbdataAlloc(generic_cbdata); c->data = f; #if USE_DNSSERVERS + dnsSubmit(hashKeyStr(&f->hash), fqdncacheHandleReply, c); #else + idnsPTRLookup(addr, fqdncacheHandleReply, c); #endif } @@ -397,53 +491,74 @@ void fqdncache_init(void) { int n; + if (fqdn_table) - return; + return; + debug(35, 3) ("Initializing FQDN Cache...\n"); + memset(&FqdncacheStats, '\0', sizeof(FqdncacheStats)); + memset(&lru_list, '\0', sizeof(lru_list)); + fqdncache_high = (long) (((float) Config.fqdncache.size * - (float) FQDN_HIGH_WATER) / (float) 100); + (float) FQDN_HIGH_WATER) / (float) 100); + fqdncache_low = (long) (((float) Config.fqdncache.size * - (float) FQDN_LOW_WATER) / (float) 100); + (float) FQDN_LOW_WATER) / (float) 100); + n = hashPrime(fqdncache_high / 4); + fqdn_table = hash_create((HASHCMP *) strcmp, n, hash4); + cachemgrRegister("fqdncache", - "FQDN Cache Stats and Contents", - fqdnStats, 0, 1); + "FQDN Cache Stats and Contents", + fqdnStats, 0, 1); + memDataInit(MEM_FQDNCACHE_ENTRY, "fqdncache_entry", - sizeof(fqdncache_entry), 0); + sizeof(fqdncache_entry), 0); } const char * + fqdncache_gethostbyaddr(struct in_addr addr, int flags) { char *name = inet_ntoa(addr); fqdncache_entry *f = NULL; + struct in_addr ip; assert(name); FqdncacheStats.requests++; f = fqdncache_get(name); - if (NULL == f) { - (void) 0; - } else if (fqdncacheExpiredEntry(f)) { - fqdncacheRelease(f); - f = NULL; - } else if (f->flags.negcached) { - FqdncacheStats.negative_hits++; - dns_error_message = f->error_message; - return NULL; - } else { - FqdncacheStats.hits++; - f->lastref = squid_curtime; - return f->names[0]; + + if (NULL == f) + { + (void) 0; + } else if (fqdncacheExpiredEntry(f)) + { + fqdncacheRelease(f); + f = NULL; + } else if (f->flags.negcached) + { + FqdncacheStats.negative_hits++; + dns_error_message = f->error_message; + return NULL; + } else + { + FqdncacheStats.hits++; + f->lastref = squid_curtime; + return f->names[0]; } + /* check if it's already a FQDN address in text form. */ if (!safe_inet_addr(name, &ip)) - return name; + return name; + FqdncacheStats.misses++; + if (flags & FQDN_LOOKUP_IF_MISS) - fqdncache_nbgethostbyaddr(addr, dummy_handler, NULL); + fqdncache_nbgethostbyaddr(addr, dummy_handler, NULL); + return NULL; } @@ -455,34 +570,47 @@ fqdnStats(StoreEntry * sentry) fqdncache_entry *f = NULL; int k; int ttl; + if (fqdn_table == NULL) - return; + return; + storeAppendPrintf(sentry, "FQDN Cache Statistics:\n"); + storeAppendPrintf(sentry, "FQDNcache Entries: %d\n", - memInUse(MEM_FQDNCACHE_ENTRY)); + memInUse(MEM_FQDNCACHE_ENTRY)); + storeAppendPrintf(sentry, "FQDNcache Requests: %d\n", - FqdncacheStats.requests); + FqdncacheStats.requests); + storeAppendPrintf(sentry, "FQDNcache Hits: %d\n", - FqdncacheStats.hits); + FqdncacheStats.hits); + storeAppendPrintf(sentry, "FQDNcache Negative Hits: %d\n", - FqdncacheStats.negative_hits); + FqdncacheStats.negative_hits); + storeAppendPrintf(sentry, "FQDNcache Misses: %d\n", - FqdncacheStats.misses); + FqdncacheStats.misses); + storeAppendPrintf(sentry, "FQDN Cache Contents:\n\n"); + storeAppendPrintf(sentry, "%-15.15s %3s %3s %3s %s\n", - "Address", "Flg", "TTL", "Cnt", "Hostnames"); + "Address", "Flg", "TTL", "Cnt", "Hostnames"); + hash_first(fqdn_table); + while ((f = (fqdncache_entry *) hash_next(fqdn_table))) { - ttl = (f->flags.fromhosts ? -1 : (f->expires - squid_curtime)); - storeAppendPrintf(sentry, "%-15.15s %c%c %3.3d % 3d", - hashKeyStr(&f->hash), - f->flags.negcached ? 'N' : ' ', - f->flags.fromhosts ? 'H' : ' ', - ttl, - (int) f->name_count); - for (k = 0; k < (int) f->name_count; k++) - storeAppendPrintf(sentry, " %s", f->names[k]); - storeAppendPrintf(sentry, "\n"); + ttl = (f->flags.fromhosts ? -1 : (f->expires - squid_curtime)); + storeAppendPrintf(sentry, "%-15.15s %c%c %3.3d % 3d", + hashKeyStr(&f->hash), + f->flags.negcached ? 'N' : ' ', + f->flags.fromhosts ? 'H' : ' ', + ttl, + (int) f->name_count); + + for (k = 0; k < (int) f->name_count; k++) + storeAppendPrintf(sentry, " %s", f->names[k]); + + storeAppendPrintf(sentry, "\n"); } } @@ -493,13 +621,17 @@ dummy_handler(const char *bufnotused, void *datanotused) } const char * + fqdnFromAddr(struct in_addr addr) { const char *n; static char buf[32]; + if (Config.onoff.log_fqdn && (n = fqdncache_gethostbyaddr(addr, 0))) - return n; + return n; + xstrncpy(buf, inet_ntoa(addr), 32); + return buf; } @@ -507,8 +639,8 @@ static void fqdncacheLockEntry(fqdncache_entry * f) { if (f->locks++ == 0) { - dlinkDelete(&f->lru, &lru_list); - dlinkAdd(f, &f->lru, &lru_list); + dlinkDelete(&f->lru, &lru_list); + dlinkAdd(f, &f->lru, &lru_list); } } @@ -517,8 +649,9 @@ fqdncacheUnlockEntry(fqdncache_entry * f) { assert(f->locks > 0); f->locks--; + if (fqdncacheExpiredEntry(f)) - fqdncacheRelease(f); + fqdncacheRelease(f); } static void @@ -526,10 +659,14 @@ fqdncacheFreeEntry(void *data) { fqdncache_entry *f = (fqdncache_entry *)data; int k; + for (k = 0; k < (int) f->name_count; k++) - safe_free(f->names[k]); + safe_free(f->names[k]); + safe_free(f->hash.key); + safe_free(f->error_message); + memFree(f, MEM_FQDNCACHE_ENTRY); } @@ -546,9 +683,9 @@ void fqdncache_restart(void) { fqdncache_high = (long) (((float) Config.fqdncache.size * - (float) FQDN_HIGH_WATER) / (float) 100); + (float) FQDN_HIGH_WATER) / (float) 100); fqdncache_low = (long) (((float) Config.fqdncache.size * - (float) FQDN_LOW_WATER) / (float) 100); + (float) FQDN_LOW_WATER) / (float) 100); purge_entries_fromhosts(); } @@ -561,24 +698,29 @@ fqdncacheAddEntryFromHosts(char *addr, wordlist * hostnames) { fqdncache_entry *fce; int j = 0; + if ((fce = fqdncache_get(addr))) { - if (1 == fce->flags.fromhosts) { - fqdncacheUnlockEntry(fce); - } else if (fce->locks > 0) { - debug(35, 1) ("fqdncacheAddEntryFromHosts: can't add static entry for locked address '%s'\n", addr); - return; - } else { - fqdncacheRelease(fce); - } + if (1 == fce->flags.fromhosts) { + fqdncacheUnlockEntry(fce); + } else if (fce->locks > 0) { + debug(35, 1) ("fqdncacheAddEntryFromHosts: can't add static entry for locked address '%s'\n", addr); + return; + } else { + fqdncacheRelease(fce); + } } + fce = fqdncacheCreateEntry(addr); + while (hostnames) { - fce->names[j] = xstrdup(hostnames->key); - j++; - hostnames = hostnames->next; - if (j >= FQDN_MAX_NAMES) - break; + fce->names[j] = xstrdup(hostnames->key); + j++; + hostnames = hostnames->next; + + if (j >= FQDN_MAX_NAMES) + break; } + fce->name_count = j; fce->names[j] = NULL; /* it's safe */ fce->flags.fromhosts = 1; @@ -599,47 +741,57 @@ snmp_netFqdnFn(variable_list * Var, snint * ErrP) debug(49, 5) ("snmp_netFqdnFn: Processing request:\n"); snmpDebugOid(5, Var->name, Var->name_length); *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_NET + 1]) { + case FQDN_ENT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - memInUse(MEM_FQDNCACHE_ENTRY), - SMI_GAUGE32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + memInUse(MEM_FQDNCACHE_ENTRY), + SMI_GAUGE32); + break; + case FQDN_REQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - FqdncacheStats.requests, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + FqdncacheStats.requests, + SMI_COUNTER32); + break; + case FQDN_HITS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - FqdncacheStats.hits, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + FqdncacheStats.hits, + SMI_COUNTER32); + break; + case FQDN_PENDHIT: - /* this is now worthless */ - Answer = snmp_var_new_integer(Var->name, Var->name_length, - 0, - SMI_GAUGE32); - break; + /* this is now worthless */ + Answer = snmp_var_new_integer(Var->name, Var->name_length, + 0, + SMI_GAUGE32); + break; + case FQDN_NEGHIT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - FqdncacheStats.negative_hits, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + FqdncacheStats.negative_hits, + SMI_COUNTER32); + break; + case FQDN_MISS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - FqdncacheStats.misses, - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + FqdncacheStats.misses, + SMI_COUNTER32); + break; + case FQDN_GHBN: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - 0, /* deprecated */ - SMI_COUNTER32); - break; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + 0, /* deprecated */ + SMI_COUNTER32); + break; + default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; + *ErrP = SNMP_ERR_NOSUCHNAME; + break; } + return Answer; } diff --git a/src/fs/aufs/aiops.cc b/src/fs/aufs/aiops.cc index 8786a9fc9d..e3fb62b016 100644 --- a/src/fs/aufs/aiops.cc +++ b/src/fs/aufs/aiops.cc @@ -1,5 +1,5 @@ /* - * $Id: aiops.cc,v 1.22 2003/01/23 00:38:09 robertc Exp $ + * $Id: aiops.cc,v 1.23 2003/02/21 22:50:29 robertc Exp $ * * DEBUG: section 43 AIOPS * AUTHOR: Stewart Forster @@ -59,7 +59,9 @@ enum _squidaio_thread_status { }; typedef enum _squidaio_thread_status squidaio_thread_status; -typedef struct squidaio_request_t { +typedef struct squidaio_request_t +{ + struct squidaio_request_t *next; squidaio_request_type request_type; int cancelled; @@ -74,25 +76,35 @@ typedef struct squidaio_request_t { int whence; int ret; int err; + struct stat *tmpstatp; + struct stat *statp; squidaio_result_t *resultp; -} squidaio_request_t; +} + +squidaio_request_t; -typedef struct squidaio_request_queue_t { +typedef struct squidaio_request_queue_t +{ pthread_mutex_t mutex; pthread_cond_t cond; squidaio_request_t *volatile head; squidaio_request_t *volatile *volatile tailp; unsigned long requests; unsigned long blocked; /* main failed to lock the queue */ -} squidaio_request_queue_t; +} + +squidaio_request_queue_t; typedef struct squidaio_thread_t squidaio_thread_t; -struct squidaio_thread_t { + +struct squidaio_thread_t +{ squidaio_thread_t *next; pthread_t thread; squidaio_thread_status status; + struct squidaio_request_t *current_req; unsigned long requests; }; @@ -134,21 +146,30 @@ static int request_queue_len = 0; static MemPool *squidaio_request_pool = NULL; static MemPool *squidaio_thread_pool = NULL; static squidaio_request_queue_t request_queue; -static struct { + +static struct +{ squidaio_request_t *head, **tailp; -} request_queue2 = { +} - NULL, &request_queue2.head -}; +request_queue2 = { + + NULL, &request_queue2.head + }; static squidaio_request_queue_t done_queue; -static struct { + +static struct +{ squidaio_request_t *head, **tailp; -} done_requests = { +} - NULL, &done_requests.head -}; +done_requests = { + + NULL, &done_requests.head + }; static pthread_attr_t globattr; #if HAVE_SCHED_H + static struct sched_param globsched; #endif static pthread_t main_thread; @@ -157,19 +178,21 @@ static MemPool * squidaio_get_pool(int size) { MemPool *p; + if (size <= AIO_LARGE_BUFS) { - if (size <= AIO_MICRO_BUFS) - p = squidaio_micro_bufs; - else if (size <= AIO_TINY_BUFS) - p = squidaio_tiny_bufs; - else if (size <= AIO_SMALL_BUFS) - p = squidaio_small_bufs; - else if (size <= AIO_MEDIUM_BUFS) - p = squidaio_medium_bufs; - else - p = squidaio_large_bufs; + if (size <= AIO_MICRO_BUFS) + p = squidaio_micro_bufs; + else if (size <= AIO_TINY_BUFS) + p = squidaio_tiny_bufs; + else if (size <= AIO_SMALL_BUFS) + p = squidaio_small_bufs; + else if (size <= AIO_MEDIUM_BUFS) + p = squidaio_medium_bufs; + else + p = squidaio_large_bufs; } else - p = NULL; + p = NULL; + return p; } @@ -180,9 +203,9 @@ squidaio_xmalloc(int size) MemPool *pool; if ((pool = squidaio_get_pool(size)) != NULL) { - p = memPoolAlloc(pool); + p = memPoolAlloc(pool); } else - p = xmalloc(size); + p = xmalloc(size); return p; } @@ -205,9 +228,9 @@ squidaio_xfree(void *p, int size) MemPool *pool; if ((pool = squidaio_get_pool(size)) != NULL) { - memPoolFree(pool, p); + memPoolFree(pool, p); } else - xfree(p); + xfree(p); } static void @@ -217,9 +240,9 @@ squidaio_xstrfree(char *str) int len = strlen(str) + 1; if ((pool = squidaio_get_pool(len)) != NULL) { - memPoolFree(pool, str); + memPoolFree(pool, str); } else - xfree(str); + xfree(str); } static void @@ -229,69 +252,100 @@ squidaio_init(void) squidaio_thread_t *threadp; if (squidaio_initialised) - return; + return; pthread_attr_init(&globattr); + #if HAVE_PTHREAD_ATTR_SETSCOPE + pthread_attr_setscope(&globattr, PTHREAD_SCOPE_SYSTEM); + #endif #if HAVE_SCHED_H + globsched.sched_priority = 1; + #endif + main_thread = pthread_self(); + #if HAVE_SCHED_H && HAVE_PTHREAD_SETSCHEDPARAM + pthread_setschedparam(main_thread, SCHED_OTHER, &globsched); + #endif #if HAVE_SCHED_H + globsched.sched_priority = 2; + #endif #if HAVE_SCHED_H && HAVE_PTHREAD_ATTR_SETSCHEDPARAM + pthread_attr_setschedparam(&globattr, &globsched); + #endif /* Initialize request queue */ if (pthread_mutex_init(&(request_queue.mutex), NULL)) - fatal("Failed to create mutex"); + fatal("Failed to create mutex"); + if (pthread_cond_init(&(request_queue.cond), NULL)) - fatal("Failed to create condition variable"); + fatal("Failed to create condition variable"); + request_queue.head = NULL; + request_queue.tailp = &request_queue.head; + request_queue.requests = 0; + request_queue.blocked = 0; /* Initialize done queue */ if (pthread_mutex_init(&(done_queue.mutex), NULL)) - fatal("Failed to create mutex"); + fatal("Failed to create mutex"); + if (pthread_cond_init(&(done_queue.cond), NULL)) - fatal("Failed to create condition variable"); + fatal("Failed to create condition variable"); + done_queue.head = NULL; + done_queue.tailp = &done_queue.head; + done_queue.requests = 0; + done_queue.blocked = 0; /* Create threads and get them to sit in their wait loop */ squidaio_thread_pool = memPoolCreate("aio_thread", sizeof(squidaio_thread_t)); + assert(NUMTHREADS); + for (i = 0; i < NUMTHREADS; i++) { - threadp = (squidaio_thread_t *)memPoolAlloc(squidaio_thread_pool); - threadp->status = _THREAD_STARTING; - threadp->current_req = NULL; - threadp->requests = 0; - threadp->next = threads; - threads = threadp; - if (pthread_create(&threadp->thread, &globattr, squidaio_thread_loop, threadp)) { - fprintf(stderr, "Thread creation failed\n"); - threadp->status = _THREAD_FAILED; - continue; - } + threadp = (squidaio_thread_t *)memPoolAlloc(squidaio_thread_pool); + threadp->status = _THREAD_STARTING; + threadp->current_req = NULL; + threadp->requests = 0; + threadp->next = threads; + threads = threadp; + + if (pthread_create(&threadp->thread, &globattr, squidaio_thread_loop, threadp)) { + fprintf(stderr, "Thread creation failed\n"); + threadp->status = _THREAD_FAILED; + continue; + } } /* Create request pool */ squidaio_request_pool = memPoolCreate("aio_request", sizeof(squidaio_request_t)); + squidaio_large_bufs = memPoolCreate("squidaio_large_bufs", AIO_LARGE_BUFS); + squidaio_medium_bufs = memPoolCreate("squidaio_medium_bufs", AIO_MEDIUM_BUFS); + squidaio_small_bufs = memPoolCreate("squidaio_small_bufs", AIO_SMALL_BUFS); + squidaio_tiny_bufs = memPoolCreate("squidaio_tiny_bufs", AIO_TINY_BUFS); + squidaio_micro_bufs = memPoolCreate("squidaio_micro_bufs", AIO_MICRO_BUFS); squidaio_initialised = 1; @@ -315,12 +369,15 @@ squidaio_thread_loop(void *ptr) sigaddset(&newSig, SIGPIPE); sigaddset(&newSig, SIGCHLD); #ifdef _SQUID_LINUX_THREADS_ + sigaddset(&newSig, SIGQUIT); sigaddset(&newSig, SIGTRAP); #else + sigaddset(&newSig, SIGUSR1); sigaddset(&newSig, SIGUSR2); #endif + sigaddset(&newSig, SIGHUP); sigaddset(&newSig, SIGTERM); sigaddset(&newSig, SIGINT); @@ -328,71 +385,92 @@ squidaio_thread_loop(void *ptr) pthread_sigmask(SIG_BLOCK, &newSig, NULL); while (1) { - threadp->current_req = request = NULL; - request = NULL; - /* Get a request to process */ - threadp->status = _THREAD_WAITING; - pthread_mutex_lock(&request_queue.mutex); - while (!request_queue.head) { - pthread_cond_wait(&request_queue.cond, &request_queue.mutex); - } - request = request_queue.head; - if (request) - request_queue.head = request->next; - if (!request_queue.head) - request_queue.tailp = &request_queue.head; - pthread_mutex_unlock(&request_queue.mutex); - /* process the request */ - threadp->status = _THREAD_BUSY; - request->next = NULL; - threadp->current_req = request; - errno = 0; - if (!request->cancelled) { - switch (request->request_type) { - case _AIO_OP_OPEN: - squidaio_do_open(request); - break; - case _AIO_OP_READ: - squidaio_do_read(request); - break; - case _AIO_OP_WRITE: - squidaio_do_write(request); - break; - case _AIO_OP_CLOSE: - squidaio_do_close(request); - break; - case _AIO_OP_UNLINK: - squidaio_do_unlink(request); - break; - case _AIO_OP_TRUNCATE: - squidaio_do_truncate(request); - break; + threadp->current_req = request = NULL; + request = NULL; + /* Get a request to process */ + threadp->status = _THREAD_WAITING; + pthread_mutex_lock(&request_queue.mutex); + + while (!request_queue.head) { + pthread_cond_wait(&request_queue.cond, &request_queue.mutex); + } + + request = request_queue.head; + + if (request) + request_queue.head = request->next; + + if (!request_queue.head) + request_queue.tailp = &request_queue.head; + + pthread_mutex_unlock(&request_queue.mutex); + + /* process the request */ + threadp->status = _THREAD_BUSY; + + request->next = NULL; + + threadp->current_req = request; + + errno = 0; + + if (!request->cancelled) { + switch (request->request_type) { + + case _AIO_OP_OPEN: + squidaio_do_open(request); + break; + + case _AIO_OP_READ: + squidaio_do_read(request); + break; + + case _AIO_OP_WRITE: + squidaio_do_write(request); + break; + + case _AIO_OP_CLOSE: + squidaio_do_close(request); + break; + + case _AIO_OP_UNLINK: + squidaio_do_unlink(request); + break; + + case _AIO_OP_TRUNCATE: + squidaio_do_truncate(request); + break; #if AIO_OPENDIR /* Opendir not implemented yet */ - case _AIO_OP_OPENDIR: - squidaio_do_opendir(request); - break; + + case _AIO_OP_OPENDIR: + squidaio_do_opendir(request); + break; #endif - case _AIO_OP_STAT: - squidaio_do_stat(request); - break; - default: - request->ret = -1; - request->err = EINVAL; - break; - } - } else { /* cancelled */ - request->ret = -1; - request->err = EINTR; - } - threadp->status = _THREAD_DONE; - /* put the request in the done queue */ - pthread_mutex_lock(&done_queue.mutex); - *done_queue.tailp = request; - done_queue.tailp = &request->next; - pthread_mutex_unlock(&done_queue.mutex); - CommIO::NotifyIOCompleted(); - threadp->requests++; + + case _AIO_OP_STAT: + squidaio_do_stat(request); + break; + + default: + request->ret = -1; + request->err = EINVAL; + break; + } + } else { /* cancelled */ + request->ret = -1; + request->err = EINTR; + } + + threadp->status = _THREAD_DONE; + /* put the request in the done queue */ + pthread_mutex_lock(&done_queue.mutex); + *done_queue.tailp = request; + done_queue.tailp = &request->next; + pthread_mutex_unlock(&done_queue.mutex); + CommIO::NotifyIOCompleted(); + threadp->requests++; } /* while forever */ + return NULL; } /* squidaio_thread_loop */ @@ -401,7 +479,7 @@ squidaio_queue_request(squidaio_request_t * request) { static int high_start = 0; debug(43, 9) ("squidaio_queue_request: %p type=%d result=%p\n", - request, request->request_type, request->resultp); + request, request->request_type, request->resultp); /* Mark it as not executed (failing result, no error) */ request->ret = -1; request->err = 0; @@ -410,66 +488,82 @@ squidaio_queue_request(squidaio_request_t * request) request->resultp->_data = request; /* Play some tricks with the request_queue2 queue */ request->next = NULL; + if (pthread_mutex_trylock(&request_queue.mutex) == 0) { - if (request_queue2.head) { - /* Grab blocked requests */ - *request_queue.tailp = request_queue2.head; - request_queue.tailp = request_queue2.tailp; - } - /* Enqueue request */ - *request_queue.tailp = request; - request_queue.tailp = &request->next; - pthread_cond_signal(&request_queue.cond); - pthread_mutex_unlock(&request_queue.mutex); - if (request_queue2.head) { - /* Clear queue of blocked requests */ - request_queue2.head = NULL; - request_queue2.tailp = &request_queue2.head; - } + if (request_queue2.head) { + /* Grab blocked requests */ + *request_queue.tailp = request_queue2.head; + request_queue.tailp = request_queue2.tailp; + } + + /* Enqueue request */ + *request_queue.tailp = request; + + request_queue.tailp = &request->next; + + pthread_cond_signal(&request_queue.cond); + + pthread_mutex_unlock(&request_queue.mutex); + + if (request_queue2.head) { + /* Clear queue of blocked requests */ + request_queue2.head = NULL; + request_queue2.tailp = &request_queue2.head; + } } else { - /* Oops, the request queue is blocked, use request_queue2 */ - *request_queue2.tailp = request; - request_queue2.tailp = &request->next; + /* Oops, the request queue is blocked, use request_queue2 */ + *request_queue2.tailp = request; + request_queue2.tailp = &request->next; } + if (request_queue2.head) { - static int filter = 0; - static int filter_limit = 8; - if (++filter >= filter_limit) { - filter_limit += filter; - filter = 0; - debug(43, 1) ("squidaio_queue_request: WARNING - Queue congestion\n"); - } + static int filter = 0; + static int filter_limit = 8; + + if (++filter >= filter_limit) { + filter_limit += filter; + filter = 0; + debug(43, 1) ("squidaio_queue_request: WARNING - Queue congestion\n"); + } } + /* Warn if out of threads */ if (request_queue_len > MAGIC1) { - static int last_warn = 0; - static int queue_high, queue_low; - if (high_start == 0) { - high_start = squid_curtime; - queue_high = request_queue_len; - queue_low = request_queue_len; - } - if (request_queue_len > queue_high) - queue_high = request_queue_len; - if (request_queue_len < queue_low) - queue_low = request_queue_len; - if (squid_curtime >= (last_warn + 15) && - squid_curtime >= (high_start + 5)) { - debug(43, 1) ("squidaio_queue_request: WARNING - Disk I/O overloading\n"); - if (squid_curtime >= (high_start + 15)) - debug(43, 1) ("squidaio_queue_request: Queue Length: current=%d, high=%d, low=%d, duration=%ld\n", - request_queue_len, queue_high, queue_low, (long int) (squid_curtime - high_start)); - last_warn = squid_curtime; - } + static int last_warn = 0; + static int queue_high, queue_low; + + if (high_start == 0) { + high_start = squid_curtime; + queue_high = request_queue_len; + queue_low = request_queue_len; + } + + if (request_queue_len > queue_high) + queue_high = request_queue_len; + + if (request_queue_len < queue_low) + queue_low = request_queue_len; + + if (squid_curtime >= (last_warn + 15) && + squid_curtime >= (high_start + 5)) { + debug(43, 1) ("squidaio_queue_request: WARNING - Disk I/O overloading\n"); + + if (squid_curtime >= (high_start + 15)) + debug(43, 1) ("squidaio_queue_request: Queue Length: current=%d, high=%d, low=%d, duration=%ld\n", + request_queue_len, queue_high, queue_low, (long int) (squid_curtime - high_start)); + + last_warn = squid_curtime; + } } else { - high_start = 0; + high_start = 0; } + /* Warn if seriously overloaded */ if (request_queue_len > RIDICULOUS_LENGTH) { - debug(43, 0) ("squidaio_queue_request: Async request queue growing uncontrollably!\n"); - debug(43, 0) ("squidaio_queue_request: Syncing pending I/O operations.. (blocking)\n"); - squidaio_sync(); - debug(43, 0) ("squidaio_queue_request: Synced\n"); + debug(43, 0) ("squidaio_queue_request: Async request queue growing uncontrollably!\n"); + debug(43, 0) ("squidaio_queue_request: Syncing pending I/O operations.. (blocking)\n"); + squidaio_sync(); + debug(43, 0) ("squidaio_queue_request: Synced\n"); } } /* squidaio_queue_request */ @@ -481,41 +575,63 @@ squidaio_cleanup_request(squidaio_request_t * requestp) /* Free allocated structures and copy data back to user space if the */ /* request hasn't been cancelled */ + switch (requestp->request_type) { + case _AIO_OP_STAT: - if (!cancelled && requestp->ret == 0) - xmemcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat)); - squidaio_xfree(requestp->tmpstatp, sizeof(struct stat)); - squidaio_xstrfree(requestp->path); - break; + + if (!cancelled && requestp->ret == 0) + + xmemcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat)); + + squidaio_xfree(requestp->tmpstatp, sizeof(struct stat)); + + squidaio_xstrfree(requestp->path); + + break; + case _AIO_OP_OPEN: - if (cancelled && requestp->ret >= 0) - /* The open() was cancelled but completed */ - close(requestp->ret); - squidaio_xstrfree(requestp->path); - break; + if (cancelled && requestp->ret >= 0) + /* The open() was cancelled but completed */ + close(requestp->ret); + + squidaio_xstrfree(requestp->path); + + break; + case _AIO_OP_CLOSE: - if (cancelled && requestp->ret < 0) - /* The close() was cancelled and never got executed */ - close(requestp->fd); - break; + if (cancelled && requestp->ret < 0) + /* The close() was cancelled and never got executed */ + close(requestp->fd); + + break; + case _AIO_OP_UNLINK: + case _AIO_OP_TRUNCATE: + case _AIO_OP_OPENDIR: - squidaio_xstrfree(requestp->path); - break; + squidaio_xstrfree(requestp->path); + + break; + case _AIO_OP_READ: - break; + break; + case _AIO_OP_WRITE: - squidaio_xfree(requestp->tmpbufp, requestp->buflen); - break; + squidaio_xfree(requestp->tmpbufp, requestp->buflen); + + break; + default: - break; + break; } + if (resultp != NULL && !cancelled) { - resultp->aio_return = requestp->ret; - resultp->aio_errno = requestp->err; + resultp->aio_return = requestp->ret; + resultp->aio_errno = requestp->err; } + memPoolFree(squidaio_request_pool, requestp); } /* squidaio_cleanup_request */ @@ -526,14 +642,15 @@ squidaio_cancel(squidaio_result_t * resultp) squidaio_request_t *request = (squidaio_request_t *)resultp->_data; if (request && request->resultp == resultp) { - debug(43, 9) ("squidaio_cancel: %p type=%d result=%p\n", - request, request->request_type, request->resultp); - request->cancelled = 1; - request->resultp = NULL; - resultp->_data = NULL; - resultp->result_type = _AIO_OP_NONE; - return 0; + debug(43, 9) ("squidaio_cancel: %p type=%d result=%p\n", + request, request->request_type, request->resultp); + request->cancelled = 1; + request->resultp = NULL; + resultp->_data = NULL; + resultp->result_type = _AIO_OP_NONE; + return 0; } + return 1; } /* squidaio_cancel */ @@ -544,17 +661,26 @@ squidaio_open(const char *path, int oflag, mode_t mode, squidaio_result_t * resu squidaio_request_t *requestp; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool); + requestp->path = (char *) squidaio_xstrdup(path); + requestp->oflag = oflag; + requestp->mode = mode; + requestp->resultp = resultp; + requestp->request_type = _AIO_OP_OPEN; + requestp->cancelled = 0; + resultp->result_type = _AIO_OP_OPEN; squidaio_queue_request(requestp); + return 0; } @@ -573,19 +699,30 @@ squidaio_read(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_r squidaio_request_t *requestp; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool); + requestp->fd = fd; + requestp->bufferp = bufp; + requestp->buflen = bufs; + requestp->offset = offset; + requestp->whence = whence; + requestp->resultp = resultp; + requestp->request_type = _AIO_OP_READ; + requestp->cancelled = 0; + resultp->result_type = _AIO_OP_READ; squidaio_queue_request(requestp); + return 0; } @@ -605,20 +742,32 @@ squidaio_write(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_ squidaio_request_t *requestp; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool); + requestp->fd = fd; + requestp->tmpbufp = (char *) squidaio_xmalloc(bufs); + xmemcpy(requestp->tmpbufp, bufp, bufs); + requestp->buflen = bufs; + requestp->offset = offset; + requestp->whence = whence; + requestp->resultp = resultp; + requestp->request_type = _AIO_OP_WRITE; + requestp->cancelled = 0; + resultp->result_type = _AIO_OP_WRITE; squidaio_queue_request(requestp); + return 0; } @@ -637,15 +786,22 @@ squidaio_close(int fd, squidaio_result_t * resultp) squidaio_request_t *requestp; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool); + requestp->fd = fd; + requestp->resultp = resultp; + requestp->request_type = _AIO_OP_CLOSE; + requestp->cancelled = 0; + resultp->result_type = _AIO_OP_CLOSE; squidaio_queue_request(requestp); + return 0; } @@ -659,22 +815,32 @@ squidaio_do_close(squidaio_request_t * requestp) int + squidaio_stat(const char *path, struct stat *sb, squidaio_result_t * resultp) { squidaio_request_t *requestp; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool); + requestp->path = (char *) squidaio_xstrdup(path); + requestp->statp = sb; + requestp->tmpstatp = (struct stat *) squidaio_xmalloc(sizeof(struct stat)); + requestp->resultp = resultp; + requestp->request_type = _AIO_OP_STAT; + requestp->cancelled = 0; + resultp->result_type = _AIO_OP_STAT; squidaio_queue_request(requestp); + return 0; } @@ -693,15 +859,22 @@ squidaio_unlink(const char *path, squidaio_result_t * resultp) squidaio_request_t *requestp; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool); + requestp->path = squidaio_xstrdup(path); + requestp->resultp = resultp; + requestp->request_type = _AIO_OP_UNLINK; + requestp->cancelled = 0; + resultp->result_type = _AIO_OP_UNLINK; squidaio_queue_request(requestp); + return 0; } @@ -719,16 +892,24 @@ squidaio_truncate(const char *path, off_t length, squidaio_result_t * resultp) squidaio_request_t *requestp; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool); + requestp->path = (char *) squidaio_xstrdup(path); + requestp->offset = length; + requestp->resultp = resultp; + requestp->request_type = _AIO_OP_TRUNCATE; + requestp->cancelled = 0; + resultp->result_type = _AIO_OP_TRUNCATE; squidaio_queue_request(requestp); + return 0; } @@ -751,9 +932,12 @@ squidaio_opendir(const char *path, squidaio_result_t * resultp) int len; if (!squidaio_initialised) - squidaio_init(); + squidaio_init(); + requestp = memPoolAlloc(squidaio_request_pool); + resultp->result_type = _AIO_OP_OPENDIR; + return -1; } @@ -769,28 +953,33 @@ static void squidaio_poll_queues(void) { /* kick "overflow" request queue */ + if (request_queue2.head && - pthread_mutex_trylock(&request_queue.mutex) == 0) { - *request_queue.tailp = request_queue2.head; - request_queue.tailp = request_queue2.tailp; - pthread_cond_signal(&request_queue.cond); - pthread_mutex_unlock(&request_queue.mutex); - request_queue2.head = NULL; - request_queue2.tailp = &request_queue2.head; + pthread_mutex_trylock(&request_queue.mutex) == 0) { + *request_queue.tailp = request_queue2.head; + request_queue.tailp = request_queue2.tailp; + pthread_cond_signal(&request_queue.cond); + pthread_mutex_unlock(&request_queue.mutex); + request_queue2.head = NULL; + request_queue2.tailp = &request_queue2.head; } + /* poll done queue */ if (done_queue.head && pthread_mutex_trylock(&done_queue.mutex) == 0) { - struct squidaio_request_t *requests = done_queue.head; - done_queue.head = NULL; - done_queue.tailp = &done_queue.head; - pthread_mutex_unlock(&done_queue.mutex); - *done_requests.tailp = requests; - request_queue_len -= 1; - while (requests->next) { - requests = requests->next; - request_queue_len -= 1; - } - done_requests.tailp = &requests->next; + + struct squidaio_request_t *requests = done_queue.head; + done_queue.head = NULL; + done_queue.tailp = &done_queue.head; + pthread_mutex_unlock(&done_queue.mutex); + *done_requests.tailp = requests; + request_queue_len -= 1; + + while (requests->next) { + requests = requests->next; + request_queue_len -= 1; + } + + done_requests.tailp = &requests->next; } } @@ -802,29 +991,40 @@ squidaio_poll_done(void) int cancelled; int polled = 0; - AIO_REPOLL: +AIO_REPOLL: request = done_requests.head; + if (request == NULL && !polled) { - CommIO::ResetNotifications(); - squidaio_poll_queues(); - polled = 1; - request = done_requests.head; + CommIO::ResetNotifications(); + squidaio_poll_queues(); + polled = 1; + request = done_requests.head; } + if (!request) { - return NULL; + return NULL; } + debug(43, 9) ("squidaio_poll_done: %p type=%d result=%p\n", - request, request->request_type, request->resultp); + request, request->request_type, request->resultp); done_requests.head = request->next; + if (!done_requests.head) - done_requests.tailp = &done_requests.head; + done_requests.tailp = &done_requests.head; + resultp = request->resultp; + cancelled = request->cancelled; + squidaio_debug(request); + debug(43, 5) ("DONE: %d -> %d\n", request->ret, request->err); + squidaio_cleanup_request(request); + if (cancelled) - goto AIO_REPOLL; + goto AIO_REPOLL; + return resultp; } /* squidaio_poll_done */ @@ -838,9 +1038,11 @@ int squidaio_sync(void) { /* XXX This might take a while if the queue is large.. */ + do { - squidaio_poll_queues(); + squidaio_poll_queues(); } while (request_queue_len > 0); + return squidaio_operations_pending(); } @@ -854,25 +1056,32 @@ static void squidaio_debug(squidaio_request_t * request) { switch (request->request_type) { + case _AIO_OP_OPEN: - debug(43, 5) ("OPEN of %s to FD %d\n", request->path, request->ret); - break; + debug(43, 5) ("OPEN of %s to FD %d\n", request->path, request->ret); + break; + case _AIO_OP_READ: - debug(43, 5) ("READ on fd: %d\n", request->fd); - break; + debug(43, 5) ("READ on fd: %d\n", request->fd); + break; + case _AIO_OP_WRITE: - debug(43, 5) ("WRITE on fd: %d\n", request->fd); - break; + debug(43, 5) ("WRITE on fd: %d\n", request->fd); + break; + case _AIO_OP_CLOSE: - debug(43, 5) ("CLOSE of fd: %d\n", request->fd); - break; + debug(43, 5) ("CLOSE of fd: %d\n", request->fd); + break; + case _AIO_OP_UNLINK: - debug(43, 5) ("UNLINK of %s\n", request->path); - break; + debug(43, 5) ("UNLINK of %s\n", request->path); + break; + case _AIO_OP_TRUNCATE: - debug(43, 5) ("UNLINK of %s\n", request->path); - break; + debug(43, 5) ("UNLINK of %s\n", request->path); + break; + default: - break; + break; } } diff --git a/src/fs/aufs/async_io.cc b/src/fs/aufs/async_io.cc index 02fe2020f2..605dae6661 100644 --- a/src/fs/aufs/async_io.cc +++ b/src/fs/aufs/async_io.cc @@ -1,6 +1,6 @@ /* - * $Id: async_io.cc,v 1.22 2003/01/23 00:38:09 robertc Exp $ + * $Id: async_io.cc,v 1.23 2003/02/21 22:50:29 robertc Exp $ * * DEBUG: section 32 Asynchronous Disk I/O * AUTHOR: Pete Bentley @@ -48,7 +48,9 @@ #define _AIO_OPENDIR 5 #define _AIO_STAT 6 -typedef struct squidaio_ctrl_t { +typedef struct squidaio_ctrl_t +{ + struct squidaio_ctrl_t *next; int fd; int operation; @@ -59,9 +61,12 @@ typedef struct squidaio_ctrl_t { char *bufp; FREE *free_func; dlink_node node; -} squidaio_ctrl_t; +} + +squidaio_ctrl_t; -static struct { +static struct +{ int open_start; int open_finish; int close_start; @@ -76,12 +81,18 @@ static struct { int unlink_start; int unlink_finish; int check_callback; -} squidaio_counts; +} + +squidaio_counts; -typedef struct squidaio_unlinkq_t { +typedef struct squidaio_unlinkq_t +{ char *path; + struct squidaio_unlinkq_t *next; -} squidaio_unlinkq_t; +} + +squidaio_unlinkq_t; static dlink_list used_list; static int initialised = 0; @@ -93,7 +104,7 @@ static void aioFDWasClosed(int fd) { if (fd_table[fd].flags.closing) - fd_close(fd); + fd_close(fd); } @@ -101,10 +112,13 @@ void aioInit(void) { if (initialised) - return; + return; + squidaio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(squidaio_ctrl_t)); + cachemgrRegister("squidaio_counts", "Async IO Function Counters", - aioStats, 0, 1); + aioStats, 0, 1); + initialised = 1; } @@ -160,30 +174,36 @@ aioCancel(int fd) assert(initialised); squidaio_counts.cancel++; + for (m = used_list.head; m; m = next) { - next = m->next; - ctrlp = (squidaio_ctrl_t *)m->data; - if (ctrlp->fd != fd) - continue; - - squidaio_cancel(&ctrlp->result); - - if (ctrlp->done_handler) { - AIOCB *callback = ctrlp->done_handler; - void *cbdata; - ctrlp->done_handler = NULL; - debug(32, 1) ("this be aioCancel. Danger ahead!\n"); - if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) - callback(fd, cbdata, NULL, -2, -2); - /* free data if requested to aioWrite() */ - if (ctrlp->free_func) - ctrlp->free_func(ctrlp->bufp); - /* free temporary read buffer */ - if (ctrlp->operation == _AIO_READ) - squidaio_xfree(ctrlp->bufp, ctrlp->len); - } - dlinkDelete(m, &used_list); - memPoolFree(squidaio_ctrl_pool, ctrlp); + next = m->next; + ctrlp = (squidaio_ctrl_t *)m->data; + + if (ctrlp->fd != fd) + continue; + + squidaio_cancel(&ctrlp->result); + + if (ctrlp->done_handler) { + AIOCB *callback = ctrlp->done_handler; + void *cbdata; + ctrlp->done_handler = NULL; + debug(32, 1) ("this be aioCancel. Danger ahead!\n"); + + if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) + callback(fd, cbdata, NULL, -2, -2); + + /* free data if requested to aioWrite() */ + if (ctrlp->free_func) + ctrlp->free_func(ctrlp->bufp); + + /* free temporary read buffer */ + if (ctrlp->operation == _AIO_READ) + squidaio_xfree(ctrlp->bufp, ctrlp->len); + } + + dlinkDelete(m, &used_list); + memPoolFree(squidaio_ctrl_pool, ctrlp); } } @@ -203,12 +223,14 @@ aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callba ctrlp->operation = _AIO_WRITE; ctrlp->bufp = bufp; ctrlp->free_func = free_func; + if (offset >= 0) - seekmode = SEEK_SET; + seekmode = SEEK_SET; else { - seekmode = SEEK_END; - offset = 0; + seekmode = SEEK_END; + offset = 0; } + ctrlp->result.data = ctrlp; squidaio_write(fd, bufp, len, offset, seekmode, &ctrlp->result); dlinkAdd(ctrlp, &ctrlp->node, &used_list); @@ -230,12 +252,14 @@ aioRead(int fd, int offset, int len, AIOCB * callback, void *callback_data) ctrlp->operation = _AIO_READ; ctrlp->len = len; ctrlp->bufp = (char *)squidaio_xmalloc(len); + if (offset >= 0) - seekmode = SEEK_SET; + seekmode = SEEK_SET; else { - seekmode = SEEK_CUR; - offset = 0; + seekmode = SEEK_CUR; + offset = 0; } + ctrlp->result.data = ctrlp; squidaio_read(fd, ctrlp->bufp, len, offset, seekmode, &ctrlp->result); dlinkAdd(ctrlp, &ctrlp->node, &used_list); @@ -243,6 +267,7 @@ aioRead(int fd, int offset, int len, AIOCB * callback, void *callback_data) } /* aioRead */ void + aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data) { squidaio_ctrl_t *ctrlp; @@ -302,64 +327,86 @@ AUFSSwapDir::callback() assert(initialised); squidaio_counts.check_callback++; + for (;;) { - if ((resultp = squidaio_poll_done()) == NULL) - break; - ctrlp = (squidaio_ctrl_t *) resultp->data; - switch (resultp->result_type) { - case _AIO_OP_NONE: - case _AIO_OP_TRUNCATE: - case _AIO_OP_OPENDIR: - break; - case _AIO_OP_OPEN: - ++squidaio_counts.open_finish; - break; - case _AIO_OP_READ: - ++squidaio_counts.read_finish; - break; - case _AIO_OP_WRITE: - ++squidaio_counts.write_finish; - break; - case _AIO_OP_CLOSE: - ++squidaio_counts.close_finish; - break; - case _AIO_OP_UNLINK: - ++squidaio_counts.unlink_finish; - break; - case _AIO_OP_STAT: - ++squidaio_counts.stat_finish; - break; - } - if (ctrlp == NULL) - continue; /* XXX Should not happen */ - dlinkDelete(&ctrlp->node, &used_list); - if (ctrlp->done_handler) { - AIOCB *callback = ctrlp->done_handler; - void *cbdata; - ctrlp->done_handler = NULL; - if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) { - retval = 1; /* Return that we've actually done some work */ - callback(ctrlp->fd, cbdata, ctrlp->bufp, - ctrlp->result.aio_return, ctrlp->result.aio_errno); - } else { - if (ctrlp->operation == _AIO_OPEN) { - /* The open operation was aborted.. */ - int fd = ctrlp->result.aio_return; - if (fd >= 0) - aioClose(fd); - } - } - } - /* free data if requested to aioWrite() */ - if (ctrlp->free_func) - ctrlp->free_func(ctrlp->bufp); - /* free temporary read buffer */ - if (ctrlp->operation == _AIO_READ) - squidaio_xfree(ctrlp->bufp, ctrlp->len); - if (ctrlp->operation == _AIO_CLOSE) - aioFDWasClosed(ctrlp->fd); - memPoolFree(squidaio_ctrl_pool, ctrlp); + if ((resultp = squidaio_poll_done()) == NULL) + break; + + ctrlp = (squidaio_ctrl_t *) resultp->data; + + switch (resultp->result_type) { + + case _AIO_OP_NONE: + + case _AIO_OP_TRUNCATE: + + case _AIO_OP_OPENDIR: + break; + + case _AIO_OP_OPEN: + ++squidaio_counts.open_finish; + break; + + case _AIO_OP_READ: + ++squidaio_counts.read_finish; + break; + + case _AIO_OP_WRITE: + ++squidaio_counts.write_finish; + break; + + case _AIO_OP_CLOSE: + ++squidaio_counts.close_finish; + break; + + case _AIO_OP_UNLINK: + ++squidaio_counts.unlink_finish; + break; + + case _AIO_OP_STAT: + ++squidaio_counts.stat_finish; + break; + } + + if (ctrlp == NULL) + continue; /* XXX Should not happen */ + + dlinkDelete(&ctrlp->node, &used_list); + + if (ctrlp->done_handler) { + AIOCB *callback = ctrlp->done_handler; + void *cbdata; + ctrlp->done_handler = NULL; + + if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) { + retval = 1; /* Return that we've actually done some work */ + callback(ctrlp->fd, cbdata, ctrlp->bufp, + ctrlp->result.aio_return, ctrlp->result.aio_errno); + } else { + if (ctrlp->operation == _AIO_OPEN) { + /* The open operation was aborted.. */ + int fd = ctrlp->result.aio_return; + + if (fd >= 0) + aioClose(fd); + } + } + } + + /* free data if requested to aioWrite() */ + if (ctrlp->free_func) + ctrlp->free_func(ctrlp->bufp); + + /* free temporary read buffer */ + if (ctrlp->operation == _AIO_READ) + squidaio_xfree(ctrlp->bufp, ctrlp->len); + + if (ctrlp->operation == _AIO_CLOSE) + aioFDWasClosed(ctrlp->fd); + + memPoolFree(squidaio_ctrl_pool, ctrlp); } + return retval; } @@ -384,12 +431,15 @@ void AUFSSwapDir::sync() { if (!initialised) - return; /* nothing to do then */ + return; /* nothing to do then */ + /* Flush all pending operations */ debug(32, 1) ("aioSync: flushing pending I/O operations\n"); + do { - callback(); + callback(); } while (squidaio_sync()); + debug(32, 1) ("aioSync: done\n"); } diff --git a/src/fs/aufs/store_asyncufs.h b/src/fs/aufs/store_asyncufs.h index 167f5218e3..e2da87ebae 100644 --- a/src/fs/aufs/store_asyncufs.h +++ b/src/fs/aufs/store_asyncufs.h @@ -38,7 +38,8 @@ enum _squidaio_request_type { }; typedef enum _squidaio_request_type squidaio_request_type; -struct _squidaio_result_t { +struct _squidaio_result_t +{ int aio_return; int aio_errno; enum _squidaio_request_type result_type; @@ -55,6 +56,7 @@ int squidaio_open(const char *, int, mode_t, squidaio_result_t *); int squidaio_read(int, char *, int, off_t, int, squidaio_result_t *); int squidaio_write(int, char *, int, off_t, int, squidaio_result_t *); int squidaio_close(int, squidaio_result_t *); + int squidaio_stat(const char *, struct stat *, squidaio_result_t *); int squidaio_unlink(const char *, squidaio_result_t *); int squidaio_truncate(const char *, off_t length, squidaio_result_t *); @@ -73,6 +75,7 @@ void aioOpen(const char *, int, mode_t, AIOCB *, void *); void aioClose(int); void aioWrite(int, int offset, char *, int size, AIOCB *, void *, FREE *); void aioRead(int, int offset, int size, AIOCB *, void *); + void aioStat(char *, struct stat *, AIOCB *, void *); void aioUnlink(const char *, AIOCB *, void *); void aioTruncate(const char *, off_t length, AIOCB *, void *); @@ -81,8 +84,11 @@ int aioQueueSize(void); #include "ufscommon.h" class AufsIO; -class AUFSFile : public DiskFile { - public: + +class AUFSFile : public DiskFile +{ + +public: virtual void deleteSelf() const; void * operator new (size_t); void operator delete (void *); @@ -95,19 +101,26 @@ class AUFSFile : public DiskFile { void close(); virtual bool error() const; virtual int getFD() const { return fd;} + virtual bool canRead() const; virtual bool canWrite() const; - private: + +private: #if ASYNC_READ -static AIOCB ReadDone; + + static AIOCB ReadDone; #else -static DRCB ReadDone; + + static DRCB ReadDone; #endif #if ASYNC_WRITE -static AIOCB WriteDone; + + static AIOCB WriteDone; #else -static DWCB WriteDone; + + static DWCB WriteDone; #endif + int fd; bool errorOccured; char const *path_; @@ -117,14 +130,17 @@ static DWCB WriteDone; IORequestor::Pointer ioRequestor; CBDATA_CLASS(AUFSFile); void doClose(); - + void readDone(int fd, const char *buf, int len, int errflag); void writeDone (int fd, int errflag, size_t len); }; -class squidaiostate_t : public UFSStoreState { - public: +class squidaiostate_t : public UFSStoreState +{ + +public: virtual void deleteSelf() const {delete this;} + void * operator new (size_t); void operator delete (void *); squidaiostate_t(SwapDir *, StoreEntry *, STIOCB *, void *); @@ -132,17 +148,28 @@ class squidaiostate_t : public UFSStoreState { void close(); int fd; - struct { - unsigned int write_kicking:1; - unsigned int read_kicking:1; - unsigned int inreaddone:1; - } flags; + + struct + { + +unsigned int write_kicking: + 1; + +unsigned int read_kicking: + 1; + +unsigned int inreaddone: + 1; + } + + flags; void ioCompletedNotification(); void closeCompleted(); void readCompleted(const char *buf, int len, int errflag); void writeCompleted(int errflag, size_t len); void writeDone(int fd, int errflag, size_t len); - private: + +private: CBDATA_CLASS(squidaiostate_t); void openDone(); }; @@ -151,27 +178,30 @@ class squidaiostate_t : public UFSStoreState { * Store IO stuff */ #include "SwapDir.h" + class AUFSSwapDir : public UFSSwapDir { + public: - virtual void dump(StoreEntry &)const; - virtual void unlink(StoreEntry &); - virtual int canStore(StoreEntry const &)const; - virtual int callback(); - virtual void sync(); - virtual void parse (int index, char *path); - virtual void reconfigure(int, char *); - virtual void unlinkFile(char const *); + virtual void dump(StoreEntry &)const; + virtual void unlink(StoreEntry &); + virtual int canStore(StoreEntry const &)const; + virtual int callback(); + virtual void sync(); + virtual void parse (int index, char *path); + virtual void reconfigure(int, char *); + virtual void unlinkFile(char const *); }; class AufsIO : public UFSStrategy { + public: - virtual bool shedLoad(); - virtual void deleteSelf() const; - virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const; - virtual DiskFile::Pointer newFile(char const *path); - static AufsIO Instance; + virtual bool shedLoad(); + virtual void deleteSelf() const; + virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const; + virtual DiskFile::Pointer newFile(char const *path); + static AufsIO Instance; }; #endif diff --git a/src/fs/aufs/store_dir_aufs.cc b/src/fs/aufs/store_dir_aufs.cc index 4fe12e10fa..95068391a2 100644 --- a/src/fs/aufs/store_dir_aufs.cc +++ b/src/fs/aufs/store_dir_aufs.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir_aufs.cc,v 1.54 2003/01/23 00:38:09 robertc Exp $ + * $Id: store_dir_aufs.cc,v 1.55 2003/02/21 22:50:29 robertc Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -61,18 +61,24 @@ AUFSSwapDir::canStore(StoreEntry const &e) const int ql; #if OLD_UNUSED_CODE + if (storeAufsDirExpiredReferenceAge(this) < 300) { - debug(47, 3) ("storeAufsDirCheckObj: NO: LRU Age = %d\n", - storeAufsDirExpiredReferenceAge(this)); - /* store_check_cachable_hist.no.lru_age_too_low++; */ - return -1; + debug(47, 3) ("storeAufsDirCheckObj: NO: LRU Age = %d\n", + storeAufsDirExpiredReferenceAge(this)); + /* store_check_cachable_hist.no.lru_age_too_low++; */ + return -1; } + #endif ql = aioQueueSize(); + if (ql == 0) - loadav = 0; + loadav = 0; + loadav = ql * 1000 / MAGIC1; + debug(47, 9) ("storeAufsDirCheckObj: load=%d\n", loadav); + return loadav; } @@ -82,6 +88,7 @@ AUFSSwapDir::unlinkFile(char const *path) #if USE_TRUNCATE_NOT_UNLINK aioTruncate(path, NULL, NULL); #else + aioUnlink(path, NULL, NULL); #endif } @@ -89,13 +96,13 @@ AUFSSwapDir::unlinkFile(char const *path) /* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */ static struct cache_dir_option options[] = -{ + { #if NOT_YET_DONE - {"L1", storeAufsDirParseL1, storeAufsDirDumpL1}, - {"L2", storeAufsDirParseL2, storeAufsDirDumpL2}, + {"L1", storeAufsDirParseL1, storeAufsDirDumpL1}, + {"L2", storeAufsDirParseL2, storeAufsDirDumpL2}, #endif - {NULL, NULL} -}; + {NULL, NULL} + }; /* * storeAufsDirReconfigure diff --git a/src/fs/aufs/store_io_aufs.cc b/src/fs/aufs/store_io_aufs.cc index dab875bef2..a546e5cfbc 100644 --- a/src/fs/aufs/store_io_aufs.cc +++ b/src/fs/aufs/store_io_aufs.cc @@ -28,7 +28,7 @@ squidaiostate_t::operator new (size_t) cbdataReference(result); return result; } - + void squidaiostate_t::operator delete (void *address) { @@ -37,7 +37,7 @@ squidaiostate_t::operator delete (void *address) /* And allow the memory to be freed */ cbdataReferenceDone (t); } - + squidaiostate_t::squidaiostate_t(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_) { swap_filen = anEntry->swap_filen; @@ -58,11 +58,15 @@ AufsIO::shedLoad() * NULL here. */ #ifdef MAGIC2 + if (aioQueueSize() > MAGIC2) - return true; + return true; + #endif + return false; } + void AufsIO::deleteSelf() const { @@ -92,7 +96,7 @@ AUFSFile::operator new (size_t) cbdataReference(result); return result; } - + void AUFSFile::operator delete (void *address) { @@ -105,7 +109,8 @@ AUFSFile::operator delete (void *address) void AUFSFile::deleteSelf() const {delete this;} -AUFSFile::AUFSFile (char const *aPath, AufsIO *anIO):fd(-1), errorOccured (false), IO(anIO) { +AUFSFile::AUFSFile (char const *aPath, AufsIO *anIO):fd(-1), errorOccured (false), IO(anIO) +{ assert (aPath); debug (79,3)("UFSFile::UFSFile: %s\n", aPath); path_ = xstrdup (aPath); @@ -122,19 +127,28 @@ AUFSFile::open (int flags, mode_t mode, IORequestor::Pointer callback) { statCounter.syscalls.disk.opens++; #if !ASYNC_OPEN + fd = file_open(path_, flags); + if (fd < 0) { - debug(79, 3) ("AUFSFile::open: got failure (%d)\n", errno); - errorOccured = true; - return; + debug(79, 3) ("AUFSFile::open: got failure (%d)\n", errno); + errorOccured = true; + return; } + #endif Opening_FD++; + ioRequestor = callback; + #if ASYNC_OPEN + aioOpen(path_, flags, mode, AUFSFile::OpenDone, this); + #else + openDone(fd, NULL, fd, 0); + #endif } @@ -145,8 +159,10 @@ AUFSFile::read(char *buf, off_t offset, size_t size) assert (ioRequestor.getRaw()); statCounter.syscalls.disk.reads++; #if ASYNC_READ + aioRead(fd, offset, size, ReadDone, this); #else + file_read(fd, buf, size, offset, ReadDone, this); #endif } @@ -156,19 +172,28 @@ AUFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback) { statCounter.syscalls.disk.opens++; #if !ASYNC_CREATE + int fd = file_open(path_, flags); + if (fd < 0) { - debug(79, 3) ("storeAufsCreate: got failure (%d)\n", errno); - errorOccured = true; - return; + debug(79, 3) ("storeAufsCreate: got failure (%d)\n", errno); + errorOccured = true; + return; } + #endif Opening_FD++; + ioRequestor = callback; + #if ASYNC_CREATE + aioOpen(path_, flags, mode, AUFSFile::OpenDone, this); + #else + openDone (fd, NULL, fd, 0); + #endif } @@ -192,17 +217,18 @@ AUFSFile::openDone(int unused, const char *unused2, int anFD, int errflag) Opening_FD--; fd = anFD; + if (errflag || fd < 0) { - errno = errflag; - debug(79, 0) ("AUFSFile::openDone: %s\n", xstrerror()); - debug(79, 1) ("\t%s\n", path_); - errorOccured = true; + errno = errflag; + debug(79, 0) ("AUFSFile::openDone: %s\n", xstrerror()); + debug(79, 1) ("\t%s\n", path_); + errorOccured = true; } else { - store_open_disk_fd++; - commSetCloseOnExec(fd); - fd_open(fd, FD_FILE, path_); + store_open_disk_fd++; + commSetCloseOnExec(fd); + fd_open(fd, FD_FILE, path_); } - + debug(79, 3) ("AUFSFile::openDone: exiting\n"); IORequestor::Pointer t = ioRequestor; @@ -212,18 +238,18 @@ AUFSFile::openDone(int unused, const char *unused2, int anFD, int errflag) void AUFSFile::doClose() { if (fd > -1) { - statCounter.syscalls.disk.closes++; - aioClose(fd); - fd_close(fd); - store_open_disk_fd--; - fd = -1; + statCounter.syscalls.disk.closes++; + aioClose(fd); + fd_close(fd); + store_open_disk_fd--; + fd = -1; } } /* open for reading */ StoreIOState::Pointer storeAufsOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, - STIOCB * callback, void *callback_data) + STIOCB * callback, void *callback_data) { UFSStrategy *IO = dynamic_cast (((AUFSSwapDir *)SD)->IO); assert (IO); @@ -244,12 +270,14 @@ void squidaiostate_t::close() { debug(79, 3) ("storeAufsClose: dirno %d, fileno %08X, FD %d\n", - swap_dirn, swap_filen, fd); + swap_dirn, swap_filen, fd); /* mark the object to be closed on the next io that completes */ + if (storeAufsNeedCompletetion(this)) { - closing = true; - return; + closing = true; + return; } + storeAufsIOCallback(this, DISK_OK); } @@ -266,16 +294,19 @@ AUFSFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) debug(79, 3) ("storeAufsWrite: FD %d\n", fd); statCounter.syscalls.disk.writes++; #if ASYNC_WRITE + aioWrite(fd, offset, (char *)buf, size, WriteDone, this, - free_func); + free_func); #else + file_write(fd, offset, (char *)buf, size, WriteDone, this, - free_func); + free_func); #endif } bool -AUFSFile::canWrite() const { +AUFSFile::canWrite() const +{ return fd > -1; } @@ -302,7 +333,7 @@ AUFSFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data) { AUFSFile *myFile = static_cast(my_data); assert (myFile); - myFile->readDone (fd, buf, len, errflag); + myFile->readDone (fd, buf, len, errflag); } void @@ -312,23 +343,30 @@ AUFSFile::readDone(int rvfd, const char *buf, int len, int errflag) assert (fd == rvfd); ssize_t rlen; + if (errflag) { - debug(79, 3) ("AUFSFile::readDone: got failure (%d)\n", errflag); - rlen = -1; + debug(79, 3) ("AUFSFile::readDone: got failure (%d)\n", errflag); + rlen = -1; } else { - rlen = (ssize_t) len; + rlen = (ssize_t) len; } + #if ASYNC_READ /* translate errflag from errno to Squid disk error */ errno = errflag; + if (errflag) - errflag = DISK_ERROR; + errflag = DISK_ERROR; else - errflag = DISK_OK; + errflag = DISK_OK; + #else + if (errflag == DISK_EOF) - errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ + errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ + #endif + ioRequestor->readCompleted(buf, rlen, errflag); } @@ -339,53 +377,69 @@ squidaiostate_t::readCompleted(const char *buf, int len, int errflag) flags.inreaddone = 1; reading = false; debug(79, 3) ("squidaiostate_t::readCompleted: dirno %d, fileno %08X, len %d\n", - swap_dirn, swap_filen, len); + swap_dirn, swap_filen, len); + if (len > 0) - offset_ += len; + offset_ += len; STRCB *callback = read.callback; + assert(callback); + read.callback = NULL; + void *cbdata; + if (!closing && cbdataReferenceValidDone(read.callback_data, &cbdata)) { - if (len > 0 && read_buf != buf) - memcpy(read_buf, buf, len); - callback(cbdata, read_buf, len); + if (len > 0 && read_buf != buf) + memcpy(read_buf, buf, len); + + callback(cbdata, read_buf, len); } flags.inreaddone = 0; + if (closing && !localinreaddone) - storeAufsIOCallback(this, errflag); + storeAufsIOCallback(this, errflag); } - + void squidaiostate_t::writeCompleted(int errflag, size_t len) { debug(79, 3) ("storeAufsWriteDone: dirno %d, fileno %08X, len %ld, err=%d\n", - swap_dirn, swap_filen, (long int) len, errflag); + swap_dirn, swap_filen, (long int) len, errflag); writing = false; + if (errflag) { - debug(79, 0) ("storeAufsWriteDone: got failure (%d)\n", errflag); - storeAufsIOCallback(this, errflag); - return; + debug(79, 0) ("storeAufsWriteDone: got failure (%d)\n", errflag); + storeAufsIOCallback(this, errflag); + return; } + offset_ += len; #if ASYNC_WRITE + if (!kickWriteQueue()) - 0; + 0; else if (closing) - storeAufsIOCallback(this, errflag); + storeAufsIOCallback(this, errflag); + #else + if (!flags.write_kicking) { - flags.write_kicking = 1; - while (kickWriteQueue()) - (void) 0; - flags.write_kicking = 0; - if (closing) - storeAufsIOCallback(this, errflag); + flags.write_kicking = 1; + + while (kickWriteQueue()) + (void) 0; + + flags.write_kicking = 0; + + if (closing) + storeAufsIOCallback(this, errflag); } + #endif } @@ -408,19 +462,23 @@ AUFSFile::writeDone (int rvfd, int errflag, size_t len) assert (rvfd == fd); static int loop_detect = 0; debug(79, 3) ("storeAufsWriteDone: FD %d, len %ld, err=%d\n", - fd, (long int) len, errflag); + fd, (long int) len, errflag); #if ASYNC_WRITE /* Translate from errno to Squid disk error */ errno = errflag; + if (errflag) - errflag = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; + errflag = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; else - errflag = DISK_OK; + errflag = DISK_OK; + #endif + assert(++loop_detect < 10); ioRequestor->writeCompleted(errflag, len); + --loop_detect; } @@ -432,20 +490,28 @@ storeAufsIOCallback(storeIOState * sio, int errflag) int fd = aiostate->fd; debug(79, 3) ("storeAufsIOCallback: errflag=%d\n", errflag); debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); + if (callback) { - void *cbdata; - sio->callback = NULL; - if (cbdataReferenceValidDone(sio->callback_data, &cbdata)) - callback(cbdata, errflag, sio); + void *cbdata; + sio->callback = NULL; + + if (cbdataReferenceValidDone(sio->callback_data, &cbdata)) + callback(cbdata, errflag, sio); } + debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); aiostate->fd = -1; + if (aiostate->opening || aiostate->creating) - Opening_FD--; + Opening_FD--; + if (fd < 0) - return; + return; + debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); + aiostate->theFile = NULL; + debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); } @@ -456,40 +522,44 @@ storeAufsNeedCompletetion(storeIOState * sio) squidaiostate_t *aiostate = dynamic_cast(sio); if (aiostate->writing) - return true; + return true; + if (aiostate->creating && FILE_MODE(sio->mode) == O_WRONLY) - return 1; + return 1; + if (aiostate->reading) - return 1; + return 1; + if (aiostate->flags.inreaddone) - return 1; + return 1; return 0; } -/* +/* * Clean up references from the SIO before it gets released. * The actuall SIO is managed by cbdata so we do not need * to bother with that. */ squidaiostate_t::~squidaiostate_t() -{ -} +{} void squidaiostate_t::ioCompletedNotification() { if (opening) { - opening = false; - openDone(); - return; + opening = false; + openDone(); + return; } + if (creating) { - creating = false; - openDone(); - return; + creating = false; + openDone(); + return; } + assert (0); } @@ -499,22 +569,26 @@ squidaiostate_t::closeCompleted() assert (0); } -void +void squidaiostate_t::openDone() { if (theFile->error()) { - storeAufsIOCallback(this, DISK_ERROR); - return; + storeAufsIOCallback(this, DISK_ERROR); + return; } + fd = theFile->getFD(); + if (FILE_MODE(mode) == O_WRONLY) { - if (kickWriteQueue()) - return; + if (kickWriteQueue()) + return; } else if ((FILE_MODE(mode) == O_RDONLY) && !closing) { - if (kickReadQueue()) - return; + if (kickReadQueue()) + return; } + if (closing) - storeAufsIOCallback(this, theFile->error() ? -1 : 0); + storeAufsIOCallback(this, theFile->error() ? -1 : 0); + debug(79, 3) ("squidaiostate_t::openDone: exiting\n"); } diff --git a/src/fs/coss/async_io.cc b/src/fs/coss/async_io.cc index 9c244da9f6..252fcbb175 100644 --- a/src/fs/coss/async_io.cc +++ b/src/fs/coss/async_io.cc @@ -11,7 +11,7 @@ * supports are read/write, and since COSS works on a single file * per storedir it should work just fine. * - * $Id: async_io.cc,v 1.13 2003/01/23 00:38:13 robertc Exp $ + * $Id: async_io.cc,v 1.14 2003/02/21 22:50:39 robertc Exp $ */ #include "squid.h" @@ -39,11 +39,13 @@ a_file_findslot(async_queue_t * q) int i; /* Later we should use something a little more .. efficient :) */ + for (i = 0; i < MAX_ASYNCOP; i++) { - if (q->aq_queue[i].aq_e_state == AQ_ENTRY_FREE) - /* Found! */ - return i; + if (q->aq_queue[i].aq_e_state == AQ_ENTRY_FREE) + /* Found! */ + return i; } + /* found nothing */ return -1; } @@ -55,7 +57,7 @@ a_file_findslot(async_queue_t * q) void a_file_read(async_queue_t * q, int fd, void *buf, int req_len, off_t offset, - DRCB * callback, void *data) + DRCB * callback, void *data) { int slot; async_queue_entry_t *qe; @@ -63,27 +65,40 @@ a_file_read(async_queue_t * q, int fd, void *buf, int req_len, off_t offset, assert(q->aq_state == AQ_STATE_SETUP); #if 0 + file_read(fd, buf, req_len, offset, callback, data); #endif /* Find a free slot */ slot = a_file_findslot(q); + if (slot < 0) { - /* No free slot? Callback error, and return */ - fatal("Aiee! out of aiocb slots!\n"); + /* No free slot? Callback error, and return */ + fatal("Aiee! out of aiocb slots!\n"); } + /* Mark slot as ours */ qe = &q->aq_queue[slot]; + qe->aq_e_state = AQ_ENTRY_USED; + qe->aq_e_callback.read = callback; + qe->aq_e_callback_data = cbdataReference(data); + qe->aq_e_type = AQ_ENTRY_READ; + qe->aq_e_free = NULL; + qe->aq_e_buf = buf; + qe->aq_e_fd = fd; qe->aq_e_aiocb.aio_fildes = fd; + qe->aq_e_aiocb.aio_nbytes = req_len; + qe->aq_e_aiocb.aio_offset = offset; + qe->aq_e_aiocb.aio_buf = buf; /* Account */ @@ -91,14 +106,14 @@ a_file_read(async_queue_t * q, int fd, void *buf, int req_len, off_t offset, /* Initiate aio */ if (aio_read(&qe->aq_e_aiocb) < 0) { - fatalf("Aiee! aio_read() returned error (%d)!\n", errno); + fatalf("Aiee! aio_read() returned error (%d)!\n", errno); } } void a_file_write(async_queue_t * q, int fd, off_t offset, void *buf, int len, - DWCB * callback, void *data, FREE * freefunc) + DWCB * callback, void *data, FREE * freefunc) { int slot; async_queue_entry_t *qe; @@ -106,27 +121,40 @@ a_file_write(async_queue_t * q, int fd, off_t offset, void *buf, int len, assert(q->aq_state == AQ_STATE_SETUP); #if 0 + file_write(fd, offset, buf, len, callback, data, freefunc); #endif /* Find a free slot */ slot = a_file_findslot(q); + if (slot < 0) { - /* No free slot? Callback error, and return */ - fatal("Aiee! out of aiocb slots!\n"); + /* No free slot? Callback error, and return */ + fatal("Aiee! out of aiocb slots!\n"); } + /* Mark slot as ours */ qe = &q->aq_queue[slot]; + qe->aq_e_state = AQ_ENTRY_USED; + qe->aq_e_callback.write = callback; + qe->aq_e_callback_data = cbdataReference(data); + qe->aq_e_type = AQ_ENTRY_WRITE; + qe->aq_e_free = freefunc; + qe->aq_e_buf = buf; + qe->aq_e_fd = fd; qe->aq_e_aiocb.aio_fildes = fd; + qe->aq_e_aiocb.aio_nbytes = len; + qe->aq_e_aiocb.aio_offset = offset; + qe->aq_e_aiocb.aio_buf = buf; /* Account */ @@ -134,8 +162,8 @@ a_file_write(async_queue_t * q, int fd, off_t offset, void *buf, int len, /* Initiate aio */ if (aio_write(&qe->aq_e_aiocb) < 0) { - fatalf("Aiee! aio_read() returned error (%d)!\n", errno); - assert(1 == 0); + fatalf("Aiee! aio_read() returned error (%d)!\n", errno); + assert(1 == 0); } } @@ -167,44 +195,51 @@ a_file_callback(async_queue_t * q) assert(q->aq_state == AQ_STATE_SETUP); /* Loop through all slots */ + for (i = 0; i < MAX_ASYNCOP; i++) { - if (q->aq_queue[i].aq_e_state == AQ_ENTRY_USED) { - aqe = &q->aq_queue[i]; - /* Active, get status */ - reterr = aio_error(&aqe->aq_e_aiocb); - if (reterr < 0) { - fatal("aio_error returned an error!\n"); - } - if (reterr != EINPROGRESS) { - /* Get the return code */ - retval = aio_return(&aqe->aq_e_aiocb); - - /* Get the callback parameters */ - freefunc = aqe->aq_e_free; - rc = aqe->aq_e_callback.read; - wc = aqe->aq_e_callback.write; - buf = aqe->aq_e_buf; - fd = aqe->aq_e_fd; - type = aqe->aq_e_type; - callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata); - - /* Free slot */ - bzero(aqe, sizeof(async_queue_entry_t)); - aqe->aq_e_state = AQ_ENTRY_FREE; - q->aq_numpending--; - - /* Callback */ - if (callback_valid) { - if (type == AQ_ENTRY_READ) - rc(fd, (char *)buf, retval, reterr, cbdata); - if (type == AQ_ENTRY_WRITE) - wc(fd, reterr, retval, cbdata); - } - if (type == AQ_ENTRY_WRITE && freefunc) - freefunc(buf); - } - } + if (q->aq_queue[i].aq_e_state == AQ_ENTRY_USED) { + aqe = &q->aq_queue[i]; + /* Active, get status */ + reterr = aio_error(&aqe->aq_e_aiocb); + + if (reterr < 0) { + fatal("aio_error returned an error!\n"); + } + + if (reterr != EINPROGRESS) { + /* Get the return code */ + retval = aio_return(&aqe->aq_e_aiocb); + + /* Get the callback parameters */ + freefunc = aqe->aq_e_free; + rc = aqe->aq_e_callback.read; + wc = aqe->aq_e_callback.write; + buf = aqe->aq_e_buf; + fd = aqe->aq_e_fd; + type = aqe->aq_e_type; + callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata); + + /* Free slot */ + bzero(aqe, sizeof(async_queue_entry_t)); + aqe->aq_e_state = AQ_ENTRY_FREE; + q->aq_numpending--; + + /* Callback */ + + if (callback_valid) { + if (type == AQ_ENTRY_READ) + rc(fd, (char *)buf, retval, reterr, cbdata); + + if (type == AQ_ENTRY_WRITE) + wc(fd, reterr, retval, cbdata); + } + + if (type == AQ_ENTRY_WRITE && freefunc) + freefunc(buf); + } + } } + return completed; } @@ -232,8 +267,9 @@ a_file_syncqueue(async_queue_t * q) * We can't quit when callback returns 0 - some calls may not * return any completed pending events, but they're still pending! */ + while (q->aq_numpending) - a_file_callback(q); + a_file_callback(q); } diff --git a/src/fs/coss/async_io.h b/src/fs/coss/async_io.h index 6ad7b2e5ca..b09f428de4 100644 --- a/src/fs/coss/async_io.h +++ b/src/fs/coss/async_io.h @@ -21,16 +21,20 @@ typedef enum { typedef struct _async_queue_entry async_queue_entry_t; + typedef struct _async_queue async_queue_t; /* An async queue entry */ -struct _async_queue_entry { + +struct _async_queue_entry +{ async_queue_entry_state_t aq_e_state; async_queue_entry_type_t aq_e_type; + struct aiocb aq_e_aiocb; union { - DRCB *read; - DWCB *write; + DRCB *read; + DWCB *write; } aq_e_callback; void *aq_e_callback_data; FREE *aq_e_free; @@ -39,7 +43,9 @@ struct _async_queue_entry { }; /* An async queue */ -struct _async_queue { + +struct _async_queue +{ async_queue_state_t aq_state; async_queue_entry_t aq_queue[MAX_ASYNCOP]; /* queued ops */ int aq_numpending; /* Num of pending ops */ @@ -48,9 +54,9 @@ struct _async_queue { /* Functions */ extern void a_file_read(async_queue_t * q, int fd, void *buf, int req_len, - off_t offset, DRCB * callback, void *data); + off_t offset, DRCB * callback, void *data); extern void a_file_write(async_queue_t * q, int fd, off_t offset, void *buf, - int len, DWCB * callback, void *data, FREE * freefunc); + int len, DWCB * callback, void *data, FREE * freefunc); extern int a_file_callback(async_queue_t * q); extern void a_file_setupqueue(async_queue_t * q); extern void a_file_syncqueue(async_queue_t * q); diff --git a/src/fs/coss/store_coss.h b/src/fs/coss/store_coss.h index 2d3e9d173e..776e08af47 100644 --- a/src/fs/coss/store_coss.h +++ b/src/fs/coss/store_coss.h @@ -21,21 +21,33 @@ #define COSS_ALLOC_NOTIFY 0 #define COSS_ALLOC_ALLOCATE 1 #define COSS_ALLOC_REALLOC 2 + class CossSwapDir; -struct _cossmembuf { + +struct _cossmembuf +{ dlink_node node; size_t diskstart; /* in blocks */ size_t diskend; /* in blocks */ CossSwapDir *SD; int lockcount; char buffer[COSS_MEMBUF_SZ]; - struct _cossmembuf_flags { - unsigned int full:1; - unsigned int writing:1; - } flags; + + struct _cossmembuf_flags + { + +unsigned int full: + 1; + +unsigned int writing: + 1; + } + + flags; }; -struct _cossindex { +struct _cossindex +{ /* Note: the dlink_node MUST be the first member of the structure. * This member is later pointer typecasted to coss_index_node *. */ @@ -45,9 +57,13 @@ struct _cossindex { /* Per-storeiostate info */ -class CossState : public storeIOState { + +class CossState : public storeIOState +{ + public: virtual void deleteSelf() const {delete this;} + void * operator new (size_t); void operator delete (void *); CossState(CossSwapDir *); @@ -58,21 +74,31 @@ public: size_t requestlen; size_t requestoffset; /* in blocks */ sfileno reqdiskoffset; /* in blocks */ - struct { - unsigned int reading:1; - unsigned int writing:1; - } flags; + + struct + { + +unsigned int reading: + 1; + +unsigned int writing: + 1; + } + + flags; size_t st_size; void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data); void write(char const *buf, size_t size, off_t offset, FREE * free_func); void close(); CossSwapDir *SD; + private: static MemPool *Pool; }; typedef struct _cossmembuf CossMemBuf; + typedef struct _cossindex CossIndexNode; /* Whether the coss system has been setup or not */ @@ -80,8 +106,9 @@ extern int coss_initialised; extern MemPool *coss_membuf_pool; extern MemPool *coss_index_pool; -class CossSwapDir : public SwapDir +class CossSwapDir : public SwapDir { + public: CossSwapDir(); virtual void init(); @@ -102,11 +129,12 @@ public: virtual void logEntry(const StoreEntry & e, int op) const; virtual void parse (int index, char *path); virtual void reconfigure (int, char *); -//private: + //private: int fd; int swaplog_fd; int count; dlink_list membufs; + struct _cossmembuf *current_membuf; size_t current_offset; /* in Blocks */ int numcollisions; diff --git a/src/fs/coss/store_dir_coss.cc b/src/fs/coss/store_dir_coss.cc index 577adf4b82..a576423716 100644 --- a/src/fs/coss/store_dir_coss.cc +++ b/src/fs/coss/store_dir_coss.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir_coss.cc,v 1.43 2003/01/23 00:38:13 robertc Exp $ + * $Id: store_dir_coss.cc,v 1.44 2003/02/21 22:50:39 robertc Exp $ * * DEBUG: section 47 Store COSS Directory Routines * AUTHOR: Eric Stern @@ -50,29 +50,38 @@ int coss_initialised = 0; MemPool *coss_index_pool = NULL; typedef struct _RebuildState RebuildState; -struct _RebuildState { + +struct _RebuildState +{ CossSwapDir *sd; int n_read; FILE *log; int speed; - struct { - unsigned int clean:1; - } flags; + + struct + { + +unsigned int clean: + 1; + } + + flags; + struct _store_rebuild_data counts; }; static char *storeCossDirSwapLogFile(SwapDir *, const char *); static EVH storeCossRebuildFromSwapLog; static StoreEntry *storeCossAddDiskRestore(CossSwapDir * SD, const cache_key * key, - int file_number, - size_t swap_file_sz, - time_t expires, - time_t timestamp, - time_t lastref, - time_t lastmod, - u_int32_t refcount, - u_int16_t flags, - int clean); + int file_number, + size_t swap_file_sz, + time_t expires, + time_t timestamp, + time_t lastref, + time_t lastmod, + u_int32_t refcount, + u_int16_t flags, + int clean); static void storeCossDirRebuild(CossSwapDir * sd); static void storeCossDirCloseTmpSwapLog(CossSwapDir * sd); static FILE *storeCossDirOpenTmpSwapLog(CossSwapDir *, int *, int *); @@ -87,26 +96,35 @@ storeCossDirSwapLogFile(SwapDir * sd, const char *ext) LOCAL_ARRAY(char, pathtmp, SQUID_MAXPATHLEN); LOCAL_ARRAY(char, digit, 32); char *pathtmp2; + if (Config.Log.swap) { - xstrncpy(pathtmp, sd->path, SQUID_MAXPATHLEN - 64); - pathtmp2 = pathtmp; - while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL) - *pathtmp2 = '.'; - while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.') - pathtmp[strlen(pathtmp) - 1] = '\0'; - for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++); - snprintf(path, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2); - if (strncmp(path, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) { - strcat(path, "."); - snprintf(digit, 32, "%02d", sd->index); - strncat(path, digit, 3); - } + xstrncpy(pathtmp, sd->path, SQUID_MAXPATHLEN - 64); + pathtmp2 = pathtmp; + + while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL) + *pathtmp2 = '.'; + + while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.') + pathtmp[strlen(pathtmp) - 1] = '\0'; + + for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++) + + ; + snprintf(path, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2); + + if (strncmp(path, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) { + strcat(path, "."); + snprintf(digit, 32, "%02d", sd->index); + strncat(path, digit, 3); + } } else { - xstrncpy(path, sd->path, SQUID_MAXPATHLEN - 64); - strcat(path, "/swap.state"); + xstrncpy(path, sd->path, SQUID_MAXPATHLEN - 64); + strcat(path, "/swap.state"); } + if (ext) - strncat(path, ext, 16); + strncat(path, ext, 16); + return path; } @@ -116,10 +134,12 @@ CossSwapDir::openLog() char *logPath; logPath = storeCossDirSwapLogFile(this, NULL); swaplog_fd = file_open(logPath, O_WRONLY | O_CREAT | O_BINARY); + if (swaplog_fd < 0) { - debug(47, 1) ("%s: %s\n", logPath, xstrerror()); - fatal("storeCossDirOpenSwapLog: Failed to open swap log."); + debug(47, 1) ("%s: %s\n", logPath, xstrerror()); + fatal("storeCossDirOpenSwapLog: Failed to open swap log."); } + debug(47, 3) ("Cache COSS Dir #%d log opened on FD %d\n", index, swaplog_fd); } @@ -127,10 +147,13 @@ void CossSwapDir::closeLog() { if (swaplog_fd < 0) /* not open */ - return; + return; + file_close(swaplog_fd); + debug(47, 3) ("Cache COSS Dir #%d log closed on FD %d\n", - index, swaplog_fd); + index, swaplog_fd); + swaplog_fd = -1; } @@ -141,10 +164,12 @@ CossSwapDir::init() openLog(); storeCossDirRebuild(this); fd = file_open(path, O_RDWR | O_CREAT); + if (fd < 0) { - debug(47, 1) ("%s: %s\n", path, xstrerror()); - fatal("storeCossDirInit: Failed to open a COSS directory."); + debug(47, 1) ("%s: %s\n", path, xstrerror()); + fatal("storeCossDirInit: Failed to open a COSS directory."); } + n_coss_dirs++; (void) storeDirGetBlkSize(path, &fs.blksize); } @@ -191,87 +216,110 @@ storeCossRebuildFromSwapLog(void *data) double x; assert(rb != NULL); /* load a number of objects per invocation */ + for (int aCount = 0; aCount < rb->speed; aCount++) { - if (fread(&s, ss, 1, rb->log) != 1) { - debug(47, 1) ("Done reading %s swaplog (%d entries)\n", - rb->sd->path, rb->n_read); - fclose(rb->log); - rb->log = NULL; - storeCossRebuildComplete(rb); - return; - } - rb->n_read++; - if (s.op <= SWAP_LOG_NOP) - continue; - if (s.op >= SWAP_LOG_MAX) - continue; - debug(47, 3) ("storeCossRebuildFromSwapLog: %s %s %08X\n", - swap_log_op_str[(int) s.op], - storeKeyText(s.key), - s.swap_filen); - if (s.op == SWAP_LOG_ADD) { - (void) 0; - } else if (s.op == SWAP_LOG_DEL) { - /* Delete unless we already have a newer copy */ - if ((e = storeGet(s.key)) != NULL && s.lastref > e->lastref) { - /* - * Make sure we don't unlink the file, it might be - * in use by a subsequent entry. Also note that - * we don't have to subtract from store_swap_size - * because adding to store_swap_size happens in - * the cleanup procedure. - */ - storeExpireNow(e); - storeReleaseRequest(e); - if (e->swap_filen > -1) { - e->swap_filen = -1; - } - storeRelease(e); - /* Fake an unlink here, this is a bad hack :( */ - storeCossRemove(rb->sd, e); - rb->counts.objcount--; - rb->counts.cancelcount++; - } - continue; - } else { - x = log(++rb->counts.bad_log_op) / log(10.0); - if (0.0 == x - (double) (int) x) - debug(47, 1) ("WARNING: %d invalid swap log entries found\n", - rb->counts.bad_log_op); - rb->counts.invalid++; - continue; - } - if ((++rb->counts.scancount & 0xFFF) == 0) { - struct stat sb; - if (0 == fstat(fileno(rb->log), &sb)) - storeRebuildProgress(rb->sd->index, - (int) sb.st_size / ss, rb->n_read); - } - if (EBIT_TEST(s.flags, KEY_PRIVATE)) { - rb->counts.badflags++; - continue; - } - e = storeGet(s.key); - if (e) { - /* key already exists, current entry is newer */ - /* keep old, ignore new */ - rb->counts.dupcount++; - continue; - } - /* update store_swap_size */ - rb->counts.objcount++; - e = storeCossAddDiskRestore(rb->sd, s.key, - s.swap_filen, - s.swap_file_sz, - s.expires, - s.timestamp, - s.lastref, - s.lastmod, - s.refcount, - s.flags, - (int) rb->flags.clean); - storeDirSwapLog(e, SWAP_LOG_ADD); + if (fread(&s, ss, 1, rb->log) != 1) { + debug(47, 1) ("Done reading %s swaplog (%d entries)\n", + rb->sd->path, rb->n_read); + fclose(rb->log); + rb->log = NULL; + storeCossRebuildComplete(rb); + return; + } + + rb->n_read++; + + if (s.op <= SWAP_LOG_NOP) + continue; + + if (s.op >= SWAP_LOG_MAX) + continue; + + debug(47, 3) ("storeCossRebuildFromSwapLog: %s %s %08X\n", + swap_log_op_str[(int) s.op], + storeKeyText(s.key), + s.swap_filen); + + if (s.op == SWAP_LOG_ADD) { + (void) 0; + } else if (s.op == SWAP_LOG_DEL) { + /* Delete unless we already have a newer copy */ + + if ((e = storeGet(s.key)) != NULL && s.lastref > e->lastref) { + /* + * Make sure we don't unlink the file, it might be + * in use by a subsequent entry. Also note that + * we don't have to subtract from store_swap_size + * because adding to store_swap_size happens in + * the cleanup procedure. + */ + storeExpireNow(e); + storeReleaseRequest(e); + + if (e->swap_filen > -1) { + e->swap_filen = -1; + } + + storeRelease(e); + /* Fake an unlink here, this is a bad hack :( */ + storeCossRemove(rb->sd, e); + rb->counts.objcount--; + rb->counts.cancelcount++; + } + + continue; + } else { + x = log(++rb->counts.bad_log_op) / log(10.0); + + if (0.0 == x - (double) (int) x) + debug(47, 1) ("WARNING: %d invalid swap log entries found\n", + rb->counts.bad_log_op); + + rb->counts.invalid++; + + continue; + } + + if ((++rb->counts.scancount & 0xFFF) == 0) { + + struct stat sb; + + if (0 == fstat(fileno(rb->log), &sb)) + storeRebuildProgress(rb->sd->index, + (int) sb.st_size / ss, rb->n_read); + } + + if (EBIT_TEST(s.flags, KEY_PRIVATE)) { + rb->counts.badflags++; + continue; + } + + e = storeGet(s.key); + + if (e) { + /* key already exists, current entry is newer */ + /* keep old, ignore new */ + rb->counts.dupcount++; + continue; + } + + /* update store_swap_size */ + rb->counts.objcount++; + + e = storeCossAddDiskRestore(rb->sd, s.key, + s.swap_filen, + s.swap_file_sz, + s.expires, + s.timestamp, + s.lastref, + s.lastmod, + s.refcount, + s.flags, + (int) rb->flags.clean); + + storeDirSwapLog(e, SWAP_LOG_ADD); } + eventAdd("storeCossRebuild", storeCossRebuildFromSwapLog, rb, 0.0, 1); } @@ -279,19 +327,19 @@ storeCossRebuildFromSwapLog(void *data) * use to rebuild store from disk. */ static StoreEntry * storeCossAddDiskRestore(CossSwapDir * SD, const cache_key * key, - int file_number, - size_t swap_file_sz, - time_t expires, - time_t timestamp, - time_t lastref, - time_t lastmod, - u_int32_t refcount, - u_int16_t flags, - int clean) + int file_number, + size_t swap_file_sz, + time_t expires, + time_t timestamp, + time_t lastref, + time_t lastmod, + u_int32_t refcount, + u_int16_t flags, + int clean) { StoreEntry *e = NULL; debug(47, 5) ("storeCossAddDiskRestore: %s, fileno=%08X\n", storeKeyText(key), file_number); - /* if you call this you'd better be sure file_number is not + /* if you call this you'd better be sure file_number is not * already in use! */ e = new_StoreEntry(STORE_ENTRY_WITHOUT_MEMOBJ, NULL, NULL); e->store_status = STORE_OK; @@ -339,26 +387,31 @@ storeCossDirRebuild(CossSwapDir * sd) */ fp = storeCossDirOpenTmpSwapLog(sd, &clean, &zero); debug(47, 1) ("Rebuilding COSS storage in %s (%s)\n", - sd->path, clean ? "CLEAN" : "DIRTY"); + sd->path, clean ? "CLEAN" : "DIRTY"); rb->log = fp; store_dirs_rebuilding++; + if (!clean || fp == NULL) { - /* COSS cannot yet rebuild from a dirty state. If the log - * is dirty then the COSS contents is thrown away. - * Why? I guess it is because some contents will be lost, - * and COSS cannot verify this.. - */ - if (fp != NULL) - fclose(fp); - /* - * XXX Make sure we don't trigger an assertion if this is the first - * storedir, since if we are, this call will cause storeRebuildComplete - * to prematurely complete the rebuild process, and then some other - * storedir will try to rebuild and eventually die. - */ - eventAdd("storeCossRebuildComplete", storeCossRebuildComplete, rb, 0.0, 0); - return; + /* COSS cannot yet rebuild from a dirty state. If the log + * is dirty then the COSS contents is thrown away. + * Why? I guess it is because some contents will be lost, + * and COSS cannot verify this.. + */ + + if (fp != NULL) + fclose(fp); + + /* + * XXX Make sure we don't trigger an assertion if this is the first + * storedir, since if we are, this call will cause storeRebuildComplete + * to prematurely complete the rebuild process, and then some other + * storedir will try to rebuild and eventually die. + */ + eventAdd("storeCossRebuildComplete", storeCossRebuildComplete, rb, 0.0, 0); + + return; } + eventAdd("storeCossRebuild", func, rb, 0.0, 1); } @@ -370,19 +423,24 @@ storeCossDirCloseTmpSwapLog(CossSwapDir * sd) int anfd; file_close(sd->swaplog_fd); #if defined (_SQUID_OS2_) || defined (_SQUID_CYGWIN_) + if (unlink(swaplog_path) < 0) { - debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); - fatal("storeCossDirCloseTmpSwapLog: unlink failed"); + debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); + fatal("storeCossDirCloseTmpSwapLog: unlink failed"); } + #endif if (xrename(new_path, swaplog_path) < 0) { - fatal("storeCossDirCloseTmpSwapLog: rename failed"); + fatal("storeCossDirCloseTmpSwapLog: rename failed"); } + anfd = file_open(swaplog_path, O_WRONLY | O_CREAT | O_BINARY); + if (anfd < 0) { - debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror()); - fatal("storeCossDirCloseTmpSwapLog: Failed to open swap log."); + debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror()); + fatal("storeCossDirCloseTmpSwapLog: Failed to open swap log."); } + safe_free(swaplog_path); safe_free(new_path); sd->swaplog_fd = anfd; @@ -395,50 +453,68 @@ storeCossDirOpenTmpSwapLog(CossSwapDir * sd, int *clean_flag, int *zero_flag) char *swaplog_path = xstrdup(storeCossDirSwapLogFile(sd, NULL)); char *clean_path = xstrdup(storeCossDirSwapLogFile(sd, ".last-clean")); char *new_path = xstrdup(storeCossDirSwapLogFile(sd, ".new")); + struct stat log_sb; + struct stat clean_sb; FILE *fp; int anfd; + if (stat(swaplog_path, &log_sb) < 0) { - debug(50, 1) ("Cache COSS Dir #%d: No log file\n", sd->index); -safe_free(swaplog_path); - safe_free(clean_path); - safe_free(new_path); - return NULL; + debug(50, 1) ("Cache COSS Dir #%d: No log file\n", sd->index); + safe_free(swaplog_path); + safe_free(clean_path); + safe_free(new_path); + return NULL; } + *zero_flag = log_sb.st_size == 0 ? 1 : 0; /* close the existing write-only FD */ + if (sd->swaplog_fd >= 0) - file_close(sd->swaplog_fd); + file_close(sd->swaplog_fd); + /* open a write-only FD for the new log */ anfd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); + if (anfd < 0) { - debug(50, 1) ("%s: %s\n", new_path, xstrerror()); - fatal("storeDirOpenTmpSwapLog: Failed to open swap log."); + debug(50, 1) ("%s: %s\n", new_path, xstrerror()); + fatal("storeDirOpenTmpSwapLog: Failed to open swap log."); } + sd->swaplog_fd = anfd; /* open a read-only stream of the old log */ fp = fopen(swaplog_path, "rb"); + if (fp == NULL) { - debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); - fatal("Failed to open swap log for reading"); + debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); + fatal("Failed to open swap log for reading"); } + memset(&clean_sb, '\0', sizeof(struct stat)); + if (stat(clean_path, &clean_sb) < 0) - *clean_flag = 0; + *clean_flag = 0; else if (clean_sb.st_mtime < log_sb.st_mtime) - *clean_flag = 0; + *clean_flag = 0; else - *clean_flag = 1; + *clean_flag = 1; + safeunlink(clean_path, 1); + safe_free(swaplog_path); + safe_free(clean_path); + safe_free(new_path); + return fp; } -class CossCleanLog : public SwapDir::CleanLog { - public: +class CossCleanLog : public SwapDir::CleanLog +{ + +public: CossCleanLog(SwapDir *); virtual const StoreEntry *nextEntry(); virtual void write(StoreEntry const &); @@ -455,9 +531,8 @@ class CossCleanLog : public SwapDir::CleanLog { #define CLEAN_BUF_SZ 16384 CossCleanLog::CossCleanLog(SwapDir *aSwapDir) : cur(NULL),newLog(NULL),cln(NULL),outbuf(NULL), - outbuf_offset(0), fd(-1),current(NULL), sd(aSwapDir) -{ -} + outbuf_offset(0), fd(-1),current(NULL), sd(aSwapDir) +{} /* * Begin the process to write clean cache state. For COSS this means @@ -469,16 +544,20 @@ CossSwapDir::writeCleanStart() { CossCleanLog *state = new CossCleanLog(this); #if HAVE_FCHMOD + struct stat sb; #endif + state->newLog = xstrdup(storeCossDirSwapLogFile(this, ".clean")); state->fd = file_open(state->newLog, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); cleanLog = NULL; + if (state->fd < 0) { - xfree(state->newLog); - delete state; - return -1; + xfree(state->newLog); + delete state; + return -1; } + state->cur = xstrdup(storeCossDirSwapLogFile(this, NULL)); state->cln = xstrdup(storeCossDirSwapLogFile(this, ".last-clean")); state->outbuf = (char *)xcalloc(CLEAN_BUF_SZ, 1); @@ -486,11 +565,14 @@ CossSwapDir::writeCleanStart() ::unlink(state->cln); state->current = cossindex.tail; debug(50, 3) ("storeCOssDirWriteCleanLogs: opened %s, FD %d\n", - state->newLog, state->fd); + state->newLog, state->fd); #if HAVE_FCHMOD + if (stat(state->cur, &sb) == 0) - fchmod(state->fd, sb.st_mode); + fchmod(state->fd, sb.st_mode); + #endif + cleanLog = state; return 0; @@ -500,10 +582,14 @@ const StoreEntry * CossCleanLog::nextEntry() { const StoreEntry *entry; + if (!current) - return NULL; + return NULL; + entry = (const StoreEntry *) current->data; + current = current->prev; + return entry; } @@ -530,19 +616,21 @@ CossCleanLog::write(StoreEntry const &e) xmemcpy(state->outbuf + state->outbuf_offset, &s, ss); state->outbuf_offset += ss; /* buffered write */ + if (state->outbuf_offset + ss > CLEAN_BUF_SZ) { - if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { - debug(50, 0) ("storeCossDirWriteCleanLogs: %s: write: %s\n", - state->newLog, xstrerror()); - debug(50, 0) ("storeCossDirWriteCleanLogs: Current swap logfile not replaced.\n"); - file_close(state->fd); - state->fd = -1; - unlink(state->newLog); - delete state; - sd->cleanLog = NULL; - return; - } - state->outbuf_offset = 0; + if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { + debug(50, 0) ("storeCossDirWriteCleanLogs: %s: write: %s\n", + state->newLog, xstrerror()); + debug(50, 0) ("storeCossDirWriteCleanLogs: Current swap logfile not replaced.\n"); + file_close(state->fd); + state->fd = -1; + unlink(state->newLog); + delete state; + sd->cleanLog = NULL; + return; + } + + state->outbuf_offset = 0; } } @@ -550,19 +638,23 @@ void CossSwapDir::writeCleanDone() { CossCleanLog *state = (CossCleanLog *)cleanLog; + if (NULL == state) - return; + return; + if (state->fd < 0) - return; + return; + if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { - debug(50, 0) ("storeCossDirWriteCleanLogs: %s: write: %s\n", - state->newLog, xstrerror()); - debug(50, 0) ("storeCossDirWriteCleanLogs: Current swap logfile " - "not replaced.\n"); - file_close(state->fd); - state->fd = -1; - ::unlink(state->newLog); + debug(50, 0) ("storeCossDirWriteCleanLogs: %s: write: %s\n", + state->newLog, xstrerror()); + debug(50, 0) ("storeCossDirWriteCleanLogs: Current swap logfile " + "not replaced.\n"); + file_close(state->fd); + state->fd = -1; + ::unlink(state->newLog); } + safe_free(state->outbuf); /* * You can't rename open files on Microsoft "operating systems" @@ -572,31 +664,43 @@ CossSwapDir::writeCleanDone() /* save the fd value for a later test */ int anfd = state->fd; /* rename */ + if (state->fd >= 0) { #if defined(_SQUID_OS2_) || defined (_SQUID_CYGWIN_) - file_close(state->fd); - state->fd = -1; - if (unlink(state->cur) < 0) - debug(50, 0) ("storeCossDirWriteCleanLogs: unlinkd failed: %s, %s\n", - xstrerror(), state->cur); + file_close(state->fd); + state->fd = -1; + + if (unlink(state->cur) < 0) + debug(50, 0) ("storeCossDirWriteCleanLogs: unlinkd failed: %s, %s\n", + xstrerror(), state->cur); + #endif - xrename(state->newLog, state->cur); + + xrename(state->newLog, state->cur); } + /* touch a timestamp file if we're not still validating */ if (store_dirs_rebuilding) - (void) 0; + (void) 0; else if (anfd < 0) - (void) 0; + (void) 0; else - file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)); + file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)); + /* close */ safe_free(state->cur); + safe_free(state->newLog); + safe_free(state->cln); + if (state->fd >= 0) - file_close(state->fd); + file_close(state->fd); + state->fd = -1; + delete state; + cleanLog = NULL; } @@ -621,12 +725,12 @@ CossSwapDir::logEntry(const StoreEntry & e, int op) const s->flags = e.flags; xmemcpy(s->key, e.key, MD5_DIGEST_CHARS); file_write(swaplog_fd, - -1, - s, - sizeof(storeSwapLogData), - NULL, - NULL, - (FREE *) storeSwapLogDataFree); + -1, + s, + sizeof(storeSwapLogData), + NULL, + NULL, + (FREE *) storeSwapLogDataFree); } void @@ -662,12 +766,14 @@ CossSwapDir::canStore(StoreEntry const &e)const int loadav; /* Check if the object is a special object, we can't cache these */ + if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) - return -1; + return -1; /* Otherwise, we're ok */ /* Return load, cs->aq.aq_numpending out of MAX_ASYNCOP */ loadav = aq.aq_numpending * 1000 / MAX_ASYNCOP; + return loadav; } @@ -689,20 +795,24 @@ CossSwapDir::statfs(StoreEntry & sentry) const storeAppendPrintf(&sentry, "Maximum Size: %d KB\n", max_size); storeAppendPrintf(&sentry, "Current Size: %d KB\n", cur_size); storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n", - 100.0 * cur_size / max_size); + 100.0 * cur_size / max_size); storeAppendPrintf(&sentry, "Number of object collisions: %d\n", (int) numcollisions); #if 0 /* is this applicable? I Hope not .. */ storeAppendPrintf(sentry, "Filemap bits in use: %d of %d (%d%%)\n", - SD->map->n_files_in_map, SD->map->max_n_files, - percent(SD->map->n_files_in_map, SD->map->max_n_files)); + SD->map->n_files_in_map, SD->map->max_n_files, + percent(SD->map->n_files_in_map, SD->map->max_n_files)); #endif + storeAppendPrintf(&sentry, "Pending operations: %d out of %d\n", aq.aq_numpending, MAX_ASYNCOP); storeAppendPrintf(&sentry, "Flags:"); + if (flags.selected) - storeAppendPrintf(&sentry, " SELECTED"); + storeAppendPrintf(&sentry, " SELECTED"); + if (flags.read_only) - storeAppendPrintf(&sentry, " READ-ONLY"); + storeAppendPrintf(&sentry, " READ-ONLY"); + storeAppendPrintf(&sentry, "\n"); } @@ -714,17 +824,21 @@ CossSwapDir::parse(int anIndex, char *aPath) i = GetInteger(); size = i << 10; /* Mbytes to Kbytes */ + if (size <= 0) - fatal("storeCossDirParse: invalid size value"); + fatal("storeCossDirParse: invalid size value"); index = anIndex; + path = xstrdup(aPath); + max_size = size; parse_cachedir_options(this, NULL, 0); + /* Enforce maxobjsize being set to something */ if (max_objsize == -1) - fatal("COSS requires max-size to be set to something other than -1!\n"); + fatal("COSS requires max-size to be set to something other than -1!\n"); } @@ -736,26 +850,29 @@ CossSwapDir::reconfigure(int index, char *path) i = GetInteger(); size = i << 10; /* Mbytes to Kbytes */ + if (size <= 0) - fatal("storeCossDirParse: invalid size value"); + fatal("storeCossDirParse: invalid size value"); if (size == (size_t)max_size) - debug(3, 1) ("Cache COSS dir '%s' size remains unchanged at %d KB\n", path, size); + debug(3, 1) ("Cache COSS dir '%s' size remains unchanged at %d KB\n", path, size); else { - debug(3, 1) ("Cache COSS dir '%s' size changed to %d KB\n", path, size); - max_size = size; + debug(3, 1) ("Cache COSS dir '%s' size changed to %d KB\n", path, size); + max_size = size; } + parse_cachedir_options(this, NULL, 1); /* Enforce maxobjsize being set to something */ + if (max_objsize == -1) - fatal("COSS requires max-size to be set to something other than -1!\n"); + fatal("COSS requires max-size to be set to something other than -1!\n"); } void CossSwapDir::dump(StoreEntry &entry)const { storeAppendPrintf(&entry, " %d", - max_size >> 20); + max_size >> 20); dump_cachedir_options(&entry, NULL, this); } @@ -767,37 +884,43 @@ storeCossDirPick(void) SwapDir *SD; if (n_coss_dirs == 0) - return NULL; + return NULL; + for (i = 0; i < Config.cacheSwap.n_configured; i++) { - SD = &Config.cacheSwap.swapDirs[i]; - if (SD->type == SWAPDIR_COSS) { - if ((last_coss_pick_index == -1) || (n_coss_dirs == 1)) { - last_coss_pick_index = i; - return SD; - } else if (choosenext) { - last_coss_pick_index = i; - return SD; - } else if (last_coss_pick_index == i) { - choosenext = 1; - } - } + SD = &Config.cacheSwap.swapDirs[i]; + + if (SD->type == SWAPDIR_COSS) { + if ((last_coss_pick_index == -1) || (n_coss_dirs == 1)) { + last_coss_pick_index = i; + return SD; + } else if (choosenext) { + last_coss_pick_index = i; + return SD; + } else if (last_coss_pick_index == i) { + choosenext = 1; + } + } } + for (i = 0; i < Config.cacheSwap.n_configured; i++) { - SD = &Config.cacheSwap.swapDirs[i]; - if (SD->type == SWAPDIR_COSS) { - if ((last_coss_pick_index == -1) || (n_coss_dirs == 1)) { - last_coss_pick_index = i; - return SD; - } else if (choosenext) { - last_coss_pick_index = i; - return SD; - } else if (last_coss_pick_index == i) { - choosenext = 1; - } - } + SD = &Config.cacheSwap.swapDirs[i]; + + if (SD->type == SWAPDIR_COSS) { + if ((last_coss_pick_index == -1) || (n_coss_dirs == 1)) { + last_coss_pick_index = i; + return SD; + } else if (choosenext) { + last_coss_pick_index = i; + return SD; + } else if (last_coss_pick_index == i) { + choosenext = 1; + } + } } + return NULL; } + #endif /* @@ -806,7 +929,7 @@ storeCossDirPick(void) static void storeCossDirDone(void) { -/* memPoolDestroy(&coss_index_pool); XXX Should be here? */ + /* memPoolDestroy(&coss_index_pool); XXX Should be here? */ coss_initialised = 0; } diff --git a/src/fs/coss/store_io_coss.cc b/src/fs/coss/store_io_coss.cc index 420a287d7d..bbeafe6f48 100644 --- a/src/fs/coss/store_io_coss.cc +++ b/src/fs/coss/store_io_coss.cc @@ -1,6 +1,6 @@ /* - * $Id: store_io_coss.cc,v 1.21 2003/01/23 00:38:13 robertc Exp $ + * $Id: store_io_coss.cc,v 1.22 2003/02/21 22:50:39 robertc Exp $ * * DEBUG: section 79 Storage Manager COSS Interface * AUTHOR: Eric Stern @@ -51,31 +51,31 @@ static void storeCossMemBufUnlock(CossSwapDir * SD, storeIOState * e); static void storeCossWriteMemBuf(CossSwapDir * SD, CossMemBuf * t); static void storeCossWriteMemBufDone(int, int errflag, size_t len, void *my_data); static CossMemBuf *storeCossCreateMemBuf(CossSwapDir * SD, size_t start, - sfileno curfn, int *collision); + sfileno curfn, int *collision); CBDATA_TYPE(CossMemBuf); /* === PUBLIC =========================================================== */ -MemPool *CossState::Pool = NULL; +MemPool *CossState::Pool = NULL; void * CossState::operator new (size_t) { if (!Pool) - Pool = memPoolCreate("Squid COSS State Data", sizeof (CossState)); + Pool = memPoolCreate("Squid COSS State Data", sizeof (CossState)); + return memPoolAlloc(Pool); } - + void CossState::operator delete (void *address) { memPoolFree (Pool, address); } - + CossState::CossState(CossSwapDir *aCSD):SD (aCSD) -{ -} +{} /* @@ -95,55 +95,57 @@ storeCossAllocate(CossSwapDir * SD, const StoreEntry * e, int which) sfileno checkf; /* Make sure we chcek collisions if reallocating */ + if (which == COSS_ALLOC_REALLOC) - checkf = e->swap_filen; + checkf = e->swap_filen; else - checkf = -1; + checkf = -1; retofs = e->swap_filen; /* Just for defaults, or while rebuilding */ if (e->swap_file_sz > 0) - allocsize = e->swap_file_sz; + allocsize = e->swap_file_sz; else - allocsize = objectLen(e) + e->mem_obj->swap_hdr_sz; + allocsize = objectLen(e) + e->mem_obj->swap_hdr_sz; /* Since we're not supporting NOTIFY anymore, lets fail */ assert(which != COSS_ALLOC_NOTIFY); /* Check if we have overflowed the disk .. */ if ((SD->current_offset + allocsize) > (size_t)(SD->max_size << 10)) { - /* - * tried to allocate past the end of the disk, so wrap - * back to the beginning - */ - SD->current_membuf->flags.full = 1; - SD->current_membuf->diskend = SD->current_offset - 1; - SD->current_offset = 0; /* wrap back to beginning */ - debug(79, 2) ("storeCossAllocate: wrap to 0\n"); - - newmb = storeCossCreateMemBuf(SD, 0, checkf, &coll); - SD->current_membuf = newmb; - - /* Check if we have overflowed the MemBuf */ + /* + * tried to allocate past the end of the disk, so wrap + * back to the beginning + */ + SD->current_membuf->flags.full = 1; + SD->current_membuf->diskend = SD->current_offset - 1; + SD->current_offset = 0; /* wrap back to beginning */ + debug(79, 2) ("storeCossAllocate: wrap to 0\n"); + + newmb = storeCossCreateMemBuf(SD, 0, checkf, &coll); + SD->current_membuf = newmb; + + /* Check if we have overflowed the MemBuf */ } else if ((SD->current_offset + allocsize) > SD->current_membuf->diskend) { - /* - * Skip the blank space at the end of the stripe. start over. - */ - SD->current_membuf->flags.full = 1; - SD->current_offset = SD->current_membuf->diskend + 1; - debug(79, 2) ("storeCossAllocate: New offset - %ld\n", - (long int) SD->current_offset); - newmb = storeCossCreateMemBuf(SD, SD->current_offset, checkf, &coll); - SD->current_membuf = newmb; + /* + * Skip the blank space at the end of the stripe. start over. + */ + SD->current_membuf->flags.full = 1; + SD->current_offset = SD->current_membuf->diskend + 1; + debug(79, 2) ("storeCossAllocate: New offset - %ld\n", + (long int) SD->current_offset); + newmb = storeCossCreateMemBuf(SD, SD->current_offset, checkf, &coll); + SD->current_membuf = newmb; } + /* If we didn't get a collision, then update the current offset and return it */ if (coll == 0) { - retofs = SD->current_offset; - SD->current_offset = retofs + allocsize; - return retofs; + retofs = SD->current_offset; + SD->current_offset = retofs + allocsize; + return retofs; } else { - debug(79, 3) ("storeCossAllocate: Collision\n"); - return -1; + debug(79, 3) ("storeCossAllocate: Collision\n"); + return -1; } } @@ -197,7 +199,7 @@ CossSwapDir::createStoreIO(StoreEntry &e, STFNCB * file_callback, STIOCB * callb StoreIOState::Pointer CossSwapDir::openStoreIO(StoreEntry & e, STFNCB * file_callback, - STIOCB * callback, void *callback_data) + STIOCB * callback, void *callback_data) { char *p; CossState *cstate; @@ -224,51 +226,56 @@ CossSwapDir::openStoreIO(StoreEntry & e, STFNCB * file_callback, cstate->reqdiskoffset = -1; p = storeCossMemPointerFromDiskOffset(this, f, NULL); /* make local copy so we don't have to lock membuf */ + if (p) { - cstate->readbuffer = (char *)xmalloc(cstate->st_size); - xmemcpy(cstate->readbuffer, p, cstate->st_size); + cstate->readbuffer = (char *)xmalloc(cstate->st_size); + xmemcpy(cstate->readbuffer, p, cstate->st_size); } else { - /* Do the allocation */ - /* this is the first time we've been called on a new sio - * read the whole object into memory, then return the - * requested amount - */ - /* - * This bit of code actually does the LRU disk thing - we realloc - * a place for the object here, and the file_read() reads the object - * into the cossmembuf for later writing .. - */ - cstate->reqdiskoffset = sio->swap_filen; - sio->swap_filen = -1; - sio->swap_filen = storeCossAllocate(this, &e, COSS_ALLOC_REALLOC); - if (sio->swap_filen == -1) { - /* We have to clean up neatly .. */ - numcollisions++; - debug(79, 2) ("storeCossOpen: Reallocation of %d/%d failed\n", e.swap_dirn, e.swap_filen); - /* XXX XXX XXX Will squid call storeUnlink for this object? */ - return NULL; - } - /* Notify the upper levels that we've changed file number */ - sio->file_callback(sio->callback_data, 0, sio.getRaw()); - - /* - * lock the buffer so it doesn't get swapped out on us - * this will get unlocked in storeCossReadDone - */ - storeCossMemBufLock(this, sio.getRaw()); - - /* - * Do the index magic to keep the disk and memory LRUs identical - */ - storeCossRemove(this, &e); - storeCossAdd(this, &e); - - /* - * Since we've reallocated a spot for this object, we need to - * write it to the cossmembuf *and* return it in the read .. - */ - cstate->readbuffer = NULL; + /* Do the allocation */ + /* this is the first time we've been called on a new sio + * read the whole object into memory, then return the + * requested amount + */ + /* + * This bit of code actually does the LRU disk thing - we realloc + * a place for the object here, and the file_read() reads the object + * into the cossmembuf for later writing .. + */ + cstate->reqdiskoffset = sio->swap_filen; + sio->swap_filen = -1; + sio->swap_filen = storeCossAllocate(this, &e, COSS_ALLOC_REALLOC); + + if (sio->swap_filen == -1) { + /* We have to clean up neatly .. */ + numcollisions++; + debug(79, 2) ("storeCossOpen: Reallocation of %d/%d failed\n", e.swap_dirn, e.swap_filen); + /* XXX XXX XXX Will squid call storeUnlink for this object? */ + return NULL; + } + + /* Notify the upper levels that we've changed file number */ + sio->file_callback(sio->callback_data, 0, sio.getRaw()); + + /* + * lock the buffer so it doesn't get swapped out on us + * this will get unlocked in storeCossReadDone + */ + storeCossMemBufLock(this, sio.getRaw()); + + /* + * Do the index magic to keep the disk and memory LRUs identical + */ + storeCossRemove(this, &e); + + storeCossAdd(this, &e); + + /* + * Since we've reallocated a spot for this object, we need to + * write it to the cossmembuf *and* return it in the read .. + */ + cstate->readbuffer = NULL; } + return sio; } @@ -276,8 +283,10 @@ void CossState::close() { debug(79, 3) ("storeCossClose: offset %d\n", swap_filen); + if (FILE_MODE(mode) == O_WRONLY) - storeCossMemBufUnlock(SD, this); + storeCossMemBufUnlock(SD, this); + storeCossIOCallback(this, 0); } @@ -294,27 +303,32 @@ CossState::read_(char *buf, size_t size, off_t offset, STRCB * callback, void *c debug(79, 3) ("storeCossRead: offset %ld\n", (long int) offset); offset_ = offset; flags.reading = 1; + if ((offset + size) > st_size) - size = st_size - offset; + size = st_size - offset; + requestlen = size; + requestbuf = buf; + requestoffset = offset; + if (readbuffer == NULL) { - p = storeCossMemPointerFromDiskOffset(SD, swap_filen, NULL); - /* Remember we need to translate the block offset to a disk offset! */ - a_file_read(&SD->aq, SD->fd, - p, - st_size, - reqdiskoffset, - storeCossReadDone, - this); - reqdiskoffset = 0; /* XXX */ + p = storeCossMemPointerFromDiskOffset(SD, swap_filen, NULL); + /* Remember we need to translate the block offset to a disk offset! */ + a_file_read(&SD->aq, SD->fd, + p, + st_size, + reqdiskoffset, + storeCossReadDone, + this); + reqdiskoffset = 0; /* XXX */ } else { - storeCossReadDone(SD->fd, - readbuffer, - st_size, - 0, - this); + storeCossReadDone(SD->fd, + readbuffer, + st_size, + 0, + this); } } @@ -338,8 +352,9 @@ CossState::write(char const *buf, size_t size, off_t offset, FREE * free_func) assert(dest != NULL); xmemcpy(dest, buf, size); offset_ += size; + if (free_func) - (free_func) ((char *)buf); + (free_func) ((char *)buf); } @@ -357,27 +372,31 @@ storeCossReadDone(int rvfd, const char *buf, int len, int errflag, void *my_data ssize_t rlen; debug(79, 3) ("storeCossReadDone: fileno %d, FD %d, len %d\n", - sio->swap_filen, rvfd, len); + sio->swap_filen, rvfd, len); cstate->flags.reading = 0; + if (errflag) { - debug(79, 3) ("storeCossReadDone: got failure (%d)\n", errflag); - rlen = -1; + debug(79, 3) ("storeCossReadDone: got failure (%d)\n", errflag); + rlen = -1; } else { - if (cstate->readbuffer == NULL) { - cstate->readbuffer = (char *)xmalloc(cstate->st_size); - p = storeCossMemPointerFromDiskOffset(SD, sio->swap_filen, NULL); - xmemcpy(cstate->readbuffer, p, cstate->st_size); - storeCossMemBufUnlock(SD, sio); - } - sio->offset_ += len; - xmemcpy(cstate->requestbuf, &cstate->readbuffer[cstate->requestoffset], - cstate->requestlen); - rlen = (size_t) cstate->requestlen; + if (cstate->readbuffer == NULL) { + cstate->readbuffer = (char *)xmalloc(cstate->st_size); + p = storeCossMemPointerFromDiskOffset(SD, sio->swap_filen, NULL); + xmemcpy(cstate->readbuffer, p, cstate->st_size); + storeCossMemBufUnlock(SD, sio); + } + + sio->offset_ += len; + xmemcpy(cstate->requestbuf, &cstate->readbuffer[cstate->requestoffset], + cstate->requestlen); + rlen = (size_t) cstate->requestlen; } + assert(callback); sio->read.callback = NULL; + if (cbdataReferenceValidDone(sio->read.callback_data, &cbdata)) - callback(cbdata, cstate->requestbuf, rlen); + callback(cbdata, cstate->requestbuf, rlen); } static void @@ -389,8 +408,10 @@ storeCossIOCallback(storeIOState * sio, int errflag) debug(79, 3) ("storeCossIOCallback: errflag=%d\n", errflag); xfree(cstate->readbuffer); sio->callback = NULL; + if (cbdataReferenceValidDone(sio->callback_data, &cbdata)) - callback(cbdata, errflag, sio); + callback(cbdata, errflag, sio); + cbdataFree(sio); } @@ -401,16 +422,19 @@ storeCossMemPointerFromDiskOffset(CossSwapDir * SD, size_t offset, CossMemBuf ** dlink_node *m; for (m = SD->membufs.head; m; m = m->next) { - t = (CossMemBuf *)m->data; - if ((offset >= t->diskstart) && (offset <= t->diskend)) { - if (mb) - *mb = t; - return &t->buffer[offset - t->diskstart]; - } + t = (CossMemBuf *)m->data; + + if ((offset >= t->diskstart) && (offset <= t->diskend)) { + if (mb) + *mb = t; + + return &t->buffer[offset - t->diskstart]; + } } if (mb) - *mb = NULL; + *mb = NULL; + return NULL; } @@ -421,13 +445,15 @@ storeCossMemBufLock(CossSwapDir * SD, storeIOState * e) dlink_node *m; for (m = SD->membufs.head; m; m = m->next) { - t = (CossMemBuf *)m->data; - if (((size_t)e->swap_filen >= t->diskstart) && ((size_t)e->swap_filen <= t->diskend)) { - debug(79, 3) ("storeCossMemBufLock: locking %p, lockcount %d\n", t, t->lockcount); - t->lockcount++; - return; - } + t = (CossMemBuf *)m->data; + + if (((size_t)e->swap_filen >= t->diskstart) && ((size_t)e->swap_filen <= t->diskend)) { + debug(79, 3) ("storeCossMemBufLock: locking %p, lockcount %d\n", t, t->lockcount); + t->lockcount++; + return; + } } + debug(79, 3) ("storeCossMemBufLock: FAILED to lock %p\n", e); } @@ -438,19 +464,21 @@ storeCossMemBufUnlock(CossSwapDir * SD, storeIOState * e) dlink_node *m, *n; for (m = SD->membufs.head; m; m = n) { - /* - * Note that storeCossWriteMemBuf() might call storeCossWriteMemBufDone - * immediately (if the write finishes immediately, of course!) which - * will make m = m->next kinda unworkable. So, get the next pointer. - */ - n = m->next; - t = (CossMemBuf *)m->data; - if (((size_t)e->swap_filen >= t->diskstart) && ((size_t)e->swap_filen <= t->diskend)) { - t->lockcount--; - debug(79, 3) ("storeCossMemBufUnlock: unlocking %p, lockcount %d\n", t, t->lockcount); - } - if (t->flags.full && !t->flags.writing && !t->lockcount) - storeCossWriteMemBuf(SD, t); + /* + * Note that storeCossWriteMemBuf() might call storeCossWriteMemBufDone + * immediately (if the write finishes immediately, of course!) which + * will make m = m->next kinda unworkable. So, get the next pointer. + */ + n = m->next; + t = (CossMemBuf *)m->data; + + if (((size_t)e->swap_filen >= t->diskstart) && ((size_t)e->swap_filen <= t->diskend)) { + t->lockcount--; + debug(79, 3) ("storeCossMemBufUnlock: unlocking %p, lockcount %d\n", t, t->lockcount); + } + + if (t->flags.full && !t->flags.writing && !t->lockcount) + storeCossWriteMemBuf(SD, t); } } @@ -465,15 +493,21 @@ CossSwapDir::sync() a_file_syncqueue(&aq); /* Then, flush any in-memory partial membufs */ + if (!membufs.head) - return; + return; + for (m = membufs.head; m; m = m->next) { - t = (CossMemBuf *)m->data; - if (t->flags.writing) - sleep(5); /* XXX EEEWWW! */ - lseek(fd, t->diskstart, SEEK_SET); - end = (t == current_membuf) ? current_offset : t->diskend; - FD_WRITE_METHOD(fd, t->buffer, end - t->diskstart); + t = (CossMemBuf *)m->data; + + if (t->flags.writing) + sleep(5); /* XXX EEEWWW! */ + + lseek(fd, t->diskstart, SEEK_SET); + + end = (t == current_membuf) ? current_offset : t->diskend; + + FD_WRITE_METHOD(fd, t->buffer, end - t->diskstart); } } @@ -481,11 +515,11 @@ static void storeCossWriteMemBuf(CossSwapDir * SD, CossMemBuf * t) { debug(79, 3) ("storeCossWriteMemBuf: offset %ld, len %ld\n", - (long int) t->diskstart, (long int) (t->diskend - t->diskstart)); + (long int) t->diskstart, (long int) (t->diskend - t->diskstart)); t->flags.writing = 1; /* Remember that diskstart/diskend are block offsets! */ a_file_write(&SD->aq, SD->fd, t->diskstart, &t->buffer, - t->diskend - t->diskstart, storeCossWriteMemBufDone, t, NULL); + t->diskend - t->diskstart, storeCossWriteMemBufDone, t, NULL); } @@ -495,16 +529,18 @@ storeCossWriteMemBufDone(int rvfd, int errflag, size_t len, void *my_data) CossMemBuf *t = (CossMemBuf *)my_data; debug(79, 3) ("storeCossWriteMemBufDone: buf %p, len %ld\n", t, (long int) len); + if (errflag) - debug(79, 0) ("storeCossMemBufWriteDone: got failure (%d)\n", errflag); + debug(79, 0) ("storeCossMemBufWriteDone: got failure (%d)\n", errflag); dlinkDelete(&t->node, &t->SD->membufs); + cbdataFree(t); } static CossMemBuf * storeCossCreateMemBuf(CossSwapDir * SD, size_t start, - sfileno curfn, int *collision) + sfileno curfn, int *collision) { CossMemBuf *newmb, *t; StoreEntry *e; @@ -525,28 +561,33 @@ storeCossCreateMemBuf(CossSwapDir * SD, size_t start, dlinkAdd(newmb, &newmb->node, &SD->membufs); /* Print out the list of membufs */ + for (m = SD->membufs.head; m; m = m->next) { - t = (CossMemBuf *)m->data; - debug(79, 3) ("storeCossCreateMemBuf: membuflist %ld lockcount %d\n", (long int) t->diskstart, t->lockcount); + t = (CossMemBuf *)m->data; + debug(79, 3) ("storeCossCreateMemBuf: membuflist %ld lockcount %d\n", (long int) t->diskstart, t->lockcount); } /* * Kill objects from the tail to make space for a new chunk */ for (m = SD->cossindex.tail; m; m = prev) { - prev = m->prev; - e = (StoreEntry *)m->data; - if (curfn == e->swap_filen) - *collision = 1; /* Mark an object alloc collision */ - if (((size_t)e->swap_filen >= newmb->diskstart) && - ((size_t)e->swap_filen <= newmb->diskend)) { - storeRelease(e); - numreleased++; - } else - break; + prev = m->prev; + e = (StoreEntry *)m->data; + + if (curfn == e->swap_filen) + *collision = 1; /* Mark an object alloc collision */ + + if (((size_t)e->swap_filen >= newmb->diskstart) && + ((size_t)e->swap_filen <= newmb->diskend)) { + storeRelease(e); + numreleased++; + } else + break; } + if (numreleased > 0) - debug(79, 3) ("storeCossCreateMemBuf: this allocation released %d storeEntries\n", numreleased); + debug(79, 3) ("storeCossCreateMemBuf: this allocation released %d storeEntries\n", numreleased); + return newmb; } @@ -565,5 +606,4 @@ storeCossStartMembuf(CossSwapDir * sd) * Clean up any references from the SIO before it get's released. */ CossState::~CossState() -{ -} +{} diff --git a/src/fs/diskd/dio.h b/src/fs/diskd/dio.h index 52a5d80236..e78fad69d5 100644 --- a/src/fs/diskd/dio.h +++ b/src/fs/diskd/dio.h @@ -19,7 +19,8 @@ enum { _MQD_UNLINK }; -struct _diomsg { +struct _diomsg +{ mtyp_t mtype; int id; int seq_no; diff --git a/src/fs/diskd/diskd.cc b/src/fs/diskd/diskd.cc index dc4c4c6a20..d9c8541e68 100644 --- a/src/fs/diskd/diskd.cc +++ b/src/fs/diskd/diskd.cc @@ -1,5 +1,5 @@ /* - * $Id: diskd.cc,v 1.14 2003/01/23 20:59:10 robertc Exp $ + * $Id: diskd.cc,v 1.15 2003/02/21 22:50:40 robertc Exp $ * * DEBUG: section -- External DISKD process implementation. * AUTHOR: Harvest Derived @@ -49,7 +49,8 @@ typedef struct _file_state file_state; -struct _file_state { +struct _file_state +{ void *key; file_state *next; int id; @@ -71,24 +72,27 @@ do_open(diomsg * r, int len, const char *buf) * note r->offset holds open() flags */ fd = open(buf, r->offset, 0600); + if (fd < 0) { - DEBUG(1) { - fprintf(stderr, "%d %s: ", (int) mypid, buf); - perror("open"); - } - return -errno; + DEBUG(1) { + fprintf(stderr, "%d %s: ", (int) mypid, buf); + perror("open"); + } + + return -errno; } + fs = (file_state *)xcalloc(1, sizeof(*fs)); fs->id = r->id; fs->key = &fs->id; /* gack */ fs->fd = fd; hash_join(hash, (hash_link *) fs); DEBUG(2) - fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n", - (int) mypid, - fs->id, - fs->fd, - fs); + fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n", + (int) mypid, + fs->id, + fs->fd, + fs); return fd; } @@ -98,22 +102,25 @@ do_close(diomsg * r, int len) int fd; file_state *fs; fs = (file_state *) hash_lookup(hash, &r->id); + if (NULL == fs) { - errno = EBADF; - DEBUG(1) { - fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id); - perror("do_close"); - } - return -errno; + errno = EBADF; + DEBUG(1) { + fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id); + perror("do_close"); + } + + return -errno; } + fd = fs->fd; hash_remove_link(hash, (hash_link *) fs); DEBUG(2) - fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n", - (int) mypid, - r->id, - fs->fd, - fs); + fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n", + (int) mypid, + r->id, + fs->fd, + fs); xfree(fs); return close(fd); } @@ -125,35 +132,43 @@ do_read(diomsg * r, int len, char *buf) int readlen = r->size; file_state *fs; fs = (file_state *) hash_lookup(hash, &r->id); + if (NULL == fs) { - errno = EBADF; - DEBUG(1) { - fprintf(stderr, "%d READ id %d: ", (int) mypid, r->id); - perror("do_read"); - } - return -errno; + errno = EBADF; + DEBUG(1) { + fprintf(stderr, "%d READ id %d: ", (int) mypid, r->id); + perror("do_read"); + } + + return -errno; } + if (r->offset > -1 && r->offset != fs->offset) { - DEBUG(2) - fprintf(stderr, "seeking to %d\n", r->offset); - if (lseek(fs->fd, r->offset, SEEK_SET) < 0) { - DEBUG(1) { - fprintf(stderr, "%d FD %d, offset %d: ", (int) mypid, fs->fd, r->offset); - perror("lseek"); - } - } + DEBUG(2) + fprintf(stderr, "seeking to %d\n", r->offset); + + if (lseek(fs->fd, r->offset, SEEK_SET) < 0) { + DEBUG(1) { + fprintf(stderr, "%d FD %d, offset %d: ", (int) mypid, fs->fd, r->offset); + perror("lseek"); + } + } } + x = read(fs->fd, buf, readlen); DEBUG(2) - fprintf(stderr, "%d READ %d,%d,%d ret %d\n", (int) mypid, - fs->fd, readlen, r->offset, x); + fprintf(stderr, "%d READ %d,%d,%d ret %d\n", (int) mypid, + fs->fd, readlen, r->offset, x); + if (x < 0) { - DEBUG(1) { - fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd); - perror("read"); - } - return -errno; + DEBUG(1) { + fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd); + perror("read"); + } + + return -errno; } + fs->offset = r->offset + x; return x; } @@ -165,33 +180,40 @@ do_write(diomsg * r, int len, const char *buf) int x; file_state *fs; fs = (file_state *) hash_lookup(hash, &r->id); + if (NULL == fs) { - errno = EBADF; - DEBUG(1) { - fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id); - perror("do_write"); - } - return -errno; + errno = EBADF; + DEBUG(1) { + fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id); + perror("do_write"); + } + + return -errno; } + if (r->offset > -1 && r->offset != fs->offset) { - if (lseek(fs->fd, r->offset, SEEK_SET) < 0) { - DEBUG(1) { - fprintf(stderr, "%d FD %d, offset %d: ", (int) mypid, fs->fd, r->offset); - perror("lseek"); - } - } + if (lseek(fs->fd, r->offset, SEEK_SET) < 0) { + DEBUG(1) { + fprintf(stderr, "%d FD %d, offset %d: ", (int) mypid, fs->fd, r->offset); + perror("lseek"); + } + } } + DEBUG(2) - fprintf(stderr, "%d WRITE %d,%d,%d\n", (int) mypid, - fs->fd, wrtlen, r->offset); + fprintf(stderr, "%d WRITE %d,%d,%d\n", (int) mypid, + fs->fd, wrtlen, r->offset); x = write(fs->fd, buf, wrtlen); + if (x < 0) { - DEBUG(1) { - fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd); - perror("write"); - } - return -errno; + DEBUG(1) { + fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd); + perror("write"); + } + + return -errno; } + fs->offset = r->offset + x; return x; } @@ -200,19 +222,24 @@ static int do_unlink(diomsg * r, int len, const char *buf) { #if USE_TRUNCATE + if (truncate(buf, 0) < 0) #else + if (unlink(buf) < 0) #endif + { - DEBUG(1) { - fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf); - perror("truncate"); - } - return -errno; + DEBUG(1) { + fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf); + perror("truncate"); + } + + return -errno; } + DEBUG(2) - fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf); + fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf); return 0; } @@ -225,28 +252,37 @@ msg_handle(diomsg * r, int rl, diomsg * s) s->shm_offset = r->shm_offset; s->id = r->id; s->newstyle = r->newstyle; + if (s->shm_offset > -1) - buf = shmbuf + s->shm_offset; + buf = shmbuf + s->shm_offset; + switch (r->mtype) { + case _MQD_OPEN: + case _MQD_CREATE: - s->status = do_open(r, rl, buf); - break; + s->status = do_open(r, rl, buf); + break; + case _MQD_CLOSE: - s->status = do_close(r, rl); - break; + s->status = do_close(r, rl); + break; + case _MQD_READ: - s->status = do_read(r, rl, buf); - break; + s->status = do_read(r, rl, buf); + break; + case _MQD_WRITE: - s->status = do_write(r, rl, buf); - break; + s->status = do_write(r, rl, buf); + break; + case _MQD_UNLINK: - s->status = do_unlink(r, rl, buf); - break; + s->status = do_unlink(r, rl, buf); + break; + default: - assert(0); - break; + assert(0); + break; } } @@ -283,6 +319,7 @@ main(int argc, char *argv[]) diomsg smsg; int rlen; char rbuf[512]; + struct sigaction sa; setbuf(stdout, NULL); setbuf(stderr, NULL); @@ -290,27 +327,35 @@ main(int argc, char *argv[]) assert(4 == argc); key = atoi(argv[1]); rmsgid = msgget(key, 0600); + if (rmsgid < 0) { - perror("msgget"); - return 1; + perror("msgget"); + return 1; } + key = atoi(argv[2]); smsgid = msgget(key, 0600); + if (smsgid < 0) { - perror("msgget"); - return 1; + perror("msgget"); + return 1; } + key = atoi(argv[3]); shmid = shmget(key, 0, 0600); + if (shmid < 0) { - perror("shmget"); - return 1; + perror("shmget"); + return 1; } + shmbuf = (char *)shmat(shmid, NULL, 0); + if (shmbuf == (void *) -1) { - perror("shmat"); - return 1; + perror("shmat"); + return 1; } + hash = hash_create(fsCmp, 1 << 4, fsHash); assert(hash); fcntl(0, F_SETFL, SQUID_NONBLOCK); @@ -318,43 +363,55 @@ main(int argc, char *argv[]) sa.sa_handler = alarm_handler; sa.sa_flags = SA_RESTART; sigaction(SIGALRM, &sa, NULL); + for (;;) { - alarm(1); - memset(&rmsg, '\0', sizeof(rmsg)); - rlen = msgrcv(rmsgid, &rmsg, msg_snd_rcv_sz, 0, 0); - if (rlen < 0) { - if (EINTR == errno) { - if (read(0, rbuf, 512) <= 0) { - if (EWOULDBLOCK == errno) - (void) 0; - else if (EAGAIN == errno) - (void) 0; - else - break; - } - } - if (EAGAIN == errno) { - continue; - } - perror("msgrcv"); - break; - } - alarm(0); - msg_handle(&rmsg, rlen, &smsg); - if (msgsnd(smsgid, &smsg, msg_snd_rcv_sz, 0) < 0) { - perror("msgsnd"); - break; - } + alarm(1); + memset(&rmsg, '\0', sizeof(rmsg)); + rlen = msgrcv(rmsgid, &rmsg, msg_snd_rcv_sz, 0, 0); + + if (rlen < 0) { + if (EINTR == errno) { + if (read(0, rbuf, 512) <= 0) { + if (EWOULDBLOCK == errno) + (void) 0; + else if (EAGAIN == errno) + (void) 0; + else + break; + } + } + + if (EAGAIN == errno) { + continue; + } + + perror("msgrcv"); + break; + } + + alarm(0); + msg_handle(&rmsg, rlen, &smsg); + + if (msgsnd(smsgid, &smsg, msg_snd_rcv_sz, 0) < 0) { + perror("msgsnd"); + break; + } } + DEBUG(2) - fprintf(stderr, "%d diskd exiting\n", (int) mypid); + fprintf(stderr, "%d diskd exiting\n", (int) mypid); + if (msgctl(rmsgid, IPC_RMID, 0) < 0) - perror("msgctl IPC_RMID"); + perror("msgctl IPC_RMID"); + if (msgctl(smsgid, IPC_RMID, 0) < 0) - perror("msgctl IPC_RMID"); + perror("msgctl IPC_RMID"); + if (shmdt(shmbuf) < 0) - perror("shmdt"); + perror("shmdt"); + if (shmctl(shmid, IPC_RMID, 0) < 0) - perror("shmctl IPC_RMID"); + perror("shmctl IPC_RMID"); + return 0; } diff --git a/src/fs/diskd/store_dir_diskd.cc b/src/fs/diskd/store_dir_diskd.cc index cd30ae1ec3..adacce486f 100644 --- a/src/fs/diskd/store_dir_diskd.cc +++ b/src/fs/diskd/store_dir_diskd.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir_diskd.cc,v 1.75 2003/01/23 00:38:15 robertc Exp $ + * $Id: store_dir_diskd.cc,v 1.76 2003/02/21 22:50:40 robertc Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -72,15 +72,19 @@ DiskdSwapDir::init() ikey = (getpid() << 10) + (index << 2); ikey &= 0x7fffffff; DIO->smsgid = msgget((key_t) ikey, 0700 | IPC_CREAT); + if (DIO->smsgid < 0) { - debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); - fatal("msgget failed"); + debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); + fatal("msgget failed"); } + DIO->rmsgid = msgget((key_t) (ikey + 1), 0700 | IPC_CREAT); + if (DIO->rmsgid < 0) { - debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); - fatal("msgget failed"); + debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); + fatal("msgget failed"); } + DIO->shm.init(ikey, DIO->magic2); snprintf(skey1, 32, "%d", ikey); snprintf(skey2, 32, "%d", ikey + 1); @@ -91,21 +95,26 @@ DiskdSwapDir::init() args[3] = skey3; args[4] = NULL; x = ipcCreate(IPC_STREAM, - Config.Program.diskd, - args, - "diskd", - &rfd, - &DIO->wfd); + Config.Program.diskd, + args, + "diskd", + &rfd, + &DIO->wfd); + if (x < 0) - fatalf("execl: %s", Config.Program.diskd); + fatalf("execl: %s", Config.Program.diskd); + if (rfd != DIO->wfd) - comm_close(rfd); + comm_close(rfd); + fd_note(DIO->wfd, "squid -> diskd"); + commSetTimeout(DIO->wfd, -1, NULL, NULL); + commSetNonBlocking(DIO->wfd); - + UFSSwapDir::init(); - + comm_quick_poll_required(); } @@ -122,17 +131,17 @@ storeDiskdStats(StoreEntry * sentry) diskd_stats.max_away = diskd_stats.max_shmuse = 0; storeAppendPrintf(sentry, "\n OPS SUCCESS FAIL\n"); storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "open", diskd_stats.open.ops, diskd_stats.open.success, diskd_stats.open.fail); + "open", diskd_stats.open.ops, diskd_stats.open.success, diskd_stats.open.fail); storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "create", diskd_stats.create.ops, diskd_stats.create.success, diskd_stats.create.fail); + "create", diskd_stats.create.ops, diskd_stats.create.success, diskd_stats.create.fail); storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "close", diskd_stats.close.ops, diskd_stats.close.success, diskd_stats.close.fail); + "close", diskd_stats.close.ops, diskd_stats.close.success, diskd_stats.close.fail); storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "unlink", diskd_stats.unlink.ops, diskd_stats.unlink.success, diskd_stats.unlink.fail); + "unlink", diskd_stats.unlink.ops, diskd_stats.unlink.success, diskd_stats.unlink.fail); storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "read", diskd_stats.read.ops, diskd_stats.read.success, diskd_stats.read.fail); + "read", diskd_stats.read.ops, diskd_stats.read.success, diskd_stats.read.fail); storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "write", diskd_stats.write.ops, diskd_stats.write.success, diskd_stats.write.fail); + "write", diskd_stats.write.ops, diskd_stats.write.success, diskd_stats.write.fail); } /* @@ -146,13 +155,15 @@ DiskdSwapDir::sync() { static time_t lastmsg = 0; DiskdIO *DIO = dynamic_cast(IO); + while (DIO->away > 0) { - if (squid_curtime > lastmsg) { - debug(47, 1) ("storeDiskdDirSync: %d messages away\n", - DIO->away); - lastmsg = squid_curtime; - } - callback(); + if (squid_curtime > lastmsg) { + debug(47, 1) ("storeDiskdDirSync: %d messages away\n", + DIO->away); + lastmsg = squid_curtime; + } + + callback(); } } @@ -172,34 +183,42 @@ DiskdSwapDir::callback() int retval = 0; DiskdIO *DIO = dynamic_cast(IO); + if (DIO->away >= DIO->magic2) { - diskd_stats.block_queue_len++; - retval = 1; /* We might not have anything to do, but our queue - * is full.. */ + diskd_stats.block_queue_len++; + retval = 1; /* We might not have anything to do, but our queue + * is full.. */ } + if (diskd_stats.sent_count - diskd_stats.recv_count > - diskd_stats.max_away) { - diskd_stats.max_away = diskd_stats.sent_count - diskd_stats.recv_count; + diskd_stats.max_away) { + diskd_stats.max_away = diskd_stats.sent_count - diskd_stats.recv_count; } + while (1) { #ifdef ALWAYS_ZERO_BUFFERS - memset(&M, '\0', sizeof(M)); + memset(&M, '\0', sizeof(M)); #endif - x = msgrcv(DIO->rmsgid, &M, msg_snd_rcv_sz, 0, IPC_NOWAIT); - if (x < 0) - break; - else if (x != msg_snd_rcv_sz) { - debug(47, 1) ("storeDiskdDirCallback: msgget returns %d\n", - x); - break; - } - diskd_stats.recv_count++; - --DIO->away; - storeDiskdHandle(&M); - retval = 1; /* Return that we've actually done some work */ - if (M.shm_offset > -1) - DIO->shm.put ((off_t) M.shm_offset); + + x = msgrcv(DIO->rmsgid, &M, msg_snd_rcv_sz, 0, IPC_NOWAIT); + + if (x < 0) + break; + else if (x != msg_snd_rcv_sz) { + debug(47, 1) ("storeDiskdDirCallback: msgget returns %d\n", + x); + break; + } + + diskd_stats.recv_count++; + --DIO->away; + storeDiskdHandle(&M); + retval = 1; /* Return that we've actually done some work */ + + if (M.shm_offset > -1) + DIO->shm.put ((off_t) M.shm_offset); } + return retval; } @@ -214,7 +233,8 @@ int DiskdSwapDir::canStore(StoreEntry const &e)const { if (IO->shedLoad()) - return -1; + return -1; + return IO->load(); } @@ -224,11 +244,13 @@ DiskdSwapDir::unlinkFile(char const *path) #if USE_UNLINKD unlinkdUnlink(path); #elif USE_TRUNCATE + truncate(path, 0); #else + unlink(path); #endif - + } /* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */ @@ -247,23 +269,26 @@ storeDiskdDirParseQ1(SwapDir * sd, const char *name, const char *value, int reco DiskdIO *IO = dynamic_cast(((DiskdSwapDir *)sd)->IO); int old_magic1 = IO->magic1; IO->magic1 = atoi(value); + if (!reconfiguring) - return; + return; + if (old_magic1 < IO->magic1) { - /* - * This is because shm.nbufs is computed at startup, when - * we call shmget(). We can't increase the Q1/Q2 parameters - * beyond their initial values because then we might have - * more "Q2 messages" than shared memory chunks, and this - * will cause an assertion in storeDiskdShmGet(). - */ - debug(3, 1) ("WARNING: cannot increase cache_dir '%s' Q1 value while Squid is running.\n", sd->path); - IO->magic1 = old_magic1; - return; + /* + * This is because shm.nbufs is computed at startup, when + * we call shmget(). We can't increase the Q1/Q2 parameters + * beyond their initial values because then we might have + * more "Q2 messages" than shared memory chunks, and this + * will cause an assertion in storeDiskdShmGet(). + */ + debug(3, 1) ("WARNING: cannot increase cache_dir '%s' Q1 value while Squid is running.\n", sd->path); + IO->magic1 = old_magic1; + return; } + if (old_magic1 != IO->magic1) - debug(3, 1) ("cache_dir '%s' new Q1 value '%d'\n", - sd->path, IO->magic1); + debug(3, 1) ("cache_dir '%s' new Q1 value '%d'\n", + sd->path, IO->magic1); } static void @@ -280,17 +305,20 @@ storeDiskdDirParseQ2(SwapDir * sd, const char *name, const char *value, int reco assert (IO); int old_magic2 = IO->magic2; IO->magic2 = atoi(value); + if (!reconfiguring) - return; + return; + if (old_magic2 < IO->magic2) { - /* See comments in Q1 function above */ - debug(3, 1) ("WARNING: cannot increase cache_dir '%s' Q2 value while Squid is running.\n", sd->path); - IO->magic2 = old_magic2; - return; + /* See comments in Q1 function above */ + debug(3, 1) ("WARNING: cannot increase cache_dir '%s' Q2 value while Squid is running.\n", sd->path); + IO->magic2 = old_magic2; + return; } + if (old_magic2 != IO->magic2) - debug(3, 1) ("cache_dir '%s' new Q2 value '%d'\n", - sd->path, IO->magic2); + debug(3, 1) ("cache_dir '%s' new Q2 value '%d'\n", + sd->path, IO->magic2); } static void @@ -301,15 +329,15 @@ storeDiskdDirDumpQ2(StoreEntry * e, const char *option, SwapDir const * sd) } struct cache_dir_option options[] = -{ + { #if NOT_YET - {"L1", storeDiskdDirParseL1, storeDiskdDirDumpL1}, - {"L2", storeDiskdDirParseL2, storeDiskdDirDumpL2}, + {"L1", storeDiskdDirParseL1, storeDiskdDirDumpL1}, + {"L2", storeDiskdDirParseL2, storeDiskdDirDumpL2}, #endif - {"Q1", storeDiskdDirParseQ1, storeDiskdDirDumpQ1}, - {"Q2", storeDiskdDirParseQ2, storeDiskdDirDumpQ2}, - {NULL, NULL} -}; + {"Q1", storeDiskdDirParseQ1, storeDiskdDirDumpQ1}, + {"Q2", storeDiskdDirParseQ2, storeDiskdDirDumpQ2}, + {NULL, NULL} + }; /* * storeDiskdDirReconfigure diff --git a/src/fs/diskd/store_diskd.h b/src/fs/diskd/store_diskd.h index 0e721e39db..7420767724 100644 --- a/src/fs/diskd/store_diskd.h +++ b/src/fs/diskd/store_diskd.h @@ -16,10 +16,15 @@ * is 75% of SHMBUFS. magic1 is the number of messages away which we * stop allowing open/create for. */ + typedef struct _diomsg diomsg; + class DiskdIO; -class DiskdFile : public DiskFile { - public: + +class DiskdFile : public DiskFile +{ + +public: virtual void deleteSelf() const; void * operator new (size_t); void operator delete (void *); @@ -35,15 +40,16 @@ class DiskdFile : public DiskFile { /* Temporary */ int getID() const {return id;} + void completed (diomsg *); - - private: + +private: int id; char const *path_; bool errorOccured; DiskdIO *IO; IORequestor::Pointer ioRequestor; - CBDATA_CLASS(DiskdFile); + CBDATA_CLASS(DiskdFile); void openDone(diomsg *); void createDone (diomsg *); void readDone (diomsg *); @@ -54,39 +60,53 @@ class DiskdFile : public DiskFile { bool canNotifyClient() const; }; -class SharedMemory{ +class SharedMemory +{ + public: void put(off_t); - void *get(off_t *); + + void *get + (off_t *); + void init (int ikey, int magic2); + int nbufs; + char *buf; + char *inuse_map; + int id; }; -class diskdstate_t : public UFSStoreState { - public: +class diskdstate_t : public UFSStoreState +{ + +public: virtual void deleteSelf() const {delete this;} + void * operator new (size_t); void operator delete (void *); diskdstate_t(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data); ~diskdstate_t(); void close(); - + void ioCompletedNotification(); void readCompleted(const char *buf, int len, int errflag); void writeCompleted(int errflag, size_t len); void closeCompleted(); - private: + +private: CBDATA_CLASS(diskdstate_t); void doCallback(int); }; #include "dio.h" -struct _diskd_stats { +struct _diskd_stats +{ int open_fail_queue_len; int block_queue_len; int max_away; @@ -95,11 +115,15 @@ struct _diskd_stats { int sent_count; int recv_count; int sio_id; - struct { - int ops; - int success; - int fail; - } open, create, close, unlink, read, write; + + struct + { + int ops; + int success; + int fail; + } + + open, create, close, unlink, read, write; }; typedef struct _diskd_stats diskd_stats_t; @@ -107,8 +131,10 @@ typedef struct _diskd_stats diskd_stats_t; extern void storeDiskdHandle(diomsg * M); #include "SwapDir.h" + class DiskdSwapDir : public UFSSwapDir { + public: virtual void init(); virtual void dump(StoreEntry &)const; @@ -125,8 +151,10 @@ public: #define SHMBUF_BLKSZ SM_PAGE_SIZE extern diskd_stats_t diskd_stats; + class DiskdIO : public UFSStrategy { + public: DiskdIO(); virtual bool shedLoad(); diff --git a/src/fs/diskd/store_io_diskd.cc b/src/fs/diskd/store_io_diskd.cc index 3991e01544..7426827886 100644 --- a/src/fs/diskd/store_io_diskd.cc +++ b/src/fs/diskd/store_io_diskd.cc @@ -1,6 +1,6 @@ /* - * $Id: store_io_diskd.cc,v 1.32 2003/02/19 21:23:53 robertc Exp $ + * $Id: store_io_diskd.cc,v 1.33 2003/02/21 22:50:40 robertc Exp $ * * DEBUG: section 79 Squid-side DISKD I/O functions. * AUTHOR: Duane Wessels @@ -49,8 +49,7 @@ static int storeDiskdSend(int, DiskdIO *, int, DiskdFile *, int, int, off_t); /* === PUBLIC =========================================================== */ DiskdIO::DiskdIO() : away (0), magic1(64), magic2(72) -{ -} +{} bool DiskdIO::shedLoad() @@ -58,11 +57,13 @@ DiskdIO::shedLoad() /* * Fail on open() if there are too many requests queued. */ + if (away > magic1) { - debug(79, 3) ("storeDiskdIO::sheLoad: Shedding, too many requests away\n"); + debug(79, 3) ("storeDiskdIO::sheLoad: Shedding, too many requests away\n"); - return true; + return true; } + return false; } @@ -116,24 +117,34 @@ SharedMemory::put (off_t offset) } void * -SharedMemory::get (off_t * shm_offset) + +SharedMemory::get + (off_t * shm_offset) { char *aBuf = NULL; int i; + for (i = 0; i < nbufs; i++) { - if (CBIT_TEST(inuse_map, i)) - continue; - CBIT_SET(inuse_map, i); - *shm_offset = i * SHMBUF_BLKSZ; - aBuf = buf + (*shm_offset); - break; + if (CBIT_TEST(inuse_map, i)) + continue; + + CBIT_SET(inuse_map, i); + + *shm_offset = i * SHMBUF_BLKSZ; + + aBuf = buf + (*shm_offset); + + break; } + assert(aBuf); assert(aBuf >= buf); assert(aBuf < buf + (nbufs * SHMBUF_BLKSZ)); diskd_stats.shmbuf_count++; + if (diskd_stats.max_shmuse < diskd_stats.shmbuf_count) - diskd_stats.max_shmuse = diskd_stats.shmbuf_count; + diskd_stats.max_shmuse = diskd_stats.shmbuf_count; + return aBuf; } @@ -142,21 +153,26 @@ SharedMemory::init(int ikey, int magic2) { nbufs = (int)(magic2 * 1.3); id = shmget((key_t) (ikey + 2), - nbufs * SHMBUF_BLKSZ, 0600 | IPC_CREAT); + nbufs * SHMBUF_BLKSZ, 0600 | IPC_CREAT); + if (id < 0) { - debug(50, 0) ("storeDiskdInit: shmget: %s\n", xstrerror()); - fatal("shmget failed"); + debug(50, 0) ("storeDiskdInit: shmget: %s\n", xstrerror()); + fatal("shmget failed"); } + buf = (char *)shmat(id, NULL, 0); + if (buf == (void *) -1) { - debug(50, 0) ("storeDiskdInit: shmat: %s\n", xstrerror()); - fatal("shmat failed"); + debug(50, 0) ("storeDiskdInit: shmat: %s\n", xstrerror()); + fatal("shmat failed"); } + inuse_map = (char *)xcalloc((nbufs + 7) / 8, 1); diskd_stats.shmbuf_count += nbufs; + for (int i = 0; i < nbufs; i++) { - CBIT_SET(inuse_map, i); - put (i * SHMBUF_BLKSZ); + CBIT_SET(inuse_map, i); + put (i * SHMBUF_BLKSZ); } } @@ -173,7 +189,7 @@ DiskdFile::operator new (size_t) debug (79,3)("diskdFile with base %p allocating\n", result); return result; } - + void DiskdFile::operator delete (void *address) { @@ -212,23 +228,26 @@ DiskdFile::open (int flags, mode_t aMode, IORequestor::Pointer callback) char *buf = (char *)IO->shm.get(&shm_offset); xstrncpy(buf, path_, SHMBUF_BLKSZ); int x = storeDiskdSend(_MQD_OPEN, - IO, - id, - this, - strlen(buf) + 1, - mode, - shm_offset); + IO, + id, + this, + strlen(buf) + 1, + mode, + shm_offset); + if (x < 0) { - errorOccured = true; - IO->shm.put (shm_offset); - ioRequestor->ioCompletedNotification(); - ioRequestor = NULL; + errorOccured = true; + IO->shm.put (shm_offset); + ioRequestor->ioCompletedNotification(); + ioRequestor = NULL; } + diskd_stats.open.ops++; } void -DiskdFile::create (int flags, mode_t aMode, IORequestor::Pointer callback){ +DiskdFile::create (int flags, mode_t aMode, IORequestor::Pointer callback) +{ debug (79,3)("DiskdFile::create: %p creating for %p\n", this, callback.getRaw()); assert (ioRequestor.getRaw() == NULL); ioRequestor = callback; @@ -238,20 +257,22 @@ DiskdFile::create (int flags, mode_t aMode, IORequestor::Pointer callback){ char *buf = (char *)IO->shm.get(&shm_offset); xstrncpy(buf, path_, SHMBUF_BLKSZ); int x = storeDiskdSend(_MQD_CREATE, - IO, - id, - this, - strlen(buf) + 1, - mode, - shm_offset); + IO, + id, + this, + strlen(buf) + 1, + mode, + shm_offset); + if (x < 0) { - errorOccured = true; - IO->shm.put (shm_offset); - debug(79, 1) ("storeDiskdSend CREATE: %s\n", xstrerror()); - notifyClient(); - ioRequestor = NULL; - return; + errorOccured = true; + IO->shm.put (shm_offset); + debug(79, 1) ("storeDiskdSend CREATE: %s\n", xstrerror()); + notifyClient(); + ioRequestor = NULL; + return; } + diskd_stats.create.ops++; } @@ -263,20 +284,22 @@ DiskdFile::read(char *buf, off_t offset, size_t size) char *rbuf = (char *)IO->shm.get(&shm_offset); assert(rbuf); int x = storeDiskdSend(_MQD_READ, - IO, - id, - this, - (int) size, - (int) offset, - shm_offset); + IO, + id, + this, + (int) size, + (int) offset, + shm_offset); + if (x < 0) { - errorOccured = true; - IO->shm.put (shm_offset); - debug(79, 1) ("storeDiskdSend READ: %s\n", xstrerror()); - notifyClient(); - ioRequestor = NULL; - return; + errorOccured = true; + IO->shm.put (shm_offset); + debug(79, 1) ("storeDiskdSend READ: %s\n", xstrerror()); + notifyClient(); + ioRequestor = NULL; + return; } + diskd_stats.read.ops++; } @@ -286,19 +309,21 @@ DiskdFile::close() debug (79,3)("DiskdFile::close: %p closing for %p\n", this, ioRequestor.getRaw()); assert (ioRequestor.getRaw()); int x = storeDiskdSend(_MQD_CLOSE, - IO, - id, - this, - 0, - 0, - -1); + IO, + id, + this, + 0, + 0, + -1); + if (x < 0) { - errorOccured = true; - debug(79, 1) ("storeDiskdSend CLOSE: %s\n", xstrerror()); - notifyClient(); - ioRequestor = NULL; - return; + errorOccured = true; + debug(79, 1) ("storeDiskdSend CLOSE: %s\n", xstrerror()); + notifyClient(); + ioRequestor = NULL; + return; } + diskd_stats.close.ops++; } @@ -318,9 +343,10 @@ bool DiskdFile::canNotifyClient() const { if (!ioRequestor.getRaw()) { - debug (79,3)("DiskdFile::canNotifyClient: No ioRequestor to notify\n"); - return false; + debug (79,3)("DiskdFile::canNotifyClient: No ioRequestor to notify\n"); + return false; } + return true; } @@ -328,8 +354,9 @@ void DiskdFile::notifyClient() { if (!canNotifyClient()) { - return; + return; } + ioRequestor->ioCompletedNotification(); } @@ -337,55 +364,69 @@ void DiskdFile::completed(diomsg *M) { assert (M->newstyle); + switch (M->mtype) { - case _MQD_OPEN: - openDone(M); - break; - case _MQD_CREATE: - createDone(M); - break; - case _MQD_CLOSE: - closeDone(M); - break; - case _MQD_READ: - readDone(M); - break; - case _MQD_WRITE: - writeDone(M); - break; - case _MQD_UNLINK: - assert (0); - break; - default: - assert(0); - break; - } + + case _MQD_OPEN: + openDone(M); + break; + + case _MQD_CREATE: + createDone(M); + break; + + case _MQD_CLOSE: + closeDone(M); + break; + + case _MQD_READ: + readDone(M); + break; + + case _MQD_WRITE: + writeDone(M); + break; + + case _MQD_UNLINK: + assert (0); + break; + + default: + assert(0); + break; + } } void -DiskdFile::openDone(diomsg *M) { +DiskdFile::openDone(diomsg *M) +{ statCounter.syscalls.disk.opens++; debug(79, 3) ("storeDiskdOpenDone: status %d\n", M->status); assert (FILE_MODE(mode) == O_RDONLY); + if (M->status < 0) { - diskd_stats.open.fail++; - errorOccured = true; + diskd_stats.open.fail++; + errorOccured = true; } else { - diskd_stats.open.success++; + diskd_stats.open.success++; } + notifyClient(); } void -DiskdFile::createDone(diomsg *M) { +DiskdFile::createDone(diomsg *M) +{ statCounter.syscalls.disk.opens++; debug(79, 3) ("storeDiskdCreateDone: status %d\n", M->status); + if (M->status < 0) { - diskd_stats.create.fail++; - errorOccured = true; + diskd_stats.create.fail++; + errorOccured = true; } else { - diskd_stats.create.success++; + diskd_stats.create.success++; } + notifyClient(); } @@ -428,31 +469,36 @@ diskdstate_t::diskdstate_t(SwapDir *SD, StoreEntry *e_, STIOCB * callback_, void * the fsdata variable .. */ diskdstate_t::~diskdstate_t() -{ -} +{} void diskdstate_t::ioCompletedNotification() { if (opening) { - opening = false; - debug(79, 3) ("storeDiskdOpenDone: dirno %d, fileno %08x status %d\n", - swap_dirn, swap_filen, theFile->error()); - assert (FILE_MODE(mode) == O_RDONLY); - if (theFile->error()) { - doCallback(DISK_ERROR); - } - return; + opening = false; + debug(79, 3) ("storeDiskdOpenDone: dirno %d, fileno %08x status %d\n", + swap_dirn, swap_filen, theFile->error()); + assert (FILE_MODE(mode) == O_RDONLY); + + if (theFile->error()) { + doCallback(DISK_ERROR); + } + + return; } + if (creating) { - creating = false; - debug(79, 3) ("storeDiskdCreateDone: dirno %d, fileno %08x status %d\n", - swap_dirn, swap_filen, theFile->error()); - if (theFile->error()) { - doCallback(DISK_ERROR); - } - return; + creating = false; + debug(79, 3) ("storeDiskdCreateDone: dirno %d, fileno %08x status %d\n", + swap_dirn, swap_filen, theFile->error()); + + if (theFile->error()) { + doCallback(DISK_ERROR); + } + + return; } + assert (!closing); debug(79, 3) ("diskd::ioCompleted: dirno %d, fileno %08x status %d\n", swap_dirn, swap_filen, theFile->error()); /* Ok, notification past open means an error has occured */ @@ -465,19 +511,20 @@ diskdstate_t::closeCompleted() { assert (closing); debug(79, 3) ("storeDiskdCloseDone: dirno %d, fileno %08x status %d\n", - swap_dirn, swap_filen, theFile->error()); + swap_dirn, swap_filen, theFile->error()); + if (theFile->error()) { - doCallback(DISK_ERROR); + doCallback(DISK_ERROR); } else { - doCallback(DISK_OK); + doCallback(DISK_OK); } } - + void diskdstate_t::close() { debug(79, 3) ("storeDiskdClose: dirno %d, fileno %08X\n", swap_dirn, - swap_filen); + swap_filen); closing = true; ((DiskdFile *)theFile.getRaw())->close(); } @@ -488,26 +535,30 @@ DiskdFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) off_t shm_offset; char *sbuf = (char *)IO->shm.get(&shm_offset); xmemcpy(sbuf, buf, size); + if (free_func) - free_func(const_cast(buf)); + free_func(const_cast(buf)); + int x = storeDiskdSend(_MQD_WRITE, - IO, - id, - this, - (int) size, - (int) offset, - shm_offset); + IO, + id, + this, + (int) size, + (int) offset, + shm_offset); + if (x < 0) { - errorOccured = true; - debug(79, 1) ("storeDiskdSend WRITE: %s\n", xstrerror()); - IO->shm.put (shm_offset); - notifyClient(); - ioRequestor = NULL; - return; + errorOccured = true; + debug(79, 1) ("storeDiskdSend WRITE: %s\n", xstrerror()); + IO->shm.put (shm_offset); + notifyClient(); + ioRequestor = NULL; + return; } + diskd_stats.write.ops++; } - + void DiskdSwapDir::unlink(StoreEntry & e) { @@ -516,30 +567,36 @@ DiskdSwapDir::unlink(StoreEntry & e) char *buf; debug(79, 3) ("storeDiskdUnlink: dirno %d, fileno %08X\n", index, - e.swap_filen); + e.swap_filen); replacementRemove(&e); mapBitReset(e.swap_filen); + if (IO->shedLoad()) { - /* Damn, we need to issue a sync unlink here :( */ - debug(79, 2) ("storeDiskUnlink: Out of queue space, sync unlink\n"); + /* Damn, we need to issue a sync unlink here :( */ + debug(79, 2) ("storeDiskUnlink: Out of queue space, sync unlink\n"); UFSSwapDir::unlinkFile(e.swap_filen); - return; + return; } + /* We can attempt a diskd unlink */ buf = (char *)((DiskdIO *)IO)->shm.get(&shm_offset); + xstrncpy(buf, fullPath(e.swap_filen, NULL), SHMBUF_BLKSZ); + x = storeDiskdSend(_MQD_UNLINK, - (DiskdIO *)IO, - e.swap_filen, - (StoreIOState::Pointer )NULL, - 0, - 0, - shm_offset); + (DiskdIO *)IO, + e.swap_filen, + (StoreIOState::Pointer )NULL, + 0, + 0, + shm_offset); + if (x < 0) { - debug(79, 1) ("storeDiskdSend UNLINK: %s\n", xstrerror()); - ::unlink(buf); /* XXX EWW! */ - ((DiskdIO *)IO)->shm.put (shm_offset); + debug(79, 1) ("storeDiskdSend UNLINK: %s\n", xstrerror()); + ::unlink(buf); /* XXX EWW! */ + ((DiskdIO *)IO)->shm.put (shm_offset); } + diskd_stats.unlink.ops++; } @@ -551,14 +608,17 @@ DiskdFile::closeDone(diomsg * M) { statCounter.syscalls.disk.closes++; debug(79, 3) ("storeDiskdCloseDone: status %d\n", M->status); + if (M->status < 0) { - diskd_stats.close.fail++; - errorOccured = true; + diskd_stats.close.fail++; + errorOccured = true; } else { - diskd_stats.close.success++; + diskd_stats.close.success++; } + if (canNotifyClient()) - ioRequestor->closeCompleted(); + ioRequestor->closeCompleted(); + ioRequestor = NULL; } @@ -569,11 +629,12 @@ DiskdFile::readDone(diomsg * M) debug(79, 3) ("DiskdFile::readDone: status %d\n", M->status); if (M->status < 0) { - diskd_stats.read.fail++; - errorOccured = true; - ioRequestor->readCompleted(NULL, -1, DISK_ERROR); - return; + diskd_stats.read.fail++; + errorOccured = true; + ioRequestor->readCompleted(NULL, -1, DISK_ERROR); + return; } + diskd_stats.read.success++; ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK); @@ -584,25 +645,32 @@ diskdstate_t::readCompleted(const char *buf, int len, int errflag) { reading = false; debug(79, 3) ("storeDiskdReadDone: dirno %d, fileno %08x len %d\n", - swap_dirn, swap_filen, len); + swap_dirn, swap_filen, len); + if (len > 0) - offset_ += len; + offset_ += len; STRCB *callback = read.callback; + assert(callback); + read.callback = NULL; + void *cbdata; + if (cbdataReferenceValidDone(read.callback_data, &cbdata)) { - assert (!closing); - /* - * Only copy the data if the callback is still valid, - * if it isn't valid then the request should have been - * aborted. - * -- adrian - */ - if (len > 0 && read_buf != buf) - memcpy(read_buf, buf, len); - callback(cbdata, read_buf, len); + assert (!closing); + /* + * Only copy the data if the callback is still valid, + * if it isn't valid then the request should have been + * aborted. + * -- adrian + */ + + if (len > 0 && read_buf != buf) + memcpy(read_buf, buf, len); + + callback(cbdata, read_buf, len); } } @@ -611,10 +679,11 @@ diskdstate_t::writeCompleted(int errflag, size_t len) { writing = false; debug(79, 3) ("storeDiskdWriteDone: dirno %d, fileno %08x status %d\n", - swap_dirn, swap_filen, len); + swap_dirn, swap_filen, len); offset_ += len; + if (errflag) - doCallback(DISK_ERROR); + doCallback(DISK_ERROR); } void @@ -622,12 +691,14 @@ DiskdFile::writeDone(diomsg *M) { statCounter.syscalls.disk.writes++; debug(79, 3) ("storeDiskdWriteDone: status %d\n", M->status); + if (M->status < 0) { - errorOccured = true; - diskd_stats.write.fail++; - ioRequestor->writeCompleted (DISK_ERROR,0); - return; + errorOccured = true; + diskd_stats.write.fail++; + ioRequestor->writeCompleted (DISK_ERROR,0); + return; } + diskd_stats.write.success++; ioRequestor->writeCompleted (DISK_OK,M->status); } @@ -636,44 +707,53 @@ static void storeDiskdUnlinkDone(diomsg * M) { debug(79, 3) ("storeDiskdUnlinkDone: fileno %08x status %d\n", - M->id, M->status); + M->id, M->status); statCounter.syscalls.disk.unlinks++; + if (M->status < 0) - diskd_stats.unlink.fail++; + diskd_stats.unlink.fail++; else - diskd_stats.unlink.success++; + diskd_stats.unlink.success++; } void storeDiskdHandle(diomsg * M) { if (!cbdataReferenceValid (M->callback_data)) { - debug(79, 3) ("storeDiskdHandle: Invalid callback_data %p\n", - M->callback_data); - cbdataReferenceDone (M->callback_data); - return; + debug(79, 3) ("storeDiskdHandle: Invalid callback_data %p\n", + M->callback_data); + cbdataReferenceDone (M->callback_data); + return; } - + if (M->newstyle) { - DiskdFile *theFile = (DiskdFile *)M->callback_data; - theFile->completed (M); - } else - switch (M->mtype) { - case _MQD_OPEN: - case _MQD_CREATE: - case _MQD_CLOSE: - case _MQD_READ: - case _MQD_WRITE: - assert (0); - break; - case _MQD_UNLINK: - storeDiskdUnlinkDone(M); - break; - default: - assert(0); - break; - } + DiskdFile *theFile = (DiskdFile *)M->callback_data; + theFile->completed (M); + } else + switch (M->mtype) { + + case _MQD_OPEN: + + case _MQD_CREATE: + + case _MQD_CLOSE: + + case _MQD_READ: + + case _MQD_WRITE: + assert (0); + break; + + case _MQD_UNLINK: + storeDiskdUnlinkDone(M); + break; + + default: + assert(0); + break; + } + cbdataReferenceDone (M->callback_data); } @@ -681,15 +761,17 @@ void diskdstate_t::doCallback(int errflag) { if (!this || !cbdataReferenceValid(this)) { - debug (79, 0) ("storeDiskdIOCallback: invalid siocb %p\n",this); - return; + debug (79, 0) ("storeDiskdIOCallback: invalid siocb %p\n",this); + return; } + void *cbdata; STIOCB *theCallback = callback; debug(79, 3) ("storeUfsIOCallback: errflag=%d\n", errflag); callback = NULL; + if (cbdataReferenceValidDone(callback_data, &cbdata) && theCallback) - theCallback(cbdata, errflag, this); + theCallback(cbdata, errflag, this); } int @@ -709,19 +791,24 @@ storeDiskdSend(int mtype, DiskdIO *IO, int id, DiskdFile *theFile, int size, int M.id = id; M.seq_no = ++seq_no; M.newstyle = true; + if (M.seq_no < last_seq_no) - debug(79, 1) ("WARNING: sequencing out of order\n"); + debug(79, 1) ("WARNING: sequencing out of order\n"); + x = msgsnd(IO->smsgid, &M, msg_snd_rcv_sz, IPC_NOWAIT); + last_seq_no = M.seq_no; + if (0 == x) { - diskd_stats.sent_count++; - IO->away++; + diskd_stats.sent_count++; + IO->away++; } else { - debug(79, 1) ("storeDiskdSend: msgsnd: %s\n", xstrerror()); - cbdataReferenceDone(M.callback_data); - assert(++send_errors < 100); - IO->shm.put (shm_offset); + debug(79, 1) ("storeDiskdSend: msgsnd: %s\n", xstrerror()); + cbdataReferenceDone(M.callback_data); + assert(++send_errors < 100); + IO->shm.put (shm_offset); } + /* * We have to drain the queue here if necessary. If we don't, * then we can have a lot of messages in the queue (probably @@ -734,13 +821,16 @@ storeDiskdSend(int mtype, DiskdIO *IO, int id, DiskdFile *theFile, int size, int * from other SDs that might be ready. */ while (IO->away > IO->magic2) { - struct timeval delay = - {0, 1}; - select(0, NULL, NULL, NULL, &delay); - storeDirCallback(); - if (delay.tv_usec < 1000000) - delay.tv_usec <<= 1; + + struct timeval delay = {0, 1}; + + select(0, NULL, NULL, NULL, &delay); + storeDirCallback(); + + if (delay.tv_usec < 1000000) + delay.tv_usec <<= 1; } + return x; } @@ -761,18 +851,23 @@ storeDiskdSend(int mtype, DiskdIO *IO, int id, StoreIOState::Pointer sio, int si M.id = id; M.seq_no = ++seq_no; M.newstyle = false; + if (M.seq_no < last_seq_no) - debug(79, 1) ("WARNING: sequencing out of order\n"); + debug(79, 1) ("WARNING: sequencing out of order\n"); + x = msgsnd(IO->smsgid, &M, msg_snd_rcv_sz, IPC_NOWAIT); + last_seq_no = M.seq_no; + if (0 == x) { - diskd_stats.sent_count++; - IO->away++; + diskd_stats.sent_count++; + IO->away++; } else { - debug(79, 1) ("storeDiskdSend: msgsnd: %s\n", xstrerror()); - cbdataReferenceDone(M.callback_data); - assert(++send_errors < 100); + debug(79, 1) ("storeDiskdSend: msgsnd: %s\n", xstrerror()); + cbdataReferenceDone(M.callback_data); + assert(++send_errors < 100); } + /* * We have to drain the queue here if necessary. If we don't, * then we can have a lot of messages in the queue (probably @@ -785,13 +880,16 @@ storeDiskdSend(int mtype, DiskdIO *IO, int id, StoreIOState::Pointer sio, int si * from other SDs that might be ready. */ while (IO->away > IO->magic2) { - struct timeval delay = - {0, 1}; - select(0, NULL, NULL, NULL, &delay); - storeDirCallback(); - if (delay.tv_usec < 1000000) - delay.tv_usec <<= 1; + + struct timeval delay = {0, 1}; + + select(0, NULL, NULL, NULL, &delay); + storeDirCallback(); + + if (delay.tv_usec < 1000000) + delay.tv_usec <<= 1; } + return x; } diff --git a/src/fs/null/store_null.cc b/src/fs/null/store_null.cc index 7ed1ea9baf..0b88411dc0 100644 --- a/src/fs/null/store_null.cc +++ b/src/fs/null/store_null.cc @@ -1,6 +1,6 @@ /* - * $Id: store_null.cc,v 1.5 2003/01/23 00:38:19 robertc Exp $ + * $Id: store_null.cc,v 1.6 2003/02/21 22:50:44 robertc Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -42,8 +42,9 @@ #include "SwapDir.h" #include "Store.h" -class NullSwapDir : public SwapDir +class NullSwapDir : public SwapDir { + public: virtual void init(); virtual int canStore(StoreEntry const &)const; @@ -83,7 +84,7 @@ NullSwapDir::init() { store_dirs_rebuilding++; eventAdd("storeNullDirRebuildComplete", storeNullDirRebuildComplete, - NULL, 0.0, 1); + NULL, 0.0, 1); } StoreIOState::Pointer @@ -103,6 +104,7 @@ NullSwapDir::openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *) static void storeNullDirRebuildComplete(void *unused) { + struct _store_rebuild_data counts; memset(&counts, '\0', sizeof(counts)); store_dirs_rebuilding--; diff --git a/src/fs/ufs/store_dir_ufs.cc b/src/fs/ufs/store_dir_ufs.cc index a24e5f48cf..e720ab4da0 100644 --- a/src/fs/ufs/store_dir_ufs.cc +++ b/src/fs/ufs/store_dir_ufs.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir_ufs.cc,v 1.55 2003/01/23 20:59:11 robertc Exp $ + * $Id: store_dir_ufs.cc,v 1.56 2003/02/21 22:50:45 robertc Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -67,8 +67,10 @@ UfsSwapDir::unlinkFile(char const *path) #if USE_UNLINKD unlinkdUnlink(path); #elif USE_TRUNCATE + truncate(path, 0); #else + ::unlink(path); #endif } @@ -76,13 +78,13 @@ UfsSwapDir::unlinkFile(char const *path) /* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */ static struct cache_dir_option options[] = -{ + { #if NOT_YET_DONE - {"L1", storeUfsDirParseL1, storeUfsDirDumpL1}, - {"L2", storeUfsDirParseL2, storeUfsDirDumpL2}, + {"L1", storeUfsDirParseL1, storeUfsDirDumpL1}, + {"L2", storeUfsDirParseL2, storeUfsDirDumpL2}, #endif - {NULL, NULL} -}; + {NULL, NULL} + }; /* * storeUfsDirReconfigure @@ -104,22 +106,28 @@ UFSSwapDir::reconfigure(int index, char *path) i = GetInteger(); size = i << 10; /* Mbytes to kbytes */ + if (size <= 0) - fatal("storeDiskdDirReconfigure: invalid size value"); + fatal("storeDiskdDirReconfigure: invalid size value"); + l1 = GetInteger(); + if (l1 <= 0) - fatal("storeDiskdDirReconfigure: invalid level 1 directories value"); + fatal("storeDiskdDirReconfigure: invalid level 1 directories value"); + l2 = GetInteger(); + if (l2 <= 0) - fatal("storeDiskdDirReconfigure: invalid level 2 directories value"); + fatal("storeDiskdDirReconfigure: invalid level 2 directories value"); /* just reconfigure it */ if (size == max_size) - debug(3, 1) ("Cache dir '%s' size remains unchanged at %d KB\n", - path, size); + debug(3, 1) ("Cache dir '%s' size remains unchanged at %d KB\n", + path, size); else - debug(3, 1) ("Cache dir '%s' size changed to %d KB\n", - path, size); + debug(3, 1) ("Cache dir '%s' size changed to %d KB\n", + path, size); + max_size = size; } @@ -147,16 +155,22 @@ void UFSSwapDir::parse (int anIndex, char *aPath) { max_size = GetInteger() << 10; /* Mbytes to kbytes */ + if (max_size <= 0) - fatal("storeAufsDirParse: invalid size value"); + fatal("storeAufsDirParse: invalid size value"); + l1 = GetInteger(); + if (l1 <= 0) - fatal("storeAufsDirParse: invalid level 1 directories value"); + fatal("storeAufsDirParse: invalid level 1 directories value"); + l2 = GetInteger(); + if (l2 <= 0) - fatal("storeAufsDirParse: invalid level 2 directories value"); + fatal("storeAufsDirParse: invalid level 2 directories value"); index = anIndex; + path = xstrdup(aPath); /* Initialise replacement policy stuff */ @@ -171,18 +185,23 @@ UFSSwapDir::init() { static int started_clean_event = 0; static const char *errmsg = - "\tFailed to verify one of the swap directories, Check cache.log\n" - "\tfor details. Run 'squid -z' to create swap directories\n" - "\tif needed, or if running Squid for the first time."; + "\tFailed to verify one of the swap directories, Check cache.log\n" + "\tfor details. Run 'squid -z' to create swap directories\n" + "\tif needed, or if running Squid for the first time."; initBitmap(); + if (verifyCacheDirs()) - fatal(errmsg); + fatal(errmsg); + openLog(); + rebuild(); + if (!started_clean_event) { - eventAdd("UFS storeDirClean", CleanEvent, NULL, 15.0, 1); - started_clean_event = 1; + eventAdd("UFS storeDirClean", CleanEvent, NULL, 15.0, 1); + started_clean_event = 1; } + (void) storeDirGetBlkSize(path, &fs.blksize); } @@ -199,12 +218,15 @@ UFSSwapDir::UFSSwapDir() : IO(NULL), map(NULL), suggest(0), swaplog_fd (-1) {} UFSSwapDir::~UFSSwapDir() { if (swaplog_fd > -1) { - file_close(swaplog_fd); - swaplog_fd = -1; + file_close(swaplog_fd); + swaplog_fd = -1; } + filemapFreeMemory(map); + if (IO) - IO->deleteSelf(); + IO->deleteSelf(); + IO = NULL; } @@ -236,7 +258,7 @@ UFSSwapDir::dumpEntry(StoreEntry &e) const { debug(47, 0) ("UFSSwapDir::dumpEntry: FILENO %08X\n", e.swap_filen); debug(47, 0) ("UFSSwapDir::dumpEntry: PATH %s\n", - fullPath(e.swap_filen, NULL)); + fullPath(e.swap_filen, NULL)); storeEntryDump(&e, 0); } @@ -248,19 +270,23 @@ UFSSwapDir::dumpEntry(StoreEntry &e) const bool UFSSwapDir::doubleCheck(StoreEntry & e) { + struct stat sb; + if (stat(fullPath(e.swap_filen, NULL), &sb) < 0) { - debug(47, 0) ("UFSSwapDir::doubleCheck: MISSING SWAP FILE\n"); - dumpEntry(e); - return true; + debug(47, 0) ("UFSSwapDir::doubleCheck: MISSING SWAP FILE\n"); + dumpEntry(e); + return true; } + if ((off_t)e.swap_file_sz != sb.st_size) { - debug(47, 0) ("UFSSwapDir::doubleCheck: SIZE MISMATCH\n"); - debug(47, 0) ("UFSSwapDir::doubleCheck: ENTRY SIZE: %ld, FILE SIZE: %ld\n", - (long int) e.swap_file_sz, (long int) sb.st_size); - dumpEntry(e); - return true; + debug(47, 0) ("UFSSwapDir::doubleCheck: SIZE MISMATCH\n"); + debug(47, 0) ("UFSSwapDir::doubleCheck: ENTRY SIZE: %ld, FILE SIZE: %ld\n", + (long int) e.swap_file_sz, (long int) sb.st_size); + dumpEntry(e); + return true; } + return false; } @@ -277,26 +303,31 @@ UFSSwapDir::statfs(StoreEntry & sentry) const storeAppendPrintf(&sentry, "Maximum Size: %d KB\n", max_size); storeAppendPrintf(&sentry, "Current Size: %d KB\n", cur_size); storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n", - 100.0 * cur_size / max_size); + 100.0 * cur_size / max_size); storeAppendPrintf(&sentry, "Filemap bits in use: %d of %d (%d%%)\n", - map->n_files_in_map, map->max_n_files, - percent(map->n_files_in_map, map->max_n_files)); + map->n_files_in_map, map->max_n_files, + percent(map->n_files_in_map, map->max_n_files)); x = storeDirGetUFSStats(path, &totl_kb, &free_kb, &totl_in, &free_in); + if (0 == x) { - storeAppendPrintf(&sentry, "Filesystem Space in use: %d/%d KB (%d%%)\n", - totl_kb - free_kb, - totl_kb, - percent(totl_kb - free_kb, totl_kb)); - storeAppendPrintf(&sentry, "Filesystem Inodes in use: %d/%d (%d%%)\n", - totl_in - free_in, - totl_in, - percent(totl_in - free_in, totl_in)); + storeAppendPrintf(&sentry, "Filesystem Space in use: %d/%d KB (%d%%)\n", + totl_kb - free_kb, + totl_kb, + percent(totl_kb - free_kb, totl_kb)); + storeAppendPrintf(&sentry, "Filesystem Inodes in use: %d/%d (%d%%)\n", + totl_in - free_in, + totl_in, + percent(totl_in - free_in, totl_in)); } + storeAppendPrintf(&sentry, "Flags:"); + if (flags.selected) - storeAppendPrintf(&sentry, " SELECTED"); + storeAppendPrintf(&sentry, " SELECTED"); + if (flags.read_only) - storeAppendPrintf(&sentry, " READ-ONLY"); + storeAppendPrintf(&sentry, " READ-ONLY"); + storeAppendPrintf(&sentry, "\n"); } @@ -310,34 +341,43 @@ UFSSwapDir::maintainfs() double f; RemovalPurgeWalker *walker; /* We can't delete objects while rebuilding swap */ + if (store_dirs_rebuilding) { - return; + return; } else { - f = (double) (cur_size - low_size) / (max_size - low_size); - f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; - max_scan = (int) (f * 400.0 + 100.0); - max_remove = (int) (f * 70.0 + 10.0); - /* - * This is kinda cheap, but so we need this priority hack? - */ + f = (double) (cur_size - low_size) / (max_size - low_size); + f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; + max_scan = (int) (f * 400.0 + 100.0); + max_remove = (int) (f * 70.0 + 10.0); + /* + * This is kinda cheap, but so we need this priority hack? + */ } + debug(47, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n", - f, max_scan, max_remove); + f, max_scan, max_remove); walker = repl->PurgeInit(repl, max_scan); + while (1) { - if (cur_size < low_size) - break; - if (removed >= max_remove) - break; - e = walker->Next(walker); - if (!e) - break; /* no more objects */ - removed++; - storeRelease(e); + if (cur_size < low_size) + break; + + if (removed >= max_remove) + break; + + e = walker->Next(walker); + + if (!e) + break; /* no more objects */ + + removed++; + + storeRelease(e); } + walker->Done(walker); debug(47, (removed ? 2 : 3)) ("UFSSwapDir::maintainfs: %s removed %d/%d f=%.03f max_scan=%d\n", - path, removed, max_remove, f, max_scan); + path, removed, max_remove, f, max_scan); } /* @@ -350,10 +390,11 @@ void UFSSwapDir::reference(StoreEntry &e) { debug(47, 3) ("UFSSwapDir::reference: referencing %p %d/%d\n", &e, e.swap_dirn, - e.swap_filen); + e.swap_filen); + if (repl->Referenced) - repl->Referenced(repl, &e, &e.repl); -} + repl->Referenced(repl, &e, &e.repl); +} /* * UFSSwapDir::dereference @@ -364,9 +405,10 @@ void UFSSwapDir::dereference(StoreEntry & e) { debug(47, 3) ("UFSSwapDir::dereference: referencing %p %d/%d\n", &e, e.swap_dirn, - e.swap_filen); + e.swap_filen); + if (repl->Dereferenced) - repl->Dereferenced(repl, &e, &e.repl); + repl->Dereferenced(repl, &e, &e.repl); } StoreIOState::Pointer @@ -403,8 +445,9 @@ UFSSwapDir::mapBitReset(sfileno filn) * the map is dynamic in size. Also clearing an already clear * bit puts the map counter of-of-whack. */ + if (file_map_bit_test(map, filn)) - file_map_bit_reset(map, filn); + file_map_bit_reset(map, filn); } int @@ -427,12 +470,13 @@ void UFSSwapDir::initBitmap() { if (map == NULL) { - /* First time */ - map = file_map_create(); + /* First time */ + map = file_map_create(); } else if (map->max_n_files) { - /* it grew, need to expand */ - /* XXX We don't need it anymore .. */ + /* it grew, need to expand */ + /* XXX We don't need it anymore .. */ } + /* else it shrunk, and we leave the old one in place */ } @@ -449,40 +493,50 @@ int UFSSwapDir::createDirectory(const char *path, int should_exist) { int created = 0; + struct stat st; getCurrentTime(); + if (0 == stat(path, &st)) { - if (S_ISDIR(st.st_mode)) { - debug(47, should_exist ? 3 : 1) ("%s exists\n", path); - } else { - fatalf("Swap directory %s is not a directory.", path); - } + if (S_ISDIR(st.st_mode)) { + debug(47, should_exist ? 3 : 1) ("%s exists\n", path); + } else { + fatalf("Swap directory %s is not a directory.", path); + } + #ifdef _SQUID_MSWIN_ + } else if (0 == mkdir(path)) { #else + } else if (0 == mkdir(path, 0755)) { #endif - debug(47, should_exist ? 1 : 3) ("%s created\n", path); - created = 1; + debug(47, should_exist ? 1 : 3) ("%s created\n", path); + created = 1; } else { - fatalf("Failed to make swap directory %s: %s", - path, xstrerror()); + fatalf("Failed to make swap directory %s: %s", + path, xstrerror()); } + return created; } bool UFSSwapDir::pathIsDirectory(const char *path)const { + struct stat sb; + if (stat(path, &sb) < 0) { - debug(47, 0) ("%s: %s\n", path, xstrerror()); - return false; + debug(47, 0) ("%s: %s\n", path, xstrerror()); + return false; } + if (S_ISDIR(sb.st_mode) == 0) { - debug(47, 0) ("%s is not a directory\n", path); - return false; + debug(47, 0) ("%s is not a directory\n", path); + return false; } + return true; } @@ -495,12 +549,15 @@ bool UFSSwapDir::verifyCacheDirs() { if (!pathIsDirectory(path)) - return true; + return true; + for (int j = 0; j < l1; j++) { - char const *aPath = swapSubDir(j); - if (!pathIsDirectory(aPath)) - return true; + char const *aPath = swapSubDir(j); + + if (!pathIsDirectory(aPath)) + return true; } + return false; } @@ -510,17 +567,21 @@ UFSSwapDir::createSwapSubDirs() int i, k; int should_exist; LOCAL_ARRAY(char, name, MAXPATHLEN); + for (i = 0; i < l1; i++) { - snprintf(name, MAXPATHLEN, "%s/%02X", path, i); - if (createDirectory(name, 0)) - should_exist = 0; - else - should_exist = 1; - debug(47, 1) ("Making directories in %s\n", name); - for (k = 0; k < l2; k++) { - snprintf(name, MAXPATHLEN, "%s/%02X/%02X", path, i, k); - createDirectory(name, should_exist); - } + snprintf(name, MAXPATHLEN, "%s/%02X", path, i); + + if (createDirectory(name, 0)) + should_exist = 0; + else + should_exist = 1; + + debug(47, 1) ("Making directories in %s\n", name); + + for (k = 0; k < l2; k++) { + snprintf(name, MAXPATHLEN, "%s/%02X/%02X", path, i, k); + createDirectory(name, should_exist); + } } } @@ -531,26 +592,35 @@ UFSSwapDir::logFile(char const *ext) const LOCAL_ARRAY(char, pathtmp, SQUID_MAXPATHLEN); LOCAL_ARRAY(char, digit, 32); char *pathtmp2; + if (Config.Log.swap) { - xstrncpy(pathtmp, path, SQUID_MAXPATHLEN - 64); - pathtmp2 = pathtmp; - while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL) - *pathtmp2 = '.'; - while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.') - pathtmp[strlen(pathtmp) - 1] = '\0'; - for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++); - snprintf(lpath, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2); - if (strncmp(lpath, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) { - strcat(lpath, "."); - snprintf(digit, 32, "%02d", index); - strncat(lpath, digit, 3); - } + xstrncpy(pathtmp, path, SQUID_MAXPATHLEN - 64); + pathtmp2 = pathtmp; + + while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL) + *pathtmp2 = '.'; + + while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.') + pathtmp[strlen(pathtmp) - 1] = '\0'; + + for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++) + + ; + snprintf(lpath, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2); + + if (strncmp(lpath, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) { + strcat(lpath, "."); + snprintf(digit, 32, "%02d", index); + strncat(lpath, digit, 3); + } } else { - xstrncpy(lpath, path, SQUID_MAXPATHLEN - 64); - strcat(lpath, "/swap.state"); + xstrncpy(lpath, path, SQUID_MAXPATHLEN - 64); + strcat(lpath, "/swap.state"); } + if (ext) - strncat(lpath, ext, 16); + strncat(lpath, ext, 16); + return lpath; } @@ -560,14 +630,19 @@ UFSSwapDir::openLog() char *logPath; logPath = logFile(); swaplog_fd = file_open(logPath, O_WRONLY | O_CREAT | O_BINARY); + if (swaplog_fd < 0) { - debug(50, 1) ("%s: %s\n", logPath, xstrerror()); - fatal("commonUfsDirOpenSwapLog: Failed to open swap log."); + debug(50, 1) ("%s: %s\n", logPath, xstrerror()); + fatal("commonUfsDirOpenSwapLog: Failed to open swap log."); } + debug(50, 3) ("Cache Dir #%d log opened on FD %d\n", index, swaplog_fd); + if (0 == NumberOfUFSDirs) - assert(NULL == UFSDirToGlobalDirMapping); + assert(NULL == UFSDirToGlobalDirMapping); + ++NumberOfUFSDirs; + assert(NumberOfUFSDirs <= Config.cacheSwap.n_configured); } @@ -575,15 +650,21 @@ void UFSSwapDir::closeLog() { if (swaplog_fd < 0) /* not open */ - return; + return; + file_close(swaplog_fd); + debug(47, 3) ("Cache Dir #%d log closed on FD %d\n", - index, swaplog_fd); + index, swaplog_fd); + swaplog_fd = -1; + NumberOfUFSDirs--; + assert(NumberOfUFSDirs >= 0); + if (0 == NumberOfUFSDirs) - safe_free(UFSDirToGlobalDirMapping); + safe_free(UFSDirToGlobalDirMapping); } bool @@ -602,19 +683,19 @@ UFSSwapDir::validL2(int anInt) const * use to rebuild store from disk. */ StoreEntry * UFSSwapDir::addDiskRestore(const cache_key * key, - sfileno file_number, - size_t swap_file_sz, - time_t expires, - time_t timestamp, - time_t lastref, - time_t lastmod, - u_int32_t refcount, - u_int16_t flags, - int clean) + sfileno file_number, + size_t swap_file_sz, + time_t expires, + time_t timestamp, + time_t lastref, + time_t lastmod, + u_int32_t refcount, + u_int16_t flags, + int clean) { StoreEntry *e = NULL; debug(47, 5) ("commonUfsAddDiskRestore: %s, fileno=%08X\n", storeKeyText(key), file_number); - /* if you call this you'd better be sure file_number is not + /* if you call this you'd better be sure file_number is not * already in use! */ e = new_StoreEntry(STORE_ENTRY_WITHOUT_MEMOBJ, NULL, NULL); e->store_status = STORE_OK; @@ -658,20 +739,26 @@ UFSSwapDir::rebuild() * and suck in the meta data. */ fp = openTmpSwapLog(&clean, &zeroLengthLog); + if (fp == NULL || zeroLengthLog) { - if (fp != NULL) - fclose(fp); - func = RebuildState::RebuildFromDirectory; + if (fp != NULL) + fclose(fp); + + func = RebuildState::RebuildFromDirectory; } else { - func = RebuildState::RebuildFromSwapLog; - rb->log = fp; - rb->flags.clean = (unsigned int) clean; + func = RebuildState::RebuildFromSwapLog; + rb->log = fp; + rb->flags.clean = (unsigned int) clean; } + if (!clean) - rb->flags.need_to_validate = 1; + rb->flags.need_to_validate = 1; + debug(47, 1) ("Rebuilding storage in %s (%s)\n", - path, clean ? "CLEAN" : "DIRTY"); + path, clean ? "CLEAN" : "DIRTY"); + store_dirs_rebuilding++; + eventAdd("storeRebuild", func, rb, 0.0, 1); } @@ -683,19 +770,24 @@ UFSSwapDir::closeTmpSwapLog() int fd; file_close(swaplog_fd); #if defined (_SQUID_OS2_) || defined (_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_) + if (::unlink(swaplog_path) < 0) { - debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); - fatal("commonUfsDirCloseTmpSwapLog: unlink failed"); + debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); + fatal("commonUfsDirCloseTmpSwapLog: unlink failed"); } + #endif if (xrename(new_path, swaplog_path) < 0) { - fatal("commonUfsDirCloseTmpSwapLog: rename failed"); + fatal("commonUfsDirCloseTmpSwapLog: rename failed"); } + fd = file_open(swaplog_path, O_WRONLY | O_CREAT | O_BINARY); + if (fd < 0) { - debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror()); - fatal("commonUfsDirCloseTmpSwapLog: Failed to open swap log."); + debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror()); + fatal("commonUfsDirCloseTmpSwapLog: Failed to open swap log."); } + safe_free(swaplog_path); safe_free(new_path); swaplog_fd = fd; @@ -708,50 +800,68 @@ UFSSwapDir::openTmpSwapLog(int *clean_flag, int *zero_flag) char *swaplog_path = xstrdup(logFile(NULL)); char *clean_path = xstrdup(logFile(".last-clean")); char *new_path = xstrdup(logFile(".new")); + struct stat log_sb; + struct stat clean_sb; FILE *fp; int fd; + if (stat(swaplog_path, &log_sb) < 0) { - debug(47, 1) ("Cache Dir #%d: No log file\n", index); - safe_free(swaplog_path); - safe_free(clean_path); - safe_free(new_path); - return NULL; + debug(47, 1) ("Cache Dir #%d: No log file\n", index); + safe_free(swaplog_path); + safe_free(clean_path); + safe_free(new_path); + return NULL; } + *zero_flag = log_sb.st_size == 0 ? 1 : 0; /* close the existing write-only FD */ + if (swaplog_fd >= 0) - file_close(swaplog_fd); + file_close(swaplog_fd); + /* open a write-only FD for the new log */ fd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); + if (fd < 0) { - debug(50, 1) ("%s: %s\n", new_path, xstrerror()); - fatal("storeDirOpenTmpSwapLog: Failed to open swap log."); + debug(50, 1) ("%s: %s\n", new_path, xstrerror()); + fatal("storeDirOpenTmpSwapLog: Failed to open swap log."); } + swaplog_fd = fd; /* open a read-only stream of the old log */ fp = fopen(swaplog_path, "rb"); + if (fp == NULL) { - debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); - fatal("Failed to open swap log for reading"); + debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); + fatal("Failed to open swap log for reading"); } + memset(&clean_sb, '\0', sizeof(struct stat)); + if (stat(clean_path, &clean_sb) < 0) - *clean_flag = 0; + *clean_flag = 0; else if (clean_sb.st_mtime < log_sb.st_mtime) - *clean_flag = 0; + *clean_flag = 0; else - *clean_flag = 1; + *clean_flag = 1; + safeunlink(clean_path, 1); + safe_free(swaplog_path); + safe_free(clean_path); + safe_free(new_path); + return fp; } -class UFSCleanLog : public SwapDir::CleanLog { - public: +class UFSCleanLog : public SwapDir::CleanLog +{ + +public: UFSCleanLog(SwapDir *); virtual const StoreEntry *nextEntry(); virtual void write(StoreEntry const &); @@ -774,25 +884,28 @@ class UFSCleanLog : public SwapDir::CleanLog { */ UFSCleanLog::UFSCleanLog(SwapDir *aSwapDir) : cur(NULL),newLog(NULL),cln(NULL),outbuf(NULL), - outbuf_offset(0), fd(-1),walker(NULL), sd(aSwapDir) -{ -} + outbuf_offset(0), fd(-1),walker(NULL), sd(aSwapDir) +{} int UFSSwapDir::writeCleanStart() { UFSCleanLog *state = new UFSCleanLog(this); #if HAVE_FCHMOD + struct stat sb; #endif + cleanLog = NULL; state->newLog = xstrdup(logFile(".clean")); state->fd = file_open(state->newLog, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); + if (state->fd < 0) { - xfree(state->newLog); - delete state; - return -1; + xfree(state->newLog); + delete state; + return -1; } + state->cur = xstrdup(logFile(NULL)); state->cln = xstrdup(logFile(".last-clean")); state->outbuf = (char *)xcalloc(CLEAN_BUF_SZ, 1); @@ -800,12 +913,16 @@ UFSSwapDir::writeCleanStart() state->walker = repl->WalkInit(repl); ::unlink(state->cln); debug(47, 3) ("storeDirWriteCleanLogs: opened %s, FD %d\n", - state->newLog, state->fd); + state->newLog, state->fd); #if HAVE_FCHMOD + if (stat(state->cur, &sb) == 0) - fchmod(state->fd, sb.st_mode); + fchmod(state->fd, sb.st_mode); + #endif + cleanLog = state; + return 0; } @@ -816,8 +933,10 @@ const StoreEntry * UFSCleanLog::nextEntry() { const StoreEntry *entry = NULL; + if (walker) - entry = walker->Next(walker); + entry = walker->Next(walker); + return entry; } @@ -844,19 +963,21 @@ UFSCleanLog::write(StoreEntry const &e) xmemcpy(state->outbuf + state->outbuf_offset, &s, ss); state->outbuf_offset += ss; /* buffered write */ + if (state->outbuf_offset + ss > CLEAN_BUF_SZ) { - if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { - debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n", - state->newLog, xstrerror()); - debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n"); - file_close(state->fd); - state->fd = -1; - unlink(state->newLog); - delete state; - sd->cleanLog = NULL; - return; - } - state->outbuf_offset = 0; + if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { + debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n", + state->newLog, xstrerror()); + debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n"); + file_close(state->fd); + state->fd = -1; + unlink(state->newLog); + delete state; + sd->cleanLog = NULL; + return; + } + + state->outbuf_offset = 0; } } @@ -865,20 +986,25 @@ UFSSwapDir::writeCleanDone() { UFSCleanLog *state = (UFSCleanLog *)cleanLog; int fd; + if (NULL == state) - return; + return; + if (state->fd < 0) - return; + return; + state->walker->Done(state->walker); + if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) { - debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n", - state->newLog, xstrerror()); - debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile " - "not replaced.\n"); - file_close(state->fd); - state->fd = -1; - ::unlink(state->newLog); + debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n", + state->newLog, xstrerror()); + debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile " + "not replaced.\n"); + file_close(state->fd); + state->fd = -1; + ::unlink(state->newLog); } + safe_free(state->outbuf); /* * You can't rename open files on Microsoft "operating systems" @@ -888,31 +1014,43 @@ UFSSwapDir::writeCleanDone() /* save the fd value for a later test */ fd = state->fd; /* rename */ + if (state->fd >= 0) { #if defined(_SQUID_OS2_) || defined (_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_) - file_close(state->fd); - state->fd = -1; - if (::unlink(state->cur) < 0) - debug(50, 0) ("storeDirWriteCleanLogs: unlinkd failed: %s, %s\n", - xstrerror(), state->cur); + file_close(state->fd); + state->fd = -1; + + if (::unlink(state->cur) < 0) + debug(50, 0) ("storeDirWriteCleanLogs: unlinkd failed: %s, %s\n", + xstrerror(), state->cur); + #endif - xrename(state->newLog, state->cur); + + xrename(state->newLog, state->cur); } + /* touch a timestamp file if we're not still validating */ if (store_dirs_rebuilding) - (void) 0; + (void) 0; else if (fd < 0) - (void) 0; + (void) 0; else - file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)); + file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)); + /* close */ safe_free(state->cur); + safe_free(state->newLog); + safe_free(state->cln); + if (state->fd >= 0) - file_close(state->fd); + file_close(state->fd); + state->fd = -1; + delete state; + cleanLog = NULL; } @@ -937,12 +1075,12 @@ UFSSwapDir::logEntry(const StoreEntry & e, int op) const s->flags = e.flags; xmemcpy(s->key, e.key, MD5_DIGEST_CHARS); file_write(swaplog_fd, - -1, - s, - sizeof(storeSwapLogData), - NULL, - NULL, - (FREE *) storeSwapLogDataFree); + -1, + s, + sizeof(storeSwapLogData), + NULL, + NULL, + (FREE *) storeSwapLogDataFree); } static QS rev_int_sort; @@ -958,12 +1096,15 @@ int UFSSwapDir::DirClean(int swap_index) { DIR *dp = NULL; + struct dirent *de = NULL; LOCAL_ARRAY(char, p1, MAXPATHLEN + 1); LOCAL_ARRAY(char, p2, MAXPATHLEN + 1); #if USE_TRUNCATE + struct stat sb; #endif + int files[20]; int swapfileno; int fn; /* same as swapfileno, but with dirn bits set */ @@ -981,54 +1122,75 @@ UFSSwapDir::DirClean(int swap_index) N2 = SD->l2; D2 = ((swap_index / N0) / N1) % N2; snprintf(p1, SQUID_MAXPATHLEN, "%s/%02X/%02X", - SD->path, D1, D2); + SD->path, D1, D2); debug(36, 3) ("storeDirClean: Cleaning directory %s\n", p1); dp = opendir(p1); + if (dp == NULL) { - if (errno == ENOENT) { - debug(36, 0) ("storeDirClean: WARNING: Creating %s\n", p1); + if (errno == ENOENT) { + debug(36, 0) ("storeDirClean: WARNING: Creating %s\n", p1); #ifdef _SQUID_MSWIN_ - if (mkdir(p1) == 0) + + if (mkdir(p1) == 0) #else - if (mkdir(p1, 0777) == 0) + + if (mkdir(p1, 0777) == 0) #endif - return 0; - } - debug(50, 0) ("storeDirClean: %s: %s\n", p1, xstrerror()); - safeunlink(p1, 1); - return 0; + + return 0; + } + + debug(50, 0) ("storeDirClean: %s: %s\n", p1, xstrerror()); + safeunlink(p1, 1); + return 0; } + while ((de = readdir(dp)) != NULL && k < 20) { - if (sscanf(de->d_name, "%X", &swapfileno) != 1) - continue; - fn = swapfileno; /* XXX should remove this cruft ! */ - if (SD->validFileno(fn, 1)) - if (SD->mapBitTest(fn)) - if (UFSSwapDir::FilenoBelongsHere(fn, D0, D1, D2)) - continue; + if (sscanf(de->d_name, "%X", &swapfileno) != 1) + continue; + + fn = swapfileno; /* XXX should remove this cruft ! */ + + if (SD->validFileno(fn, 1)) + if (SD->mapBitTest(fn)) + if (UFSSwapDir::FilenoBelongsHere(fn, D0, D1, D2)) + continue; + #if USE_TRUNCATE - if (!stat(de->d_name, &sb)) - if (sb.st_size == 0) - continue; + + if (!stat(de->d_name, &sb)) + if (sb.st_size == 0) + continue; + #endif - files[k++] = swapfileno; + + files[k++] = swapfileno; } + closedir(dp); + if (k == 0) - return 0; + return 0; + qsort(files, k, sizeof(int), rev_int_sort); + if (k > 10) - k = 10; + k = 10; + for (n = 0; n < k; n++) { - debug(36, 3) ("storeDirClean: Cleaning file %08X\n", files[n]); - snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]); + debug(36, 3) ("storeDirClean: Cleaning file %08X\n", files[n]); + snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]); #if USE_TRUNCATE - truncate(p2, 0); + + truncate(p2, 0); #else - safeunlink(p2, 0); + + safeunlink(p2, 0); #endif - statCounter.swap.files_cleaned++; + + statCounter.swap.files_cleaned++; } + debug(36, 3) ("Cleaned %d unused files from %s\n", k, p1); return k; } @@ -1045,36 +1207,46 @@ UFSSwapDir::CleanEvent(void *unused) * we should never be called. */ assert(NumberOfUFSDirs); + if (NULL == UFSDirToGlobalDirMapping) { - SwapDir *sd; - /* - * Initialize the little array that translates UFS cache_dir - * number into the Config.cacheSwap.swapDirs array index. - */ - UFSDirToGlobalDirMapping = (int *)xcalloc(NumberOfUFSDirs, sizeof(*UFSDirToGlobalDirMapping)); - for (i = 0, n = 0; i < Config.cacheSwap.n_configured; i++) { - sd = INDEXSD(i); - if (!UFSSwapDir::IsUFSDir(sd)) - continue; - UFSSwapDir *usd = dynamic_cast(sd); - assert (usd); - UFSDirToGlobalDirMapping[n++] = i; - j += (usd->l1 * usd->l2); - } - assert(n == NumberOfUFSDirs); - /* - * Start the commonUfsDirClean() swap_index with a random - * value. j equals the total number of UFS level 2 - * swap directories - */ - swap_index = (int) (squid_random() % j); + SwapDir *sd; + /* + * Initialize the little array that translates UFS cache_dir + * number into the Config.cacheSwap.swapDirs array index. + */ + UFSDirToGlobalDirMapping = (int *)xcalloc(NumberOfUFSDirs, sizeof(*UFSDirToGlobalDirMapping)); + + for (i = 0, n = 0; i < Config.cacheSwap.n_configured; i++) { + sd = INDEXSD(i); + + if (!UFSSwapDir::IsUFSDir(sd)) + continue; + + UFSSwapDir *usd = dynamic_cast(sd); + + assert (usd); + + UFSDirToGlobalDirMapping[n++] = i; + + j += (usd->l1 * usd->l2); + } + + assert(n == NumberOfUFSDirs); + /* + * Start the commonUfsDirClean() swap_index with a random + * value. j equals the total number of UFS level 2 + * swap directories + */ + swap_index = (int) (squid_random() % j); } + if (0 == store_dirs_rebuilding) { - n = DirClean(swap_index); - swap_index++; + n = DirClean(swap_index); + swap_index++; } + eventAdd("storeDirClean", CleanEvent, NULL, - 15.0 * exp(-0.25 * n), 1); + 15.0 * exp(-0.25 * n), 1); } int @@ -1100,16 +1272,24 @@ UFSSwapDir::FilenoBelongsHere(int fn, int F0, int F1, int F2) assert(F0 < Config.cacheSwap.n_configured); assert (UFSSwapDir::IsUFSDir (INDEXSD(F0))); UFSSwapDir *sd = dynamic_cast(INDEXSD(F0)); + if (!sd) - return 0; + return 0; + L1 = sd->l1; + L2 = sd->l2; + D1 = ((filn / L2) / L2) % L1; + if (F1 != D1) - return 0; + return 0; + D2 = (filn / L2) % L2; + if (F2 != D2) - return 0; + return 0; + return 1; } @@ -1117,14 +1297,16 @@ int UFSSwapDir::validFileno(sfileno filn, int flag) const { if (filn < 0) - return 0; + return 0; + /* * If flag is set it means out-of-range file number should * be considered invalid. */ if (flag) - if (filn > map->max_n_files) - return 0; + if (filn > map->max_n_files) + return 0; + return 1; } @@ -1152,7 +1334,7 @@ void UFSSwapDir::replacementAdd(StoreEntry * e) { debug(47, 4) ("UFSSwapDir::replacementAdd: added node %p to dir %d\n", e, - index); + index); repl->Add(repl, e, &e->repl); } @@ -1161,12 +1343,17 @@ void UFSSwapDir::replacementRemove(StoreEntry * e) { SwapDir *SD; + if (e->swap_dirn < 0) - return; + return; + SD = INDEXSD(e->swap_dirn); + assert (dynamic_cast(SD) == this); + debug(47, 4) ("UFSSwapDir::replacementRemove: remove node %p from dir %d\n", e, - index); + index); + repl->Remove(repl, e, &e->repl); } @@ -1174,9 +1361,9 @@ void UFSSwapDir::dump(StoreEntry & entry) const { storeAppendPrintf(&entry, " %d %d %d", - max_size >> 10, - l1, - l2); + max_size >> 10, + l1, + l2); } char * @@ -1185,13 +1372,17 @@ UFSSwapDir::fullPath(sfileno filn, char *fullpath) const LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN); int L1 = l1; int L2 = l2; + if (!fullpath) - fullpath = fullfilename; + fullpath = fullfilename; + fullpath[0] = '\0'; + snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X/%08X", - path, - ((filn / L2) / L2) % L1, - (filn / L2) % L2, - filn); + path, + ((filn / L2) / L2) % L1, + (filn / L2) % L2, + filn); + return fullpath; } diff --git a/src/fs/ufs/store_io_ufs.cc b/src/fs/ufs/store_io_ufs.cc index e16e4e3d30..f898ea08f4 100644 --- a/src/fs/ufs/store_io_ufs.cc +++ b/src/fs/ufs/store_io_ufs.cc @@ -1,6 +1,6 @@ /* - * $Id: store_io_ufs.cc,v 1.16 2003/02/19 21:23:52 robertc Exp $ + * $Id: store_io_ufs.cc,v 1.17 2003/02/21 22:50:45 robertc Exp $ * * DEBUG: section 79 Storage Manager UFS Interface * AUTHOR: Duane Wessels @@ -46,6 +46,7 @@ UfsIO::shedLoad() { return false; } + void UfsIO::deleteSelf() const { @@ -58,7 +59,7 @@ UfsIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback return new ufsstate_t (SD, e, callback, callback_data); } -DiskFile::Pointer +DiskFile::Pointer UfsIO::newFile (char const *path) { return new UFSFile (path); @@ -76,7 +77,7 @@ ufsstate_t::operator new (size_t) cbdataReference(result); return result; } - + void ufsstate_t::operator delete (void *address) { @@ -85,8 +86,8 @@ ufsstate_t::operator delete (void *address) /* And allow the memory to be freed */ cbdataReferenceDone (t); } - -ufsstate_t::ufsstate_t(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_) + +ufsstate_t::ufsstate_t(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_) { swap_filen = anEntry->swap_filen; swap_dirn = SD->index; @@ -107,7 +108,7 @@ UFSFile::operator new (size_t) cbdataReference(result); return result; } - + void UFSFile::operator delete (void *address) { @@ -139,12 +140,14 @@ UFSFile::open (int flags, mode_t mode, IORequestor::Pointer callback) /* Simulate async calls */ fd = file_open(path_ , flags); ioRequestor = callback; + if (fd < 0) { - debug(79, 3) ("UFSFile::open: got failure (%d)\n", errno); + debug(79, 3) ("UFSFile::open: got failure (%d)\n", errno); } else { - store_open_disk_fd++; + store_open_disk_fd++; debug(79, 3) ("UFSFile::open: opened FD %d\n", fd); } + callback->ioCompletedNotification(); } @@ -159,9 +162,9 @@ UFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback) void UFSFile::doClose() { if (fd > -1) { - file_close(fd); - store_open_disk_fd--; - fd = -1; + file_close(fd); + store_open_disk_fd--; + fd = -1; } } @@ -184,7 +187,8 @@ bool UFSFile::error() const { if (fd < 0) - return true; + return true; + return false; } @@ -192,14 +196,16 @@ void ufsstate_t::ioCompletedNotification() { if (opening) { - opening = false; - /* There is no 'opened' callback */ - return; + opening = false; + /* There is no 'opened' callback */ + return; } + if (creating) { - creating = false; - return; + creating = false; + return; } + assert(0); } @@ -213,8 +219,9 @@ void ufsstate_t::close() { debug(79, 3) ("storeUfsClose: dirno %d, fileno %08X\n", - swap_dirn, swap_filen); + swap_dirn, swap_filen); closing = true; + if (!(reading || writing)) { ((UFSFile *)theFile.getRaw())->close(); } @@ -228,15 +235,17 @@ UFSStoreState::read_(char *buf, size_t size, off_t offset, STRCB * callback, voi assert(!reading); assert(!closing); assert (callback); + if (!theFile->canRead()) { - debug(79, 3) ("UFSStoreState::read_: queueing read because theFile can't read\n"); - queueRead (buf, size, offset, callback, callback_data); - return; + debug(79, 3) ("UFSStoreState::read_: queueing read because theFile can't read\n"); + queueRead (buf, size, offset, callback, callback_data); + return; } + read.callback = callback; read.callback_data = cbdataReference(callback_data); debug(79, 3) ("UFSStoreState::read_: dirno %d, fileno %08X\n", - swap_dirn, swap_filen); + swap_dirn, swap_filen); offset_ = offset; read_buf = buf; reading = true; @@ -250,7 +259,7 @@ UFSFile::read(char *buf, off_t offset, size_t size) assert (ioRequestor.getRaw()); file_read(fd, buf, size, offset, ReadDone, this); } - + void UFSFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data) { @@ -264,23 +273,25 @@ UFSFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) { debug(79, 3) ("storeUfsWrite: FD %d\n",fd); file_write(fd, - offset, - (char *)buf, - size, - WriteDone, - this, - free_func); + offset, + (char *)buf, + size, + WriteDone, + this, + free_func); } void UFSStoreState::write(char const *buf, size_t size, off_t offset, FREE * free_func) { debug(79, 3) ("UFSStoreState::write: dirn %d, fileno %08X\n", swap_dirn, swap_filen); + if (!theFile->canWrite() || writing) { - assert(creating || writing); - queueWrite(buf, size, offset, free_func); - return; + assert(creating || writing); + queueWrite(buf, size, offset, free_func); + return; } + writing = true; theFile->write(buf,size,offset,free_func); } @@ -303,14 +314,17 @@ UFSFile::readDone(int rvfd, const char *buf, int len, int errflag) assert (fd == rvfd); ssize_t rlen; + if (errflag) { - debug(79, 3) ("UFSFile::readDone: got failure (%d)\n", errflag); - rlen = -1; + debug(79, 3) ("UFSFile::readDone: got failure (%d)\n", errflag); + rlen = -1; } else { - rlen = (ssize_t) len; + rlen = (ssize_t) len; } + if (errflag == DISK_EOF) - errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ + errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ + ioRequestor->readCompleted(buf, rlen, errflag); } @@ -320,20 +334,28 @@ ufsstate_t::readCompleted(const char *buf, int len, int errflag) reading = false; debug(79, 3) ("storeUfsReadDone: dirno %d, fileno %08X, len %d\n", - swap_dirn, swap_filen, len); + swap_dirn, swap_filen, len); + if (len > 0) - offset_ += len; + offset_ += len; + STRCB *callback = read.callback; + assert(callback); + read.callback = NULL; + void *cbdata; + if (!closing && cbdataReferenceValidDone(read.callback_data, &cbdata)) { - if (len > 0 && read_buf != buf) - memcpy(read_buf, buf, len); - callback(cbdata, read_buf, len); + if (len > 0 && read_buf != buf) + memcpy(read_buf, buf, len); + + callback(cbdata, read_buf, len); } + if (closing) - fatal("Sync ufs doesn't support overlapped close and read calls\n"); + fatal("Sync ufs doesn't support overlapped close and read calls\n"); } void @@ -348,13 +370,15 @@ UFSFile::writeDone(int rvfd, int errflag, size_t len) { assert (rvfd == fd); debug(79, 3) ("storeUfsWriteDone: FD %d, len %ld\n", - fd, (long int) len); + fd, (long int) len); + if (errflag) { - debug(79, 0) ("storeUfsWriteDone: got failure (%d)\n", errflag); - doClose(); - ioRequestor->writeCompleted (DISK_ERROR,0); - return; + debug(79, 0) ("storeUfsWriteDone: got failure (%d)\n", errflag); + doClose(); + ioRequestor->writeCompleted (DISK_ERROR,0); + return; } + ioRequestor->writeCompleted(DISK_OK, len); } @@ -362,11 +386,14 @@ void ufsstate_t::writeCompleted(int errflag, size_t len) { debug(79, 3) ("storeUfsWriteDone: dirno %d, fileno %08X, len %ld\n", - swap_dirn, swap_filen, (long int) len); + swap_dirn, swap_filen, (long int) len); writing = false; + if (theFile->error()) - doCallback(DISK_ERROR); + doCallback(DISK_ERROR); + offset_ += len; + if (closing) ((UFSFile *)theFile.getRaw())->close(); } @@ -378,8 +405,10 @@ ufsstate_t::doCallback(int errflag) /* We are finished with the file */ theFile = NULL; void *cbdata; + if (cbdataReferenceValidDone(callback_data, &cbdata)) - callback(cbdata, errflag, this); + callback(cbdata, errflag, this); + callback = NULL; } @@ -395,19 +424,22 @@ ufsstate_t::~ufsstate_t() /* ============= THE REAL UFS CODE ================ */ UFSStoreState::UFSStoreState() : opening (false), creating (false), closing (false), reading(false), writing(false), pending_reads(NULL), pending_writes (NULL){} + UFSStoreState::~UFSStoreState() { _queued_read *qr; + while ((qr = (_queued_read *)linklistShift(&pending_reads))) { - cbdataReferenceDone(qr->callback_data); - delete qr; + cbdataReferenceDone(qr->callback_data); + delete qr; } struct _queued_write *qw; + while ((qw = (struct _queued_write *)linklistShift(&pending_writes))) { - if (qw->free_func) - qw->free_func(const_cast(qw->buf)); - delete qw; + if (qw->free_func) + qw->free_func(const_cast(qw->buf)); + delete qw; } } @@ -415,14 +447,20 @@ bool UFSStoreState::kickReadQueue() { _queued_read *q = (_queued_read *)linklistShift(&pending_reads); + if (NULL == q) - return false; + return false; + debug(79, 3) ("UFSStoreState::kickReadQueue: reading queued request of %ld bytes\n", - (long int) q->size); + (long int) q->size); + void *cbdata; + if (cbdataReferenceValidDone(q->callback_data, &cbdata)) - read_(q->buf, q->size, q->offset, q->callback, cbdata); + read_(q->buf, q->size, q->offset, q->callback, cbdata); + delete q; + return true; } @@ -432,7 +470,8 @@ void * UFSStoreState::_queued_read::operator new(size_t size) { if (!Pool) - Pool = memPoolCreate("AUFS Queued read data",sizeof (_queued_read)); + Pool = memPoolCreate("AUFS Queued read data",sizeof (_queued_read)); + return memPoolAlloc (Pool); } @@ -463,7 +502,8 @@ void * UFSStoreState::_queued_write::operator new(size_t size) { if (!Pool) - Pool = memPoolCreate("AUFS Queued write data",sizeof (_queued_write)); + Pool = memPoolCreate("AUFS Queued write data",sizeof (_queued_write)); + return memPoolAlloc (Pool); } @@ -477,10 +517,13 @@ bool UFSStoreState::kickWriteQueue() { _queued_write *q = (_queued_write *)linklistShift(&pending_writes); + if (NULL == q) - return false; + return false; + debug(79, 3) ("storeAufsKickWriteQueue: writing queued chunk of %ld bytes\n", - (long int) q->size); + (long int) q->size); + write(const_cast(q->buf), q->size, q->offset, q->free_func); delete q; return true; @@ -490,6 +533,7 @@ void UFSStoreState::queueWrite(char const *buf, size_t size, off_t offset, FREE * free_func) { debug(79, 3) ("UFSStoreState::queueWrite: queuing write\n"); + struct _queued_write *q; q = new _queued_write; q->buf = buf; @@ -501,70 +545,85 @@ UFSStoreState::queueWrite(char const *buf, size_t size, off_t offset, FREE * fre StoreIOState::Pointer UFSStrategy::open(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, - STIOCB * callback, void *callback_data) + STIOCB * callback, void *callback_data) { assert (((UfsSwapDir *)SD)->IO == this); debug(79, 3) ("UFSStrategy::open: fileno %08X\n", e->swap_filen); + if (shedLoad()) { - openFailed(); - return NULL; + openFailed(); + return NULL; } + /* to consider: make createstate a private UFSStrategy call */ StoreIOState::Pointer sio = createState (SD, e, callback, callback_data); - + sio->mode |= O_RDONLY; - + UFSStoreState *state = dynamic_cast (sio.getRaw()); + assert (state); + char *path = ((UFSSwapDir *)SD)->fullPath(e->swap_filen, NULL); DiskFile::Pointer myFile = newFile (path); - + state->theFile = myFile; + state->opening = true; + myFile->open (sio->mode, 0644, state); + if (myFile->error()) - return NULL; - + return NULL; + return sio; } StoreIOState::Pointer UFSStrategy::create(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, - STIOCB * callback, void *callback_data) + STIOCB * callback, void *callback_data) { assert (((UfsSwapDir *)SD)->IO == this); /* Allocate a number */ sfileno filn = ((UFSSwapDir *)SD)->mapBitAllocate(); debug(79, 3) ("UFSStrategy::create: fileno %08X\n", filn); + if (shedLoad()) { - openFailed(); - ((UFSSwapDir *)SD)->mapBitReset (filn); - return NULL; + openFailed(); + ((UFSSwapDir *)SD)->mapBitReset (filn); + return NULL; } - + /* Shouldn't we handle a 'bitmap full' error here? */ StoreIOState::Pointer sio = createState (SD, e, callback, callback_data); sio->mode |= O_WRONLY | O_CREAT | O_TRUNC; + sio->swap_filen = filn; UFSStoreState *state = dynamic_cast (sio.getRaw()); + assert (state); + char *path = ((UFSSwapDir *)SD)->fullPath(filn, NULL); - + DiskFile::Pointer myFile = newFile (path); - + state->theFile = myFile; + state->creating = true; + myFile->create (state->mode, 0644, state); + if (myFile->error()) { - ((UFSSwapDir *)SD)->mapBitReset (filn); - return NULL; + ((UFSSwapDir *)SD)->mapBitReset (filn); + return NULL; } - + /* now insert into the replacement policy */ ((UFSSwapDir *)SD)->replacementAdd(e); + return sio; } diff --git a/src/fs/ufs/store_ufs.h b/src/fs/ufs/store_ufs.h index 210809a16c..d2f09e7aec 100644 --- a/src/fs/ufs/store_ufs.h +++ b/src/fs/ufs/store_ufs.h @@ -8,8 +8,11 @@ #define __STORE_UFS_H__ #include "ufscommon.h" -class UFSFile : public DiskFile { - public: + +class UFSFile : public DiskFile +{ + +public: void *operator new(size_t); void operator delete(void *); virtual void deleteSelf() const; @@ -22,8 +25,10 @@ class UFSFile : public DiskFile { virtual void close (); virtual bool error() const; virtual int getFD() const { return fd;} + virtual bool canRead() const; - private: + +private: static DRCB ReadDone; static DWCB WriteDone; CBDATA_CLASS(UFSFile); @@ -35,9 +40,12 @@ class UFSFile : public DiskFile { void writeDone(int fd, int errflag, size_t len); }; -class ufsstate_t : public UFSStoreState { - public: +class ufsstate_t : public UFSStoreState +{ + +public: virtual void deleteSelf() const {delete this;} + void * operator new (size_t); void operator delete (void *); ufsstate_t(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data); @@ -47,7 +55,8 @@ class ufsstate_t : public UFSStoreState { void readCompleted(const char *buf, int len, int errflag); void writeCompleted(int errflag, size_t len); void closeCompleted(); - private: + +private: CBDATA_CLASS(ufsstate_t); void doCallback (int); }; @@ -58,7 +67,9 @@ class ufsstate_t : public UFSStoreState { * Store IO stuff */ /* For things that aren't factored well yet */ -class UfsSwapDir: public UFSSwapDir { + +class UfsSwapDir: public UFSSwapDir +{ virtual void dump(StoreEntry &)const; virtual void unlink(StoreEntry &); virtual int canStore(StoreEntry const&)const; @@ -69,12 +80,13 @@ class UfsSwapDir: public UFSSwapDir { class UfsIO : public UFSStrategy { + public: - virtual bool shedLoad(); - virtual void deleteSelf() const; - virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const; - virtual DiskFile::Pointer newFile (char const *path); - static UfsIO Instance; + virtual bool shedLoad(); + virtual void deleteSelf() const; + virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const; + virtual DiskFile::Pointer newFile (char const *path); + static UfsIO Instance; }; #endif diff --git a/src/ftp.cc b/src/ftp.cc index ce2aa9c31d..948b9c0965 100644 --- a/src/ftp.cc +++ b/src/ftp.cc @@ -1,6 +1,6 @@ /* - * $Id: ftp.cc,v 1.341 2003/02/14 13:59:50 robertc Exp $ + * $Id: ftp.cc,v 1.342 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 9 File Transfer Protocol (FTP) * AUTHOR: Harvest Derived @@ -71,28 +71,66 @@ typedef enum { SENT_MKDIR } ftp_state_t; -struct _ftp_flags { - unsigned int isdir:1; - unsigned int pasv_supported:1; - unsigned int skip_whitespace:1; - unsigned int rest_supported:1; - unsigned int pasv_only:1; - unsigned int authenticated:1; - unsigned int http_header_sent:1; - unsigned int tried_nlst:1; - unsigned int need_base_href:1; - unsigned int root_dir:1; - unsigned int no_dotdot:1; - unsigned int html_header_sent:1; - unsigned int binary:1; - unsigned int try_slash_hack:1; - unsigned int put:1; - unsigned int put_mkdir:1; - unsigned int listformat_unknown:1; - unsigned int datachannel_hack:1; +struct _ftp_flags +{ + +unsigned int isdir: + 1; + +unsigned int pasv_supported: + 1; + +unsigned int skip_whitespace: + 1; + +unsigned int rest_supported: + 1; + +unsigned int pasv_only: + 1; + +unsigned int authenticated: + 1; + +unsigned int http_header_sent: + 1; + +unsigned int tried_nlst: + 1; + +unsigned int need_base_href: + 1; + +unsigned int root_dir: + 1; + +unsigned int no_dotdot: + 1; + +unsigned int html_header_sent: + 1; + +unsigned int binary: + 1; + +unsigned int try_slash_hack: + 1; + +unsigned int put: + 1; + +unsigned int put_mkdir: + 1; + +unsigned int listformat_unknown: + 1; + +unsigned int datachannel_hack: + 1; }; -typedef struct _Ftpdata { +typedef struct _Ftpdata +{ StoreEntry *entry; request_t *request; char user[MAX_URL]; @@ -119,36 +157,50 @@ typedef struct _Ftpdata { char *old_reply; char *old_filepath; char typecode; - struct { - int fd; - char *buf; - size_t size; - off_t offset; - wordlist *message; - char *last_command; - char *last_reply; - int replycode; - } ctrl; - struct { - int fd; - char *buf; - size_t size; - off_t offset; - char *host; - u_short port; - } data; + + struct + { + int fd; + char *buf; + size_t size; + off_t offset; + wordlist *message; + char *last_command; + char *last_reply; + int replycode; + } + + ctrl; + + struct + { + int fd; + char *buf; + size_t size; + off_t offset; + char *host; + u_short port; + } + + data; + struct _ftp_flags flags; FwdState *fwd; -} FtpStateData; +} -typedef struct { +FtpStateData; + +typedef struct +{ char type; int size; char *date; char *name; char *showname; char *link; -} ftpListParts; +} + +ftpListParts; typedef void (FTPSM) (FtpStateData *); @@ -251,26 +303,26 @@ Quit - ************************************************/ FTPSM *FTP_SM_FUNCS[] = -{ - ftpReadWelcome, /* BEGIN */ - ftpReadUser, /* SENT_USER */ - ftpReadPass, /* SENT_PASS */ - ftpReadType, /* SENT_TYPE */ - ftpReadMdtm, /* SENT_MDTM */ - ftpReadSize, /* SENT_SIZE */ - ftpReadPort, /* SENT_PORT */ - ftpReadPasv, /* SENT_PASV */ - ftpReadCwd, /* SENT_CWD */ - ftpReadList, /* SENT_LIST */ - ftpReadList, /* SENT_NLST */ - ftpReadRest, /* SENT_REST */ - ftpReadRetr, /* SENT_RETR */ - ftpReadStor, /* SENT_STOR */ - ftpReadQuit, /* SENT_QUIT */ - ftpReadTransferDone, /* READING_DATA (RETR,LIST,NLST) */ - ftpWriteTransferDone, /* WRITING_DATA (STOR) */ - ftpReadMkdir /* SENT_MKDIR */ -}; + { + ftpReadWelcome, /* BEGIN */ + ftpReadUser, /* SENT_USER */ + ftpReadPass, /* SENT_PASS */ + ftpReadType, /* SENT_TYPE */ + ftpReadMdtm, /* SENT_MDTM */ + ftpReadSize, /* SENT_SIZE */ + ftpReadPort, /* SENT_PORT */ + ftpReadPasv, /* SENT_PASV */ + ftpReadCwd, /* SENT_CWD */ + ftpReadList, /* SENT_LIST */ + ftpReadList, /* SENT_NLST */ + ftpReadRest, /* SENT_REST */ + ftpReadRetr, /* SENT_RETR */ + ftpReadStor, /* SENT_STOR */ + ftpReadQuit, /* SENT_QUIT */ + ftpReadTransferDone, /* READING_DATA (RETR,LIST,NLST) */ + ftpWriteTransferDone, /* WRITING_DATA (STOR) */ + ftpReadMkdir /* SENT_MKDIR */ + }; static void ftpStateFree(int fdnotused, void *data) @@ -283,42 +335,63 @@ static void ftpStateFreed(void *data) { FtpStateData *ftpState = (FtpStateData *)data; + if (ftpState == NULL) - return; + return; + debug(9, 3) ("ftpStateFree: %s\n", storeUrl(ftpState->entry)); + storeUnregisterAbort(ftpState->entry); + storeUnlockObject(ftpState->entry); + if (ftpState->reply_hdr) { - memFree(ftpState->reply_hdr, MEM_8K_BUF); - ftpState->reply_hdr = NULL; + memFree(ftpState->reply_hdr, MEM_8K_BUF); + ftpState->reply_hdr = NULL; } + requestUnlink(ftpState->request); + if (ftpState->ctrl.buf) { - memFreeBuf(ftpState->ctrl.size, ftpState->ctrl.buf); - ftpState->ctrl.buf = NULL; + memFreeBuf(ftpState->ctrl.size, ftpState->ctrl.buf); + ftpState->ctrl.buf = NULL; } + if (ftpState->data.buf) { - memFreeBuf(ftpState->data.size, ftpState->data.buf); - ftpState->data.buf = NULL; + memFreeBuf(ftpState->data.size, ftpState->data.buf); + ftpState->data.buf = NULL; } + if (ftpState->pathcomps) - wordlistDestroy(&ftpState->pathcomps); + wordlistDestroy(&ftpState->pathcomps); + if (ftpState->ctrl.message) - wordlistDestroy(&ftpState->ctrl.message); + wordlistDestroy(&ftpState->ctrl.message); + if (ftpState->cwd_message) - wordlistDestroy(&ftpState->cwd_message); + wordlistDestroy(&ftpState->cwd_message); + safe_free(ftpState->ctrl.last_reply); + safe_free(ftpState->ctrl.last_command); + safe_free(ftpState->old_request); + safe_free(ftpState->old_reply); + safe_free(ftpState->old_filepath); + ftpState->title_url.clean(); + ftpState->base_href.clean(); + safe_free(ftpState->filepath); + safe_free(ftpState->data.host); + if (ftpState->data.fd > -1) { - comm_close(ftpState->data.fd); - ftpState->data.fd = -1; + comm_close(ftpState->data.fd); + ftpState->data.fd = -1; } } @@ -327,20 +400,27 @@ ftpLoginParser(const char *login, FtpStateData * ftpState, int escaped) { char *s = NULL; xstrncpy(ftpState->user, login, MAX_URL); + if ((s = strchr(ftpState->user, ':'))) { - *s = 0; - xstrncpy(ftpState->password, s + 1, MAX_URL); - if (escaped) - rfc1738_unescape(ftpState->password); - ftpState->password_url = 1; + *s = 0; + xstrncpy(ftpState->password, s + 1, MAX_URL); + + if (escaped) + rfc1738_unescape(ftpState->password); + + ftpState->password_url = 1; } else { - xstrncpy(ftpState->password, null_string, MAX_URL); + xstrncpy(ftpState->password, null_string, MAX_URL); } + if (escaped) - rfc1738_unescape(ftpState->user); + rfc1738_unescape(ftpState->user); + if (ftpState->user[0] || ftpState->password[0]) - return; + return; + xstrncpy(ftpState->user, "anonymous", MAX_URL); + xstrncpy(ftpState->password, Config.Ftp.anon_user, MAX_URL); } @@ -350,12 +430,14 @@ ftpTimeout(int fd, void *data) FtpStateData *ftpState = (FtpStateData *)data; StoreEntry *entry = ftpState->entry; debug(9, 4) ("ftpTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); + if (SENT_PASV == ftpState->state && fd == ftpState->data.fd) { - /* stupid ftp.netscape.com */ - ftpState->fwd->flags.dont_retry = 0; - ftpState->fwd->flags.ftp_pasv_failed = 1; - debug(9, 1) ("ftpTimeout: timeout in SENT_PASV state\n"); + /* stupid ftp.netscape.com */ + ftpState->fwd->flags.dont_retry = 0; + ftpState->fwd->flags.ftp_pasv_failed = 1; + debug(9, 1) ("ftpTimeout: timeout in SENT_PASV state\n"); } + ftpFailed(ftpState, ERR_READ_TIMEOUT); /* ftpFailed closes ctrl.fd and frees ftpState */ } @@ -370,54 +452,72 @@ ftpListingStart(FtpStateData * ftpState) char *title; storeBuffer(e); storeAppendPrintf(e, "\n", - version_string); + version_string); storeAppendPrintf(e, "\n", mkrfc1123(squid_curtime)); storeAppendPrintf(e, "\n"); storeAppendPrintf(e, "\n"); storeAppendPrintf(e, "FTP Directory: %s\n", - html_quote(ftpState->title_url.buf())); + html_quote(ftpState->title_url.buf())); storeAppendPrintf(e, "\n"); storeAppendPrintf(e, "\n"); + if (ftpState->flags.need_base_href) - storeAppendPrintf(e, "\n", - html_quote(ftpState->base_href.buf())); + storeAppendPrintf(e, "\n", + html_quote(ftpState->base_href.buf())); + storeAppendPrintf(e, "\n"); + if (ftpState->cwd_message) { - storeAppendPrintf(e, "
    \n");
    -	for (w = ftpState->cwd_message; w; w = w->next)
    -	    storeAppendPrintf(e, "%s\n", html_quote(w->key));
    -	storeAppendPrintf(e, "
    \n"); - storeAppendPrintf(e, "
    \n"); - wordlistDestroy(&ftpState->cwd_message); + storeAppendPrintf(e, "
    \n");
    +
    +        for (w = ftpState->cwd_message; w; w = w->next)
    +            storeAppendPrintf(e, "%s\n", html_quote(w->key));
    +
    +        storeAppendPrintf(e, "
    \n"); + + storeAppendPrintf(e, "
    \n"); + + wordlistDestroy(&ftpState->cwd_message); } + storeAppendPrintf(e, "

    \n"); storeAppendPrintf(e, "FTP Directory: "); /* "ftp://" == 6 characters */ assert(ftpState->title_url.size() >= 6); title = html_quote(ftpState->title_url.buf()); + for (i = 6, j = 0; title[i]; j = i) { - storeAppendPrintf(e, ""); - for (k = j; k < i - 1; k++) - storeAppendPrintf(e, "%c", title[k]); - if (ftpState->title_url.buf()[k] != '/') - storeAppendPrintf(e, "%c", title[k++]); - storeAppendPrintf(e, ""); - if (k < i) - storeAppendPrintf(e, "%c", title[k++]); - if (i == j) { - /* Error guard, or "assert" */ - storeAppendPrintf(e, "ERROR: Failed to parse URL: %s\n", - html_quote(ftpState->title_url.buf())); - debug(9, 0) ("Failed to parse URL: %s\n", ftpState->title_url.buf()); - break; - } + storeAppendPrintf(e, ""); + + for (k = j; k < i - 1; k++) + storeAppendPrintf(e, "%c", title[k]); + + if (ftpState->title_url.buf()[k] != '/') + storeAppendPrintf(e, "%c", title[k++]); + + storeAppendPrintf(e, ""); + + if (k < i) + storeAppendPrintf(e, "%c", title[k++]); + + if (i == j) { + /* Error guard, or "assert" */ + storeAppendPrintf(e, "ERROR: Failed to parse URL: %s\n", + html_quote(ftpState->title_url.buf())); + debug(9, 0) ("Failed to parse URL: %s\n", ftpState->title_url.buf()); + break; + } } + storeAppendPrintf(e, "

    \n"); storeAppendPrintf(e, "
    \n");
         dirup = ftpHtmlifyListEntry("", ftpState);
    @@ -432,34 +532,38 @@ ftpListingFinish(FtpStateData * ftpState)
         StoreEntry *e = ftpState->entry;
         storeBuffer(e);
         storeAppendPrintf(e, "
    \n"); + if (ftpState->flags.listformat_unknown && !ftpState->flags.tried_nlst) { - storeAppendPrintf(e, "[As plain directory]\n"); + storeAppendPrintf(e, "[As plain directory]\n"); } else if (ftpState->typecode == 'D') { - storeAppendPrintf(e, "[As extended directory]\n"); + storeAppendPrintf(e, "[As extended directory]\n"); } + storeAppendPrintf(e, "
    \n"); storeAppendPrintf(e, "
    \n"); storeAppendPrintf(e, "Generated %s by %s (%s)\n", - mkrfc1123(squid_curtime), - getMyHostname(), - full_appname_string); + mkrfc1123(squid_curtime), + getMyHostname(), + full_appname_string); storeAppendPrintf(e, "
    \n"); storeBufferFlush(e); } static const char *Month[] = -{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; + { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; static int is_month(const char *buf) { int i; + for (i = 0; i < 12; i++) - if (!strcasecmp(buf, Month[i])) - return 1; + if (!strcasecmp(buf, Month[i])) + return 1; + return 0; } @@ -477,6 +581,7 @@ ftpListPartsFree(ftpListParts ** parts) #define MAX_TOKENS 64 static ftpListParts * + ftpListParseParts(const char *buf, struct _ftp_flags flags) { ftpListParts *p = NULL; @@ -493,157 +598,217 @@ ftpListParseParts(const char *buf, struct _ftp_flags flags) static regex_t scan_ftp_dostime; static regex_t scan_ftp_dosdate; - if (!scan_ftp_initialized) { - scan_ftp_initialized = 1; - regcomp(&scan_ftp_integer, "^[0123456789]+$", REG_EXTENDED | REG_NOSUB); - regcomp(&scan_ftp_time, "^[0123456789:]+$", REG_EXTENDED | REG_NOSUB); - regcomp(&scan_ftp_dosdate, "^[0123456789]+-[0123456789]+-[0123456789]+$", REG_EXTENDED | REG_NOSUB); - regcomp(&scan_ftp_dostime, "^[0123456789]+:[0123456789]+[AP]M$", REG_EXTENDED | REG_NOSUB | REG_ICASE); + if (!scan_ftp_initialized) + { + scan_ftp_initialized = 1; + regcomp(&scan_ftp_integer, "^[0123456789]+$", REG_EXTENDED | REG_NOSUB); + regcomp(&scan_ftp_time, "^[0123456789:]+$", REG_EXTENDED | REG_NOSUB); + regcomp(&scan_ftp_dosdate, "^[0123456789]+-[0123456789]+-[0123456789]+$", REG_EXTENDED | REG_NOSUB); + regcomp(&scan_ftp_dostime, "^[0123456789]+:[0123456789]+[AP]M$", REG_EXTENDED | REG_NOSUB | REG_ICASE); } + if (buf == NULL) - return NULL; + return NULL; + if (*buf == '\0') - return NULL; + return NULL; + p = (ftpListParts *)xcalloc(1, sizeof(ftpListParts)); + n_tokens = 0; + memset(tokens, 0, sizeof(tokens)); + xbuf = xstrdup(buf); - if (flags.tried_nlst) { - /* Machine readable format, one name per line */ - p->name = xbuf; - p->type = '\0'; - return p; + + if (flags.tried_nlst) + { + /* Machine readable format, one name per line */ + p->name = xbuf; + p->type = '\0'; + return p; } + for (t = strtok(xbuf, w_space); t && n_tokens < MAX_TOKENS; t = strtok(NULL, w_space)) - tokens[n_tokens++] = xstrdup(t); + tokens[n_tokens++] = xstrdup(t); + xfree(xbuf); + /* locate the Month field */ - for (i = 3; i < n_tokens - 2; i++) { - char *size = tokens[i - 1]; - char *month = tokens[i]; - char *day = tokens[i + 1]; - char *year = tokens[i + 2]; - if (!is_month(month)) - continue; - if (regexec(&scan_ftp_integer, size, 0, NULL, 0) != 0) - continue; - if (regexec(&scan_ftp_integer, day, 0, NULL, 0) != 0) - continue; - if (regexec(&scan_ftp_time, day, 0, NULL, 0) != 0) /* Yr | hh:mm */ - continue; - snprintf(tbuf, 128, "%s %2s %5s", - month, day, year); - if (!strstr(buf, tbuf)) - snprintf(tbuf, 128, "%s %2s %-5s", - month, day, year); - if ((t = strstr(buf, tbuf))) { - p->type = *tokens[0]; - p->size = atoi(size); - p->date = xstrdup(tbuf); - if (flags.skip_whitespace) { - t += strlen(tbuf); - while (strchr(w_space, *t)) - t++; - } else { - /* XXX assumes a single space between date and filename - * suggested by: Nathan.Bailey@cc.monash.edu.au and - * Mike Battersby */ - t += strlen(tbuf) + 1; - } - p->name = xstrdup(t); - if ((t = strstr(p->name, " -> "))) { - *t = '\0'; - p->link = xstrdup(t + 4); - } - goto found; - } - break; + for (i = 3; i < n_tokens - 2; i++) + { + char *size = tokens[i - 1]; + char *month = tokens[i]; + char *day = tokens[i + 1]; + char *year = tokens[i + 2]; + + if (!is_month(month)) + continue; + + if (regexec(&scan_ftp_integer, size, 0, NULL, 0) != 0) + continue; + + if (regexec(&scan_ftp_integer, day, 0, NULL, 0) != 0) + continue; + + if (regexec(&scan_ftp_time, day, 0, NULL, 0) != 0) /* Yr | hh:mm */ + continue; + + snprintf(tbuf, 128, "%s %2s %5s", + month, day, year); + + if (!strstr(buf, tbuf)) + snprintf(tbuf, 128, "%s %2s %-5s", + month, day, year); + + if ((t = strstr(buf, tbuf))) { + p->type = *tokens[0]; + p->size = atoi(size); + p->date = xstrdup(tbuf); + + if (flags.skip_whitespace) { + t += strlen(tbuf); + + while (strchr(w_space, *t)) + t++; + } else { + /* XXX assumes a single space between date and filename + * suggested by: Nathan.Bailey@cc.monash.edu.au and + * Mike Battersby */ + t += strlen(tbuf) + 1; + } + + p->name = xstrdup(t); + + if ((t = strstr(p->name, " -> "))) { + *t = '\0'; + p->link = xstrdup(t + 4); + } + + goto found; + } + + break; } + /* try it as a DOS listing, 04-05-70 09:33PM ... */ if (n_tokens > 3 && - regexec(&scan_ftp_dosdate, tokens[0], 0, NULL, 0) == 0 && - regexec(&scan_ftp_dostime, tokens[1], 0, NULL, 0) == 0) { - if (!strcasecmp(tokens[2], "")) { - p->type = 'd'; - } else { - p->type = '-'; - p->size = atoi(tokens[2]); - } - snprintf(tbuf, 128, "%s %s", tokens[0], tokens[1]); - p->date = xstrdup(tbuf); - if (p->type == 'd') { - /* Directory.. name begins with first printable after */ - ct = strstr(buf, tokens[2]); - ct += strlen(tokens[2]); - while (xisspace(*ct)) - ct++; - if (!*ct) - ct = NULL; - } else { - /* A file. Name begins after size, with a space in between */ - snprintf(tbuf, 128, " %s %s", tokens[2], tokens[3]); - ct = strstr(buf, tbuf); - if (ct) { - ct += strlen(tokens[2]) + 2; - } - } - p->name = xstrdup(ct ? ct : tokens[3]); - goto found; + regexec(&scan_ftp_dosdate, tokens[0], 0, NULL, 0) == 0 && + regexec(&scan_ftp_dostime, tokens[1], 0, NULL, 0) == 0) + { + if (!strcasecmp(tokens[2], "")) { + p->type = 'd'; + } else { + p->type = '-'; + p->size = atoi(tokens[2]); + } + + snprintf(tbuf, 128, "%s %s", tokens[0], tokens[1]); + p->date = xstrdup(tbuf); + + if (p->type == 'd') { + /* Directory.. name begins with first printable after */ + ct = strstr(buf, tokens[2]); + ct += strlen(tokens[2]); + + while (xisspace(*ct)) + ct++; + + if (!*ct) + ct = NULL; + } else { + /* A file. Name begins after size, with a space in between */ + snprintf(tbuf, 128, " %s %s", tokens[2], tokens[3]); + ct = strstr(buf, tbuf); + + if (ct) { + ct += strlen(tokens[2]) + 2; + } + } + + p->name = xstrdup(ct ? ct : tokens[3]); + goto found; } + /* Try EPLF format; carson@lehman.com */ - if (buf[0] == '+') { - ct = buf + 1; - p->type = 0; - while (ct && *ct) { - time_t t; - int l = strcspn(ct + 1, ","); - char *tmp; - if (l < 1) - goto blank; - switch (*ct) { - case '\t': - p->name = xstrndup(ct + 1, l + 1); - break; - case 's': - p->size = atoi(ct + 1); - break; - case 'm': - t = (time_t) strtol(ct + 1, &tmp, 0); - if (*tmp || (tmp == ct + 1)) - break; /* not a valid integer */ - p->date = xstrdup(ctime(&t)); - *(strstr(p->date, "\n")) = '\0'; - break; - case '/': - p->type = 'd'; - break; - case 'r': - p->type = '-'; - break; - case 'i': - break; - default: - break; - } - blank: - ct = strstr(ct, ","); - if (ct) { - ct++; - } - } - if (p->type == 0) { - p->type = '-'; - } - if (p->name) - goto found; - else - safe_free(p->date); - } - found: + if (buf[0] == '+') + { + ct = buf + 1; + p->type = 0; + + while (ct && *ct) { + time_t t; + int l = strcspn(ct + 1, ","); + char *tmp; + + if (l < 1) + goto blank; + + switch (*ct) { + + case '\t': + p->name = xstrndup(ct + 1, l + 1); + break; + + case 's': + p->size = atoi(ct + 1); + break; + + case 'm': + t = (time_t) strtol(ct + 1, &tmp, 0); + + if (*tmp || (tmp == ct + 1)) + break; /* not a valid integer */ + + p->date = xstrdup(ctime(&t)); + + *(strstr(p->date, "\n")) = '\0'; + + break; + + case '/': + p->type = 'd'; + + break; + + case 'r': + p->type = '-'; + + break; + + case 'i': + break; + + default: + break; + } + +blank: + ct = strstr(ct, ","); + + if (ct) { + ct++; + } + } + + if (p->type == 0) { + p->type = '-'; + } + + if (p->name) + goto found; + else + safe_free(p->date); + } + +found: + for (i = 0; i < n_tokens; i++) - xfree(tokens[i]); + xfree(tokens[i]); + if (!p->name) - ftpListPartsFree(&p); /* cleanup */ + ftpListPartsFree(&p); /* cleanup */ + return p; } @@ -652,15 +817,19 @@ dots_fill(size_t len) { static char buf[256]; size_t i = 0; + if (len > Config.Ftp.list_width) { - memset(buf, ' ', 256); - buf[0] = '\n'; - buf[Config.Ftp.list_width + 4] = '\0'; - return buf; + memset(buf, ' ', 256); + buf[0] = '\n'; + buf[Config.Ftp.list_width + 4] = '\0'; + return buf; } + for (i = len; i < Config.Ftp.list_width; i++) - buf[i - len] = (i % 2) ? '.' : ' '; + buf[i - len] = (i % 2) ? '.' : ' '; + buf[i - len] = '\0'; + return buf; } @@ -679,130 +848,156 @@ ftpHtmlifyListEntry(const char *line, FtpStateData * ftpState) size_t width = Config.Ftp.list_width; ftpListParts *parts; *icon = *href = *text = *size = *chdir = *view = *download = *link = *html = '\0'; + if ((int) strlen(line) > 1024) { - snprintf(html, 8192, "%s\n", line); - return html; + snprintf(html, 8192, "%s\n", line); + return html; } + /* Handle builtin */ if (strcmp(line, "") == 0) { - /* {icon} {text} {link} */ - snprintf(icon, 2048, "\"%-6s\"", - mimeGetIconURL("internal-dirup"), - "[DIRUP]"); - if (!ftpState->flags.no_dotdot && !ftpState->flags.root_dir) { - /* Normal directory */ - strcpy(href, "../"); - strcpy(text, "Parent Directory"); - } else if (!ftpState->flags.no_dotdot && ftpState->flags.root_dir) { - /* "Top level" directory */ - strcpy(href, "%2e%2e/"); - strcpy(text, "Parent Directory"); - snprintf(link, 2048, "(%s)", - "%2f/", - "Root Directory"); - } else if (ftpState->flags.no_dotdot && !ftpState->flags.root_dir) { - /* Normal directory where last component is / or .. */ - strcpy(href, "%2e%2e/"); - strcpy(text, "Parent Directory"); - snprintf(link, 2048, "(%s)", - "../", - "Back"); - } else { /* NO_DOTDOT && ROOT_DIR */ - /* "UNIX Root" directory */ - strcpy(href, "../"); - strcpy(text, "Home Directory"); - } - snprintf(html, 8192, "%s %s %s\n", - href, icon, href, text, link); - return html; + /* {icon} {text} {link} */ + snprintf(icon, 2048, "\"%-6s\"", + mimeGetIconURL("internal-dirup"), + "[DIRUP]"); + + if (!ftpState->flags.no_dotdot && !ftpState->flags.root_dir) { + /* Normal directory */ + strcpy(href, "../"); + strcpy(text, "Parent Directory"); + } else if (!ftpState->flags.no_dotdot && ftpState->flags.root_dir) { + /* "Top level" directory */ + strcpy(href, "%2e%2e/"); + strcpy(text, "Parent Directory"); + snprintf(link, 2048, "(%s)", + "%2f/", + "Root Directory"); + } else if (ftpState->flags.no_dotdot && !ftpState->flags.root_dir) { + /* Normal directory where last component is / or .. */ + strcpy(href, "%2e%2e/"); + strcpy(text, "Parent Directory"); + snprintf(link, 2048, "(%s)", + "../", + "Back"); + } else { /* NO_DOTDOT && ROOT_DIR */ + /* "UNIX Root" directory */ + strcpy(href, "../"); + strcpy(text, "Home Directory"); + } + + snprintf(html, 8192, "%s %s %s\n", + href, icon, href, text, link); + return html; } + if ((parts = ftpListParseParts(line, ftpState->flags)) == NULL) { - const char *p; - snprintf(html, 8192, "%s\n", line); - for (p = line; *p && xisspace(*p); p++); - if (*p && !xisspace(*p)) - ftpState->flags.listformat_unknown = 1; - return html; + const char *p; + snprintf(html, 8192, "%s\n", line); + + for (p = line; *p && xisspace(*p); p++) + + ; + if (*p && !xisspace(*p)) + ftpState->flags.listformat_unknown = 1; + + return html; } + if (!strcmp(parts->name, ".") || !strcmp(parts->name, "..")) { - *html = '\0'; - ftpListPartsFree(&parts); - return html; + *html = '\0'; + ftpListPartsFree(&parts); + return html; } + parts->size += 1023; parts->size >>= 10; parts->showname = xstrdup(parts->name); + if (!Config.Ftp.list_wrap) { - if (strlen(parts->showname) > width - 1) { - *(parts->showname + width - 1) = '>'; - *(parts->showname + width - 0) = '\0'; - } + if (strlen(parts->showname) > width - 1) { + *(parts->showname + width - 1) = '>'; + *(parts->showname + width - 0) = '\0'; + } } + /* {icon} {text} . . . {date}{size}{chdir}{view}{download}{link}\n */ xstrncpy(href, rfc1738_escape_part(parts->name), 2048); + xstrncpy(text, parts->showname, 2048); + switch (parts->type) { + case 'd': - snprintf(icon, 2048, "\"%-6s\"", - mimeGetIconURL("internal-dir"), - "[DIR]"); - strcat(href, "/"); /* margin is allocated above */ - break; + snprintf(icon, 2048, "\"%-6s\"", + mimeGetIconURL("internal-dir"), + "[DIR]"); + strcat(href, "/"); /* margin is allocated above */ + break; + case 'l': - snprintf(icon, 2048, "\"%-6s\"", - mimeGetIconURL("internal-link"), - "[LINK]"); - /* sometimes there is an 'l' flag, but no "->" link */ - if (parts->link) { - char *link2 = xstrdup(html_quote(rfc1738_escape(parts->link))); - snprintf(link, 2048, " -> %s", - link2, - html_quote(parts->link)); - safe_free(link2); - } - break; + snprintf(icon, 2048, "\"%-6s\"", + mimeGetIconURL("internal-link"), + "[LINK]"); + /* sometimes there is an 'l' flag, but no "->" link */ + + if (parts->link) { + char *link2 = xstrdup(html_quote(rfc1738_escape(parts->link))); + snprintf(link, 2048, " -> %s", + link2, + html_quote(parts->link)); + safe_free(link2); + } + + break; + case '\0': - snprintf(icon, 2048, "\"%-6s\"", - mimeGetIconURL(parts->name), - "[UNKNOWN]"); - snprintf(chdir, 2048, " ", - rfc1738_escape_part(parts->name), - mimeGetIconURL("internal-dir")); - break; + snprintf(icon, 2048, "\"%-6s\"", + mimeGetIconURL(parts->name), + "[UNKNOWN]"); + snprintf(chdir, 2048, " ", + rfc1738_escape_part(parts->name), + mimeGetIconURL("internal-dir")); + break; + case '-': + default: - snprintf(icon, 2048, "\"%-6s\"", - mimeGetIconURL(parts->name), - "[FILE]"); - snprintf(size, 2048, " %6dk", parts->size); - break; + snprintf(icon, 2048, "\"%-6s\"", + mimeGetIconURL(parts->name), + "[FILE]"); + snprintf(size, 2048, " %6dk", parts->size); + break; } + if (parts->type != 'd') { - if (mimeGetViewOption(parts->name)) { - snprintf(view, 2048, " ", - href, mimeGetIconURL("internal-view")); - } - if (mimeGetDownloadOption(parts->name)) { - snprintf(download, 2048, " ", - href, mimeGetIconURL("internal-download")); - } + if (mimeGetViewOption(parts->name)) { + snprintf(view, 2048, " ", + href, mimeGetIconURL("internal-view")); + } + + if (mimeGetDownloadOption(parts->name)) { + snprintf(download, 2048, " ", + href, mimeGetIconURL("internal-download")); + } } + /* {icon} {text} . . . {date}{size}{chdir}{view}{download}{link}\n */ if (parts->type != '\0') { - snprintf(html, 8192, "%s %s%s " - "%s%8s%s%s%s%s\n", - href, icon, href, html_quote(text), dots_fill(strlen(text)), - parts->date, size, chdir, view, download, link); + snprintf(html, 8192, "%s %s%s " + "%s%8s%s%s%s%s\n", + href, icon, href, html_quote(text), dots_fill(strlen(text)), + parts->date, size, chdir, view, download, link); } else { - /* Plain listing. {icon} {text} ... {chdir}{view}{download} */ - snprintf(html, 8192, "%s %s%s " - "%s%s%s%s\n", - href, icon, href, html_quote(text), dots_fill(strlen(text)), - chdir, view, download, link); + /* Plain listing. {icon} {text} ... {chdir}{view}{download} */ + snprintf(html, 8192, "%s %s%s " + "%s%s%s%s\n", + href, icon, href, html_quote(text), dots_fill(strlen(text)), + chdir, view, download, link); } + ftpListPartsFree(&parts); return html; } @@ -826,47 +1021,68 @@ ftpParseListing(FtpStateData * ftpState) sbuf = (char *)xmalloc(len + 1); xstrncpy(sbuf, buf, len + 1); end = sbuf + len - 1; + while (*end != '\r' && *end != '\n' && end > sbuf) - end--; + end--; + usable = end - sbuf; + debug(9, 3) ("ftpParseListing: usable = %d\n", (int) usable); + if (usable == 0) { - debug(9, 3) ("ftpParseListing: didn't find end for %s\n", storeUrl(e)); - xfree(sbuf); - return; + debug(9, 3) ("ftpParseListing: didn't find end for %s\n", storeUrl(e)); + xfree(sbuf); + return; } + debug(9, 3) ("ftpParseListing: %lu bytes to play with\n", (unsigned long int)len); line = (char *)memAllocate(MEM_4K_BUF); end++; storeBuffer(e); s = sbuf; s += strspn(s, crlf); + for (; s < end; s += strcspn(s, crlf), s += strspn(s, crlf)) { - debug(9, 3) ("ftpParseListing: s = {%s}\n", s); - linelen = strcspn(s, crlf) + 1; - if (linelen < 2) - break; - if (linelen > 4096) - linelen = 4096; - xstrncpy(line, s, linelen); - debug(9, 7) ("ftpParseListing: {%s}\n", line); - if (!strncmp(line, "total", 5)) - continue; - t = ftpHtmlifyListEntry(line, ftpState); - assert(t != NULL); - storeAppend(e, t, strlen(t)); + debug(9, 3) ("ftpParseListing: s = {%s}\n", s); + linelen = strcspn(s, crlf) + 1; + + if (linelen < 2) + break; + + if (linelen > 4096) + linelen = 4096; + + xstrncpy(line, s, linelen); + + debug(9, 7) ("ftpParseListing: {%s}\n", line); + + if (!strncmp(line, "total", 5)) + continue; + + t = ftpHtmlifyListEntry(line, ftpState); + + assert(t != NULL); + + storeAppend(e, t, strlen(t)); } + storeBufferFlush(e); assert(usable <= len); + if (usable < len) { - /* must copy partial line to beginning of buf */ - linelen = len - usable; - if (linelen > 4096) - linelen = 4096; - xstrncpy(line, end, linelen); - xstrncpy(ftpState->data.buf, line, ftpState->data.size); - ftpState->data.offset = strlen(ftpState->data.buf); + /* must copy partial line to beginning of buf */ + linelen = len - usable; + + if (linelen > 4096) + linelen = 4096; + + xstrncpy(line, end, linelen); + + xstrncpy(ftpState->data.buf, line, ftpState->data.size); + + ftpState->data.offset = strlen(ftpState->data.buf); } + memFree(line, MEM_4K_BUF); xfree(sbuf); } @@ -876,14 +1092,16 @@ ftpDataComplete(FtpStateData * ftpState) { debug(9, 3) ("ftpDataComplete\n"); /* Connection closed; transfer done. */ + if (ftpState->data.fd > -1) { - /* - * close data socket so it does not occupy resources while - * we wait - */ - comm_close(ftpState->data.fd); - ftpState->data.fd = -1; + /* + * close data socket so it does not occupy resources while + * we wait + */ + comm_close(ftpState->data.fd); + ftpState->data.fd = -1; } + /* expect the "transfer complete" message on the control socket */ ftpScheduleReadControlReply(ftpState, 1); } @@ -897,67 +1115,86 @@ ftpDataRead(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *da StoreEntry *entry = ftpState->entry; size_t read_sz; #if DELAY_POOLS + DelayId delayId = entry->mem_obj->mostBytesAllowed(); #endif + assert(fd == ftpState->data.fd); /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ + if (flag == COMM_ERR_CLOSING) { - return; + return; } - + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - comm_close(ftpState->ctrl.fd); - return; + comm_close(ftpState->ctrl.fd); + return; } if (flag == COMM_OK && len > 0) { #if DELAY_POOLS - delayId.bytesIn(len); + delayId.bytesIn(len); #endif - kb_incr(&statCounter.server.all.kbytes_in, len); - kb_incr(&statCounter.server.ftp.kbytes_in, len); - ftpState->data.offset += len; + + kb_incr(&statCounter.server.all.kbytes_in, len); + kb_incr(&statCounter.server.ftp.kbytes_in, len); + ftpState->data.offset += len; } + debug(9, 5) ("ftpDataRead: FD %d, Read %d bytes\n", fd, (unsigned int)len); + if (flag == COMM_OK && len > 0) { - IOStats.Ftp.reads++; - for (j = len - 1, bin = 0; j; bin++) - j >>= 1; - IOStats.Ftp.read_hist[bin]++; + IOStats.Ftp.reads++; + + for (j = len - 1, bin = 0; j; bin++) + j >>= 1; + + IOStats.Ftp.read_hist[bin]++; } + if (ftpState->flags.isdir && !ftpState->flags.html_header_sent && len >= 0) { - ftpListingStart(ftpState); + ftpListingStart(ftpState); } + if (flag != COMM_OK || len < 0) { - debug(50, ignoreErrno(errno) ? 3 : 1) ("ftpDataRead: read error: %s\n", xstrerror()); - if (ignoreErrno(errno)) { - /* XXX what about Config.Timeout.read? */ - read_sz = ftpState->data.size - ftpState->data.offset; + debug(50, ignoreErrno(errno) ? 3 : 1) ("ftpDataRead: read error: %s\n", xstrerror()); + + if (ignoreErrno(errno)) { + /* XXX what about Config.Timeout.read? */ + read_sz = ftpState->data.size - ftpState->data.offset; #if DELAY_POOLS - read_sz = delayId.bytesWanted(1, read_sz); + + read_sz = delayId.bytesWanted(1, read_sz); #endif - comm_read(fd, ftpState->data.buf + ftpState->data.offset, read_sz, ftpDataRead, data); - } else { - ftpFailed(ftpState, ERR_READ_ERROR); - /* ftpFailed closes ctrl.fd and frees ftpState */ - return; - } + + comm_read(fd, ftpState->data.buf + ftpState->data.offset, read_sz, ftpDataRead, data); + } else { + ftpFailed(ftpState, ERR_READ_ERROR); + /* ftpFailed closes ctrl.fd and frees ftpState */ + return; + } } else if (len == 0) { - ftpDataComplete(ftpState); + ftpDataComplete(ftpState); } else { - if (ftpState->flags.isdir) { - ftpParseListing(ftpState); - } else { - storeAppend(entry, ftpState->data.buf, len); - ftpState->data.offset = 0; - } - /* XXX what about Config.Timeout.read? */ - read_sz = ftpState->data.size - ftpState->data.offset; + if (ftpState->flags.isdir) { + ftpParseListing(ftpState); + } else { + storeAppend(entry, ftpState->data.buf, len); + ftpState->data.offset = 0; + } + + /* XXX what about Config.Timeout.read? */ + read_sz = ftpState->data.size - ftpState->data.offset; + #if DELAY_POOLS - read_sz = delayId.bytesWanted(1, read_sz); + + read_sz = delayId.bytesWanted(1, read_sz); + #endif - comm_read(fd, ftpState->data.buf + ftpState->data.offset, read_sz, ftpDataRead, data);} + + comm_read(fd, ftpState->data.buf + ftpState->data.offset, read_sz, ftpDataRead, data); + } } /* @@ -972,20 +1209,28 @@ ftpCheckAuth(FtpStateData * ftpState, const HttpHeader * req_hdr) char *orig_user; const char *auth; ftpLoginParser(ftpState->request->login, ftpState, FTP_LOGIN_ESCAPED); + if (!ftpState->user[0]) - return 1; /* no name */ + return 1; /* no name */ + if (ftpState->password_url || ftpState->password[0]) - return 1; /* passwd provided in URL */ + return 1; /* passwd provided in URL */ + /* URL has name, but no passwd */ if (!(auth = httpHeaderGetAuth(req_hdr, HDR_AUTHORIZATION, "Basic"))) - return 0; /* need auth header */ + return 0; /* need auth header */ + ftpState->flags.authenticated = 1; + orig_user = xstrdup(ftpState->user); + ftpLoginParser(auth, ftpState, FTP_LOGIN_NOT_ESCAPED); + if (strcmp(orig_user, ftpState->user) == 0) { - xfree(orig_user); - return 1; /* same username */ + xfree(orig_user); + return 1; /* same username */ } + xstrncpy(ftpState->user, orig_user, sizeof(ftpState->user)); xfree(orig_user); return 0; /* different username */ @@ -997,29 +1242,33 @@ ftpCheckUrlpath(FtpStateData * ftpState) request_t *request = ftpState->request; int l; const char *t; + if ((t = strRChr(request->urlpath, ';')) != NULL) { - if (strncasecmp(t + 1, "type=", 5) == 0) { - ftpState->typecode = (char) toupper((int) *(t + 6)); - strCutPtr(request->urlpath, t); - } + if (strncasecmp(t + 1, "type=", 5) == 0) { + ftpState->typecode = (char) toupper((int) *(t + 6)); + strCutPtr(request->urlpath, t); + } } + l = request->urlpath.size(); ftpState->flags.need_base_href = 1; /* check for null path */ + if (!l) { - ftpState->flags.isdir = 1; - ftpState->flags.root_dir = 1; + ftpState->flags.isdir = 1; + ftpState->flags.root_dir = 1; } else if (!strCmp(request->urlpath, "/%2f/")) { - /* UNIX root directory */ - ftpState->flags.need_base_href = 0; - ftpState->flags.isdir = 1; - ftpState->flags.root_dir = 1; + /* UNIX root directory */ + ftpState->flags.need_base_href = 0; + ftpState->flags.isdir = 1; + ftpState->flags.root_dir = 1; } else if ((l >= 1) && (*(request->urlpath.buf() + l - 1) == '/')) { - /* Directory URL, ending in / */ - ftpState->flags.isdir = 1; - ftpState->flags.need_base_href = 0; - if (l == 1) - ftpState->flags.root_dir = 1; + /* Directory URL, ending in / */ + ftpState->flags.isdir = 1; + ftpState->flags.need_base_href = 0; + + if (l == 1) + ftpState->flags.root_dir = 1; } } @@ -1029,31 +1278,41 @@ ftpBuildTitleUrl(FtpStateData * ftpState) request_t *request = ftpState->request; ftpState->title_url = "ftp://"; + if (strcmp(ftpState->user, "anonymous")) { - ftpState->title_url.append(ftpState->user); - ftpState->title_url.append("@"); + ftpState->title_url.append(ftpState->user); + ftpState->title_url.append("@"); } + ftpState->title_url.append(request->host); + if (request->port != urlDefaultPort(PROTO_FTP)) { - ftpState->title_url.append(":"); - ftpState->title_url.append(xitoa(request->port)); + ftpState->title_url.append(":"); + ftpState->title_url.append(xitoa(request->port)); } + ftpState->title_url.append (request->urlpath); ftpState->base_href = "ftp://"; + if (strcmp(ftpState->user, "anonymous") != 0) { - ftpState->base_href.append(rfc1738_escape_part(ftpState->user)); - if (ftpState->password_url) { - ftpState->base_href.append (":"); - ftpState->base_href.append(rfc1738_escape_part(ftpState->password)); - } - ftpState->base_href.append("@"); + ftpState->base_href.append(rfc1738_escape_part(ftpState->user)); + + if (ftpState->password_url) { + ftpState->base_href.append (":"); + ftpState->base_href.append(rfc1738_escape_part(ftpState->password)); + } + + ftpState->base_href.append("@"); } + ftpState->base_href.append(request->host); + if (request->port != urlDefaultPort(PROTO_FTP)) { - ftpState->base_href.append(":"); - ftpState->base_href.append(xitoa(request->port)); + ftpState->base_href.append(":"); + ftpState->base_href.append(xitoa(request->port)); } + ftpState->base_href.append(request->urlpath); ftpState->base_href.append("/"); } @@ -1082,40 +1341,55 @@ ftpStart(FwdState * fwd) ftpState->data.fd = -1; ftpState->size = -1; ftpState->mdtm = -1; + if (!Config.Ftp.passive) - ftpState->flags.rest_supported = 0; + ftpState->flags.rest_supported = 0; else if (fwd->flags.ftp_pasv_failed) - ftpState->flags.pasv_supported = 0; + ftpState->flags.pasv_supported = 0; else - ftpState->flags.pasv_supported = 1; + ftpState->flags.pasv_supported = 1; + ftpState->flags.rest_supported = 1; + ftpState->fwd = fwd; + comm_add_close_handler(fd, ftpStateFree, ftpState); + if (ftpState->request->method == METHOD_PUT) - ftpState->flags.put = 1; + ftpState->flags.put = 1; + if (!ftpCheckAuth(ftpState, &request->header)) { - /* This request is not fully authenticated */ - if (request->port == 21) { - snprintf(realm, 8192, "ftp %s", ftpState->user); - } else { - snprintf(realm, 8192, "ftp %s port %d", - ftpState->user, request->port); - } - /* create reply */ - reply = httpReplyCreate (); - assert(reply != NULL); - /* create appropriate reply */ - ftpAuthRequired(reply, request, realm); - httpReplySwapOut(reply, entry); - fwdComplete(ftpState->fwd); - comm_close(fd); - return; + /* This request is not fully authenticated */ + + if (request->port == 21) { + snprintf(realm, 8192, "ftp %s", ftpState->user); + } else { + snprintf(realm, 8192, "ftp %s port %d", + ftpState->user, request->port); + } + + /* create reply */ + reply = httpReplyCreate (); + + assert(reply != NULL); + + /* create appropriate reply */ + ftpAuthRequired(reply, request, realm); + + httpReplySwapOut(reply, entry); + + fwdComplete(ftpState->fwd); + + comm_close(fd); + + return; } + ftpCheckUrlpath(ftpState); ftpBuildTitleUrl(ftpState); debug(9, 5) ("ftpStart: host=%s, path=%s, user=%s, passwd=%s\n", - ftpState->request->host, ftpState->request->urlpath.buf(), - ftpState->user, ftpState->password); + ftpState->request->host, ftpState->request->urlpath.buf(), + ftpState->user, ftpState->password); ftpState->state = BEGIN; ftpState->ctrl.last_command = xstrdup("Connect to server"); ftpState->ctrl.buf = (char *)memAllocBuf(4096, &ftpState->ctrl.size); @@ -1134,11 +1408,11 @@ ftpWriteCommand(const char *buf, FtpStateData * ftpState) safe_free(ftpState->ctrl.last_reply); ftpState->ctrl.last_command = xstrdup(buf); comm_old_write(ftpState->ctrl.fd, - xstrdup(buf), - strlen(buf), - ftpWriteCommandCallback, - ftpState, - xfree); + xstrdup(buf), + strlen(buf), + ftpWriteCommandCallback, + ftpState, + xfree); ftpScheduleReadControlReply(ftpState, 0); } @@ -1147,18 +1421,21 @@ ftpWriteCommandCallback(int fd, char *bufnotused, size_t size, comm_err_t errfla { FtpStateData *ftpState = (FtpStateData *)data; debug(9, 7) ("ftpWriteCommandCallback: wrote %d bytes\n", (int) size); + if (size > 0) { - fd_bytes(fd, size, FD_WRITE); - kb_incr(&statCounter.server.all.kbytes_out, size); - kb_incr(&statCounter.server.ftp.kbytes_out, size); + fd_bytes(fd, size, FD_WRITE); + kb_incr(&statCounter.server.all.kbytes_out, size); + kb_incr(&statCounter.server.ftp.kbytes_out, size); } + if (errflag == COMM_ERR_CLOSING) - return; + return; + if (errflag) { - debug(9, 1) ("ftpWriteCommandCallback: FD %d: %s\n", fd, xstrerror()); - ftpFailed(ftpState, ERR_WRITE_ERROR); - /* ftpFailed closes ctrl.fd and frees ftpState */ - return; + debug(9, 1) ("ftpWriteCommandCallback: FD %d: %s\n", fd, xstrerror()); + ftpFailed(ftpState, ERR_WRITE_ERROR); + /* ftpFailed closes ctrl.fd and frees ftpState */ + return; } } @@ -1183,47 +1460,70 @@ ftpParseControlReply(char *buf, size_t len, int *codep, int *used) sbuf = (char *)xmalloc(len + 1); xstrncpy(sbuf, buf, len + 1); end = sbuf + len - 1; + while (*end != '\r' && *end != '\n' && end > sbuf) - end--; + end--; + usable = end - sbuf; + debug(9, 3) ("ftpParseControlReply: usable = %d\n", usable); + if (usable == 0) { - debug(9, 3) ("ftpParseControlReply: didn't find end of line\n"); - safe_free(sbuf); - return NULL; + debug(9, 3) ("ftpParseControlReply: didn't find end of line\n"); + safe_free(sbuf); + return NULL; } + debug(9, 3) ("ftpParseControlReply: %d bytes to play with\n", (int) len); end++; s = sbuf; s += strspn(s, crlf); + for (; s < end; s += strcspn(s, crlf), s += strspn(s, crlf)) { - if (complete) - break; - debug(9, 3) ("ftpParseControlReply: s = {%s}\n", s); - linelen = strcspn(s, crlf) + 1; - if (linelen < 2) - break; - if (linelen > 3) - complete = (*s >= '0' && *s <= '9' && *(s + 3) == ' '); - if (complete) - code = atoi(s); - offset = 0; - if (linelen > 3) - if (*s >= '0' && *s <= '9' && (*(s + 3) == '-' || *(s + 3) == ' ')) - offset = 4; - list = (wordlist *)memAllocate(MEM_WORDLIST); - list->key = (char *)xmalloc(linelen - offset); - xstrncpy(list->key, s + offset, linelen - offset); - debug(9, 7) ("%d %s\n", code, list->key); - *tail = list; - tail = &list->next; + if (complete) + break; + + debug(9, 3) ("ftpParseControlReply: s = {%s}\n", s); + + linelen = strcspn(s, crlf) + 1; + + if (linelen < 2) + break; + + if (linelen > 3) + complete = (*s >= '0' && *s <= '9' && *(s + 3) == ' '); + + if (complete) + code = atoi(s); + + offset = 0; + + if (linelen > 3) + if (*s >= '0' && *s <= '9' && (*(s + 3) == '-' || *(s + 3) == ' ')) + offset = 4; + + list = (wordlist *)memAllocate(MEM_WORDLIST); + + list->key = (char *)xmalloc(linelen - offset); + + xstrncpy(list->key, s + offset, linelen - offset); + + debug(9, 7) ("%d %s\n", code, list->key); + + *tail = list; + + tail = &list->next; } + *used = (int) (s - sbuf); safe_free(sbuf); + if (!complete) - wordlistDestroy(&head); + wordlistDestroy(&head); + if (codep) - *codep = code; + *codep = code; + return head; } @@ -1231,20 +1531,23 @@ static void ftpScheduleReadControlReply(FtpStateData * ftpState, int buffered_ok) { debug(9, 3) ("ftpScheduleReadControlReply: FD %d\n", ftpState->ctrl.fd); + if (buffered_ok && ftpState->ctrl.offset > 0) { - /* We've already read some reply data */ - ftpHandleControlReply(ftpState); + /* We've already read some reply data */ + ftpHandleControlReply(ftpState); } else { - /* XXX What about Config.Timeout.read? */ - comm_read(ftpState->ctrl.fd, ftpState->ctrl.buf + ftpState->ctrl.offset, ftpState->ctrl.size - ftpState->ctrl.offset, ftpReadControlReply, ftpState); - /* - * Cancel the timeout on the Data socket (if any) and - * establish one on the control socket. - */ - if (ftpState->data.fd > -1) - commSetTimeout(ftpState->data.fd, -1, NULL, NULL); - commSetTimeout(ftpState->ctrl.fd, Config.Timeout.read, ftpTimeout, - ftpState); + /* XXX What about Config.Timeout.read? */ + comm_read(ftpState->ctrl.fd, ftpState->ctrl.buf + ftpState->ctrl.offset, ftpState->ctrl.size - ftpState->ctrl.offset, ftpReadControlReply, ftpState); + /* + * Cancel the timeout on the Data socket (if any) and + * establish one on the control socket. + */ + + if (ftpState->data.fd > -1) + commSetTimeout(ftpState->data.fd, -1, NULL, NULL); + + commSetTimeout(ftpState->ctrl.fd, Config.Timeout.read, ftpTimeout, + ftpState); } } @@ -1256,42 +1559,52 @@ ftpReadControlReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, debug(9, 5) ("ftpReadControlReply\n"); /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us -*/ + */ + if (flag == COMM_ERR_CLOSING) { return; } - + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - comm_close(ftpState->ctrl.fd); - return; + comm_close(ftpState->ctrl.fd); + return; } + assert(ftpState->ctrl.offset < (off_t)ftpState->ctrl.size); + if (flag == COMM_OK && len > 0) { - fd_bytes(fd, len, FD_READ); - kb_incr(&statCounter.server.all.kbytes_in, len); - kb_incr(&statCounter.server.ftp.kbytes_in, len); + fd_bytes(fd, len, FD_READ); + kb_incr(&statCounter.server.all.kbytes_in, len); + kb_incr(&statCounter.server.ftp.kbytes_in, len); } + debug(9, 5) ("ftpReadControlReply: FD %d, Read %d bytes\n", fd, (int)len); + if (flag != COMM_OK || len < 0) { - debug(50, ignoreErrno(errno) ? 3 : 1) ("ftpReadControlReply: read error: %s\n", xstrerror()); - if (ignoreErrno(errno)) { - ftpScheduleReadControlReply(ftpState, 0); - } else { - ftpFailed(ftpState, ERR_READ_ERROR); - /* ftpFailed closes ctrl.fd and frees ftpState */ - return; - } - return; + debug(50, ignoreErrno(errno) ? 3 : 1) ("ftpReadControlReply: read error: %s\n", xstrerror()); + + if (ignoreErrno(errno)) { + ftpScheduleReadControlReply(ftpState, 0); + } else { + ftpFailed(ftpState, ERR_READ_ERROR); + /* ftpFailed closes ctrl.fd and frees ftpState */ + return; + } + + return; } + if (len == 0) { - if (entry->store_status == STORE_PENDING) { - ftpFailed(ftpState, ERR_FTP_FAILURE); - /* ftpFailed closes ctrl.fd and frees ftpState */ - return; - } - comm_close(ftpState->ctrl.fd); - return; + if (entry->store_status == STORE_PENDING) { + ftpFailed(ftpState, ERR_FTP_FAILURE); + /* ftpFailed closes ctrl.fd and frees ftpState */ + return; + } + + comm_close(ftpState->ctrl.fd); + return; } + len += ftpState->ctrl.offset; ftpState->ctrl.offset = len; assert(len <= ftpState->ctrl.size); @@ -1305,35 +1618,46 @@ ftpHandleControlReply(FtpStateData * ftpState) int bytes_used = 0; wordlistDestroy(&ftpState->ctrl.message); ftpState->ctrl.message = ftpParseControlReply(ftpState->ctrl.buf, - ftpState->ctrl.offset, &ftpState->ctrl.replycode, &bytes_used); + ftpState->ctrl.offset, &ftpState->ctrl.replycode, &bytes_used); + if (ftpState->ctrl.message == NULL) { - /* didn't get complete reply yet */ - if (ftpState->ctrl.offset == (off_t)ftpState->ctrl.size) { - ftpState->ctrl.buf = (char *)memReallocBuf(ftpState->ctrl.buf, ftpState->ctrl.size << 1, &ftpState->ctrl.size); - } - ftpScheduleReadControlReply(ftpState, 0); - return; + /* didn't get complete reply yet */ + + if (ftpState->ctrl.offset == (off_t)ftpState->ctrl.size) { + ftpState->ctrl.buf = (char *)memReallocBuf(ftpState->ctrl.buf, ftpState->ctrl.size << 1, &ftpState->ctrl.size); + } + + ftpScheduleReadControlReply(ftpState, 0); + return; } else if (ftpState->ctrl.offset == bytes_used) { - /* used it all up */ - ftpState->ctrl.offset = 0; + /* used it all up */ + ftpState->ctrl.offset = 0; } else { - /* Got some data past the complete reply */ - assert(bytes_used < ftpState->ctrl.offset); - ftpState->ctrl.offset -= bytes_used; - xmemmove(ftpState->ctrl.buf, ftpState->ctrl.buf + bytes_used, - ftpState->ctrl.offset); + /* Got some data past the complete reply */ + assert(bytes_used < ftpState->ctrl.offset); + ftpState->ctrl.offset -= bytes_used; + xmemmove(ftpState->ctrl.buf, ftpState->ctrl.buf + bytes_used, + ftpState->ctrl.offset); } + /* Move the last line of the reply message to ctrl.last_reply */ - for (W = &ftpState->ctrl.message; (*W)->next; W = &(*W)->next); + for (W = &ftpState->ctrl.message; (*W)->next; W = &(*W)->next) + + ; safe_free(ftpState->ctrl.last_reply); + ftpState->ctrl.last_reply = xstrdup((*W)->key); + wordlistDestroy(W); + /* Copy the rest of the message to cwd_message to be printed in * error messages */ wordlistAddWl(&ftpState->cwd_message, ftpState->ctrl.message); + debug(9, 8) ("ftpHandleControlReply: state=%d, code=%d\n", ftpState->state, - ftpState->ctrl.replycode); + ftpState->ctrl.replycode); + FTP_SM_FUNCS[ftpState->state] (ftpState); } @@ -1344,23 +1668,28 @@ ftpReadWelcome(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("ftpReadWelcome\n"); + if (ftpState->flags.pasv_only) - ftpState->login_att++; + ftpState->login_att++; + /* Dont retry if the FTP server accepted the connection */ ftpState->fwd->flags.dont_retry = 1; + if (code == 220) { - if (ftpState->ctrl.message) { - if (strstr(ftpState->ctrl.message->key, "NetWare")) - ftpState->flags.skip_whitespace = 1; - } - ftpSendUser(ftpState); + if (ftpState->ctrl.message) { + if (strstr(ftpState->ctrl.message->key, "NetWare")) + ftpState->flags.skip_whitespace = 1; + } + + ftpSendUser(ftpState); } else if (code == 120) { - if (NULL != ftpState->ctrl.message) - debug(9, 3) ("FTP server is busy: %s\n", - ftpState->ctrl.message->key); - return; + if (NULL != ftpState->ctrl.message) + debug(9, 3) ("FTP server is busy: %s\n", + ftpState->ctrl.message->key); + + return; } else { - ftpFail(ftpState); + ftpFail(ftpState); } } @@ -1368,12 +1697,14 @@ static void ftpSendUser(FtpStateData * ftpState) { if (ftpState->proxy_host != NULL) - snprintf(cbuf, 1024, "USER %s@%s\r\n", - ftpState->user, - ftpState->request->host); + snprintf(cbuf, 1024, "USER %s@%s\r\n", + ftpState->user, + ftpState->request->host); else - snprintf(cbuf, 1024, "USER %s\r\n", ftpState->user); + snprintf(cbuf, 1024, "USER %s\r\n", ftpState->user); + ftpWriteCommand(cbuf, ftpState); + ftpState->state = SENT_USER; } @@ -1382,12 +1713,13 @@ ftpReadUser(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("ftpReadUser\n"); + if (code == 230) { - ftpReadPass(ftpState); + ftpReadPass(ftpState); } else if (code == 331) { - ftpSendPass(ftpState); + ftpSendPass(ftpState); } else { - ftpFail(ftpState); + ftpFail(ftpState); } } @@ -1404,10 +1736,11 @@ ftpReadPass(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("ftpReadPass\n"); + if (code == 230) { - ftpSendType(ftpState); + ftpSendType(ftpState); } else { - ftpFail(ftpState); + ftpFail(ftpState); } } @@ -1421,29 +1754,40 @@ ftpSendType(FtpStateData * ftpState) * Ref section 3.2.2 of RFC 1738 */ mode = ftpState->typecode; + switch (mode) { + case 'D': - mode = 'A'; - break; + mode = 'A'; + break; + case 'A': + case 'I': - break; + break; + default: - if (ftpState->flags.isdir) { - mode = 'A'; - } else { - t = strRChr(ftpState->request->urlpath, '/'); - filename = t ? t + 1 : ftpState->request->urlpath.buf(); - mode = mimeGetTransferMode(filename); - } - break; + + if (ftpState->flags.isdir) { + mode = 'A'; + } else { + t = strRChr(ftpState->request->urlpath, '/'); + filename = t ? t + 1 : ftpState->request->urlpath.buf(); + mode = mimeGetTransferMode(filename); + } + + break; } + if (mode == 'I') - ftpState->flags.binary = 1; + ftpState->flags.binary = 1; else - ftpState->flags.binary = 0; + ftpState->flags.binary = 0; + snprintf(cbuf, 1024, "TYPE %c\r\n", mode); + ftpWriteCommand(cbuf, ftpState); + ftpState->state = SENT_TYPE; } @@ -1454,25 +1798,33 @@ ftpReadType(FtpStateData * ftpState) char *path; char *d, *p; debug(9, 3) ("This is ftpReadType\n"); + if (code == 200) { - p = path = xstrdup(ftpState->request->urlpath.buf()); - if (*p == '/') - p++; - while (*p) { - d = p; - p += strcspn(p, "/"); - if (*p) - *p++ = '\0'; - rfc1738_unescape(d); - wordlistAdd(&ftpState->pathcomps, d); - } - xfree(path); - if (ftpState->pathcomps) - ftpTraverseDirectory(ftpState); - else - ftpListDir(ftpState); + p = path = xstrdup(ftpState->request->urlpath.buf()); + + if (*p == '/') + p++; + + while (*p) { + d = p; + p += strcspn(p, "/"); + + if (*p) + *p++ = '\0'; + + rfc1738_unescape(d); + + wordlistAdd(&ftpState->pathcomps, d); + } + + xfree(path); + + if (ftpState->pathcomps) + ftpTraverseDirectory(ftpState); + else + ftpListDir(ftpState); } else { - ftpFail(ftpState); + ftpFail(ftpState); } } @@ -1481,27 +1833,33 @@ ftpTraverseDirectory(FtpStateData * ftpState) { wordlist *w; debug(9, 4) ("ftpTraverseDirectory %s\n", - ftpState->filepath ? ftpState->filepath : ""); + ftpState->filepath ? ftpState->filepath : ""); safe_free(ftpState->filepath); /* Done? */ + if (ftpState->pathcomps == NULL) { - debug(9, 3) ("the final component was a directory\n"); - ftpListDir(ftpState); - return; + debug(9, 3) ("the final component was a directory\n"); + ftpListDir(ftpState); + return; } + /* Go to next path component */ w = ftpState->pathcomps; + ftpState->filepath = w->key; + ftpState->pathcomps = w->next; + memFree(w, MEM_WORDLIST); + /* Check if we are to CWD or RETR */ if (ftpState->pathcomps != NULL || ftpState->flags.isdir) { - ftpSendCwd(ftpState); + ftpSendCwd(ftpState); } else { - debug(9, 3) ("final component is probably a file\n"); - ftpGetFile(ftpState); - return; + debug(9, 3) ("final component is probably a file\n"); + ftpGetFile(ftpState); + return; } } @@ -1510,16 +1868,20 @@ ftpSendCwd(FtpStateData * ftpState) { char *path = ftpState->filepath; debug(9, 3) ("ftpSendCwd\n"); + if (!strcmp(path, "..") || !strcmp(path, "/")) { - ftpState->flags.no_dotdot = 1; + ftpState->flags.no_dotdot = 1; } else { - ftpState->flags.no_dotdot = 0; + ftpState->flags.no_dotdot = 0; } + if (*path) - snprintf(cbuf, 1024, "CWD %s\r\n", path); + snprintf(cbuf, 1024, "CWD %s\r\n", path); else - snprintf(cbuf, 1024, "CWD\r\n"); + snprintf(cbuf, 1024, "CWD\r\n"); + ftpWriteCommand(cbuf, ftpState); + ftpState->state = SENT_CWD; } @@ -1528,22 +1890,28 @@ ftpReadCwd(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadCwd\n"); + if (code >= 200 && code < 300) { - /* CWD OK */ - ftpUnhack(ftpState); - /* Reset cwd_message to only include the last message */ - if (ftpState->cwd_message) - wordlistDestroy(&ftpState->cwd_message); - ftpState->cwd_message = ftpState->ctrl.message; - ftpState->ctrl.message = NULL; - /* Continue to traverse the path */ - ftpTraverseDirectory(ftpState); + /* CWD OK */ + ftpUnhack(ftpState); + /* Reset cwd_message to only include the last message */ + + if (ftpState->cwd_message) + wordlistDestroy(&ftpState->cwd_message); + + ftpState->cwd_message = ftpState->ctrl.message; + + ftpState->ctrl.message = NULL; + + /* Continue to traverse the path */ + ftpTraverseDirectory(ftpState); } else { - /* CWD FAILED */ - if (!ftpState->flags.put) - ftpFail(ftpState); - else - ftpSendMkdir(ftpState); + /* CWD FAILED */ + + if (!ftpState->flags.put) + ftpFail(ftpState); + else + ftpSendMkdir(ftpState); } } @@ -1564,16 +1932,18 @@ ftpReadMkdir(FtpStateData * ftpState) int code = ftpState->ctrl.replycode; debug(9, 3) ("ftpReadMkdir: path %s, code %d\n", path, code); + if (code == 257) { /* success */ - ftpSendCwd(ftpState); + ftpSendCwd(ftpState); } else if (code == 550) { /* dir exists */ - if (ftpState->flags.put_mkdir) { - ftpState->flags.put_mkdir = 1; - ftpSendCwd(ftpState); - } else - ftpSendReply(ftpState); + + if (ftpState->flags.put_mkdir) { + ftpState->flags.put_mkdir = 1; + ftpSendCwd(ftpState); + } else + ftpSendReply(ftpState); } else - ftpSendReply(ftpState); + ftpSendReply(ftpState); } static void @@ -1588,11 +1958,12 @@ static void ftpListDir(FtpStateData * ftpState) { if (!ftpState->flags.isdir) { - debug(9, 3) ("Directory path did not end in /\n"); - ftpState->title_url.append("/"); - ftpState->flags.isdir = 1; - ftpState->flags.need_base_href = 1; + debug(9, 3) ("Directory path did not end in /\n"); + ftpState->title_url.append("/"); + ftpState->flags.isdir = 1; + ftpState->flags.need_base_href = 1; } + ftpSendPasv(ftpState); } @@ -1610,12 +1981,14 @@ ftpReadMdtm(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadMdtm\n"); + if (code == 213) { - ftpState->mdtm = parse_iso3307_time(ftpState->ctrl.last_reply); - ftpUnhack(ftpState); + ftpState->mdtm = parse_iso3307_time(ftpState->ctrl.last_reply); + ftpUnhack(ftpState); } else if (code < 0) { - ftpFail(ftpState); + ftpFail(ftpState); } + ftpSendSize(ftpState); } @@ -1624,15 +1997,16 @@ ftpSendSize(FtpStateData * ftpState) { /* Only send SIZE for binary transfers. The returned size * is useless on ASCII transfers */ + if (ftpState->flags.binary) { - assert(ftpState->filepath != NULL); - assert(*ftpState->filepath != '\0'); - snprintf(cbuf, 1024, "SIZE %s\r\n", ftpState->filepath); - ftpWriteCommand(cbuf, ftpState); - ftpState->state = SENT_SIZE; + assert(ftpState->filepath != NULL); + assert(*ftpState->filepath != '\0'); + snprintf(cbuf, 1024, "SIZE %s\r\n", ftpState->filepath); + ftpWriteCommand(cbuf, ftpState); + ftpState->state = SENT_SIZE; } else - /* Skip to next state no non-binary transfers */ - ftpSendPasv(ftpState); + /* Skip to next state no non-binary transfers */ + ftpSendPasv(ftpState); } static void @@ -1640,18 +2014,21 @@ ftpReadSize(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadSize\n"); + if (code == 213) { - ftpUnhack(ftpState); - ftpState->size = atoi(ftpState->ctrl.last_reply); - if (ftpState->size == 0) { - debug(9, 2) ("ftpReadSize: SIZE reported %s on %s\n", - ftpState->ctrl.last_reply, - ftpState->title_url.buf()); - ftpState->size = -1; - } + ftpUnhack(ftpState); + ftpState->size = atoi(ftpState->ctrl.last_reply); + + if (ftpState->size == 0) { + debug(9, 2) ("ftpReadSize: SIZE reported %s on %s\n", + ftpState->ctrl.last_reply, + ftpState->title_url.buf()); + ftpState->size = -1; + } } else if (code < 0) { - ftpFail(ftpState); + ftpFail(ftpState); } + ftpSendPasv(ftpState); } @@ -1659,56 +2036,69 @@ static void ftpSendPasv(FtpStateData * ftpState) { int fd; + struct sockaddr_in addr; socklen_t addr_len; + if (ftpState->request->method == METHOD_HEAD) { - /* Terminate here for HEAD requests */ - ftpAppendSuccessHeader(ftpState); - storeTimestampsSet(ftpState->entry); - /* - * On rare occasions I'm seeing the entry get aborted after - * ftpReadControlReply() and before here, probably when - * trying to write to the client. - */ - if (!EBIT_TEST(ftpState->entry->flags, ENTRY_ABORTED)) - fwdComplete(ftpState->fwd); - ftpSendQuit(ftpState); - return; + /* Terminate here for HEAD requests */ + ftpAppendSuccessHeader(ftpState); + storeTimestampsSet(ftpState->entry); + /* + * On rare occasions I'm seeing the entry get aborted after + * ftpReadControlReply() and before here, probably when + * trying to write to the client. + */ + + if (!EBIT_TEST(ftpState->entry->flags, ENTRY_ABORTED)) + fwdComplete(ftpState->fwd); + + ftpSendQuit(ftpState); + + return; } + if (ftpState->data.fd >= 0) { - if (!ftpState->flags.datachannel_hack) { - /* We are already connected, reuse this connection. */ - ftpRestOrList(ftpState); - return; - } else { - /* Close old connection */ - comm_close(ftpState->data.fd); - ftpState->data.fd = -1; - } + if (!ftpState->flags.datachannel_hack) { + /* We are already connected, reuse this connection. */ + ftpRestOrList(ftpState); + return; + } else { + /* Close old connection */ + comm_close(ftpState->data.fd); + ftpState->data.fd = -1; + } } + if (!ftpState->flags.pasv_supported) { - ftpSendPort(ftpState); - return; + ftpSendPort(ftpState); + return; } + addr_len = sizeof(addr); + if (getsockname(ftpState->ctrl.fd, (struct sockaddr *) &addr, &addr_len)) { - debug(9, 0) ("ftpSendPasv: getsockname(%d,..): %s\n", - ftpState->ctrl.fd, xstrerror()); - ftpFail(ftpState); - return; + debug(9, 0) ("ftpSendPasv: getsockname(%d,..): %s\n", + ftpState->ctrl.fd, xstrerror()); + ftpFail(ftpState); + return; } + /* Open data channel with the same local address as control channel */ fd = comm_open(SOCK_STREAM, - 0, - addr.sin_addr, - 0, - COMM_NONBLOCKING, - storeUrl(ftpState->entry)); + 0, + addr.sin_addr, + 0, + COMM_NONBLOCKING, + storeUrl(ftpState->entry)); + debug(9, 3) ("ftpSendPasv: Unconnected data socket created on FD %d\n", fd); + if (fd < 0) { - ftpFail(ftpState); - return; + ftpFail(ftpState); + return; } + /* * No comm_add_close_handler() here. If we have both ctrl and * data FD's call ftpStateFree() upon close, then we have @@ -1720,9 +2110,13 @@ ftpSendPasv(FtpStateData * ftpState) * managed correctly and comm close handlers are cbdata fenced */ ftpState->data.fd = fd; + snprintf(cbuf, 1024, "PASV\r\n"); + ftpWriteCommand(cbuf, ftpState); + ftpState->state = SENT_PASV; + /* * ugly hack for ftp servers like ftp.netscape.com that sometimes * dont acknowledge PORT commands. @@ -1742,51 +2136,64 @@ ftpReadPasv(FtpStateData * ftpState) char *buf; LOCAL_ARRAY(char, ipaddr, 1024); debug(9, 3) ("This is ftpReadPasv\n"); + if (code != 227) { - debug(9, 3) ("PASV not supported by remote end\n"); - ftpSendPort(ftpState); - return; + debug(9, 3) ("PASV not supported by remote end\n"); + ftpSendPort(ftpState); + return; } + /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */ /* ANSI sez [^0-9] is undefined, it breaks on Watcom cc */ debug(9, 5) ("scanning: %s\n", ftpState->ctrl.last_reply); + buf = strstr(ftpState->ctrl.last_reply, "("); + if (!buf) { - debug(9, 1) ("Unsafe PASV reply from %s: '%s'\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); - ftpSendPort(ftpState); - return; + debug(9, 1) ("Unsafe PASV reply from %s: '%s'\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); + ftpSendPort(ftpState); + return; } + buf++; /* skip ( */ n = sscanf(buf, "%d,%d,%d,%d,%d,%d", &h1, &h2, &h3, &h4, &p1, &p2); + if (n != 6 || p1 < 0 || p2 < 0 || p1 > 255 || p2 > 255) { - debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); - ftpSendPort(ftpState); - return; + debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); + ftpSendPort(ftpState); + return; } + snprintf(ipaddr, 1024, "%d.%d.%d.%d", h1, h2, h3, h4); + if (!safe_inet_addr(ipaddr, NULL)) { - debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); - ftpSendPort(ftpState); - return; + debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); + ftpSendPort(ftpState); + return; } + port = ((p1 << 8) + p2); + if (0 == port) { - debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); - ftpSendPort(ftpState); - return; + debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); + ftpSendPort(ftpState); + return; } + if (Config.Ftp.sanitycheck) { - if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, ipaddr) != 0) { - debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); - ftpSendPort(ftpState); - return; - } - if (port < 1024) { - debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); - ftpSendPort(ftpState); - return; - } + if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, ipaddr) != 0) { + debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); + ftpSendPort(ftpState); + return; + } + + if (port < 1024) { + debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); + ftpSendPort(ftpState); + return; + } } + debug(9, 5) ("ftpReadPasv: connecting to %s, port %d\n", ipaddr, port); ftpState->data.port = port; ftpState->data.host = xstrdup(ipaddr); @@ -1801,14 +2208,16 @@ ftpPasvCallback(int fd, comm_err_t status, void *data) { FtpStateData *ftpState = (FtpStateData *)data; debug(9, 3) ("ftpPasvCallback\n"); + if (status != COMM_OK) { - debug(9, 2) ("ftpPasvCallback: failed to connect. Retrying without PASV.\n"); - ftpState->fwd->flags.dont_retry = 0; /* this is a retryable error */ - ftpState->fwd->flags.ftp_pasv_failed = 1; - ftpFailed(ftpState, ERR_NONE); - /* ftpFailed closes ctrl.fd and frees ftpState */ - return; + debug(9, 2) ("ftpPasvCallback: failed to connect. Retrying without PASV.\n"); + ftpState->fwd->flags.dont_retry = 0; /* this is a retryable error */ + ftpState->fwd->flags.ftp_pasv_failed = 1; + ftpFailed(ftpState, ERR_NONE); + /* ftpFailed closes ctrl.fd and frees ftpState */ + return; } + ftpRestOrList(ftpState); } @@ -1816,6 +2225,7 @@ static int ftpOpenListenSocket(FtpStateData * ftpState, int fallback) { int fd; + struct sockaddr_in addr; socklen_t addr_len; int on = 1; @@ -1824,43 +2234,51 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback) * Tear down any old data connection if any. We are about to * establish a new one. */ + if (ftpState->data.fd > 0) { - comm_close(ftpState->data.fd); - ftpState->data.fd = -1; + comm_close(ftpState->data.fd); + ftpState->data.fd = -1; } + /* * Set up a listen socket on the same local address as the * control connection. */ addr_len = sizeof(addr); + if (getsockname(ftpState->ctrl.fd, (struct sockaddr *) &addr, &addr_len)) { - debug(9, 0) ("ftpOpenListenSocket: getsockname(%d,..): %s\n", - ftpState->ctrl.fd, xstrerror()); - return -1; + debug(9, 0) ("ftpOpenListenSocket: getsockname(%d,..): %s\n", + ftpState->ctrl.fd, xstrerror()); + return -1; } + /* * REUSEADDR is needed in fallback mode, since the same port is * used for both control and data. */ if (fallback) { - setsockopt(ftpState->ctrl.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); - port = ntohs(addr.sin_port); + setsockopt(ftpState->ctrl.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); + port = ntohs(addr.sin_port); } + fd = comm_open(SOCK_STREAM, - 0, - addr.sin_addr, - port, - COMM_NONBLOCKING | (fallback ? COMM_REUSEADDR : 0), - storeUrl(ftpState->entry)); + 0, + addr.sin_addr, + port, + COMM_NONBLOCKING | (fallback ? COMM_REUSEADDR : 0), + storeUrl(ftpState->entry)); debug(9, 3) ("ftpOpenListenSocket: Unconnected data socket created on FD %d\n", fd); + if (fd < 0) { - debug(9, 0) ("ftpOpenListenSocket: comm_open failed\n"); - return -1; + debug(9, 0) ("ftpOpenListenSocket: comm_open failed\n"); + return -1; } + if (comm_listen(fd) < 0) { - comm_close(fd); - return -1; + comm_close(fd); + return -1; } + ftpState->data.fd = fd; ftpState->data.port = comm_local_port(fd); ftpState->data.host = NULL; @@ -1871,6 +2289,7 @@ static void ftpSendPort(FtpStateData * ftpState) { int fd; + struct sockaddr_in addr; socklen_t addr_len; unsigned char *addrptr; @@ -1879,17 +2298,19 @@ ftpSendPort(FtpStateData * ftpState) ftpState->flags.pasv_supported = 0; fd = ftpOpenListenSocket(ftpState, 0); addr_len = sizeof(addr); + if (getsockname(fd, (struct sockaddr *) &addr, &addr_len)) { - debug(9, 0) ("ftpSendPort: getsockname(%d,..): %s\n", fd, xstrerror()); - /* XXX Need to set error message */ - ftpFail(ftpState); - return; + debug(9, 0) ("ftpSendPort: getsockname(%d,..): %s\n", fd, xstrerror()); + /* XXX Need to set error message */ + ftpFail(ftpState); + return; } + addrptr = (unsigned char *) &addr.sin_addr.s_addr; portptr = (unsigned char *) &addr.sin_port; snprintf(cbuf, 1024, "PORT %d,%d,%d,%d,%d,%d\r\n", - addrptr[0], addrptr[1], addrptr[2], addrptr[3], - portptr[0], portptr[1]); + addrptr[0], addrptr[1], addrptr[2], addrptr[3], + portptr[0], portptr[1]); ftpWriteCommand(cbuf, ftpState); ftpState->state = SENT_PORT; } @@ -1899,18 +2320,20 @@ ftpReadPort(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadPort\n"); + if (code != 200) { - /* Fall back on using the same port as the control connection */ - debug(9, 3) ("PORT not supported by remote end\n"); - ftpOpenListenSocket(ftpState, 1); + /* Fall back on using the same port as the control connection */ + debug(9, 3) ("PORT not supported by remote end\n"); + ftpOpenListenSocket(ftpState, 1); } + ftpRestOrList(ftpState); } /* "read" handler to accept data connection */ static void ftpAcceptDataConnection(int fd, int newfd, ConnectionDetail *details, - comm_err_t flag, int xerrno, void *data) + comm_err_t flag, int xerrno, void *data) { FtpStateData *ftpState = (FtpStateData *)data; debug(9, 3) ("ftpAcceptDataConnection\n"); @@ -1920,35 +2343,45 @@ ftpAcceptDataConnection(int fd, int newfd, ConnectionDetail *details, } if (EBIT_TEST(ftpState->entry->flags, ENTRY_ABORTED)) { - comm_close(ftpState->ctrl.fd); - return; + comm_close(ftpState->ctrl.fd); + return; } if (Config.Ftp.sanitycheck) { - char *ipaddr = inet_ntoa(details->peer.sin_addr); - if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, ipaddr) != 0) { - debug(9, 1) ("FTP data connection from unexpected server (%s:%d), expecting %s\n", ipaddr, (int) ntohs(details->peer.sin_port), fd_table[ftpState->ctrl.fd].ipaddr); - comm_close(newfd); - comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); - return; - } + char *ipaddr = inet_ntoa(details->peer.sin_addr); + + if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, ipaddr) != 0) { + debug(9, 1) ("FTP data connection from unexpected server (%s:%d), expecting %s\n", ipaddr, (int) ntohs(details->peer.sin_port), fd_table[ftpState->ctrl.fd].ipaddr); + comm_close(newfd); + comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); + return; + } } + if (flag != COMM_OK) { errno = xerrno; - debug(9, 1) ("ftpHandleDataAccept: comm_accept(%d): %s", newfd, xstrerror()); - /* XXX Need to set error message */ - ftpFail(ftpState); - return; + debug(9, 1) ("ftpHandleDataAccept: comm_accept(%d): %s", newfd, xstrerror()); + /* XXX Need to set error message */ + ftpFail(ftpState); + return; } + /* Replace the Listen socket with the accepted data socket */ comm_close(ftpState->data.fd); + debug(9, 3) ("ftpAcceptDataConnection: Connected data socket on FD %d\n", newfd); + ftpState->data.fd = newfd; + ftpState->data.port = ntohs(details->peer.sin_port); + ftpState->data.host = xstrdup(inet_ntoa(details->peer.sin_addr)); + commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); + commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, - ftpState); + ftpState); + /* XXX We should have a flag to track connect state... * host NULL -> not connected, port == local port * host set -> connected, port == remote port @@ -1961,41 +2394,43 @@ static void ftpRestOrList(FtpStateData * ftpState) { debug(9, 3) ("This is ftpRestOrList\n"); + if (ftpState->typecode == 'D') { - ftpState->flags.isdir = 1; - ftpState->flags.need_base_href = 1; - if (ftpState->flags.put) { - ftpSendMkdir(ftpState); /* PUT name;type=d */ - } else { - ftpSendNlst(ftpState); /* GET name;type=d sec 3.2.2 of RFC 1738 */ - } + ftpState->flags.isdir = 1; + ftpState->flags.need_base_href = 1; + + if (ftpState->flags.put) { + ftpSendMkdir(ftpState); /* PUT name;type=d */ + } else { + ftpSendNlst(ftpState); /* GET name;type=d sec 3.2.2 of RFC 1738 */ + } } else if (ftpState->flags.put) { - debug(9, 3) ("ftpRestOrList: Sending STOR request...\n"); - ftpSendStor(ftpState); + debug(9, 3) ("ftpRestOrList: Sending STOR request...\n"); + ftpSendStor(ftpState); } else if (ftpState->flags.isdir) - ftpSendList(ftpState); + ftpSendList(ftpState); else if (ftpRestartable(ftpState)) - ftpSendRest(ftpState); + ftpSendRest(ftpState); else - ftpSendRetr(ftpState); + ftpSendRetr(ftpState); } static void ftpSendStor(FtpStateData * ftpState) { if (ftpState->filepath != NULL) { - /* Plain file upload */ - snprintf(cbuf, 1024, "STOR %s\r\n", ftpState->filepath); - ftpWriteCommand(cbuf, ftpState); - ftpState->state = SENT_STOR; + /* Plain file upload */ + snprintf(cbuf, 1024, "STOR %s\r\n", ftpState->filepath); + ftpWriteCommand(cbuf, ftpState); + ftpState->state = SENT_STOR; } else if (httpHeaderGetInt(&ftpState->request->header, HDR_CONTENT_LENGTH) > 0) { - /* File upload without a filename. use STOU to generate one */ - snprintf(cbuf, 1024, "STOU\r\n"); - ftpWriteCommand(cbuf, ftpState); - ftpState->state = SENT_STOR; + /* File upload without a filename. use STOU to generate one */ + snprintf(cbuf, 1024, "STOU\r\n"); + ftpWriteCommand(cbuf, ftpState); + ftpState->state = SENT_STOR; } else { - /* No file to transfer. Only create directories if needed */ - ftpSendReply(ftpState); + /* No file to transfer. Only create directories if needed */ + ftpSendReply(ftpState); } } @@ -2004,30 +2439,31 @@ ftpReadStor(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadStor\n"); + if (code == 125 || (code == 150 && ftpState->data.host)) { - /* Begin data transfer */ - debug(9, 3) ("ftpReadStor: starting data transfer\n"); - commSetSelect(ftpState->data.fd, - COMM_SELECT_WRITE, - ftpDataWrite, - ftpState, - Config.Timeout.read); - /* - * Cancel the timeout on the Control socket and - * establish one on the data socket. - */ - commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); - commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, - ftpState); - ftpState->state = WRITING_DATA; - debug(9, 3) ("ftpReadStor: writing data channel\n"); + /* Begin data transfer */ + debug(9, 3) ("ftpReadStor: starting data transfer\n"); + commSetSelect(ftpState->data.fd, + COMM_SELECT_WRITE, + ftpDataWrite, + ftpState, + Config.Timeout.read); + /* + * Cancel the timeout on the Control socket and + * establish one on the data socket. + */ + commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); + commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, + ftpState); + ftpState->state = WRITING_DATA; + debug(9, 3) ("ftpReadStor: writing data channel\n"); } else if (code == 150) { - /* Accept data channel */ - debug(9, 3) ("ftpReadStor: accepting data channel\n"); - comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); + /* Accept data channel */ + debug(9, 3) ("ftpReadStor: accepting data channel\n"); + comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); } else { - debug(9, 3) ("ftpReadStor: Unexpected reply code %03d\n", code); - ftpFail(ftpState); + debug(9, 3) ("ftpReadStor: Unexpected reply code %03d\n", code); + ftpFail(ftpState); } } @@ -2043,17 +2479,22 @@ static int ftpRestartable(FtpStateData * ftpState) { if (ftpState->restart_offset > 0) - return 1; + return 1; + if (!ftpState->request->range) - return 0; + return 0; + if (!ftpState->flags.binary) - return 0; + return 0; + if (ftpState->size <= 0) - return 0; + return 0; ftpState->restart_offset = ftpState->request->range->lowestOffset((size_t) ftpState->size); + if (ftpState->restart_offset <= 0) - return 0; + return 0; + return 1; } @@ -2063,15 +2504,16 @@ ftpReadRest(FtpStateData * ftpState) int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadRest\n"); assert(ftpState->restart_offset > 0); + if (code == 350) { - ftpState->restarted_offset = ftpState->restart_offset; - ftpSendRetr(ftpState); + ftpState->restarted_offset = ftpState->restart_offset; + ftpSendRetr(ftpState); } else if (code > 0) { - debug(9, 3) ("ftpReadRest: REST not supported\n"); - ftpState->flags.rest_supported = 0; - ftpSendRetr(ftpState); + debug(9, 3) ("ftpReadRest: REST not supported\n"); + ftpState->flags.rest_supported = 0; + ftpSendRetr(ftpState); } else { - ftpFail(ftpState); + ftpFail(ftpState); } } @@ -2079,11 +2521,12 @@ static void ftpSendList(FtpStateData * ftpState) { if (ftpState->filepath) { - ftpState->flags.need_base_href = 1; - snprintf(cbuf, 1024, "LIST %s\r\n", ftpState->filepath); + ftpState->flags.need_base_href = 1; + snprintf(cbuf, 1024, "LIST %s\r\n", ftpState->filepath); } else { - snprintf(cbuf, 1024, "LIST\r\n"); + snprintf(cbuf, 1024, "LIST\r\n"); } + ftpWriteCommand(cbuf, ftpState); ftpState->state = SENT_LIST; } @@ -2092,12 +2535,14 @@ static void ftpSendNlst(FtpStateData * ftpState) { ftpState->flags.tried_nlst = 1; + if (ftpState->filepath) { - ftpState->flags.need_base_href = 1; - snprintf(cbuf, 1024, "NLST %s\r\n", ftpState->filepath); + ftpState->flags.need_base_href = 1; + snprintf(cbuf, 1024, "NLST %s\r\n", ftpState->filepath); } else { - snprintf(cbuf, 1024, "NLST\r\n"); + snprintf(cbuf, 1024, "NLST\r\n"); } + ftpWriteCommand(cbuf, ftpState); ftpState->state = SENT_NLST; } @@ -2107,36 +2552,37 @@ ftpReadList(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadList\n"); + if (code == 125 || (code == 150 && ftpState->data.host)) { - /* Begin data transfer */ - ftpAppendSuccessHeader(ftpState); - /* XXX what about Config.Timeout.read? */ - assert(ftpState->data.offset == 0); - comm_read(ftpState->data.fd, ftpState->data.buf, ftpState->data.size, ftpDataRead, ftpState); - commSetDefer(ftpState->data.fd, StoreEntry::CheckDeferRead, ftpState->entry); - ftpState->state = READING_DATA; - /* - * Cancel the timeout on the Control socket and establish one - * on the data socket - */ - commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); - commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState); - return; + /* Begin data transfer */ + ftpAppendSuccessHeader(ftpState); + /* XXX what about Config.Timeout.read? */ + assert(ftpState->data.offset == 0); + comm_read(ftpState->data.fd, ftpState->data.buf, ftpState->data.size, ftpDataRead, ftpState); + commSetDefer(ftpState->data.fd, StoreEntry::CheckDeferRead, ftpState->entry); + ftpState->state = READING_DATA; + /* + * Cancel the timeout on the Control socket and establish one + * on the data socket + */ + commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); + commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState); + return; } else if (code == 150) { - /* Accept data channel */ - comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); - /* - * Cancel the timeout on the Control socket and establish one - * on the data socket - */ - commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); - commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState); - return; + /* Accept data channel */ + comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); + /* + * Cancel the timeout on the Control socket and establish one + * on the data socket + */ + commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); + commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState); + return; } else if (!ftpState->flags.tried_nlst && code > 300) { - ftpSendNlst(ftpState); + ftpSendNlst(ftpState); } else { - ftpFail(ftpState); - return; + ftpFail(ftpState); + return; } } @@ -2154,45 +2600,48 @@ ftpReadRetr(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadRetr\n"); + if (code == 125 || (code == 150 && ftpState->data.host)) { - /* Begin data transfer */ - debug(9, 3) ("ftpReadRetr: reading data channel\n"); - ftpAppendSuccessHeader(ftpState); - /* XXX what about Config.Timeout.read? */ - size_t read_sz = ftpState->data.size - ftpState->data.offset; + /* Begin data transfer */ + debug(9, 3) ("ftpReadRetr: reading data channel\n"); + ftpAppendSuccessHeader(ftpState); + /* XXX what about Config.Timeout.read? */ + size_t read_sz = ftpState->data.size - ftpState->data.offset; #if DELAY_POOLS - read_sz = ftpState->entry->mem_obj->mostBytesAllowed().bytesWanted(1, read_sz); + + read_sz = ftpState->entry->mem_obj->mostBytesAllowed().bytesWanted(1, read_sz); #endif - comm_read(ftpState->data.fd, ftpState->data.buf + ftpState->data.offset, - read_sz, ftpDataRead, ftpState); - commSetDefer(ftpState->data.fd, StoreEntry::CheckDeferRead, ftpState->entry); - ftpState->state = READING_DATA; - /* - * Cancel the timeout on the Control socket and establish one - * on the data socket - */ - commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); - commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, - ftpState); + + comm_read(ftpState->data.fd, ftpState->data.buf + ftpState->data.offset, + read_sz, ftpDataRead, ftpState); + commSetDefer(ftpState->data.fd, StoreEntry::CheckDeferRead, ftpState->entry); + ftpState->state = READING_DATA; + /* + * Cancel the timeout on the Control socket and establish one + * on the data socket + */ + commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); + commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, + ftpState); } else if (code == 150) { - /* Accept data channel */ - comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); - /* - * Cancel the timeout on the Control socket and establish one - * on the data socket - */ - commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); - commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, - ftpState); + /* Accept data channel */ + comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); + /* + * Cancel the timeout on the Control socket and establish one + * on the data socket + */ + commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); + commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, + ftpState); } else if (code >= 300) { - if (!ftpState->flags.try_slash_hack) { - /* Try this as a directory missing trailing slash... */ - ftpHackShortcut(ftpState, ftpSendCwd); - } else { - ftpFail(ftpState); - } + if (!ftpState->flags.try_slash_hack) { + /* Try this as a directory missing trailing slash... */ + ftpHackShortcut(ftpState, ftpSendCwd); + } else { + ftpFail(ftpState); + } } else { - ftpFail(ftpState); + ftpFail(ftpState); } } @@ -2201,19 +2650,24 @@ ftpReadTransferDone(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpReadTransferDone\n"); + if (code == 226) { - /* Connection closed; retrieval done. */ - if (ftpState->flags.html_header_sent) - ftpListingFinish(ftpState); - fwdUnregister(ftpState->ctrl.fd, ftpState->fwd); - fwdComplete(ftpState->fwd); - ftpSendQuit(ftpState); + /* Connection closed; retrieval done. */ + + if (ftpState->flags.html_header_sent) + ftpListingFinish(ftpState); + + fwdUnregister(ftpState->ctrl.fd, ftpState->fwd); + + fwdComplete(ftpState->fwd); + + ftpSendQuit(ftpState); } else { /* != 226 */ - debug(9, 1) ("ftpReadTransferDone: Got code %d after reading data\n", - code); - ftpFailed(ftpState, ERR_FTP_FAILURE); - /* ftpFailed closes ctrl.fd and frees ftpState */ - return; + debug(9, 1) ("ftpReadTransferDone: Got code %d after reading data\n", + code); + ftpFailed(ftpState, ERR_FTP_FAILURE); + /* ftpFailed closes ctrl.fd and frees ftpState */ + return; } } @@ -2224,16 +2678,17 @@ ftpRequestBody(char *buf, ssize_t size, void *data) FtpStateData *ftpState = (FtpStateData *) data; debug(9, 3) ("ftpRequestBody: buf=%p size=%d ftpState=%p\n", buf, (int) size, data); ftpState->data.offset = size; + if (size > 0) { - /* DataWrite */ - comm_write(ftpState->data.fd, buf, size, ftpDataWriteCallback, ftpState); + /* DataWrite */ + comm_write(ftpState->data.fd, buf, size, ftpDataWriteCallback, ftpState); } else if (size < 0) { - /* Error */ - debug(9, 1) ("ftpRequestBody: request aborted"); - ftpFailed(ftpState, ERR_READ_ERROR); + /* Error */ + debug(9, 1) ("ftpRequestBody: request aborted"); + ftpFailed(ftpState, ERR_READ_ERROR); } else if (size == 0) { - /* End of transfer */ - ftpDataComplete(ftpState); + /* End of transfer */ + ftpDataComplete(ftpState); } } @@ -2242,12 +2697,13 @@ static void ftpDataWriteCallback(int fd, char *buf, size_t size, comm_err_t err, int xerrno, void *data) { FtpStateData *ftpState = (FtpStateData *) data; + if (!err) { - /* Shedule the rest of the request */ - clientReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); + /* Shedule the rest of the request */ + clientReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); } else { - debug(9, 1) ("ftpDataWriteCallback: write error: %s\n", xstrerror()); - ftpFailed(ftpState, ERR_WRITE_ERROR); + debug(9, 1) ("ftpDataWriteCallback: write error: %s\n", xstrerror()); + ftpFailed(ftpState, ERR_WRITE_ERROR); } } @@ -2265,12 +2721,14 @@ ftpWriteTransferDone(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debug(9, 3) ("This is ftpWriteTransferDone\n"); + if (code != 226) { - debug(9, 1) ("ftpReadTransferDone: Got code %d after sending data\n", - code); - ftpFailed(ftpState, ERR_FTP_PUT_ERROR); - return; + debug(9, 1) ("ftpReadTransferDone: Got code %d after sending data\n", + code); + ftpFailed(ftpState, ERR_FTP_PUT_ERROR); + return; } + storeTimestampsSet(ftpState->entry); /* XXX Is this needed? */ ftpSendReply(ftpState); } @@ -2296,13 +2754,19 @@ ftpTrySlashHack(FtpStateData * ftpState) char *path; ftpState->flags.try_slash_hack = 1; /* Free old paths */ + if (ftpState->pathcomps) - wordlistDestroy(&ftpState->pathcomps); + wordlistDestroy(&ftpState->pathcomps); + safe_free(ftpState->filepath); + /* Build the new path (urlpath begins with /) */ path = xstrdup(ftpState->request->urlpath.buf()); + rfc1738_unescape(path); + ftpState->filepath = path; + /* And off we go */ ftpGetFile(ftpState); } @@ -2312,19 +2776,23 @@ ftpTryDatachannelHack(FtpStateData * ftpState) { ftpState->flags.datachannel_hack = 1; /* we have to undo some of the slash hack... */ + if (ftpState->old_filepath != NULL) { - ftpState->flags.try_slash_hack = 0; - safe_free(ftpState->filepath); - ftpState->filepath = ftpState->old_filepath; - ftpState->old_filepath = NULL; + ftpState->flags.try_slash_hack = 0; + safe_free(ftpState->filepath); + ftpState->filepath = ftpState->old_filepath; + ftpState->old_filepath = NULL; } + ftpState->flags.tried_nlst = 0; /* And off we go */ + if (ftpState->flags.isdir) { - ftpListDir(ftpState); + ftpListDir(ftpState); } else { - ftpGetFile(ftpState); + ftpGetFile(ftpState); } + return; } @@ -2333,8 +2801,8 @@ static void ftpUnhack(FtpStateData * ftpState) { if (ftpState->old_request != NULL) { - safe_free(ftpState->old_request); - safe_free(ftpState->old_reply); + safe_free(ftpState->old_request); + safe_free(ftpState->old_reply); } } @@ -2345,14 +2813,17 @@ ftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState) ftpState->restarted_offset = 0; ftpState->restart_offset = 0; /* Save old error message & some state info */ + if (ftpState->old_request == NULL) { - ftpState->old_request = ftpState->ctrl.last_command; - ftpState->ctrl.last_command = NULL; - ftpState->old_reply = ftpState->ctrl.last_reply; - ftpState->ctrl.last_reply = NULL; - if (ftpState->pathcomps == NULL && ftpState->filepath != NULL) - ftpState->old_filepath = xstrdup(ftpState->filepath); + ftpState->old_request = ftpState->ctrl.last_command; + ftpState->ctrl.last_command = NULL; + ftpState->old_reply = ftpState->ctrl.last_reply; + ftpState->ctrl.last_reply = NULL; + + if (ftpState->pathcomps == NULL && ftpState->filepath != NULL) + ftpState->old_filepath = xstrdup(ftpState->filepath); } + /* Jump to the "hack" state */ nextState(ftpState); } @@ -2362,34 +2833,45 @@ ftpFail(FtpStateData * ftpState) { debug(9, 3) ("ftpFail\n"); /* Try the / hack to support "Netscape" FTP URL's for retreiving files */ + if (!ftpState->flags.isdir && /* Not a directory */ - !ftpState->flags.try_slash_hack && /* Not in slash hack */ - ftpState->mdtm <= 0 && ftpState->size < 0 && /* Not known as a file */ - ftpState->request->urlpath.nCaseCmp("/%2f", 4) != 0) { /* No slash encoded */ - switch (ftpState->state) { - case SENT_CWD: - case SENT_RETR: - /* Try the / hack */ - ftpHackShortcut(ftpState, ftpTrySlashHack); - return; - default: - break; - } + !ftpState->flags.try_slash_hack && /* Not in slash hack */ + ftpState->mdtm <= 0 && ftpState->size < 0 && /* Not known as a file */ + ftpState->request->urlpath.nCaseCmp("/%2f", 4) != 0) { /* No slash encoded */ + + switch (ftpState->state) { + + case SENT_CWD: + + case SENT_RETR: + /* Try the / hack */ + ftpHackShortcut(ftpState, ftpTrySlashHack); + return; + + default: + break; + } } + /* Try to reopen datachannel */ if (!ftpState->flags.datachannel_hack && - ftpState->pathcomps == NULL) { - switch (ftpState->state) { - case SENT_RETR: - case SENT_LIST: - case SENT_NLST: - /* Try to reopen datachannel */ - ftpHackShortcut(ftpState, ftpTryDatachannelHack); - return; - default: - break; - } + ftpState->pathcomps == NULL) { + switch (ftpState->state) { + + case SENT_RETR: + + case SENT_LIST: + + case SENT_NLST: + /* Try to reopen datachannel */ + ftpHackShortcut(ftpState, ftpTryDatachannelHack); + return; + + default: + break; + } } + ftpFailed(ftpState, ERR_NONE); /* ftpFailed closes ctrl.fd and frees ftpState */ } @@ -2398,12 +2880,15 @@ static void ftpFailed(FtpStateData * ftpState, err_type error) { StoreEntry *entry = ftpState->entry; + if (entry->isEmpty()) - ftpFailedErrorMessage(ftpState, error); + ftpFailedErrorMessage(ftpState, error); + if (ftpState->data.fd > -1) { - comm_close(ftpState->data.fd); - ftpState->data.fd = -1; + comm_close(ftpState->data.fd); + ftpState->data.fd = -1; } + comm_close(ftpState->ctrl.fd); } @@ -2414,52 +2899,77 @@ ftpFailedErrorMessage(FtpStateData * ftpState, err_type error) const char *command, *reply; /* Translate FTP errors into HTTP errors */ err = NULL; + switch (error) { + case ERR_NONE: - switch (ftpState->state) { - case SENT_USER: - case SENT_PASS: - if (ftpState->ctrl.replycode > 500) - err = errorCon(ERR_FTP_FORBIDDEN, HTTP_FORBIDDEN); - else if (ftpState->ctrl.replycode == 421) - err = errorCon(ERR_FTP_UNAVAILABLE, HTTP_SERVICE_UNAVAILABLE); - break; - case SENT_CWD: - case SENT_RETR: - if (ftpState->ctrl.replycode == 550) - err = errorCon(ERR_FTP_NOT_FOUND, HTTP_NOT_FOUND); - break; - default: - break; - } - break; + + switch (ftpState->state) { + + case SENT_USER: + + case SENT_PASS: + + if (ftpState->ctrl.replycode > 500) + err = errorCon(ERR_FTP_FORBIDDEN, HTTP_FORBIDDEN); + else if (ftpState->ctrl.replycode == 421) + err = errorCon(ERR_FTP_UNAVAILABLE, HTTP_SERVICE_UNAVAILABLE); + + break; + + case SENT_CWD: + + case SENT_RETR: + if (ftpState->ctrl.replycode == 550) + err = errorCon(ERR_FTP_NOT_FOUND, HTTP_NOT_FOUND); + + break; + + default: + break; + } + + break; + case ERR_READ_TIMEOUT: - err = errorCon(error, HTTP_GATEWAY_TIMEOUT); - break; + err = errorCon(error, HTTP_GATEWAY_TIMEOUT); + break; + default: - err = errorCon(error, HTTP_BAD_GATEWAY); - break; + err = errorCon(error, HTTP_BAD_GATEWAY); + break; } + if (err == NULL) - err = errorCon(ERR_FTP_FAILURE, HTTP_BAD_GATEWAY); + err = errorCon(ERR_FTP_FAILURE, HTTP_BAD_GATEWAY); + err->xerrno = errno; + err->request = requestLink(ftpState->request); + err->ftp.server_msg = ftpState->ctrl.message; + ftpState->ctrl.message = NULL; + if (ftpState->old_request) - command = ftpState->old_request; + command = ftpState->old_request; else - command = ftpState->ctrl.last_command; + command = ftpState->ctrl.last_command; + if (command && strncmp(command, "PASS", 4) == 0) - command = "PASS "; + command = "PASS "; + if (ftpState->old_reply) - reply = ftpState->old_reply; + reply = ftpState->old_reply; else - reply = ftpState->ctrl.last_reply; + reply = ftpState->ctrl.last_reply; + if (command) - err->ftp.request = xstrdup(command); + err->ftp.request = xstrdup(command); + if (reply) - err->ftp.reply = xstrdup(reply); + err->ftp.reply = xstrdup(reply); + fwdFail(ftpState->fwd, err); } @@ -2471,33 +2981,41 @@ ftpSendReply(FtpStateData * ftpState) http_status http_code; err_type err_code = ERR_NONE; debug(9, 5) ("ftpSendReply: %s, code %d\n", - storeUrl(ftpState->entry), code); + storeUrl(ftpState->entry), code); + if (cbdataReferenceValid(ftpState)) - debug(9, 5) ("ftpSendReply: ftpState (%p) is valid!\n", ftpState); + debug(9, 5) ("ftpSendReply: ftpState (%p) is valid!\n", ftpState); + if (code == 226) { - err_code = (ftpState->mdtm > 0) ? ERR_FTP_PUT_MODIFIED : ERR_FTP_PUT_CREATED; - http_code = (ftpState->mdtm > 0) ? HTTP_ACCEPTED : HTTP_CREATED; + err_code = (ftpState->mdtm > 0) ? ERR_FTP_PUT_MODIFIED : ERR_FTP_PUT_CREATED; + http_code = (ftpState->mdtm > 0) ? HTTP_ACCEPTED : HTTP_CREATED; } else if (code == 227) { - err_code = ERR_FTP_PUT_CREATED; - http_code = HTTP_CREATED; + err_code = ERR_FTP_PUT_CREATED; + http_code = HTTP_CREATED; } else { - err_code = ERR_FTP_PUT_ERROR; - http_code = HTTP_INTERNAL_SERVER_ERROR; + err_code = ERR_FTP_PUT_ERROR; + http_code = HTTP_INTERNAL_SERVER_ERROR; } + err = errorCon(err_code, http_code); err->request = requestLink(ftpState->request); + if (ftpState->old_request) - err->ftp.request = xstrdup(ftpState->old_request); + err->ftp.request = xstrdup(ftpState->old_request); else - err->ftp.request = xstrdup(ftpState->ctrl.last_command); + err->ftp.request = xstrdup(ftpState->ctrl.last_command); + if (ftpState->old_reply) - err->ftp.reply = xstrdup(ftpState->old_reply); + err->ftp.reply = xstrdup(ftpState->old_reply); else if (ftpState->ctrl.last_reply) - err->ftp.reply = xstrdup(ftpState->ctrl.last_reply); + err->ftp.reply = xstrdup(ftpState->ctrl.last_reply); else - err->ftp.reply = xstrdup(""); + err->ftp.reply = xstrdup(""); + errorAppendEntry(ftpState->entry, err); + storeBufferFlush(ftpState->entry); + ftpSendQuit(ftpState); } @@ -2514,61 +3032,76 @@ ftpAppendSuccessHeader(FtpStateData * ftpState) http_version_t version; if (ftpState->flags.http_header_sent) - return; + return; + ftpState->flags.http_header_sent = 1; + assert(e->isEmpty()); + EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); + filename = (t = strRChr(urlpath, '/')) ? t + 1 : urlpath.buf(); + if (ftpState->flags.isdir) { - mime_type = "text/html"; + mime_type = "text/html"; } else { - switch (ftpState->typecode) { - case 'I': - mime_type = "application/octet-stream"; - mime_enc = mimeGetContentEncoding(filename); - break; - case 'A': - mime_type = "text/plain"; - break; - default: - mime_type = mimeGetContentType(filename); - mime_enc = mimeGetContentEncoding(filename); - break; - } + switch (ftpState->typecode) { + + case 'I': + mime_type = "application/octet-stream"; + mime_enc = mimeGetContentEncoding(filename); + break; + + case 'A': + mime_type = "text/plain"; + break; + + default: + mime_type = mimeGetContentType(filename); + mime_enc = mimeGetContentEncoding(filename); + break; + } } + storeBuffer(e); reply = httpReplyCreate(); /* set standard stuff */ + if (ftpState->restarted_offset) { - /* Partial reply */ - HttpHdrRangeSpec range_spec; - range_spec.offset = ftpState->restarted_offset; - range_spec.length = ftpState->size - ftpState->restarted_offset; - httpBuildVersion(&version, 1, 0); - httpReplySetHeaders(reply, version, HTTP_PARTIAL_CONTENT, "Gatewaying", - mime_type, ftpState->size - ftpState->restarted_offset, ftpState->mdtm, -2); - httpHeaderAddContRange(&reply->header, range_spec, ftpState->size); + /* Partial reply */ + HttpHdrRangeSpec range_spec; + range_spec.offset = ftpState->restarted_offset; + range_spec.length = ftpState->size - ftpState->restarted_offset; + httpBuildVersion(&version, 1, 0); + httpReplySetHeaders(reply, version, HTTP_PARTIAL_CONTENT, "Gatewaying", + mime_type, ftpState->size - ftpState->restarted_offset, ftpState->mdtm, -2); + httpHeaderAddContRange(&reply->header, range_spec, ftpState->size); } else { - /* Full reply */ - httpBuildVersion(&version, 1, 0); - httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", - mime_type, ftpState->size, ftpState->mdtm, -2); + /* Full reply */ + httpBuildVersion(&version, 1, 0); + httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", + mime_type, ftpState->size, ftpState->mdtm, -2); } + /* additional info */ if (mime_enc) - httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc); + httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc); + httpReplySwapOut(reply, e); + storeBufferFlush(e); + storeTimestampsSet(e); + if (ftpState->flags.authenticated) { - /* - * Authenticated requests can't be cached. - */ - storeRelease(e); + /* + * Authenticated requests can't be cached. + */ + storeRelease(e); } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE) && !ftpState->restarted_offset) { - storeSetPublicKey(e); + storeSetPublicKey(e); } else { - storeRelease(e); + storeRelease(e); } } @@ -2594,25 +3127,34 @@ ftpUrlWith2f(const request_t * request) LOCAL_ARRAY(char, portbuf, 32); char *t; portbuf[0] = '\0'; + if (request->protocol != PROTO_FTP) - return NULL; + return NULL; + if (request->port != urlDefaultPort(request->protocol)) - snprintf(portbuf, 32, ":%d", request->port); + snprintf(portbuf, 32, ":%d", request->port); + loginbuf[0] = '\0'; + if ((int) strlen(request->login) > 0) { - xstrncpy(loginbuf, request->login, sizeof(loginbuf) - 2); - if ((t = strchr(loginbuf, ':'))) - *t = '\0'; - strcat(loginbuf, "@"); + xstrncpy(loginbuf, request->login, sizeof(loginbuf) - 2); + + if ((t = strchr(loginbuf, ':'))) + *t = '\0'; + + strcat(loginbuf, "@"); } + snprintf(buf, MAX_URL, "%s://%s%s%s%s%s", - ProtocolStr[request->protocol], - loginbuf, - request->host, - portbuf, - "/%2f", - request->urlpath.buf()); + ProtocolStr[request->protocol], + loginbuf, + request->host, + portbuf, + "/%2f", + request->urlpath.buf()); + if ((t = strchr(buf, '?'))) - *t = '\0'; + *t = '\0'; + return buf; } diff --git a/src/globals.h b/src/globals.h index 3f5e076bb6..21d84e69be 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,6 +1,6 @@ /* - * $Id: globals.h,v 1.119 2003/02/21 19:53:01 hno Exp $ + * $Id: globals.h,v 1.120 2003/02/21 22:50:08 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -102,13 +102,21 @@ extern char *snmp_agentinfo; #endif extern int n_disk_objects; /* 0 */ extern iostats IOStats; + extern struct _acl_deny_info_list *DenyInfoList; /* NULL */ + extern struct in_addr any_addr; + extern struct in_addr local_addr; + extern struct in_addr no_addr; + extern struct in_addr theOutICPAddr; + extern struct in_addr theOutSNMPAddr; + extern struct timeval current_time; + extern struct timeval squid_start; extern time_t squid_curtime; /* 0 */ extern int shutting_down; /* 0 */ diff --git a/src/gopher.cc b/src/gopher.cc index d8e8f3dbc8..497a711cbc 100644 --- a/src/gopher.cc +++ b/src/gopher.cc @@ -1,6 +1,6 @@ /* - * $Id: gopher.cc,v 1.179 2003/02/05 10:36:51 robertc Exp $ + * $Id: gopher.cc,v 1.180 2003/02/21 22:50:08 robertc Exp $ * * DEBUG: section 10 Gopher * AUTHOR: Harvest Derived @@ -72,15 +72,16 @@ #define TEMP_BUF_SIZE 4096 #define MAX_CSO_RESULT 1024 -typedef struct gopher_ds { +typedef struct gopher_ds +{ StoreEntry *entry; enum { - NORMAL, - HTML_DIR, - HTML_INDEX_RESULT, - HTML_CSO_RESULT, - HTML_INDEX_PAGE, - HTML_CSO_PAGE + NORMAL, + HTML_DIR, + HTML_INDEX_RESULT, + HTML_CSO_RESULT, + HTML_INDEX_PAGE, + HTML_CSO_PAGE } conversion; int HTML_header_added; char type_id; @@ -93,14 +94,16 @@ typedef struct gopher_ds { request_t *req; FwdState *fwdState; char replybuf[BUFSIZ]; -} GopherStateData; +} + +GopherStateData; static PF gopherStateFree; static void gopher_mime_content(MemBuf * mb, const char *name, const char *def); static void gopherMimeCreate(GopherStateData *); static void gopher_request_parse(const request_t * req, - char *type_id, - char *request); + char *type_id, + char *request); static void gopherEndHTML(GopherStateData *); static void gopherToHTML(GopherStateData *, char *inbuf, int len); static PF gopherTimeout; @@ -115,14 +118,18 @@ static void gopherStateFree(int fdnotused, void *data) { GopherStateData *gopherState = (GopherStateData *)data; + if (gopherState == NULL) - return; + return; + if (gopherState->entry) { - storeUnlockObject(gopherState->entry); + storeUnlockObject(gopherState->entry); } + if (gopherState->req) { - requestUnlink(gopherState->req); + requestUnlink(gopherState->req); } + memFree(gopherState->buf, MEM_4K_BUF); gopherState->buf = NULL; cbdataFree(gopherState); @@ -135,10 +142,12 @@ gopher_mime_content(MemBuf * mb, const char *name, const char *def_ctype) { char *ctype = mimeGetContentType(name); char *cenc = mimeGetContentEncoding(name); + if (cenc) - memBufPrintf(mb, "Content-Encoding: %s\r\n", cenc); + memBufPrintf(mb, "Content-Encoding: %s\r\n", cenc); + memBufPrintf(mb, "Content-Type: %s\r\n", - ctype ? ctype : def_ctype); + ctype ? ctype : def_ctype); } @@ -152,44 +161,61 @@ gopherMimeCreate(GopherStateData * gopherState) memBufDefInit(&mb); memBufPrintf(&mb, - "HTTP/1.0 200 OK Gatewaying\r\n" - "Server: Squid/%s\r\n" - "Date: %s\r\n", - version_string, mkrfc1123(squid_curtime)); + "HTTP/1.0 200 OK Gatewaying\r\n" + "Server: Squid/%s\r\n" + "Date: %s\r\n", + version_string, mkrfc1123(squid_curtime)); switch (gopherState->type_id) { case GOPHER_DIRECTORY: + case GOPHER_INDEX: + case GOPHER_HTML: + case GOPHER_WWW: + case GOPHER_CSO: - memBufPrintf(&mb, "Content-Type: text/html\r\n"); - break; + memBufPrintf(&mb, "Content-Type: text/html\r\n"); + break; + case GOPHER_GIF: + case GOPHER_IMAGE: + case GOPHER_PLUS_IMAGE: - memBufPrintf(&mb, "Content-Type: image/gif\r\n"); - break; + memBufPrintf(&mb, "Content-Type: image/gif\r\n"); + break; + case GOPHER_SOUND: + case GOPHER_PLUS_SOUND: - memBufPrintf(&mb, "Content-Type: audio/basic\r\n"); - break; + memBufPrintf(&mb, "Content-Type: audio/basic\r\n"); + break; + case GOPHER_PLUS_MOVIE: - memBufPrintf(&mb, "Content-Type: video/mpeg\r\n"); - break; + memBufPrintf(&mb, "Content-Type: video/mpeg\r\n"); + break; + case GOPHER_MACBINHEX: + case GOPHER_DOSBIN: + case GOPHER_UUENCODED: + case GOPHER_BIN: - /* Rightnow We have no idea what it is. */ - gopher_mime_content(&mb, gopherState->request, def_gopher_bin); - break; + /* Rightnow We have no idea what it is. */ + gopher_mime_content(&mb, gopherState->request, def_gopher_bin); + break; + case GOPHER_FILE: + default: - gopher_mime_content(&mb, gopherState->request, def_gopher_text); - break; + gopher_mime_content(&mb, gopherState->request, def_gopher_text); + break; } + memBufPrintf(&mb, "\r\n"); EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT); storeAppend(gopherState->entry, mb.buf, mb.size); @@ -203,21 +229,22 @@ gopher_request_parse(const request_t * req, char *type_id, char *request) const char *path = req->urlpath.buf(); if (request) - request[0] = '\0'; + request[0] = '\0'; if (path && (*path == '/')) - path++; + path++; if (!path || !*path) { - *type_id = GOPHER_DIRECTORY; - return; + *type_id = GOPHER_DIRECTORY; + return; } + *type_id = path[0]; if (request) { - xstrncpy(request, path + 1, MAX_URL); - /* convert %xx to char */ - url_convert_hex(request, 0); + xstrncpy(request, path + 1, MAX_URL); + /* convert %xx to char */ + url_convert_hex(request, 0); } } @@ -228,18 +255,25 @@ gopherCachable(const request_t * req) char type_id; /* parse to see type */ gopher_request_parse(req, - &type_id, - NULL); + &type_id, + NULL); + switch (type_id) { + case GOPHER_INDEX: + case GOPHER_CSO: + case GOPHER_TELNET: + case GOPHER_3270: - cachable = 0; - break; + cachable = 0; + break; + default: - cachable = 1; + cachable = 1; } + return cachable; } @@ -262,9 +296,9 @@ gopherHTMLFooter(StoreEntry * e) storeAppendPrintf(e, "
    \n"); storeAppendPrintf(e, "
    \n"); storeAppendPrintf(e, "Generated %s by %s (%s)\n", - mkrfc1123(squid_curtime), - getMyHostname(), - full_appname_string); + mkrfc1123(squid_curtime), + getMyHostname(), + full_appname_string); storeAppendPrintf(e, "
    \n"); } @@ -272,12 +306,14 @@ static void gopherEndHTML(GopherStateData * gopherState) { StoreEntry *e = gopherState->entry; + if (!gopherState->data_in) { - gopherHTMLHeader(e, "Server Return Nothing", NULL); - storeAppendPrintf(e, "

    The Gopher query resulted in a blank response

    "); + gopherHTMLHeader(e, "Server Return Nothing", NULL); + storeAppendPrintf(e, "

    The Gopher query resulted in a blank response

    "); } else { - storeAppendPrintf(e, "\n"); + storeAppendPrintf(e, "\n"); } + gopherHTMLFooter(e); } @@ -308,297 +344,351 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) entry = gopherState->entry; if (gopherState->conversion == gopher_ds::HTML_INDEX_PAGE) { - char *html_url = html_quote(storeUrl(entry)); - gopherHTMLHeader(entry, "Gopher Index %s", html_url); - storeAppendPrintf(entry, - "

    This is a searchable Gopher index. Use the search\n" - "function of your browser to enter search terms.\n" - "\n"); - gopherHTMLFooter(entry); - /* now let start sending stuff to client */ - storeBufferFlush(entry); - gopherState->data_in = 1; - - return; + char *html_url = html_quote(storeUrl(entry)); + gopherHTMLHeader(entry, "Gopher Index %s", html_url); + storeAppendPrintf(entry, + "

    This is a searchable Gopher index. Use the search\n" + "function of your browser to enter search terms.\n" + "\n"); + gopherHTMLFooter(entry); + /* now let start sending stuff to client */ + storeBufferFlush(entry); + gopherState->data_in = 1; + + return; } + if (gopherState->conversion == gopher_ds::HTML_CSO_PAGE) { - char *html_url = html_quote(storeUrl(entry)); - gopherHTMLHeader(entry, "CSO Search of %s", html_url); - storeAppendPrintf(entry, - "

    A CSO database usually contains a phonebook or\n" - "directory. Use the search function of your browser to enter\n" - "search terms.

    \n"); - gopherHTMLFooter(entry); - /* now let start sending stuff to client */ - storeBufferFlush(entry); - gopherState->data_in = 1; - - return; + char *html_url = html_quote(storeUrl(entry)); + gopherHTMLHeader(entry, "CSO Search of %s", html_url); + storeAppendPrintf(entry, + "

    A CSO database usually contains a phonebook or\n" + "directory. Use the search function of your browser to enter\n" + "search terms.

    \n"); + gopherHTMLFooter(entry); + /* now let start sending stuff to client */ + storeBufferFlush(entry); + gopherState->data_in = 1; + + return; } + inbuf[len] = '\0'; if (!gopherState->HTML_header_added) { - if (gopherState->conversion == gopher_ds::HTML_CSO_RESULT) - gopherHTMLHeader(entry, "CSO Search Result", NULL); - else - gopherHTMLHeader(entry, "Gopher Menu", NULL); - outbuf.append ("
    ");
    -	gopherState->HTML_header_added = 1;
    +        if (gopherState->conversion == gopher_ds::HTML_CSO_RESULT)
    +            gopherHTMLHeader(entry, "CSO Search Result", NULL);
    +        else
    +            gopherHTMLHeader(entry, "Gopher Menu", NULL);
    +
    +        outbuf.append ("
    ");
    +
    +        gopherState->HTML_header_added = 1;
         }
    +
         while ((pos != NULL) && (pos < inbuf + len)) {
     
    -	if (gopherState->len != 0) {
    -	    /* there is something left from last tx. */
    -	    xstrncpy(line, gopherState->buf, gopherState->len + 1);
    -	    lpos = (char *) memccpy(line + gopherState->len, inbuf, '\n', len);
    -	    if (lpos)
    -		*lpos = '\0';
    -	    else {
    -		/* there is no complete line in inbuf */
    -		/* copy it to temp buffer */
    -		if (gopherState->len + len > TEMP_BUF_SIZE) {
    -		    debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n",
    -			storeUrl(entry));
    -		    len = TEMP_BUF_SIZE - gopherState->len;
    -		}
    -		xmemcpy(gopherState->buf + gopherState->len, inbuf, len);
    -		gopherState->len += len;
    -		return;
    -	    }
    -
    -	    /* skip one line */
    -	    pos = (char *) memchr(pos, '\n', len);
    -	    if (pos)
    -		pos++;
    -
    -	    /* we're done with the remain from last tx. */
    -	    gopherState->len = 0;
    -	    *(gopherState->buf) = '\0';
    -	} else {
    -
    -	    lpos = (char *) memccpy(line, pos, '\n', len - (pos - inbuf));
    -	    if (lpos)
    -		*lpos = '\0';
    -	    else {
    -		/* there is no complete line in inbuf */
    -		/* copy it to temp buffer */
    -		if ((len - (pos - inbuf)) > TEMP_BUF_SIZE) {
    -		    debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n",
    -			storeUrl(entry));
    -		    len = TEMP_BUF_SIZE;
    -		}
    -		if (len > (pos - inbuf)) {
    -		    xmemcpy(gopherState->buf, pos, len - (pos - inbuf));
    -		    gopherState->len = len - (pos - inbuf);
    -		}
    -		break;
    -	    }
    -
    -	    /* skip one line */
    -	    pos = (char *) memchr(pos, '\n', len);
    -	    if (pos)
    -		pos++;
    -
    -	}
    -
    -	/* at this point. We should have one line in buffer to process */
    -
    -	if (*line == '.') {
    -	    /* skip it */
    -	    memset(line, '\0', TEMP_BUF_SIZE);
    -	    continue;
    -	}
    -	switch (gopherState->conversion) {
    -
    -	case gopher_ds::HTML_INDEX_RESULT:
    -	case gopher_ds::HTML_DIR:{
    -		tline = line;
    -		gtype = *tline++;
    -		name = tline;
    -		selector = strchr(tline, TAB);
    -		if (selector) {
    -		    *selector++ = '\0';
    -		    host = strchr(selector, TAB);
    -		    if (host) {
    -			*host++ = '\0';
    -			port = strchr(host, TAB);
    -			if (port) {
    -			    char *junk;
    -			    port[0] = ':';
    -			    junk = strchr(host, TAB);
    -			    if (junk)
    -				*junk++ = 0;	/* Chop port */
    -			    else {
    -				junk = strchr(host, '\r');
    -				if (junk)
    -				    *junk++ = 0;	/* Chop port */
    -				else {
    -				    junk = strchr(host, '\n');
    -				    if (junk)
    -					*junk++ = 0;	/* Chop port */
    -				}
    -			    }
    -			    if ((port[1] == '0') && (!port[2]))
    -				port[0] = 0;	/* 0 means none */
    -			}
    -			/* escape a selector here */
    -			escaped_selector = xstrdup(rfc1738_escape_part(selector));
    -
    -			switch (gtype) {
    -			case GOPHER_DIRECTORY:
    -			    icon_url = mimeGetIconURL("internal-menu");
    -			    break;
    -			case GOPHER_HTML:
    -			case GOPHER_FILE:
    -			    icon_url = mimeGetIconURL("internal-text");
    -			    break;
    -			case GOPHER_INDEX:
    -			case GOPHER_CSO:
    -			    icon_url = mimeGetIconURL("internal-index");
    -			    break;
    -			case GOPHER_IMAGE:
    -			case GOPHER_GIF:
    -			case GOPHER_PLUS_IMAGE:
    -			    icon_url = mimeGetIconURL("internal-image");
    -			    break;
    -			case GOPHER_SOUND:
    -			case GOPHER_PLUS_SOUND:
    -			    icon_url = mimeGetIconURL("internal-sound");
    -			    break;
    -			case GOPHER_PLUS_MOVIE:
    -			    icon_url = mimeGetIconURL("internal-movie");
    -			    break;
    -			case GOPHER_TELNET:
    -			case GOPHER_3270:
    -			    icon_url = mimeGetIconURL("internal-telnet");
    -			    break;
    -			case GOPHER_BIN:
    -			case GOPHER_MACBINHEX:
    -			case GOPHER_DOSBIN:
    -			case GOPHER_UUENCODED:
    -			    icon_url = mimeGetIconURL("internal-binary");
    -			    break;
    -			case GOPHER_INFO:
    -			    icon_url = NULL;
    -			    break;
    -			default:
    -			    icon_url = mimeGetIconURL("internal-unknown");
    -			    break;
    -			}
    -
    -			memset(tmpbuf, '\0', TEMP_BUF_SIZE);
    -			if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) {
    -			    if (strlen(escaped_selector) != 0)
    -				snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    -				    icon_url, escaped_selector, rfc1738_escape_part(host),
    -				    *port ? ":" : "", port, html_quote(name));
    -			    else
    -				snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    -				    icon_url, rfc1738_escape_part(host), *port ? ":" : "",
    -				    port, html_quote(name));
    -
    -			} else if (gtype == GOPHER_INFO) {
    -			    snprintf(tmpbuf, TEMP_BUF_SIZE, "\t%s\n", html_quote(name));
    -			} else {
    -			    if (strncmp(selector, "GET /", 5) == 0) {
    -				/* WWW link */
    -				snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    -				    icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name));
    -			    } else {
    -				/* Standard link */
    -				snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    -				    icon_url, host, gtype, escaped_selector, html_quote(name));
    -			    }
    -			}
    -			safe_free(escaped_selector);
    -			outbuf.append(tmpbuf);
    -			gopherState->data_in = 1;
    -		    } else {
    -			memset(line, '\0', TEMP_BUF_SIZE);
    -			continue;
    -		    }
    -		} else {
    -		    memset(line, '\0', TEMP_BUF_SIZE);
    -		    continue;
    -		}
    -		break;
    -	    }			/* HTML_DIR, HTML_INDEX_RESULT */
    -
    -
    -	case gopher_ds::HTML_CSO_RESULT:{
    -		if (line[0] == '-') {
    -		    int code, recno;
    -		    char *s_code, *s_recno, *result;
    -
    -		    s_code = strtok(line + 1, ":\n");
    -		    s_recno = strtok(NULL, ":\n");
    -		    result = strtok(NULL, "\n");
    -
    -		    if (!result)
    -			break;
    -
    -		    code = atoi(s_code);
    -		    recno = atoi(s_recno);
    -
    -		    if (code != 200)
    -			break;
    -
    -		    if (gopherState->cso_recno != recno) {
    -			snprintf(tmpbuf, TEMP_BUF_SIZE, "

    Record# %d
    %s

    \n
    ", recno, html_quote(result));
    -			gopherState->cso_recno = recno;
    -		    } else {
    -			snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", html_quote(result));
    -		    }
    -		    outbuf.append(tmpbuf);
    -		    gopherState->data_in = 1;
    -		    break;
    -		} else {
    -		    int code;
    -		    char *s_code, *result;
    -
    -		    s_code = strtok(line, ":");
    -		    result = strtok(NULL, "\n");
    -
    -		    if (!result)
    -			break;
    -
    -		    code = atoi(s_code);
    -		    switch (code) {
    -
    -		    case 200:{
    -			    /* OK */
    -			    /* Do nothing here */
    -			    break;
    -			}
    -
    -		    case 102:	/* Number of matches */
    -		    case 501:	/* No Match */
    -		    case 502:	/* Too Many Matches */
    -			{
    -			    /* Print the message the server returns */
    -			    snprintf(tmpbuf, TEMP_BUF_SIZE, "

    %s

    \n
    ", html_quote(result));
    -			    outbuf.append(tmpbuf);
    -			    gopherState->data_in = 1;
    -			    break;
    -			}
    -
    -
    -		    }
    -		}
    -
    -	    }			/* HTML_CSO_RESULT */
    -	default:
    -	    break;		/* do nothing */
    -
    -	}			/* switch */
    +        if (gopherState->len != 0) {
    +            /* there is something left from last tx. */
    +            xstrncpy(line, gopherState->buf, gopherState->len + 1);
    +            lpos = (char *) memccpy(line + gopherState->len, inbuf, '\n', len);
    +
    +            if (lpos)
    +                *lpos = '\0';
    +            else {
    +                /* there is no complete line in inbuf */
    +                /* copy it to temp buffer */
    +
    +                if (gopherState->len + len > TEMP_BUF_SIZE) {
    +                    debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n",
    +                                  storeUrl(entry));
    +                    len = TEMP_BUF_SIZE - gopherState->len;
    +                }
    +
    +                xmemcpy(gopherState->buf + gopherState->len, inbuf, len);
    +                gopherState->len += len;
    +                return;
    +            }
    +
    +            /* skip one line */
    +            pos = (char *) memchr(pos, '\n', len);
    +
    +            if (pos)
    +                pos++;
    +
    +            /* we're done with the remain from last tx. */
    +            gopherState->len = 0;
    +
    +            *(gopherState->buf) = '\0';
    +        } else {
    +
    +            lpos = (char *) memccpy(line, pos, '\n', len - (pos - inbuf));
    +
    +            if (lpos)
    +                *lpos = '\0';
    +            else {
    +                /* there is no complete line in inbuf */
    +                /* copy it to temp buffer */
    +
    +                if ((len - (pos - inbuf)) > TEMP_BUF_SIZE) {
    +                    debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n",
    +                                  storeUrl(entry));
    +                    len = TEMP_BUF_SIZE;
    +                }
    +
    +                if (len > (pos - inbuf)) {
    +                    xmemcpy(gopherState->buf, pos, len - (pos - inbuf));
    +                    gopherState->len = len - (pos - inbuf);
    +                }
    +
    +                break;
    +            }
    +
    +            /* skip one line */
    +            pos = (char *) memchr(pos, '\n', len);
    +
    +            if (pos)
    +                pos++;
    +
    +        }
    +
    +        /* at this point. We should have one line in buffer to process */
    +
    +        if (*line == '.') {
    +            /* skip it */
    +            memset(line, '\0', TEMP_BUF_SIZE);
    +            continue;
    +        }
    +
    +        switch (gopherState->conversion) {
    +
    +        case gopher_ds::HTML_INDEX_RESULT:
    +
    +        case gopher_ds::HTML_DIR: {
    +                tline = line;
    +                gtype = *tline++;
    +                name = tline;
    +                selector = strchr(tline, TAB);
    +
    +                if (selector) {
    +                    *selector++ = '\0';
    +                    host = strchr(selector, TAB);
    +
    +                    if (host) {
    +                        *host++ = '\0';
    +                        port = strchr(host, TAB);
    +
    +                        if (port) {
    +                            char *junk;
    +                            port[0] = ':';
    +                            junk = strchr(host, TAB);
    +
    +                            if (junk)
    +                                *junk++ = 0;	/* Chop port */
    +                            else {
    +                                junk = strchr(host, '\r');
    +
    +                                if (junk)
    +                                    *junk++ = 0;	/* Chop port */
    +                                else {
    +                                    junk = strchr(host, '\n');
    +
    +                                    if (junk)
    +                                        *junk++ = 0;	/* Chop port */
    +                                }
    +                            }
    +
    +                            if ((port[1] == '0') && (!port[2]))
    +                                port[0] = 0;	/* 0 means none */
    +                        }
    +
    +                        /* escape a selector here */
    +                        escaped_selector = xstrdup(rfc1738_escape_part(selector));
    +
    +                        switch (gtype) {
    +
    +                        case GOPHER_DIRECTORY:
    +                            icon_url = mimeGetIconURL("internal-menu");
    +                            break;
    +
    +                        case GOPHER_HTML:
    +
    +                        case GOPHER_FILE:
    +                            icon_url = mimeGetIconURL("internal-text");
    +                            break;
    +
    +                        case GOPHER_INDEX:
    +
    +                        case GOPHER_CSO:
    +                            icon_url = mimeGetIconURL("internal-index");
    +                            break;
    +
    +                        case GOPHER_IMAGE:
    +
    +                        case GOPHER_GIF:
    +
    +                        case GOPHER_PLUS_IMAGE:
    +                            icon_url = mimeGetIconURL("internal-image");
    +                            break;
    +
    +                        case GOPHER_SOUND:
    +
    +                        case GOPHER_PLUS_SOUND:
    +                            icon_url = mimeGetIconURL("internal-sound");
    +                            break;
    +
    +                        case GOPHER_PLUS_MOVIE:
    +                            icon_url = mimeGetIconURL("internal-movie");
    +                            break;
    +
    +                        case GOPHER_TELNET:
    +
    +                        case GOPHER_3270:
    +                            icon_url = mimeGetIconURL("internal-telnet");
    +                            break;
    +
    +                        case GOPHER_BIN:
    +
    +                        case GOPHER_MACBINHEX:
    +
    +                        case GOPHER_DOSBIN:
    +
    +                        case GOPHER_UUENCODED:
    +                            icon_url = mimeGetIconURL("internal-binary");
    +                            break;
    +
    +                        case GOPHER_INFO:
    +                            icon_url = NULL;
    +                            break;
    +
    +                        default:
    +                            icon_url = mimeGetIconURL("internal-unknown");
    +                            break;
    +                        }
    +
    +                        memset(tmpbuf, '\0', TEMP_BUF_SIZE);
    +
    +                        if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) {
    +                            if (strlen(escaped_selector) != 0)
    +                                snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    +                                         icon_url, escaped_selector, rfc1738_escape_part(host),
    +                                         *port ? ":" : "", port, html_quote(name));
    +                            else
    +                                snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    +                                         icon_url, rfc1738_escape_part(host), *port ? ":" : "",
    +                                         port, html_quote(name));
    +
    +                        } else if (gtype == GOPHER_INFO) {
    +                            snprintf(tmpbuf, TEMP_BUF_SIZE, "\t%s\n", html_quote(name));
    +                        } else {
    +                            if (strncmp(selector, "GET /", 5) == 0) {
    +                                /* WWW link */
    +                                snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    +                                         icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name));
    +                            } else {
    +                                /* Standard link */
    +                                snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
    +                                         icon_url, host, gtype, escaped_selector, html_quote(name));
    +                            }
    +                        }
    +
    +                        safe_free(escaped_selector);
    +                        outbuf.append(tmpbuf);
    +                        gopherState->data_in = 1;
    +                    } else {
    +                        memset(line, '\0', TEMP_BUF_SIZE);
    +                        continue;
    +                    }
    +                } else {
    +                    memset(line, '\0', TEMP_BUF_SIZE);
    +                    continue;
    +                }
    +
    +                break;
    +            }			/* HTML_DIR, HTML_INDEX_RESULT */
    +
    +
    +        case gopher_ds::HTML_CSO_RESULT: {
    +                if (line[0] == '-') {
    +                    int code, recno;
    +                    char *s_code, *s_recno, *result;
    +
    +                    s_code = strtok(line + 1, ":\n");
    +                    s_recno = strtok(NULL, ":\n");
    +                    result = strtok(NULL, "\n");
    +
    +                    if (!result)
    +                        break;
    +
    +                    code = atoi(s_code);
    +
    +                    recno = atoi(s_recno);
    +
    +                    if (code != 200)
    +                        break;
    +
    +                    if (gopherState->cso_recno != recno) {
    +                        snprintf(tmpbuf, TEMP_BUF_SIZE, "

    Record# %d
    %s

    \n
    ", recno, html_quote(result));
    +                        gopherState->cso_recno = recno;
    +                    } else {
    +                        snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", html_quote(result));
    +                    }
    +
    +                    outbuf.append(tmpbuf);
    +                    gopherState->data_in = 1;
    +                    break;
    +                } else {
    +                    int code;
    +                    char *s_code, *result;
    +
    +                    s_code = strtok(line, ":");
    +                    result = strtok(NULL, "\n");
    +
    +                    if (!result)
    +                        break;
    +
    +                    code = atoi(s_code);
    +
    +                    switch (code) {
    +
    +                    case 200: {
    +                            /* OK */
    +                            /* Do nothing here */
    +                            break;
    +                        }
    +
    +                    case 102:	/* Number of matches */
    +
    +                    case 501:	/* No Match */
    +
    +                    case 502:	/* Too Many Matches */
    +                        {
    +                            /* Print the message the server returns */
    +                            snprintf(tmpbuf, TEMP_BUF_SIZE, "

    %s

    \n
    ", html_quote(result));
    +                            outbuf.append(tmpbuf);
    +                            gopherState->data_in = 1;
    +                            break;
    +                        }
    +
    +
    +                    }
    +                }
    +
    +            }			/* HTML_CSO_RESULT */
    +
    +        default:
    +            break;		/* do nothing */
    +
    +        }			/* switch */
     
         }				/* while loop */
     
         if (outbuf.size() > 0) {
    -	storeAppend(entry, outbuf.buf(), outbuf.size());
    -	/* now let start sending stuff to client */
    -	storeBufferFlush(entry);
    +        storeAppend(entry, outbuf.buf(), outbuf.size());
    +        /* now let start sending stuff to client */
    +        storeBufferFlush(entry);
         }
    +
         outbuf.clean();
         return;
     }
    @@ -609,12 +699,14 @@ gopherTimeout(int fd, void *data)
         GopherStateData *gopherState = (GopherStateData *)data;
         StoreEntry *entry = gopherState->entry;
         debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
    +
         if (entry->store_status == STORE_PENDING) {
    -	if (entry->isEmpty()) {
    -	    fwdFail(gopherState->fwdState,
    -		errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
    -	}
    +        if (entry->isEmpty()) {
    +            fwdFail(gopherState->fwdState,
    +                    errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
    +        }
         }
    +
         comm_close(fd);
     }
     
    @@ -630,85 +722,106 @@ gopherReadReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void
         size_t read_sz = BUFSIZ;
         int do_next_read = 0;
     #if DELAY_POOLS
    +
         DelayId delayId = entry->mem_obj->mostBytesAllowed();
     #endif
     
         /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
    +
         if (flag == COMM_ERR_CLOSING) {
             return;
         }
     
         assert(buf == gopherState->replybuf);
    +
         if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
    -	comm_close(fd);
    -	return;
    +        comm_close(fd);
    +        return;
         }
     
         errno = 0;
     #if DELAY_POOLS
    +
         read_sz = delayId.bytesWanted(1, read_sz);
     #endif
     
         /* leave one space for \0 in gopherToHTML */
    +
         if (flag == COMM_OK && len > 0) {
     #if DELAY_POOLS
    -	delayId.bytesIn(len);
    +        delayId.bytesIn(len);
     #endif
    -	kb_incr(&statCounter.server.all.kbytes_in, len);
    -	kb_incr(&statCounter.server.other.kbytes_in, len);
    +
    +        kb_incr(&statCounter.server.all.kbytes_in, len);
    +        kb_incr(&statCounter.server.other.kbytes_in, len);
         }
    +
         debug(10, 5) ("gopherReadReply: FD %d read len=%d\n", fd, (int)len);
    +
         if (flag == COMM_OK && len > 0) {
    -	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
    -	IOStats.Gopher.reads++;
    -	for (clen = len - 1, bin = 0; clen; bin++)
    -	    clen >>= 1;
    -	IOStats.Gopher.read_hist[bin]++;
    +        commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
    +        IOStats.Gopher.reads++;
    +
    +        for (clen = len - 1, bin = 0; clen; bin++)
    +            clen >>= 1;
    +
    +        IOStats.Gopher.read_hist[bin]++;
         }
    +
         if (flag != COMM_OK || len < 0) {
    -	debug(50, 1) ("gopherReadReply: error reading: %s\n", xstrerror());
    -	if (ignoreErrno(errno)) {
    +        debug(50, 1) ("gopherReadReply: error reading: %s\n", xstrerror());
    +
    +        if (ignoreErrno(errno)) {
                 do_next_read = 1;
    -	} else if (entry->isEmpty()) {
    -	    ErrorState *err;
    -	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    -	    err->xerrno = errno;
    -	    err->url = xstrdup(storeUrl(entry));
    -	    errorAppendEntry(entry, err);
    -	    comm_close(fd);
    +        } else if (entry->isEmpty()) {
    +            ErrorState *err;
    +            err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    +            err->xerrno = errno;
    +            err->url = xstrdup(storeUrl(entry));
    +            errorAppendEntry(entry, err);
    +            comm_close(fd);
                 do_next_read = 0;
    -	} else {
    -	    comm_close(fd);
    +        } else {
    +            comm_close(fd);
                 do_next_read = 0;
    -	}
    +        }
         } else if (len == 0 && entry->isEmpty()) {
    -	ErrorState *err;
    -	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
    -	err->xerrno = errno;
    -	err->url = xstrdup(gopherState->request);
    -	errorAppendEntry(entry, err);
    -	comm_close(fd);
    +        ErrorState *err;
    +        err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
    +        err->xerrno = errno;
    +        err->url = xstrdup(gopherState->request);
    +        errorAppendEntry(entry, err);
    +        comm_close(fd);
             do_next_read = 0;
         } else if (len == 0) {
    -	/* Connection closed; retrieval done. */
    -	/* flush the rest of data in temp buf if there is one. */
    -	if (gopherState->conversion != gopher_ds::NORMAL)
    -	    gopherEndHTML(gopherState);
    -	storeTimestampsSet(entry);
    -	storeBufferFlush(entry);
    -	fwdComplete(gopherState->fwdState);
    -	comm_close(fd);
    +        /* Connection closed; retrieval done. */
    +        /* flush the rest of data in temp buf if there is one. */
    +
    +        if (gopherState->conversion != gopher_ds::NORMAL)
    +            gopherEndHTML(gopherState);
    +
    +        storeTimestampsSet(entry);
    +
    +        storeBufferFlush(entry);
    +
    +        fwdComplete(gopherState->fwdState);
    +
    +        comm_close(fd);
    +
             do_next_read = 0;
         } else {
    -	if (gopherState->conversion != gopher_ds::NORMAL) {
    -	    gopherToHTML(gopherState, buf, len);
    -	} else {
    -	    storeAppend(entry, buf, len);
    -	}
    +        if (gopherState->conversion != gopher_ds::NORMAL) {
    +            gopherToHTML(gopherState, buf, len);
    +        } else {
    +            storeAppend(entry, buf, len);
    +        }
    +
             do_next_read = 1;
         }
    +
         if (do_next_read)
             comm_read(fd, buf, read_sz, gopherReadReply, gopherState);
    +
         return;
     }
     
    @@ -720,59 +833,72 @@ gopherSendComplete(int fd, char *buf, size_t size, comm_err_t errflag, int xerrn
         GopherStateData *gopherState = (GopherStateData *) data;
         StoreEntry *entry = gopherState->entry;
         debug(10, 5) ("gopherSendComplete: FD %d size: %d errflag: %d\n",
    -	fd, (int) size, errflag);
    +                  fd, (int) size, errflag);
    +
         if (size > 0) {
    -	fd_bytes(fd, size, FD_WRITE);
    -	kb_incr(&statCounter.server.all.kbytes_out, size);
    -	kb_incr(&statCounter.server.other.kbytes_out, size);
    +        fd_bytes(fd, size, FD_WRITE);
    +        kb_incr(&statCounter.server.all.kbytes_out, size);
    +        kb_incr(&statCounter.server.other.kbytes_out, size);
         }
    +
         if (errflag) {
    -	ErrorState *err;
    -	err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
    -	err->xerrno = errno;
    -	err->host = xstrdup(gopherState->req->host);
    -	err->port = gopherState->req->port;
    -	err->url = xstrdup(storeUrl(entry));
    -	errorAppendEntry(entry, err);
    -	comm_close(fd);
    -	if (buf)
    -	    memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */
    -	return;
    +        ErrorState *err;
    +        err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
    +        err->xerrno = errno;
    +        err->host = xstrdup(gopherState->req->host);
    +        err->port = gopherState->req->port;
    +        err->url = xstrdup(storeUrl(entry));
    +        errorAppendEntry(entry, err);
    +        comm_close(fd);
    +
    +        if (buf)
    +            memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */
    +
    +        return;
         }
    -    /* 
    +
    +    /*
          * OK. We successfully reach remote site.  Start MIME typing
          * stuff.  Do it anyway even though request is not HTML type.
          */
         gopherMimeCreate(gopherState);
    +
         switch (gopherState->type_id) {
    +
         case GOPHER_DIRECTORY:
    -	/* we got to convert it first */
    -	storeBuffer(entry);
    -	gopherState->conversion = gopher_ds::HTML_DIR;
    -	gopherState->HTML_header_added = 0;
    -	break;
    +        /* we got to convert it first */
    +        storeBuffer(entry);
    +        gopherState->conversion = gopher_ds::HTML_DIR;
    +        gopherState->HTML_header_added = 0;
    +        break;
    +
         case GOPHER_INDEX:
    -	/* we got to convert it first */
    -	storeBuffer(entry);
    -	gopherState->conversion = gopher_ds::HTML_INDEX_RESULT;
    -	gopherState->HTML_header_added = 0;
    -	break;
    +        /* we got to convert it first */
    +        storeBuffer(entry);
    +        gopherState->conversion = gopher_ds::HTML_INDEX_RESULT;
    +        gopherState->HTML_header_added = 0;
    +        break;
    +
         case GOPHER_CSO:
    -	/* we got to convert it first */
    -	storeBuffer(entry);
    -	gopherState->conversion = gopher_ds::HTML_CSO_RESULT;
    -	gopherState->cso_recno = 0;
    -	gopherState->HTML_header_added = 0;
    -	break;
    +        /* we got to convert it first */
    +        storeBuffer(entry);
    +        gopherState->conversion = gopher_ds::HTML_CSO_RESULT;
    +        gopherState->cso_recno = 0;
    +        gopherState->HTML_header_added = 0;
    +        break;
    +
         default:
    -	gopherState->conversion = gopher_ds::NORMAL;
    +        gopherState->conversion = gopher_ds::NORMAL;
         }
    +
         /* Schedule read reply. */
         /* XXX this read isn't being bound by delay pools! */
         comm_read(fd, gopherState->replybuf, BUFSIZ, gopherReadReply, gopherState);
    +
         commSetDefer(fd, StoreEntry::CheckDeferRead, entry);
    +
         if (buf)
    -	memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */
    +        memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */
     }
     
     /* This will be called when connect completes. Write request. */
    @@ -781,29 +907,36 @@ gopherSendRequest(int fd, void *data)
     {
         GopherStateData *gopherState = (GopherStateData *)data;
         char *buf = (char *)memAllocate(MEM_4K_BUF);
    +
         if (gopherState->type_id == GOPHER_CSO) {
    -	const char *t = strchr(gopherState->request, '?');
    -	if (t != NULL)
    -	    t++;		/* skip the ? */
    -	else
    -	    t = "";
    -	snprintf(buf, 4096, "query %s\r\nquit\r\n", t);
    +        const char *t = strchr(gopherState->request, '?');
    +
    +        if (t != NULL)
    +            t++;		/* skip the ? */
    +        else
    +            t = "";
    +
    +        snprintf(buf, 4096, "query %s\r\nquit\r\n", t);
         } else if (gopherState->type_id == GOPHER_INDEX) {
    -	char *t = strchr(gopherState->request, '?');
    -	if (t != NULL)
    -	    *t = '\t';
    -	snprintf(buf, 4096, "%s\r\n", gopherState->request);
    +        char *t = strchr(gopherState->request, '?');
    +
    +        if (t != NULL)
    +            *t = '\t';
    +
    +        snprintf(buf, 4096, "%s\r\n", gopherState->request);
         } else {
    -	snprintf(buf, 4096, "%s\r\n", gopherState->request);
    +        snprintf(buf, 4096, "%s\r\n", gopherState->request);
         }
    +
         debug(10, 5) ("gopherSendRequest: FD %d\n", fd);
         comm_write(fd,
    -	buf,
    -	strlen(buf),
    -	gopherSendComplete,
    -	gopherState);
    +               buf,
    +               strlen(buf),
    +               gopherSendComplete,
    +               gopherState);
    +
         if (EBIT_TEST(gopherState->entry->flags, ENTRY_CACHABLE))
    -	storeSetPublicKey(gopherState->entry);	/* Make it public */
    +        storeSetPublicKey(gopherState->entry);	/* Make it public */
     }
     
     CBDATA_TYPE(GopherStateData);
    @@ -825,37 +958,43 @@ gopherStart(FwdState * fwdState)
         statCounter.server.other.requests++;
         /* Parse url. */
         gopher_request_parse(fwdState->request,
    -	&gopherState->type_id, gopherState->request);
    +                         &gopherState->type_id, gopherState->request);
     #if OLD_PARSE_ERROR_CODE
    +
         if (...) {
    -	ErrorState *err;
    -	err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST);
    -	err->url = xstrdup(storeUrl(entry));
    -	errorAppendEntry(entry, err);
    -	gopherStateFree(-1, gopherState);
    -	return;
    +        ErrorState *err;
    +        err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST);
    +        err->url = xstrdup(storeUrl(entry));
    +        errorAppendEntry(entry, err);
    +        gopherStateFree(-1, gopherState);
    +        return;
         }
    +
     #endif
         comm_add_close_handler(fd, gopherStateFree, gopherState);
    +
         if (((gopherState->type_id == GOPHER_INDEX) || (gopherState->type_id == GOPHER_CSO))
    -	&& (strchr(gopherState->request, '?') == NULL)) {
    -	/* Index URL without query word */
    -	/* We have to generate search page back to client. No need for connection */
    -	gopherMimeCreate(gopherState);
    -	if (gopherState->type_id == GOPHER_INDEX) {
    -	    gopherState->conversion = gopher_ds::HTML_INDEX_PAGE;
    -	} else {
    -	    if (gopherState->type_id == GOPHER_CSO) {
    -		gopherState->conversion = gopher_ds::HTML_CSO_PAGE;
    -	    } else {
    -		gopherState->conversion = gopher_ds::HTML_INDEX_PAGE;
    -	    }
    -	}
    -	gopherToHTML(gopherState, (char *) NULL, 0);
    -	fwdComplete(fwdState);
    -	comm_close(fd);
    -	return;
    +            && (strchr(gopherState->request, '?') == NULL)) {
    +        /* Index URL without query word */
    +        /* We have to generate search page back to client. No need for connection */
    +        gopherMimeCreate(gopherState);
    +
    +        if (gopherState->type_id == GOPHER_INDEX) {
    +            gopherState->conversion = gopher_ds::HTML_INDEX_PAGE;
    +        } else {
    +            if (gopherState->type_id == GOPHER_CSO) {
    +                gopherState->conversion = gopher_ds::HTML_CSO_PAGE;
    +            } else {
    +                gopherState->conversion = gopher_ds::HTML_INDEX_PAGE;
    +            }
    +        }
    +
    +        gopherToHTML(gopherState, (char *) NULL, 0);
    +        fwdComplete(fwdState);
    +        comm_close(fd);
    +        return;
         }
    +
         gopherState->fd = fd;
         gopherState->fwdState = fwdState;
         gopherSendRequest(fd, gopherState);
    diff --git a/src/helper.cc b/src/helper.cc
    index 2200dded22..75f9b7b096 100644
    --- a/src/helper.cc
    +++ b/src/helper.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: helper.cc,v 1.56 2003/01/23 00:37:21 robertc Exp $
    + * $Id: helper.cc,v 1.57 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 84    Helper process maintenance
      * AUTHOR: Harvest Derived?
    @@ -75,61 +75,79 @@ helperOpenServers(helper * hlp)
         int rfd;
         int wfd;
         wordlist *w;
    +
         if (hlp->cmdline == NULL)
    -	return;
    +        return;
    +
         progname = hlp->cmdline->key;
    +
         if ((s = strrchr(progname, '/')))
    -	shortname = xstrdup(s + 1);
    +        shortname = xstrdup(s + 1);
         else
    -	shortname = xstrdup(progname);
    +        shortname = xstrdup(progname);
    +
         debug(84, 1) ("helperOpenServers: Starting %d '%s' processes\n",
    -	hlp->n_to_start, shortname);
    +                  hlp->n_to_start, shortname);
    +
         procname = (char *)xmalloc(strlen(shortname) + 3);
    +
         snprintf(procname, strlen(shortname) + 3, "(%s)", shortname);
    +
         args[nargs++] = procname;
    +
         for (w = hlp->cmdline->next; w && nargs < HELPER_MAX_ARGS; w = w->next)
    -	args[nargs++] = w->key;
    +        args[nargs++] = w->key;
    +
         args[nargs++] = NULL;
    +
         assert(nargs <= HELPER_MAX_ARGS);
    +
         for (k = 0; k < hlp->n_to_start; k++) {
    -	getCurrentTime();
    -	rfd = wfd = -1;
    -	x = ipcCreate(hlp->ipc_type,
    -	    progname,
    -	    args,
    -	    shortname,
    -	    &rfd,
    -	    &wfd);
    -	if (x < 0) {
    -	    debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
    -	    continue;
    -	}
    -	hlp->n_running++;
    -	srv = cbdataAlloc(helper_server);
    -	srv->pid = x;
    -	srv->flags.alive = 1;
    -	srv->index = k;
    -	srv->rfd = rfd;
    -	srv->wfd = wfd;
    -	srv->buf = (char *)memAllocate(MEM_8K_BUF);
    -	srv->buf_sz = 8192;
    -	srv->offset = 0;
    -	srv->parent = cbdataReference(hlp);
    -	dlinkAddTail(srv, &srv->link, &hlp->servers);
    -	if (rfd == wfd) {
    -	    snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1);
    -	    fd_note(rfd, fd_note_buf);
    -	} else {
    -	    snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1);
    -	    fd_note(rfd, fd_note_buf);
    -	    snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1);
    -	    fd_note(wfd, fd_note_buf);
    -	}
    -	commSetNonBlocking(rfd);
    -	if (wfd != rfd)
    -	    commSetNonBlocking(wfd);
    -	comm_add_close_handler(rfd, helperServerFree, srv);
    +        getCurrentTime();
    +        rfd = wfd = -1;
    +        x = ipcCreate(hlp->ipc_type,
    +                      progname,
    +                      args,
    +                      shortname,
    +                      &rfd,
    +                      &wfd);
    +
    +        if (x < 0) {
    +            debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
    +            continue;
    +        }
    +
    +        hlp->n_running++;
    +        srv = cbdataAlloc(helper_server);
    +        srv->pid = x;
    +        srv->flags.alive = 1;
    +        srv->index = k;
    +        srv->rfd = rfd;
    +        srv->wfd = wfd;
    +        srv->buf = (char *)memAllocate(MEM_8K_BUF);
    +        srv->buf_sz = 8192;
    +        srv->offset = 0;
    +        srv->parent = cbdataReference(hlp);
    +        dlinkAddTail(srv, &srv->link, &hlp->servers);
    +
    +        if (rfd == wfd) {
    +            snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1);
    +            fd_note(rfd, fd_note_buf);
    +        } else {
    +            snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1);
    +            fd_note(rfd, fd_note_buf);
    +            snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1);
    +            fd_note(wfd, fd_note_buf);
    +        }
    +
    +        commSetNonBlocking(rfd);
    +
    +        if (wfd != rfd)
    +            commSetNonBlocking(wfd);
    +
    +        comm_add_close_handler(rfd, helperServerFree, srv);
         }
    +
         safe_free(shortname);
         safe_free(procname);
         helperKickQueue(hlp);
    @@ -151,69 +169,89 @@ helperStatefulOpenServers(statefulhelper * hlp)
         int rfd;
         int wfd;
         wordlist *w;
    +
         if (hlp->cmdline == NULL)
    -	return;
    +        return;
    +
         progname = hlp->cmdline->key;
    +
         if ((s = strrchr(progname, '/')))
    -	shortname = xstrdup(s + 1);
    +        shortname = xstrdup(s + 1);
         else
    -	shortname = xstrdup(progname);
    +        shortname = xstrdup(progname);
    +
         debug(84, 1) ("helperStatefulOpenServers: Starting %d '%s' processes\n",
    -	hlp->n_to_start, shortname);
    +                  hlp->n_to_start, shortname);
    +
         procname = (char *)xmalloc(strlen(shortname) + 3);
    +
         snprintf(procname, strlen(shortname) + 3, "(%s)", shortname);
    +
         args[nargs++] = procname;
    +
         for (w = hlp->cmdline->next; w && nargs < HELPER_MAX_ARGS; w = w->next)
    -	args[nargs++] = w->key;
    +        args[nargs++] = w->key;
    +
         args[nargs++] = NULL;
    +
         assert(nargs <= HELPER_MAX_ARGS);
    +
         for (k = 0; k < hlp->n_to_start; k++) {
    -	getCurrentTime();
    -	rfd = wfd = -1;
    -	x = ipcCreate(hlp->ipc_type,
    -	    progname,
    -	    args,
    -	    shortname,
    -	    &rfd,
    -	    &wfd);
    -	if (x < 0) {
    -	    debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
    -	    continue;
    -	}
    -	hlp->n_running++;
    -	srv = cbdataAlloc(helper_stateful_server);
    -	srv->pid = x;
    -	srv->flags.alive = 1;
    -	srv->flags.reserved = S_HELPER_FREE;
    -	srv->deferred_requests = 0;
    -	srv->stats.deferbyfunc = 0;
    -	srv->stats.deferbycb = 0;
    -	srv->stats.submits = 0;
    -	srv->stats.releases = 0;
    -	srv->index = k;
    -	srv->rfd = rfd;
    -	srv->wfd = wfd;
    -	srv->buf = (char *)memAllocate(MEM_8K_BUF);
    -	srv->buf_sz = 8192;
    -	srv->offset = 0;
    -	srv->parent = cbdataReference(hlp);
    -	if (hlp->datapool != NULL)
    -	    srv->data = memPoolAlloc(hlp->datapool);
    -	dlinkAddTail(srv, &srv->link, &hlp->servers);
    -	if (rfd == wfd) {
    -	    snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1);
    -	    fd_note(rfd, fd_note_buf);
    -	} else {
    -	    snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1);
    -	    fd_note(rfd, fd_note_buf);
    -	    snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1);
    -	    fd_note(wfd, fd_note_buf);
    -	}
    -	commSetNonBlocking(rfd);
    -	if (wfd != rfd)
    -	    commSetNonBlocking(wfd);
    -	comm_add_close_handler(rfd, helperStatefulServerFree, srv);
    +        getCurrentTime();
    +        rfd = wfd = -1;
    +        x = ipcCreate(hlp->ipc_type,
    +                      progname,
    +                      args,
    +                      shortname,
    +                      &rfd,
    +                      &wfd);
    +
    +        if (x < 0) {
    +            debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
    +            continue;
    +        }
    +
    +        hlp->n_running++;
    +        srv = cbdataAlloc(helper_stateful_server);
    +        srv->pid = x;
    +        srv->flags.alive = 1;
    +        srv->flags.reserved = S_HELPER_FREE;
    +        srv->deferred_requests = 0;
    +        srv->stats.deferbyfunc = 0;
    +        srv->stats.deferbycb = 0;
    +        srv->stats.submits = 0;
    +        srv->stats.releases = 0;
    +        srv->index = k;
    +        srv->rfd = rfd;
    +        srv->wfd = wfd;
    +        srv->buf = (char *)memAllocate(MEM_8K_BUF);
    +        srv->buf_sz = 8192;
    +        srv->offset = 0;
    +        srv->parent = cbdataReference(hlp);
    +
    +        if (hlp->datapool != NULL)
    +            srv->data = memPoolAlloc(hlp->datapool);
    +
    +        dlinkAddTail(srv, &srv->link, &hlp->servers);
    +
    +        if (rfd == wfd) {
    +            snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1);
    +            fd_note(rfd, fd_note_buf);
    +        } else {
    +            snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1);
    +            fd_note(rfd, fd_note_buf);
    +            snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1);
    +            fd_note(wfd, fd_note_buf);
    +        }
    +
    +        commSetNonBlocking(rfd);
    +
    +        if (wfd != rfd)
    +            commSetNonBlocking(wfd);
    +
    +        comm_add_close_handler(rfd, helperStatefulServerFree, srv);
         }
    +
         safe_free(shortname);
         safe_free(procname);
         helperStatefulKickQueue(hlp);
    @@ -225,18 +263,22 @@ helperSubmit(helper * hlp, const char *buf, HLPCB * callback, void *data)
     {
         helper_request *r = (helper_request *)memAllocate(MEM_HELPER_REQUEST);
         helper_server *srv;
    +
         if (hlp == NULL) {
    -	debug(84, 3) ("helperSubmit: hlp == NULL\n");
    -	callback(data, NULL);
    -	return;
    +        debug(84, 3) ("helperSubmit: hlp == NULL\n");
    +        callback(data, NULL);
    +        return;
         }
    +
         r->callback = callback;
         r->data = cbdataReference(data);
         r->buf = xstrdup(buf);
    +
         if ((srv = GetFirstAvailable(hlp)))
    -	helperDispatch(srv, r);
    +        helperDispatch(srv, r);
         else
    -	Enqueue(hlp, r);
    +        Enqueue(hlp, r);
    +
         debug(84, 9) ("helperSubmit: %s\n", buf);
     }
     
    @@ -248,48 +290,55 @@ helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPSCB * callback, v
     {
         helper_stateful_request *r = (helper_stateful_request *)memAllocate(MEM_HELPER_STATEFUL_REQUEST);
         helper_stateful_server *srv;
    +
         if (hlp == NULL) {
    -	debug(84, 3) ("helperStatefulSubmit: hlp == NULL\n");
    -	callback(data, 0, NULL);
    -	return;
    +        debug(84, 3) ("helperStatefulSubmit: hlp == NULL\n");
    +        callback(data, 0, NULL);
    +        return;
         }
    +
         r->callback = callback;
         r->data = cbdataReference(data);
    +
         if (buf != NULL) {
    -	r->buf = xstrdup(buf);
    -	r->placeholder = 0;
    +        r->buf = xstrdup(buf);
    +        r->placeholder = 0;
         } else {
    -	r->buf = NULL;
    -	r->placeholder = 1;
    +        r->buf = NULL;
    +        r->placeholder = 1;
         }
    +
         if ((buf != NULL) && lastserver) {
    -	debug(84, 5) ("StatefulSubmit with lastserver %p\n", lastserver);
    -	/* the queue doesn't count for this assert because queued requests
    -	 * have already gone through here and been tested.
    -	 * It's legal to have deferred_requests == 0 and queue entries 
    -	 * and status of S_HELPEER_DEFERRED.
    -	 * BUT:  It's not legal to submit a new request w/lastserver in
    -	 * that state.
    -	 */
    -	assert(!(lastserver->deferred_requests == 0 &&
    -		lastserver->flags.reserved == S_HELPER_DEFERRED));
    -	if (lastserver->flags.reserved != S_HELPER_RESERVED) {
    -	    lastserver->stats.submits++;
    -	    lastserver->deferred_requests--;
    -	}
    -	if (!(lastserver->request)) {
    -	    debug(84, 5) ("StatefulSubmit dispatching\n");
    -	    helperStatefulDispatch(lastserver, r);
    -	} else {
    -	    debug(84, 5) ("StatefulSubmit queuing\n");
    -	    StatefulServerEnqueue(lastserver, r);
    -	}
    +        debug(84, 5) ("StatefulSubmit with lastserver %p\n", lastserver);
    +        /* the queue doesn't count for this assert because queued requests
    +         * have already gone through here and been tested.
    +         * It's legal to have deferred_requests == 0 and queue entries 
    +         * and status of S_HELPEER_DEFERRED.
    +         * BUT:  It's not legal to submit a new request w/lastserver in
    +         * that state.
    +         */
    +        assert(!(lastserver->deferred_requests == 0 &&
    +                 lastserver->flags.reserved == S_HELPER_DEFERRED));
    +
    +        if (lastserver->flags.reserved != S_HELPER_RESERVED) {
    +            lastserver->stats.submits++;
    +            lastserver->deferred_requests--;
    +        }
    +
    +        if (!(lastserver->request)) {
    +            debug(84, 5) ("StatefulSubmit dispatching\n");
    +            helperStatefulDispatch(lastserver, r);
    +        } else {
    +            debug(84, 5) ("StatefulSubmit queuing\n");
    +            StatefulServerEnqueue(lastserver, r);
    +        }
         } else {
    -	if ((srv = StatefulGetFirstAvailable(hlp))) {
    -	    helperStatefulDispatch(srv, r);
    -	} else
    -	    StatefulEnqueue(hlp, r);
    +        if ((srv = StatefulGetFirstAvailable(hlp))) {
    +            helperStatefulDispatch(srv, r);
    +        } else
    +            StatefulEnqueue(hlp, r);
         }
    +
         debug(84, 9) ("helperStatefulSubmit: placeholder: '%d', buf '%s'.\n", r->placeholder, buf);
     }
     
    @@ -299,39 +348,56 @@ helperStatefulDefer(statefulhelper * hlp)
     {
         dlink_node *n;
         helper_stateful_server *srv = NULL, *rv = NULL;
    -    if (hlp == NULL) {
    -	debug(84, 3) ("helperStatefulDefer: hlp == NULL\n");
    -	return NULL;
    +
    +    if (hlp == NULL)
    +    {
    +        debug(84, 3) ("helperStatefulDefer: hlp == NULL\n");
    +        return NULL;
         }
    +
         debug(84, 5) ("helperStatefulDefer: Running servers %d.\n", hlp->n_running);
    -    if (hlp->n_running == 0) {
    -	debug(84, 1) ("helperStatefulDefer: No running servers!. \n");
    -	return NULL;
    +
    +    if (hlp->n_running == 0)
    +    {
    +        debug(84, 1) ("helperStatefulDefer: No running servers!. \n");
    +        return NULL;
         }
    +
         rv = srv = StatefulGetFirstAvailable(hlp);
    -    if (rv == NULL) {
    -	/*
    -	 * all currently busy; loop through servers and find server
    -	 * with the shortest queue
    -	 */
    -	for (n = hlp->servers.head; n != NULL; n = n->next) {
    -	    srv = (helper_stateful_server *)n->data;
    -	    if (srv->flags.reserved == S_HELPER_RESERVED)
    -		continue;
    -	    if (!srv->flags.alive)
    -		continue;
    -	    if ((hlp->IsAvailable != NULL) && (srv->data != NULL) &&
    -		!(hlp->IsAvailable(srv->data)))
    -		continue;
    -	    if ((rv != NULL) && (rv->deferred_requests < srv->deferred_requests))
    -		continue;
    -	    rv = srv;
    -	}
    +
    +    if (rv == NULL)
    +    {
    +        /*
    +         * all currently busy; loop through servers and find server
    +         * with the shortest queue
    +         */
    +
    +        for (n = hlp->servers.head; n != NULL; n = n->next) {
    +            srv = (helper_stateful_server *)n->data;
    +
    +            if (srv->flags.reserved == S_HELPER_RESERVED)
    +                continue;
    +
    +            if (!srv->flags.alive)
    +                continue;
    +
    +            if ((hlp->IsAvailable != NULL) && (srv->data != NULL) &&
    +                    !(hlp->IsAvailable(srv->data)))
    +                continue;
    +
    +            if ((rv != NULL) && (rv->deferred_requests < srv->deferred_requests))
    +                continue;
    +
    +            rv = srv;
    +        }
         }
    -    if (rv == NULL) {
    -	debug(84, 1) ("helperStatefulDefer: None available.\n");
    -	return NULL;
    +
    +    if (rv == NULL)
    +    {
    +        debug(84, 1) ("helperStatefulDefer: None available.\n");
    +        return NULL;
         }
    +
         /* consistency check:
          * when the deferred count is 0,
          *   submits + releases == deferbyfunc + deferbycb
    @@ -340,42 +406,53 @@ helperStatefulDefer(statefulhelper * hlp)
          * we have said we wanted to be able to submit or cancel
          */
         if (rv->deferred_requests == 0)
    -	assert(rv->stats.submits + rv->stats.releases ==
    -	    rv->stats.deferbyfunc + rv->stats.deferbycb);
    +        assert(rv->stats.submits + rv->stats.releases ==
    +               rv->stats.deferbyfunc + rv->stats.deferbycb);
     
         rv->flags.reserved = S_HELPER_DEFERRED;
    +
         rv->deferred_requests++;
    +
         rv->stats.deferbyfunc++;
    +
         return rv;
     }
     
     void
     helperStatefulReset(helper_stateful_server * srv)
    -/* puts this helper back in the queue. the calling app is required to 
    +/* puts this helper back in the queue. the calling app is required to
      * manage the state in the helper.
      */
     {
         statefulhelper *hlp = srv->parent;
         helper_stateful_request *r;
         r = srv->request;
    -    if (r != NULL) {
    -	/* reset attempt DURING an outstaning request */
    -	debug(84, 1) ("helperStatefulReset: RESET During request %s \n",
    -	    hlp->id_name);
    -	srv->flags.busy = 0;
    -	srv->offset = 0;
    -	helperStatefulRequestFree(r);
    -	srv->request = NULL;
    +
    +    if (r != NULL)
    +    {
    +        /* reset attempt DURING an outstaning request */
    +        debug(84, 1) ("helperStatefulReset: RESET During request %s \n",
    +                      hlp->id_name);
    +        srv->flags.busy = 0;
    +        srv->offset = 0;
    +        helperStatefulRequestFree(r);
    +        srv->request = NULL;
         }
    +
         srv->flags.busy = 0;
    -    if (srv->queue.head) {
    -	srv->flags.reserved = S_HELPER_DEFERRED;
    -	helperStatefulServerKickQueue(srv);
    -    } else {
    -	srv->flags.reserved = S_HELPER_FREE;
    -	if ((srv->parent->OnEmptyQueue != NULL) && (srv->data))
    -	    srv->parent->OnEmptyQueue(srv->data);
    -	helperStatefulKickQueue(hlp);
    +
    +    if (srv->queue.head)
    +    {
    +        srv->flags.reserved = S_HELPER_DEFERRED;
    +        helperStatefulServerKickQueue(srv);
    +    } else
    +    {
    +        srv->flags.reserved = S_HELPER_FREE;
    +
    +        if ((srv->parent->OnEmptyQueue != NULL) && (srv->data))
    +            srv->parent->OnEmptyQueue(srv->data);
    +
    +        helperStatefulKickQueue(hlp);
         }
     }
     
    @@ -384,14 +461,19 @@ helperStatefulReleaseServer(helper_stateful_server * srv)
     /*decrease the number of 'waiting' clients that set the helper to be DEFERRED */
     {
         srv->stats.releases++;
    -    if (srv->flags.reserved == S_HELPER_DEFERRED) {
    -	assert(srv->deferred_requests);
    -	srv->deferred_requests--;
    +
    +    if (srv->flags.reserved == S_HELPER_DEFERRED)
    +    {
    +        assert(srv->deferred_requests);
    +        srv->deferred_requests--;
         }
    -    if (!(srv->deferred_requests) && (srv->flags.reserved == S_HELPER_DEFERRED) && !(srv->queue.head)) {
    -	srv->flags.reserved = S_HELPER_FREE;
    -	if ((srv->parent->OnEmptyQueue != NULL) && (srv->data))
    -	    srv->parent->OnEmptyQueue(srv->data);
    +
    +    if (!(srv->deferred_requests) && (srv->flags.reserved == S_HELPER_DEFERRED) && !(srv->queue.head))
    +    {
    +        srv->flags.reserved = S_HELPER_FREE;
    +
    +        if ((srv->parent->OnEmptyQueue != NULL) && (srv->data))
    +            srv->parent->OnEmptyQueue(srv->data);
         }
     }
     
    @@ -409,44 +491,46 @@ helperStats(StoreEntry * sentry, helper * hlp)
         dlink_node *link;
         double tt;
         storeAppendPrintf(sentry, "program: %s\n",
    -	hlp->cmdline->key);
    +                      hlp->cmdline->key);
         storeAppendPrintf(sentry, "number running: %d of %d\n",
    -	hlp->n_running, hlp->n_to_start);
    +                      hlp->n_running, hlp->n_to_start);
         storeAppendPrintf(sentry, "requests sent: %d\n",
    -	hlp->stats.requests);
    +                      hlp->stats.requests);
         storeAppendPrintf(sentry, "replies received: %d\n",
    -	hlp->stats.replies);
    +                      hlp->stats.replies);
         storeAppendPrintf(sentry, "queue length: %d\n",
    -	hlp->stats.queue_size);
    +                      hlp->stats.queue_size);
         storeAppendPrintf(sentry, "avg service time: %.2f msec\n",
    -	(double) hlp->stats.avg_svc_time / 1000.0);
    +                      (double) hlp->stats.avg_svc_time / 1000.0);
         storeAppendPrintf(sentry, "\n");
         storeAppendPrintf(sentry, "%7s\t%7s\t%7s\t%11s\t%s\t%7s\t%7s\t%7s\n",
    -	"#",
    -	"FD",
    -	"PID",
    -	"# Requests",
    -	"Flags",
    -	"Time",
    -	"Offset",
    -	"Request");
    +                      "#",
    +                      "FD",
    +                      "PID",
    +                      "# Requests",
    +                      "Flags",
    +                      "Time",
    +                      "Offset",
    +                      "Request");
    +
         for (link = hlp->servers.head; link; link = link->next) {
    -	srv = (helper_server*)link->data;
    -	tt = 0.001 * tvSubMsec(srv->dispatch_time,
    -	    srv->flags.busy ? current_time : srv->answer_time);
    -	storeAppendPrintf(sentry, "%7d\t%7d\t%7d\t%11d\t%c%c%c%c\t%7.3f\t%7d\t%s\n",
    -	    srv->index + 1,
    -	    srv->rfd,
    -	    srv->pid,
    -	    srv->stats.uses,
    -	    srv->flags.alive ? 'A' : ' ',
    -	    srv->flags.busy ? 'B' : ' ',
    -	    srv->flags.closing ? 'C' : ' ',
    -	    srv->flags.shutdown ? 'S' : ' ',
    -	    tt < 0.0 ? 0.0 : tt,
    -	    (int) srv->offset,
    -	    srv->request ? log_quote(srv->request->buf) : "(none)");
    +        srv = (helper_server*)link->data;
    +        tt = 0.001 * tvSubMsec(srv->dispatch_time,
    +                               srv->flags.busy ? current_time : srv->answer_time);
    +        storeAppendPrintf(sentry, "%7d\t%7d\t%7d\t%11d\t%c%c%c%c\t%7.3f\t%7d\t%s\n",
    +                          srv->index + 1,
    +                          srv->rfd,
    +                          srv->pid,
    +                          srv->stats.uses,
    +                          srv->flags.alive ? 'A' : ' ',
    +                          srv->flags.busy ? 'B' : ' ',
    +                          srv->flags.closing ? 'C' : ' ',
    +                          srv->flags.shutdown ? 'S' : ' ',
    +                          tt < 0.0 ? 0.0 : tt,
    +                          (int) srv->offset,
    +                          srv->request ? log_quote(srv->request->buf) : "(none)");
         }
    +
         storeAppendPrintf(sentry, "\nFlags key:\n\n");
         storeAppendPrintf(sentry, "   A = ALIVE\n");
         storeAppendPrintf(sentry, "   B = BUSY\n");
    @@ -461,45 +545,47 @@ helperStatefulStats(StoreEntry * sentry, statefulhelper * hlp)
         dlink_node *link;
         double tt;
         storeAppendPrintf(sentry, "number running: %d of %d\n",
    -	hlp->n_running, hlp->n_to_start);
    +                      hlp->n_running, hlp->n_to_start);
         storeAppendPrintf(sentry, "requests sent: %d\n",
    -	hlp->stats.requests);
    +                      hlp->stats.requests);
         storeAppendPrintf(sentry, "replies received: %d\n",
    -	hlp->stats.replies);
    +                      hlp->stats.replies);
         storeAppendPrintf(sentry, "queue length: %d\n",
    -	hlp->stats.queue_size);
    +                      hlp->stats.queue_size);
         storeAppendPrintf(sentry, "avg service time: %d msec\n",
    -	hlp->stats.avg_svc_time);
    +                      hlp->stats.avg_svc_time);
         storeAppendPrintf(sentry, "\n");
         storeAppendPrintf(sentry, "%7s\t%7s\t%7s\t%11s\t%20s\t%s\t%7s\t%7s\t%7s\n",
    -	"#",
    -	"FD",
    -	"PID",
    -	"# Requests",
    -	"# Deferred Requests",
    -	"Flags",
    -	"Time",
    -	"Offset",
    -	"Request");
    +                      "#",
    +                      "FD",
    +                      "PID",
    +                      "# Requests",
    +                      "# Deferred Requests",
    +                      "Flags",
    +                      "Time",
    +                      "Offset",
    +                      "Request");
    +
         for (link = hlp->servers.head; link; link = link->next) {
    -	srv = (helper_stateful_server *)link->data;
    -	tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time);
    -	storeAppendPrintf(sentry, "%7d\t%7d\t%7d\t%11d\t%20d\t%c%c%c%c%c%c\t%7.3f\t%7d\t%s\n",
    -	    srv->index + 1,
    -	    srv->rfd,
    -	    srv->pid,
    -	    srv->stats.uses,
    -	    (int) srv->deferred_requests,
    -	    srv->flags.alive ? 'A' : ' ',
    -	    srv->flags.busy ? 'B' : ' ',
    -	    srv->flags.closing ? 'C' : ' ',
    -	    srv->flags.reserved != S_HELPER_FREE ? 'R' : ' ',
    -	    srv->flags.shutdown ? 'S' : ' ',
    -	    srv->request ? (srv->request->placeholder ? 'P' : ' ') : ' ',
    -	    tt < 0.0 ? 0.0 : tt,
    -	    (int) srv->offset,
    -	    srv->request ? log_quote(srv->request->buf) : "(none)");
    +        srv = (helper_stateful_server *)link->data;
    +        tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time);
    +        storeAppendPrintf(sentry, "%7d\t%7d\t%7d\t%11d\t%20d\t%c%c%c%c%c%c\t%7.3f\t%7d\t%s\n",
    +                          srv->index + 1,
    +                          srv->rfd,
    +                          srv->pid,
    +                          srv->stats.uses,
    +                          (int) srv->deferred_requests,
    +                          srv->flags.alive ? 'A' : ' ',
    +                          srv->flags.busy ? 'B' : ' ',
    +                          srv->flags.closing ? 'C' : ' ',
    +                          srv->flags.reserved != S_HELPER_FREE ? 'R' : ' ',
    +                          srv->flags.shutdown ? 'S' : ' ',
    +                          srv->request ? (srv->request->placeholder ? 'P' : ' ') : ' ',
    +                                  tt < 0.0 ? 0.0 : tt,
    +                                  (int) srv->offset,
    +                                  srv->request ? log_quote(srv->request->buf) : "(none)");
         }
    +
         storeAppendPrintf(sentry, "\nFlags key:\n\n");
         storeAppendPrintf(sentry, "   A = ALIVE\n");
         storeAppendPrintf(sentry, "   B = BUSY\n");
    @@ -513,31 +599,37 @@ void
     helperShutdown(helper * hlp)
     {
         dlink_node *link = hlp->servers.head;
    +
         while (link) {
    -	helper_server *srv;
    -	srv = (helper_server *)link->data;
    -	link = link->next;
    -	if (!srv->flags.alive) {
    -	    debug(84, 3) ("helperShutdown: %s #%d is NOT ALIVE.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	srv->flags.shutdown = 1;	/* request it to shut itself down */
    -	if (srv->flags.busy) {
    -	    debug(84, 3) ("helperShutdown: %s #%d is BUSY.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	if (srv->flags.closing) {
    -	    debug(84, 3) ("helperShutdown: %s #%d is CLOSING.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	srv->flags.closing = 1;
    -	/* the rest of the details is dealt with in the helperServerFree
    -	 * close handler
    -	 */
    -	comm_close(srv->rfd);
    +        helper_server *srv;
    +        srv = (helper_server *)link->data;
    +        link = link->next;
    +
    +        if (!srv->flags.alive) {
    +            debug(84, 3) ("helperShutdown: %s #%d is NOT ALIVE.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        srv->flags.shutdown = 1;	/* request it to shut itself down */
    +
    +        if (srv->flags.busy) {
    +            debug(84, 3) ("helperShutdown: %s #%d is BUSY.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        if (srv->flags.closing) {
    +            debug(84, 3) ("helperShutdown: %s #%d is CLOSING.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        srv->flags.closing = 1;
    +        /* the rest of the details is dealt with in the helperServerFree
    +         * close handler
    +         */
    +        comm_close(srv->rfd);
         }
     }
     
    @@ -546,40 +638,48 @@ helperStatefulShutdown(statefulhelper * hlp)
     {
         dlink_node *link = hlp->servers.head;
         helper_stateful_server *srv;
    +
         while (link) {
    -	srv = (helper_stateful_server *)link->data;
    -	link = link->next;
    -	if (!srv->flags.alive) {
    -	    debug(84, 3) ("helperStatefulShutdown: %s #%d is NOT ALIVE.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	srv->flags.shutdown = 1;	/* request it to shut itself down */
    -	if (srv->flags.busy) {
    -	    debug(84, 3) ("helperStatefulShutdown: %s #%d is BUSY.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	if (srv->flags.closing) {
    -	    debug(84, 3) ("helperStatefulShutdown: %s #%d is CLOSING.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	if (srv->flags.reserved != S_HELPER_FREE) {
    -	    debug(84, 3) ("helperStatefulShutdown: %s #%d is RESERVED.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	if (srv->deferred_requests) {
    -	    debug(84, 3) ("helperStatefulShutdown: %s #%d has DEFERRED requests.\n",
    -		hlp->id_name, srv->index + 1);
    -	    continue;
    -	}
    -	srv->flags.closing = 1;
    -	/* the rest of the details is dealt with in the helperStatefulServerFree
    -	 * close handler
    -	 */
    -	comm_close(srv->rfd);
    +        srv = (helper_stateful_server *)link->data;
    +        link = link->next;
    +
    +        if (!srv->flags.alive) {
    +            debug(84, 3) ("helperStatefulShutdown: %s #%d is NOT ALIVE.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        srv->flags.shutdown = 1;	/* request it to shut itself down */
    +
    +        if (srv->flags.busy) {
    +            debug(84, 3) ("helperStatefulShutdown: %s #%d is BUSY.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        if (srv->flags.closing) {
    +            debug(84, 3) ("helperStatefulShutdown: %s #%d is CLOSING.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        if (srv->flags.reserved != S_HELPER_FREE) {
    +            debug(84, 3) ("helperStatefulShutdown: %s #%d is RESERVED.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        if (srv->deferred_requests) {
    +            debug(84, 3) ("helperStatefulShutdown: %s #%d has DEFERRED requests.\n",
    +                          hlp->id_name, srv->index + 1);
    +            continue;
    +        }
    +
    +        srv->flags.closing = 1;
    +        /* the rest of the details is dealt with in the helperStatefulServerFree
    +         * close handler
    +         */
    +        comm_close(srv->rfd);
         }
     }
     
    @@ -607,11 +707,13 @@ void
     helperFree(helper * hlp)
     {
         if (!hlp)
    -	return;
    +        return;
    +
         /* note, don't free hlp->name, it probably points to static memory */
         if (hlp->queue.head)
    -	debug(84, 0) ("WARNING: freeing %s helper with %d requests queued\n",
    -	    hlp->id_name, hlp->stats.queue_size);
    +        debug(84, 0) ("WARNING: freeing %s helper with %d requests queued\n",
    +                      hlp->id_name, hlp->stats.queue_size);
    +
         cbdataFree(hlp);
     }
     
    @@ -619,11 +721,13 @@ void
     helperStatefulFree(statefulhelper * hlp)
     {
         if (!hlp)
    -	return;
    +        return;
    +
         /* note, don't free hlp->name, it probably points to static memory */
         if (hlp->queue.head)
    -	debug(84, 0) ("WARNING: freeing %s helper with %d requests queued\n",
    -	    hlp->id_name, hlp->stats.queue_size);
    +        debug(84, 0) ("WARNING: freeing %s helper with %d requests queued\n",
    +                      hlp->id_name, hlp->stats.queue_size);
    +
         cbdataFree(hlp);
     }
     
    @@ -639,28 +743,40 @@ helperServerFree(int fd, void *data)
         helper *hlp = srv->parent;
         helper_request *r;
         assert(srv->rfd == fd);
    +
         if (srv->buf) {
    -	memFree(srv->buf, MEM_8K_BUF);
    -	srv->buf = NULL;
    +        memFree(srv->buf, MEM_8K_BUF);
    +        srv->buf = NULL;
         }
    +
         if ((r = srv->request)) {
    -	void *cbdata;
    -	if (cbdataReferenceValidDone(r->data, &cbdata))
    -	    r->callback(cbdata, srv->buf);
    -	helperRequestFree(r);
    -	srv->request = NULL;
    +        void *cbdata;
    +
    +        if (cbdataReferenceValidDone(r->data, &cbdata))
    +            r->callback(cbdata, srv->buf);
    +
    +        helperRequestFree(r);
    +
    +        srv->request = NULL;
         }
    +
         if (srv->wfd != srv->rfd && srv->wfd != -1)
    -	comm_close(srv->wfd);
    +        comm_close(srv->wfd);
    +
         dlinkDelete(&srv->link, &hlp->servers);
    +
         hlp->n_running--;
    +
         assert(hlp->n_running >= 0);
    +
         if (!srv->flags.shutdown) {
    -	debug(84, 0) ("WARNING: %s #%d (FD %d) exited\n",
    -	    hlp->id_name, srv->index + 1, fd);
    -	if (hlp->n_running < hlp->n_to_start / 2)
    -	    fatalf("Too few %s processes are running", hlp->id_name);
    +        debug(84, 0) ("WARNING: %s #%d (FD %d) exited\n",
    +                      hlp->id_name, srv->index + 1, fd);
    +
    +        if (hlp->n_running < hlp->n_to_start / 2)
    +            fatalf("Too few %s processes are running", hlp->id_name);
         }
    +
         cbdataReferenceDone(srv->parent);
         cbdataFree(srv);
     }
    @@ -672,32 +788,46 @@ helperStatefulServerFree(int fd, void *data)
         statefulhelper *hlp = srv->parent;
         helper_stateful_request *r;
         assert(srv->rfd == fd);
    +
         if (srv->buf) {
    -	memFree(srv->buf, MEM_8K_BUF);
    -	srv->buf = NULL;
    +        memFree(srv->buf, MEM_8K_BUF);
    +        srv->buf = NULL;
         }
    +
         if ((r = srv->request)) {
    -	void *cbdata;
    -	if (cbdataReferenceValidDone(r->data, &cbdata))
    -	    r->callback(cbdata, srv, srv->buf);
    -	helperStatefulRequestFree(r);
    -	srv->request = NULL;
    +        void *cbdata;
    +
    +        if (cbdataReferenceValidDone(r->data, &cbdata))
    +            r->callback(cbdata, srv, srv->buf);
    +
    +        helperStatefulRequestFree(r);
    +
    +        srv->request = NULL;
         }
    +
         /* TODO: walk the local queue of requests and carry them all out */
         if (srv->wfd != srv->rfd && srv->wfd != -1)
    -	comm_close(srv->wfd);
    +        comm_close(srv->wfd);
    +
         dlinkDelete(&srv->link, &hlp->servers);
    +
         hlp->n_running--;
    +
         assert(hlp->n_running >= 0);
    +
         if (!srv->flags.shutdown) {
    -	debug(84, 0) ("WARNING: %s #%d (FD %d) exited\n",
    -	    hlp->id_name, srv->index + 1, fd);
    -	if (hlp->n_running < hlp->n_to_start / 2)
    -	    fatalf("Too few %s processes are running", hlp->id_name);
    +        debug(84, 0) ("WARNING: %s #%d (FD %d) exited\n",
    +                      hlp->id_name, srv->index + 1, fd);
    +
    +        if (hlp->n_running < hlp->n_to_start / 2)
    +            fatalf("Too few %s processes are running", hlp->id_name);
         }
    +
         if (srv->data != NULL)
    -	memPoolFree(hlp->datapool, srv->data);
    +        memPoolFree(hlp->datapool, srv->data);
    +
         cbdataReferenceDone(srv->parent);
    +
         cbdataFree(srv);
     }
     
    @@ -713,53 +843,68 @@ helperHandleRead(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, voi
         assert(cbdataReferenceValid(data));
     
         /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
    +
         if (flag == COMM_ERR_CLOSING) {
             return;
         }
     
         debug(84, 5) ("helperHandleRead: %d bytes from %s #%d.\n",
    -	(int)len, hlp->id_name, srv->index + 1);
    +                  (int)len, hlp->id_name, srv->index + 1);
    +
         if (flag != COMM_OK || len <= 0) {
    -	if (len < 0)
    -	    debug(84, 1) ("helperHandleRead: FD %d read: %s\n", fd, xstrerror());
    -	comm_close(fd);
    -	return;
    +        if (len < 0)
    +            debug(84, 1) ("helperHandleRead: FD %d read: %s\n", fd, xstrerror());
    +
    +        comm_close(fd);
    +
    +        return;
         }
    +
         srv->offset += len;
         srv->buf[srv->offset] = '\0';
         debug(84, 9) ("helperHandleRead: '%s'\n", srv->buf);
         r = srv->request;
    +
         if (r == NULL) {
    -	/* someone spoke without being spoken to */
    -	debug(84, 1) ("helperHandleRead: unexpected read from %s #%d, %d bytes\n",
    -	    hlp->id_name, srv->index + 1, (int)len);
    -	srv->offset = 0;
    +        /* someone spoke without being spoken to */
    +        debug(84, 1) ("helperHandleRead: unexpected read from %s #%d, %d bytes\n",
    +                      hlp->id_name, srv->index + 1, (int)len);
    +        srv->offset = 0;
         } else if ((t = strchr(srv->buf, '\n'))) {
    -	/* end of reply found */
    -	HLPCB *callback;
    -	void *cbdata;
    -	debug(84, 3) ("helperHandleRead: end of reply found\n");
    -	*t = '\0';
    -	callback = r->callback;
    -	r->callback = NULL;
    -	if (cbdataReferenceValidDone(r->data, &cbdata))
    -	    callback(cbdata, srv->buf);
    -	srv->flags.busy = 0;
    -	srv->offset = 0;
    -	helperRequestFree(r);
    -	srv->request = NULL;
    -	hlp->stats.replies++;
    -	srv->answer_time = current_time;
    -	hlp->stats.avg_svc_time =
    -	    intAverage(hlp->stats.avg_svc_time,
    -	    tvSubUsec(srv->dispatch_time, current_time),
    -	    hlp->stats.replies, REDIRECT_AV_FACTOR);
    -	if (srv->flags.shutdown) {
    -	    int wfd = srv->wfd;
    -	    srv->wfd = -1;
    -	    comm_close(wfd);
    -	} else
    -	    helperKickQueue(hlp);
    +        /* end of reply found */
    +        HLPCB *callback;
    +        void *cbdata;
    +        debug(84, 3) ("helperHandleRead: end of reply found\n");
    +        *t = '\0';
    +        callback = r->callback;
    +        r->callback = NULL;
    +
    +        if (cbdataReferenceValidDone(r->data, &cbdata))
    +            callback(cbdata, srv->buf);
    +
    +        srv->flags.busy = 0;
    +
    +        srv->offset = 0;
    +
    +        helperRequestFree(r);
    +
    +        srv->request = NULL;
    +
    +        hlp->stats.replies++;
    +
    +        srv->answer_time = current_time;
    +
    +        hlp->stats.avg_svc_time =
    +            intAverage(hlp->stats.avg_svc_time,
    +                       tvSubUsec(srv->dispatch_time, current_time),
    +                       hlp->stats.replies, REDIRECT_AV_FACTOR);
    +
    +        if (srv->flags.shutdown) {
    +            int wfd = srv->wfd;
    +            srv->wfd = -1;
    +            comm_close(wfd);
    +        } else
    +            helperKickQueue(hlp);
         } else {
             comm_read(fd, srv->buf + srv->offset, srv->buf_sz - srv->offset, helperHandleRead, data);
         }
    @@ -776,95 +921,115 @@ helperStatefulHandleRead(int fd, char *buf, size_t len, comm_err_t flag, int xer
         assert(cbdataReferenceValid(data));
     
         /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
    +
         if (flag == COMM_ERR_CLOSING) {
             return;
         }
     
         debug(84, 5) ("helperStatefulHandleRead: %d bytes from %s #%d.\n",
    -	(int)len, hlp->id_name, srv->index + 1);
    +                  (int)len, hlp->id_name, srv->index + 1);
    +
         if (flag != COMM_OK || len <= 0) {
    -	if (len < 0)
    -	    debug(84, 1) ("helperStatefulHandleRead: FD %d read: %s\n", fd, xstrerror());
    -	comm_close(fd);
    -	return;
    +        if (len < 0)
    +            debug(84, 1) ("helperStatefulHandleRead: FD %d read: %s\n", fd, xstrerror());
    +
    +        comm_close(fd);
    +
    +        return;
         }
    +
         srv->offset += len;
         srv->buf[srv->offset] = '\0';
         r = srv->request;
    +
         if (r == NULL) {
    -	/* someone spoke without being spoken to */
    -	debug(84, 1) ("helperStatefulHandleRead: unexpected read from %s #%d, %d bytes\n",
    -	    hlp->id_name, srv->index + 1, (int)len);
    -	srv->offset = 0;
    +        /* someone spoke without being spoken to */
    +        debug(84, 1) ("helperStatefulHandleRead: unexpected read from %s #%d, %d bytes\n",
    +                      hlp->id_name, srv->index + 1, (int)len);
    +        srv->offset = 0;
         } else if ((t = strchr(srv->buf, '\n'))) {
    -	/* end of reply found */
    -	debug(84, 3) ("helperStatefulHandleRead: end of reply found\n");
    -	*t = '\0';
    -	if (cbdataReferenceValid(r->data)) {
    -	    switch ((r->callback(r->data, srv, srv->buf))) {	/*if non-zero reserve helper */
    -	    case S_HELPER_UNKNOWN:
    -		fatal("helperStatefulHandleRead: either a non-state aware callback was give to the stateful helper routines, or an uninitialised callback response was recieved.\n");
    -		break;
    -	    case S_HELPER_RELEASE:	/* helper finished with */
    -		if (!srv->deferred_requests && !srv->queue.head) {
    -		    srv->flags.reserved = S_HELPER_FREE;
    -		    if ((srv->parent->OnEmptyQueue != NULL) && (srv->data))
    -			srv->parent->OnEmptyQueue(srv->data);
    -		    debug(84, 5) ("StatefulHandleRead: releasing %s #%d\n", hlp->id_name, srv->index + 1);
    -		} else {
    -		    srv->flags.reserved = S_HELPER_DEFERRED;
    -		    debug(84, 5) ("StatefulHandleRead: outstanding deferred requests on %s #%d. reserving for deferred requests.\n", hlp->id_name, srv->index + 1);
    -		}
    -		break;
    -	    case S_HELPER_RESERVE:	/* 'pin' this helper for the caller */
    -		if (!srv->queue.head) {
    -		    assert(srv->deferred_requests == 0);
    -		    srv->flags.reserved = S_HELPER_RESERVED;
    -		    debug(84, 5) ("StatefulHandleRead: reserving %s #%d\n", hlp->id_name, srv->index + 1);
    -		} else {
    -		    fatal("StatefulHandleRead: Callback routine attempted to reserve a stateful helper with deferred requests. This can lead to deadlock.\n");
    -		}
    -		break;
    -	    case S_HELPER_DEFER:
    -		/* the helper is still needed, but can
    -		 * be used for other requests in the meantime.
    -		 */
    -		srv->flags.reserved = S_HELPER_DEFERRED;
    -		srv->deferred_requests++;
    -		srv->stats.deferbycb++;
    -		debug(84, 5) ("StatefulHandleRead: reserving %s #%d for deferred requests.\n", hlp->id_name, srv->index + 1);
    -		break;
    -	    default:
    -		fatal("helperStatefulHandleRead: unknown stateful helper callback result.\n");
    -	    }
    -
    -	} else {
    -	    debug(84, 1) ("StatefulHandleRead: no callback data registered\n");
    -	}
    -	srv->flags.busy = 0;
    -	srv->offset = 0;
    -	helperStatefulRequestFree(r);
    -	srv->request = NULL;
    -	hlp->stats.replies++;
    -	hlp->stats.avg_svc_time =
    -	    intAverage(hlp->stats.avg_svc_time,
    -	    tvSubMsec(srv->dispatch_time, current_time),
    -	    hlp->stats.replies, REDIRECT_AV_FACTOR);
    -	if (srv->flags.shutdown
    -	    && srv->flags.reserved == S_HELPER_FREE
    -	    && !srv->deferred_requests) {
    -	    int wfd = srv->wfd;
    -	    srv->wfd = -1;
    -	    comm_close(wfd);
    -	} else {
    -	    if (srv->queue.head)
    -		helperStatefulServerKickQueue(srv);
    -	    else
    -		helperStatefulKickQueue(hlp);
    -	}
    +        /* end of reply found */
    +        debug(84, 3) ("helperStatefulHandleRead: end of reply found\n");
    +        *t = '\0';
    +
    +        if (cbdataReferenceValid(r->data)) {
    +            switch ((r->callback(r->data, srv, srv->buf))) {	/*if non-zero reserve helper */
    +
    +            case S_HELPER_UNKNOWN:
    +                    fatal("helperStatefulHandleRead: either a non-state aware callback was give to the stateful helper routines, or an uninitialised callback response was recieved.\n");
    +                break;
    +
    +            case S_HELPER_RELEASE:	/* helper finished with */
    +
    +                if (!srv->deferred_requests && !srv->queue.head) {
    +                    srv->flags.reserved = S_HELPER_FREE;
    +
    +                    if ((srv->parent->OnEmptyQueue != NULL) && (srv->data))
    +                        srv->parent->OnEmptyQueue(srv->data);
    +
    +                    debug(84, 5) ("StatefulHandleRead: releasing %s #%d\n", hlp->id_name, srv->index + 1);
    +                } else {
    +                    srv->flags.reserved = S_HELPER_DEFERRED;
    +                    debug(84, 5) ("StatefulHandleRead: outstanding deferred requests on %s #%d. reserving for deferred requests.\n", hlp->id_name, srv->index + 1);
    +                }
    +
    +                break;
    +
    +            case S_HELPER_RESERVE:	/* 'pin' this helper for the caller */
    +
    +                if (!srv->queue.head) {
    +                    assert(srv->deferred_requests == 0);
    +                    srv->flags.reserved = S_HELPER_RESERVED;
    +                    debug(84, 5) ("StatefulHandleRead: reserving %s #%d\n", hlp->id_name, srv->index + 1);
    +                } else {
    +                    fatal("StatefulHandleRead: Callback routine attempted to reserve a stateful helper with deferred requests. This can lead to deadlock.\n");
    +                }
    +
    +                break;
    +
    +            case S_HELPER_DEFER:
    +                /* the helper is still needed, but can
    +                 * be used for other requests in the meantime.
    +                 */
    +                srv->flags.reserved = S_HELPER_DEFERRED;
    +                srv->deferred_requests++;
    +                srv->stats.deferbycb++;
    +                debug(84, 5) ("StatefulHandleRead: reserving %s #%d for deferred requests.\n", hlp->id_name, srv->index + 1);
    +                break;
    +
    +            default:
    +                fatal("helperStatefulHandleRead: unknown stateful helper callback result.\n");
    +            }
    +
    +        } else {
    +            debug(84, 1) ("StatefulHandleRead: no callback data registered\n");
    +        }
    +
    +        srv->flags.busy = 0;
    +        srv->offset = 0;
    +        helperStatefulRequestFree(r);
    +        srv->request = NULL;
    +        hlp->stats.replies++;
    +        hlp->stats.avg_svc_time =
    +            intAverage(hlp->stats.avg_svc_time,
    +                       tvSubMsec(srv->dispatch_time, current_time),
    +                       hlp->stats.replies, REDIRECT_AV_FACTOR);
    +
    +        if (srv->flags.shutdown
    +                && srv->flags.reserved == S_HELPER_FREE
    +                && !srv->deferred_requests) {
    +            int wfd = srv->wfd;
    +            srv->wfd = -1;
    +            comm_close(wfd);
    +        } else {
    +            if (srv->queue.head)
    +                helperStatefulServerKickQueue(srv);
    +            else
    +                helperStatefulKickQueue(hlp);
    +        }
         } else {
             comm_read(srv->rfd, srv->buf + srv->offset, srv->buf_sz - srv->offset,
    -            helperStatefulHandleRead, srv);
    +                  helperStatefulHandleRead, srv);
         }
     }
     
    @@ -874,17 +1039,25 @@ Enqueue(helper * hlp, helper_request * r)
         dlink_node *link = (dlink_node *)memAllocate(MEM_DLINK_NODE);
         dlinkAddTail(r, link, &hlp->queue);
         hlp->stats.queue_size++;
    +
         if (hlp->stats.queue_size < hlp->n_running)
    -	return;
    +        return;
    +
         if (squid_curtime - hlp->last_queue_warn < 600)
    -	return;
    +        return;
    +
         if (shutting_down || reconfiguring)
    -	return;
    +        return;
    +
         hlp->last_queue_warn = squid_curtime;
    +
         debug(84, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name);
    +
         debug(84, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size);
    +
         if (hlp->stats.queue_size > hlp->n_running * 2)
    -	fatalf("Too many queued %s requests", hlp->id_name);
    +        fatalf("Too many queued %s requests", hlp->id_name);
    +
         debug(84, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name);
     }
     
    @@ -894,17 +1067,25 @@ StatefulEnqueue(statefulhelper * hlp, helper_stateful_request * r)
         dlink_node *link = (dlink_node *)memAllocate(MEM_DLINK_NODE);
         dlinkAddTail(r, link, &hlp->queue);
         hlp->stats.queue_size++;
    +
         if (hlp->stats.queue_size < hlp->n_running)
    -	return;
    +        return;
    +
         if (hlp->stats.queue_size > hlp->n_running * 2)
    -	fatalf("Too many queued %s requests", hlp->id_name);
    +        fatalf("Too many queued %s requests", hlp->id_name);
    +
         if (squid_curtime - hlp->last_queue_warn < 600)
    -	return;
    +        return;
    +
         if (shutting_down || reconfiguring)
    -	return;
    +        return;
    +
         hlp->last_queue_warn = squid_curtime;
    +
         debug(84, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name);
    +
         debug(84, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size);
    +
         debug(84, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name);
     }
     
    @@ -913,23 +1094,23 @@ StatefulServerEnqueue(helper_stateful_server * srv, helper_stateful_request * r)
     {
         dlink_node *link = (dlink_node *)memAllocate(MEM_DLINK_NODE);
         dlinkAddTail(r, link, &srv->queue);
    -/* TODO: warning if the queue on this server is more than X
    - * We don't check the queue size at the moment, because
    - * requests hitting here are deferrable 
    - */
    -/*    hlp->stats.queue_size++;
    - * if (hlp->stats.queue_size < hlp->n_running)
    - * return;
    - * if (squid_curtime - hlp->last_queue_warn < 600)
    - * return;
    - * if (shutting_down || reconfiguring)
    - * return;
    - * hlp->last_queue_warn = squid_curtime;
    - * debug(84, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name);
    - * debug(84, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size);
    - * if (hlp->stats.queue_size > hlp->n_running * 2)
    - * fatalf("Too many queued %s requests", hlp->id_name);
    - * debug(84, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name);  */
    +    /* TODO: warning if the queue on this server is more than X
    +     * We don't check the queue size at the moment, because
    +     * requests hitting here are deferrable 
    +     */
    +    /*    hlp->stats.queue_size++;
    +     * if (hlp->stats.queue_size < hlp->n_running)
    +     * return;
    +     * if (squid_curtime - hlp->last_queue_warn < 600)
    +     * return;
    +     * if (shutting_down || reconfiguring)
    +     * return;
    +     * hlp->last_queue_warn = squid_curtime;
    +     * debug(84, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name);
    +     * debug(84, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size);
    +     * if (hlp->stats.queue_size > hlp->n_running * 2)
    +     * fatalf("Too many queued %s requests", hlp->id_name);
    +     * debug(84, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name);  */
     }
     
     
    @@ -938,12 +1119,14 @@ Dequeue(helper * hlp)
     {
         dlink_node *link;
         helper_request *r = NULL;
    +
         if ((link = hlp->queue.head)) {
    -	r = (helper_request *)link->data;
    -	dlinkDelete(link, &hlp->queue);
    -	memFree(link, MEM_DLINK_NODE);
    -	hlp->stats.queue_size--;
    +        r = (helper_request *)link->data;
    +        dlinkDelete(link, &hlp->queue);
    +        memFree(link, MEM_DLINK_NODE);
    +        hlp->stats.queue_size--;
         }
    +
         return r;
     }
     
    @@ -952,11 +1135,13 @@ StatefulServerDequeue(helper_stateful_server * srv)
     {
         dlink_node *link;
         helper_stateful_request *r = NULL;
    +
         if ((link = srv->queue.head)) {
    -	r = (helper_stateful_request *)link->data;
    -	dlinkDelete(link, &srv->queue);
    -	memFree(link, MEM_DLINK_NODE);
    +        r = (helper_stateful_request *)link->data;
    +        dlinkDelete(link, &srv->queue);
    +        memFree(link, MEM_DLINK_NODE);
         }
    +
         return r;
     }
     
    @@ -965,12 +1150,14 @@ StatefulDequeue(statefulhelper * hlp)
     {
         dlink_node *link;
         helper_stateful_request *r = NULL;
    +
         if ((link = hlp->queue.head)) {
    -	r = (helper_stateful_request *)link->data;
    -	dlinkDelete(link, &hlp->queue);
    -	memFree(link, MEM_DLINK_NODE);
    -	hlp->stats.queue_size--;
    +        r = (helper_stateful_request *)link->data;
    +        dlinkDelete(link, &hlp->queue);
    +        memFree(link, MEM_DLINK_NODE);
    +        hlp->stats.queue_size--;
         }
    +
         return r;
     }
     
    @@ -979,16 +1166,22 @@ GetFirstAvailable(helper * hlp)
     {
         dlink_node *n;
         helper_server *srv = NULL;
    +
         if (hlp->n_running == 0)
    -	return NULL;
    +        return NULL;
    +
         for (n = hlp->servers.head; n != NULL; n = n->next) {
    -	srv = (helper_server *)n->data;
    -	if (srv->flags.busy)
    -	    continue;
    -	if (!srv->flags.alive)
    -	    continue;
    -	return srv;
    +        srv = (helper_server *)n->data;
    +
    +        if (srv->flags.busy)
    +            continue;
    +
    +        if (!srv->flags.alive)
    +            continue;
    +
    +        return srv;
         }
    +
         return NULL;
     }
     
    @@ -998,20 +1191,28 @@ StatefulGetFirstAvailable(statefulhelper * hlp)
         dlink_node *n;
         helper_stateful_server *srv = NULL;
         debug(84, 5) ("StatefulGetFirstAvailable: Running servers %d.\n", hlp->n_running);
    +
         if (hlp->n_running == 0)
    -	return NULL;
    +        return NULL;
    +
         for (n = hlp->servers.head; n != NULL; n = n->next) {
    -	srv = (helper_stateful_server *)n->data;
    -	if (srv->flags.busy)
    -	    continue;
    -	if (srv->flags.reserved == S_HELPER_RESERVED)
    -	    continue;
    -	if (!srv->flags.alive)
    -	    continue;
    -	if ((hlp->IsAvailable != NULL) && (srv->data != NULL) && !(hlp->IsAvailable(srv->data)))
    -	    continue;
    -	return srv;
    +        srv = (helper_stateful_server *)n->data;
    +
    +        if (srv->flags.busy)
    +            continue;
    +
    +        if (srv->flags.reserved == S_HELPER_RESERVED)
    +            continue;
    +
    +        if (!srv->flags.alive)
    +            continue;
    +
    +        if ((hlp->IsAvailable != NULL) && (srv->data != NULL) && !(hlp->IsAvailable(srv->data)))
    +            continue;
    +
    +        return srv;
         }
    +
         debug(84, 5) ("StatefulGetFirstAvailable: None available.\n");
         return NULL;
     }
    @@ -1020,39 +1221,41 @@ StatefulGetFirstAvailable(statefulhelper * hlp)
     static void
     helperDispatchWriteDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
     {
    -	/* nothing! */
    +    /* nothing! */
     }
     
     static void
     helperDispatch(helper_server * srv, helper_request * r)
     {
         helper *hlp = srv->parent;
    +
         if (!cbdataReferenceValid(r->data)) {
    -	debug(84, 1) ("helperDispatch: invalid callback data\n");
    -	helperRequestFree(r);
    -	return;
    +        debug(84, 1) ("helperDispatch: invalid callback data\n");
    +        helperRequestFree(r);
    +        return;
         }
    +
         assert(!srv->flags.busy);
         srv->flags.busy = 1;
         srv->request = r;
         srv->dispatch_time = current_time;
         comm_write(srv->wfd,
    -	r->buf,
    -	strlen(r->buf),
    -	helperDispatchWriteDone,	/* Handler */
    -	hlp);				/* Handler-data */
    +               r->buf,
    +               strlen(r->buf),
    +               helperDispatchWriteDone,	/* Handler */
    +               hlp);				/* Handler-data */
         comm_read(srv->rfd, srv->buf + srv->offset, srv->buf_sz - srv->offset, helperHandleRead, srv);
         debug(84, 5) ("helperDispatch: Request sent to %s #%d, %d bytes\n",
    -	hlp->id_name, srv->index + 1, (int) strlen(r->buf));
    +                  hlp->id_name, srv->index + 1, (int) strlen(r->buf));
         srv->stats.uses++;
         hlp->stats.requests++;
     }
     
     static void
     helperStatefulDispatchWriteDone(int fd, char *buf, size_t len, comm_err_t flag,
    -  int xerrno, void *data)
    +                                int xerrno, void *data)
     {
    -	/* nothing! */
    +    /* nothing! */
     }
     
     
    @@ -1060,49 +1263,55 @@ static void
     helperStatefulDispatch(helper_stateful_server * srv, helper_stateful_request * r)
     {
         statefulhelper *hlp = srv->parent;
    +
         if (!cbdataReferenceValid(r->data)) {
    -	debug(84, 1) ("helperStatefulDispatch: invalid callback data\n");
    -	helperStatefulRequestFree(r);
    -	return;
    +        debug(84, 1) ("helperStatefulDispatch: invalid callback data\n");
    +        helperStatefulRequestFree(r);
    +        return;
         }
    +
         debug(84, 9) ("helperStatefulDispatch busying helper %s #%d\n", hlp->id_name, srv->index + 1);
    +
         if (r->placeholder == 1) {
    -	/* a callback is needed before this request can _use_ a helper. */
    -	/* we don't care about releasing/deferring this helper. The request NEVER
    -	 * gets to the helper. So we throw away the return code */
    -	r->callback(r->data, srv, NULL);
    -	/* throw away the placeholder */
    -	helperStatefulRequestFree(r);
    -	/* and push the queue. Note that the callback may have submitted a new 
    -	 * request to the helper which is why we test for the request*/
    -	if (srv->request == NULL) {
    -	    if (srv->flags.shutdown
    -		&& srv->flags.reserved == S_HELPER_FREE
    -		&& !srv->deferred_requests) {
    -		int wfd = srv->wfd;
    -		srv->wfd = -1;
    -		comm_close(wfd);
    -	    } else {
    -		if (srv->queue.head)
    -		    helperStatefulServerKickQueue(srv);
    -		else
    -		    helperStatefulKickQueue(hlp);
    -	    }
    -	}
    -	return;
    +        /* a callback is needed before this request can _use_ a helper. */
    +        /* we don't care about releasing/deferring this helper. The request NEVER
    +         * gets to the helper. So we throw away the return code */
    +        r->callback(r->data, srv, NULL);
    +        /* throw away the placeholder */
    +        helperStatefulRequestFree(r);
    +        /* and push the queue. Note that the callback may have submitted a new
    +         * request to the helper which is why we test for the request*/
    +
    +        if (srv->request == NULL) {
    +            if (srv->flags.shutdown
    +                    && srv->flags.reserved == S_HELPER_FREE
    +                    && !srv->deferred_requests) {
    +                int wfd = srv->wfd;
    +                srv->wfd = -1;
    +                comm_close(wfd);
    +            } else {
    +                if (srv->queue.head)
    +                    helperStatefulServerKickQueue(srv);
    +                else
    +                    helperStatefulKickQueue(hlp);
    +            }
    +        }
    +
    +        return;
         }
    +
         srv->flags.busy = 1;
         srv->request = r;
         srv->dispatch_time = current_time;
         comm_write(srv->wfd,
    -	r->buf,
    -	strlen(r->buf),
    -	helperStatefulDispatchWriteDone,	/* Handler */
    -	hlp);				/* Handler-data */
    +               r->buf,
    +               strlen(r->buf),
    +               helperStatefulDispatchWriteDone,	/* Handler */
    +               hlp);				/* Handler-data */
         comm_read(srv->rfd, srv->buf + srv->offset, srv->buf_sz - srv->offset,
    -      helperStatefulHandleRead, srv);
    +              helperStatefulHandleRead, srv);
         debug(84, 5) ("helperStatefulDispatch: Request sent to %s #%d, %d bytes\n",
    -	hlp->id_name, srv->index + 1, (int) strlen(r->buf));
    +                  hlp->id_name, srv->index + 1, (int) strlen(r->buf));
         srv->stats.uses++;
         hlp->stats.requests++;
     }
    @@ -1113,8 +1322,9 @@ helperKickQueue(helper * hlp)
     {
         helper_request *r;
         helper_server *srv;
    +
         while ((srv = GetFirstAvailable(hlp)) && (r = Dequeue(hlp)))
    -	helperDispatch(srv, r);
    +        helperDispatch(srv, r);
     }
     
     static void
    @@ -1122,16 +1332,18 @@ helperStatefulKickQueue(statefulhelper * hlp)
     {
         helper_stateful_request *r;
         helper_stateful_server *srv;
    +
         while ((srv = StatefulGetFirstAvailable(hlp)) && (r = StatefulDequeue(hlp)))
    -	helperStatefulDispatch(srv, r);
    +        helperStatefulDispatch(srv, r);
     }
     
     static void
     helperStatefulServerKickQueue(helper_stateful_server * srv)
     {
         helper_stateful_request *r;
    +
         if ((r = StatefulServerDequeue(srv)))
    -	helperStatefulDispatch(srv, r);
    +        helperStatefulDispatch(srv, r);
     }
     
     static void
    diff --git a/src/htcp.cc b/src/htcp.cc
    index 78cf50a219..66c6baecd4 100644
    --- a/src/htcp.cc
    +++ b/src/htcp.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: htcp.cc,v 1.50 2003/01/23 00:37:21 robertc Exp $
    + * $Id: htcp.cc,v 1.51 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 31    Hypertext Caching Protocol
      * AUTHOR: Duane Wesssels
    @@ -40,50 +40,80 @@
     #include "comm.h"
     
     typedef struct _Countstr Countstr;
    +
     typedef struct _htcpHeader htcpHeader;
    +
     typedef struct _htcpDataHeader htcpDataHeader;
    +
     typedef struct _htcpAuthHeader htcpAuthHeader;
    +
     typedef struct _htcpStuff htcpStuff;
    +
     typedef struct _htcpDetail htcpDetail;
     
    -struct _Countstr {
    +struct _Countstr
    +{
         u_int16_t length;
         char *text;
     };
     
    -struct _htcpHeader {
    +struct _htcpHeader
    +{
         u_int16_t length;
         u_char major;
         u_char minor;
     };
     
    -struct _htcpDataHeader {
    +struct _htcpDataHeader
    +{
         u_int16_t length;
     #if !WORDS_BIGENDIAN
    -    unsigned int opcode:4;
    -    unsigned int response:4;
    +
    +unsigned int opcode:
    +    4;
    +
    +unsigned int response:
    +    4;
     #else
    -    unsigned int response:4;
    -    unsigned int opcode:4;
    +
    +unsigned int response:
    +    4;
    +
    +unsigned int opcode:
    +    4;
     #endif
     #if !WORDS_BIGENDIAN
    -    unsigned int reserved:6;
    -    unsigned int F1:1;
    -    unsigned int RR:1;
    +
    +unsigned int reserved:
    +    6;
    +
    +unsigned int F1:
    +    1;
    +
    +unsigned int RR:
    +    1;
     #else
    -    unsigned int RR:1;
    -    unsigned int F1:1;
    -    unsigned int reserved:6;
    +
    +unsigned int RR:
    +    1;
    +
    +unsigned int F1:
    +    1;
    +
    +unsigned int reserved:
    +    6;
     #endif
    +
         u_int32_t msg_id;
     };
     
    -    /* RR == 0 --> F1 = RESPONSE DESIRED FLAG */
    -    /* RR == 1 --> F1 = MESSAGE OVERALL FLAG */
    -    /* RR == 0 --> REQUEST */
    -    /* RR == 1 --> RESPONSE */
    +/* RR == 0 --> F1 = RESPONSE DESIRED FLAG */
    +/* RR == 1 --> F1 = MESSAGE OVERALL FLAG */
    +/* RR == 0 --> REQUEST */
    +/* RR == 1 --> RESPONSE */
     
    -struct _htcpAuthHeader {
    +struct _htcpAuthHeader
    +{
         u_int16_t length;
         time_t sig_time;
         time_t sig_expire;
    @@ -91,7 +121,9 @@ struct _htcpAuthHeader {
         Countstr signature;
     };
     
    -class htcpSpecifier : public StoreClient {
    +class htcpSpecifier : public StoreClient
    +{
    +
     public:
         void *operator new (unsigned int byteCount);
         void operator delete (void *address);
    @@ -99,26 +131,31 @@ public:
         void created (StoreEntry *newEntry);
         void checkHit();
         void checkedHit(StoreEntry *e);
    +
         void setFrom (struct sockaddr_in *from);
         void setDataHeader (htcpDataHeader *);
         char *method;
         char *uri;
         char *version;
         char *req_hdrs;
    +
     private:
         static MemPool *pool;
         request_t *checkHitRequest;
    +
         struct sockaddr_in *from;
         htcpDataHeader *dhdr;
     };
     
    -struct _htcpDetail {
    +struct _htcpDetail
    +{
         char *resp_hdrs;
         char *entity_hdrs;
         char *cache_hdrs;
     };
     
    -struct _htcpStuff {
    +struct _htcpStuff
    +{
         int op;
         int rr;
         int f1;
    @@ -138,14 +175,14 @@ enum {
     };
     
     static const char *const htcpOpcodeStr[] =
    -{
    -    "HTCP_NOP",
    -    "HTCP_TST",
    -    "HTCP_MON",
    -    "HTCP_SET",
    -    "HTCP_CLR",
    -    "HTCP_END"
    -};
    +    {
    +        "HTCP_NOP",
    +        "HTCP_TST",
    +        "HTCP_MON",
    +        "HTCP_SET",
    +        "HTCP_CLR",
    +        "HTCP_END"
    +    };
     
     /*
      * values for htcpDataHeader->response
    @@ -189,16 +226,26 @@ static ssize_t htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff);
     static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff);
     static void htcpFreeSpecifier(htcpSpecifier * s);
     static void htcpFreeDetail(htcpDetail * s);
    +
     static void htcpHandle(char *buf, int sz, struct sockaddr_in *from);
    +
     static void htcpHandleData(char *buf, int sz, struct sockaddr_in *from);
    +
     static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
    +
     static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
    +
     static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
    +
     static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
     static void htcpRecv(int fd, void *data);
    +
     static void htcpSend(const char *buf, int len, struct sockaddr_in *to);
    +
     static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, struct sockaddr_in *);
    +
     static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
    +
     static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr_in *);
     
     static void
    @@ -210,14 +257,19 @@ htcpHexdump(const char *tag, const char *s, int sz)
         char hex[80];
         debug(31, 3) ("htcpHexdump %s\n", tag);
         memset(hex, '\0', 80);
    +
         for (i = 0; i < sz; i++) {
    -	k = i % 16;
    -	snprintf(&hex[k * 3], 4, " %02x", (int) *(s + i));
    -	if (k < 15 && i < (sz - 1))
    -	    continue;
    -	debug(31, 3) ("\t%s\n", hex);
    -	memset(hex, '\0', 80);
    +        k = i % 16;
    +        snprintf(&hex[k * 3], 4, " %02x", (int) *(s + i));
    +
    +        if (k < 15 && i < (sz - 1))
    +            continue;
    +
    +        debug(31, 3) ("\t%s\n", hex);
    +
    +        memset(hex, '\0', 80);
         }
    +
     #endif
     }
     
    @@ -244,22 +296,33 @@ htcpBuildCountstr(char *buf, size_t buflen, const char *s)
         u_int16_t length;
         size_t len;
         off_t off = 0;
    +
         if (buflen - off < 2)
    -	return -1;
    +        return -1;
    +
         if (s)
    -	len = strlen(s);
    +        len = strlen(s);
         else
    -	len = 0;
    +        len = 0;
    +
         debug(31, 3) ("htcpBuildCountstr: LENGTH = %d\n", len);
    +
         debug(31, 3) ("htcpBuildCountstr: TEXT = {%s}\n", s ? s : "");
    +
         length = htons((u_int16_t) len);
    +
         xmemcpy(buf + off, &length, 2);
    +
         off += 2;
    +
         if (buflen - off < len)
    -	return -1;
    +        return -1;
    +
         if (len)
    -	xmemcpy(buf + off, s, len);
    +        xmemcpy(buf + off, s, len);
    +
         off += len;
    +
         return off;
     }
     
    @@ -269,22 +332,35 @@ htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff)
         ssize_t off = 0;
         ssize_t s;
         s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.method);
    +
         if (s < 0)
    -	return s;
    +        return s;
    +
         off += s;
    +
         s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.uri);
    +
         if (s < 0)
    -	return s;
    +        return s;
    +
         off += s;
    +
         s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.version);
    +
         if (s < 0)
    -	return s;
    +        return s;
    +
         off += s;
    +
         s = htcpBuildCountstr(buf + off, buflen - off, stuff->S.req_hdrs);
    +
         if (s < 0)
    -	return s;
    +        return s;
    +
         off += s;
    +
         debug(31, 3) ("htcpBuildSpecifier: size %d\n", (int) off);
    +
         return off;
     }
     
    @@ -294,17 +370,26 @@ htcpBuildDetail(char *buf, size_t buflen, htcpStuff * stuff)
         ssize_t off = 0;
         ssize_t s;
         s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.resp_hdrs);
    +
         if (s < 0)
    -	return s;
    +        return s;
    +
         off += s;
    +
         s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.entity_hdrs);
    +
         if (s < 0)
    -	return s;
    +        return s;
    +
         off += s;
    +
         s = htcpBuildCountstr(buf + off, buflen - off, stuff->D.cache_hdrs);
    +
         if (s < 0)
    -	return s;
    +        return s;
    +
         off += s;
    +
         return off;
     }
     
    @@ -312,19 +397,24 @@ static ssize_t
     htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff)
     {
         switch (stuff->rr) {
    +
         case RR_REQUEST:
    -	debug(31, 3) ("htcpBuildTstOpData: RR_REQUEST\n");
    -	return htcpBuildSpecifier(buf, buflen, stuff);
    +        debug(31, 3) ("htcpBuildTstOpData: RR_REQUEST\n");
    +        return htcpBuildSpecifier(buf, buflen, stuff);
    +
         case RR_RESPONSE:
    -	debug(31, 3) ("htcpBuildTstOpData: RR_RESPONSE\n");
    -	debug(31, 3) ("htcpBuildTstOpData: F1 = %d\n", stuff->f1);
    -	if (stuff->f1)		/* cache miss */
    -	    return 0;
    -	else			/* cache hit */
    -	    return htcpBuildDetail(buf, buflen, stuff);
    +        debug(31, 3) ("htcpBuildTstOpData: RR_RESPONSE\n");
    +        debug(31, 3) ("htcpBuildTstOpData: F1 = %d\n", stuff->f1);
    +
    +        if (stuff->f1)		/* cache miss */
    +            return 0;
    +        else			/* cache hit */
    +            return htcpBuildDetail(buf, buflen, stuff);
    +
         default:
    -	fatal_dump("htcpBuildTstOpData: bad RR value");
    +        fatal_dump("htcpBuildTstOpData: bad RR value");
         }
    +
         return 0;
     }
     
    @@ -333,15 +423,19 @@ htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff)
     {
         ssize_t off = 0;
         debug(31, 3) ("htcpBuildOpData: opcode %s\n",
    -	htcpOpcodeStr[stuff->op]);
    +                  htcpOpcodeStr[stuff->op]);
    +
         switch (stuff->op) {
    +
         case HTCP_TST:
    -	off = htcpBuildTstOpData(buf + off, buflen, stuff);
    -	break;
    +        off = htcpBuildTstOpData(buf + off, buflen, stuff);
    +        break;
    +
         default:
    -	assert(0);
    -	break;
    +        assert(0);
    +        break;
         }
    +
         return off;
     }
     
    @@ -352,25 +446,42 @@ htcpBuildData(char *buf, size_t buflen, htcpStuff * stuff)
         ssize_t op_data_sz;
         size_t hdr_sz = sizeof(htcpDataHeader);
         htcpDataHeader hdr;
    +
         if (buflen < hdr_sz)
    -	return -1;
    +        return -1;
    +
         off += hdr_sz;		/* skip! */
    +
         op_data_sz = htcpBuildOpData(buf + off, buflen - off, stuff);
    +
         if (op_data_sz < 0)
    -	return op_data_sz;
    +        return op_data_sz;
    +
         off += op_data_sz;
    +
         debug(31, 3) ("htcpBuildData: hdr.length = %d\n", (int) off);
    +
         hdr.length = (u_int16_t) off;
    +
         hdr.opcode = stuff->op;
    +
         hdr.response = stuff->response;
    +
         hdr.RR = stuff->rr;
    +
         hdr.F1 = stuff->f1;
    +
         hdr.msg_id = stuff->msg_id;
    +
         /* convert multi-byte fields */
         hdr.length = htons(hdr.length);
    +
         hdr.msg_id = htonl(hdr.msg_id);
    +
         xmemcpy(buf, &hdr, hdr_sz);
    +
         debug(31, 3) ("htcpBuildData: size %d\n", (int) off);
    +
         return off;
     }
     
    @@ -384,22 +495,28 @@ htcpBuildPacket(htcpStuff * stuff, ssize_t * len)
         htcpHeader hdr;
         char *buf = (char *)xcalloc(buflen, 1);
         /* skip the header -- we don't know the overall length */
    +
         if (buflen < hdr_sz) {
    -	xfree(buf);
    -	return NULL;
    +        xfree(buf);
    +        return NULL;
         }
    +
         off += hdr_sz;
         s = htcpBuildData(buf + off, buflen - off, stuff);
    +
         if (s < 0) {
    -	xfree(buf);
    -	return NULL;
    +        xfree(buf);
    +        return NULL;
         }
    +
         off += s;
         s = htcpBuildAuth(buf + off, buflen - off);
    +
         if (s < 0) {
    -	xfree(buf);
    -	return NULL;
    +        xfree(buf);
    +        return NULL;
         }
    +
         off += s;
         hdr.length = htons((u_int16_t) off);
         hdr.major = 0;
    @@ -411,19 +528,22 @@ htcpBuildPacket(htcpStuff * stuff, ssize_t * len)
     }
     
     static void
    +
     htcpSend(const char *buf, int len, struct sockaddr_in *to)
     {
         int x;
         debug(31, 3) ("htcpSend: %s/%d\n",
    -	inet_ntoa(to->sin_addr), (int) ntohs(to->sin_port));
    +                  inet_ntoa(to->sin_addr), (int) ntohs(to->sin_port));
         htcpHexdump("htcpSend", buf, len);
         x = comm_udp_sendto(htcpOutSocket,
    -	to,
    -	sizeof(struct sockaddr_in),
    -	buf,
    -	len);
    +                        to,
    +
    +                        sizeof(struct sockaddr_in),
    +                        buf,
    +                        len);
    +
         if (x < 0)
    -	debug(31, 0) ("htcpSend: FD %d sendto: %s\n", htcpOutSocket, xstrerror());
    +        debug(31, 0) ("htcpSend: FD %d sendto: %s\n", htcpOutSocket, xstrerror());
     }
     
     /*
    @@ -435,18 +555,21 @@ htcpSpecifier::operator new (unsigned int byteCount)
     {
         /* derived classes with different sizes must implement their own new */
         assert (byteCount == sizeof (htcpSpecifier));
    +
         if (!pool)
    -	pool = memPoolCreate("htcpSpecifier", sizeof(htcpSpecifier));
    +        pool = memPoolCreate("htcpSpecifier", sizeof(htcpSpecifier));
    +
         return static_cast (memPoolAlloc(pool));
     }
     
    -void 
    +void
     htcpSpecifier::operator delete (void *address)
     {
         memPoolFree(pool, address);
     }
     
     void
    +
     htcpSpecifier::setFrom (struct sockaddr_in *aSocket)
     {
         from = aSocket;
    @@ -482,25 +605,30 @@ htcpUnpackCountstr(char *buf, int sz, char **str)
     {
         u_int16_t l;
         debug(31, 3) ("htcpUnpackCountstr: sz = %d\n", sz);
    +
         if (sz < 2) {
    -	debug(31, 3) ("htcpUnpackCountstr: sz < 2\n");
    -	return -1;
    +        debug(31, 3) ("htcpUnpackCountstr: sz < 2\n");
    +        return -1;
         }
    +
         htcpHexdump("htcpUnpackCountstr", buf, sz);
         xmemcpy(&l, buf, 2);
         l = ntohs(l);
         buf += 2;
         sz -= 2;
         debug(31, 3) ("htcpUnpackCountstr: LENGTH = %d\n", (int) l);
    +
         if (sz < l) {
    -	debug(31, 3) ("htcpUnpackCountstr: sz(%d) < l(%d)\n", sz, l);
    -	return -1;
    +        debug(31, 3) ("htcpUnpackCountstr: sz(%d) < l(%d)\n", sz, l);
    +        return -1;
         }
    +
         if (str) {
    -	*str = (char *)xmalloc(l + 1);
    -	xstrncpy(*str, buf, l + 1);
    -	debug(31, 3) ("htcpUnpackCountstr: TEXT = {%s}\n", *str);
    +        *str = (char *)xmalloc(l + 1);
    +        xstrncpy(*str, buf, l + 1);
    +        debug(31, 3) ("htcpUnpackCountstr: TEXT = {%s}\n", *str);
         }
    +
         return (int) l + 2;
     }
     
    @@ -511,35 +639,43 @@ htcpUnpackSpecifier(char *buf, int sz)
         int o;
         debug(31, 3) ("htcpUnpackSpecifier: %d bytes\n", (int) sz);
         o = htcpUnpackCountstr(buf, sz, &s->method);
    +
         if (o < 0) {
    -	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack METHOD\n");
    -	htcpFreeSpecifier(s);
    -	return NULL;
    +        debug(31, 1) ("htcpUnpackSpecifier: failed to unpack METHOD\n");
    +        htcpFreeSpecifier(s);
    +        return NULL;
         }
    +
         buf += o;
         sz -= o;
         o = htcpUnpackCountstr(buf, sz, &s->uri);
    +
         if (o < 0) {
    -	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack URI\n");
    -	htcpFreeSpecifier(s);
    -	return NULL;
    +        debug(31, 1) ("htcpUnpackSpecifier: failed to unpack URI\n");
    +        htcpFreeSpecifier(s);
    +        return NULL;
         }
    +
         buf += o;
         sz -= o;
         o = htcpUnpackCountstr(buf, sz, &s->version);
    +
         if (o < 0) {
    -	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack VERSION\n");
    -	htcpFreeSpecifier(s);
    -	return NULL;
    +        debug(31, 1) ("htcpUnpackSpecifier: failed to unpack VERSION\n");
    +        htcpFreeSpecifier(s);
    +        return NULL;
         }
    +
         buf += o;
         sz -= o;
         o = htcpUnpackCountstr(buf, sz, &s->req_hdrs);
    +
         if (o < 0) {
    -	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack REQ-HDRS\n");
    -	htcpFreeSpecifier(s);
    -	return NULL;
    +        debug(31, 1) ("htcpUnpackSpecifier: failed to unpack REQ-HDRS\n");
    +        htcpFreeSpecifier(s);
    +        return NULL;
         }
    +
         buf += o;
         sz -= o;
         debug(31, 3) ("htcpUnpackSpecifier: %d bytes left\n", sz);
    @@ -553,27 +689,33 @@ htcpUnpackDetail(char *buf, int sz)
         int o;
         debug(31, 3) ("htcpUnpackDetail: %d bytes\n", (int) sz);
         o = htcpUnpackCountstr(buf, sz, &d->resp_hdrs);
    +
         if (o < 0) {
    -	debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP_HDRS\n");
    -	htcpFreeDetail(d);
    -	return NULL;
    +        debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP_HDRS\n");
    +        htcpFreeDetail(d);
    +        return NULL;
         }
    +
         buf += o;
         sz -= o;
         o = htcpUnpackCountstr(buf, sz, &d->entity_hdrs);
    +
         if (o < 0) {
    -	debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY_HDRS\n");
    -	htcpFreeDetail(d);
    -	return NULL;
    +        debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY_HDRS\n");
    +        htcpFreeDetail(d);
    +        return NULL;
         }
    +
         buf += o;
         sz -= o;
         o = htcpUnpackCountstr(buf, sz, &d->cache_hdrs);
    +
         if (o < 0) {
    -	debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE_HDRS\n");
    -	htcpFreeDetail(d);
    -	return NULL;
    +        debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE_HDRS\n");
    +        htcpFreeDetail(d);
    +        return NULL;
         }
    +
         buf += o;
         sz -= o;
         debug(31, 3) ("htcpUnpackDetail: %d bytes left\n", sz);
    @@ -581,6 +723,7 @@ htcpUnpackDetail(char *buf, int sz)
     }
     
     static void
    +
     htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from)
     {
         htcpStuff stuff;
    @@ -601,56 +744,73 @@ htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct
         stuff.response = e ? 0 : 1;
         debug(31, 3) ("htcpTstReply: response = %d\n", stuff.response);
         stuff.msg_id = dhdr->msg_id;
    -    if (spec) {
    -	memBufDefInit(&mb);
    -	packerToMemInit(&p, &mb);
    -	httpHeaderInit(&hdr, hoHtcpReply);
    -	stuff.S.method = spec->method;
    -	stuff.S.uri = spec->uri;
    -	stuff.S.version = spec->version;
    -	stuff.S.req_hdrs = spec->req_hdrs;
    -	httpHeaderPutInt(&hdr, HDR_AGE,
    -	    e->timestamp <= squid_curtime ?
    -	    squid_curtime - e->timestamp : 0);
    -	httpHeaderPackInto(&hdr, &p);
    -	stuff.D.resp_hdrs = xstrdup(mb.buf);
    -	debug(31, 3) ("htcpTstReply: resp_hdrs = {%s}\n", stuff.D.resp_hdrs);
    -	memBufReset(&mb);
    -	httpHeaderReset(&hdr);
    -	if (e->expires > -1)
    -	    httpHeaderPutTime(&hdr, HDR_EXPIRES, e->expires);
    -	if (e->lastmod > -1)
    -	    httpHeaderPutTime(&hdr, HDR_LAST_MODIFIED, e->lastmod);
    -	httpHeaderPackInto(&hdr, &p);
    -	stuff.D.entity_hdrs = xstrdup(mb.buf);
    -	debug(31, 3) ("htcpTstReply: entity_hdrs = {%s}\n", stuff.D.entity_hdrs);
    -	memBufReset(&mb);
    -	httpHeaderReset(&hdr);
    -	if ((host = urlHostname(spec->uri))) {
    -	    netdbHostData(host, &samp, &rtt, &hops);
    -	    if (rtt || hops) {
    -		snprintf(cto_buf, 128, "%s %d %f %d",
    -		    host, samp, 0.001 * rtt, hops);
    -		httpHeaderPutExt(&hdr, "Cache-to-Origin", cto_buf);
    -	    }
    -	}
    -	httpHeaderPackInto(&hdr, &p);
    -	stuff.D.cache_hdrs = xstrdup(mb.buf);
    -	debug(31, 3) ("htcpTstReply: cache_hdrs = {%s}\n", stuff.D.cache_hdrs);
    -	memBufClean(&mb);
    -	httpHeaderClean(&hdr);
    -	packerClean(&p);
    +
    +    if (spec)
    +    {
    +        memBufDefInit(&mb);
    +        packerToMemInit(&p, &mb);
    +        httpHeaderInit(&hdr, hoHtcpReply);
    +        stuff.S.method = spec->method;
    +        stuff.S.uri = spec->uri;
    +        stuff.S.version = spec->version;
    +        stuff.S.req_hdrs = spec->req_hdrs;
    +        httpHeaderPutInt(&hdr, HDR_AGE,
    +                         e->timestamp <= squid_curtime ?
    +                         squid_curtime - e->timestamp : 0);
    +        httpHeaderPackInto(&hdr, &p);
    +        stuff.D.resp_hdrs = xstrdup(mb.buf);
    +        debug(31, 3) ("htcpTstReply: resp_hdrs = {%s}\n", stuff.D.resp_hdrs);
    +        memBufReset(&mb);
    +        httpHeaderReset(&hdr);
    +
    +        if (e->expires > -1)
    +            httpHeaderPutTime(&hdr, HDR_EXPIRES, e->expires);
    +
    +        if (e->lastmod > -1)
    +            httpHeaderPutTime(&hdr, HDR_LAST_MODIFIED, e->lastmod);
    +
    +        httpHeaderPackInto(&hdr, &p);
    +
    +        stuff.D.entity_hdrs = xstrdup(mb.buf);
    +
    +        debug(31, 3) ("htcpTstReply: entity_hdrs = {%s}\n", stuff.D.entity_hdrs);
    +
    +        memBufReset(&mb);
    +
    +        httpHeaderReset(&hdr);
    +
    +        if ((host = urlHostname(spec->uri))) {
    +            netdbHostData(host, &samp, &rtt, &hops);
    +
    +            if (rtt || hops) {
    +                snprintf(cto_buf, 128, "%s %d %f %d",
    +                         host, samp, 0.001 * rtt, hops);
    +                httpHeaderPutExt(&hdr, "Cache-to-Origin", cto_buf);
    +            }
    +        }
    +
    +        httpHeaderPackInto(&hdr, &p);
    +        stuff.D.cache_hdrs = xstrdup(mb.buf);
    +        debug(31, 3) ("htcpTstReply: cache_hdrs = {%s}\n", stuff.D.cache_hdrs);
    +        memBufClean(&mb);
    +        httpHeaderClean(&hdr);
    +        packerClean(&p);
         }
    +
         pkt = htcpBuildPacket(&stuff, &pktlen);
    -    if (pkt == NULL) {
    -	debug(31, 0) ("htcpTstReply: htcpBuildPacket() failed\n");
    -	return;
    +
    +    if (pkt == NULL)
    +    {
    +        debug(31, 0) ("htcpTstReply: htcpBuildPacket() failed\n");
    +        return;
         }
    +
         htcpSend(pkt, (int) pktlen, from);
         xfree(pkt);
     }
     
     static void
    +
     htcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
     {
         debug(31, 3) ("htcpHandleNop: Unimplemented\n");
    @@ -662,19 +822,23 @@ htcpSpecifier::checkHit()
         method_t m = urlParseMethod(method);
         char *blk_end;
         checkHitRequest = urlParse(m, uri);
    +
         if (NULL == checkHitRequest) {
    -	debug(31, 3) ("htcpCheckHit: NO; failed to parse URL\n");
    -	checkedHit(NullStoreEntry::getInstance());
    -	return;
    +        debug(31, 3) ("htcpCheckHit: NO; failed to parse URL\n");
    +        checkedHit(NullStoreEntry::getInstance());
    +        return;
         }
    +
         blk_end = req_hdrs + strlen(req_hdrs);
    +
         if (!httpHeaderParse(&checkHitRequest->header, req_hdrs, blk_end)) {
    -	debug(31, 3) ("htcpCheckHit: NO; failed to parse request headers\n");
    -	requestDestroy(checkHitRequest);
    -	checkHitRequest = NULL;
    -	checkedHit(NullStoreEntry::getInstance());
    -	return;
    +        debug(31, 3) ("htcpCheckHit: NO; failed to parse request headers\n");
    +        requestDestroy(checkHitRequest);
    +        checkHitRequest = NULL;
    +        checkedHit(NullStoreEntry::getInstance());
    +        return;
         }
    +
         StoreEntry::getPublicByRequest(this, checkHitRequest);
     }
     
    @@ -683,98 +847,128 @@ htcpSpecifier::created (StoreEntry *e)
     {
         StoreEntry *hit=NULL;
         assert (e);
    +
         if (e->isNull()) {
    -	debug(31, 3) ("htcpCheckHit: NO; public object not found\n");
    -	goto miss;
    +        debug(31, 3) ("htcpCheckHit: NO; public object not found\n");
    +        goto miss;
         }
    +
         if (!storeEntryValidToSend(e)) {
    -	debug(31, 3) ("htcpCheckHit: NO; entry not valid to send\n");
    -	goto miss;
    +        debug(31, 3) ("htcpCheckHit: NO; entry not valid to send\n");
    +        goto miss;
         }
    +
         if (refreshCheckHTCP(e, checkHitRequest)) {
    -	debug(31, 3) ("htcpCheckHit: NO; cached response is stale\n");
    -	goto miss;
    +        debug(31, 3) ("htcpCheckHit: NO; cached response is stale\n");
    +        goto miss;
         }
    +
         debug(31, 3) ("htcpCheckHit: YES!?\n");
         hit = e;
    -  miss:
    +
    +miss:
         requestDestroy(checkHitRequest);
         checkedHit (hit);
     }
     
     static void
    +
     htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
     {
         debug(31, 3) ("htcpHandleTst: sz = %d\n", (int) sz);
    +
         if (hdr->RR == RR_REQUEST)
    -	htcpHandleTstRequest(hdr, buf, sz, from);
    +        htcpHandleTstRequest(hdr, buf, sz, from);
         else
    -	htcpHandleTstResponse(hdr, buf, sz, from);
    +        htcpHandleTstResponse(hdr, buf, sz, from);
     }
     
     static void
    +
     htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
     {
         htcpReplyData htcpReply;
         cache_key *key = NULL;
         htcpDetail *d = NULL;
         char *t;
    -    if (hdr->F1 == 1) {
    -	debug(31, 1) ("htcpHandleTstResponse: error condition, F1/MO == 1\n");
    -	return;
    +
    +    if (hdr->F1 == 1)
    +    {
    +        debug(31, 1) ("htcpHandleTstResponse: error condition, F1/MO == 1\n");
    +        return;
         }
    +
         memset(&htcpReply, '\0', sizeof(htcpReply));
         httpHeaderInit(&htcpReply.hdr, hoHtcpReply);
         htcpReply.msg_id = hdr->msg_id;
         debug(31, 3) ("htcpHandleTstResponse: msg_id = %d\n", (int) htcpReply.msg_id);
         htcpReply.hit = hdr->response ? 0 : 1;
    -    if (hdr->F1) {
    -	debug(31, 3) ("htcpHandleTstResponse: MISS\n");
    -    } else {
    -	debug(31, 3) ("htcpHandleTstResponse: HIT\n");
    -	d = htcpUnpackDetail(buf, sz);
    -	if (d == NULL) {
    -	    debug(31, 1) ("htcpHandleTstResponse: bad DETAIL\n");
    -	    return;
    -	}
    -	if ((t = d->resp_hdrs))
    -	    httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
    -	if ((t = d->entity_hdrs))
    -	    httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
    -	if ((t = d->cache_hdrs))
    -	    httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
    +
    +    if (hdr->F1)
    +    {
    +        debug(31, 3) ("htcpHandleTstResponse: MISS\n");
    +    } else
    +    {
    +        debug(31, 3) ("htcpHandleTstResponse: HIT\n");
    +        d = htcpUnpackDetail(buf, sz);
    +
    +        if (d == NULL) {
    +            debug(31, 1) ("htcpHandleTstResponse: bad DETAIL\n");
    +            return;
    +        }
    +
    +        if ((t = d->resp_hdrs))
    +            httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
    +
    +        if ((t = d->entity_hdrs))
    +            httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
    +
    +        if ((t = d->cache_hdrs))
    +            httpHeaderParse(&htcpReply.hdr, t, t + strlen(t));
         }
    +
         key = queried_keys[htcpReply.msg_id % N_QUERIED_KEYS];
         debug(31, 3) ("htcpHandleTstResponse: key (%p) %s\n", key, storeKeyText(key));
         neighborsHtcpReply(key, &htcpReply, from);
         httpHeaderClean(&htcpReply.hdr);
    +
         if (d)
    -	htcpFreeDetail(d);
    +        htcpFreeDetail(d);
     }
     
     static void
    +
     htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, struct sockaddr_in *from)
     {
         /* buf should be a SPECIFIER */
         htcpSpecifier *s;
    -    if (sz == 0) {
    -	debug(31, 3) ("htcpHandleTst: nothing to do\n");
    -	return;
    +
    +    if (sz == 0)
    +    {
    +        debug(31, 3) ("htcpHandleTst: nothing to do\n");
    +        return;
         }
    +
         if (dhdr->F1 == 0)
    -	return;
    +        return;
    +
         /* s is a new object */
         s = htcpUnpackSpecifier(buf, sz);
    +
         s->setFrom (from);
    +
         s->setDataHeader (dhdr);
    -    if (NULL == s) {
    -	debug(31, 3) ("htcpHandleTstRequest: htcpUnpackSpecifier failed\n");
    -	return;
    +
    +    if (NULL == s)
    +    {
    +        debug(31, 3) ("htcpHandleTstRequest: htcpUnpackSpecifier failed\n");
    +        return;
         }
    +
         debug(31, 3) ("htcpHandleTstRequest: %s %s %s\n",
    -	s->method,
    -	s->uri,
    -	s->version);
    +                  s->method,
    +                  s->uri,
    +                  s->version);
         debug(31, 3) ("htcpHandleTstRequest: %s\n", s->req_hdrs);
         s->checkHit();
     }
    @@ -783,107 +977,139 @@ void
     htcpSpecifier::checkedHit(StoreEntry *e)
     {
         if (e)
    -	htcpTstReply(dhdr, e, this, from);		/* hit */
    +        htcpTstReply(dhdr, e, this, from);		/* hit */
         else
    -	htcpTstReply(dhdr, NULL, NULL, from);	/* cache miss */
    +        htcpTstReply(dhdr, NULL, NULL, from);	/* cache miss */
    +
         htcpFreeSpecifier(this);
     }
     
     static void
    +
     htcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
     {
         debug(31, 3) ("htcpHandleMon: Unimplemented\n");
     }
     
     static void
    +
     htcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
     {
         debug(31, 3) ("htcpHandleSet: Unimplemented\n");
     }
     
     static void
    +
     htcpHandleData(char *buf, int sz, struct sockaddr_in *from)
     {
         htcpDataHeader hdr;
         assert (sz >= 0);
    -    if ((size_t)sz < sizeof(htcpDataHeader)) {
    -	debug(31, 0) ("htcpHandleData: msg size less than htcpDataHeader size\n");
    -	return;
    +
    +    if ((size_t)sz < sizeof(htcpDataHeader))
    +    {
    +        debug(31, 0) ("htcpHandleData: msg size less than htcpDataHeader size\n");
    +        return;
         }
    +
         xmemcpy(&hdr, buf, sizeof(htcpDataHeader));
         hdr.length = ntohs(hdr.length);
         hdr.msg_id = ntohl(hdr.msg_id);
         debug(31, 3) ("htcpHandleData: sz = %d\n", sz);
         debug(31, 3) ("htcpHandleData: length = %d\n", (int) hdr.length);
    -    if (hdr.opcode >= HTCP_END) {
    -	debug(31, 0) ("htcpHandleData: client %s, opcode %d out of range\n",
    -	    inet_ntoa(from->sin_addr),
    -	    (int) hdr.opcode);
    -	return;
    +
    +    if (hdr.opcode >= HTCP_END)
    +    {
    +        debug(31, 0) ("htcpHandleData: client %s, opcode %d out of range\n",
    +                      inet_ntoa(from->sin_addr),
    +                      (int) hdr.opcode);
    +        return;
         }
    +
         debug(31, 3) ("htcpHandleData: opcode = %d %s\n",
    -	(int) hdr.opcode, htcpOpcodeStr[hdr.opcode]);
    +                  (int) hdr.opcode, htcpOpcodeStr[hdr.opcode]);
         debug(31, 3) ("htcpHandleData: response = %d\n", (int) hdr.response);
         debug(31, 3) ("htcpHandleData: F1 = %d\n", (int) hdr.F1);
         debug(31, 3) ("htcpHandleData: RR = %d\n", (int) hdr.RR);
         debug(31, 3) ("htcpHandleData: msg_id = %d\n", (int) hdr.msg_id);
    -    if (sz < hdr.length) {
    -	debug(31, 0) ("htcpHandle: sz < hdr.length\n");
    -	return;
    +
    +    if (sz < hdr.length)
    +    {
    +        debug(31, 0) ("htcpHandle: sz < hdr.length\n");
    +        return;
         }
    +
         /*
          * set sz = hdr.length so we ignore any AUTH fields following
          * the DATA.
          */
         sz = (int) hdr.length;
    +
         buf += sizeof(htcpDataHeader);
    +
         sz -= sizeof(htcpDataHeader);
    +
         debug(31, 3) ("htcpHandleData: sz = %d\n", sz);
    +
         htcpHexdump("htcpHandleData", buf, sz);
    -    switch (hdr.opcode) {
    +
    +    switch (hdr.opcode)
    +    {
    +
         case HTCP_NOP:
    -	htcpHandleNop(&hdr, buf, sz, from);
    -	break;
    +        htcpHandleNop(&hdr, buf, sz, from);
    +        break;
    +
         case HTCP_TST:
    -	htcpHandleTst(&hdr, buf, sz, from);
    -	break;
    +        htcpHandleTst(&hdr, buf, sz, from);
    +        break;
    +
         case HTCP_MON:
    -	htcpHandleMon(&hdr, buf, sz, from);
    -	break;
    +        htcpHandleMon(&hdr, buf, sz, from);
    +        break;
    +
         case HTCP_SET:
    -	htcpHandleSet(&hdr, buf, sz, from);
    -	break;
    +        htcpHandleSet(&hdr, buf, sz, from);
    +        break;
    +
         case HTCP_CLR:
    -	debug(31, 1) ("htcpHandleData: client %s, CLR not supported\n",
    -	    inet_ntoa(from->sin_addr));
    -	break;
    +        debug(31, 1) ("htcpHandleData: client %s, CLR not supported\n",
    +                      inet_ntoa(from->sin_addr));
    +        break;
    +
         default:
    -	assert(0);
    -	break;
    +        assert(0);
    +        break;
         }
     }
     
     static void
    +
     htcpHandle(char *buf, int sz, struct sockaddr_in *from)
     {
         htcpHeader htcpHdr;
         assert (sz >= 0);
    -    if ((size_t)sz < sizeof(htcpHeader)) {
    -	debug(31, 0) ("htcpHandle: msg size less than htcpHeader size\n");
    -	return;
    +
    +    if ((size_t)sz < sizeof(htcpHeader))
    +    {
    +        debug(31, 0) ("htcpHandle: msg size less than htcpHeader size\n");
    +        return;
         }
    +
         htcpHexdump("htcpHandle", buf, sz);
         xmemcpy(&htcpHdr, buf, sizeof(htcpHeader));
         htcpHdr.length = ntohs(htcpHdr.length);
         debug(31, 3) ("htcpHandle: htcpHdr.length = %d\n", (int) htcpHdr.length);
         debug(31, 3) ("htcpHandle: htcpHdr.major = %d\n", (int) htcpHdr.major);
         debug(31, 3) ("htcpHandle: htcpHdr.minor = %d\n", (int) htcpHdr.minor);
    -    if (sz != htcpHdr.length) {
    -	debug(31, 1) ("htcpHandle: sz/%d != htcpHdr.length/%d from %s:%d\n",
    -	    sz, htcpHdr.length,
    -	    inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port));
    -	return;
    +
    +    if (sz != htcpHdr.length)
    +    {
    +        debug(31, 1) ("htcpHandle: sz/%d != htcpHdr.length/%d from %s:%d\n",
    +                      sz, htcpHdr.length,
    +                      inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port));
    +        return;
         }
    +
         buf += sizeof(htcpHeader);
         sz -= sizeof(htcpHeader);
         htcpHandleData(buf, sz, from);
    @@ -894,12 +1120,15 @@ htcpRecv(int fd, void *data)
     {
         static char buf[8192];
         int len;
    +
         static struct sockaddr_in from;
    +
         socklen_t flen = sizeof(struct sockaddr_in);
         memset(&from, '\0', flen);
    +
         len = comm_udp_recvfrom(fd, buf, 8192, 0, (struct sockaddr *) &from, &flen);
         debug(31, 3) ("htcpRecv: FD %d, %d bytes from %s:%d\n",
    -	fd, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
    +                  fd, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
         htcpHandle(buf, len, &from);
         commSetSelect(fd, COMM_SELECT_READ, htcpRecv, NULL, 0);
     }
    @@ -914,42 +1143,52 @@ void
     htcpInit(void)
     {
         if (Config.Port.htcp <= 0) {
    -	debug(31, 1) ("HTCP Disabled.\n");
    -	return;
    +        debug(31, 1) ("HTCP Disabled.\n");
    +        return;
         }
    +
         enter_suid();
         htcpInSocket = comm_open(SOCK_DGRAM,
    -	0,
    -	Config.Addrs.udp_incoming,
    -	Config.Port.htcp,
    -	COMM_NONBLOCKING,
    -	"HTCP Socket");
    +                             0,
    +                             Config.Addrs.udp_incoming,
    +                             Config.Port.htcp,
    +                             COMM_NONBLOCKING,
    +                             "HTCP Socket");
         leave_suid();
    +
         if (htcpInSocket < 0)
    -	fatal("Cannot open HTCP Socket");
    +        fatal("Cannot open HTCP Socket");
    +
         commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
    +
         debug(31, 1) ("Accepting HTCP messages on port %d, FD %d.\n",
    -	(int) Config.Port.htcp, htcpInSocket);
    +                  (int) Config.Port.htcp, htcpInSocket);
    +
         if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) {
    -	enter_suid();
    -	htcpOutSocket = comm_open(SOCK_DGRAM,
    -	    0,
    -	    Config.Addrs.udp_outgoing,
    -	    Config.Port.htcp,
    -	    COMM_NONBLOCKING,
    -	    "Outgoing HTCP Socket");
    -	leave_suid();
    -	if (htcpOutSocket < 0)
    -	    fatal("Cannot open Outgoing HTCP Socket");
    -	commSetSelect(htcpOutSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
    -	debug(31, 1) ("Outgoing HTCP messages on port %d, FD %d.\n",
    -	    (int) Config.Port.htcp, htcpOutSocket);
    -	fd_note(htcpInSocket, "Incoming HTCP socket");
    +        enter_suid();
    +        htcpOutSocket = comm_open(SOCK_DGRAM,
    +                                  0,
    +                                  Config.Addrs.udp_outgoing,
    +                                  Config.Port.htcp,
    +                                  COMM_NONBLOCKING,
    +                                  "Outgoing HTCP Socket");
    +        leave_suid();
    +
    +        if (htcpOutSocket < 0)
    +            fatal("Cannot open Outgoing HTCP Socket");
    +
    +        commSetSelect(htcpOutSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
    +
    +        debug(31, 1) ("Outgoing HTCP messages on port %d, FD %d.\n",
    +                      (int) Config.Port.htcp, htcpOutSocket);
    +
    +        fd_note(htcpInSocket, "Incoming HTCP socket");
         } else {
    -	htcpOutSocket = htcpInSocket;
    +        htcpOutSocket = htcpInSocket;
         }
    +
         if (!htcpDetailPool) {
    -	htcpDetailPool = memPoolCreate("htcpDetail", sizeof(htcpDetail));
    +        htcpDetailPool = memPoolCreate("htcpDetail", sizeof(htcpDetail));
         }
     }
     
    @@ -967,32 +1206,52 @@ htcpQuery(StoreEntry * e, request_t * req, peer * p)
         http_state_flags flags;
     
         if (htcpInSocket < 0)
    -	return;
    +        return;
     
         memset(&flags, '\0', sizeof(flags));
    +
         snprintf(vbuf, sizeof(vbuf), "%d/%d",
    -	req->http_ver.major, req->http_ver.minor);
    +             req->http_ver.major, req->http_ver.minor);
    +
         stuff.op = HTCP_TST;
    +
         stuff.rr = RR_REQUEST;
    +
         stuff.f1 = 1;
    +
         stuff.response = 0;
    +
         stuff.msg_id = ++msg_id_counter;
    +
         stuff.S.method = (char *) RequestMethodStr[req->method];
    +
         stuff.S.uri = (char *) storeUrl(e);
    +
         stuff.S.version = vbuf;
    +
         httpBuildRequestHeader(req, req, e, &hdr, flags);
    +
         memBufDefInit(&mb);
    +
         packerToMemInit(&pa, &mb);
    +
         httpHeaderPackInto(&hdr, &pa);
    +
         httpHeaderClean(&hdr);
    +
         packerClean(&pa);
    +
         stuff.S.req_hdrs = mb.buf;
    +
         pkt = htcpBuildPacket(&stuff, &pktlen);
    +
         memBufClean(&mb);
    +
         if (pkt == NULL) {
    -	debug(31, 0) ("htcpQuery: htcpBuildPacket() failed\n");
    -	return;
    +        debug(31, 0) ("htcpQuery: htcpBuildPacket() failed\n");
    +        return;
         }
    +
         htcpSend(pkt, (int) pktlen, &p->in_addr);
         save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS];
         storeKeyCopy(save_key, (const cache_key *)e->key);
    @@ -1000,7 +1259,7 @@ htcpQuery(StoreEntry * e, request_t * req, peer * p)
         xfree(pkt);
     }
     
    -/*  
    +/*
      * htcpSocketShutdown only closes the 'in' socket if it is
      * different than the 'out' socket.
      */
    @@ -1008,19 +1267,22 @@ void
     htcpSocketShutdown(void)
     {
         if (htcpInSocket < 0)
    -	return;
    +        return;
    +
         if (htcpInSocket != htcpOutSocket) {
    -	debug(12, 1) ("FD %d Closing HTCP socket\n", htcpInSocket);
    -	comm_close(htcpInSocket);
    +        debug(12, 1) ("FD %d Closing HTCP socket\n", htcpInSocket);
    +        comm_close(htcpInSocket);
         }
    -    /*      
    +
    +    /*
          * Here we set 'htcpInSocket' to -1 even though the HTCP 'in'
          * and 'out' sockets might be just one FD.  This prevents this
          * function from executing repeatedly.  When we are really ready to
          * exit or restart, main will comm_close the 'out' descriptor.
          */
         htcpInSocket = -1;
    -    /*      
    +
    +    /*
          * Normally we only write to the outgoing HTCP socket, but
          * we also have a read handler there to catch messages sent
          * to that specific interface.  During shutdown, we must
    @@ -1030,6 +1292,7 @@ htcpSocketShutdown(void)
          * I think there should be a separate hander for reading replies..
          */
         assert(htcpOutSocket > -1);
    +
         commSetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0);
     }
     
    @@ -1037,9 +1300,10 @@ void
     htcpSocketClose(void)
     {
         htcpSocketShutdown();
    +
         if (htcpOutSocket > -1) {
    -	debug(12, 1) ("FD %d Closing HTCP socket\n", htcpOutSocket);
    -	comm_close(htcpOutSocket);
    -	htcpOutSocket = -1;
    +        debug(12, 1) ("FD %d Closing HTCP socket\n", htcpOutSocket);
    +        comm_close(htcpOutSocket);
    +        htcpOutSocket = -1;
         }
     }
    diff --git a/src/http.cc b/src/http.cc
    index dafdf833b2..9ff27e5ee8 100644
    --- a/src/http.cc
    +++ b/src/http.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: http.cc,v 1.409 2003/02/15 00:15:51 hno Exp $
    + * $Id: http.cc,v 1.410 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
      * AUTHOR: Harvest Derived
    @@ -68,7 +68,7 @@ static void httpMakePublic(StoreEntry *);
     static int httpCachableReply(HttpStateData *);
     static void httpMaybeRemovePublic(StoreEntry *, http_status);
     static void copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, String strConnection, request_t * request, request_t * orig_request,
    -HttpHeader * hdr_out, int we_do_ranges, http_state_flags);
    +        HttpHeader * hdr_out, int we_do_ranges, http_state_flags);
     static int decideIfWeDoRanges (request_t * orig_request);
     
     
    @@ -77,16 +77,22 @@ httpStateFree(int fd, void *data)
     {
         HttpStateData *httpState = static_cast(data);
     #if DELAY_POOLS
    +
         if (fd >= 0)
    -	DelayPools::ClearNoDelay(fd);
    +        DelayPools::ClearNoDelay(fd);
    +
     #endif
    +
         if (httpState == NULL)
    -	return;
    +        return;
    +
         storeUnlockObject(httpState->entry);
    +
         if (httpState->reply_hdr) {
    -	memFree(httpState->reply_hdr, MEM_8K_BUF);
    -	httpState->reply_hdr = NULL;
    +        memFree(httpState->reply_hdr, MEM_8K_BUF);
    +        httpState->reply_hdr = NULL;
         }
    +
         requestUnlink(httpState->request);
         requestUnlink(httpState->orig_request);
         httpState->request = NULL;
    @@ -98,8 +104,10 @@ int
     httpCachable(method_t method)
     {
         /* GET and HEAD are cachable. Others are not. */
    +
         if (method != METHOD_GET && method != METHOD_HEAD)
    -	return 0;
    +        return 0;
    +
         /* else cachable */
         return 1;
     }
    @@ -110,12 +118,14 @@ httpTimeout(int fd, void *data)
         HttpStateData *httpState = static_cast(data);
         StoreEntry *entry = httpState->entry;
         debug(11, 4) ("httpTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
    +
         if (entry->store_status == STORE_PENDING) {
    -	if (entry->isEmpty()) {
    -	    fwdFail(httpState->fwd,
    -		errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
    -	}
    +        if (entry->isEmpty()) {
    +            fwdFail(httpState->fwd,
    +                    errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
    +        }
         }
    +
         comm_close(fd);
     }
     
    @@ -124,7 +134,7 @@ static void
     httpMakePublic(StoreEntry * entry)
     {
         if (EBIT_TEST(entry->flags, ENTRY_CACHABLE))
    -	storeSetPublicKey(entry);
    +        storeSetPublicKey(entry);
     }
     
     /* This object should never be cached at all */
    @@ -141,97 +151,145 @@ static void
     httpCacheNegatively(StoreEntry * entry)
     {
         storeNegativeCache(entry);
    +
         if (EBIT_TEST(entry->flags, ENTRY_CACHABLE))
    -	storeSetPublicKey(entry);
    +        storeSetPublicKey(entry);
     }
     
     static void
     httpMaybeRemovePublic(StoreEntry * e, http_status status)
     {
    -    int remove = 0;
    +
    +    int remove
    +        = 0;
    +
         int forbidden = 0;
    +
         StoreEntry *pe;
    +
         if (!EBIT_TEST(e->flags, KEY_PRIVATE))
    -	return;
    +        return;
    +
         switch (status) {
    +
         case HTTP_OK:
    +
         case HTTP_NON_AUTHORITATIVE_INFORMATION:
    +
         case HTTP_MULTIPLE_CHOICES:
    +
         case HTTP_MOVED_PERMANENTLY:
    +
         case HTTP_MOVED_TEMPORARILY:
    +
         case HTTP_GONE:
    +
         case HTTP_NOT_FOUND:
    -	remove = 1;
    -	break;
    +
    +        remove
    +            = 1;
    +
    +        break;
    +
         case HTTP_FORBIDDEN:
    +
         case HTTP_METHOD_NOT_ALLOWED:
    -	forbidden = 1;
    -	break;
    +        forbidden = 1;
    +
    +        break;
    +
     #if WORK_IN_PROGRESS
    +
         case HTTP_UNAUTHORIZED:
    -	forbidden = 1;
    -	break;
    +        forbidden = 1;
    +
    +        break;
    +
     #endif
    +
         default:
     #if QUESTIONABLE
    -	/*
    -	 * Any 2xx response should eject previously cached entities...
    -	 */
    -	if (status >= 200 && status < 300)
    -	    remove = 1;
    +        /*
    +         * Any 2xx response should eject previously cached entities...
    +         */
    +        if (status >= 200 && status < 300)
    +            remove
    +                = 1;
    +
     #endif
    -	break;
    +
    +        break;
         }
    -    if (!remove && !forbidden)
    -	return;
    +
    +    if (!remove
    +            && !forbidden)
    +        return;
    +
         assert(e->mem_obj);
    +
         if (e->mem_obj->request)
    -	pe = storeGetPublicByRequest(e->mem_obj->request);
    +        pe = storeGetPublicByRequest(e->mem_obj->request);
         else
    -	pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method);
    +        pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method);
    +
         if (pe != NULL) {
    -	assert(e != pe);
    -	storeRelease(pe);
    +        assert(e != pe);
    +        storeRelease(pe);
         }
    +
         /*
          * Also remove any cached HEAD response in case the object has
          * changed.
          */
         if (e->mem_obj->request)
    -	pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD);
    +        pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD);
         else
    -	pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD);
    +        pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD);
    +
         if (pe != NULL) {
    -	assert(e != pe);
    -	storeRelease(pe);
    +        assert(e != pe);
    +        storeRelease(pe);
         }
    +
         if (forbidden)
    -	return;
    +        return;
    +
         switch (e->mem_obj->method) {
    +
         case METHOD_PUT:
    +
         case METHOD_DELETE:
    +
         case METHOD_PROPPATCH:
    +
         case METHOD_MKCOL:
    +
         case METHOD_MOVE:
    +
         case METHOD_BMOVE:
    +
         case METHOD_BDELETE:
    -	/*
    -	 * Remove any cached GET object if it is beleived that the
    -	 * object may have changed as a result of other methods
    -	 */
    -	if (e->mem_obj->request)
    -	    pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_GET);
    -	else
    -	    pe = storeGetPublic(e->mem_obj->url, METHOD_GET);
    -	if (pe != NULL) {
    -	    assert(e != pe);
    -	    storeRelease(pe);
    -	}
    -	break;
    +        /*
    +         * Remove any cached GET object if it is beleived that the
    +         * object may have changed as a result of other methods
    +         */
    +
    +        if (e->mem_obj->request)
    +            pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_GET);
    +        else
    +            pe = storeGetPublic(e->mem_obj->url, METHOD_GET);
    +
    +        if (pe != NULL) {
    +            assert(e != pe);
    +            storeRelease(pe);
    +        }
    +
    +        break;
    +
         default:
    -	/* Keep GCC happy. The methods above are all mutating HTTP methods 
    -	 */
    -	break;
    +        /* Keep GCC happy. The methods above are all mutating HTTP methods
    +         */
    +        break;
         }
     }
     
    @@ -239,14 +297,18 @@ int
     cacheControlAllowsCaching(HttpHdrCc *cc)
     {
         if (cc) {
    -       const int cc_mask = cc->mask;
    -       if (EBIT_TEST(cc_mask, CC_PRIVATE))
    -           return 0;
    -       if (EBIT_TEST(cc_mask, CC_NO_CACHE))
    -           return 0;
    -       if (EBIT_TEST(cc_mask, CC_NO_STORE))
    -           return 0;
    +        const int cc_mask = cc->mask;
    +
    +        if (EBIT_TEST(cc_mask, CC_PRIVATE))
    +            return 0;
    +
    +        if (EBIT_TEST(cc_mask, CC_NO_CACHE))
    +            return 0;
    +
    +        if (EBIT_TEST(cc_mask, CC_NO_STORE))
    +            return 0;
         }
    +
         return 1;
     }
     
    @@ -257,100 +319,144 @@ httpCachableReply(HttpStateData * httpState)
         HttpHeader const *hdr = &rep->header;
         const int cc_mask = (rep->cache_control) ? rep->cache_control->mask : 0;
         const char *v;
    +
         if (!cacheControlAllowsCaching(rep->cache_control))
    -	return 0;
    +        return 0;
    +
         if (httpState->request->flags.auth) {
    -	/*
    -	 * Responses to requests with authorization may be cached
    -	 * only if a Cache-Control: public reply header is present.
    -	 * RFC 2068, sec 14.9.4
    -	 */
    -	if (!EBIT_TEST(cc_mask, CC_PUBLIC))
    -	    return 0;
    +        /*
    +         * Responses to requests with authorization may be cached
    +         * only if a Cache-Control: public reply header is present.
    +         * RFC 2068, sec 14.9.4
    +         */
    +
    +        if (!EBIT_TEST(cc_mask, CC_PUBLIC))
    +            return 0;
         }
    +
         /* Pragma: no-cache in _replies_ is not documented in HTTP,
          * but servers like "Active Imaging Webcast/2.0" sure do use it */
         if (httpHeaderHas(hdr, HDR_PRAGMA)) {
    -	String s = httpHeaderGetList(hdr, HDR_PRAGMA);
    -	const int no_cache = strListIsMember(&s, "no-cache", ',');
    -	s.clean();
    -	if (no_cache)
    -	    return 0;
    +        String s = httpHeaderGetList(hdr, HDR_PRAGMA);
    +        const int no_cache = strListIsMember(&s, "no-cache", ',');
    +        s.clean();
    +
    +        if (no_cache)
    +            return 0;
         }
    +
         /*
          * The "multipart/x-mixed-replace" content type is used for
          * continuous push replies.  These are generally dynamic and
          * probably should not be cachable
          */
         if ((v = httpHeaderGetStr(hdr, HDR_CONTENT_TYPE)))
    -	if (!strncasecmp(v, "multipart/x-mixed-replace", 25))
    -	    return 0;
    +        if (!strncasecmp(v, "multipart/x-mixed-replace", 25))
    +            return 0;
    +
         switch (httpState->entry->getReply()->sline.status) {
    -	/* Responses that are cacheable */
    +        /* Responses that are cacheable */
    +
         case HTTP_OK:
    +
         case HTTP_NON_AUTHORITATIVE_INFORMATION:
    +
         case HTTP_MULTIPLE_CHOICES:
    +
         case HTTP_MOVED_PERMANENTLY:
    +
         case HTTP_GONE:
    -	/*
    -	 * Don't cache objects that need to be refreshed on next request,
    -	 * unless we know how to refresh it.
    -	 */
    -	if (!refreshIsCachable(httpState->entry))
    -	    return 0;
    -	/* don't cache objects from peers w/o LMT, Date, or Expires */
    -	/* check that is it enough to check headers @?@ */
    -	if (rep->date > -1)
    -	    return 1;
    -	else if (rep->last_modified > -1)
    -	    return 1;
    -	else if (!httpState->_peer)
    -	    return 1;
    -	/* @?@ (here and 302): invalid expires header compiles to squid_curtime */
    -	else if (rep->expires > -1)
    -	    return 1;
    -	else
    -	    return 0;
    -	/* NOTREACHED */
    -	break;
    -	/* Responses that only are cacheable if the server says so */
    +        /*
    +         * Don't cache objects that need to be refreshed on next request,
    +         * unless we know how to refresh it.
    +         */
    +
    +        if (!refreshIsCachable(httpState->entry))
    +            return 0;
    +
    +        /* don't cache objects from peers w/o LMT, Date, or Expires */
    +        /* check that is it enough to check headers @?@ */
    +        if (rep->date > -1)
    +            return 1;
    +        else if (rep->last_modified > -1)
    +            return 1;
    +        else if (!httpState->_peer)
    +            return 1;
    +
    +        /* @?@ (here and 302): invalid expires header compiles to squid_curtime */
    +        else if (rep->expires > -1)
    +            return 1;
    +        else
    +            return 0;
    +
    +        /* NOTREACHED */
    +        break;
    +
    +        /* Responses that only are cacheable if the server says so */
    +
         case HTTP_MOVED_TEMPORARILY:
    -	if (rep->expires > -1)
    -	    return 1;
    -	else
    -	    return 0;
    -	/* NOTREACHED */
    -	break;
    -	/* Errors can be negatively cached */
    +        if (rep->expires > -1)
    +            return 1;
    +        else
    +            return 0;
    +
    +        /* NOTREACHED */
    +        break;
    +
    +        /* Errors can be negatively cached */
    +
         case HTTP_NO_CONTENT:
    +
         case HTTP_USE_PROXY:
    +
         case HTTP_BAD_REQUEST:
    +
         case HTTP_FORBIDDEN:
    +
         case HTTP_NOT_FOUND:
    +
         case HTTP_METHOD_NOT_ALLOWED:
    +
         case HTTP_REQUEST_URI_TOO_LARGE:
    +
         case HTTP_INTERNAL_SERVER_ERROR:
    +
         case HTTP_NOT_IMPLEMENTED:
    +
         case HTTP_BAD_GATEWAY:
    +
         case HTTP_SERVICE_UNAVAILABLE:
    +
         case HTTP_GATEWAY_TIMEOUT:
    -	return -1;
    -	/* NOTREACHED */
    -	break;
    -	/* Some responses can never be cached */
    +        return -1;
    +
    +        /* NOTREACHED */
    +        break;
    +
    +        /* Some responses can never be cached */
    +
         case HTTP_PARTIAL_CONTENT:	/* Not yet supported */
    +
         case HTTP_SEE_OTHER:
    +
         case HTTP_NOT_MODIFIED:
    +
         case HTTP_UNAUTHORIZED:
    +
         case HTTP_PROXY_AUTHENTICATION_REQUIRED:
    +
         case HTTP_INVALID_HEADER:	/* Squid header parsing error */
    -	return 0;
    +        return 0;
    +
         default:			/* Unknown status code */
    -	debug (11,0)("httpCachableReply: unknown http status code in reply\n");
    -	return 0;
    -	/* NOTREACHED */
    -	break;
    +        debug (11,0)("httpCachableReply: unknown http status code in reply\n");
    +
    +        return 0;
    +
    +        /* NOTREACHED */
    +        break;
         }
    +
         /* NOTREACHED */
     }
     
    @@ -371,43 +477,53 @@ httpMakeVaryMark(request_t * request, HttpReply const * reply)
     
         vstr.clean();
         vary = httpHeaderGetList(&reply->header, HDR_VARY);
    +
         while (strListGetItem(&vary, ',', &item, &ilen, &pos)) {
    -	char *name = (char *)xmalloc(ilen + 1);
    -	xstrncpy(name, item, ilen + 1);
    -	Tolower(name);
    -	strListAdd(&vstr, name, ',');
    -	hdr = httpHeaderGetByName(&request->header, name);
    -	safe_free(name);
    -	value = hdr.buf();
    -	if (value) {
    -	    value = rfc1738_escape_part(value);
    -	    vstr.append("=\"", 2);
    -	    vstr.append(value);
    -	    vstr.append("\"", 1);
    -	}
    -	hdr.clean();
    +        char *name = (char *)xmalloc(ilen + 1);
    +        xstrncpy(name, item, ilen + 1);
    +        Tolower(name);
    +        strListAdd(&vstr, name, ',');
    +        hdr = httpHeaderGetByName(&request->header, name);
    +        safe_free(name);
    +        value = hdr.buf();
    +
    +        if (value) {
    +            value = rfc1738_escape_part(value);
    +            vstr.append("=\"", 2);
    +            vstr.append(value);
    +            vstr.append("\"", 1);
    +        }
    +
    +        hdr.clean();
         }
    +
         vary.clean();
     #if X_ACCELERATOR_VARY
    +
         vary = httpHeaderGetList(&reply->header, HDR_X_ACCELERATOR_VARY);
    +
         while (strListGetItem(&vary, ',', &item, &ilen, &pos)) {
    -	char *name = (char *)xmalloc(ilen + 1);
    -	xstrncpy(name, item, ilen + 1);
    -	Tolower(name);
    -	strListAdd(&vstr, name, ',');
    -	hdr = httpHeaderGetByName(&request->header, name);
    -	safe_free(name);
    -	value = hdr.buf();
    -	if (value) {
    -	    value = rfc1738_escape_part(value);
    -	    vstr.append("=\"", 2);
    -	    vstr.append(value);
    -	    vstr.append("\"", 1);
    -	}
    -	hdr.clean();
    +        char *name = (char *)xmalloc(ilen + 1);
    +        xstrncpy(name, item, ilen + 1);
    +        Tolower(name);
    +        strListAdd(&vstr, name, ',');
    +        hdr = httpHeaderGetByName(&request->header, name);
    +        safe_free(name);
    +        value = hdr.buf();
    +
    +        if (value) {
    +            value = rfc1738_escape_part(value);
    +            vstr.append("=\"", 2);
    +            vstr.append(value);
    +            vstr.append("\"", 1);
    +        }
    +
    +        hdr.clean();
         }
    +
         vary.clean();
     #endif
    +
         debug(11, 3) ("httpMakeVaryMark: %s\n", vstr.buf());
         return vstr.buf();
     }
    @@ -425,47 +541,64 @@ HttpStateData::processReplyHeader(const char *buf, int size)
         HttpReply *reply = httpReplyCreate();
         Ctx ctx;
         debug(11, 3) ("httpProcessReplyHeader: key '%s'\n",
    -	entry->getMD5Text());
    +                  entry->getMD5Text());
    +
         if (reply_hdr == NULL)
    -	reply_hdr = (char *)memAllocate(MEM_8K_BUF);
    +        reply_hdr = (char *)memAllocate(MEM_8K_BUF);
    +
         assert(reply_hdr_state == 0);
    +
         hdr_len = reply_hdr_size;
    +
         room = 8191 - hdr_len;
    +
         xmemcpy(reply_hdr + hdr_len, buf, room < size ? room : size);
    +
         hdr_len += room < size ? room : size;
    +
         reply_hdr[hdr_len] = '\0';
    +
         reply_hdr_size = hdr_len;
    +
         if (hdr_len > 4 && strncmp(reply_hdr, "HTTP/", 5)) {
    -	debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", reply_hdr);
    -	reply_hdr_state += 2;
    -	reply->sline.status = HTTP_INVALID_HEADER;
    -	storeEntryReplaceObject (entry, reply);
    -	if (eof == 1) {
    -	    fwdComplete(fwd);
    -	    comm_close(fd);
    -	}
    -	return;
    +        debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", reply_hdr);
    +        reply_hdr_state += 2;
    +        reply->sline.status = HTTP_INVALID_HEADER;
    +        storeEntryReplaceObject (entry, reply);
    +
    +        if (eof == 1) {
    +            fwdComplete(fwd);
    +            comm_close(fd);
    +        }
    +
    +        return;
         }
    +
         t = reply_hdr + hdr_len;
         /* headers can be incomplete only if object still arriving */
    +
         if (!eof) {
    -	size_t k = headersEnd(reply_hdr, 8192);
    -	if (0 == k) {
    -	    if (eof == 1) {
    -		fwdComplete(fwd);
    -		comm_close(fd);
    -	    }
    -	    return;		/* headers not complete */
    -	}
    -	t = reply_hdr + k;
    +        size_t k = headersEnd(reply_hdr, 8192);
    +
    +        if (0 == k) {
    +            if (eof == 1) {
    +                fwdComplete(fwd);
    +                comm_close(fd);
    +            }
    +
    +            return;		/* headers not complete */
    +        }
    +
    +        t = reply_hdr + k;
         }
    +
         *t = '\0';
         reply_hdr_state++;
         assert(reply_hdr_state == 1);
         ctx = ctx_enter(entry->mem_obj->url);
         reply_hdr_state++;
         debug(11, 9) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n",
    -	reply_hdr);
    +                  reply_hdr);
         /* Parse headers into reply structure */
         /* what happens if we fail to parse here? */
         httpReplyParse(reply, reply_hdr, hdr_len);
    @@ -482,67 +615,85 @@ HttpStateData::processReplyHeader(const char *buf, int size)
         reply = NULL;
     
         if (entry->getReply()->content_range)
    -       currentOffset = entry->getReply()->content_range->spec.offset;
    +        currentOffset = entry->getReply()->content_range->spec.offset;
    +
         storeTimestampsSet(entry);
    +
         /* Check if object is cacheable or not based on reply code */
         debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", entry->getReply()->sline.status);
    +
         if (neighbors_do_private_keys)
    -	httpMaybeRemovePublic(entry, entry->getReply()->sline.status);
    +        httpMaybeRemovePublic(entry, entry->getReply()->sline.status);
     
         switch (httpCachableReply(this)) {
    +
         case 1:
    -	if (httpHeaderHas(&entry->getReply()->header, HDR_VARY)
    +
    +        if (httpHeaderHas(&entry->getReply()->header, HDR_VARY)
     #if X_ACCELERATOR_VARY
    -	    || httpHeaderHas(&entry->getReply()->header, HDR_X_ACCELERATOR_VARY)
    +                || httpHeaderHas(&entry->getReply()->header, HDR_X_ACCELERATOR_VARY)
     #endif
    -	    ) {
    -	    const char *vary = httpMakeVaryMark(orig_request, entry->getReply());
    -	    if (vary) {
    -		entry->mem_obj->vary_headers = xstrdup(vary);
    -		/* Kill the old base object if a change in variance is detected */
    -		httpMakePublic(entry);
    -	    } else {
    -		httpMakePrivate(entry);
    -	    }
    -	} else {
    -	    httpMakePublic(entry);
    -	}
    -	break;
    +           ) {
    +            const char *vary = httpMakeVaryMark(orig_request, entry->getReply());
    +
    +            if (vary) {
    +                entry->mem_obj->vary_headers = xstrdup(vary);
    +                /* Kill the old base object if a change in variance is detected */
    +                httpMakePublic(entry);
    +            } else {
    +                httpMakePrivate(entry);
    +            }
    +        } else {
    +            httpMakePublic(entry);
    +        }
    +
    +        break;
    +
         case 0:
    -	httpMakePrivate(entry);
    -	break;
    +        httpMakePrivate(entry);
    +        break;
    +
         case -1:
    -	httpCacheNegatively(entry);
    -	break;
    +        httpCacheNegatively(entry);
    +        break;
    +
         default:
    -	assert(0);
    -	break;
    +        assert(0);
    +        break;
         }
    +
         if (entry->getReply()->cache_control) {
    -	if (EBIT_TEST(entry->getReply()->cache_control->mask, CC_PROXY_REVALIDATE))
    -	    EBIT_SET(entry->flags, ENTRY_REVALIDATE);
    -	else if (EBIT_TEST(entry->getReply()->cache_control->mask, CC_MUST_REVALIDATE))
    -	    EBIT_SET(entry->flags, ENTRY_REVALIDATE);
    +        if (EBIT_TEST(entry->getReply()->cache_control->mask, CC_PROXY_REVALIDATE))
    +            EBIT_SET(entry->flags, ENTRY_REVALIDATE);
    +        else if (EBIT_TEST(entry->getReply()->cache_control->mask, CC_MUST_REVALIDATE))
    +            EBIT_SET(entry->flags, ENTRY_REVALIDATE);
         }
    +
         if (flags.keepalive)
    -	if (_peer)
    -	    _peer->stats.n_keepalives_sent++;
    +        if (_peer)
    +            _peer->stats.n_keepalives_sent++;
    +
         if (entry->getReply()->keep_alive)
    -	if (_peer)
    -	    _peer->stats.n_keepalives_recv++;
    +        if (_peer)
    +            _peer->stats.n_keepalives_recv++;
    +
         if (entry->getReply()->date > -1 && !_peer) {
    -	int skew = abs(entry->getReply()->date - squid_curtime);
    -	if (skew > 86400)
    -	    debug(11, 3) ("%s's clock is skewed by %d seconds!\n",
    -		request->host, skew);
    +        int skew = abs(entry->getReply()->date - squid_curtime);
    +
    +        if (skew > 86400)
    +            debug(11, 3) ("%s's clock is skewed by %d seconds!\n",
    +                          request->host, skew);
         }
    +
         ctx_exit(ctx);
     #if HEADERS_LOG
    +
         headersLog(1, 0, request->method, entry->getReply());
     #endif
    +
         if (eof == 1) {
    -	fwdComplete(fwd);
    -	comm_close(fd);
    +        fwdComplete(fwd);
    +        comm_close(fd);
         }
     }
     
    @@ -551,13 +702,16 @@ HttpStateData::statusIfComplete() const
     {
         HttpReply const *reply = entry->getReply();
         /* If the reply wants to close the connection, it takes precedence */
    +
         if (httpHeaderHasConnDir(&reply->header, "close"))
    -	return COMPLETE_NONPERSISTENT_MSG;
    +        return COMPLETE_NONPERSISTENT_MSG;
    +
         /* If we didn't send a keep-alive request header, then this
          * can not be a persistent connection.
          */
         if (!flags.keepalive)
    -	return COMPLETE_NONPERSISTENT_MSG;
    +        return COMPLETE_NONPERSISTENT_MSG;
    +
         /*
          * What does the reply have to say about keep-alive?
          */
    @@ -572,6 +726,7 @@ HttpStateData::statusIfComplete() const
          */
         if (!reply->keep_alive)
             return COMPLETE_NONPERSISTENT_MSG;
    +
         return COMPLETE_PERSISTENT_MSG;
     }
     
    @@ -583,20 +738,26 @@ HttpStateData::persistentConnStatus() const
         debug(11, 3) ("httpPconnTransferDone: FD %d\n", fd);
         ConnectionStatus result = statusIfComplete();
         debug(11, 5) ("httpPconnTransferDone: content_length=%d\n",
    -	reply->content_length);
    +                  reply->content_length);
         /* If we haven't seen the end of reply headers, we are not done */
    +
         if (reply_hdr_state < 2)
    -	return INCOMPLETE_MSG;
    +        return INCOMPLETE_MSG;
    +
         clen = httpReplyBodySize(request->method, reply);
    +
         /* If there is no message body, we can be persistent */
         if (0 == clen)
    -	return result;
    +        return result;
    +
         /* If the body size is unknown we must wait for EOF */
         if (clen < 0)
    -	return INCOMPLETE_MSG;
    +        return INCOMPLETE_MSG;
    +
         /* If the body size is known, we must wait until we've gotten all of it.  */
         if (entry->mem_obj->endOffset() < reply->content_length + reply->hdr_sz)
    -	return INCOMPLETE_MSG;
    +        return INCOMPLETE_MSG;
    +
         /* We got it all */
         return result;
     }
    @@ -623,112 +784,131 @@ HttpStateData::readReply (int fd, char *readBuf, size_t len, comm_err_t flag, in
         assert(buf == readBuf);
     
         /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us
    -*/
    +    */
    +
         if (flag == COMM_ERR_CLOSING) {
    -	debug (11,1)("http socket closing\n");
    +        debug (11,1)("http socket closing\n");
             return;
         }
     
         if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
    -	maybeReadData();
    -	return;
    +        maybeReadData();
    +        return;
         }
     
         errno = 0;
         /* prepare the read size for the next read (if any) */
     #if DELAY_POOLS
    +
         DelayId delayId;
     
         /* special "if" only for http (for nodelay proxy conns) */
    +
         if (DelayPools::IsNoDelay(fd))
    -	delayId = DelayId();
    +        delayId = DelayId();
         else
    -	delayId = entry->mem_obj->mostBytesAllowed();
    +        delayId = entry->mem_obj->mostBytesAllowed();
    +
     #endif
    +
         debug(11, 5) ("httpReadReply: FD %d: len %d.\n", fd, (int)len);
    +
         if (flag == COMM_OK && len > 0) {
     #if DELAY_POOLS
    -	delayId.bytesIn(len);
    +        delayId.bytesIn(len);
     #endif
    -	kb_incr(&statCounter.server.all.kbytes_in, len);
    -	kb_incr(&statCounter.server.http.kbytes_in, len);
    -	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
    -	IOStats.Http.reads++;
    -	for (clen = len - 1, bin = 0; clen; bin++)
    -	    clen >>= 1;
    -	IOStats.Http.read_hist[bin]++;
    +
    +        kb_incr(&statCounter.server.all.kbytes_in, len);
    +        kb_incr(&statCounter.server.http.kbytes_in, len);
    +        commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
    +        IOStats.Http.reads++;
    +
    +        for (clen = len - 1, bin = 0; clen; bin++)
    +            clen >>= 1;
    +
    +        IOStats.Http.read_hist[bin]++;
         }
    +
         if (!reply_hdr && flag == COMM_OK && len > 0) {
    -	/* Skip whitespace */
    -	while (len > 0 && xisspace(*buf))
    -	    xmemmove(buf, buf + 1, len--);
    -	if (len == 0) {
    -	    /* Continue to read... */
    -	    do_next_read = 1;
    -	    maybeReadData();
    -	    return;
    -	}
    +        /* Skip whitespace */
    +
    +        while (len > 0 && xisspace(*buf))
    +            xmemmove(buf, buf + 1, len--);
    +
    +        if (len == 0) {
    +            /* Continue to read... */
    +            do_next_read = 1;
    +            maybeReadData();
    +            return;
    +        }
         }
    +
         if (flag != COMM_OK || len < 0) {
    -	debug(50, 2) ("httpReadReply: FD %d: read failure: %s.\n",
    -	    fd, xstrerror());
    -	if (ignoreErrno(errno)) {
    -	    do_next_read = 1;
    -	} else if (entry->isEmpty()) {
    -	    ErrorState *err;
    -	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    -	    err->request = requestLink((request_t *) request);
    -	    err->xerrno = errno;
    -	    fwdFail(fwd, err);
    -	    do_next_read = 0;
    -	    comm_close(fd);
    -	} else {
    -	    do_next_read = 0;
    -	    comm_close(fd);
    -	}
    +        debug(50, 2) ("httpReadReply: FD %d: read failure: %s.\n",
    +                      fd, xstrerror());
    +
    +        if (ignoreErrno(errno)) {
    +            do_next_read = 1;
    +        } else if (entry->isEmpty()) {
    +            ErrorState *err;
    +            err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    +            err->request = requestLink((request_t *) request);
    +            err->xerrno = errno;
    +            fwdFail(fwd, err);
    +            do_next_read = 0;
    +            comm_close(fd);
    +        } else {
    +            do_next_read = 0;
    +            comm_close(fd);
    +        }
         } else if (flag == COMM_OK && len == 0 && entry->isEmpty()) {
    -	ErrorState *err;
    -	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
    -	err->xerrno = errno;
    -	err->request = requestLink((request_t *) request);
    -	fwdFail(fwd, err);
    -	eof = 1;
    -	do_next_read = 0;
    -	comm_close(fd);
    +        ErrorState *err;
    +        err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
    +        err->xerrno = errno;
    +        err->request = requestLink((request_t *) request);
    +        fwdFail(fwd, err);
    +        eof = 1;
    +        do_next_read = 0;
    +        comm_close(fd);
         } else if (flag == COMM_OK && len == 0) {
    -	/* Connection closed; retrieval done. */
    -	eof = 1;
    -	if (reply_hdr_state < 2)
    -	    /*
    -	     * Yes Henrik, there is a point to doing this.  When we
    -	     * called httpProcessReplyHeader() before, we didn't find
    -	     * the end of headers, but now we are definately at EOF, so
    -	     * we want to process the reply headers.
    -	     */
    -	    /* doesn't return */
    -	    processReplyHeader(buf, len);
    -	else {
    -	    fwdComplete(fwd);
    -	    do_next_read = 0;
    -	    comm_close(fd);
    -	}
    +        /* Connection closed; retrieval done. */
    +        eof = 1;
    +
    +        if (reply_hdr_state < 2)
    +            /*
    +             * Yes Henrik, there is a point to doing this.  When we
    +             * called httpProcessReplyHeader() before, we didn't find
    +             * the end of headers, but now we are definately at EOF, so
    +             * we want to process the reply headers.
    +             */
    +            /* doesn't return */
    +            processReplyHeader(buf, len);
    +        else {
    +            fwdComplete(fwd);
    +            do_next_read = 0;
    +            comm_close(fd);
    +        }
         } else {
    -	if (reply_hdr_state < 2) {
    -	    processReplyHeader(buf, len);
    -	    if (reply_hdr_state == 2) {
    -		http_status s = entry->getReply()->sline.status;
    +        if (reply_hdr_state < 2) {
    +            processReplyHeader(buf, len);
    +
    +            if (reply_hdr_state == 2) {
    +                http_status s = entry->getReply()->sline.status;
     #if WIP_FWD_LOG
    -		fwdStatus(fwd, s);
    +
    +                fwdStatus(fwd, s);
     #endif
    -		/*
    -		 * If its not a reply that we will re-forward, then
    -		 * allow the client to get it.
    -		 */
    -		if (!fwdReforwardableStatus(s))
    -		    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
    -	    }
    -	}
    -	processReplyData(buf, len);
    +                /*
    +                 * If its not a reply that we will re-forward, then
    +                 * allow the client to get it.
    +                 */
    +
    +                if (!fwdReforwardableStatus(s))
    +                    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
    +            }
    +        }
    +
    +        processReplyData(buf, len);
         }
     }
     
    @@ -736,83 +916,92 @@ void
     HttpStateData::processReplyData(const char *buf, size_t len)
     {
         if (reply_hdr_state < 2) {
    -	do_next_read = 1;
    -	maybeReadData();
    -	return;
    +        do_next_read = 1;
    +        maybeReadData();
    +        return;
         }
    +
         StoreIOBuffer tempBuffer;
    -       if (!flags.headers_pushed)
    -         {
    -           /* The first block needs us to skip the headers */
    -           /* TODO: make this cleaner. WE should push the headers, NOT the parser */
    -           size_t end = headersEnd (buf, len);
    -	   /* IF len > end, we need to append data after the 
    -	    * out of band update to the store
    -	    */
    -           if (len > end)
    -             {
    -               tempBuffer.data = (char *)buf+end;
    -               tempBuffer.length = len - end;
    -               tempBuffer.offset = currentOffset;
    -	       currentOffset += tempBuffer.length;
    -               entry->write (tempBuffer);
    -             }
    -           flags.headers_pushed = 1;
    -         }
    -       else
    -         {
    -           tempBuffer.data = (char *)buf;
    -           tempBuffer.length = len;
    -           tempBuffer.offset = currentOffset;
    -           currentOffset += len;
    -           entry->write(tempBuffer);
    -         }
    +
    +    if (!flags.headers_pushed) {
    +        /* The first block needs us to skip the headers */
    +        /* TODO: make this cleaner. WE should push the headers, NOT the parser */
    +        size_t end = headersEnd (buf, len);
    +        /* IF len > end, we need to append data after the
    +         * out of band update to the store
    +         */
    +
    +        if (len > end) {
    +            tempBuffer.data = (char *)buf+end;
    +            tempBuffer.length = len - end;
    +            tempBuffer.offset = currentOffset;
    +            currentOffset += tempBuffer.length;
    +            entry->write (tempBuffer);
    +        }
    +
    +        flags.headers_pushed = 1;
    +    } else {
    +        tempBuffer.data = (char *)buf;
    +        tempBuffer.length = len;
    +        tempBuffer.offset = currentOffset;
    +        currentOffset += len;
    +        entry->write(tempBuffer);
    +    }
     
         if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
    -	/*
    -	 * the above storeAppend() call could ABORT this entry,
    -	 * in that case, the server FD should already be closed.
    -	 * there's nothing for us to do.
    -	 */
    -	(void) 0;
    -    } else switch (persistentConnStatus()) {
    -      case INCOMPLETE_MSG:
    -        /* Wait for EOF condition */
    -        do_next_read = 1;
    -	break;
    -      case COMPLETE_PERSISTENT_MSG:
    -	/* yes we have to clear all these! */
    -	commSetDefer(fd, NULL, NULL);
    -	commSetTimeout(fd, -1, NULL, NULL);
    -	do_next_read = 0;
    +        /*
    +         * the above storeAppend() call could ABORT this entry,
    +         * in that case, the server FD should already be closed.
    +         * there's nothing for us to do.
    +         */
    +        (void) 0;
    +    } else
    +        switch (persistentConnStatus()) {
    +
    +        case INCOMPLETE_MSG:
    +            /* Wait for EOF condition */
    +            do_next_read = 1;
    +            break;
    +
    +        case COMPLETE_PERSISTENT_MSG:
    +            /* yes we have to clear all these! */
    +            commSetDefer(fd, NULL, NULL);
    +            commSetTimeout(fd, -1, NULL, NULL);
    +            do_next_read = 0;
     #if DELAY_POOLS
    -	DelayPools::ClearNoDelay(fd);
    +
    +            DelayPools::ClearNoDelay(fd);
     #endif
    -	comm_remove_close_handler(fd, httpStateFree, this);
    -	fwdUnregister(fd, fwd);
    -	pconnPush(fd, request->host, request->port);
    -	fwdComplete(fwd);
    -	fd = -1;
    -	httpStateFree(fd, this);
    -	return;
    -      case COMPLETE_NONPERSISTENT_MSG:
    -	/* close the connection ourselves */
    -	/* yes - same as for a complete persistent conn here */
    -	commSetDefer(fd, NULL, NULL);
    -	commSetTimeout(fd, -1, NULL, NULL);
    -	commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
    +
    +            comm_remove_close_handler(fd, httpStateFree, this);
    +            fwdUnregister(fd, fwd);
    +            pconnPush(fd, request->host, request->port);
    +            fwdComplete(fwd);
    +            fd = -1;
    +            httpStateFree(fd, this);
    +            return;
    +
    +        case COMPLETE_NONPERSISTENT_MSG:
    +            /* close the connection ourselves */
    +            /* yes - same as for a complete persistent conn here */
    +            commSetDefer(fd, NULL, NULL);
    +            commSetTimeout(fd, -1, NULL, NULL);
    +            commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
     #if DELAY_POOLS
    -	DelayPools::ClearNoDelay(fd);
    +
    +            DelayPools::ClearNoDelay(fd);
     #endif
    -	comm_remove_close_handler(fd, httpStateFree, this);
    -	fwdUnregister(fd, fwd);
    -	fwdComplete(fwd);
    -	/* TODO: check that fd is still open here */
    -	comm_close (fd);
    -	fd = -1;
    -	httpStateFree(fd, this);
    -	return;
    -    }
    +
    +            comm_remove_close_handler(fd, httpStateFree, this);
    +            fwdUnregister(fd, fwd);
    +            fwdComplete(fwd);
    +            /* TODO: check that fd is still open here */
    +            comm_close (fd);
    +            fd = -1;
    +            httpStateFree(fd, this);
    +            return;
    +        }
    +
         maybeReadData();
     }
     
    @@ -822,10 +1011,14 @@ HttpStateData::amountToRead()
         read_sz = SQUID_TCP_SO_RCVBUF;
     #if DELAY_POOLS
         /* special "if" only for http (for nodelay proxy conns) */
    +
         if (!DelayPools::IsNoDelay(fd))
    -	read_sz = entry->mem_obj->mostBytesAllowed().bytesWanted(1, read_sz);
    +        read_sz = entry->mem_obj->mostBytesAllowed().bytesWanted(1, read_sz);
    +
     #endif
    +
         debug (11,4)("HttpStateData::amountToRead: Returning %u\n", (unsigned) read_sz);
    +
         return read_sz;
     }
     
    @@ -833,7 +1026,7 @@ void
     HttpStateData::maybeReadData()
     {
         if (do_next_read) {
    -	do_next_read = 0;
    +        do_next_read = 0;
             comm_read(fd, buf, amountToRead(), httpReadReply, this);
         }
     }
    @@ -847,37 +1040,41 @@ HttpStateData::SendComplete(int fd, char *bufnotused, size_t size, comm_err_t er
         StoreEntry *entry = httpState->entry;
         ErrorState *err;
         debug(11, 5) ("httpSendComplete: FD %d: size %d: errflag %d.\n",
    -	fd, (int) size, errflag);
    +                  fd, (int) size, errflag);
     #if URL_CHECKSUM_DEBUG
    +
         entry->mem_obj->checkUrlChecksum();
     #endif
    +
         if (size > 0) {
    -	fd_bytes(fd, size, FD_WRITE);
    -	kb_incr(&statCounter.server.all.kbytes_out, size);
    -	kb_incr(&statCounter.server.http.kbytes_out, size);
    +        fd_bytes(fd, size, FD_WRITE);
    +        kb_incr(&statCounter.server.all.kbytes_out, size);
    +        kb_incr(&statCounter.server.http.kbytes_out, size);
         }
    +
         if (errflag == COMM_ERR_CLOSING)
    -	return;
    +        return;
    +
         if (errflag) {
    -	err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    -	err->xerrno = errno;
    -	err->request = requestLink(httpState->orig_request);
    -	errorAppendEntry(entry, err);
    -	comm_close(fd);
    -	return;
    +        err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    +        err->xerrno = errno;
    +        err->request = requestLink(httpState->orig_request);
    +        errorAppendEntry(entry, err);
    +        comm_close(fd);
    +        return;
         } else {
    -	/* Schedule read reply. */
    -	comm_read(fd, httpState->buf, httpState->amountToRead(), httpReadReply, httpState);
    -	/*
    -	 * Set the read timeout here because it hasn't been set yet.
    -	 * We only set the read timeout after the request has been
    -	 * fully written to the server-side.  If we start the timeout
    -	 * after connection establishment, then we are likely to hit
    -	 * the timeout for POST/PUT requests that have very large
    -	 * request bodies.
    -	 */
    -	commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
    -	commSetDefer(fd, StoreEntry::CheckDeferRead, entry);
    +        /* Schedule read reply. */
    +        comm_read(fd, httpState->buf, httpState->amountToRead(), httpReadReply, httpState);
    +        /*
    +         * Set the read timeout here because it hasn't been set yet.
    +         * We only set the read timeout after the request has been
    +         * fully written to the server-side.  If we start the timeout
    +         * after connection establishment, then we are likely to hit
    +         * the timeout for POST/PUT requests that have very large
    +         * request bodies.
    +         */
    +        commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
    +        commSetDefer(fd, StoreEntry::CheckDeferRead, entry);
         }
     }
     
    @@ -888,10 +1085,10 @@ HttpStateData::SendComplete(int fd, char *bufnotused, size_t size, comm_err_t er
      */
     void
     httpBuildRequestHeader(request_t * request,
    -    request_t * orig_request,
    -    StoreEntry * entry,
    -    HttpHeader * hdr_out,
    -    http_state_flags flags)
    +                       request_t * orig_request,
    +                       StoreEntry * entry,
    +                       HttpHeader * hdr_out,
    +                       http_state_flags flags)
     {
         /* building buffer for complex strings */
     #define BBUF_SZ (MAX_URL+32)
    @@ -903,147 +1100,172 @@ httpBuildRequestHeader(request_t * request,
         HttpHeaderPos pos = HttpHeaderInitPos;
         httpHeaderInit(hdr_out, hoRequest);
         /* append our IMS header */
    +
         if (request->lastmod > -1 && request->method == METHOD_GET)
    -	httpHeaderPutTime(hdr_out, HDR_IF_MODIFIED_SINCE, request->lastmod);
    +        httpHeaderPutTime(hdr_out, HDR_IF_MODIFIED_SINCE, request->lastmod);
     
         bool we_do_ranges = decideIfWeDoRanges (orig_request);
     
         strConnection = httpHeaderGetList(hdr_in, HDR_CONNECTION);
    +
         while ((e = httpHeaderGetEntry(hdr_in, &pos)))
    -	copyOneHeaderFromClientsideRequestToUpstreamRequest(e, strConnection, request, orig_request, hdr_out, we_do_ranges, flags);
    +        copyOneHeaderFromClientsideRequestToUpstreamRequest(e, strConnection, request, orig_request, hdr_out, we_do_ranges, flags);
     
         /* Abstraction break: We should interpret myultipart/byterange responses
          * into offset-length data, and this works around our inability to do so.
          */
    -    if (!we_do_ranges && orig_request->multipartRangeRequest())
    -      {
    -	/* don't cache the result */
    -	orig_request->flags.cachable = 0; 
    -	/* pretend it's not a range request */
    -	orig_request->range->deleteSelf();
    -	orig_request->range = NULL;
    -	orig_request->flags.range = 0;
    -      }
    +    if (!we_do_ranges && orig_request->multipartRangeRequest()) {
    +        /* don't cache the result */
    +        orig_request->flags.cachable = 0;
    +        /* pretend it's not a range request */
    +        orig_request->range->deleteSelf();
    +        orig_request->range = NULL;
    +        orig_request->flags.range = 0;
    +    }
     
     
         /* append Via */
         if (Config.onoff.via) {
    -	String strVia = httpHeaderGetList(hdr_in, HDR_VIA);
    -	snprintf(bbuf, BBUF_SZ, "%d.%d %s",
    -	    orig_request->http_ver.major,
    -	    orig_request->http_ver.minor, ThisCache);
    -	strListAdd(&strVia, bbuf, ',');
    -	httpHeaderPutStr(hdr_out, HDR_VIA, strVia.buf());
    -	strVia.clean();
    +        String strVia = httpHeaderGetList(hdr_in, HDR_VIA);
    +        snprintf(bbuf, BBUF_SZ, "%d.%d %s",
    +                 orig_request->http_ver.major,
    +                 orig_request->http_ver.minor, ThisCache);
    +        strListAdd(&strVia, bbuf, ',');
    +        httpHeaderPutStr(hdr_out, HDR_VIA, strVia.buf());
    +        strVia.clean();
         }
    +
         /* append X-Forwarded-For */
         strFwd = httpHeaderGetList(hdr_in, HDR_X_FORWARDED_FOR);
    +
         if (opt_forwarded_for && orig_request->client_addr.s_addr != no_addr.s_addr)
    -	strListAdd(&strFwd, inet_ntoa(orig_request->client_addr), ',');
    +        strListAdd(&strFwd, inet_ntoa(orig_request->client_addr), ',');
         else
    -	strListAdd(&strFwd, "unknown", ',');
    +        strListAdd(&strFwd, "unknown", ',');
    +
         httpHeaderPutStr(hdr_out, HDR_X_FORWARDED_FOR, strFwd.buf());
    +
         strFwd.clean();
     
         /* append Host if not there already */
         if (!httpHeaderHas(hdr_out, HDR_HOST)) {
    -	if (orig_request->peer_domain) {
    -	    httpHeaderPutStr(hdr_out, HDR_HOST, orig_request->peer_domain);
    -	} else if (orig_request->port == urlDefaultPort(orig_request->protocol)) {
    -	    /* use port# only if not default */
    -	    httpHeaderPutStr(hdr_out, HDR_HOST, orig_request->host);
    -	} else {
    -	    httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d",
    -		orig_request->host, (int) orig_request->port);
    -	}
    +        if (orig_request->peer_domain) {
    +            httpHeaderPutStr(hdr_out, HDR_HOST, orig_request->peer_domain);
    +        } else if (orig_request->port == urlDefaultPort(orig_request->protocol)) {
    +            /* use port# only if not default */
    +            httpHeaderPutStr(hdr_out, HDR_HOST, orig_request->host);
    +        } else {
    +            httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d",
    +                              orig_request->host, (int) orig_request->port);
    +        }
         }
    +
         /* append Authorization if known in URL, not in header and going direct */
         if (!httpHeaderHas(hdr_out, HDR_AUTHORIZATION)) {
    -	if (!request->flags.proxying && *request->login) {
    -	    httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
    -		base64_encode(request->login));
    -	}
    +        if (!request->flags.proxying && *request->login) {
    +            httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
    +                              base64_encode(request->login));
    +        }
         }
    +
         /* append Proxy-Authorization if configured for peer, and proxying */
         if (request->flags.proxying && orig_request->peer_login &&
    -	!httpHeaderHas(hdr_out, HDR_PROXY_AUTHORIZATION)) {
    -	if (*orig_request->peer_login == '*') {
    -	    /* Special mode, to pass the username to the upstream cache */
    -	    char loginbuf[256];
    -	    const char *username = "-";
    -	    if (orig_request->auth_user_request)
    -		username = orig_request->auth_user_request->username();
    -	    snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
    -	    httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
    -		base64_encode(loginbuf));
    -	} else if (strcmp(orig_request->peer_login, "PASS") == 0) {
    -	    /* Nothing to do */
    -	} else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
    -	    /* Nothing to do */
    -	} else {
    -	    httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
    -		base64_encode(orig_request->peer_login));
    -	}
    +            !httpHeaderHas(hdr_out, HDR_PROXY_AUTHORIZATION)) {
    +        if (*orig_request->peer_login == '*') {
    +            /* Special mode, to pass the username to the upstream cache */
    +            char loginbuf[256];
    +            const char *username = "-";
    +
    +            if (orig_request->auth_user_request)
    +                username = orig_request->auth_user_request->username();
    +
    +            snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
    +
    +            httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
    +                              base64_encode(loginbuf));
    +        } else if (strcmp(orig_request->peer_login, "PASS") == 0) {
    +            /* Nothing to do */
    +        } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
    +            /* Nothing to do */
    +        } else {
    +            httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
    +                              base64_encode(orig_request->peer_login));
    +        }
         }
    +
         /* append WWW-Authorization if configured for peer */
         if (flags.originpeer && orig_request->peer_login &&
    -	    !httpHeaderHas(hdr_out, HDR_AUTHORIZATION)) {
    -	if (strcmp(orig_request->peer_login, "PASS") == 0) {
    -	    /* No credentials to forward.. (should have been done above if available) */
    -	} else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
    -	    /* Special mode, convert proxy authentication to WWW authentication
    -	     */
    -	    const char *auth = httpHeaderGetStr(hdr_in, HDR_PROXY_AUTHORIZATION);
    -	    if (auth && strncasecmp(auth, "basic ", 6) == 0) {
    -		httpHeaderPutStr(hdr_out, HDR_AUTHORIZATION, auth);
    -	    }
    -	} else if (*orig_request->peer_login == '*') {
    -	    /* Special mode, to pass the username to the upstream cache */
    -	    char loginbuf[256];
    -	    const char *username = "-";
    -	    if (orig_request->auth_user_request)
    -	    username = authenticateUserRequestUsername(orig_request->auth_user_request);
    -	    snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
    -	    httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
    -		base64_encode(loginbuf));
    -	} else {
    -	    /* Fixed login string */
    -	    httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
    -		base64_encode(orig_request->peer_login));
    -	}
    +            !httpHeaderHas(hdr_out, HDR_AUTHORIZATION)) {
    +        if (strcmp(orig_request->peer_login, "PASS") == 0) {
    +            /* No credentials to forward.. (should have been done above if available) */
    +        } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
    +            /* Special mode, convert proxy authentication to WWW authentication
    +             */
    +            const char *auth = httpHeaderGetStr(hdr_in, HDR_PROXY_AUTHORIZATION);
    +
    +            if (auth && strncasecmp(auth, "basic ", 6) == 0) {
    +                httpHeaderPutStr(hdr_out, HDR_AUTHORIZATION, auth);
    +            }
    +        } else if (*orig_request->peer_login == '*') {
    +            /* Special mode, to pass the username to the upstream cache */
    +            char loginbuf[256];
    +            const char *username = "-";
    +
    +            if (orig_request->auth_user_request)
    +                username = authenticateUserRequestUsername(orig_request->auth_user_request);
    +
    +            snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
    +
    +            httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
    +                              base64_encode(loginbuf));
    +        } else {
    +            /* Fixed login string */
    +            httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
    +                              base64_encode(orig_request->peer_login));
    +        }
         }
    +
         /* append Cache-Control, add max-age if not there already */
         {
    -	HttpHdrCc *cc = httpHeaderGetCc(hdr_in);
    -	if (!cc)
    -	    cc = httpHdrCcCreate();
    -	if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) {
    -	    const char *url = entry ? storeUrl(entry) : urlCanonical(orig_request);
    -	    httpHdrCcSetMaxAge(cc, getMaxAge(url));
    -	    if (request->urlpath.size())
    -		assert(strstr(url, request->urlpath.buf()));
    -	}
    -	if (flags.only_if_cached)
    -	    EBIT_SET(cc->mask, CC_ONLY_IF_CACHED);
    -	httpHeaderPutCc(hdr_out, cc);
    -	httpHdrCcDestroy(cc);
    +        HttpHdrCc *cc = httpHeaderGetCc(hdr_in);
    +
    +        if (!cc)
    +            cc = httpHdrCcCreate();
    +
    +        if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) {
    +            const char *url = entry ? storeUrl(entry) : urlCanonical(orig_request);
    +            httpHdrCcSetMaxAge(cc, getMaxAge(url));
    +
    +            if (request->urlpath.size())
    +                assert(strstr(url, request->urlpath.buf()));
    +        }
    +
    +        if (flags.only_if_cached)
    +            EBIT_SET(cc->mask, CC_ONLY_IF_CACHED);
    +
    +        httpHeaderPutCc(hdr_out, cc);
    +
    +        httpHdrCcDestroy(cc);
         }
    +
         /* maybe append Connection: keep-alive */
         if (flags.keepalive) {
    -	if (flags.proxying) {
    -	    httpHeaderPutStr(hdr_out, HDR_PROXY_CONNECTION, "keep-alive");
    -	} else {
    -	    httpHeaderPutStr(hdr_out, HDR_CONNECTION, "keep-alive");
    -	}
    +        if (flags.proxying) {
    +            httpHeaderPutStr(hdr_out, HDR_PROXY_CONNECTION, "keep-alive");
    +        } else {
    +            httpHeaderPutStr(hdr_out, HDR_CONNECTION, "keep-alive");
    +        }
         }
    +
         /* append Front-End-Https */
         if (flags.front_end_https) {
    -	if (flags.front_end_https == 1 || request->protocol == PROTO_HTTPS)
    -	    httpHeaderPutStr(hdr_out, HDR_FRONT_END_HTTPS, "On");
    +        if (flags.front_end_https == 1 || request->protocol == PROTO_HTTPS)
    +            httpHeaderPutStr(hdr_out, HDR_FRONT_END_HTTPS, "On");
         }
     
         /* Now mangle the headers. */
         httpHdrMangleList(hdr_out, request);
    +
         strConnection.clean();
     }
     
    @@ -1052,139 +1274,174 @@ void
     copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, String strConnection, request_t * request, request_t * orig_request, HttpHeader * hdr_out, int we_do_ranges, http_state_flags flags)
     {
         debug(11, 5) ("httpBuildRequestHeader: %s: %s\n",
    -       e->name.buf(), e->value.buf());
    +                  e->name.buf(), e->value.buf());
    +
         if (!httpRequestHdrAllowed(e, &strConnection)) {
    -       debug(11, 2) ("'%s' header denied by anonymize_headers configuration\n",+       e->name.buf());
    -       return;
    +        debug(11, 2) ("'%s' header denied by anonymize_headers configuration\n",+       e->name.buf());
    +        return;
         }
    +
         switch (e->id) {
    +
         case HDR_PROXY_AUTHORIZATION:
    -	/* Only pass on proxy authentication to peers for which
    -	 * authentication forwarding is explicitly enabled
    -	 */
    -	if (flags.proxying && orig_request->peer_login &&
    -		strcmp(orig_request->peer_login, "PASS") == 0) {
    -	    httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	}
    -	break;
    +        /* Only pass on proxy authentication to peers for which
    +         * authentication forwarding is explicitly enabled
    +         */
    +
    +        if (flags.proxying && orig_request->peer_login &&
    +                strcmp(orig_request->peer_login, "PASS") == 0) {
    +            httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +        }
    +
    +        break;
    +
         case HDR_AUTHORIZATION:
    -	/* Pass on WWW authentication */
    -	if (!flags.originpeer) {
    -	    httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	} else {
    -	    /* In accelerators, only forward authentication if enabled
    -	     * (see also below for proxy->server authentication)
    -	     */
    -	    if (orig_request->peer_login && (strcmp(orig_request->peer_login, "PASS") == 0 || strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
    -		httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	    }
    -	}
    -	break;
    +        /* Pass on WWW authentication */
    +
    +        if (!flags.originpeer) {
    +            httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +        } else {
    +            /* In accelerators, only forward authentication if enabled
    +             * (see also below for proxy->server authentication)
    +             */
    +
    +            if (orig_request->peer_login && (strcmp(orig_request->peer_login, "PASS") == 0 || strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
    +                httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +            }
    +        }
    +
    +        break;
    +
         case HDR_HOST:
    -	/*
    -	 * Normally Squid does not copy the Host: header from
    -	 * a client request into the forwarded request headers.
    -	 * However, there is one case when we do: If the URL
    -	 * went through our redirector and the admin configured
    -	 * 'redir_rewrites_host' to be off.
    -	 */
    -	if (request->flags.redirected)
    -	    if (!Config.onoff.redir_rewrites_host)
    -		httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	break;
    +        /*
    +         * Normally Squid does not copy the Host: header from
    +         * a client request into the forwarded request headers.
    +         * However, there is one case when we do: If the URL
    +         * went through our redirector and the admin configured
    +         * 'redir_rewrites_host' to be off.
    +         */
    +
    +        if (request->flags.redirected)
    +            if (!Config.onoff.redir_rewrites_host)
    +                httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +
    +        break;
    +
         case HDR_IF_MODIFIED_SINCE:
    -	/* append unless we added our own;
    -	 * note: at most one client's ims header can pass through */
    -	if (!httpHeaderHas(hdr_out, HDR_IF_MODIFIED_SINCE))
    -	    httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	break;
    +        /* append unless we added our own;
    +         * note: at most one client's ims header can pass through */
    +        if (!httpHeaderHas(hdr_out, HDR_IF_MODIFIED_SINCE))
    +            httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +
    +        break;
    +
         case HDR_MAX_FORWARDS:
    -	if (orig_request->method == METHOD_TRACE) {
    -	    const int hops = httpHeaderEntryGetInt(e);
    -	if (hops > 0)
    -	    httpHeaderPutInt(hdr_out, HDR_MAX_FORWARDS, hops - 1);
    -	}
    -	break;
    +        if (orig_request->method == METHOD_TRACE) {
    +            const int hops = httpHeaderEntryGetInt(e);
    +
    +            if (hops > 0)
    +                httpHeaderPutInt(hdr_out, HDR_MAX_FORWARDS, hops - 1);
    +        }
    +
    +        break;
    +
         case HDR_VIA:
    -	/* If Via is disabled then forward any received header as-is */
    -	if (!Config.onoff.via)
    -	    httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	break;
    +        /* If Via is disabled then forward any received header as-is */
    +
    +        if (!Config.onoff.via)
    +            httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +
    +        break;
    +
         case HDR_RANGE:
    +
         case HDR_IF_RANGE:
    +
         case HDR_REQUEST_RANGE:
    -	if (!we_do_ranges)
    -	    httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	break;
    +        if (!we_do_ranges)
    +            httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +
    +        break;
    +
         case HDR_PROXY_CONNECTION:
    +
         case HDR_CONNECTION:
    +
         case HDR_X_FORWARDED_FOR:
    +
         case HDR_CACHE_CONTROL:
    -	/* append these after the loop if needed */
    -	break;
    +        /* append these after the loop if needed */
    +        break;
    +
         case HDR_FRONT_END_HTTPS:
    -	if (!flags.front_end_https)
    -	    httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    -	break;
    +        if (!flags.front_end_https)
    +            httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +
    +        break;
    +
         default:
    -	/* pass on all other header fields */
    -	httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
    +        /* pass on all other header fields */
    +        httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
         }
     }
     
     int
     decideIfWeDoRanges (request_t * orig_request)
     {
    -  int result = 1;
    -  /* decide if we want to do Ranges ourselves
    -   * and fetch the whole object now)
    -   * We want to handle Ranges ourselves iff
    -   *    - we can actually parse client Range specs
    -   *    - the specs are expected to be simple enough (e.g. no out-of-order ranges)
    -   *    - reply will be cachable
    -   * (If the reply will be uncachable we have to throw it away after
    -   *  serving this request, so it is better to forward ranges to
    -   *  the server and fetch only the requested content)
    -   */
    -  if (NULL == orig_request->range || !orig_request->flags.cachable
    -      || orig_request->range->offsetLimitExceeded())
    -      result = 0;
    -  debug(11, 8) ("decideIfWeDoRanges: range specs: %p, cachable: %d; we_do_ranges: %d\n",
    -    orig_request->range, orig_request->flags.cachable, result);
    -  return result;
    +    int result = 1;
    +    /* decide if we want to do Ranges ourselves
    +     * and fetch the whole object now)
    +     * We want to handle Ranges ourselves iff
    +     *    - we can actually parse client Range specs
    +     *    - the specs are expected to be simple enough (e.g. no out-of-order ranges)
    +     *    - reply will be cachable
    +     * (If the reply will be uncachable we have to throw it away after
    +     *  serving this request, so it is better to forward ranges to
    +     *  the server and fetch only the requested content)
    +     */
    +
    +    if (NULL == orig_request->range || !orig_request->flags.cachable
    +            || orig_request->range->offsetLimitExceeded())
    +        result = 0;
    +
    +    debug(11, 8) ("decideIfWeDoRanges: range specs: %p, cachable: %d; we_do_ranges: %d\n",
    +                  orig_request->range, orig_request->flags.cachable, result);
    +
    +    return result;
     }
     
     
    -/* build request prefix and append it to a given MemBuf; 
    +/* build request prefix and append it to a given MemBuf;
      * return the length of the prefix */
     mb_size_t
     httpBuildRequestPrefix(request_t * request,
    -    request_t * orig_request,
    -    StoreEntry * entry,
    -    MemBuf * mb,
    -    http_state_flags flags)
    +                       request_t * orig_request,
    +                       StoreEntry * entry,
    +                       MemBuf * mb,
    +                       http_state_flags flags)
     {
         const int offset = mb->size;
         http_version_t httpver;
         httpBuildVersion(&httpver, 1, 0);
         memBufPrintf(mb, "%s %s HTTP/%d.%d\r\n",
    -	RequestMethodStr[request->method],
    -	request->urlpath.size() ? request->urlpath.buf() : "/",
    -	httpver.major,httpver.minor);
    +                 RequestMethodStr[request->method],
    +                 request->urlpath.size() ? request->urlpath.buf() : "/",
    +                 httpver.major,httpver.minor);
         /* build and pack headers */
         {
    -	HttpHeader hdr;
    -	Packer p;
    -	httpBuildRequestHeader(request, orig_request, entry, &hdr, flags);
    -	packerToMemInit(&p, mb);
    -	httpHeaderPackInto(&hdr, &p);
    -	httpHeaderClean(&hdr);
    -	packerClean(&p);
    +        HttpHeader hdr;
    +        Packer p;
    +        httpBuildRequestHeader(request, orig_request, entry, &hdr, flags);
    +        packerToMemInit(&p, mb);
    +        httpHeaderPackInto(&hdr, &p);
    +        httpHeaderClean(&hdr);
    +        packerClean(&p);
         }
         /* append header terminator */
         memBufAppend(mb, crlf, 2);
         return mb->size - offset;
     }
    +
     /* This will be called when connect completes. Write request. */
     static void
     httpSendRequest(HttpStateData * httpState)
    @@ -1198,45 +1455,49 @@ httpSendRequest(HttpStateData * httpState)
         debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", httpState->fd, httpState);
     
         if (httpState->orig_request->body_connection)
    -	sendHeaderDone = httpSendRequestEntity;
    +        sendHeaderDone = httpSendRequestEntity;
         else
    -	sendHeaderDone = HttpStateData::SendComplete;
    +        sendHeaderDone = HttpStateData::SendComplete;
     
         if (p != NULL) {
    -	if (p->options.originserver) {
    -	    httpState->flags.proxying = 0;
    -	    httpState->flags.originpeer = 1;
    -	} else {
    -	    httpState->flags.proxying = 1;
    -	    httpState->flags.originpeer = 0;
    -	}
    +        if (p->options.originserver) {
    +            httpState->flags.proxying = 0;
    +            httpState->flags.originpeer = 1;
    +        } else {
    +            httpState->flags.proxying = 1;
    +            httpState->flags.originpeer = 0;
    +        }
         } else {
    -	httpState->flags.proxying = 0;
    -	httpState->flags.originpeer = 0;
    +        httpState->flags.proxying = 0;
    +        httpState->flags.originpeer = 0;
         }
    +
         /*
          * Is keep-alive okay for all request methods?
          */
         if (!Config.onoff.server_pconns)
    -	httpState->flags.keepalive = 0;
    +        httpState->flags.keepalive = 0;
         else if (p == NULL)
    -	httpState->flags.keepalive = 1;
    +        httpState->flags.keepalive = 1;
         else if (p->stats.n_keepalives_sent < 10)
    -	httpState->flags.keepalive = 1;
    +        httpState->flags.keepalive = 1;
         else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50)
    -	httpState->flags.keepalive = 1;
    +        httpState->flags.keepalive = 1;
    +
         if (httpState->_peer) {
    -	if (neighborType(httpState->_peer, httpState->request) == PEER_SIBLING &&
    -	    !httpState->_peer->options.allow_miss)
    -	    httpState->flags.only_if_cached = 1;
    -	httpState->flags.front_end_https = httpState->_peer->front_end_https;
    +        if (neighborType(httpState->_peer, httpState->request) == PEER_SIBLING &&
    +                !httpState->_peer->options.allow_miss)
    +            httpState->flags.only_if_cached = 1;
    +
    +        httpState->flags.front_end_https = httpState->_peer->front_end_https;
         }
    +
         memBufDefInit(&mb);
         httpBuildRequestPrefix(req,
    -	httpState->orig_request,
    -	entry,
    -	&mb,
    -	httpState->flags);
    +                           httpState->orig_request,
    +                           entry,
    +                           &mb,
    +                           httpState->flags);
         debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", httpState->fd, mb.buf);
         comm_old_write_mbuf(httpState->fd, mb, sendHeaderDone, httpState);
     }
    @@ -1249,54 +1510,76 @@ httpStart(FwdState * fwd)
         request_t *proxy_req;
         request_t *orig_req = fwd->request;
         debug(11, 3) ("httpStart: \"%s %s\"\n",
    -	RequestMethodStr[orig_req->method],
    -	storeUrl(fwd->entry));
    +                  RequestMethodStr[orig_req->method],
    +                  storeUrl(fwd->entry));
         CBDATA_INIT_TYPE(HttpStateData);
         httpState = cbdataAlloc(HttpStateData);
         storeLockObject(fwd->entry);
         httpState->fwd = fwd;
         httpState->entry = fwd->entry;
         httpState->fd = fd;
    +
         if (fwd->servers)
    -	httpState->_peer = fwd->servers->_peer;		/* might be NULL */
    +        httpState->_peer = fwd->servers->_peer;		/* might be NULL */
    +
         if (httpState->_peer) {
    -	const char *url;
    -	if (httpState->_peer->options.originserver)
    -	    url = orig_req->urlpath.buf();
    -	else
    -	    url = storeUrl(httpState->entry);
    -	proxy_req = requestCreate(orig_req->method,
    -	    orig_req->protocol, url);
    -	xstrncpy(proxy_req->host, httpState->_peer->host, SQUIDHOSTNAMELEN);
    -	proxy_req->port = httpState->_peer->http_port;
    -	proxy_req->flags = orig_req->flags;
    -	proxy_req->lastmod = orig_req->lastmod;
    -	httpState->request = requestLink(proxy_req);
    -	httpState->orig_request = requestLink(orig_req);
    -	proxy_req->flags.proxying = 1;
    -	/*
    -	 * This NEIGHBOR_PROXY_ONLY check probably shouldn't be here.
    -	 * We might end up getting the object from somewhere else if,
    -	 * for example, the request to this neighbor fails.
    -	 */
    -	if (httpState->_peer->options.proxy_only)
    -	    storeReleaseRequest(httpState->entry);
    +        const char *url;
    +
    +        if (httpState->_peer->options.originserver)
    +            url = orig_req->urlpath.buf();
    +        else
    +            url = storeUrl(httpState->entry);
    +
    +        proxy_req = requestCreate(orig_req->method,
    +                                  orig_req->protocol, url);
    +
    +        xstrncpy(proxy_req->host, httpState->_peer->host, SQUIDHOSTNAMELEN);
    +
    +        proxy_req->port = httpState->_peer->http_port;
    +
    +        proxy_req->flags = orig_req->flags;
    +
    +        proxy_req->lastmod = orig_req->lastmod;
    +
    +        httpState->request = requestLink(proxy_req);
    +
    +        httpState->orig_request = requestLink(orig_req);
    +
    +        proxy_req->flags.proxying = 1;
    +
    +        /*
    +         * This NEIGHBOR_PROXY_ONLY check probably shouldn't be here.
    +         * We might end up getting the object from somewhere else if,
    +         * for example, the request to this neighbor fails.
    +         */
    +        if (httpState->_peer->options.proxy_only)
    +            storeReleaseRequest(httpState->entry);
    +
     #if DELAY_POOLS
    -	assert(DelayPools::IsNoDelay(fd) == 0);
    -	if (httpState->_peer->options.no_delay)
    -	    DelayPools::SetNoDelay(fd);
    +
    +        assert(DelayPools::IsNoDelay(fd) == 0);
    +
    +        if (httpState->_peer->options.no_delay)
    +            DelayPools::SetNoDelay(fd);
    +
     #endif
    +
         } else {
    -	httpState->request = requestLink(orig_req);
    -	httpState->orig_request = requestLink(orig_req);
    +        httpState->request = requestLink(orig_req);
    +        httpState->orig_request = requestLink(orig_req);
         }
    +
         /*
          * register the handler to free HTTP state data when the FD closes
          */
         comm_add_close_handler(fd, httpStateFree, httpState);
    +
         statCounter.server.all.requests++;
    +
         statCounter.server.http.requests++;
    +
         httpSendRequest(httpState);
    +
         /*
          * We used to set the read timeout here, but not any more.
          * Now its set in httpSendComplete() after the full request,
    @@ -1310,17 +1593,18 @@ httpSendRequestEntityDone(int fd, void *data)
         HttpStateData *httpState = static_cast(data);
         ACLChecklist ch;
         debug(11, 5) ("httpSendRequestEntityDone: FD %d\n",
    -	fd);
    +                  fd);
         ch.request = requestLink(httpState->request);
    +
         if (!Config.accessList.brokenPosts) {
    -	debug(11, 5) ("httpSendRequestEntityDone: No brokenPosts list\n");
    -	HttpStateData::SendComplete(fd, NULL, 0, COMM_OK, data);
    +        debug(11, 5) ("httpSendRequestEntityDone: No brokenPosts list\n");
    +        HttpStateData::SendComplete(fd, NULL, 0, COMM_OK, data);
         } else if (!aclCheckFast(Config.accessList.brokenPosts, &ch)) {
    -	debug(11, 5) ("httpSendRequestEntityDone: didn't match brokenPosts\n");
    -	HttpStateData::SendComplete(fd, NULL, 0, COMM_OK, data);
    +        debug(11, 5) ("httpSendRequestEntityDone: didn't match brokenPosts\n");
    +        HttpStateData::SendComplete(fd, NULL, 0, COMM_OK, data);
         } else {
    -	debug(11, 2) ("httpSendRequestEntityDone: matched brokenPosts\n");
    -	comm_old_write(fd, "\r\n", 2, HttpStateData::SendComplete, data, NULL);
    +        debug(11, 2) ("httpSendRequestEntityDone: matched brokenPosts\n");
    +        comm_old_write(fd, "\r\n", 2, HttpStateData::SendComplete, data, NULL);
         }
     }
     
    @@ -1328,16 +1612,17 @@ static void
     httpRequestBodyHandler(char *buf, ssize_t size, void *data)
     {
         HttpStateData *httpState = (HttpStateData *) data;
    +
         if (size > 0) {
    -	comm_old_write(httpState->fd, buf, size, httpSendRequestEntity, data, memFree8K);
    +        comm_old_write(httpState->fd, buf, size, httpSendRequestEntity, data, memFree8K);
         } else if (size == 0) {
    -	/* End of body */
    -	memFree8K(buf);
    -	httpSendRequestEntityDone(httpState->fd, data);
    +        /* End of body */
    +        memFree8K(buf);
    +        httpSendRequestEntityDone(httpState->fd, data);
         } else {
    -	/* Failed to get whole body, probably aborted */
    -	memFree8K(buf);
    -	HttpStateData::SendComplete(httpState->fd, NULL, 0, COMM_ERR_CLOSING, data);
    +        /* Failed to get whole body, probably aborted */
    +        memFree8K(buf);
    +        HttpStateData::SendComplete(httpState->fd, NULL, 0, COMM_ERR_CLOSING, data);
         }
     }
     
    @@ -1348,26 +1633,31 @@ httpSendRequestEntity(int fd, char *bufnotused, size_t size, comm_err_t errflag,
         StoreEntry *entry = httpState->entry;
         ErrorState *err;
         debug(11, 5) ("httpSendRequestEntity: FD %d: size %d: errflag %d.\n",
    -	fd, (int) size, errflag);
    +                  fd, (int) size, errflag);
    +
         if (size > 0) {
    -	fd_bytes(fd, size, FD_WRITE);
    -	kb_incr(&statCounter.server.all.kbytes_out, size);
    -	kb_incr(&statCounter.server.http.kbytes_out, size);
    +        fd_bytes(fd, size, FD_WRITE);
    +        kb_incr(&statCounter.server.all.kbytes_out, size);
    +        kb_incr(&statCounter.server.http.kbytes_out, size);
         }
    +
         if (errflag == COMM_ERR_CLOSING)
    -	return;
    +        return;
    +
         if (errflag) {
    -	err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    -	err->xerrno = errno;
    -	err->request = requestLink(httpState->orig_request);
    -	errorAppendEntry(entry, err);
    -	comm_close(fd);
    -	return;
    +        err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
    +        err->xerrno = errno;
    +        err->request = requestLink(httpState->orig_request);
    +        errorAppendEntry(entry, err);
    +        comm_close(fd);
    +        return;
         }
    +
         if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
    -	comm_close(fd);
    -	return;
    +        comm_close(fd);
    +        return;
         }
    +
         clientReadBody(httpState->orig_request, (char *)memAllocate(MEM_8K_BUF), 8192, httpRequestBodyHandler, httpState);
     }
     
    diff --git a/src/http.h b/src/http.h
    index a8fdadf912..49b650681d 100644
    --- a/src/http.h
    +++ b/src/http.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: http.h,v 1.4 2003/02/13 22:20:38 robertc Exp $
    + * $Id: http.h,v 1.5 2003/02/21 22:50:09 robertc Exp $
      *
      *
      * SQUID Web Proxy Cache          http://www.squid-cache.org/
    @@ -37,9 +37,11 @@
     #include "StoreIOBuffer.h"
     #include "comm.h"
     
    -class HttpStateData {
    -    public:
    -      static CWCB SendComplete;
    +class HttpStateData
    +{
    +
    +public:
    +    static CWCB SendComplete;
         void processReplyHeader(const char *, int);
         void processReplyData(const char *, size_t);
         IOCB readReply;
    @@ -60,11 +62,12 @@ class HttpStateData {
         int do_next_read;
         size_t read_sz;
         char buf[SQUID_TCP_SO_RCVBUF];
    +
     private:
         enum ConnectionStatus {
    -	INCOMPLETE_MSG,
    -	COMPLETE_PERSISTENT_MSG,
    -	COMPLETE_NONPERSISTENT_MSG
    +        INCOMPLETE_MSG,
    +        COMPLETE_PERSISTENT_MSG,
    +        COMPLETE_NONPERSISTENT_MSG
         };
         ConnectionStatus statusIfComplete() const;
         ConnectionStatus persistentConnStatus() const;
    diff --git a/src/icmp.cc b/src/icmp.cc
    index d8e7741fcb..c941436b26 100644
    --- a/src/icmp.cc
    +++ b/src/icmp.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: icmp.cc,v 1.82 2003/01/23 00:37:22 robertc Exp $
    + * $Id: icmp.cc,v 1.83 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 37    ICMP Routines
      * AUTHOR: Duane Wessels
    @@ -48,20 +48,29 @@
     static PF icmpRecv;
     static void icmpSend(pingerEchoData * pkt, int len);
     #if ALLOW_SOURCE_PING
    +
     static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf);
     #endif
     
     static void
    +
     icmpSendEcho(struct in_addr to, int opcode, const char *payload, int len)
     {
         static pingerEchoData pecho;
    +
         if (payload && len == 0)
    -	len = strlen(payload);
    +        len = strlen(payload);
    +
         assert(len <= PINGER_PAYLOAD_SZ);
    +
         pecho.to = to;
    +
         pecho.opcode = (unsigned char) opcode;
    +
         pecho.psize = len;
    +
         xmemcpy(pecho.payload, payload, len);
    +
         icmpSend(&pecho, sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + len);
     }
     
    @@ -71,39 +80,53 @@ icmpRecv(int unused1, void *unused2)
         int n;
         static int fail_count = 0;
         pingerReplyData preply;
    +
         static struct sockaddr_in F;
         commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0);
         memset(&preply, '\0', sizeof(pingerReplyData));
         n = comm_udp_recv(icmp_sock,
    -	(char *) &preply,
    -	sizeof(pingerReplyData),
    -	0);
    +                      (char *) &preply,
    +                      sizeof(pingerReplyData),
    +                      0);
    +
         if (n < 0) {
    -	debug(37, 1) ("icmpRecv: recv: %s\n", xstrerror());
    -	if (++fail_count == 10 || errno == ECONNREFUSED)
    -	    icmpClose();
    -	return;
    +        debug(37, 1) ("icmpRecv: recv: %s\n", xstrerror());
    +
    +        if (++fail_count == 10 || errno == ECONNREFUSED)
    +            icmpClose();
    +
    +        return;
         }
    +
         fail_count = 0;
    +
         if (n == 0)			/* test probe from pinger */
    -	return;
    +        return;
    +
         F.sin_family = AF_INET;
    +
         F.sin_addr = preply.from;
    +
         F.sin_port = 0;
    +
         switch (preply.opcode) {
    +
         case S_ICMP_ECHO:
    -	break;
    +        break;
     #if ALLOW_SOURCE_PING
    +
         case S_ICMP_ICP:
    -	icmpHandleSourcePing(&F, preply.payload);
    -	break;
    +        icmpHandleSourcePing(&F, preply.payload);
    +        break;
     #endif
    +
         case S_ICMP_DOM:
    -	netdbHandlePingReply(&F, preply.hops, preply.rtt);
    -	break;
    +        netdbHandlePingReply(&F, preply.hops, preply.rtt);
    +        break;
    +
         default:
    -	debug(37, 1) ("icmpRecv: Bad opcode: %d\n", (int) preply.opcode);
    -	break;
    +        debug(37, 1) ("icmpRecv: Bad opcode: %d\n", (int) preply.opcode);
    +        break;
         }
     }
     
    @@ -111,24 +134,30 @@ static void
     icmpSend(pingerEchoData * pkt, int len)
     {
         int x;
    +
         if (icmp_sock < 0)
    -	return;
    +        return;
    +
         debug(37, 2) ("icmpSend: to %s, opcode %d, len %d\n",
    -	inet_ntoa(pkt->to), (int) pkt->opcode, pkt->psize);
    +                  inet_ntoa(pkt->to), (int) pkt->opcode, pkt->psize);
    +
         x = comm_udp_send(icmp_sock, (char *) pkt, len, 0);
    +
         if (x < 0) {
    -	debug(37, 1) ("icmpSend: send: %s\n", xstrerror());
    -	if (errno == ECONNREFUSED || errno == EPIPE) {
    -	    icmpClose();
    -	    return;
    -	}
    +        debug(37, 1) ("icmpSend: send: %s\n", xstrerror());
    +
    +        if (errno == ECONNREFUSED || errno == EPIPE) {
    +            icmpClose();
    +            return;
    +        }
         } else if (x != len) {
    -	debug(37, 1) ("icmpSend: Wrote %d of %d bytes\n", x, len);
    +        debug(37, 1) ("icmpSend: Wrote %d of %d bytes\n", x, len);
         }
     }
     
     #if ALLOW_SOURCE_PING
     static void
    +
     icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf)
     {
         const cache_key *key;
    @@ -138,7 +167,7 @@ icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf)
         url = buf + sizeof(icp_common_t);
         key = icpGetCacheKey(url, (int) header.reqnum);
         debug(37, 3) ("icmpHandleSourcePing: from %s, key '%s'\n",
    -	inet_ntoa(from->sin_addr), storeKeyText(key));
    +                  inet_ntoa(from->sin_addr), storeKeyText(key));
         /* call neighborsUdpAck even if ping_status != PING_WAITING */
         neighborsUdpAck(key, &header, from);
     }
    @@ -149,6 +178,7 @@ icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf)
     
     #if ALLOW_SOURCE_PING
     void
    +
     icmpSourcePing(struct in_addr to, const icp_common_t * header, const char *url)
     {
     #if USE_ICMP
    @@ -156,20 +186,31 @@ icmpSourcePing(struct in_addr to, const icp_common_t * header, const char *url)
         int len;
         int ulen;
         debug(37, 3) ("icmpSourcePing: '%s'\n", url);
    +
         if ((ulen = strlen(url)) > MAX_URL)
    -	return;
    +        return;
    +
         payload = memAllocate(MEM_8K_BUF);
    +
         len = sizeof(icp_common_t);
    +
         xmemcpy(payload, header, len);
    +
         strcpy(payload + len, url);
    +
         len += ulen + 1;
    +
         icmpSendEcho(to, S_ICMP_ICP, payload, len);
    +
         memFree(payload, MEM_8K_BUF);
    +
     #endif
     }
    +
     #endif
     
     void
    +
     icmpDomainPing(struct in_addr to, const char *domain)
     {
     #if USE_ICMP
    @@ -189,19 +230,27 @@ icmpOpen(void)
         args[0] = "(pinger)";
         args[1] = NULL;
         x = ipcCreate(IPC_DGRAM,
    -	Config.Program.pinger,
    -	args,
    -	"Pinger Socket",
    -	&rfd,
    -	&wfd);
    +                  Config.Program.pinger,
    +                  args,
    +                  "Pinger Socket",
    +                  &rfd,
    +                  &wfd);
    +
         if (x < 0)
    -	return;
    +        return;
    +
         assert(rfd == wfd);
    +
         icmp_sock = rfd;
    +
         fd_note(icmp_sock, "pinger");
    +
         commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0);
    +
         commSetTimeout(icmp_sock, -1, NULL, NULL);
    +
         debug(37, 1) ("Pinger socket opened on FD %d\n", icmp_sock);
    +
     #endif
     }
     
    @@ -209,10 +258,15 @@ void
     icmpClose(void)
     {
     #if USE_ICMP
    +
         if (icmp_sock < 0)
    -	return;
    +        return;
    +
         debug(37, 1) ("Closing Pinger socket on FD %d\n", icmp_sock);
    +
         comm_close(icmp_sock);
    +
         icmp_sock = -1;
    +
     #endif
     }
    diff --git a/src/icp_v2.cc b/src/icp_v2.cc
    index e4ade56e46..882a58d68e 100644
    --- a/src/icp_v2.cc
    +++ b/src/icp_v2.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: icp_v2.cc,v 1.77 2003/02/15 18:24:17 hno Exp $
    + * $Id: icp_v2.cc,v 1.78 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 12    Internet Cache Protocol
      * AUTHOR: Duane Wessels
    @@ -41,6 +41,7 @@
     #include "ACLChecklist.h"
     
     static void icpLogIcp(struct in_addr, log_type, int, const char *, int);
    +
     static void icpHandleIcpV2(int, struct sockaddr_in, char *, int);
     static void icpCount(void *, int, size_t, int);
     
    @@ -53,16 +54,16 @@ static icpUdpData *IcpQueueHead = NULL;
     
     /* icp_common_t */
     _icp_common_t::_icp_common_t() : opcode(ICP_INVALID), version(0), length(0), reqnum(0), flags(0), pad(0), shostid(0)
    -{
    -}
    +{}
     
     _icp_common_t::_icp_common_t(char *buf, unsigned int len)
     {
         if (len < sizeof(_icp_common_t)) {
    -	/* mark as invalid */
    -	length = len + 1;
    -	return;
    +        /* mark as invalid */
    +        length = len + 1;
    +        return;
         }
    +
         xmemcpy(this, buf, sizeof(icp_common_t));
         /*
          * Convert network order sensitive fields
    @@ -77,34 +78,40 @@ icp_opcode
     _icp_common_t::getOpCode() const
     {
         if (opcode > (char)ICP_END)
    -	return ICP_INVALID;
    +        return ICP_INVALID;
    +
         return (icp_opcode)opcode;
     }
     
     /* ICPState */
     
     ICPState:: ICPState(icp_common_t & aHeader):header(aHeader)
    -    ,request(NULL),
    -    fd(-1),
    -    url(NULL)
    -{
    -}
    +        ,request(NULL),
    +        fd(-1),
    +        url(NULL)
    +{}
     
     ICPState::~ICPState()
     {
         safe_free(url);
    +
         if (request)
    -	requestDestroy(request);
    +        requestDestroy(request);
     }
     
     
     /* End ICPState */
     
     /* ICP2State */
    -class ICP2State:public ICPState, public StoreClient {
    -    public:
    -    ICP2State(icp_common_t & aHeader):ICPState(aHeader),rtt(0),src_rtt(0),flags(0) {
    -    }    ~ICP2State();
    +
    +class ICP2State:public ICPState, public StoreClient
    +{
    +
    +public:
    +    ICP2State(icp_common_t & aHeader):ICPState(aHeader),rtt(0),src_rtt(0),flags(0)
    +    {}
    +
    +    ~ICP2State();
         void created(StoreEntry * newEntry);
     
         int rtt;
    @@ -113,8 +120,7 @@ class ICP2State:public ICPState, public StoreClient {
     };
     
     ICP2State::~ICP2State ()
    -{
    -}
    +{}
     
     void
     ICP2State::created (StoreEntry *newEntry)
    @@ -122,20 +128,23 @@ ICP2State::created (StoreEntry *newEntry)
         StoreEntry *entry = newEntry->isNull () ? NULL : newEntry;
         debug(12, 5) ("icpHandleIcpV2: OPCODE %s\n", icp_opcode_str[header.opcode]);
         icp_opcode codeToSend;
    +
         if (icpCheckUdpHit(entry, request)) {
    -	codeToSend = ICP_HIT;
    +        codeToSend = ICP_HIT;
         } else {
    -	if (Config.onoff.test_reachability && rtt == 0) {
    -	    if ((rtt = netdbHostRtt(request->host)) == 0)
    -		netdbPingSite(request->host);
    -	} 
    -	if (icpGetCommonOpcode() != ICP_ERR) 
    -	    codeToSend = icpGetCommonOpcode();
    -	else if (Config.onoff.test_reachability && rtt == 0)
    -	    codeToSend = ICP_MISS_NOFETCH;
    -	else
    -	    codeToSend = ICP_MISS;
    +        if (Config.onoff.test_reachability && rtt == 0) {
    +            if ((rtt = netdbHostRtt(request->host)) == 0)
    +                netdbPingSite(request->host);
    +        }
    +
    +        if (icpGetCommonOpcode() != ICP_ERR)
    +            codeToSend = icpGetCommonOpcode();
    +        else if (Config.onoff.test_reachability && rtt == 0)
    +            codeToSend = ICP_MISS_NOFETCH;
    +        else
    +            codeToSend = ICP_MISS;
         }
    +
         icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, &from);
         delete this;
     }
    @@ -143,23 +152,36 @@ ICP2State::created (StoreEntry *newEntry)
     /* End ICP2State */
     
     static void
    +
     icpLogIcp(struct in_addr caddr, log_type logcode, int len, const char *url, int delay)
     {
         AccessLogEntry al;
    +
         if (LOG_TAG_NONE == logcode)
    -	return;
    +        return;
    +
         if (LOG_ICP_QUERY == logcode)
    -	return;
    +        return;
    +
         clientdbUpdate(caddr, logcode, PROTO_ICP, len);
    +
         if (!Config.onoff.log_udp)
    -	return;
    +        return;
    +
         memset(&al, '\0', sizeof(al));
    +
         al.icp.opcode = ICP_QUERY;
    +
         al.url = url;
    +
         al.cache.caddr = caddr;
    +
         al.cache.size = len;
    +
         al.cache.code = logcode;
    +
         al.cache.msec = delay;
    +
         accessLogLog(&al);
     }
     
    @@ -169,14 +191,16 @@ icpUdpSendQueue(int fd, void *unused)
         icpUdpData *q;
         int x;
         int delay;
    +
         while ((q = IcpQueueHead) != NULL) {
    -	delay = tvSubUsec(q->queue_time, current_time);
    -	/* increment delay to prevent looping */
    -	x = icpUdpSend(fd, &q->address, (icp_common_t *) q->msg, q->logcode, ++delay);
    -	IcpQueueHead = q->next;
    -	safe_free(q);
    -	if (x < 0)
    -	    break;
    +        delay = tvSubUsec(q->queue_time, current_time);
    +        /* increment delay to prevent looping */
    +        x = icpUdpSend(fd, &q->address, (icp_common_t *) q->msg, q->logcode, ++delay);
    +        IcpQueueHead = q->next;
    +        safe_free(q);
    +
    +        if (x < 0)
    +            break;
         }
     }
     
    @@ -193,71 +217,93 @@ _icp_common_t::createMessage(
         char *urloffset = NULL;
         int buf_len;
         buf_len = sizeof(icp_common_t) + strlen(url) + 1;
    +
         if (opcode == ICP_QUERY)
    -	buf_len += sizeof(u_int32_t);
    +        buf_len += sizeof(u_int32_t);
    +
         buf = (char *) xcalloc(buf_len, 1);
    +
         headerp = (icp_common_t *) (void *) buf;
    +
         headerp->opcode = (char) opcode;
    +
         headerp->version = ICP_VERSION_CURRENT;
    +
         headerp->length = (u_int16_t) htons(buf_len);
    +
         headerp->reqnum = htonl(reqnum);
    +
         headerp->flags = htonl(flags);
    +
         headerp->pad = htonl(pad);
    +
         headerp->shostid = theOutICPAddr.s_addr;
    +
         urloffset = buf + sizeof(icp_common_t);
    +
         if (opcode == ICP_QUERY)
    -	urloffset += sizeof(u_int32_t);
    +        urloffset += sizeof(u_int32_t);
    +
         xmemcpy(urloffset, url, strlen(url));
    +
         return (icp_common_t *)buf;
     }
     
     int
     icpUdpSend(int fd,
    -    const struct sockaddr_in *to,
    -    icp_common_t * msg,
    -    log_type logcode,
    -    int delay)
    +
    +           const struct sockaddr_in *to,
    +           icp_common_t * msg,
    +           log_type logcode,
    +           int delay)
     {
         icpUdpData *queue;
         int x;
         int len;
         len = (int) ntohs(msg->length);
         debug(12, 5) ("icpUdpSend: FD %d sending %s, %d bytes to %s:%d\n",
    -	fd,
    -	icp_opcode_str[msg->opcode],
    -	len,
    -	inet_ntoa(to->sin_addr),
    -	ntohs(to->sin_port));
    +                  fd,
    +                  icp_opcode_str[msg->opcode],
    +                  len,
    +                  inet_ntoa(to->sin_addr),
    +                  ntohs(to->sin_port));
         x = comm_udp_sendto(fd, to, sizeof(*to), msg, len);
    -    if (x >= 0) {
    -	/* successfully written */
    -	icpLogIcp(to->sin_addr, logcode, len, (char *) (msg + 1), delay);
    -	icpCount(msg, SENT, (size_t) len, delay);
    -	safe_free(msg);
    -    } else if (0 == delay) {
    -	/* send failed, but queue it */
    -	queue = (icpUdpData *) xcalloc(1, sizeof(icpUdpData));
    -	queue->address = *to;
    -	queue->msg = msg;
    -	queue->len = (int) ntohs(msg->length);
    -	queue->queue_time = current_time;
    -	queue->logcode = logcode;
    -	if (IcpQueueHead == NULL) {
    -	    IcpQueueHead = queue;
    -	    IcpQueueTail = queue;
    -	} else if (IcpQueueTail == IcpQueueHead) {
    -	    IcpQueueTail = queue;
    -	    IcpQueueHead->next = queue;
    -	} else {
    -	    IcpQueueTail->next = queue;
    -	    IcpQueueTail = queue;
    -	}
    -	commSetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0);
    -	statCounter.icp.replies_queued++;
    -    } else {
    -	/* don't queue it */
    -	statCounter.icp.replies_dropped++;
    +
    +    if (x >= 0)
    +    {
    +        /* successfully written */
    +        icpLogIcp(to->sin_addr, logcode, len, (char *) (msg + 1), delay);
    +        icpCount(msg, SENT, (size_t) len, delay);
    +        safe_free(msg);
    +    } else if (0 == delay)
    +    {
    +        /* send failed, but queue it */
    +        queue = (icpUdpData *) xcalloc(1, sizeof(icpUdpData));
    +        queue->address = *to;
    +        queue->msg = msg;
    +        queue->len = (int) ntohs(msg->length);
    +        queue->queue_time = current_time;
    +        queue->logcode = logcode;
    +
    +        if (IcpQueueHead == NULL) {
    +            IcpQueueHead = queue;
    +            IcpQueueTail = queue;
    +        } else if (IcpQueueTail == IcpQueueHead) {
    +            IcpQueueTail = queue;
    +            IcpQueueHead->next = queue;
    +        } else {
    +            IcpQueueTail->next = queue;
    +            IcpQueueTail = queue;
    +        }
    +
    +        commSetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0);
    +        statCounter.icp.replies_queued++;
    +    } else
    +    {
    +        /* don't queue it */
    +        statCounter.icp.replies_dropped++;
         }
    +
         return x;
     }
     
    @@ -265,13 +311,17 @@ int
     icpCheckUdpHit(StoreEntry * e, request_t * request)
     {
         if (e == NULL)
    -	return 0;
    +        return 0;
    +
         if (!storeEntryValidToSend(e))
    -	return 0;
    +        return 0;
    +
         if (Config.onoff.icp_hit_stale)
    -	return 1;
    +        return 1;
    +
         if (refreshCheckICP(e, request))
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -280,10 +330,12 @@ icp_opcode
     icpGetCommonOpcode()
     {
         /* if store is rebuilding, return a UDP_HIT, but not a MISS */
    +
         if (store_dirs_rebuilding && opt_reload_hit_only ||
    -	hit_only_mode_until > squid_curtime) {
    -	return ICP_MISS_NOFETCH;
    +            hit_only_mode_until > squid_curtime) {
    +        return ICP_MISS_NOFETCH;
         }
    +
         return ICP_ERR;
     }
     
    @@ -291,20 +343,27 @@ log_type
     icpLogFromICPCode(icp_opcode opcode)
     {
         if (opcode == ICP_ERR)
    -	return LOG_UDP_INVALID;
    +        return LOG_UDP_INVALID;
    +
         if (opcode == ICP_DENIED)
    -	return LOG_UDP_DENIED;
    +        return LOG_UDP_DENIED;
    +
         if (opcode == ICP_HIT)
    -	return LOG_UDP_HIT;
    +        return LOG_UDP_HIT;
    +
         if (opcode == ICP_MISS)
    -	return LOG_UDP_MISS;
    +        return LOG_UDP_MISS;
    +
         if (opcode == ICP_MISS_NOFETCH)
    -	return LOG_UDP_MISS_NOFETCH;
    +        return LOG_UDP_MISS_NOFETCH;
    +
         fatal("expected ICP opcode\n");
    +
         return LOG_UDP_INVALID;
     }
     
     void
    +
     icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const struct sockaddr_in *from)
     {
         icp_common_t *reply = _icp_common_t::createMessage(opcode, flags, url, reqnum, pad);
    @@ -312,22 +371,27 @@ icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int
     }
     
     void
    +
     icpDenyAccess(struct sockaddr_in *from, char *url, int reqnum, int fd)
     {
         debug(12, 2) ("icpDenyAccess: Access Denied for %s by %s.\n",
    -	inet_ntoa(from->sin_addr), AclMatchedName);
    -    if (clientdbCutoffDenied(from->sin_addr)) {
    -	/*
    -	 * count this DENIED query in the clientdb, even though
    -	 * we're not sending an ICP reply...
    -	 */
    -	clientdbUpdate(from->sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0);
    -    } else {
    -	icpCreateAndSend(ICP_DENIED, 0, url, reqnum, 0, fd, from);
    +                  inet_ntoa(from->sin_addr), AclMatchedName);
    +
    +    if (clientdbCutoffDenied(from->sin_addr))
    +    {
    +        /*
    +         * count this DENIED query in the clientdb, even though
    +         * we're not sending an ICP reply...
    +         */
    +        clientdbUpdate(from->sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0);
    +    } else
    +    {
    +        icpCreateAndSend(ICP_DENIED, 0, url, reqnum, 0, fd, from);
         }
     }
     
     int
    +
     icpAccessAllowed(struct sockaddr_in *from, request_t * icp_request)
     {
         ACLChecklist checklist;
    @@ -341,27 +405,33 @@ char const *
     icpGetUrlToSend(char *url)
     {
         if (strpbrk(url, w_space))
    -	return rfc1738_escape(url);
    +        return rfc1738_escape(url);
         else
    -	return url;
    +        return url;
     }
     
     request_t *
    +
     icpGetRequest(char *url, int reqnum, int fd, struct sockaddr_in * from)
     {
    -    if (strpbrk(url, w_space)) {
    -	url = rfc1738_escape(url);
    -	icpCreateAndSend(ICP_ERR, 0, rfc1738_escape(url), reqnum, 0, fd, from);
    -	return NULL;
    +    if (strpbrk(url, w_space))
    +    {
    +        url = rfc1738_escape(url);
    +        icpCreateAndSend(ICP_ERR, 0, rfc1738_escape(url), reqnum, 0, fd, from);
    +        return NULL;
         }
    +
         request_t *result;
    +
         if ((result = urlParse(METHOD_GET, url)) == NULL)
    -	icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from);
    +        icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from);
    +
         return result;
     
     }
     
     static void
    +
     doV2Query(int fd, struct sockaddr_in from, char *buf, icp_common_t header)
     {
         int rtt = 0;
    @@ -370,90 +440,121 @@ doV2Query(int fd, struct sockaddr_in from, char *buf, icp_common_t header)
         /* We have a valid packet */
         char *url = buf + sizeof(icp_common_t) + sizeof(u_int32_t);
         request_t *icp_request = icpGetRequest(url, header.reqnum, fd, &from);
    +
         if (!icp_request)
    -	return;
    -    if (!icpAccessAllowed(&from, icp_request)) {
    -	icpDenyAccess(&from, url, header.reqnum, fd);
    -	requestDestroy(icp_request);
    -	return;
    +        return;
    +
    +    if (!icpAccessAllowed(&from, icp_request))
    +    {
    +        icpDenyAccess(&from, url, header.reqnum, fd);
    +        requestDestroy(icp_request);
    +        return;
         }
    -    if (header.flags & ICP_FLAG_SRC_RTT) {
    -	rtt = netdbHostRtt(icp_request->host);
    -	int hops = netdbHostHops(icp_request->host);
    -	src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF);
    -	if (rtt)
    -	    flags |= ICP_FLAG_SRC_RTT;
    +
    +    if (header.flags & ICP_FLAG_SRC_RTT)
    +    {
    +        rtt = netdbHostRtt(icp_request->host);
    +        int hops = netdbHostHops(icp_request->host);
    +        src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF);
    +
    +        if (rtt)
    +            flags |= ICP_FLAG_SRC_RTT;
         }
    +
         /* The peer is allowed to use this cache */
         ICP2State *state = new ICP2State (header);
    +
         state->fd = fd;
    +
         state->from = from;
    +
         state->url = xstrdup (url);
    +
         state->flags = flags;
    +
         state->rtt = rtt;
    +
         state->src_rtt = src_rtt;
    +
         StoreEntry::getPublic (state, url, METHOD_GET);
     }
     
     void
    +
     _icp_common_t::handleReply(char *buf, struct sockaddr_in *from)
     {
    -    if (neighbors_do_private_keys && reqnum == 0) {
    -	debug(12, 0) ("icpHandleIcpV2: Neighbor %s returned reqnum = 0\n",
    -	    inet_ntoa(from->sin_addr));
    -	debug(12, 0) ("icpHandleIcpV2: Disabling use of private keys\n");
    -	neighbors_do_private_keys = 0;
    +    if (neighbors_do_private_keys && reqnum == 0)
    +    {
    +        debug(12, 0) ("icpHandleIcpV2: Neighbor %s returned reqnum = 0\n",
    +                      inet_ntoa(from->sin_addr));
    +        debug(12, 0) ("icpHandleIcpV2: Disabling use of private keys\n");
    +        neighbors_do_private_keys = 0;
         }
    +
         char *url = buf + sizeof(icp_common_t);
         debug(12, 3) ("icpHandleIcpV2: %s from %s for '%s'\n",
    -	icp_opcode_str[opcode],
    -	inet_ntoa(from->sin_addr),
    -	url);
    +                  icp_opcode_str[opcode],
    +                  inet_ntoa(from->sin_addr),
    +                  url);
         const cache_key *key = icpGetCacheKey(url, (int) reqnum);
         /* call neighborsUdpAck even if ping_status != PING_WAITING */
         neighborsUdpAck(key, this, from);
     }
     
     static void
    +
     icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len)
     {
    -    if (len <= 0) {
    -	debug(12, 3) ("icpHandleIcpV2: ICP message is too small\n");
    -	return;
    +    if (len <= 0)
    +    {
    +        debug(12, 3) ("icpHandleIcpV2: ICP message is too small\n");
    +        return;
         }
    +
         icp_common_t header(buf, len);
         /*
          * Length field should match the number of bytes read
          */
    -    if (len != header.length) {
    -	debug(12, 3) ("icpHandleIcpV2: ICP message is too small\n");
    -	return;
    +
    +    if (len != header.length)
    +    {
    +        debug(12, 3) ("icpHandleIcpV2: ICP message is too small\n");
    +        return;
         }
    -    switch (header.opcode) {
    +
    +    switch (header.opcode)
    +    {
    +
         case ICP_QUERY:
    -	/* We have a valid packet */
    -	doV2Query(fd, from, buf, header);
    -	break;
    +        /* We have a valid packet */
    +        doV2Query(fd, from, buf, header);
    +        break;
     
         case ICP_HIT:
     #if ALLOW_SOURCE_PING
    +
         case ICP_SECHO:
     #endif
    +
         case ICP_DECHO:
    +
         case ICP_MISS:
    +
         case ICP_DENIED:
    +
         case ICP_MISS_NOFETCH:
    -	header.handleReply(buf, &from);
    -	break;
    +        header.handleReply(buf, &from);
    +        break;
     
         case ICP_INVALID:
    +
         case ICP_ERR:
    -	break;
    +        break;
     
         default:
    -	debug(12, 0) ("icpHandleIcpV2: UNKNOWN OPCODE: %d from %s\n",
    -	    header.opcode, inet_ntoa(from.sin_addr));
    -	break;
    +        debug(12, 0) ("icpHandleIcpV2: UNKNOWN OPCODE: %d from %s\n",
    +                      header.opcode, inet_ntoa(from.sin_addr));
    +        break;
         }
     }
     
    @@ -461,11 +562,12 @@ icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len)
     static void
     icpPktDump(icp_common_t * pkt)
     {
    +
         struct in_addr a;
     
         debug(12, 9) ("opcode:     %3d %s\n",
    -	(int) pkt->opcode,
    -	icp_opcode_str[pkt->opcode]);
    +                  (int) pkt->opcode,
    +                  icp_opcode_str[pkt->opcode]);
         debug(12, 9) ("version: %-8d\n", (int) pkt->version);
         debug(12, 9) ("length:  %-8d\n", (int) ntohs(pkt->length));
         debug(12, 9) ("reqnum:  %-8d\n", ntohl(pkt->reqnum));
    @@ -474,12 +576,14 @@ icpPktDump(icp_common_t * pkt)
         debug(12, 9) ("shostid: %s\n", inet_ntoa(a));
         debug(12, 9) ("payload: %s\n", (char *) pkt + sizeof(icp_common_t));
     }
    +
     #endif
     
     void
     icpHandleUdp(int sock, void *data)
     {
         int *N = &incoming_sockets_accepted;
    +
         struct sockaddr_in from;
         socklen_t from_len;
         LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF);
    @@ -487,55 +591,67 @@ icpHandleUdp(int sock, void *data)
         int icp_version;
         int max = INCOMING_ICP_MAX;
         commSetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
    +
         while (max--) {
    -	from_len = sizeof(from);
    -	memset(&from, '\0', from_len);
    -	len = comm_udp_recvfrom(sock,
    -	    buf,
    -	    SQUID_UDP_SO_RCVBUF - 1,
    -	    0,
    -	    (struct sockaddr *) &from,
    -	    &from_len);
    -	if (len == 0)
    -	    break;
    -	if (len < 0) {
    -	    if (ignoreErrno(errno))
    -		break;
    +        from_len = sizeof(from);
    +        memset(&from, '\0', from_len);
    +        len = comm_udp_recvfrom(sock,
    +                                buf,
    +                                SQUID_UDP_SO_RCVBUF - 1,
    +                                0,
    +
    +                                (struct sockaddr *) &from,
    +                                &from_len);
    +
    +        if (len == 0)
    +            break;
    +
    +        if (len < 0) {
    +            if (ignoreErrno(errno))
    +                break;
    +
     #ifdef _SQUID_LINUX_
    -	    /* Some Linux systems seem to set the FD for reading and then
    -	     * return ECONNREFUSED when sendto() fails and generates an ICMP
    -	     * port unreachable message. */
    -	    /* or maybe an EHOSTUNREACH "No route to host" message */
    -	    if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
    +            /* Some Linux systems seem to set the FD for reading and then
    +             * return ECONNREFUSED when sendto() fails and generates an ICMP
    +             * port unreachable message. */
    +            /* or maybe an EHOSTUNREACH "No route to host" message */
    +            if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
     #endif
    -		debug(50, 1) ("icpHandleUdp: FD %d recvfrom: %s\n",
    -		    sock, xstrerror());
    -	    break;
    -	}
    -	(*N)++;
    -	icpCount(buf, RECV, (size_t) len, 0);
    -	buf[len] = '\0';
    -	debug(12, 4) ("icpHandleUdp: FD %d: received %lu bytes from %s.\n",
    -	    sock,
    -	    (unsigned long int)len,
    -	    inet_ntoa(from.sin_addr));
    +
    +                debug(50, 1) ("icpHandleUdp: FD %d recvfrom: %s\n",
    +                              sock, xstrerror());
    +
    +            break;
    +        }
    +
    +        (*N)++;
    +        icpCount(buf, RECV, (size_t) len, 0);
    +        buf[len] = '\0';
    +        debug(12, 4) ("icpHandleUdp: FD %d: received %lu bytes from %s.\n",
    +                      sock,
    +                      (unsigned long int)len,
    +                      inet_ntoa(from.sin_addr));
     #ifdef ICP_PACKET_DUMP
    -	icpPktDump(buf);
    +
    +        icpPktDump(buf);
     #endif
    -	if (len < sizeof(icp_common_t)) {
    -	    debug(12, 4) ("icpHandleUdp: Ignoring too-small UDP packet\n");
    -	    break;
    -	}
    -	icp_version = (int) buf[1];	/* cheat! */
    -	if (icp_version == ICP_VERSION_2)
    -	    icpHandleIcpV2(sock, from, buf, len);
    -	else if (icp_version == ICP_VERSION_3)
    -	    icpHandleIcpV3(sock, from, buf, len);
    -	else
    -	    debug(12, 1) ("WARNING: Unused ICP version %d received from %s:%d\n",
    -		icp_version,
    -		inet_ntoa(from.sin_addr),
    -		ntohs(from.sin_port));
    +
    +        if (len < sizeof(icp_common_t)) {
    +            debug(12, 4) ("icpHandleUdp: Ignoring too-small UDP packet\n");
    +            break;
    +        }
    +
    +        icp_version = (int) buf[1];	/* cheat! */
    +
    +        if (icp_version == ICP_VERSION_2)
    +            icpHandleIcpV2(sock, from, buf, len);
    +        else if (icp_version == ICP_VERSION_3)
    +            icpHandleIcpV3(sock, from, buf, len);
    +        else
    +            debug(12, 1) ("WARNING: Unused ICP version %d received from %s:%d\n",
    +                          icp_version,
    +                          inet_ntoa(from.sin_addr),
    +                          ntohs(from.sin_port));
         }
     }
     
    @@ -543,66 +659,86 @@ void
     icpConnectionsOpen(void)
     {
         u_int16_t port;
    +
         struct in_addr addr;
    +
         struct sockaddr_in xaddr;
         int x;
         socklen_t len;
         wordlist *s;
    +
         if ((port = Config.Port.icp) <= 0)
    -	return;
    +        return;
    +
         enter_suid();
    +
         theInIcpConnection = comm_open(SOCK_DGRAM,
    -	0,
    -	Config.Addrs.udp_incoming,
    -	port,
    -	COMM_NONBLOCKING,
    -	"ICP Socket");
    +                                   0,
    +                                   Config.Addrs.udp_incoming,
    +                                   port,
    +                                   COMM_NONBLOCKING,
    +                                   "ICP Socket");
    +
         leave_suid();
    +
         if (theInIcpConnection < 0)
    -	fatal("Cannot open ICP Port");
    +        fatal("Cannot open ICP Port");
    +
         commSetSelect(theInIcpConnection,
    -	COMM_SELECT_READ,
    -	icpHandleUdp,
    -	NULL,
    -	0);
    +                  COMM_SELECT_READ,
    +                  icpHandleUdp,
    +                  NULL,
    +                  0);
    +
         for (s = Config.mcast_group_list; s; s = s->next)
    -	ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
    +        ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
    +
         debug(12, 1) ("Accepting ICP messages at %s, port %d, FD %d.\n",
    -	inet_ntoa(Config.Addrs.udp_incoming),
    -	(int) port, theInIcpConnection);
    +                  inet_ntoa(Config.Addrs.udp_incoming),
    +                  (int) port, theInIcpConnection);
    +
         if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) {
    -	enter_suid();
    -	theOutIcpConnection = comm_open(SOCK_DGRAM,
    -	    0,
    -	    addr,
    -	    port,
    -	    COMM_NONBLOCKING,
    -	    "ICP Port");
    -	leave_suid();
    -	if (theOutIcpConnection < 0)
    -	    fatal("Cannot open Outgoing ICP Port");
    -	commSetSelect(theOutIcpConnection,
    -	    COMM_SELECT_READ,
    -	    icpHandleUdp,
    -	    NULL,
    -	    0);
    -	debug(12, 1) ("Outgoing ICP messages on port %d, FD %d.\n",
    -	    (int) port, theOutIcpConnection);
    -	fd_note(theOutIcpConnection, "Outgoing ICP socket");
    -	fd_note(theInIcpConnection, "Incoming ICP socket");
    +        enter_suid();
    +        theOutIcpConnection = comm_open(SOCK_DGRAM,
    +                                        0,
    +                                        addr,
    +                                        port,
    +                                        COMM_NONBLOCKING,
    +                                        "ICP Port");
    +        leave_suid();
    +
    +        if (theOutIcpConnection < 0)
    +            fatal("Cannot open Outgoing ICP Port");
    +
    +        commSetSelect(theOutIcpConnection,
    +                      COMM_SELECT_READ,
    +                      icpHandleUdp,
    +                      NULL,
    +                      0);
    +
    +        debug(12, 1) ("Outgoing ICP messages on port %d, FD %d.\n",
    +                      (int) port, theOutIcpConnection);
    +
    +        fd_note(theOutIcpConnection, "Outgoing ICP socket");
    +
    +        fd_note(theInIcpConnection, "Incoming ICP socket");
         } else {
    -	theOutIcpConnection = theInIcpConnection;
    +        theOutIcpConnection = theInIcpConnection;
         }
    +
         memset(&theOutICPAddr, '\0', sizeof(struct in_addr));
    +
         len = sizeof(struct sockaddr_in);
         memset(&xaddr, '\0', len);
         x = getsockname(theOutIcpConnection,
    -	(struct sockaddr *) &xaddr, &len);
    +
    +                    (struct sockaddr *) &xaddr, &len);
    +
         if (x < 0)
    -	debug(50, 1) ("theOutIcpConnection FD %d: getsockname: %s\n",
    -	    theOutIcpConnection, xstrerror());
    +        debug(50, 1) ("theOutIcpConnection FD %d: getsockname: %s\n",
    +                      theOutIcpConnection, xstrerror());
         else
    -	theOutICPAddr = xaddr.sin_addr;
    +        theOutICPAddr = xaddr.sin_addr;
     }
     
     /*
    @@ -613,11 +749,13 @@ void
     icpConnectionShutdown(void)
     {
         if (theInIcpConnection < 0)
    -	return;
    +        return;
    +
         if (theInIcpConnection != theOutIcpConnection) {
    -	debug(12, 1) ("FD %d Closing ICP connection\n", theInIcpConnection);
    -	comm_close(theInIcpConnection);
    +        debug(12, 1) ("FD %d Closing ICP connection\n", theInIcpConnection);
    +        comm_close(theInIcpConnection);
         }
    +
         /*
          * Here we set 'theInIcpConnection' to -1 even though the ICP 'in'
          * and 'out' sockets might be just one FD.  This prevents this
    @@ -625,6 +763,7 @@ icpConnectionShutdown(void)
          * exit or restart, main will comm_close the 'out' descriptor.
          */
         theInIcpConnection = -1;
    +
         /*
          * Normally we only write to the outgoing ICP socket, but
          * we also have a read handler there to catch messages sent
    @@ -632,6 +771,7 @@ icpConnectionShutdown(void)
          * disable reading on the outgoing socket.
          */
         assert(theOutIcpConnection > -1);
    +
         commSetSelect(theOutIcpConnection, COMM_SELECT_READ, NULL, NULL, 0);
     }
     
    @@ -639,10 +779,11 @@ void
     icpConnectionClose(void)
     {
         icpConnectionShutdown();
    +
         if (theOutIcpConnection > -1) {
    -	debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection);
    -	comm_close(theOutIcpConnection);
    -	theOutIcpConnection = -1;
    +        debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection);
    +        comm_close(theOutIcpConnection);
    +        theOutIcpConnection = -1;
         }
     }
     
    @@ -650,35 +791,41 @@ static void
     icpCount(void *buf, int which, size_t len, int delay)
     {
         icp_common_t *icp = (icp_common_t *) buf;
    +
         if (len < sizeof(*icp))
    -	return;
    +        return;
    +
         if (SENT == which) {
    -	statCounter.icp.pkts_sent++;
    -	kb_incr(&statCounter.icp.kbytes_sent, len);
    -	if (ICP_QUERY == icp->opcode) {
    -	    statCounter.icp.queries_sent++;
    -	    kb_incr(&statCounter.icp.q_kbytes_sent, len);
    -	} else {
    -	    statCounter.icp.replies_sent++;
    -	    kb_incr(&statCounter.icp.r_kbytes_sent, len);
    -	    /* this is the sent-reply service time */
    -	    statHistCount(&statCounter.icp.reply_svc_time, delay);
    -	}
    -	if (ICP_HIT == icp->opcode)
    -	    statCounter.icp.hits_sent++;
    +        statCounter.icp.pkts_sent++;
    +        kb_incr(&statCounter.icp.kbytes_sent, len);
    +
    +        if (ICP_QUERY == icp->opcode) {
    +            statCounter.icp.queries_sent++;
    +            kb_incr(&statCounter.icp.q_kbytes_sent, len);
    +        } else {
    +            statCounter.icp.replies_sent++;
    +            kb_incr(&statCounter.icp.r_kbytes_sent, len);
    +            /* this is the sent-reply service time */
    +            statHistCount(&statCounter.icp.reply_svc_time, delay);
    +        }
    +
    +        if (ICP_HIT == icp->opcode)
    +            statCounter.icp.hits_sent++;
         } else if (RECV == which) {
    -	statCounter.icp.pkts_recv++;
    -	kb_incr(&statCounter.icp.kbytes_recv, len);
    -	if (ICP_QUERY == icp->opcode) {
    -	    statCounter.icp.queries_recv++;
    -	    kb_incr(&statCounter.icp.q_kbytes_recv, len);
    -	} else {
    -	    statCounter.icp.replies_recv++;
    -	    kb_incr(&statCounter.icp.r_kbytes_recv, len);
    -	    /* statCounter.icp.query_svc_time set in clientUpdateCounters */
    -	}
    -	if (ICP_HIT == icp->opcode)
    -	    statCounter.icp.hits_recv++;
    +        statCounter.icp.pkts_recv++;
    +        kb_incr(&statCounter.icp.kbytes_recv, len);
    +
    +        if (ICP_QUERY == icp->opcode) {
    +            statCounter.icp.queries_recv++;
    +            kb_incr(&statCounter.icp.q_kbytes_recv, len);
    +        } else {
    +            statCounter.icp.replies_recv++;
    +            kb_incr(&statCounter.icp.r_kbytes_recv, len);
    +            /* statCounter.icp.query_svc_time set in clientUpdateCounters */
    +        }
    +
    +        if (ICP_HIT == icp->opcode)
    +            statCounter.icp.hits_recv++;
         }
     }
     
    @@ -690,9 +837,12 @@ int
     icpSetCacheKey(const cache_key * key)
     {
         static int reqnum = 0;
    +
         if (++reqnum < 0)
    -	reqnum = 1;
    +        reqnum = 1;
    +
         storeKeyCopy(queried_keys[reqnum & N_QUERIED_KEYS_MASK], key);
    +
         return reqnum;
     }
     
    @@ -700,6 +850,7 @@ const cache_key *
     icpGetCacheKey(const char *url, int reqnum)
     {
         if (neighbors_do_private_keys && reqnum)
    -	return queried_keys[reqnum & N_QUERIED_KEYS_MASK];
    +        return queried_keys[reqnum & N_QUERIED_KEYS_MASK];
    +
         return storeKeyPublic(url, METHOD_GET);
     }
    diff --git a/src/icp_v3.cc b/src/icp_v3.cc
    index eedc4ae2ec..ee9bb0d46f 100644
    --- a/src/icp_v3.cc
    +++ b/src/icp_v3.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: icp_v3.cc,v 1.37 2003/01/23 00:37:22 robertc Exp $
    + * $Id: icp_v3.cc,v 1.38 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 12    Internet Cache Protocol
      * AUTHOR: Duane Wessels
    @@ -38,95 +38,124 @@
     #include "ICP.h"
     #include "HttpRequest.h"
     
    -class ICP3State : public ICPState, public StoreClient {
    +class ICP3State : public ICPState, public StoreClient
    +{
    +
     public:
         ICP3State(icp_common_t &aHeader):ICPState(aHeader){}
    +
         ~ICP3State();
         void created (StoreEntry *newEntry);
     };
     
     static void
    +
     doV3Query(int fd, struct sockaddr_in from, char *buf, icp_common_t header)
     {
         /* We have a valid packet */
         char *url = buf + sizeof(icp_common_t) + sizeof(u_int32_t);
         request_t *icp_request = icpGetRequest (url, header.reqnum, fd, &from);
    +
         if (!icp_request)
    -	return;
    -    if (!icpAccessAllowed(&from, icp_request)) {
    -	icpDenyAccess (&from, url, header.reqnum, fd);
    -	requestDestroy(icp_request);
    -	return;
    +        return;
    +
    +    if (!icpAccessAllowed(&from, icp_request))
    +    {
    +        icpDenyAccess (&from, url, header.reqnum, fd);
    +        requestDestroy(icp_request);
    +        return;
         }
    +
         /* The peer is allowed to use this cache */
         ICP3State *state = new ICP3State (header);
    +
         state->request = icp_request;
    +
         state->fd = fd;
    +
         state->from = from;
    +
         state->url = xstrdup (url);
    +
         StoreEntry::getPublic (state, url, METHOD_GET);
     }
     
     ICP3State::~ICP3State ()
    -{
    -}
    +{}
     
     void
     ICP3State::created (StoreEntry *newEntry)
     {
         StoreEntry *entry = newEntry->isNull () ? NULL : newEntry;
         debug(12, 5) ("icpHandleIcpV3: OPCODE %s\n",
    -	icp_opcode_str[header.opcode]);
    +                  icp_opcode_str[header.opcode]);
         icp_opcode codeToSend;
    +
         if (icpCheckUdpHit(entry, request)) {
    -	codeToSend = ICP_HIT;
    +        codeToSend = ICP_HIT;
         } else if (icpGetCommonOpcode() == ICP_ERR)
    -	codeToSend = ICP_MISS;
    +        codeToSend = ICP_MISS;
         else
    -	codeToSend = icpGetCommonOpcode();
    +        codeToSend = icpGetCommonOpcode();
    +
         icpCreateAndSend (codeToSend, 0, url, header.reqnum, 0, fd, &from);
    +
         delete this;
     }
     
     /* Currently Harvest cached-2.x uses ICP_VERSION_3 */
     void
    +
     icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len)
     {
    -    if (len <= 0) {
    -	debug(12, 3) ("icpHandleIcpV3: ICP message is too small\n");
    -	return;
    +    if (len <= 0)
    +    {
    +        debug(12, 3) ("icpHandleIcpV3: ICP message is too small\n");
    +        return;
         }
    +
         icp_common_t header (buf, len);
         /*
          * Length field should match the number of bytes read
          */
    -    if (len != header.length) {
    -	debug(12, 3) ("icpHandleIcpV3: ICP message is too small\n");
    -	return;
    +
    +    if (len != header.length)
    +    {
    +        debug(12, 3) ("icpHandleIcpV3: ICP message is too small\n");
    +        return;
         }
    -    switch (header.opcode) {
    +
    +    switch (header.opcode)
    +    {
    +
         case ICP_QUERY:
    -	doV3Query(fd, from,buf, header);
    -	break;
    +        doV3Query(fd, from,buf, header);
    +        break;
     
         case ICP_HIT:
     #if ALLOW_SOURCE_PING
    +
         case ICP_SECHO:
     #endif
    +
         case ICP_DECHO:
    +
         case ICP_MISS:
    +
         case ICP_DENIED:
    +
         case ICP_MISS_NOFETCH:
    -	header.handleReply(buf, &from);
    -	break;
    +        header.handleReply(buf, &from);
    +        break;
     
         case ICP_INVALID:
    +
         case ICP_ERR:
    -	break;
    +        break;
     
         default:
    -	debug(12, 0) ("icpHandleIcpV3: UNKNOWN OPCODE: %d from %s\n",
    -	    header.opcode, inet_ntoa(from.sin_addr));
    -	break;
    +        debug(12, 0) ("icpHandleIcpV3: UNKNOWN OPCODE: %d from %s\n",
    +                      header.opcode, inet_ntoa(from.sin_addr));
    +        break;
         }
     }
    diff --git a/src/ident.cc b/src/ident.cc
    index 90595f6403..1180e34525 100644
    --- a/src/ident.cc
    +++ b/src/ident.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: ident.cc,v 1.65 2003/02/12 06:11:04 robertc Exp $
    + * $Id: ident.cc,v 1.66 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 30    Ident (RFC 931)
      * AUTHOR: Duane Wessels
    @@ -38,20 +38,29 @@
     #define IDENT_PORT 113
     #define IDENT_KEY_SZ 50
     
    -typedef struct _IdentClient {
    +typedef struct _IdentClient
    +{
         IDCB *callback;
         void *callback_data;
    +
         struct _IdentClient *next;
    -} IdentClient;
    +}
    +
    +IdentClient;
     
    -typedef struct _IdentStateData {
    +typedef struct _IdentStateData
    +{
         hash_link hash;		/* must be first */
         int fd;			/* IDENT fd */
    +
         struct sockaddr_in me;
    +
         struct sockaddr_in my_peer;
         IdentClient *clients;
         char buf[4096];
    -} IdentStateData;
    +}
    +
    +IdentStateData;
     
     static IOCB identReadReply;
     static PF identClose;
    @@ -66,14 +75,18 @@ static void
     identCallback(IdentStateData * state, char *result)
     {
         IdentClient *client;
    +
         if (result && *result == '\0')
    -	result = NULL;
    +        result = NULL;
    +
         while ((client = state->clients)) {
    -	void *cbdata;
    -	state->clients = client->next;
    -	if (cbdataReferenceValidDone(client->callback_data, &cbdata))
    -	    client->callback(result, cbdata);
    -	xfree(client);
    +        void *cbdata;
    +        state->clients = client->next;
    +
    +        if (cbdataReferenceValidDone(client->callback_data, &cbdata))
    +            client->callback(result, cbdata);
    +
    +        xfree(client);
         }
     }
     
    @@ -92,7 +105,7 @@ identTimeout(int fd, void *data)
     {
         IdentStateData *state = (IdentStateData *)data;
         debug(30, 3) ("identTimeout: FD %d, %s\n", fd,
    -	inet_ntoa(state->my_peer.sin_addr));
    +                  inet_ntoa(state->my_peer.sin_addr));
         comm_close(fd);
     }
     
    @@ -102,27 +115,31 @@ identConnectDone(int fd, comm_err_t status, void *data)
         IdentStateData *state = (IdentStateData *)data;
         IdentClient *c;
         MemBuf mb;
    +
         if (status != COMM_OK) {
    -	/* Failed to connect */
    -	comm_close(fd);
    -	return;
    +        /* Failed to connect */
    +        comm_close(fd);
    +        return;
         }
    +
         /*
          * see if any of our clients still care
          */
         for (c = state->clients; c; c = c->next) {
    -	if (cbdataReferenceValid(c->callback_data))
    -	    break;
    +        if (cbdataReferenceValid(c->callback_data))
    +            break;
         }
    +
         if (c == NULL) {
    -	/* no clients care */
    -	comm_close(fd);
    -	return;
    +        /* no clients care */
    +        comm_close(fd);
    +        return;
         }
    +
         memBufDefInit(&mb);
         memBufPrintf(&mb, "%d, %d\r\n",
    -	ntohs(state->my_peer.sin_port),
    -	ntohs(state->me.sin_port));
    +                 ntohs(state->my_peer.sin_port),
    +                 ntohs(state->me.sin_port));
         comm_old_write_mbuf(fd, mb, NULL, state);
         comm_read(fd, state->buf, BUFSIZ, identReadReply, state);
         commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
    @@ -136,28 +153,36 @@ identReadReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void
         char *t = NULL;
     
         assert (buf == state->buf);
    -    
    +
         if (flag != COMM_OK || len <= 0) {
    -	comm_close(fd);
    -	return;
    +        comm_close(fd);
    +        return;
         }
    +
         /*
          * XXX This isn't really very tolerant. It should read until EOL
          * or EOF and then decode the answer... If the reply is fragmented
          * then this will fail
          */
         buf[len] = '\0';
    +
         if ((t = strchr(buf, '\r')))
    -	*t = '\0';
    +        *t = '\0';
    +
         if ((t = strchr(buf, '\n')))
    -	*t = '\0';
    +        *t = '\0';
    +
         debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
    +
         if (strstr(buf, "USERID")) {
    -	if ((ident = strrchr(buf, ':'))) {
    -	    while (xisspace(*++ident));
    -	    identCallback(state, ident);
    -	}
    +        if ((ident = strrchr(buf, ':'))) {
    +            while (xisspace(*++ident))
    +
    +                ;
    +            identCallback(state, ident);
    +        }
         }
    +
         comm_close(fd);
     }
     
    @@ -169,7 +194,10 @@ identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
         IdentClient **C;
         c->callback = callback;
         c->callback_data = cbdataReference(callback_data);
    -    for (C = &state->clients; *C; C = &(*C)->next);
    +
    +    for (C = &state->clients; *C; C = &(*C)->next)
    +
    +        ;
         *C = c;
     }
     
    @@ -181,6 +209,7 @@ CBDATA_TYPE(IdentStateData);
      * start a TCP connection to the peer host on port 113
      */
     void
    +
     identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data)
     {
         IdentStateData *state;
    @@ -189,27 +218,33 @@ identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback,
         char key2[IDENT_KEY_SZ];
         char key[IDENT_KEY_SZ];
         snprintf(key1, IDENT_KEY_SZ, "%s:%d",
    -	inet_ntoa(me->sin_addr),
    -	ntohs(me->sin_port));
    +             inet_ntoa(me->sin_addr),
    +             ntohs(me->sin_port));
         snprintf(key2, IDENT_KEY_SZ, "%s:%d",
    -	inet_ntoa(my_peer->sin_addr),
    -	ntohs(my_peer->sin_port));
    +             inet_ntoa(my_peer->sin_addr),
    +             ntohs(my_peer->sin_port));
         snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
    -    if ((state = (IdentStateData *)hash_lookup(ident_hash, key)) != NULL) {
    -	identClientAdd(state, callback, data);
    -	return;
    +
    +    if ((state = (IdentStateData *)hash_lookup(ident_hash, key)) != NULL)
    +    {
    +        identClientAdd(state, callback, data);
    +        return;
         }
    +
         fd = comm_open(SOCK_STREAM,
    -	0,
    -	me->sin_addr,
    -	0,
    -	COMM_NONBLOCKING,
    -	"ident");
    -    if (fd == COMM_ERROR) {
    -	/* Failed to get a local socket */
    -	callback(NULL, data);
    -	return;
    +                   0,
    +                   me->sin_addr,
    +                   0,
    +                   COMM_NONBLOCKING,
    +                   "ident");
    +
    +    if (fd == COMM_ERROR)
    +    {
    +        /* Failed to get a local socket */
    +        callback(NULL, data);
    +        return;
         }
    +
         CBDATA_INIT_TYPE(IdentStateData);
         state = cbdataAlloc(IdentStateData);
         state->hash.key = xstrdup(key);
    @@ -219,20 +254,20 @@ identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback,
         identClientAdd(state, callback, data);
         hash_join(ident_hash, &state->hash);
         comm_add_close_handler(fd,
    -	identClose,
    -	state);
    +                           identClose,
    +                           state);
         commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
         commConnectStart(fd,
    -	inet_ntoa(state->my_peer.sin_addr),
    -	IDENT_PORT,
    -	identConnectDone,
    -	state);
    +                     inet_ntoa(state->my_peer.sin_addr),
    +                     IDENT_PORT,
    +                     identConnectDone,
    +                     state);
     }
     
     void
     identInit(void)
     {
         ident_hash = hash_create((HASHCMP *) strcmp,
    -	hashPrime(Squid_MaxFD / 8),
    -	hash4);
    +                             hashPrime(Squid_MaxFD / 8),
    +                             hash4);
     }
    diff --git a/src/int.cc b/src/int.cc
    index 17bdd1482a..9e0b94c14e 100644
    --- a/src/int.cc
    +++ b/src/int.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: int.cc,v 1.1 2003/01/17 05:37:24 robertc Exp $
    + * $Id: int.cc,v 1.2 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 21    Integer functions
      * AUTHOR: Harvest Derived
    @@ -38,7 +38,9 @@ int
     isPowTen(int count)
     {
         double x = log(count) / log(10.0);
    +
         if (0.0 != x - (double) (int) x)
    -	return 0;
    +        return 0;
    +
         return 1;
     }
    diff --git a/src/internal.cc b/src/internal.cc
    index a3e72160fc..3a01ff2b1e 100644
    --- a/src/internal.cc
    +++ b/src/internal.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: internal.cc,v 1.27 2003/01/23 00:37:22 robertc Exp $
    + * $Id: internal.cc,v 1.28 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 76    Internal Squid Object handling
      * AUTHOR: Duane, Alex, Henrik
    @@ -49,34 +49,37 @@ internalStart(request_t * request, StoreEntry * entry)
         const char *upath = request->urlpath.buf();
         http_version_t version;
         debug(76, 3) ("internalStart: %s requesting '%s'\n",
    -	inet_ntoa(request->client_addr), upath);
    +                  inet_ntoa(request->client_addr), upath);
    +
         if (0 == strcmp(upath, "/squid-internal-dynamic/netdb")) {
    -	netdbBinaryExchange(entry);
    +        netdbBinaryExchange(entry);
         } else if (0 == strcmp(upath, "/squid-internal-periodic/store_digest")) {
     #if USE_CACHE_DIGESTS
    -	const char *msgbuf = "This cache is currently building its digest.\n";
    +        const char *msgbuf = "This cache is currently building its digest.\n";
     #else
    -	const char *msgbuf = "This cache does not suport Cache Digests.\n";
    +
    +        const char *msgbuf = "This cache does not suport Cache Digests.\n";
     #endif
    -	httpBuildVersion(&version, 1, 0);
    -	HttpReply *reply = httpReplyCreate ();
    -	httpReplySetHeaders(reply,
    -	    version,
    -	    HTTP_NOT_FOUND,
    -	    "Not Found",
    -	    "text/plain",
    -	    strlen(msgbuf),
    -	    squid_curtime,
    -	    -2);
    -	httpReplySwapOut(reply, entry);
    -	storeAppend(entry, msgbuf, strlen(msgbuf));
    -	entry->complete();
    +
    +        httpBuildVersion(&version, 1, 0);
    +        HttpReply *reply = httpReplyCreate ();
    +        httpReplySetHeaders(reply,
    +                            version,
    +                            HTTP_NOT_FOUND,
    +                            "Not Found",
    +                            "text/plain",
    +                            strlen(msgbuf),
    +                            squid_curtime,
    +                            -2);
    +        httpReplySwapOut(reply, entry);
    +        storeAppend(entry, msgbuf, strlen(msgbuf));
    +        entry->complete();
         } else {
    -	debugObj(76, 1, "internalStart: unknown request:\n",
    -	    request, (ObjPackMethod) & httpRequestPack);
    -	err = errorCon(ERR_INVALID_REQ, HTTP_NOT_FOUND);
    -	err->request = requestLink(request);
    -	errorAppendEntry(entry, err);
    +        debugObj(76, 1, "internalStart: unknown request:\n",
    +                 request, (ObjPackMethod) & httpRequestPack);
    +        err = errorCon(ERR_INVALID_REQ, HTTP_NOT_FOUND);
    +        err->request = requestLink(request);
    +        errorAppendEntry(entry, err);
         }
     }
     
    @@ -108,18 +111,25 @@ internalRemoteUri(const char *host, u_short port, const char *dir, const char *n
          * append the domain in order to mirror the requests with appended
          * domains
          */
    +
         if (Config.appendDomain && !strchr(lc_host, '.'))
    -	strncat(lc_host, Config.appendDomain, SQUIDHOSTNAMELEN -
    -	    strlen(lc_host) - 1);
    +        strncat(lc_host, Config.appendDomain, SQUIDHOSTNAMELEN -
    +                strlen(lc_host) - 1);
    +
         /* build uri in mb */
         memBufReset(&mb);
    +
         memBufPrintf(&mb, "http://%s", lc_host);
    +
         /* append port if not default */
         if (port && port != urlDefaultPort(PROTO_HTTP))
    -	memBufPrintf(&mb, ":%d", port);
    +        memBufPrintf(&mb, ":%d", port);
    +
         if (dir)
    -	memBufPrintf(&mb, "%s", dir);
    +        memBufPrintf(&mb, "%s", dir);
    +
         memBufPrintf(&mb, "%s", name);
    +
         /* return a pointer to a local static buffer */
         return mb.buf;
     }
    @@ -131,7 +141,7 @@ char *
     internalLocalUri(const char *dir, const char *name)
     {
         return internalRemoteUri(getMyHostname(),
    -	getMyPort(), dir, name);
    +                             getMyPort(), dir, name);
     }
     
     const char *
    @@ -147,10 +157,13 @@ int
     internalHostnameIs(const char *arg)
     {
         wordlist *w;
    +
         if (0 == strcmp(arg, internalHostname()))
    -	return 1;
    +        return 1;
    +
         for (w = Config.hostnameAliases; w; w = w->next)
    -	if (0 == strcmp(arg, w->key))
    -	    return 1;
    +        if (0 == strcmp(arg, w->key))
    +            return 1;
    +
         return 0;
     }
    diff --git a/src/ipc.cc b/src/ipc.cc
    index 4bb4083601..dd92c57173 100644
    --- a/src/ipc.cc
    +++ b/src/ipc.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: ipc.cc,v 1.35 2003/01/23 00:37:22 robertc Exp $
    + * $Id: ipc.cc,v 1.36 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 54    Interprocess Communication
      * AUTHOR: Duane Wessels
    @@ -45,22 +45,26 @@ static int
     ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
     {
         if (prfd >= 0)
    -	comm_close(prfd);
    +        comm_close(prfd);
    +
         if (prfd != pwfd)
    -	if (pwfd >= 0)
    -	    comm_close(pwfd);
    +        if (pwfd >= 0)
    +            comm_close(pwfd);
    +
         if (crfd >= 0)
    -	comm_close(crfd);
    +        comm_close(crfd);
    +
         if (crfd != cwfd)
    -	if (cwfd >= 0)
    -	    comm_close(cwfd);
    +        if (cwfd >= 0)
    +            comm_close(cwfd);
    +
         return -1;
     }
     
     static void
     PutEnvironment()
     {
    -#if HAVE_PUTENV   
    +#if HAVE_PUTENV
         char *env_str;
         int tmp_s;
         env_str = (char *)xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
    @@ -73,7 +77,9 @@ int
     ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd)
     {
         pid_t pid;
    +
         struct sockaddr_in CS;
    +
         struct sockaddr_in PS;
         int crfd = -1;
         int prfd = -1;
    @@ -85,234 +91,305 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name
         int x;
     
     #if USE_POLL && defined(_SQUID_OSF_)
    +
         assert(type != IPC_FIFO);
     #endif
     
         if (rfd)
    -	*rfd = -1;
    +        *rfd = -1;
    +
         if (wfd)
    -	*wfd = -1;
    +        *wfd = -1;
    +
         if (type == IPC_TCP_SOCKET) {
    -	crfd = cwfd = comm_open(SOCK_STREAM,
    -	    0,
    -	    local_addr,
    -	    0,
    -	    COMM_NOCLOEXEC,
    -	    name);
    -	prfd = pwfd = comm_open(SOCK_STREAM,
    -	    0,			/* protocol */
    -	    local_addr,
    -	    0,			/* port */
    -	    0,			/* blocking */
    -	    name);
    +        crfd = cwfd = comm_open(SOCK_STREAM,
    +                                0,
    +                                local_addr,
    +                                0,
    +                                COMM_NOCLOEXEC,
    +                                name);
    +        prfd = pwfd = comm_open(SOCK_STREAM,
    +                                0,			/* protocol */
    +                                local_addr,
    +                                0,			/* port */
    +                                0,			/* blocking */
    +                                name);
         } else if (type == IPC_UDP_SOCKET) {
    -	crfd = cwfd = comm_open(SOCK_DGRAM,
    -	    0,
    -	    local_addr,
    -	    0,
    -	    COMM_NOCLOEXEC,
    -	    name);
    -	prfd = pwfd = comm_open(SOCK_DGRAM,
    -	    0,
    -	    local_addr,
    -	    0,
    -	    0,
    -	    name);
    +        crfd = cwfd = comm_open(SOCK_DGRAM,
    +                                0,
    +                                local_addr,
    +                                0,
    +                                COMM_NOCLOEXEC,
    +                                name);
    +        prfd = pwfd = comm_open(SOCK_DGRAM,
    +                                0,
    +                                local_addr,
    +                                0,
    +                                0,
    +                                name);
         } else if (type == IPC_FIFO) {
    -	int p2c[2];
    -	int c2p[2];
    -	if (pipe(p2c) < 0) {
    -	    debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
    -	    return -1;
    -	}
    -	if (pipe(c2p) < 0) {
    -	    debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
    -	    return -1;
    -	}
    -	fdc_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read");
    -	fdc_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write");
    -	fdc_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read");
    -	fdc_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write");
    +        int p2c[2];
    +        int c2p[2];
    +
    +        if (pipe(p2c) < 0) {
    +            debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
    +            return -1;
    +        }
    +
    +        if (pipe(c2p) < 0) {
    +            debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
    +            return -1;
    +        }
    +
    +        fdc_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read");
    +        fdc_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write");
    +        fdc_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read");
    +        fdc_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write");
     #if HAVE_SOCKETPAIR && defined(AF_UNIX)
    +
         } else if (type == IPC_UNIX_STREAM) {
    -	int fds[2];
    -	int buflen = 32768;
    -	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
    -	    debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
    -	    return -1;
    -	}
    -	setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
    -	setsockopt(fds[0], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
    -	setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
    -	setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
    -	fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX STREAM Parent");
    -	fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX STREAM Parent");
    +        int fds[2];
    +        int buflen = 32768;
    +
    +        if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
    +            debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
    +            return -1;
    +        }
    +
    +        setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
    +        setsockopt(fds[0], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
    +        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
    +        setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
    +        fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX STREAM Parent");
    +        fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX STREAM Parent");
         } else if (type == IPC_UNIX_DGRAM) {
    -	int fds[2];
    -	if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) < 0) {
    -	    debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
    -	    return -1;
    -	}
    -	fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX DGRAM Parent");
    -	fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX DGRAM Parent");
    +        int fds[2];
    +
    +        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) < 0) {
    +            debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
    +            return -1;
    +        }
    +
    +        fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX DGRAM Parent");
    +        fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX DGRAM Parent");
     #endif
    +
         } else {
    -	assert(IPC_NONE);
    +        assert(IPC_NONE);
         }
    +
         debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd);
         debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd);
         debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd);
         debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd);
     
         if (crfd < 0) {
    -	debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
    -	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
    +        return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
         }
    +
         if (pwfd < 0) {
    -	debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
    -	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
    +        return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
         }
    +
         if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
    -	len = sizeof(PS);
    -	memset(&PS, '\0', len);
    -	if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) {
    -	    debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
    -	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    -	}
    -	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
    -	    pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port));
    -	len = sizeof(CS);
    -	memset(&CS, '\0', len);
    -	if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) {
    -	    debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
    -	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    -	}
    -	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
    -	    crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port));
    +        len = sizeof(PS);
    +        memset(&PS, '\0', len);
    +
    +        if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) {
    +            debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
    +            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        }
    +
    +        debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
    +                      pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port));
    +        len = sizeof(CS);
    +        memset(&CS, '\0', len);
    +
    +        if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) {
    +            debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
    +            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        }
    +
    +        debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
    +                      crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port));
         }
    +
         if (type == IPC_TCP_SOCKET) {
    -	if (listen(crfd, 1) < 0) {
    -	    debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
    -	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    -	}
    -	debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
    +        if (listen(crfd, 1) < 0) {
    +            debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
    +            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        }
    +
    +        debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
         }
    +
         /* flush or else we get dup data if unbuffered_logs is set */
         logsFlush();
    +
         if ((pid = fork()) < 0) {
    -	debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror());
    -	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror());
    +        return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
         }
    +
         if (pid > 0) {		/* parent */
    -	/* close shared socket with child */
    -	comm_close(crfd);
    -	if (cwfd != crfd)
    -	    comm_close(cwfd);
    -	cwfd = crfd = -1;
    -	if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
    -	    if (comm_connect_addr(pwfd, &CS) == COMM_ERROR)
    -		return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    -	}
    -	memset(hello_buf, '\0', HELLO_BUF_SZ);
    -	if (type == IPC_UDP_SOCKET)
    -	    x = comm_udp_recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
    -	else
    -	    x = read(prfd, hello_buf, HELLO_BUF_SZ - 1);
    -	if (x < 0) {
    -	    debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n");
    -	    debug(50, 0) ("--> read: %s\n", xstrerror());
    -	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    -	} else if (strcmp(hello_buf, hello_string)) {
    -	    debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
    -	    debug(54, 0) ("--> read returned %d\n", x);
    -	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
    -	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    -	}
    -	commSetTimeout(prfd, -1, NULL, NULL);
    -	commSetNonBlocking(prfd);
    -	commSetNonBlocking(pwfd);
    -	if (rfd)
    -	    *rfd = prfd;
    -	if (wfd)
    -	    *wfd = pwfd;
    -	fd_table[prfd].flags.ipc = 1;
    -	fd_table[pwfd].flags.ipc = 1;
    -	if (Config.sleep_after_fork) {
    -	    /* XXX emulation of usleep() */
    -	    struct timeval sl;
    -	    sl.tv_sec = Config.sleep_after_fork / 1000000;
    -	    sl.tv_usec = Config.sleep_after_fork % 1000000;
    -	    select(0, NULL, NULL, NULL, &sl);
    -	}
    -	return pid;
    +        /* close shared socket with child */
    +        comm_close(crfd);
    +
    +        if (cwfd != crfd)
    +            comm_close(cwfd);
    +
    +        cwfd = crfd = -1;
    +
    +        if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
    +            if (comm_connect_addr(pwfd, &CS) == COMM_ERROR)
    +                return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        }
    +
    +        memset(hello_buf, '\0', HELLO_BUF_SZ);
    +
    +        if (type == IPC_UDP_SOCKET)
    +            x = comm_udp_recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
    +        else
    +            x = read(prfd, hello_buf, HELLO_BUF_SZ - 1);
    +
    +        if (x < 0) {
    +            debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n");
    +            debug(50, 0) ("--> read: %s\n", xstrerror());
    +            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        } else if (strcmp(hello_buf, hello_string)) {
    +            debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
    +            debug(54, 0) ("--> read returned %d\n", x);
    +            debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
    +            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        }
    +
    +        commSetTimeout(prfd, -1, NULL, NULL);
    +        commSetNonBlocking(prfd);
    +        commSetNonBlocking(pwfd);
    +
    +        if (rfd)
    +            *rfd = prfd;
    +
    +        if (wfd)
    +            *wfd = pwfd;
    +
    +        fd_table[prfd].flags.ipc = 1;
    +
    +        fd_table[pwfd].flags.ipc = 1;
    +
    +        if (Config.sleep_after_fork) {
    +            /* XXX emulation of usleep() */
    +
    +            struct timeval sl;
    +            sl.tv_sec = Config.sleep_after_fork / 1000000;
    +            sl.tv_usec = Config.sleep_after_fork % 1000000;
    +            select(0, NULL, NULL, NULL, &sl);
    +        }
    +
    +        return pid;
         }
    +
         /* child */
         no_suid();			/* give up extra priviliges */
    +
         /* close shared socket with parent */
         close(prfd);
    +
         if (pwfd != prfd)
    -	close(pwfd);
    +        close(pwfd);
    +
         pwfd = prfd = -1;
     
         if (type == IPC_TCP_SOCKET) {
    -	debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
    -	if ((fd = accept(crfd, NULL, NULL)) < 0) {
    -	    debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
    -	    _exit(1);
    -	}
    -	debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
    -	close(crfd);
    -	cwfd = crfd = fd;
    +        debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
    +
    +        if ((fd = accept(crfd, NULL, NULL)) < 0) {
    +            debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
    +            _exit(1);
    +        }
    +
    +        debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
    +        close(crfd);
    +        cwfd = crfd = fd;
         } else if (type == IPC_UDP_SOCKET) {
    -	if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
    -	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    +        if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
    +            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
         }
    +
         if (type == IPC_UDP_SOCKET) {
    -	x = comm_udp_send(cwfd, hello_string, strlen(hello_string) + 1, 0);
    -	if (x < 0) {
    -	    debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
    -	    debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
    -	    _exit(1);
    -	}
    +        x = comm_udp_send(cwfd, hello_string, strlen(hello_string) + 1, 0);
    +
    +        if (x < 0) {
    +            debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
    +            debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
    +            _exit(1);
    +        }
         } else {
    -	if (write(cwfd, hello_string, strlen(hello_string) + 1) < 0) {
    -	    debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror());
    -	    debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
    -	    _exit(1);
    -	}
    +        if (write(cwfd, hello_string, strlen(hello_string) + 1) < 0) {
    +            debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror());
    +            debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
    +            _exit(1);
    +        }
         }
    +
         PutEnvironment();
         /*
          * This double-dup stuff avoids problems when one of 
          *  crfd, cwfd, or debug_log are in the rage 0-2.
          */
    +
         do {
    -	x = open(_PATH_DEVNULL, 0, 0444);
    -	if (x > -1)
    -	    commSetCloseOnExec(x);
    +        x = open(_PATH_DEVNULL, 0, 0444);
    +
    +        if (x > -1)
    +            commSetCloseOnExec(x);
         } while (x < 3);
    +
         t1 = dup(crfd);
    +
         t2 = dup(cwfd);
    +
         t3 = dup(fileno(debug_log));
    +
         assert(t1 > 2 && t2 > 2 && t3 > 2);
    +
         close(crfd);
    +
         close(cwfd);
    +
         close(fileno(debug_log));
    +
         dup2(t1, 0);
    +
         dup2(t2, 1);
    +
         dup2(t3, 2);
    +
         close(t1);
    +
         close(t2);
    +
         close(t3);
    +
         /* Make sure all other filedescriptors are closed */
         for (x = 3; x < SQUID_MAXFD; x++)
    -	close(x);
    +        close(x);
    +
     #if HAVE_SETSID
    +
         setsid();
    +
     #endif
    +
         execvp(prog, (char *const *) args);
    +
         debug_log = fdopen(2, "a+");
    +
         debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror());
    +
         _exit(1);
    +
         return 0;
     }
    diff --git a/src/ipcache.cc b/src/ipcache.cc
    index 801f212cc6..cf56486b8f 100644
    --- a/src/ipcache.cc
    +++ b/src/ipcache.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: ipcache.cc,v 1.241 2003/02/13 20:47:53 wessels Exp $
    + * $Id: ipcache.cc,v 1.242 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 14    IP Cache
      * AUTHOR: Harvest Derived
    @@ -38,7 +38,8 @@
     
     typedef struct _ipcache_entry ipcache_entry;
     
    -struct _ipcache_entry {
    +struct _ipcache_entry
    +{
         hash_link hash;		/* must be first */
         time_t lastref;
         time_t expires;
    @@ -46,22 +47,34 @@ struct _ipcache_entry {
         IPH *handler;
         void *handlerData;
         char *error_message;
    +
         struct timeval request_time;
         dlink_node lru;
         unsigned short locks;
    -    struct {
    -	unsigned int negcached:1;
    -	unsigned int fromhosts:1;
    -    } flags;
    +
    +    struct
    +    {
    +
    +unsigned int negcached:
    +        1;
    +
    +unsigned int fromhosts:
    +        1;
    +    }
    +
    +    flags;
     };
     
    -static struct {
    +static struct
    +{
         int requests;
         int replies;
         int hits;
         int misses;
         int negative_hits;
    -} IpcacheStats;
    +}
    +
    +IpcacheStats;
     
     static dlink_list lru_list;
     
    @@ -100,12 +113,15 @@ ipcache_testname(void)
     {
         wordlist *w = NULL;
         debug(14, 1) ("Performing DNS Tests...\n");
    +
         if ((w = Config.dns_testname_list) == NULL)
    -	return 1;
    +        return 1;
    +
         for (; w; w = w->next) {
    -	if (gethostbyname(w->key) != NULL)
    -	    return 1;
    +        if (gethostbyname(w->key) != NULL)
    +            return 1;
         }
    +
         return 0;
     }
     
    @@ -122,22 +138,26 @@ static ipcache_entry *
     ipcache_get(const char *name)
     {
         if (ip_table != NULL)
    -	return (ipcache_entry *) hash_lookup(ip_table, name);
    +        return (ipcache_entry *) hash_lookup(ip_table, name);
         else
    -	return NULL;
    +        return NULL;
     }
     
     static int
     ipcacheExpiredEntry(ipcache_entry * i)
     {
         /* all static entries are locked, so this takes care of them too */
    +
         if (i->locks != 0)
    -	return 0;
    +        return 0;
    +
         if (i->addrs.count == 0)
    -	if (0 == i->flags.negcached)
    -	    return 1;
    +        if (0 == i->flags.negcached)
    +            return 1;
    +
         if (i->expires > squid_curtime)
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -149,16 +169,23 @@ ipcache_purgelru(void *voidnotused)
         ipcache_entry *i;
         int removed = 0;
         eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
    +
         for (m = lru_list.tail; m; m = prev) {
    -	if (memInUse(MEM_IPCACHE_ENTRY) < ipcache_low)
    -	    break;
    -	prev = m->prev;
    -	i = (ipcache_entry *)m->data;
    -	if (i->locks != 0)
    -	    continue;
    -	ipcacheRelease(i);
    -	removed++;
    +        if (memInUse(MEM_IPCACHE_ENTRY) < ipcache_low)
    +            break;
    +
    +        prev = m->prev;
    +
    +        i = (ipcache_entry *)m->data;
    +
    +        if (i->locks != 0)
    +            continue;
    +
    +        ipcacheRelease(i);
    +
    +        removed++;
         }
    +
         debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed);
     }
     
    @@ -168,18 +195,23 @@ purge_entries_fromhosts(void)
     {
         dlink_node *m = lru_list.head;
         ipcache_entry *i = NULL, *t;
    +
         while (m) {
    -	if (i != NULL) {	/* need to delay deletion */
    -	    ipcacheRelease(i);	/* we just override locks */
    -	    i = NULL;
    -	}
    -	t = (ipcache_entry*)m->data;
    -	if (t->flags.fromhosts)
    -	    i = t;
    -	m = m->next;
    +        if (i != NULL) {	/* need to delay deletion */
    +            ipcacheRelease(i);	/* we just override locks */
    +            i = NULL;
    +        }
    +
    +        t = (ipcache_entry*)m->data;
    +
    +        if (t->flags.fromhosts)
    +            i = t;
    +
    +        m = m->next;
         }
    +
         if (i != NULL)
    -	ipcacheRelease(i);
    +        ipcacheRelease(i);
     }
     
     /* create blank ipcache_entry */
    @@ -197,11 +229,13 @@ static void
     ipcacheAddEntry(ipcache_entry * i)
     {
         hash_link *e = (hash_link *)hash_lookup(ip_table, i->hash.key);
    +
         if (NULL != e) {
    -	/* avoid colission */
    -	ipcache_entry *q = (ipcache_entry *) e;
    -	ipcacheRelease(q);
    +        /* avoid colission */
    +        ipcache_entry *q = (ipcache_entry *) e;
    +        ipcacheRelease(q);
         }
    +
         hash_join(ip_table, &i->hash);
         dlinkAdd(i, &i->lru, &lru_list);
         i->lastref = squid_curtime;
    @@ -214,15 +248,21 @@ ipcacheCallback(ipcache_entry * i)
         IPH *callback = i->handler;
         void *cbdata;
         i->lastref = squid_curtime;
    +
         if (!i->handler)
    -	return;
    +        return;
    +
         ipcacheLockEntry(i);
    +
         callback = i->handler;
    +
         i->handler = NULL;
    +
         if (cbdataReferenceValidDone(i->handlerData, &cbdata)) {
    -	dns_error_message = i->error_message;
    -	callback(i->flags.negcached ? NULL : &i->addrs, cbdata);
    +        dns_error_message = i->error_message;
    +        callback(i->flags.negcached ? NULL : &i->addrs, cbdata);
         }
    +
         ipcacheUnlockEntry(i);
     }
     
    @@ -241,61 +281,77 @@ ipcacheParse(const char *inbuf)
         memset(&i, '\0', sizeof(i));
         i.expires = squid_curtime;
         i.flags.negcached = 1;
    +
         if (inbuf == NULL) {
    -	debug(14, 1) ("ipcacheParse: Got  reply\n");
    -	i.error_message = xstrdup("Internal Squid Error");
    -	return &i;
    +        debug(14, 1) ("ipcacheParse: Got  reply\n");
    +        i.error_message = xstrdup("Internal Squid Error");
    +        return &i;
         }
    +
         xstrncpy(buf, inbuf, DNS_INBUF_SZ);
         debug(14, 5) ("ipcacheParse: parsing: {%s}\n", buf);
         token = strtok(buf, w_space);
    +
         if (NULL == token) {
    -	debug(14, 1) ("ipcacheParse: Got , expecting '$addr'\n");
    -	return &i;
    +        debug(14, 1) ("ipcacheParse: Got , expecting '$addr'\n");
    +        return &i;
         }
    +
         if (0 == strcmp(token, "$fail")) {
    -	i.expires = squid_curtime + Config.negativeDnsTtl;
    -	token = strtok(NULL, "\n");
    -	assert(NULL != token);
    -	i.error_message = xstrdup(token);
    -	return &i;
    +        i.expires = squid_curtime + Config.negativeDnsTtl;
    +        token = strtok(NULL, "\n");
    +        assert(NULL != token);
    +        i.error_message = xstrdup(token);
    +        return &i;
         }
    +
         if (0 != strcmp(token, "$addr")) {
    -	debug(14, 1) ("ipcacheParse: Got '%s', expecting '$addr'\n", token);
    -	return &i;
    +        debug(14, 1) ("ipcacheParse: Got '%s', expecting '$addr'\n", token);
    +        return &i;
         }
    +
         token = strtok(NULL, w_space);
    +
         if (NULL == token) {
    -	debug(14, 1) ("ipcacheParse: Got , expecting TTL\n");
    -	return &i;
    +        debug(14, 1) ("ipcacheParse: Got , expecting TTL\n");
    +        return &i;
         }
    +
         i.flags.negcached = 0;
         ttl = atoi(token);
    +
         if (ttl > 0)
    -	i.expires = squid_curtime + ttl;
    +        i.expires = squid_curtime + ttl;
         else
    -	i.expires = squid_curtime + Config.positiveDnsTtl;
    +        i.expires = squid_curtime + Config.positiveDnsTtl;
    +
         while (NULL != (token = strtok(NULL, w_space))) {
    -	xstrncpy(A[ipcount], token, 16);
    -	if (++ipcount == 32)
    -	    break;
    +        xstrncpy(A[ipcount], token, 16);
    +
    +        if (++ipcount == 32)
    +            break;
         }
    +
         if (0 == ipcount) {
    -	i.addrs.in_addrs = NULL;
    -	i.addrs.bad_mask = NULL;
    +        i.addrs.in_addrs = NULL;
    +        i.addrs.bad_mask = NULL;
         } else {
    -	i.addrs.in_addrs = (struct in_addr *)xcalloc(ipcount, sizeof(struct in_addr));
    -	i.addrs.bad_mask = (unsigned char *)xcalloc(ipcount, sizeof(unsigned char));
    +
    +        i.addrs.in_addrs = (struct in_addr *)xcalloc(ipcount, sizeof(struct in_addr));
    +        i.addrs.bad_mask = (unsigned char *)xcalloc(ipcount, sizeof(unsigned char));
         }
    +
         for (j = 0, k = 0; k < ipcount; k++) {
    -	if (safe_inet_addr(A[k], &i.addrs.in_addrs[j]))
    -	    j++;
    -	else
    -	    debug(14, 1) ("ipcacheParse: Invalid IP address '%s'\n", A[k]);
    +        if (safe_inet_addr(A[k], &i.addrs.in_addrs[j]))
    +            j++;
    +        else
    +            debug(14, 1) ("ipcacheParse: Invalid IP address '%s'\n", A[k]);
         }
    +
         i.addrs.count = (unsigned char) j;
         return &i;
     }
    +
     #else
     ipcacheParse(rfc1035_rr * answers, int nr)
     {
    @@ -306,51 +362,68 @@ ipcacheParse(rfc1035_rr * answers, int nr)
         memset(&i, '\0', sizeof(i));
         i.expires = squid_curtime + Config.negativeDnsTtl;
         i.flags.negcached = 1;
    +
         if (nr < 0) {
    -	debug(14, 3) ("ipcacheParse: Lookup failed (error %d)\n",
    -	    rfc1035_errno);
    -	assert(rfc1035_error_message);
    -	i.error_message = xstrdup(rfc1035_error_message);
    -	return &i;
    +        debug(14, 3) ("ipcacheParse: Lookup failed (error %d)\n",
    +                      rfc1035_errno);
    +        assert(rfc1035_error_message);
    +        i.error_message = xstrdup(rfc1035_error_message);
    +        return &i;
         }
    +
         if (nr == 0) {
    -	debug(14, 3) ("ipcacheParse: No DNS records\n");
    -	i.error_message = xstrdup("No DNS records");
    -	return &i;
    +        debug(14, 3) ("ipcacheParse: No DNS records\n");
    +        i.error_message = xstrdup("No DNS records");
    +        return &i;
         }
    +
         assert(answers);
    +
         for (j = 0, k = 0; k < nr; k++) {
    -	if (answers[k].type != RFC1035_TYPE_A)
    -	    continue;
    -	if (answers[k]._class != RFC1035_CLASS_IN)
    -	    continue;
    -	na++;
    +        if (answers[k].type != RFC1035_TYPE_A)
    +            continue;
    +
    +        if (answers[k]._class != RFC1035_CLASS_IN)
    +            continue;
    +
    +        na++;
         }
    +
         if (na == 0) {
    -	debug(14, 1) ("ipcacheParse: No Address records\n");
    -	i.error_message = xstrdup("No Address records");
    -	return &i;
    +        debug(14, 1) ("ipcacheParse: No Address records\n");
    +        i.error_message = xstrdup("No Address records");
    +        return &i;
         }
    +
         i.flags.negcached = 0;
    +
         i.addrs.in_addrs = (struct in_addr *)xcalloc(na, sizeof(struct in_addr));
         i.addrs.bad_mask = (unsigned char *)xcalloc(na, sizeof(unsigned char));
         i.addrs.count = (unsigned char) na;
    +
         for (j = 0, k = 0; k < nr; k++) {
    -	if (answers[k].type != RFC1035_TYPE_A)
    -	    continue;
    -	if (answers[k]._class != RFC1035_CLASS_IN)
    -	    continue;
    -	if (j == 0)
    -	    i.expires = squid_curtime + answers[k].ttl;
    -	assert(answers[k].rdlength == 4);
    -	xmemcpy(&i.addrs.in_addrs[j++], answers[k].rdata, 4);
    -	debug(14, 3) ("ipcacheParse: #%d %s\n",
    -	    j - 1,
    -	    inet_ntoa(i.addrs.in_addrs[j - 1]));
    +        if (answers[k].type != RFC1035_TYPE_A)
    +            continue;
    +
    +        if (answers[k]._class != RFC1035_CLASS_IN)
    +            continue;
    +
    +        if (j == 0)
    +            i.expires = squid_curtime + answers[k].ttl;
    +
    +        assert(answers[k].rdlength == 4);
    +
    +        xmemcpy(&i.addrs.in_addrs[j++], answers[k].rdata, 4);
    +
    +        debug(14, 3) ("ipcacheParse: #%d %s\n",
    +                      j - 1,
    +                      inet_ntoa(i.addrs.in_addrs[j - 1]));
         }
    +
         assert(j == na);
         return &i;
     }
    +
     #endif
     
     static void
    @@ -367,12 +440,15 @@ ipcacheHandleReply(void *data, rfc1035_rr * answers, int na)
         c = NULL;
         IpcacheStats.replies++;
         statHistCount(&statCounter.dns.svc_time,
    -	tvSubMsec(i->request_time, current_time));
    +                  tvSubMsec(i->request_time, current_time));
     #if USE_DNSSERVERS
    +
         x = ipcacheParse(reply);
     #else
    +
         x = ipcacheParse(answers, na);
     #endif
    +
         assert(x);
         i->addrs = x->addrs;
         i->error_message = x->error_message;
    @@ -391,35 +467,45 @@ ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData)
         assert(handler != NULL);
         debug(14, 4) ("ipcache_nbgethostbyname: Name '%s'.\n", name);
         IpcacheStats.requests++;
    +
         if (name == NULL || name[0] == '\0') {
    -	debug(14, 4) ("ipcache_nbgethostbyname: Invalid name!\n");
    -	handler(NULL, handlerData);
    -	return;
    +        debug(14, 4) ("ipcache_nbgethostbyname: Invalid name!\n");
    +        handler(NULL, handlerData);
    +        return;
         }
    +
         if ((addrs = ipcacheCheckNumeric(name))) {
    -	handler(addrs, handlerData);
    -	return;
    +        handler(addrs, handlerData);
    +        return;
         }
    +
         i = ipcache_get(name);
    +
         if (NULL == i) {
    -	/* miss */
    -	(void) 0;
    +        /* miss */
    +        (void) 0;
         } else if (ipcacheExpiredEntry(i)) {
    -	/* hit, but expired -- bummer */
    -	ipcacheRelease(i);
    -	i = NULL;
    +        /* hit, but expired -- bummer */
    +        ipcacheRelease(i);
    +        i = NULL;
         } else {
    -	/* hit */
    -	debug(14, 4) ("ipcache_nbgethostbyname: HIT for '%s'\n", name);
    -	if (i->flags.negcached)
    -	    IpcacheStats.negative_hits++;
    -	else
    -	    IpcacheStats.hits++;
    -	i->handler = handler;
    -	i->handlerData = cbdataReference(handlerData);
    -	ipcacheCallback(i);
    -	return;
    +        /* hit */
    +        debug(14, 4) ("ipcache_nbgethostbyname: HIT for '%s'\n", name);
    +
    +        if (i->flags.negcached)
    +            IpcacheStats.negative_hits++;
    +        else
    +            IpcacheStats.hits++;
    +
    +        i->handler = handler;
    +
    +        i->handlerData = cbdataReference(handlerData);
    +
    +        ipcacheCallback(i);
    +
    +        return;
         }
    +
         debug(14, 5) ("ipcache_nbgethostbyname: MISS for '%s'\n", name);
         IpcacheStats.misses++;
         i = ipcacheCreateEntry(name);
    @@ -429,8 +515,10 @@ ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData)
         c = cbdataAlloc(generic_cbdata);
         c->data = i;
     #if USE_DNSSERVERS
    +
         dnsSubmit(hashKeyStr(&i->hash), ipcacheHandleReply, c);
     #else
    +
         idnsALookup(hashKeyStr(&i->hash), ipcacheHandleReply, c);
     #endif
     }
    @@ -444,25 +532,28 @@ ipcache_init(void)
         memset(&IpcacheStats, '\0', sizeof(IpcacheStats));
         memset(&lru_list, '\0', sizeof(lru_list));
         /* test naming lookup */
    +
         if (!opt_dns_tests) {
    -	debug(14, 4) ("ipcache_init: Skipping DNS name lookup tests.\n");
    +        debug(14, 4) ("ipcache_init: Skipping DNS name lookup tests.\n");
         } else if (!ipcache_testname()) {
    -	fatal("ipcache_init: DNS name lookup tests failed.");
    +        fatal("ipcache_init: DNS name lookup tests failed.");
         } else {
    -	debug(14, 1) ("Successful DNS name lookup tests...\n");
    +        debug(14, 1) ("Successful DNS name lookup tests...\n");
         }
    +
         memset(&static_addrs, '\0', sizeof(ipcache_addrs));
    +
         static_addrs.in_addrs = (struct in_addr *)xcalloc(1, sizeof(struct in_addr));
         static_addrs.bad_mask = (unsigned char *)xcalloc(1, sizeof(unsigned char));
         ipcache_high = (long) (((float) Config.ipcache.size *
    -	    (float) Config.ipcache.high) / (float) 100);
    +                            (float) Config.ipcache.high) / (float) 100);
         ipcache_low = (long) (((float) Config.ipcache.size *
    -	    (float) Config.ipcache.low) / (float) 100);
    +                           (float) Config.ipcache.low) / (float) 100);
         n = hashPrime(ipcache_high / 4);
         ip_table = hash_create((HASHCMP *) strcmp, n, hash4);
         cachemgrRegister("ipcache",
    -	"IP Cache Stats and Contents",
    -	stat_ipcache_get, 0, 1);
    +                     "IP Cache Stats and Contents",
    +                     stat_ipcache_get, 0, 1);
         memDataInit(MEM_IPCACHE_ENTRY, "ipcache_entry", sizeof(ipcache_entry), 0);
     }
     
    @@ -475,25 +566,30 @@ ipcache_gethostbyname(const char *name, int flags)
         debug(14, 3) ("ipcache_gethostbyname: '%s', flags=%x\n", name, flags);
         IpcacheStats.requests++;
         i = ipcache_get(name);
    +
         if (NULL == i) {
    -	(void) 0;
    +        (void) 0;
         } else if (ipcacheExpiredEntry(i)) {
    -	ipcacheRelease(i);
    -	i = NULL;
    +        ipcacheRelease(i);
    +        i = NULL;
         } else if (i->flags.negcached) {
    -	IpcacheStats.negative_hits++;
    -	dns_error_message = i->error_message;
    -	return NULL;
    +        IpcacheStats.negative_hits++;
    +        dns_error_message = i->error_message;
    +        return NULL;
         } else {
    -	IpcacheStats.hits++;
    -	i->lastref = squid_curtime;
    -	return &i->addrs;
    +        IpcacheStats.hits++;
    +        i->lastref = squid_curtime;
    +        return &i->addrs;
         }
    +
         if ((addrs = ipcacheCheckNumeric(name)))
    -	return addrs;
    +        return addrs;
    +
         IpcacheStats.misses++;
    +
         if (flags & IP_LOOKUP_IF_MISS)
    -	ipcache_nbgethostbyname(name, dummy_handler, NULL);
    +        ipcache_nbgethostbyname(name, dummy_handler, NULL);
    +
         return NULL;
     }
     
    @@ -502,17 +598,19 @@ ipcacheStatPrint(ipcache_entry * i, StoreEntry * sentry)
     {
         int k;
         storeAppendPrintf(sentry, " %-32.32s %c%c %6d %6d %2d(%2d)",
    -	hashKeyStr(&i->hash),
    -	i->flags.fromhosts ? 'H' : ' ',
    -	i->flags.negcached ? 'N' : ' ',
    -	(int) (squid_curtime - i->lastref),
    -	(int) ((i->flags.fromhosts ? -1 : i->expires - squid_curtime)),
    -	(int) i->addrs.count,
    -	(int) i->addrs.badcount);
    +                      hashKeyStr(&i->hash),
    +                      i->flags.fromhosts ? 'H' : ' ',
    +                      i->flags.negcached ? 'N' : ' ',
    +                      (int) (squid_curtime - i->lastref),
    +                      (int) ((i->flags.fromhosts ? -1 : i->expires - squid_curtime)),
    +                      (int) i->addrs.count,
    +                      (int) i->addrs.badcount);
    +
         for (k = 0; k < (int) i->addrs.count; k++) {
    -	storeAppendPrintf(sentry, " %15s-%3s", inet_ntoa(i->addrs.in_addrs[k]),
    -	    i->addrs.bad_mask[k] ? "BAD" : "OK ");
    +        storeAppendPrintf(sentry, " %15s-%3s", inet_ntoa(i->addrs.in_addrs[k]),
    +                          i->addrs.bad_mask[k] ? "BAD" : "OK ");
         }
    +
         storeAppendPrintf(sentry, "\n");
     }
     
    @@ -524,25 +622,26 @@ stat_ipcache_get(StoreEntry * sentry)
         assert(ip_table != NULL);
         storeAppendPrintf(sentry, "IP Cache Statistics:\n");
         storeAppendPrintf(sentry, "IPcache Entries: %d\n",
    -	memInUse(MEM_IPCACHE_ENTRY));
    +                      memInUse(MEM_IPCACHE_ENTRY));
         storeAppendPrintf(sentry, "IPcache Requests: %d\n",
    -	IpcacheStats.requests);
    +                      IpcacheStats.requests);
         storeAppendPrintf(sentry, "IPcache Hits: %d\n",
    -	IpcacheStats.hits);
    +                      IpcacheStats.hits);
         storeAppendPrintf(sentry, "IPcache Negative Hits: %d\n",
    -	IpcacheStats.negative_hits);
    +                      IpcacheStats.negative_hits);
         storeAppendPrintf(sentry, "IPcache Misses: %d\n",
    -	IpcacheStats.misses);
    +                      IpcacheStats.misses);
         storeAppendPrintf(sentry, "\n\n");
         storeAppendPrintf(sentry, "IP Cache Contents:\n\n");
         storeAppendPrintf(sentry, " %-29.29s %3s %6s %6s %1s\n",
    -	"Hostname",
    -	"Flg",
    -	"lstref",
    -	"TTL",
    -	"N");
    +                      "Hostname",
    +                      "Flg",
    +                      "lstref",
    +                      "TTL",
    +                      "N");
    +
         for (m = lru_list.head; m; m = m->next)
    -	ipcacheStatPrint((ipcache_entry *)m->data, sentry);
    +        ipcacheStatPrint((ipcache_entry *)m->data, sentry);
     }
     
     static void
    @@ -555,9 +654,12 @@ void
     ipcacheInvalidate(const char *name)
     {
         ipcache_entry *i;
    +
         if ((i = ipcache_get(name)) == NULL)
    -	return;
    +        return;
    +
         i->expires = squid_curtime;
    +
         /*
          * NOTE, don't call ipcacheRelease here becuase we might be here due
          * to a thread started from a callback.
    @@ -567,15 +669,23 @@ ipcacheInvalidate(const char *name)
     ipcache_addrs *
     ipcacheCheckNumeric(const char *name)
     {
    +
         struct in_addr ip;
         /* check if it's already a IP address in text form. */
    +
         if (!safe_inet_addr(name, &ip))
    -	return NULL;
    +        return NULL;
    +
         static_addrs.count = 1;
    +
         static_addrs.cur = 0;
    +
         static_addrs.in_addrs[0].s_addr = ip.s_addr;
    +
         static_addrs.bad_mask[0] = FALSE;
    +
         static_addrs.badcount = 0;
    +
         return &static_addrs;
     }
     
    @@ -583,8 +693,8 @@ static void
     ipcacheLockEntry(ipcache_entry * i)
     {
         if (i->locks++ == 0) {
    -	dlinkDelete(&i->lru, &lru_list);
    -	dlinkAdd(i, &i->lru, &lru_list);
    +        dlinkDelete(&i->lru, &lru_list);
    +        dlinkAdd(i, &i->lru, &lru_list);
         }
     }
     
    @@ -593,8 +703,9 @@ ipcacheUnlockEntry(ipcache_entry * i)
     {
         assert(i->locks > 0);
         i->locks--;
    +
         if (ipcacheExpiredEntry(i))
    -	ipcacheRelease(i);
    +        ipcacheRelease(i);
     }
     
     void
    @@ -603,30 +714,40 @@ ipcacheCycleAddr(const char *name, ipcache_addrs * ia)
         ipcache_entry *i;
         unsigned char k;
         assert(name || ia);
    +
         if (NULL == ia) {
    -	if ((i = ipcache_get(name)) == NULL)
    -	    return;
    -	if (i->flags.negcached)
    -	    return;
    -	ia = &i->addrs;
    +        if ((i = ipcache_get(name)) == NULL)
    +            return;
    +
    +        if (i->flags.negcached)
    +            return;
    +
    +        ia = &i->addrs;
         }
    +
         for (k = 0; k < ia->count; k++) {
    -	if (++ia->cur == ia->count)
    -	    ia->cur = 0;
    -	if (!ia->bad_mask[ia->cur])
    -	    break;
    +        if (++ia->cur == ia->count)
    +            ia->cur = 0;
    +
    +        if (!ia->bad_mask[ia->cur])
    +            break;
         }
    +
         if (k == ia->count) {
    -	/* All bad, reset to All good */
    -	debug(14, 3) ("ipcacheCycleAddr: Changing ALL %s addrs from BAD to OK\n",
    -	    name);
    -	for (k = 0; k < ia->count; k++)
    -	    ia->bad_mask[k] = 0;
    -	ia->badcount = 0;
    -	ia->cur = 0;
    +        /* All bad, reset to All good */
    +        debug(14, 3) ("ipcacheCycleAddr: Changing ALL %s addrs from BAD to OK\n",
    +                      name);
    +
    +        for (k = 0; k < ia->count; k++)
    +            ia->bad_mask[k] = 0;
    +
    +        ia->badcount = 0;
    +
    +        ia->cur = 0;
         }
    +
         debug(14, 3) ("ipcacheCycleAddr: %s now at %s\n", name,
    -	inet_ntoa(ia->in_addrs[ia->cur]));
    +                  inet_ntoa(ia->in_addrs[ia->cur]));
     }
     
     /*
    @@ -634,47 +755,66 @@ ipcacheCycleAddr(const char *name, ipcache_addrs * ia)
      * advance the current pointer to the next OK address.
      */
     void
    +
     ipcacheMarkBadAddr(const char *name, struct in_addr addr)
     {
         ipcache_entry *i;
         ipcache_addrs *ia;
         int k;
    +
         if ((i = ipcache_get(name)) == NULL)
    -	return;
    +        return;
    +
         ia = &i->addrs;
    -    for (k = 0; k < (int) ia->count; k++) {
    -	if (ia->in_addrs[k].s_addr == addr.s_addr)
    -	    break;
    +
    +    for (k = 0; k < (int) ia->count; k++)
    +    {
    +        if (ia->in_addrs[k].s_addr == addr.s_addr)
    +            break;
         }
    +
         if (k == (int) ia->count)	/* not found */
    -	return;
    -    if (!ia->bad_mask[k]) {
    -	ia->bad_mask[k] = TRUE;
    -	ia->badcount++;
    -	debug(14, 2) ("ipcacheMarkBadAddr: %s [%s]\n", name, inet_ntoa(addr));
    +        return;
    +
    +    if (!ia->bad_mask[k])
    +    {
    +        ia->bad_mask[k] = TRUE;
    +        ia->badcount++;
    +        debug(14, 2) ("ipcacheMarkBadAddr: %s [%s]\n", name, inet_ntoa(addr));
         }
    +
         ipcacheCycleAddr(name, ia);
     }
     
     void
    +
     ipcacheMarkGoodAddr(const char *name, struct in_addr addr)
     {
         ipcache_entry *i;
         ipcache_addrs *ia;
         int k;
    +
         if ((i = ipcache_get(name)) == NULL)
    -	return;
    +        return;
    +
         ia = &i->addrs;
    -    for (k = 0; k < (int) ia->count; k++) {
    -	if (ia->in_addrs[k].s_addr == addr.s_addr)
    -	    break;
    +
    +    for (k = 0; k < (int) ia->count; k++)
    +    {
    +        if (ia->in_addrs[k].s_addr == addr.s_addr)
    +            break;
         }
    +
         if (k == (int) ia->count)	/* not found */
    -	return;
    +        return;
    +
         if (!ia->bad_mask[k])	/* already OK */
    -	return;
    +        return;
    +
         ia->bad_mask[k] = FALSE;
    +
         ia->badcount--;
    +
         debug(14, 2) ("ipcacheMarkGoodAddr: %s [%s]\n", name, inet_ntoa(addr));
     }
     
    @@ -702,9 +842,9 @@ void
     ipcache_restart(void)
     {
         ipcache_high = (long) (((float) Config.ipcache.size *
    -	    (float) Config.ipcache.high) / (float) 100);
    +                            (float) Config.ipcache.high) / (float) 100);
         ipcache_low = (long) (((float) Config.ipcache.size *
    -	    (float) Config.ipcache.low) / (float) 100);
    +                           (float) Config.ipcache.low) / (float) 100);
         purge_entries_fromhosts();
     }
     
    @@ -716,31 +856,37 @@ int
     ipcacheAddEntryFromHosts(const char *name, const char *ipaddr)
     {
         ipcache_entry *i;
    +
         struct in_addr ip;
    +
         if (!safe_inet_addr(ipaddr, &ip)) {
    -	if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) {
    -	    debug(14, 3) ("ipcacheAddEntryFromHosts: Skipping IPv6 address '%s'\n", ipaddr);
    -	} else {
    -	    debug(14, 1) ("ipcacheAddEntryFromHosts: Bad IP address '%s'\n",
    -		ipaddr);
    -	}
    -	return 1;
    +        if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) {
    +            debug(14, 3) ("ipcacheAddEntryFromHosts: Skipping IPv6 address '%s'\n", ipaddr);
    +        } else {
    +            debug(14, 1) ("ipcacheAddEntryFromHosts: Bad IP address '%s'\n",
    +                          ipaddr);
    +        }
    +
    +        return 1;
         }
    +
         if ((i = ipcache_get(name))) {
    -	if (1 == i->flags.fromhosts) {
    -	    ipcacheUnlockEntry(i);
    -	} else if (i->locks > 0) {
    -	    debug(14, 1) ("ipcacheAddEntryFromHosts: can't add static entry"
    -		" for locked name '%s'\n", name);
    -	    return 1;
    -	} else {
    -	    ipcacheRelease(i);
    -	}
    +        if (1 == i->flags.fromhosts) {
    +            ipcacheUnlockEntry(i);
    +        } else if (i->locks > 0) {
    +            debug(14, 1) ("ipcacheAddEntryFromHosts: can't add static entry"
    +                          " for locked name '%s'\n", name);
    +            return 1;
    +        } else {
    +            ipcacheRelease(i);
    +        }
         }
    +
         i = ipcacheCreateEntry(name);
         i->addrs.count = 1;
         i->addrs.cur = 0;
         i->addrs.badcount = 0;
    +
         i->addrs.in_addrs = (struct in_addr *)xcalloc(1, sizeof(struct in_addr));
         i->addrs.bad_mask = (unsigned char *)xcalloc(1, sizeof(unsigned char));
         i->addrs.in_addrs[0].s_addr = ip.s_addr;
    @@ -763,52 +909,63 @@ snmp_netIpFn(variable_list * Var, snint * ErrP)
         debug(49, 5) ("snmp_netIpFn: Processing request:\n");
         snmpDebugOid(5, Var->name, Var->name_length);
         *ErrP = SNMP_ERR_NOERROR;
    +
         switch (Var->name[LEN_SQ_NET + 1]) {
    +
         case IP_ENT:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    memInUse(MEM_IPCACHE_ENTRY),
    -	    SMI_GAUGE32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      memInUse(MEM_IPCACHE_ENTRY),
    +                                      SMI_GAUGE32);
    +        break;
    +
         case IP_REQ:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    IpcacheStats.requests,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      IpcacheStats.requests,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case IP_HITS:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    IpcacheStats.hits,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      IpcacheStats.hits,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case IP_PENDHIT:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    0,
    -	    SMI_GAUGE32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      0,
    +                                      SMI_GAUGE32);
    +        break;
    +
         case IP_NEGHIT:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    IpcacheStats.negative_hits,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      IpcacheStats.negative_hits,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case IP_MISS:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    IpcacheStats.misses,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      IpcacheStats.misses,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case IP_GHBN:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    0, /* deprecated */
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      0, /* deprecated */
    +                                      SMI_COUNTER32);
    +        break;
    +
         case IP_LOC:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    0, /* deprecated */
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      0, /* deprecated */
    +                                      SMI_COUNTER32);
    +        break;
    +
         default:
    -	*ErrP = SNMP_ERR_NOSUCHNAME;
    -	snmp_var_free(Answer);
    -	return (NULL);
    +        *ErrP = SNMP_ERR_NOSUCHNAME;
    +        snmp_var_free(Answer);
    +        return (NULL);
         }
    +
         return Answer;
     }
     
    diff --git a/src/leakfinder.cc b/src/leakfinder.cc
    index b855cf85ff..0afc3c6998 100644
    --- a/src/leakfinder.cc
    +++ b/src/leakfinder.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: leakfinder.cc,v 1.8 2003/01/23 00:37:23 robertc Exp $
    + * $Id: leakfinder.cc,v 1.9 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 45    Callback Data Registry
      * AUTHOR: Duane Wessels
    @@ -44,14 +44,18 @@ static hash_table *htable = NULL;
     
     static int leakCount = 0;
     
    -typedef struct _ptr {
    +typedef struct _ptr
    +{
         hash_link hash;		/* must be first */
         void *key;
    +
         struct _ptr *next;
         const char *file;
         int line;
         time_t when;
    -} ptr;
    +}
    +
    +ptr;
     
     static HASHCMP ptr_cmp;
     static HASHHASH ptr_hash;
    @@ -65,8 +69,8 @@ leakInit(void)
         debug(45, 3) ("ptrInit\n");
         htable = hash_create(ptr_cmp, 1 << 8, ptr_hash);
         cachemgrRegister("leaks",
    -	"Memory Leak Tracking",
    -	ptrDump, 0, 1);
    +                     "Memory Leak Tracking",
    +                     ptrDump, 0, 1);
     }
     
     void *
    @@ -133,9 +137,10 @@ ptrDump(StoreEntry * sentry)
         ptr *c;
         storeAppendPrintf(sentry, "Tracking %d pointers\n", leakCount);
         hash_first(htable);
    +
         while ((hptr = (hash_link *)hash_next(htable))) {
    -	c = (ptr *) hptr;
    -	storeAppendPrintf(sentry, "%20p last used %9d seconds ago by %s:%d\n",
    -	    c->key, (int)(squid_curtime - c->when), c->file, c->line);
    +        c = (ptr *) hptr;
    +        storeAppendPrintf(sentry, "%20p last used %9d seconds ago by %s:%d\n",
    +                          c->key, (int)(squid_curtime - c->when), c->file, c->line);
         }
     }
    diff --git a/src/logfile.cc b/src/logfile.cc
    index 0b62277edd..05adda25bb 100644
    --- a/src/logfile.cc
    +++ b/src/logfile.cc
    @@ -1,5 +1,5 @@
     /*
    - * $Id: logfile.cc,v 1.14 2003/01/27 08:08:04 hno Exp $
    + * $Id: logfile.cc,v 1.15 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 50    Log file handling
      * AUTHOR: Duane Wessels
    @@ -44,30 +44,36 @@ logfileOpen(const char *path, size_t bufsz, int fatal_flag)
         int fd;
         Logfile *lf;
         fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT);
    +
         if (DISK_ERROR == fd) {
    -	if (ENOENT == errno && fatal_flag) {
    -	    fatalf("Cannot open '%s' because\n"
    -		"\tthe parent directory does not exist.\n"
    -		"\tPlease create the directory.\n", path);
    -	} else if (EACCES == errno && fatal_flag) {
    -	    fatalf("Cannot open '%s' for writing.\n"
    -		"\tThe parent directory must be writeable by the\n"
    -		"\tuser '%s', which is the cache_effective_user\n"
    -		"\tset in squid.conf.", path, Config.effectiveUser);
    -	} else {
    -	    debug(50, 1) ("logfileOpen: %s: %s\n", path, xstrerror());
    -	    return NULL;
    -	}
    +        if (ENOENT == errno && fatal_flag) {
    +            fatalf("Cannot open '%s' because\n"
    +                   "\tthe parent directory does not exist.\n"
    +                   "\tPlease create the directory.\n", path);
    +        } else if (EACCES == errno && fatal_flag) {
    +            fatalf("Cannot open '%s' for writing.\n"
    +                   "\tThe parent directory must be writeable by the\n"
    +                   "\tuser '%s', which is the cache_effective_user\n"
    +                   "\tset in squid.conf.", path, Config.effectiveUser);
    +        } else {
    +            debug(50, 1) ("logfileOpen: %s: %s\n", path, xstrerror());
    +            return NULL;
    +        }
         }
    +
         lf = static_cast(xcalloc(1, sizeof(*lf)));
         lf->fd = fd;
    +
         if (fatal_flag)
    -	lf->flags.fatal = 1;
    +        lf->flags.fatal = 1;
    +
         xstrncpy(lf->path, path, MAXPATHLEN);
    +
         if (bufsz > 0) {
    -	lf->buf = (char *) xmalloc(bufsz);
    -	lf->bufsz = bufsz;
    +        lf->buf = (char *) xmalloc(bufsz);
    +        lf->bufsz = bufsz;
         }
    +
         return lf;
     }
     
    @@ -76,8 +82,10 @@ logfileClose(Logfile * lf)
     {
         logfileFlush(lf);
         file_close(lf->fd);
    +
         if (lf->buf)
    -	xfree(lf->buf);
    +        xfree(lf->buf);
    +
         xfree(lf);
     }
     
    @@ -85,37 +93,48 @@ void
     logfileRotate(Logfile * lf)
     {
     #ifdef S_ISREG
    +
         struct stat sb;
     #endif
    +
         int i;
         char from[MAXPATHLEN];
         char to[MAXPATHLEN];
         assert(lf->path);
     #ifdef S_ISREG
    +
         if (stat(lf->path, &sb) == 0)
    -	if (S_ISREG(sb.st_mode) == 0)
    -	    return;
    +        if (S_ISREG(sb.st_mode) == 0)
    +            return;
    +
     #endif
    +
         debug(0, 1) ("logfileRotate: %s\n", lf->path);
    +
         /* Rotate numbers 0 through N up one */
         for (i = Config.Log.rotateNumber; i > 1;) {
    -	i--;
    -	snprintf(from, MAXPATHLEN, "%s.%d", lf->path, i - 1);
    -	snprintf(to, MAXPATHLEN, "%s.%d", lf->path, i);
    -	xrename(from, to);
    +        i--;
    +        snprintf(from, MAXPATHLEN, "%s.%d", lf->path, i - 1);
    +        snprintf(to, MAXPATHLEN, "%s.%d", lf->path, i);
    +        xrename(from, to);
         }
    +
         /* Rotate the current log to .0 */
         logfileFlush(lf);
    +
         file_close(lf->fd);		/* always close */
    +
         if (Config.Log.rotateNumber > 0) {
    -	snprintf(to, MAXPATHLEN, "%s.%d", lf->path, 0);
    -	xrename(lf->path, to);
    +        snprintf(to, MAXPATHLEN, "%s.%d", lf->path, 0);
    +        xrename(lf->path, to);
         }
    +
         /* Reopen the log.  It may have been renamed "manually" */
         lf->fd = file_open(lf->path, O_WRONLY | O_CREAT | O_TEXT);
    +
         if (DISK_ERROR == lf->fd && lf->flags.fatal) {
    -	debug(50, 1) ("logfileRotate: %s: %s\n", lf->path, xstrerror());
    -	fatalf("Cannot open %s: %s", lf->path, xstrerror());
    +        debug(50, 1) ("logfileRotate: %s: %s\n", lf->path, xstrerror());
    +        fatalf("Cannot open %s: %s", lf->path, xstrerror());
         }
     }
     
    @@ -123,21 +142,27 @@ void
     logfileWrite(Logfile * lf, void *buf, size_t len)
     {
         if (0 == lf->bufsz) {
    -	/* buffering disabled */
    -	logfileWriteWrapper(lf, buf, len);
    -	return;
    +        /* buffering disabled */
    +        logfileWriteWrapper(lf, buf, len);
    +        return;
         }
    +
         if (lf->offset > 0 && lf->offset + len > lf->bufsz)
    -	logfileFlush(lf);
    +        logfileFlush(lf);
    +
         if (len > lf->bufsz) {
    -	/* too big to fit in buffer */
    -	logfileWriteWrapper(lf, buf, len);
    -	return;
    +        /* too big to fit in buffer */
    +        logfileWriteWrapper(lf, buf, len);
    +        return;
         }
    +
         /* buffer it */
         xmemcpy(lf->buf + lf->offset, buf, len);
    +
         lf->offset += len;
    +
         assert (lf->offset >= 0);
    +
         assert((size_t)lf->offset <= lf->bufsz);
     }
     
    @@ -146,27 +171,33 @@ void
     logfilePrintf(Logfile * lf, const char *fmt,...)
     #else
     logfilePrintf(va_alist)
    -     va_dcl
    +va_dcl
     #endif
     {
         va_list args;
         char buf[8192];
         int s;
     #if STDC_HEADERS
    +
         va_start(args, fmt);
     #else
    +
         Logfile *lf;
         const char *fmt;
         va_start(args);
         lf = va_arg(args, Logfile *);
         fmt = va_arg(args, char *);
     #endif
    +
         s = vsnprintf(buf, 8192, fmt, args);
    +
         if (s > 8192) {
    -	s = 8192;
    -	if (fmt[strlen(fmt) - 1] == '\n')
    -	    buf[8191] = '\n';
    +        s = 8192;
    +
    +        if (fmt[strlen(fmt) - 1] == '\n')
    +            buf[8191] = '\n';
         }
    +
         logfileWrite(lf, buf, (size_t) s);
         va_end(args);
     }
    @@ -175,8 +206,10 @@ void
     logfileFlush(Logfile * lf)
     {
         if (0 == lf->offset)
    -	return;
    +        return;
    +
         logfileWriteWrapper(lf, lf->buf, (size_t) lf->offset);
    +
         lf->offset = 0;
     }
     
    @@ -190,9 +223,12 @@ logfileWriteWrapper(Logfile * lf, const void *buf, size_t len)
         size_t s;
         s = FD_WRITE_METHOD(lf->fd, (char const *)buf, len);
         fd_bytes(lf->fd, s, FD_WRITE);
    +
         if (s == len)
    -	return;
    +        return;
    +
         if (!lf->flags.fatal)
    -	return;
    +        return;
    +
         fatalf("logfileWrite: %s: %s\n", lf->path, xstrerror());
     }
    diff --git a/src/main.cc b/src/main.cc
    index 38feda3a7f..63e167d6c2 100644
    --- a/src/main.cc
    +++ b/src/main.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: main.cc,v 1.367 2003/02/21 19:53:01 hno Exp $
    + * $Id: main.cc,v 1.368 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 1     Startup and Main Loop
      * AUTHOR: Harvest Derived
    @@ -84,29 +84,29 @@ static void
     usage(void)
     {
         fprintf(stderr,
    -	"Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n"
    -	"       -a port   Specify HTTP port number (default: %d).\n"
    -	"       -d level  Write debugging to stderr also.\n"
    -	"       -f file   Use given config-file instead of\n"
    -	"                 %s\n"
    -	"       -h        Print help message.\n"
    -	"       -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
    -	"                 Parse configuration file, then send signal to \n"
    -	"                 running copy (except -k parse) and exit.\n"
    -	"       -s        Enable logging to syslog.\n"
    -	"       -u port   Specify ICP port number (default: %d), disable with 0.\n"
    -	"       -v        Print version.\n"
    -	"       -z        Create swap directories\n"
    -	"       -C        Do not catch fatal signals.\n"
    -	"       -D        Disable initial DNS tests.\n"
    -	"       -F        Don't serve any requests until store is rebuilt.\n"
    -	"       -N        No daemon mode.\n"
    -	"       -R        Do not set REUSEADDR on port.\n"
    -	"       -S        Double-check swap during rebuild.\n"
    -	"       -V        Virtual host httpd-accelerator.\n"
    -	"       -X        Force full debugging.\n"
    -	"       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
    -	appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
    +            "Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n"
    +            "       -a port   Specify HTTP port number (default: %d).\n"
    +            "       -d level  Write debugging to stderr also.\n"
    +            "       -f file   Use given config-file instead of\n"
    +            "                 %s\n"
    +            "       -h        Print help message.\n"
    +            "       -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
    +            "                 Parse configuration file, then send signal to \n"
    +            "                 running copy (except -k parse) and exit.\n"
    +            "       -s        Enable logging to syslog.\n"
    +            "       -u port   Specify ICP port number (default: %d), disable with 0.\n"
    +            "       -v        Print version.\n"
    +            "       -z        Create swap directories\n"
    +            "       -C        Do not catch fatal signals.\n"
    +            "       -D        Disable initial DNS tests.\n"
    +            "       -F        Don't serve any requests until store is rebuilt.\n"
    +            "       -N        No daemon mode.\n"
    +            "       -R        Do not set REUSEADDR on port.\n"
    +            "       -S        Double-check swap during rebuild.\n"
    +            "       -V        Virtual host httpd-accelerator.\n"
    +            "       -X        Force full debugging.\n"
    +            "       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
    +            appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
         exit(1);
     }
     
    @@ -117,127 +117,185 @@ mainParseOptions(int argc, char *argv[])
         int c;
     
         while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
    -	switch (c) {
    -	case 'C':
    -	    opt_catch_signals = 0;
    -	    break;
    -	case 'D':
    -	    opt_dns_tests = 0;
    -	    break;
    -	case 'F':
    -	    opt_foreground_rebuild = 1;
    -	    break;
    -	case 'N':
    -	    opt_no_daemon = 1;
    -	    break;
    -	case 'R':
    -	    opt_reuseaddr = 0;
    -	    break;
    -	case 'S':
    -	    opt_store_doublecheck = 1;
    -	    break;
    -	case 'V':
    -	    if (Config.Sockaddr.http)
    -		Config.Sockaddr.http->vhost = 1;
    +        switch (c) {
    +
    +        case 'C':
    +            opt_catch_signals = 0;
    +            break;
    +
    +        case 'D':
    +            opt_dns_tests = 0;
    +            break;
    +
    +        case 'F':
    +            opt_foreground_rebuild = 1;
    +            break;
    +
    +        case 'N':
    +            opt_no_daemon = 1;
    +            break;
    +
    +        case 'R':
    +            opt_reuseaddr = 0;
    +            break;
    +
    +        case 'S':
    +            opt_store_doublecheck = 1;
    +            break;
    +
    +        case 'V':
    +
    +            if (Config.Sockaddr.http)
    +                Config.Sockaddr.http->vhost = 1;
    +
     #if USE_SSL
    -	    else if (Config.Sockaddr.https)
    -		Config.Sockaddr.https->http.vhost = 1;
    -#endif
    -	    else
    -		fatal("No http_port specified\n");
    -	    break;
    -	case 'X':
    -	    /* force full debugging */
    -	    sigusr2_handle(SIGUSR2);
    -	    break;
    -	case 'Y':
    -	    opt_reload_hit_only = 1;
    -	    break;
    -	case 'a':
    -	    add_http_port(optarg);
    -	    break;
    -	case 'd':
    -	    opt_debug_stderr = atoi(optarg);
    -	    break;
    -	case 'f':
    -	    xfree(ConfigFile);
    -	    ConfigFile = xstrdup(optarg);
    -	    break;
    -	case 'h':
    -	    usage();
    -	    break;
    -	case 'k':
    -	    if ((int) strlen(optarg) < 1)
    -		usage();
    -	    if (!strncmp(optarg, "reconfigure", strlen(optarg)))
    -		opt_send_signal = SIGHUP;
    -	    else if (!strncmp(optarg, "rotate", strlen(optarg)))
    +
    +            else if (Config.Sockaddr.https)
    +                Config.Sockaddr.https->http.vhost = 1;
    +
    +#endif
    +
    +            else
    +                fatal("No http_port specified\n");
    +
    +            break;
    +
    +        case 'X':
    +            /* force full debugging */
    +            sigusr2_handle(SIGUSR2);
    +
    +            break;
    +
    +        case 'Y':
    +            opt_reload_hit_only = 1;
    +
    +            break;
    +
    +        case 'a':
    +            add_http_port(optarg);
    +
    +            break;
    +
    +        case 'd':
    +            opt_debug_stderr = atoi(optarg);
    +
    +            break;
    +
    +        case 'f':
    +            xfree(ConfigFile);
    +
    +            ConfigFile = xstrdup(optarg);
    +
    +            break;
    +
    +        case 'h':
    +            usage();
    +
    +            break;
    +
    +        case 'k':
    +            if ((int) strlen(optarg) < 1)
    +                usage();
    +
    +            if (!strncmp(optarg, "reconfigure", strlen(optarg)))
    +                opt_send_signal = SIGHUP;
    +            else if (!strncmp(optarg, "rotate", strlen(optarg)))
     #ifdef _SQUID_LINUX_THREADS_
    -		opt_send_signal = SIGQUIT;
    +
    +                opt_send_signal = SIGQUIT;
    +
     #else
    -		opt_send_signal = SIGUSR1;
    +
    +                opt_send_signal = SIGUSR1;
    +
     #endif
    -	    else if (!strncmp(optarg, "debug", strlen(optarg)))
    +
    +            else if (!strncmp(optarg, "debug", strlen(optarg)))
     #ifdef _SQUID_LINUX_THREADS_
    -		opt_send_signal = SIGTRAP;
    +
    +                opt_send_signal = SIGTRAP;
    +
     #else
    -		opt_send_signal = SIGUSR2;
    -#endif
    -	    else if (!strncmp(optarg, "shutdown", strlen(optarg)))
    -		opt_send_signal = SIGTERM;
    -	    else if (!strncmp(optarg, "interrupt", strlen(optarg)))
    -		opt_send_signal = SIGINT;
    -	    else if (!strncmp(optarg, "kill", strlen(optarg)))
    -		opt_send_signal = SIGKILL;
    -	    else if (!strncmp(optarg, "check", strlen(optarg)))
    -		opt_send_signal = 0;	/* SIGNULL */
    -	    else if (!strncmp(optarg, "parse", strlen(optarg)))
    -		opt_parse_cfg_only = 1;		/* parse cfg file only */
    -	    else
    -		usage();
    -	    break;
    -	case 'm':
    -	    if (optarg) {
    +
    +                opt_send_signal = SIGUSR2;
    +
    +#endif
    +
    +            else if (!strncmp(optarg, "shutdown", strlen(optarg)))
    +                opt_send_signal = SIGTERM;
    +            else if (!strncmp(optarg, "interrupt", strlen(optarg)))
    +                opt_send_signal = SIGINT;
    +            else if (!strncmp(optarg, "kill", strlen(optarg)))
    +                opt_send_signal = SIGKILL;
    +            else if (!strncmp(optarg, "check", strlen(optarg)))
    +                opt_send_signal = 0;	/* SIGNULL */
    +            else if (!strncmp(optarg, "parse", strlen(optarg)))
    +                opt_parse_cfg_only = 1;		/* parse cfg file only */
    +            else
    +                usage();
    +
    +            break;
    +
    +        case 'm':
    +            if (optarg) {
     #if MALLOC_DBG
    -		malloc_debug_level = atoi(optarg);
    -		/* NOTREACHED */
    -		break;
    +                malloc_debug_level = atoi(optarg);
    +                /* NOTREACHED */
    +                break;
     #else
    -		fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
    -		/* NOTREACHED */
    +
    +                fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
    +                /* NOTREACHED */
     #endif
    -	    } else {
    +
    +            } else {
     #if XMALLOC_TRACE
    -		xmalloc_trace = !xmalloc_trace;
    +                xmalloc_trace = !xmalloc_trace;
     #else
    -		fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
    +
    +                fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
     #endif
    -	    }
    -	case 's':
    +
    +            }
    +
    +        case 's':
     #if HAVE_SYSLOG
    -	    opt_syslog_enable = 1;
    -	    break;
    +
    +            opt_syslog_enable = 1;
    +            break;
     #else
    -	    fatal("Logging to syslog not available on this platform");
    -	    /* NOTREACHED */
    -#endif
    -	case 'u':
    -	    icpPortNumOverride = atoi(optarg);
    -	    if (icpPortNumOverride < 0)
    -		icpPortNumOverride = 0;
    -	    break;
    -	case 'v':
    -	    printf("Squid Cache: Version %s\nconfigure options: %s\n", version_string, SQUID_CONFIGURE_OPTIONS);
    -	    exit(0);
    -	    /* NOTREACHED */
    -	case 'z':
    -	    opt_create_swap_dirs = 1;
    -	    break;
    -	case '?':
    -	default:
    -	    usage();
    -	    break;
    -	}
    +
    +            fatal("Logging to syslog not available on this platform");
    +            /* NOTREACHED */
    +#endif
    +
    +        case 'u':
    +            icpPortNumOverride = atoi(optarg);
    +
    +            if (icpPortNumOverride < 0)
    +                icpPortNumOverride = 0;
    +
    +            break;
    +
    +        case 'v':
    +            printf("Squid Cache: Version %s\nconfigure options: %s\n", version_string, SQUID_CONFIGURE_OPTIONS);
    +
    +            exit(0);
    +
    +            /* NOTREACHED */
    +
    +        case 'z':
    +            opt_create_swap_dirs = 1;
    +
    +            break;
    +
    +        case '?':
    +
    +        default:
    +            usage();
    +
    +            break;
    +        }
         }
     }
     
    @@ -247,6 +305,7 @@ rotate_logs(int sig)
     {
         do_rotate = 1;
     #if !HAVE_SIGACTION
    +
         signal(sig, rotate_logs);
     #endif
     }
    @@ -257,6 +316,7 @@ reconfigure(int sig)
     {
         do_reconfigure = 1;
     #if !HAVE_SIGACTION
    +
         signal(sig, reconfigure);
     #endif
     }
    @@ -266,15 +326,20 @@ shut_down(int sig)
     {
         do_shutdown = sig == SIGINT ? -1 : 1;
     #ifdef KILL_PARENT_OPT
    +
         if (getppid() > 1) {
    -	debug(1, 1) ("Killing RunCache, pid %d\n", getppid());
    -	if (kill(getppid(), sig) < 0)
    -	    debug(1, 1) ("kill %d: %s\n", getppid(), xstrerror());
    +        debug(1, 1) ("Killing RunCache, pid %d\n", getppid());
    +
    +        if (kill(getppid(), sig) < 0)
    +            debug(1, 1) ("kill %d: %s\n", getppid(), xstrerror());
         }
    +
     #endif
     #if SA_RESETHAND == 0
         signal(SIGTERM, SIG_DFL);
    +
         signal(SIGINT, SIG_DFL);
    +
     #endif
     }
     
    @@ -284,20 +349,25 @@ serverConnectionsOpen(void)
         clientOpenListenSockets();
         icpConnectionsOpen();
     #if USE_HTCP
    +
         htcpInit();
     #endif
     #ifdef SQUID_SNMP
    +
         snmpConnectionOpen();
     #endif
     #if USE_WCCP
    +
         wccpConnectionOpen();
     #endif
    +
         clientdbInit();
         icmpOpen();
         netdbInit();
         asnInit();
         peerSelectInit();
     #if USE_CARP
    +
         carpInit();
     #endif
     }
    @@ -309,15 +379,20 @@ serverConnectionsClose(void)
         clientHttpConnectionsClose();
         icpConnectionShutdown();
     #if USE_HTCP
    +
         htcpSocketShutdown();
     #endif
    +
         icmpClose();
     #ifdef SQUID_SNMP
    +
         snmpConnectionShutdown();
     #endif
     #if USE_WCCP
    +
         wccpConnectionShutdown();
     #endif
    +
         asnFreeMemory();
     }
     
    @@ -330,19 +405,25 @@ mainReconfigure(void)
         serverConnectionsClose();
         icpConnectionClose();
     #if USE_HTCP
    +
         htcpSocketClose();
     #endif
     #ifdef SQUID_SNMP
    +
         snmpConnectionClose();
     #endif
     #if USE_WCCP
    +
         wccpConnectionClose();
     #endif
     #if USE_DNSSERVERS
    +
         dnsShutdown();
     #else
    +
         idnsShutdown();
     #endif
    +
         redirectShutdown();
         authenticateShutdown();
         externalAclShutdown();
    @@ -358,16 +439,21 @@ mainReconfigure(void)
         parseEtcHosts();
         errorInitialize();		/* reload error pages */
     #if USE_DNSSERVERS
    +
         dnsInit();
     #else
    +
         idnsInit();
     #endif
    +
         redirectInit();
         authenticateInit(&Config.authConfiguration);
         externalAclInit();
     #if USE_WCCP
    +
         wccpInit();
     #endif
    +
         serverConnectionsOpen();
         neighbors_init();
         storeDirOpenSwapLogs();
    @@ -382,8 +468,10 @@ mainRotate(void)
     {
         icmpClose();
     #if USE_DNSSERVERS
    +
         dnsShutdown();
     #endif
    +
         redirectShutdown();
         authenticateShutdown();
         externalAclShutdown();
    @@ -394,12 +482,16 @@ mainRotate(void)
         useragentRotateLog();	/* useragent.log */
         refererRotateLog();		/* referer.log */
     #if WIP_FWD_LOG
    +
         fwdLogRotate();
     #endif
    +
         icmpOpen();
     #if USE_DNSSERVERS
    +
         dnsInit();
     #endif
    +
         redirectInit();
         authenticateInit(&Config.authConfiguration);
         externalAclInit();
    @@ -410,14 +502,16 @@ setEffectiveUser(void)
     {
         leave_suid();		/* Run as non privilegied user */
     #ifdef _SQUID_OS2_
    +
         return;
     #endif
    +
         if (geteuid() == 0) {
    -	debug(0, 0) ("Squid is not safe to run as root!  If you must\n");
    -	debug(0, 0) ("start Squid as root, then you must configure\n");
    -	debug(0, 0) ("it to run as a non-priveledged user with the\n");
    -	debug(0, 0) ("'cache_effective_user' option in the config file.\n");
    -	fatal("Don't run Squid as root, set 'cache_effective_user'!");
    +        debug(0, 0) ("Squid is not safe to run as root!  If you must\n");
    +        debug(0, 0) ("start Squid as root, then you must configure\n");
    +        debug(0, 0) ("it to run as a non-priveledged user with the\n");
    +        debug(0, 0) ("'cache_effective_user' option in the config file.\n");
    +        fatal("Don't run Squid as root, set 'cache_effective_user'!");
         }
     }
     
    @@ -425,21 +519,23 @@ static void
     mainSetCwd(void)
     {
         char pathbuf[MAXPATHLEN];
    +
         if (Config.coredump_dir) {
    -	if (0 == strcmp("none", Config.coredump_dir)) {
    -	    (void) 0;
    -	} else if (chdir(Config.coredump_dir) == 0) {
    -	    debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
    -	    return;
    -	} else {
    -	    debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
    -	}
    +        if (0 == strcmp("none", Config.coredump_dir)) {
    +            (void) 0;
    +        } else if (chdir(Config.coredump_dir) == 0) {
    +            debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
    +            return;
    +        } else {
    +            debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
    +        }
         }
    +
         /* If we don't have coredump_dir or couldn't cd there, report current dir */
         if (getcwd(pathbuf, MAXPATHLEN)) {
    -	debug(0, 1) ("Current Directory is %s\n", pathbuf);
    +        debug(0, 1) ("Current Directory is %s\n", pathbuf);
         } else {
    -	debug(50, 0) ("WARNING: Can't find current directory, getcwd: %s\n", xstrerror());
    +        debug(50, 0) ("WARNING: Can't find current directory, getcwd: %s\n", xstrerror());
         }
     }
     
    @@ -451,113 +547,176 @@ static void
     mainInitialize(void)
     {
         /* chroot if configured to run inside chroot */
    +
         if (Config.chroot_dir && chroot(Config.chroot_dir)) {
    -	fatal("failed to chroot");
    +        fatal("failed to chroot");
         }
    +
         if (opt_catch_signals) {
    -	squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
    -	squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
    +        squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
    +        squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
         }
    +
         squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
         squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
     
         setEffectiveUser();
    +
         if (icpPortNumOverride != 1)
    -	Config.Port.icp = (u_short) icpPortNumOverride;
    +        Config.Port.icp = (u_short) icpPortNumOverride;
     
         _db_init(Config.Log.log, Config.debugOptions);
    +
         fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
    +
     #if MEM_GEN_TRACE
    +
         log_trace_init("/tmp/squid.alloc");
    +
     #endif
    +
         debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
    -	version_string,
    -	CONFIG_HOST_TYPE);
    +                 version_string,
    +                 CONFIG_HOST_TYPE);
    +
         debug(1, 1) ("Process ID %d\n", (int) getpid());
    +
         debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
     
         if (!configured_once)
    -	disk_init();		/* disk_init must go before ipcache_init() */
    +        disk_init();		/* disk_init must go before ipcache_init() */
    +
         ipcache_init();
    +
         fqdncache_init();
    +
         parseEtcHosts();
    +
     #if USE_DNSSERVERS
    +
         dnsInit();
    +
     #else
    +
         idnsInit();
    +
     #endif
    +
         redirectInit();
    +
         authenticateInit(&Config.authConfiguration);
    +
         externalAclInit();
    +
         useragentOpenLog();
    +
         refererOpenLog();
    +
         httpHeaderInitModule();	/* must go before any header processing (e.g. the one in errorInitialize) */
    +
         httpReplyInitModule();	/* must go before accepting replies */
    +
         errorInitialize();
    +
         accessLogInit();
    +
     #if USE_IDENT
    +
         identInit();
    +
     #endif
     #ifdef SQUID_SNMP
    +
         snmpInit();
    +
     #endif
     #if MALLOC_DBG
    +
         malloc_debug(0, malloc_debug_level);
    +
     #endif
     
         if (!configured_once) {
     #if USE_UNLINKD
    -	unlinkdInit();
    -#endif
    -	urlInitialize();
    -	cachemgrInit();
    -	statInit();
    -	storeInit();
    -	mainSetCwd();
    -	/* after this point we want to see the mallinfo() output */
    -	do_mallinfo = 1;
    -	mimeInit(Config.mimeTablePathname);
    -	pconnInit();
    -	refreshInit();
    +        unlinkdInit();
    +#endif
    +
    +        urlInitialize();
    +        cachemgrInit();
    +        statInit();
    +        storeInit();
    +        mainSetCwd();
    +        /* after this point we want to see the mallinfo() output */
    +        do_mallinfo = 1;
    +        mimeInit(Config.mimeTablePathname);
    +        pconnInit();
    +        refreshInit();
     #if DELAY_POOLS
    -	DelayPools::Init();
    +
    +        DelayPools::Init();
     #endif
    -	fwdInit();
    +
    +        fwdInit();
         }
    +
     #if USE_WCCP
         wccpInit();
    +
     #endif
    +
         serverConnectionsOpen();
    +
         neighbors_init();
    +
         if (Config.chroot_dir)
    -	no_suid();
    +        no_suid();
    +
         if (!configured_once)
    -	writePidFile();		/* write PID file */
    +        writePidFile();		/* write PID file */
     
     #ifdef _SQUID_LINUX_THREADS_
    +
         squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
    +
         squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
    +
     #else
    +
         squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
    +
         squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
    +
     #endif
    +
         squid_signal(SIGHUP, reconfigure, SA_RESTART);
    +
         squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
    +
         squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
    +
         memCheckInit();
    +
         debug(1, 1) ("Ready to serve requests.\n");
    +
         if (!configured_once) {
    -	eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1);
    -	if (Config.onoff.announce)
    -	    eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
    -	eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
    -	eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
    +        eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1);
    +
    +        if (Config.onoff.announce)
    +            eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
    +
    +        eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
    +
    +        eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
    +
     #if USE_XPROF_STATS
    -	eventAdd("cpuProfiling", xprof_event, NULL, 1.0, 1);
    +
    +        eventAdd("cpuProfiling", xprof_event, NULL, 1.0, 1);
    +
     #endif
    -	  
    -	eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools, NULL, 15.0, 1);
    +
    +        eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools, NULL, 15.0, 1);
         }
    +
         configured_once = 1;
     }
     
    @@ -568,20 +727,25 @@ main(int argc, char **argv)
         int n;			/* # of GC'd objects */
         mode_t oldmask;
     #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_)
    +
         int WIN32_init_err;
     #endif
     
     #if HAVE_SBRK
    +
         sbrk_start = sbrk(0);
     #endif
     
         debug_log = stderr;
    +
         if (FD_SETSIZE < Squid_MaxFD)
    -	Squid_MaxFD = FD_SETSIZE;
    +        Squid_MaxFD = FD_SETSIZE;
     
     #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_)
    +
         if ((WIN32_init_err = WIN32_Subsystem_Init()))
    -	return WIN32_init_err;
    +        return WIN32_init_err;
    +
     #endif
     
         /* call mallopt() before anything else */
    @@ -589,14 +753,17 @@ main(int argc, char **argv)
     #ifdef M_GRAIN
         /* Round up all sizes to a multiple of this */
         mallopt(M_GRAIN, 16);
    +
     #endif
     #ifdef M_MXFAST
         /* biggest size that is considered a small block */
         mallopt(M_MXFAST, 256);
    +
     #endif
     #ifdef M_NBLKS
         /* allocate this many small blocks at once */
         mallopt(M_NLBLKS, 32);
    +
     #endif
     #endif /* HAVE_MALLOPT */
     
    @@ -607,19 +774,28 @@ main(int argc, char **argv)
          * umask value without setting it.
          */
         oldmask = umask(S_IRWXO);
    +
         if (oldmask)
    -	umask(oldmask);
    +        umask(oldmask);
     
         memset(&local_addr, '\0', sizeof(struct in_addr));
    +
         safe_inet_addr(localhost, &local_addr);
    +
         memset(&any_addr, '\0', sizeof(struct in_addr));
    +
         safe_inet_addr("0.0.0.0", &any_addr);
    +
         memset(&no_addr, '\0', sizeof(struct in_addr));
    +
         safe_inet_addr("255.255.255.255", &no_addr);
    +
         squid_srandom(time(NULL));
     
         getCurrentTime();
    +
         squid_start = current_time;
    +
         failure_notify = fatal_dump;
     
         mainParseOptions(argc, argv);
    @@ -627,127 +803,172 @@ main(int argc, char **argv)
         /* parse configuration file
          * note: in "normal" case this used to be called from mainInitialize() */
         {
    -	int parse_err;
    -	if (!ConfigFile)
    -	    ConfigFile = xstrdup(DefaultConfigFile);
    -	assert(!configured_once);
    +        int parse_err;
    +
    +        if (!ConfigFile)
    +            ConfigFile = xstrdup(DefaultConfigFile);
    +
    +        assert(!configured_once);
    +
     #if USE_LEAKFINDER
    -	leakInit();
    +
    +        leakInit();
    +
     #endif
    -	Mem::Init();
    -	cbdataInit();
    -	eventInit();		/* eventInit() is required for config parsing */
    -	storeFsInit();		/* required for config parsing */
    -	authenticateSchemeInit();	/* required for config parsign */
    -	parse_err = parseConfigFile(ConfigFile);
     
    -	if (opt_parse_cfg_only)
    -	    return parse_err;
    +        Mem::Init();
    +
    +        cbdataInit();
    +
    +        eventInit();		/* eventInit() is required for config parsing */
    +
    +        storeFsInit();		/* required for config parsing */
    +
    +        authenticateSchemeInit();	/* required for config parsign */
    +
    +        parse_err = parseConfigFile(ConfigFile);
    +
    +        if (opt_parse_cfg_only)
    +            return parse_err;
         }
         if (-1 == opt_send_signal)
    -	if (checkRunningPid())
    -	    exit(1);
    +        if (checkRunningPid())
    +            exit(1);
     
     #if TEST_ACCESS
    +
         comm_init();
    +
         comm_select_init();
    +
         mainInitialize();
    +
         test_access();
    +
         return 0;
    +
     #endif
     
         /* send signal to running copy and exit */
         if (opt_send_signal != -1) {
    -	/* chroot if configured to run inside chroot */
    -	if (Config.chroot_dir && chroot(Config.chroot_dir)) {
    -	    fatal("failed to chroot");
    -	}
    -	sendSignal();
    -	/* NOTREACHED */
    +        /* chroot if configured to run inside chroot */
    +
    +        if (Config.chroot_dir && chroot(Config.chroot_dir)) {
    +            fatal("failed to chroot");
    +        }
    +
    +        sendSignal();
    +        /* NOTREACHED */
         }
    +
         if (opt_create_swap_dirs) {
    -	/* chroot if configured to run inside chroot */
    -	if (Config.chroot_dir && chroot(Config.chroot_dir)) {
    -	    fatal("failed to chroot");
    -	}
    -	setEffectiveUser();
    -	debug(0, 0) ("Creating Swap Directories\n");
    -	storeCreateSwapDirectories();
    -	return 0;
    +        /* chroot if configured to run inside chroot */
    +
    +        if (Config.chroot_dir && chroot(Config.chroot_dir)) {
    +            fatal("failed to chroot");
    +        }
    +
    +        setEffectiveUser();
    +        debug(0, 0) ("Creating Swap Directories\n");
    +        storeCreateSwapDirectories();
    +        return 0;
         }
    +
         if (!opt_no_daemon)
    -	watch_child(argv);
    +        watch_child(argv);
    +
         setMaxFD();
     
         if (opt_catch_signals)
    -	for (n = Squid_MaxFD; n > 2; n--)
    -	    close(n);
    +        for (n = Squid_MaxFD; n > 2; n--)
    +            close(n);
     
         /* init comm module */
         comm_init();
    +
         comm_select_init();
     
         if (opt_no_daemon) {
    -	/* we have to init fdstat here. */
    -	fd_open(0, FD_LOG, "stdin");
    -	fd_open(1, FD_LOG, "stdout");
    -	fd_open(2, FD_LOG, "stderr");
    +        /* we have to init fdstat here. */
    +        fd_open(0, FD_LOG, "stdin");
    +        fd_open(1, FD_LOG, "stdout");
    +        fd_open(2, FD_LOG, "stderr");
         }
    +
         mainInitialize();
     
         /* main loop */
    +
         for (;;) {
    -	if (do_reconfigure) {
    -	    mainReconfigure();
    -	    do_reconfigure = 0;
    -	} else if (do_rotate) {
    -	    mainRotate();
    -	    do_rotate = 0;
    -	} else if (do_shutdown) {
    -	    time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
    -	    debug(1, 1) ("Preparing for shutdown after %d requests\n",
    -		statCounter.client_http.requests);
    -	    debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
    -		(int) wait);
    -	    do_shutdown = 0;
    -	    shutting_down = 1;
    -	    serverConnectionsClose();
    +        if (do_reconfigure) {
    +            mainReconfigure();
    +            do_reconfigure = 0;
    +        } else if (do_rotate) {
    +            mainRotate();
    +            do_rotate = 0;
    +        } else if (do_shutdown) {
    +            time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
    +            debug(1, 1) ("Preparing for shutdown after %d requests\n",
    +                         statCounter.client_http.requests);
    +            debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
    +                         (int) wait);
    +            do_shutdown = 0;
    +            shutting_down = 1;
    +            serverConnectionsClose();
     #if USE_DNSSERVERS
    -	    dnsShutdown();
    +
    +            dnsShutdown();
     #else
    -	    idnsShutdown();
    +
    +            idnsShutdown();
     #endif
    -	    redirectShutdown();
    -	    externalAclShutdown();
    -	    eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
    -	}
    -	eventRun();
    +
    +            redirectShutdown();
    +            externalAclShutdown();
    +            eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
    +        }
    +
    +        eventRun();
             int loop_delay = eventNextTime();
    -	if (loop_delay < 0)
    -	    loop_delay = 0;
    +
    +        if (loop_delay < 0)
    +            loop_delay = 0;
    +
             /* Attempt any pending storedir IO */
             storeDirCallback();
    -	comm_calliocallback();
    -	switch (comm_select(loop_delay)) {
    -	case COMM_OK:
    -	    errcount = 0;	/* reset if successful */
    -	    break;
    -	case COMM_ERROR:
    -	    errcount++;
    -	    debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
    -	    if (errcount == 10)
    -		fatal_dump("Select Loop failed!");
    -	    break;
    -	case COMM_TIMEOUT:
    -	    break;
    -	case COMM_SHUTDOWN:
    -	    SquidShutdown(NULL);
    -	    break;
    -	default:
    -	    fatal_dump("MAIN: Internal error -- this should never happen.");
    -	    break;
    -	}
    +
    +        comm_calliocallback();
    +
    +        switch (comm_select(loop_delay)) {
    +
    +        case COMM_OK:
    +            errcount = 0;	/* reset if successful */
    +            break;
    +
    +        case COMM_ERROR:
    +            errcount++;
    +            debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
    +
    +            if (errcount == 10)
    +                fatal_dump("Select Loop failed!");
    +
    +            break;
    +
    +        case COMM_TIMEOUT:
    +            break;
    +
    +        case COMM_SHUTDOWN:
    +            SquidShutdown(NULL);
    +
    +            break;
    +
    +        default:
    +            fatal_dump("MAIN: Internal error -- this should never happen.");
    +
    +            break;
    +        }
         }
    +
         /* NOTREACHED */
         return 0;
     }
    @@ -758,19 +979,21 @@ sendSignal(void)
         pid_t pid;
         debug_log = stderr;
         pid = readPidFile();
    +
         if (pid > 1) {
    -	if (kill(pid, opt_send_signal) &&
    -	/* ignore permissions if just running check */
    -	    !(opt_send_signal == 0 && errno == EPERM)) {
    -	    fprintf(stderr, "%s: ERROR: Could not send ", appname);
    -	    fprintf(stderr, "signal %d to process %d: %s\n",
    -		opt_send_signal, (int) pid, xstrerror());
    -	    exit(1);
    -	}
    +        if (kill(pid, opt_send_signal) &&
    +                /* ignore permissions if just running check */
    +                !(opt_send_signal == 0 && errno == EPERM)) {
    +            fprintf(stderr, "%s: ERROR: Could not send ", appname);
    +            fprintf(stderr, "signal %d to process %d: %s\n",
    +                    opt_send_signal, (int) pid, xstrerror());
    +            exit(1);
    +        }
         } else {
    -	fprintf(stderr, "%s: ERROR: No running copy\n", appname);
    -	exit(1);
    +        fprintf(stderr, "%s: ERROR: No running copy\n", appname);
    +        exit(1);
         }
    +
         /* signal successfully sent */
         exit(0);
     }
    @@ -790,25 +1013,30 @@ mainStartScript(const char *prog)
         pid_t cpid;
         pid_t rpid;
         xstrncpy(script, prog, MAXPATHLEN);
    +
         if ((t = strrchr(script, '/'))) {
    -	*(++t) = '\0';
    -	sl = strlen(script);
    +        *(++t) = '\0';
    +        sl = strlen(script);
         }
    +
         xstrncpy(&script[sl], squid_start_script, MAXPATHLEN - sl);
    +
         if ((cpid = fork()) == 0) {
    -	/* child */
    -	execl(script, squid_start_script, 0);
    -	_exit(0);
    +        /* child */
    +        execl(script, squid_start_script, 0);
    +        _exit(0);
         } else {
    -	do {
    +        do {
     #ifdef _SQUID_NEXT_
    -	    union wait status;
    -	    rpid = wait3(&status, 0, NULL);
    +            union wait status;
    +            rpid = wait3(&status, 0, NULL);
     #else
    -	    int status;
    -	    rpid = waitpid(-1, &status, 0);
    +
    +            int status;
    +            rpid = waitpid(-1, &status, 0);
     #endif
    -	} while (rpid != cpid);
    +
    +        } while (rpid != cpid);
         }
     }
     
    @@ -818,11 +1046,15 @@ checkRunningPid(void)
         pid_t pid;
         debug_log = stderr;
         pid = readPidFile();
    +
         if (pid < 2)
    -	return 0;
    +        return 0;
    +
         if (kill(pid, 0) < 0)
    -	return 0;
    +        return 0;
    +
         debug(0, 0) ("Squid is already running!  Process ID %d\n", pid);
    +
         return 1;
     }
     
    @@ -834,28 +1066,39 @@ watch_child(char *argv[])
         time_t start;
         time_t stop;
     #ifdef _SQUID_NEXT_
    +
         union wait status;
     #else
    +
         int status;
     #endif
    +
         pid_t pid;
         int i;
         int nullfd;
    +
         if (*(argv[0]) == '(')
    -	return;
    +        return;
    +
         openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
    +
         if ((pid = fork()) < 0)
    -	syslog(LOG_ALERT, "fork failed: %s", xstrerror());
    +        syslog(LOG_ALERT, "fork failed: %s", xstrerror());
         else if (pid > 0)
    -	exit(0);
    +        exit(0);
    +
         if (setsid() < 0)
    -	syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
    +        syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
    +
         closelog();
    +
     #ifdef TIOCNOTTY
    +
         if ((i = open("/dev/tty", O_RDWR | O_TEXT)) >= 0) {
    -	ioctl(i, TIOCNOTTY, NULL);
    -	close(i);
    +        ioctl(i, TIOCNOTTY, NULL);
    +        close(i);
         }
    +
     #endif
     
     
    @@ -866,69 +1109,93 @@ watch_child(char *argv[])
          */
         /* Connect stdio to /dev/null in daemon mode */
         nullfd = open("/dev/null", O_RDWR | O_TEXT);
    +
         dup2(nullfd, 0);
    +
         if (opt_debug_stderr < 0) {
    -	dup2(nullfd, 1);
    -	dup2(nullfd, 2);
    +        dup2(nullfd, 1);
    +        dup2(nullfd, 2);
         }
    +
         /* Close all else */
         for (i = 3; i < Squid_MaxFD; i++)
    -	close(i);
    +        close(i);
    +
         for (;;) {
    -	mainStartScript(argv[0]);
    -	if ((pid = fork()) == 0) {
    -	    /* child */
    -	    openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
    -	    prog = xstrdup(argv[0]);
    -	    argv[0] = xstrdup("(squid)");
    -	    execvp(prog, argv);
    -	    syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
    -	}
    -	/* parent */
    -	openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
    -	syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
    -	time(&start);
    -	squid_signal(SIGINT, SIG_IGN, SA_RESTART);
    +        mainStartScript(argv[0]);
    +
    +        if ((pid = fork()) == 0) {
    +            /* child */
    +            openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
    +            prog = xstrdup(argv[0]);
    +            argv[0] = xstrdup("(squid)");
    +            execvp(prog, argv);
    +            syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
    +        }
    +
    +        /* parent */
    +        openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
    +
    +        syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
    +
    +        time(&start);
    +
    +        squid_signal(SIGINT, SIG_IGN, SA_RESTART);
    +
     #ifdef _SQUID_NEXT_
    -	pid = wait3(&status, 0, NULL);
    +
    +        pid = wait3(&status, 0, NULL);
    +
     #else
    -	pid = waitpid(-1, &status, 0);
    -#endif
    -	time(&stop);
    -	if (WIFEXITED(status)) {
    -	    syslog(LOG_NOTICE,
    -		"Squid Parent: child process %d exited with status %d",
    -		pid, WEXITSTATUS(status));
    -	} else if (WIFSIGNALED(status)) {
    -	    syslog(LOG_NOTICE,
    -		"Squid Parent: child process %d exited due to signal %d",
    -		pid, WTERMSIG(status));
    -	} else {
    -	    syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
    -	}
    -	if (stop - start < 10)
    -	    failcount++;
    -	else
    -	    failcount = 0;
    -	if (failcount == 5) {
    -	    syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
    -	    exit(1);
    -	}
    -	if (WIFEXITED(status))
    -	    if (WEXITSTATUS(status) == 0)
    -		exit(0);
    -	if (WIFSIGNALED(status)) {
    -	    switch (WTERMSIG(status)) {
    -	    case SIGKILL:
    -		exit(0);
    -		break;
    -	    default:
    -		break;
    -	    }
    -	}
    -	squid_signal(SIGINT, SIG_DFL, SA_RESTART);
    -	sleep(3);
    +
    +        pid = waitpid(-1, &status, 0);
    +
    +#endif
    +
    +        time(&stop);
    +
    +        if (WIFEXITED(status)) {
    +            syslog(LOG_NOTICE,
    +                   "Squid Parent: child process %d exited with status %d",
    +                   pid, WEXITSTATUS(status));
    +        } else if (WIFSIGNALED(status)) {
    +            syslog(LOG_NOTICE,
    +                   "Squid Parent: child process %d exited due to signal %d",
    +                   pid, WTERMSIG(status));
    +        } else {
    +            syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
    +        }
    +
    +        if (stop - start < 10)
    +            failcount++;
    +        else
    +            failcount = 0;
    +
    +        if (failcount == 5) {
    +            syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
    +            exit(1);
    +        }
    +
    +        if (WIFEXITED(status))
    +            if (WEXITSTATUS(status) == 0)
    +                exit(0);
    +
    +        if (WIFSIGNALED(status)) {
    +            switch (WTERMSIG(status)) {
    +
    +            case SIGKILL:
    +                exit(0);
    +                break;
    +
    +            default:
    +                break;
    +            }
    +        }
    +
    +        squid_signal(SIGINT, SIG_DFL, SA_RESTART);
    +        sleep(3);
         }
    +
         /* NOTREACHED */
     }
     
    @@ -938,23 +1205,31 @@ SquidShutdown(void *unused)
         debug(1, 1) ("Shutting down...\n");
         icpConnectionClose();
     #if USE_HTCP
    +
         htcpSocketClose();
     #endif
     #ifdef SQUID_SNMP
    +
         snmpConnectionClose();
     #endif
     #if USE_WCCP
    +
         wccpConnectionClose();
     #endif
    +
         releaseServerSockets();
         commCloseAllSockets();
     #if DELAY_POOLS
    +
         DelayPools::FreePools();
     #endif
    +
         authenticateShutdown();
     #if USE_UNLINKD
    +
         unlinkdClose();
     #endif
    +
         storeDirSync();		/* Flush pending object writes/unlinks */
         storeDirWriteCleanLogs(0);
         PrintRusage();
    @@ -965,10 +1240,13 @@ SquidShutdown(void *unused)
         useragentLogClose();
         refererCloseLog();
     #if WIP_FWD_LOG
    +
         fwdUninit();
     #endif
    +
         storeDirSync();		/* Flush log close */
     #if PURIFY || XMALLOC_TRACE
    +
         storeFsDone();
         configFreeMemory();
         storeFreeMemory();
    @@ -985,30 +1263,44 @@ SquidShutdown(void *unused)
         errorClean();
     #endif
     #if !XMALLOC_TRACE
    +
         if (opt_no_daemon) {
    -	file_close(0);
    -	file_close(1);
    -	file_close(2);
    +        file_close(0);
    +        file_close(1);
    +        file_close(2);
         }
    +
     #endif
         fdDumpOpen();
    +
         fdFreeMemory();
    +
         memClean();
    +
     #if XMALLOC_TRACE
    +
         xmalloc_find_leaks();
    +
         debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
    +
     #endif
     #if MEM_GEN_TRACE
    +
         log_trace_done();
    +
     #endif
    +
         if (Config.pidFilename && strcmp(Config.pidFilename, "none") != 0) {
    -	enter_suid();
    -	safeunlink(Config.pidFilename, 0);
    -	leave_suid();
    +        enter_suid();
    +        safeunlink(Config.pidFilename, 0);
    +        leave_suid();
         }
    +
         debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",
    -	version_string);
    +                 version_string);
    +
         if (debug_log)
    -	fclose(debug_log);
    +        fclose(debug_log);
    +
         exit(0);
     }
    diff --git a/src/mem.cc b/src/mem.cc
    index 26d299bfa3..d000a31404 100644
    --- a/src/mem.cc
    +++ b/src/mem.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: mem.cc,v 1.73 2003/02/17 07:01:36 robertc Exp $
    + * $Id: mem.cc,v 1.74 2003/02/21 22:50:09 robertc Exp $
      *
      * DEBUG: section 13    High Level Memory Pool Management
      * AUTHOR: Harvest Derived
    @@ -50,24 +50,32 @@ static double xm_deltat = 0;
     
     /* string pools */
     #define mem_str_pool_count 3
    -static const struct {
    +
    +static const struct
    +{
         const char *name;
         size_t obj_size;
    -} StrPoolsAttrs[mem_str_pool_count] = {
    -
    -    {
    -	"Short Strings", 36,
    -    },				/* to fit rfc1123 and similar */
    -    {
    -	"Medium Strings", 128,
    -    },				/* to fit most urls */
    -    {
    -	"Long Strings", 512
    -    }				/* other */
    -};
    -static struct {
    +}
    +
    +StrPoolsAttrs[mem_str_pool_count] = {
    +
    +                                        {
    +                                            "Short Strings", 36,
    +                                        },				/* to fit rfc1123 and similar */
    +                                        {
    +                                            "Medium Strings", 128,
    +                                        },				/* to fit most urls */
    +                                        {
    +                                            "Long Strings", 512
    +                                        }				/* other */
    +                                    };
    +
    +static struct
    +{
         MemPool *pool;
    -} StrPools[mem_str_pool_count];
    +}
    +
    +StrPools[mem_str_pool_count];
     static MemMeter StrCountMeter;
     static MemMeter StrVolumeMeter;
     
    @@ -85,24 +93,27 @@ memStringStats(StoreEntry * sentry)
         size_t pooled_volume = 0;
         /* heading */
         storeAppendPrintf(sentry,
    -	"String Pool\t Impact\t\t\n"
    -	" \t (%%strings)\t (%%volume)\n");
    +                      "String Pool\t Impact\t\t\n"
    +                      " \t (%%strings)\t (%%volume)\n");
         /* table body */
    +
         for (i = 0; i < mem_str_pool_count; i++) {
    -	const MemPool *pool = StrPools[i].pool;
    -	const int plevel = pool->meter.inuse.level;
    -	storeAppendPrintf(sentry, pfmt,
    -	    pool->label,
    -	    xpercentInt(plevel, StrCountMeter.level),
    -	    xpercentInt(plevel * pool->obj_size, StrVolumeMeter.level));
    -	pooled_count += plevel;
    -	pooled_volume += plevel * pool->obj_size;
    +        const MemPool *pool = StrPools[i].pool;
    +        const int plevel = pool->meter.inuse.level;
    +        storeAppendPrintf(sentry, pfmt,
    +                          pool->label,
    +                          xpercentInt(plevel, StrCountMeter.level),
    +                          xpercentInt(plevel * pool->obj_size, StrVolumeMeter.level));
    +        pooled_count += plevel;
    +        pooled_volume += plevel * pool->obj_size;
         }
    +
         /* malloc strings */
         storeAppendPrintf(sentry, pfmt,
    -	"Other Strings",
    -	xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level),
    -	xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level));
    +                      "Other Strings",
    +                      xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level),
    +                      xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level));
    +
         storeAppendPrintf(sentry, "\n");
     }
     
    @@ -110,8 +121,8 @@ static void
     memBufStats(StoreEntry * sentry)
     {
         storeAppendPrintf(sentry, "Large buffers: %d (%d KB)\n",
    -	HugeBufCountMeter.level,
    -	HugeBufVolumeMeter.level / 1024);
    +                      HugeBufCountMeter.level,
    +                      HugeBufVolumeMeter.level / 1024);
     }
     
     void
    @@ -179,12 +190,14 @@ memAllocString(size_t net_size, size_t * gross_size)
         int i;
         MemPool *pool = NULL;
         assert(gross_size);
    +
         for (i = 0; i < mem_str_pool_count; i++) {
    -	if (net_size <= StrPoolsAttrs[i].obj_size) {
    -	    pool = StrPools[i].pool;
    -	    break;
    -	}
    +        if (net_size <= StrPoolsAttrs[i].obj_size) {
    +            pool = StrPools[i].pool;
    +            break;
    +        }
         }
    +
         *gross_size = pool ? pool->obj_size : net_size;
         assert(*gross_size >= net_size);
         memMeterInc(StrCountMeter);
    @@ -199,13 +212,15 @@ memFreeString(size_t size, void *buf)
         int i;
         MemPool *pool = NULL;
         assert(size && buf);
    +
         for (i = 0; i < mem_str_pool_count; i++) {
    -	if (size <= StrPoolsAttrs[i].obj_size) {
    -	    assert(size == StrPoolsAttrs[i].obj_size);
    -	    pool = StrPools[i].pool;
    -	    break;
    -	}
    +        if (size <= StrPoolsAttrs[i].obj_size) {
    +            assert(size == StrPoolsAttrs[i].obj_size);
    +            pool = StrPools[i].pool;
    +            break;
    +        }
         }
    +
         memMeterDec(StrCountMeter);
         memMeterDel(StrVolumeMeter, size);
         pool ? memPoolFree(pool, buf) : xfree(buf);
    @@ -217,30 +232,33 @@ memFindBufSizeType(size_t net_size, size_t * gross_size)
     {
         mem_type type;
         size_t size;
    +
         if (net_size <= 2 * 1024) {
    -	type = MEM_2K_BUF;
    -	size = 2 * 1024;
    +        type = MEM_2K_BUF;
    +        size = 2 * 1024;
         } else if (net_size <= 4 * 1024) {
    -	type = MEM_4K_BUF;
    -	size = 4 * 1024;
    +        type = MEM_4K_BUF;
    +        size = 4 * 1024;
         } else if (net_size <= 8 * 1024) {
    -	type = MEM_8K_BUF;
    -	size = 8 * 1024;
    +        type = MEM_8K_BUF;
    +        size = 8 * 1024;
         } else if (net_size <= 16 * 1024) {
    -	type = MEM_16K_BUF;
    -	size = 16 * 1024;
    +        type = MEM_16K_BUF;
    +        size = 16 * 1024;
         } else if (net_size <= 32 * 1024) {
    -	type = MEM_32K_BUF;
    -	size = 32 * 1024;
    +        type = MEM_32K_BUF;
    +        size = 32 * 1024;
         } else if (net_size <= 64 * 1024) {
    -	type = MEM_64K_BUF;
    -	size = 64 * 1024;
    +        type = MEM_64K_BUF;
    +        size = 64 * 1024;
         } else {
    -	type = MEM_NONE;
    -	size = net_size;
    +        type = MEM_NONE;
    +        size = net_size;
         }
    +
         if (gross_size)
    -	*gross_size = size;
    +        *gross_size = size;
    +
         return type;
     }
     
    @@ -249,12 +267,13 @@ void *
     memAllocBuf(size_t net_size, size_t * gross_size)
     {
         mem_type type = memFindBufSizeType(net_size, gross_size);
    +
         if (type != MEM_NONE)
    -	return memAllocate(type);
    +        return memAllocate(type);
         else {
    -	memMeterInc(HugeBufCountMeter);
    -	memMeterAdd(HugeBufVolumeMeter, *gross_size);
    -	return xcalloc(1, net_size);
    +        memMeterInc(HugeBufCountMeter);
    +        memMeterAdd(HugeBufVolumeMeter, *gross_size);
    +        return xcalloc(1, net_size);
         }
     }
     
    @@ -266,13 +285,18 @@ memReallocBuf(void *oldbuf, size_t net_size, size_t * gross_size)
         /* TODO: if the existing gross size is >= new gross size, do nothing */
         size_t new_gross_size;
         void *newbuf = memAllocBuf(net_size, &new_gross_size);
    +
         if (oldbuf) {
    -	size_t data_size = *gross_size;
    -	if (data_size > net_size)
    -	    data_size = net_size;
    -	memcpy(newbuf, oldbuf, data_size);
    -	memFreeBuf(*gross_size, oldbuf);
    +        size_t data_size = *gross_size;
    +
    +        if (data_size > net_size)
    +            data_size = net_size;
    +
    +        memcpy(newbuf, oldbuf, data_size);
    +
    +        memFreeBuf(*gross_size, oldbuf);
         }
    +
         *gross_size = new_gross_size;
         return newbuf;
     }
    @@ -282,12 +306,13 @@ void
     memFreeBuf(size_t size, void *buf)
     {
         mem_type type = memFindBufSizeType(size, NULL);
    +
         if (type != MEM_NONE)
    -	memFree(buf, type);
    +        memFree(buf, type);
         else {
    -	xfree(buf);
    -	memMeterDec(HugeBufCountMeter);
    -	memMeterDel(HugeBufVolumeMeter, size);
    +        xfree(buf);
    +        memMeterDec(HugeBufCountMeter);
    +        memMeterDel(HugeBufVolumeMeter, size);
         }
     }
     
    @@ -307,16 +332,19 @@ memConfigure(void)
     {
         int new_pool_limit;
         /* set to configured value first */
    +
         if (!Config.onoff.mem_pools)
    -	new_pool_limit = 0;
    +        new_pool_limit = 0;
         else if (Config.MemPools.limit > 0)
    -	new_pool_limit = Config.MemPools.limit;
    +        new_pool_limit = Config.MemPools.limit;
         else
    -	new_pool_limit = mem_unlimited_size;
    +        new_pool_limit = mem_unlimited_size;
     
         if (mem_idle_limit > new_pool_limit)
    -	debug(13, 1) ("Shrinking idle mem pools to %.2f MB\n", toMB(new_pool_limit));
    +        debug(13, 1) ("Shrinking idle mem pools to %.2f MB\n", toMB(new_pool_limit));
    +
         memPoolSetIdleLimit(new_pool_limit);
    +
         mem_idle_limit = new_pool_limit;
     }
     
    @@ -329,7 +357,7 @@ Mem::Init(void)
         int i;
     
         debug(13, 1) ("Memory pools are '%s'; limit: %.2f MB\n",
    -	(Config.onoff.mem_pools ? "on" : "off"), toMB(mem_idle_limit));
    +                  (Config.onoff.mem_pools ? "on" : "off"), toMB(mem_idle_limit));
     
         /* set all pointers to null */
         memset(MemPools, '\0', sizeof(MemPools));
    @@ -346,13 +374,15 @@ Mem::Init(void)
         memDataInit(MEM_32K_BUF, "32K Buffer", 32768, 10);
         memDataInit(MEM_64K_BUF, "64K Buffer", 65536, 10);
         memDataInit(MEM_ACL_DENY_INFO_LIST, "acl_deny_info_list",
    -	sizeof(acl_deny_info_list), 0);
    +                sizeof(acl_deny_info_list), 0);
         memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0);
         memDataInit(MEM_ACL_PROXY_AUTH_MATCH, "acl_proxy_auth_match_cache",
    -	sizeof(acl_proxy_auth_match_cache), 0);
    +                sizeof(acl_proxy_auth_match_cache), 0);
     #if USE_CACHE_DIGESTS
    +
         memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0);
     #endif
    +
         memDataInit(MEM_LINK_LIST, "link_list", sizeof(link_list), 10);
         memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10);
         memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0);
    @@ -367,24 +397,26 @@ Mem::Init(void)
         memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0);
         memDataInit(MEM_RELIST, "relist", sizeof(relist), 0);
         memDataInit(MEM_REQUEST_T, "request_t", sizeof(request_t),
    -	Squid_MaxFD >> 3);
    +                Squid_MaxFD >> 3);
         memDataInit(MEM_WORDLIST, "wordlist", sizeof(wordlist), 0);
         memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0);
         memDataInit(MEM_MD5_DIGEST, "MD5 digest", MD5_DIGEST_CHARS, 0);
         memPoolSetChunkSize(MemPools[MEM_MD5_DIGEST], 512 * 1024);
         memDataInit(MEM_HELPER_REQUEST, "helper_request",
    -	sizeof(helper_request), 0);
    +                sizeof(helper_request), 0);
         memDataInit(MEM_HELPER_STATEFUL_REQUEST, "helper_stateful_request",
    -	sizeof(helper_stateful_request), 0);
    +                sizeof(helper_stateful_request), 0);
         memDataInit(MEM_SWAP_LOG_DATA, "storeSwapLogData", sizeof(storeSwapLogData), 0);
     
         /* init string pools */
    +
         for (i = 0; i < mem_str_pool_count; i++) {
    -	StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size);
    +        StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size);
         }
    +
         cachemgrRegister("mem",
    -	"Memory Utilization",
    -	Mem::Stats, 0, 1);
    +                     "Memory Utilization",
    +                     Mem::Stats, 0, 1);
     }
     
     mem_type &operator++ (mem_type &aMem)
    @@ -400,14 +432,16 @@ void
     memCheckInit(void)
     {
         mem_type t;
    +
         for (t = MEM_NONE, ++t; t < MEM_MAX; ++t) {
    -	if (MEM_DONTFREE == t)
    -	    continue;
    -	/*
    -	 * If you hit this assertion, then you forgot to add a
    -	 * memDataInit() line for type 't'.
    -	 */
    -	assert(MemPools[t]);
    +        if (MEM_DONTFREE == t)
    +            continue;
    +
    +        /*
    +         * If you hit this assertion, then you forgot to add a
    +         * memDataInit() line for type 't'.
    +         */
    +        assert(MemPools[t]);
         }
     }
     
    @@ -419,8 +453,8 @@ memPoolDescribe(const MemPool * pool)
     {
         assert(pool);
         debug(13, 2) ("%-20s: %6d x %4d bytes = %5d KB\n",
    -	pool->label, memPoolInUseCount(pool), pool->obj_size,
    -	toKB(pool->obj_size * pool->meter.inuse.level));
    +                  pool->label, memPoolInUseCount(pool), pool->obj_size,
    +                  toKB(pool->obj_size * pool->meter.inuse.level));
     }
     
     #endif
    @@ -432,9 +466,10 @@ memClean(void)
         memPoolSetIdleLimit(0);
         memPoolClean(0);
         memPoolGetGlobalStats(&stats);
    +
         if (stats.tot_items_inuse)
    -	debug(13, 2) ("memCleanModule: %d items in %d chunks and %d pools are left dirty\n", stats.tot_items_inuse,
    -	    stats.tot_chunks_inuse, stats.tot_pools_inuse);
    +        debug(13, 2) ("memCleanModule: %d items in %d chunks and %d pools are left dirty\n", stats.tot_items_inuse,
    +                      stats.tot_chunks_inuse, stats.tot_pools_inuse);
     }
     
     int
    @@ -485,22 +520,29 @@ FREE *
     memFreeBufFunc(size_t size)
     {
         switch (size) {
    +
         case 2 * 1024:
    -	return memFree2K;
    +        return memFree2K;
    +
         case 4 * 1024:
    -	return memFree4K;
    +        return memFree4K;
    +
         case 8 * 1024:
    -	return memFree8K;
    +        return memFree8K;
    +
         case 16 * 1024:
    -	return memFree16K;
    +        return memFree16K;
    +
         case 32 * 1024:
    -	return memFree32K;
    +        return memFree32K;
    +
         case 64 * 1024:
    -	return memFree64K;
    +        return memFree64K;
    +
         default:
    -	memMeterDec(HugeBufCountMeter);
    -	memMeterDel(HugeBufVolumeMeter, size);
    -	return xfree;
    +        memMeterDec(HugeBufCountMeter);
    +        memMeterDel(HugeBufVolumeMeter, size);
    +        return xfree;
         }
     }
     
    @@ -514,55 +556,58 @@ Mem::PoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, Store
         MemPoolMeter *pm = mp_st->meter;
     
         storeAppendPrintf(e, "%-20s\t %4d\t ",
    -	mp_st->label, mp_st->obj_size);
    +                      mp_st->label, mp_st->obj_size);
     
         /* Chunks */
         storeAppendPrintf(e, "%4d\t %4d\t ",
    -	toKB(mp_st->obj_size * mp_st->chunk_capacity), mp_st->chunk_capacity);
    +                      toKB(mp_st->obj_size * mp_st->chunk_capacity), mp_st->chunk_capacity);
     
         if (mp_st->chunk_capacity) {
    -	needed = mp_st->items_inuse / mp_st->chunk_capacity;
    -	if (mp_st->items_inuse % mp_st->chunk_capacity)
    -	    needed++;
    -	excess = mp_st->chunks_inuse - needed;
    +        needed = mp_st->items_inuse / mp_st->chunk_capacity;
    +
    +        if (mp_st->items_inuse % mp_st->chunk_capacity)
    +            needed++;
    +
    +        excess = mp_st->chunks_inuse - needed;
         }
    +
         storeAppendPrintf(e, "%4d\t %4d\t %4d\t %4d\t %.1f\t ",
    -	mp_st->chunks_alloc, mp_st->chunks_inuse, mp_st->chunks_free, mp_st->chunks_partial,
    -	xpercent(excess, needed));
    -/*
    - *  Fragmentation calculation:
    - *    needed = inuse.level / chunk_capacity
    - *    excess = used - needed
    - *    fragmentation = excess / needed * 100%
    - *
    - *    Fragm = (alloced - (inuse / obj_ch) ) / alloced
    - */
    +                      mp_st->chunks_alloc, mp_st->chunks_inuse, mp_st->chunks_free, mp_st->chunks_partial,
    +                      xpercent(excess, needed));
    +    /*
    +     *  Fragmentation calculation:
    +     *    needed = inuse.level / chunk_capacity
    +     *    excess = used - needed
    +     *    fragmentation = excess / needed * 100%
    +     *
    +     *    Fragm = (alloced - (inuse / obj_ch) ) / alloced
    +     */
     
         storeAppendPrintf(e,
    -	"%d\t %d\t %d\t %.2f\t %.1f\t"	/* alloc */
    -	"%d\t %d\t %d\t %.1f\t"	/* in use */
    -	"%d\t %d\t %d\t"	/* idle */
    -	"%.0f\t %.1f\t %.1f\t %.1f\n",	/* saved */
    -    /* alloc */
    -	mp_st->items_alloc,
    -	toKB(mp_st->obj_size * pm->alloc.level),
    -	toKB(mp_st->obj_size * pm->alloc.hwater_level),
    -	(double) ((squid_curtime - pm->alloc.hwater_stamp) / 3600.),
    -	xpercent(mp_st->obj_size * pm->alloc.level, AllMeter->alloc.level),
    -    /* in use */
    -	mp_st->items_inuse,
    -	toKB(mp_st->obj_size * pm->inuse.level),
    -	toKB(mp_st->obj_size * pm->inuse.hwater_level),
    -	xpercent(pm->inuse.level, pm->alloc.level),
    -    /* idle */
    -	mp_st->items_idle,
    -	toKB(mp_st->obj_size * pm->idle.level),
    -	toKB(mp_st->obj_size * pm->idle.hwater_level),
    -    /* saved */
    -	pm->gb_saved.count,
    -	xpercent(pm->gb_saved.count, AllMeter->gb_saved.count),
    -	xpercent(pm->gb_saved.bytes, AllMeter->gb_saved.bytes),
    -	xdiv(pm->gb_saved.count - pm->gb_osaved.count, xm_deltat));
    +                      "%d\t %d\t %d\t %.2f\t %.1f\t"	/* alloc */
    +                      "%d\t %d\t %d\t %.1f\t"	/* in use */
    +                      "%d\t %d\t %d\t"	/* idle */
    +                      "%.0f\t %.1f\t %.1f\t %.1f\n",	/* saved */
    +                      /* alloc */
    +                      mp_st->items_alloc,
    +                      toKB(mp_st->obj_size * pm->alloc.level),
    +                      toKB(mp_st->obj_size * pm->alloc.hwater_level),
    +                      (double) ((squid_curtime - pm->alloc.hwater_stamp) / 3600.),
    +                      xpercent(mp_st->obj_size * pm->alloc.level, AllMeter->alloc.level),
    +                      /* in use */
    +                      mp_st->items_inuse,
    +                      toKB(mp_st->obj_size * pm->inuse.level),
    +                      toKB(mp_st->obj_size * pm->inuse.hwater_level),
    +                      xpercent(pm->inuse.level, pm->alloc.level),
    +                      /* idle */
    +                      mp_st->items_idle,
    +                      toKB(mp_st->obj_size * pm->idle.level),
    +                      toKB(mp_st->obj_size * pm->idle.hwater_level),
    +                      /* saved */
    +                      pm->gb_saved.count,
    +                      xpercent(pm->gb_saved.count, AllMeter->gb_saved.count),
    +                      xpercent(pm->gb_saved.bytes, AllMeter->gb_saved.bytes),
    +                      xdiv(pm->gb_saved.count - pm->gb_osaved.count, xm_deltat));
         pm->gb_osaved.count = pm->gb_saved.count;
     }
     
    @@ -580,23 +625,23 @@ Mem::Report(StoreEntry * e)
         storeAppendPrintf(e, "Current memory usage:\n");
         /* heading */
         storeAppendPrintf(e,
    -	"Pool\t Obj Size\t"
    -	"Chunks\t\t\t\t\t\t\t"
    -	"Allocated\t\t\t\t\t"
    -	"In Use\t\t\t\t"
    -	"Idle\t\t\t"
    -	"Allocations Saved\t\t\t"
    -	"Hit Rate\t"
    -	"\n"
    -	" \t (bytes)\t"
    -	"KB/ch\t obj/ch\t"
    -	"(#)\t used\t free\t part\t %%Frag\t "
    -	"(#)\t (KB)\t high (KB)\t high (hrs)\t %%Tot\t"
    -	"(#)\t (KB)\t high (KB)\t %%alloc\t"
    -	"(#)\t (KB)\t high (KB)\t"
    -	"(#)\t %%cnt\t %%vol\t"
    -	"(#) / sec\t"
    -	"\n");
    +                      "Pool\t Obj Size\t"
    +                      "Chunks\t\t\t\t\t\t\t"
    +                      "Allocated\t\t\t\t\t"
    +                      "In Use\t\t\t\t"
    +                      "Idle\t\t\t"
    +                      "Allocations Saved\t\t\t"
    +                      "Hit Rate\t"
    +                      "\n"
    +                      " \t (bytes)\t"
    +                      "KB/ch\t obj/ch\t"
    +                      "(#)\t used\t free\t part\t %%Frag\t "
    +                      "(#)\t (KB)\t high (KB)\t high (hrs)\t %%Tot\t"
    +                      "(#)\t (KB)\t high (KB)\t %%alloc\t"
    +                      "(#)\t (KB)\t high (KB)\t"
    +                      "(#)\t %%cnt\t %%vol\t"
    +                      "(#) / sec\t"
    +                      "\n");
         xm_deltat = current_dtime - xm_time;
         xm_time = current_dtime;
     
    @@ -605,15 +650,19 @@ Mem::Report(StoreEntry * e)
     
         /* main table */
         iter = memPoolIterate();
    +
         while ((pool = memPoolIterateNext(iter))) {
    -	memPoolGetStats(&mp_stats, pool);
    -	if (!mp_stats.pool)	/* pool destroyed */
    -	    continue;
    -	if (mp_stats.pool->meter.gb_saved.count > 0)	/* this pool has been used */
    -	    PoolReport(&mp_stats, mp_total.TheMeter, e);
    -	else
    -	    not_used++;
    +        memPoolGetStats(&mp_stats, pool);
    +
    +        if (!mp_stats.pool)	/* pool destroyed */
    +            continue;
    +
    +        if (mp_stats.pool->meter.gb_saved.count > 0)	/* this pool has been used */
    +            PoolReport(&mp_stats, mp_total.TheMeter, e);
    +        else
    +            not_used++;
         }
    +
         memPoolIterateDone(&iter);
     
         mp_stats.pool = NULL;
    @@ -637,7 +686,7 @@ Mem::Report(StoreEntry * e)
         storeAppendPrintf(e, "Cumulative allocated volume: %s\n", double_to_str(buf, 64, mp_total.TheMeter->gb_saved.bytes));
         /* overhead */
         storeAppendPrintf(e, "Current overhead: %d bytes (%.3f%%)\n",
    -	mp_total.tot_overhead, xpercent(mp_total.tot_overhead, mp_total.TheMeter->inuse.level));
    +                      mp_total.tot_overhead, xpercent(mp_total.tot_overhead, mp_total.TheMeter->inuse.level));
         /* limits */
         storeAppendPrintf(e, "Idle pool limit: %.2f MB\n", toMB(mp_total.mem_idle_limit));
         /* limits */
    diff --git a/src/mem_node.cc b/src/mem_node.cc
    index 81fa5f2408..37f0cd2d8d 100644
    --- a/src/mem_node.cc
    +++ b/src/mem_node.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: mem_node.cc,v 1.1 2003/01/23 00:37:23 robertc Exp $
    + * $Id: mem_node.cc,v 1.2 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 19    Store Memory Primitives
      * AUTHOR: Robert Collins
    @@ -44,8 +44,10 @@ mem_node::operator new (size_t byteCount)
     {
         /* derived classes with different sizes must implement their own new */
         assert (byteCount == sizeof (mem_node));
    +
         if (!pool)
    -	pool = memPoolCreate("mem_node", sizeof (mem_node));
    +        pool = memPoolCreate("mem_node", sizeof (mem_node));
    +
         return memPoolAlloc(pool);
     }
     
    @@ -56,8 +58,7 @@ mem_node::operator delete (void *address)
     }
     
     mem_node::mem_node(off_t offset):nodeBuffer(0,offset,data), next (NULL)
    -{
    -}
    +{}
     
     mem_node::~mem_node()
     {
    @@ -68,9 +69,12 @@ size_t
     mem_node::InUseCount()
     {
         if (!pool)
    -	return 0;
    +        return 0;
    +
         MemPoolStats stats;
    +
         memPoolGetStats (&stats, pool);
    +
         return stats.items_inuse;
     }
     
    @@ -97,7 +101,8 @@ bool
     mem_node::contains (size_t const &location) const
     {
         if (start() <= location && end() > location)
    -	return true;
    +        return true;
    +
         return false;
     }
     
    @@ -106,6 +111,7 @@ bool
     mem_node::canAccept (size_t const &location) const
     {
         if (location == end() && space() > 0)
    -	return true;
    +        return true;
    +
         return false;
     }
    diff --git a/src/mem_node.h b/src/mem_node.h
    index 7ac0b1c46c..67ac51a66a 100644
    --- a/src/mem_node.h
    +++ b/src/mem_node.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: mem_node.h,v 1.1 2003/01/23 00:37:23 robertc Exp $
    + * $Id: mem_node.h,v 1.2 2003/02/21 22:50:10 robertc Exp $
      *
      *
      * SQUID Web Proxy Cache          http://www.squid-cache.org/
    @@ -35,7 +35,10 @@
     #define SQUID_MEM_NODE_H
     
     #include "StoreIOBuffer.h"
    -class mem_node {
    +
    +class mem_node
    +{
    +
     public:
         static size_t InUseCount();
         static unsigned long store_mem_size;	/* 0 */
    @@ -45,7 +48,7 @@ public:
         mem_node(off_t);
         ~mem_node();
         size_t space() const;
    -    size_t start() const;  
    +    size_t start() const;
         size_t end() const;
         bool contains (size_t const &location) const;
         bool canAccept (size_t const &location) const;
    @@ -54,6 +57,7 @@ public:
         mem_node *next;
         /* Private */
         char data[SM_PAGE_SIZE];
    +
     private:
         static MemPool *pool;
     };
    diff --git a/src/mime.cc b/src/mime.cc
    index aaed05ccfe..66a592edb7 100644
    --- a/src/mime.cc
    +++ b/src/mime.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: mime.cc,v 1.110 2003/01/23 00:37:23 robertc Exp $
    + * $Id: mime.cc,v 1.111 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 25    MIME Parsing
      * AUTHOR: Harvest Derived
    @@ -43,31 +43,40 @@
     
     #define GET_HDR_SZ 1024
     
    -class MimeIcon : public StoreClient {
    -public: 
    +class MimeIcon : public StoreClient
    +{
    +
    +public:
         MimeIcon ();
         void setName (char const *);
         char const * getName () const;
         void _free();
         void load();
         void created (StoreEntry *newEntry);
    +
     private:
         char *icon;
         char *url;
     };
     
    -class mimeEntry {
    +class mimeEntry
    +{
    +
     public:
         void *operator new (size_t byteCount);
         void operator delete (void *address);
    -  
    +
         char *pattern;
         regex_t compiled_pattern;
         char *icon;
         char *content_type;
         char *content_encoding;
         char transfer_mode;
    -    unsigned int view_option:1, download_option:1;
    +
    +unsigned int view_option:
    +
    +1, download_option:
    +    1;
         mimeEntry *next;
         MimeIcon theIcon;
     };
    @@ -110,41 +119,56 @@ mime_get_header_field(const char *mime, const char *name, const char *prefix)
         int l;
     
         if (NULL == mime)
    -	return NULL;
    +        return NULL;
    +
         assert(NULL != name);
     
         debug(25, 5) ("mime_get_header: looking for '%s'\n", name);
     
         for (p = mime; *p; p += strcspn(p, "\n\r")) {
    -	if (strcmp(p, "\r\n\r\n") == 0 || strcmp(p, "\n\n") == 0)
    -	    return NULL;
    -	while (xisspace(*p))
    -	    p++;
    -	if (strncasecmp(p, name, namelen))
    -	    continue;
    -	if (!xisspace(p[namelen]) && p[namelen] != ':')
    -	    continue;
    -	l = strcspn(p, "\n\r") + 1;
    -	if (l > GET_HDR_SZ)
    -	    l = GET_HDR_SZ;
    -	xstrncpy(header, p, l);
    -	debug(25, 5) ("mime_get_header: checking '%s'\n", header);
    -	q = header;
    -	q += namelen;
    -	if (*q == ':')
    -	    q++, got = 1;
    -	while (xisspace(*q))
    -	    q++, got = 1;
    -	if (got && prefix) {
    -	    /* we could process list entries here if we had strcasestr(). */
    -	    /* make sure we did not match a part of another field-value */
    -	    got = !strncasecmp(q, prefix, preflen) && !xisalpha(q[preflen]);
    -	}
    -	if (got) {
    -	    debug(25, 5) ("mime_get_header: returning '%s'\n", q);
    -	    return q;
    -	}
    +        if (strcmp(p, "\r\n\r\n") == 0 || strcmp(p, "\n\n") == 0)
    +            return NULL;
    +
    +        while (xisspace(*p))
    +            p++;
    +
    +        if (strncasecmp(p, name, namelen))
    +            continue;
    +
    +        if (!xisspace(p[namelen]) && p[namelen] != ':')
    +            continue;
    +
    +        l = strcspn(p, "\n\r") + 1;
    +
    +        if (l > GET_HDR_SZ)
    +            l = GET_HDR_SZ;
    +
    +        xstrncpy(header, p, l);
    +
    +        debug(25, 5) ("mime_get_header: checking '%s'\n", header);
    +
    +        q = header;
    +
    +        q += namelen;
    +
    +        if (*q == ':')
    +            q++, got = 1;
    +
    +        while (xisspace(*q))
    +            q++, got = 1;
    +
    +        if (got && prefix) {
    +            /* we could process list entries here if we had strcasestr(). */
    +            /* make sure we did not match a part of another field-value */
    +            got = !strncasecmp(q, prefix, preflen) && !xisalpha(q[preflen]);
    +        }
    +
    +        if (got) {
    +            debug(25, 5) ("mime_get_header: returning '%s'\n", q);
    +            return q;
    +        }
         }
    +
         return NULL;
     }
     
    @@ -153,35 +177,47 @@ headersEnd(const char *mime, size_t l)
     {
         size_t e = 0;
         int state = 0;
    +
         while (e < l && state < 3) {
    -	switch (state) {
    -	case 0:
    -	    if ('\n' == mime[e])
    -		state = 1;
    -	    break;
    -	case 1:
    -	    if ('\r' == mime[e])
    -		state = 2;
    -	    else if ('\n' == mime[e])
    -		state = 3;
    -	    else
    -		state = 0;
    -	    break;
    -	case 2:
    -	    if ('\r' == mime[e])	/* ignore repeated CR */
    -		(void) 0;
    -	    else if ('\n' == mime[e])
    -		state = 3;
    -	    else
    -		state = 0;
    -	    break;
    -	default:
    -	    break;
    -	}
    -	e++;
    +        switch (state) {
    +
    +        case 0:
    +
    +            if ('\n' == mime[e])
    +                state = 1;
    +
    +            break;
    +
    +        case 1:
    +            if ('\r' == mime[e])
    +                state = 2;
    +            else if ('\n' == mime[e])
    +                state = 3;
    +            else
    +                state = 0;
    +
    +            break;
    +
    +        case 2:
    +            if ('\r' == mime[e])	/* ignore repeated CR */
    +                (void) 0;
    +            else if ('\n' == mime[e])
    +                state = 3;
    +            else
    +                state = 0;
    +
    +            break;
    +
    +        default:
    +            break;
    +        }
    +
    +        e++;
         }
    +
         if (3 == state)
    -	return e;
    +        return e;
    +
         return 0;
     }
     
    @@ -190,20 +226,28 @@ mime_get_auth(const char *hdr, const char *auth_scheme, const char **auth_field)
     {
         char *auth_hdr;
         char *t;
    +
         if (auth_field)
    -	*auth_field = NULL;
    +        *auth_field = NULL;
    +
         if (hdr == NULL)
    -	return NULL;
    +        return NULL;
    +
         if ((auth_hdr = mime_get_header(hdr, "Authorization")) == NULL)
    -	return NULL;
    +        return NULL;
    +
         if (auth_field)
    -	*auth_field = auth_hdr;
    +        *auth_field = auth_hdr;
    +
         if ((t = strtok(auth_hdr, " \t")) == NULL)
    -	return NULL;
    +        return NULL;
    +
         if (strcasecmp(t, auth_scheme) != 0)
    -	return NULL;
    +        return NULL;
    +
         if ((t = strtok(NULL, " \t")) == NULL)
    -	return NULL;
    +        return NULL;
    +
         return base64_decode(t);
     }
     
    @@ -213,35 +257,40 @@ mimeGetEntry(const char *fn, int skip_encodings)
         mimeEntry *m;
         char *t;
         char *name = xstrdup(fn);
    -  try_again:
    +
    +try_again:
    +
         for (m = MimeTable; m; m = m->next) {
    -	if (regexec(&m->compiled_pattern, name, 0, 0, 0) == 0)
    -	    break;
    +        if (regexec(&m->compiled_pattern, name, 0, 0, 0) == 0)
    +            break;
         }
    +
         if (!skip_encodings)
    -	(void) 0;
    +        (void) 0;
         else if (m == NULL)
    -	(void) 0;
    +        (void) 0;
         else if (strcmp(m->content_type, dash_str))
    -	(void) 0;
    +        (void) 0;
         else if (!strcmp(m->content_encoding, dash_str))
    -	(void) 0;
    +        (void) 0;
         else {
    -	/* Assume we matched /\.\w$/ and cut off the last extension */
    -	if ((t = strrchr(name, '.'))) {
    -	    *t = '\0';
    -	    goto try_again;
    -	}
    -	/* What? A encoding without a extension? */
    -	m = NULL;
    +        /* Assume we matched /\.\w$/ and cut off the last extension */
    +
    +        if ((t = strrchr(name, '.'))) {
    +            *t = '\0';
    +            goto try_again;
    +        }
    +
    +        /* What? A encoding without a extension? */
    +        m = NULL;
         }
    +
         xfree(name);
         return m;
     }
     
     MimeIcon::MimeIcon () : icon (NULL), url (NULL)
    -{
    -}
    +{}
     
     void
     MimeIcon::setName (char const *aString)
    @@ -270,10 +319,13 @@ char const *
     mimeGetIcon(const char *fn)
     {
         mimeEntry *m = mimeGetEntry(fn, 1);
    +
         if (m == NULL)
    -	return NULL;
    +        return NULL;
    +
         if (!strcmp(m->theIcon.getName(), dash_str))
    -	return NULL;
    +        return NULL;
    +
         return m->theIcon.getName();
     }
     
    @@ -281,8 +333,10 @@ const char *
     mimeGetIconURL(const char *fn)
     {
         char const *icon = mimeGetIcon(fn);
    +
         if (icon == NULL)
    -	return null_string;
    +        return null_string;
    +
         return internalLocalUri("/squid-internal-static/icons/", icon);
     }
     
    @@ -290,10 +344,13 @@ char *
     mimeGetContentType(const char *fn)
     {
         mimeEntry *m = mimeGetEntry(fn, 1);
    +
         if (m == NULL)
    -	return NULL;
    +        return NULL;
    +
         if (!strcmp(m->content_type, dash_str))
    -	return NULL;
    +        return NULL;
    +
         return m->content_type;
     }
     
    @@ -301,10 +358,13 @@ char *
     mimeGetContentEncoding(const char *fn)
     {
         mimeEntry *m = mimeGetEntry(fn, 0);
    +
         if (m == NULL)
    -	return NULL;
    +        return NULL;
    +
         if (!strcmp(m->content_encoding, dash_str))
    -	return NULL;
    +        return NULL;
    +
         return m->content_encoding;
     }
     
    @@ -352,84 +412,112 @@ mimeInit(char *filename)
         regex_t re;
         mimeEntry *m;
         int re_flags = REG_EXTENDED | REG_NOSUB | REG_ICASE;
    +
         if (filename == NULL)
    -	return;
    +        return;
    +
         if ((fp = fopen(filename, "r")) == NULL) {
    -	debug(25, 1) ("mimeInit: %s: %s\n", filename, xstrerror());
    -	return;
    +        debug(25, 1) ("mimeInit: %s: %s\n", filename, xstrerror());
    +        return;
         }
    +
     #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_)
         setmode(fileno(fp), O_TEXT);
    +
     #endif
    +
         mimeFreeMemory();
    +
         while (fgets(buf, BUFSIZ, fp)) {
    -	if ((t = strchr(buf, '#')))
    -	    *t = '\0';
    -	if ((t = strchr(buf, '\r')))
    -	    *t = '\0';
    -	if ((t = strchr(buf, '\n')))
    -	    *t = '\0';
    -	if (buf[0] == '\0')
    -	    continue;
    -	xstrncpy(chopbuf, buf, BUFSIZ);
    -	if ((pattern = strtok(chopbuf, w_space)) == NULL) {
    -	    debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    -	    continue;
    -	}
    -	if ((type = strtok(NULL, w_space)) == NULL) {
    -	    debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    -	    continue;
    -	}
    -	if ((icon = strtok(NULL, w_space)) == NULL) {
    -	    debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    -	    continue;
    -	}
    -	if ((encoding = strtok(NULL, w_space)) == NULL) {
    -	    debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    -	    continue;
    -	}
    -	if ((mode = strtok(NULL, w_space)) == NULL) {
    -	    debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    -	    continue;
    -	}
    -	download_option = 0;
    -	view_option = 0;
    -	while ((option = strtok(NULL, w_space)) != NULL) {
    -	    if (!strcmp(option, "+download"))
    -		download_option = 1;
    -	    else if (!strcmp(option, "+view"))
    -		view_option = 1;
    -	    else
    -		debug(25, 1) ("mimeInit: unknown option: '%s' (%s)\n", buf, option);
    -	}
    -	if (regcomp(&re, pattern, re_flags) != 0) {
    -	    debug(25, 1) ("mimeInit: regcomp error: '%s'\n", buf);
    -	    continue;
    -	}
    -	m = new mimeEntry;
    -	m->pattern = xstrdup(pattern);
    -	m->content_type = xstrdup(type);
    -	m->theIcon.setName(icon);
    -	m->content_encoding = xstrdup(encoding);
    -	m->compiled_pattern = re;
    -	if (!strcasecmp(mode, "ascii"))
    -	    m->transfer_mode = 'A';
    -	else if (!strcasecmp(mode, "text"))
    -	    m->transfer_mode = 'A';
    -	else
    -	    m->transfer_mode = 'I';
    -	m->view_option = view_option;
    -	m->download_option = download_option;
    -	*MimeTableTail = m;
    -	MimeTableTail = &m->next;
    -	debug(25, 5) ("mimeInit: added '%s'\n", buf);
    +        if ((t = strchr(buf, '#')))
    +            *t = '\0';
    +
    +        if ((t = strchr(buf, '\r')))
    +            *t = '\0';
    +
    +        if ((t = strchr(buf, '\n')))
    +            *t = '\0';
    +
    +        if (buf[0] == '\0')
    +            continue;
    +
    +        xstrncpy(chopbuf, buf, BUFSIZ);
    +
    +        if ((pattern = strtok(chopbuf, w_space)) == NULL) {
    +            debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    +            continue;
    +        }
    +
    +        if ((type = strtok(NULL, w_space)) == NULL) {
    +            debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    +            continue;
    +        }
    +
    +        if ((icon = strtok(NULL, w_space)) == NULL) {
    +            debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    +            continue;
    +        }
    +
    +        if ((encoding = strtok(NULL, w_space)) == NULL) {
    +            debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    +            continue;
    +        }
    +
    +        if ((mode = strtok(NULL, w_space)) == NULL) {
    +            debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
    +            continue;
    +        }
    +
    +        download_option = 0;
    +        view_option = 0;
    +
    +        while ((option = strtok(NULL, w_space)) != NULL) {
    +            if (!strcmp(option, "+download"))
    +                download_option = 1;
    +            else if (!strcmp(option, "+view"))
    +                view_option = 1;
    +            else
    +                debug(25, 1) ("mimeInit: unknown option: '%s' (%s)\n", buf, option);
    +        }
    +
    +        if (regcomp(&re, pattern, re_flags) != 0) {
    +            debug(25, 1) ("mimeInit: regcomp error: '%s'\n", buf);
    +            continue;
    +        }
    +
    +        m = new mimeEntry;
    +        m->pattern = xstrdup(pattern);
    +        m->content_type = xstrdup(type);
    +        m->theIcon.setName(icon);
    +        m->content_encoding = xstrdup(encoding);
    +        m->compiled_pattern = re;
    +
    +        if (!strcasecmp(mode, "ascii"))
    +            m->transfer_mode = 'A';
    +        else if (!strcasecmp(mode, "text"))
    +            m->transfer_mode = 'A';
    +        else
    +            m->transfer_mode = 'I';
    +
    +        m->view_option = view_option;
    +
    +        m->download_option = download_option;
    +
    +        *MimeTableTail = m;
    +
    +        MimeTableTail = &m->next;
    +
    +        debug(25, 5) ("mimeInit: added '%s'\n", buf);
         }
    +
         fclose(fp);
         /*
          * Create Icon StoreEntry's
          */
    +
         for (m = MimeTable; m != NULL; m = m->next)
    -	m->theIcon.load();
    +        m->theIcon.load();
    +
         debug(25, 1) ("Loaded Icons.\n");
     }
     
    @@ -437,15 +525,17 @@ void
     mimeFreeMemory(void)
     {
         mimeEntry *m;
    +
         while ((m = MimeTable)) {
    -	MimeTable = m->next;
    -	safe_free(m->pattern);
    -	safe_free(m->content_type);
    -	safe_free(m->icon);
    -	safe_free(m->content_encoding);
    -	regfree(&m->compiled_pattern);
    -	delete m;
    +        MimeTable = m->next;
    +        safe_free(m->pattern);
    +        safe_free(m->content_type);
    +        safe_free(m->icon);
    +        safe_free(m->content_encoding);
    +        regfree(&m->compiled_pattern);
    +        delete m;
         }
    +
         MimeTableTail = &MimeTable;
     }
     
    @@ -453,8 +543,10 @@ void
     MimeIcon::load()
     {
         const char *type = mimeGetContentType(icon);
    +
         if (type == NULL)
    -	fatal("Unknown icon format while reading mime.conf\n");
    +        fatal("Unknown icon format while reading mime.conf\n");
    +
         StoreEntry::getPublic(this, url, METHOD_GET);
     }
     
    @@ -462,58 +554,88 @@ void
     MimeIcon::created (StoreEntry *newEntry)
     {
         /* is already in the store, do nothing */
    +
         if (!newEntry->isNull())
    -	return;
    +        return;
    +
         int fd;
    +
         int n;
    +
         request_flags flags;
    +
         struct stat sb;
    +
         LOCAL_ARRAY(char, path, MAXPATHLEN);
    +
         char *buf;
    +
         http_version_t version;
    -	
    -				
    +
    +
         snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon);
    +
         fd = file_open(path, O_RDONLY | O_BINARY);
    +
         if (fd < 0) {
    -	debug(25, 0) ("mimeLoadIconFile: %s: %s\n", path, xstrerror());
    -	return;
    +        debug(25, 0) ("mimeLoadIconFile: %s: %s\n", path, xstrerror());
    +        return;
         }
    +
         if (fstat(fd, &sb) < 0) {
    -	debug(25, 0) ("mimeLoadIconFile: FD %d: fstat: %s\n", fd, xstrerror());
    -	file_close(fd);
    -	return;
    +        debug(25, 0) ("mimeLoadIconFile: FD %d: fstat: %s\n", fd, xstrerror());
    +        file_close(fd);
    +        return;
         }
    +
         flags.cachable = 1;
         StoreEntry *e = storeCreateEntry(url,
    -	url,
    -	flags,
    -	METHOD_GET);
    +                                     url,
    +                                     flags,
    +                                     METHOD_GET);
         assert(e != NULL);
         EBIT_SET(e->flags, ENTRY_SPECIAL);
         storeSetPublicKey(e);
         storeBuffer(e);
         request_t *r = urlParse(METHOD_GET, url);
    +
         if (NULL == r)
    -	fatal("mimeLoadIcon: cannot parse internal URL");
    +        fatal("mimeLoadIcon: cannot parse internal URL");
    +
         e->mem_obj->request = requestLink(r);
    +
         HttpReply *reply = httpReplyCreate();
    +
         httpBuildVersion(&version, 1, 0);
    +
         httpReplySetHeaders(reply, version, HTTP_OK, NULL,
    -	mimeGetContentType(icon), (int) sb.st_size, sb.st_mtime, -1);
    +                        mimeGetContentType(icon), (int) sb.st_size, sb.st_mtime, -1);
    +
         reply->cache_control = httpHdrCcCreate();
    +
         httpHdrCcSetMaxAge(reply->cache_control, 86400);
    +
         httpHeaderPutCc(&reply->header, reply->cache_control);
    +
         httpReplySwapOut(reply, e);
    +
         /* read the file into the buffer and append it to store */
         buf = (char *)memAllocate(MEM_4K_BUF);
    +
         while ((n = FD_READ_METHOD(fd, buf, 4096)) > 0)
    -	storeAppend(e, buf, n);
    +        storeAppend(e, buf, n);
    +
         file_close(fd);
    +
         storeBufferFlush(e);
    +
         e->complete();
    +
         storeTimestampsSet(e);
    +
         debug(25, 3) ("Loaded icon %s\n", url);
    +
         storeUnlockObject(e);
    +
         memFree(buf, MEM_4K_BUF);
     }
    diff --git a/src/multicast.cc b/src/multicast.cc
    index f87a303fda..2c57fd1adf 100644
    --- a/src/multicast.cc
    +++ b/src/multicast.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: multicast.cc,v 1.10 2003/01/23 00:37:23 robertc Exp $
    + * $Id: multicast.cc,v 1.11 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 7     Multicast
      * AUTHOR: Martin Hamilton
    @@ -40,10 +40,13 @@ mcastSetTtl(int fd, int mcast_ttl)
     {
     #ifdef IP_MULTICAST_TTL
         char ttl = (char) mcast_ttl;
    +
         if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 1) < 0)
    -	debug(50, 1) ("comm_set_mcast_ttl: FD %d, TTL: %d: %s\n",
    -	    fd, mcast_ttl, xstrerror());
    +        debug(50, 1) ("comm_set_mcast_ttl: FD %d, TTL: %d: %s\n",
    +                      fd, mcast_ttl, xstrerror());
    +
     #endif
    +
         return 0;
     }
     
    @@ -52,27 +55,35 @@ mcastJoinGroups(const ipcache_addrs * ia, void *datanotused)
     {
     #ifdef IP_MULTICAST_TTL
         int fd = theInIcpConnection;
    +
         struct ip_mreq mr;
         int i;
         int x;
         char c = 0;
    +
         if (ia == NULL) {
    -	debug(7, 0) ("comm_join_mcast_groups: Unknown host\n");
    -	return;
    +        debug(7, 0) ("comm_join_mcast_groups: Unknown host\n");
    +        return;
         }
    +
         for (i = 0; i < (int) ia->count; i++) {
    -	debug(7, 10) ("Listening for ICP requests on %s\n",
    -	    inet_ntoa(*(ia->in_addrs + i)));
    -	mr.imr_multiaddr.s_addr = (ia->in_addrs + i)->s_addr;
    -	mr.imr_interface.s_addr = INADDR_ANY;
    -	x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
    -	    (char *) &mr, sizeof(struct ip_mreq));
    -	if (x < 0)
    -	    debug(7, 1) ("comm_join_mcast_groups: FD %d, [%s]\n",
    -		fd, inet_ntoa(*(ia->in_addrs + i)));
    -	x = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1);
    -	if (x < 0)
    -	    debug(7, 1) ("Can't disable multicast loopback: %s\n", xstrerror());
    +        debug(7, 10) ("Listening for ICP requests on %s\n",
    +                      inet_ntoa(*(ia->in_addrs + i)));
    +        mr.imr_multiaddr.s_addr = (ia->in_addrs + i)->s_addr;
    +        mr.imr_interface.s_addr = INADDR_ANY;
    +        x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
    +
    +                       (char *) &mr, sizeof(struct ip_mreq));
    +
    +        if (x < 0)
    +            debug(7, 1) ("comm_join_mcast_groups: FD %d, [%s]\n",
    +                         fd, inet_ntoa(*(ia->in_addrs + i)));
    +
    +        x = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1);
    +
    +        if (x < 0)
    +            debug(7, 1) ("Can't disable multicast loopback: %s\n", xstrerror());
         }
    +
     #endif
     }
    diff --git a/src/neighbors.cc b/src/neighbors.cc
    index 9dac74d60e..1b7364fa29 100644
    --- a/src/neighbors.cc
    +++ b/src/neighbors.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: neighbors.cc,v 1.316 2003/02/21 19:53:02 hno Exp $
    + * $Id: neighbors.cc,v 1.317 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 15    Neighbor Routines
      * AUTHOR: Harvest Derived
    @@ -60,6 +60,7 @@ static void peerCountMcastPeersDone(void *data);
     static void peerCountMcastPeersStart(void *data);
     static void peerCountMcastPeersSchedule(peer * p, time_t when);
     static IRCB peerCountHandleIcpReply;
    +
     static void neighborIgnoreNonPeer(const struct sockaddr_in *, icp_opcode);
     static OBJH neighborDumpPeers;
     static OBJH neighborDumpNonPeers;
    @@ -75,42 +76,53 @@ const char *
     neighborTypeStr(const peer * p)
     {
         if (p->type == PEER_NONE)
    -	return "Non-Peer";
    +        return "Non-Peer";
    +
         if (p->type == PEER_SIBLING)
    -	return "Sibling";
    +        return "Sibling";
    +
         if (p->type == PEER_MULTICAST)
    -	return "Multicast Group";
    +        return "Multicast Group";
    +
         return "Parent";
     }
     
     
     peer *
    +
     whichPeer(const struct sockaddr_in * from)
     {
         int j;
         u_short port = ntohs(from->sin_port);
    +
         struct in_addr ip = from->sin_addr;
         peer *p = NULL;
         debug(15, 3) ("whichPeer: from %s port %d\n", inet_ntoa(ip), port);
    -    for (p = Config.peers; p; p = p->next) {
    -	for (j = 0; j < p->n_addresses; j++) {
    -	    if (ip.s_addr == p->addresses[j].s_addr && port == p->icp.port) {
    -		return p;
    -	    }
    -	}
    +
    +    for (p = Config.peers; p; p = p->next)
    +    {
    +        for (j = 0; j < p->n_addresses; j++) {
    +            if (ip.s_addr == p->addresses[j].s_addr && port == p->icp.port) {
    +                return p;
    +            }
    +        }
         }
    +
         return NULL;
     }
     
     peer_t
     neighborType(const peer * p, const request_t * request)
     {
    +
         const struct _domain_type *d = NULL;
    +
         for (d = p->typelist; d; d = d->next) {
    -	if (0 == matchDomainName(request->host, d->domain))
    -	    if (d->type != PEER_NONE)
    -		return d->type;
    +        if (0 == matchDomainName(request->host, d->domain))
    +            if (d->type != PEER_NONE)
    +                return d->type;
         }
    +
         return p->type;
     }
     
    @@ -123,38 +135,55 @@ neighborType(const peer * p, const request_t * request)
     static int
     peerAllowedToUse(const peer * p, request_t * request)
     {
    +
         const struct _domain_ping *d = NULL;
         int do_ping = 1;
         assert(request != NULL);
    +
         if (neighborType(p, request) == PEER_SIBLING) {
    -	if (request->flags.nocache)
    -	    return 0;
    -	if (request->flags.refresh)
    -	    return 0;
    -	if (request->flags.loopdetect)
    -	    return 0;
    -	if (request->flags.need_validation)
    -	    return 0;
    +        if (request->flags.nocache)
    +            return 0;
    +
    +        if (request->flags.refresh)
    +            return 0;
    +
    +        if (request->flags.loopdetect)
    +            return 0;
    +
    +        if (request->flags.need_validation)
    +            return 0;
         }
    +
         if (p->peer_domain == NULL && p->access == NULL)
    -	return do_ping;
    +        return do_ping;
    +
         do_ping = 0;
    +
         for (d = p->peer_domain; d; d = d->next) {
    -	if (0 == matchDomainName(request->host, d->domain)) {
    -	    do_ping = d->do_ping;
    -	    break;
    -	}
    -	do_ping = !d->do_ping;
    +        if (0 == matchDomainName(request->host, d->domain)) {
    +            do_ping = d->do_ping;
    +            break;
    +        }
    +
    +        do_ping = !d->do_ping;
         }
    +
         if (p->peer_domain && 0 == do_ping)
    -	return do_ping;
    +        return do_ping;
    +
         if (p->access == NULL)
    -	return do_ping;
    +        return do_ping;
    +
         ACLChecklist checklist;
    +
         checklist.src_addr = request->client_addr;
    +
         checklist.my_addr = request->my_addr;
    +
         checklist.my_port = request->my_port;
    +
         checklist.request = requestLink(request);
    +
     #if 0 && USE_IDENT
         /*
          * this is currently broken because 'request->user_ident' has been
    @@ -162,8 +191,10 @@ peerAllowedToUse(const peer * p, request_t * request)
          * ConnStateData here.
          */
         if (request->user_ident[0])
    -	xstrncpy(checklist.rfc931, request->user_ident, USER_IDENT_SZ);
    +        xstrncpy(checklist.rfc931, request->user_ident, USER_IDENT_SZ);
    +
     #endif
    +
         return aclCheckFast(p->access, &checklist);
     }
     
    @@ -172,28 +203,37 @@ static int
     peerWouldBePinged(const peer * p, request_t * request)
     {
         if (!peerAllowedToUse(p, request))
    -	return 0;
    +        return 0;
    +
         if (p->options.no_query)
    -	return 0;
    +        return 0;
    +
         if (p->options.background_ping && (squid_curtime - p->stats.last_query < Config.backgroundPingRate))
    -	return 0;
    +        return 0;
    +
         if (p->options.mcast_responder)
    -	return 0;
    +        return 0;
    +
         if (p->n_addresses == 0)
    -	return 0;
    +        return 0;
    +
         if (p->icp.port == 0)
    -	return 0;
    +        return 0;
    +
         /* the case below seems strange, but can happen if the
          * URL host is on the other side of a firewall */
         if (p->type == PEER_SIBLING)
    -	if (!request->flags.hierarchical)
    -	    return 0;
    +        if (!request->flags.hierarchical)
    +            return 0;
    +
         /* Ping dead peers every timeout interval */
         if (squid_curtime - p->stats.last_query > Config.Timeout.deadPeer)
    -	return 1;
    +        return 1;
    +
         if (p->icp.port == echo_port)
    -	if (!neighborUp(p))
    -	    return 0;
    +        if (!neighborUp(p))
    +            return 0;
    +
         return 1;
     }
     
    @@ -202,12 +242,15 @@ int
     peerHTTPOkay(const peer * p, request_t * request)
     {
         if (!peerAllowedToUse(p, request))
    -	return 0;
    +        return 0;
    +
         if (!neighborUp(p))
    -	return 0;
    +        return 0;
    +
         if (p->max_conn)
    -	if (p->stats.conn_open >= p->max_conn)
    -	    return 0;
    +        if (p->stats.conn_open >= p->max_conn)
    +            return 0;
    +
         return 1;
     }
     
    @@ -216,10 +259,13 @@ neighborsCount(request_t * request)
     {
         peer *p = NULL;
         int count = 0;
    +
         for (p = Config.peers; p; p = p->next)
    -	if (peerWouldBePinged(p, request))
    -	    count++;
    +        if (peerWouldBePinged(p, request))
    +            count++;
    +
         debug(15, 3) ("neighborsCount: %d\n", count);
    +
         return count;
     }
     
    @@ -229,35 +275,48 @@ getSingleParent(request_t * request)
     {
         peer *p = NULL;
         peer *q = NULL;
    +
         for (q = Config.peers; q; q = q->next) {
    -	if (!peerHTTPOkay(q, request))
    -	    continue;
    -	if (neighborType(q, request) != PEER_PARENT)
    -	    return NULL;	/* oops, found SIBLING */
    -	if (p)
    -	    return NULL;	/* oops, found second parent */
    -	p = q;
    +        if (!peerHTTPOkay(q, request))
    +            continue;
    +
    +        if (neighborType(q, request) != PEER_PARENT)
    +            return NULL;	/* oops, found SIBLING */
    +
    +        if (p)
    +            return NULL;	/* oops, found second parent */
    +
    +        p = q;
         }
    +
         if (p != NULL && !p->options.no_query)
    -	return NULL;
    +        return NULL;
    +
         debug(15, 3) ("getSingleParent: returning %s\n", p ? p->host : "NULL");
    +
         return p;
     }
    +
     #endif
     
     peer *
     getFirstUpParent(request_t * request)
     {
         peer *p = NULL;
    +
         for (p = Config.peers; p; p = p->next) {
    -	if (!neighborUp(p))
    -	    continue;
    -	if (neighborType(p, request) != PEER_PARENT)
    -	    continue;
    -	if (!peerHTTPOkay(p, request))
    -	    continue;
    -	break;
    +        if (!neighborUp(p))
    +            continue;
    +
    +        if (neighborType(p, request) != PEER_PARENT)
    +            continue;
    +
    +        if (!peerHTTPOkay(p, request))
    +            continue;
    +
    +        break;
         }
    +
         debug(15, 3) ("getFirstUpParent: returning %s\n", p ? p->host : "NULL");
         return p;
     }
    @@ -267,20 +326,28 @@ getRoundRobinParent(request_t * request)
     {
         peer *p;
         peer *q = NULL;
    +
         for (p = Config.peers; p; p = p->next) {
    -	if (!p->options.roundrobin)
    -	    continue;
    -	if (neighborType(p, request) != PEER_PARENT)
    -	    continue;
    -	if (!peerHTTPOkay(p, request))
    -	    continue;
    -	if (q && q->rr_count < p->rr_count)
    -	    continue;
    -	q = p;
    +        if (!p->options.roundrobin)
    +            continue;
    +
    +        if (neighborType(p, request) != PEER_PARENT)
    +            continue;
    +
    +        if (!peerHTTPOkay(p, request))
    +            continue;
    +
    +        if (q && q->rr_count < p->rr_count)
    +            continue;
    +
    +        q = p;
         }
    +
         if (q)
    -	q->rr_count++;
    +        q->rr_count++;
    +
         debug(15, 3) ("getRoundRobinParent: returning %s\n", q ? q->host : "NULL");
    +
         return q;
     }
     
    @@ -290,33 +357,45 @@ getWeightedRoundRobinParent(request_t * request)
         peer *p;
         peer *q = NULL;
         int weighted_rtt;
    +
         for (p = Config.peers; p; p = p->next) {
    -	if (!p->options.weighted_roundrobin)
    -	    continue;
    -	if (neighborType(p, request) != PEER_PARENT)
    -	    continue;
    -	if (!peerHTTPOkay(p, request))
    -	    continue;
    -	if (q && q->rr_count < p->rr_count)
    -	    continue;
    -	q = p;
    +        if (!p->options.weighted_roundrobin)
    +            continue;
    +
    +        if (neighborType(p, request) != PEER_PARENT)
    +            continue;
    +
    +        if (!peerHTTPOkay(p, request))
    +            continue;
    +
    +        if (q && q->rr_count < p->rr_count)
    +            continue;
    +
    +        q = p;
         }
    +
         if (q && q->rr_count > 1000000)
    -	for (p = Config.peers; p; p = p->next) {
    -	    if (!p->options.weighted_roundrobin)
    -		continue;
    -	    if (neighborType(p, request) != PEER_PARENT)
    -		continue;
    -	    p->rr_count = 0;
    -	}
    +        for (p = Config.peers; p; p = p->next) {
    +            if (!p->options.weighted_roundrobin)
    +                continue;
    +
    +            if (neighborType(p, request) != PEER_PARENT)
    +                continue;
    +
    +            p->rr_count = 0;
    +        }
    +
         if (q) {
    -	weighted_rtt = (q->stats.rtt - q->basetime) / q->weight;
    +        weighted_rtt = (q->stats.rtt - q->basetime) / q->weight;
     
    -	if (weighted_rtt < 1)
    -	    weighted_rtt = 1;
    -	q->rr_count += weighted_rtt;
    -	debug(15, 3) ("getWeightedRoundRobinParent: weighted_rtt %d\n", (int) weighted_rtt);
    +        if (weighted_rtt < 1)
    +            weighted_rtt = 1;
    +
    +        q->rr_count += weighted_rtt;
    +
    +        debug(15, 3) ("getWeightedRoundRobinParent: weighted_rtt %d\n", (int) weighted_rtt);
         }
    +
         debug(15, 3) ("getWeightedRoundRobinParent: returning %s\n", q ? q->host : "NULL");
         return q;
     }
    @@ -327,9 +406,12 @@ peerClearRR(void *data)
     {
         peer *p = (peer *)data;
         p->rr_count -= p->rr_lastcount;
    +
         if (p->rr_count < 0)
    -	p->rr_count = 0;
    +        p->rr_count = 0;
    +
         p->rr_lastcount = p->rr_count;
    +
         eventAdd("peerClearRR", peerClearRR, p, 5 * 60.0, 0);
     }
     
    @@ -337,16 +419,22 @@ peer *
     getDefaultParent(request_t * request)
     {
         peer *p = NULL;
    +
         for (p = Config.peers; p; p = p->next) {
    -	if (neighborType(p, request) != PEER_PARENT)
    -	    continue;
    -	if (!p->options.default_parent)
    -	    continue;
    -	if (!peerHTTPOkay(p, request))
    -	    continue;
    -	debug(15, 3) ("getDefaultParent: returning %s\n", p->host);
    -	return p;
    +        if (neighborType(p, request) != PEER_PARENT)
    +            continue;
    +
    +        if (!p->options.default_parent)
    +            continue;
    +
    +        if (!peerHTTPOkay(p, request))
    +            continue;
    +
    +        debug(15, 3) ("getDefaultParent: returning %s\n", p->host);
    +
    +        return p;
         }
    +
         debug(15, 3) ("getDefaultParent: returning NULL\n");
         return NULL;
     }
    @@ -361,14 +449,19 @@ peer *
     getAnyParent(request_t * request)
     {
         peer *p = NULL;
    +
         for (p = Config.peers; p; p = p->next) {
    -	if (neighborType(p, request) != PEER_PARENT)
    -	    continue;
    -	if (!peerHTTPOkay(p, request))
    -	    continue;
    -	debug(15, 3) ("getAnyParent: returning %s\n", p->host);
    -	return p;
    +        if (neighborType(p, request) != PEER_PARENT)
    +            continue;
    +
    +        if (!peerHTTPOkay(p, request))
    +            continue;
    +
    +        debug(15, 3) ("getAnyParent: returning %s\n", p->host);
    +
    +        return p;
         }
    +
         debug(15, 3) ("getAnyParent: returning NULL\n");
         return NULL;
     }
    @@ -392,80 +485,101 @@ neighborRemove(peer * target)
         peer **P = NULL;
         p = Config.peers;
         P = &Config.peers;
    +
         while (p) {
    -	if (target == p)
    -	    break;
    -	P = &p->next;
    -	p = p->next;
    +        if (target == p)
    +            break;
    +
    +        P = &p->next;
    +
    +        p = p->next;
         }
    +
         if (p) {
    -	*P = p->next;
    -	cbdataFree(p);
    -	Config.npeers--;
    +        *P = p->next;
    +        cbdataFree(p);
    +        Config.npeers--;
         }
    +
         first_ping = Config.peers;
     }
     
     void
     neighbors_init(void)
     {
    +
         struct sockaddr_in name;
    +
         socklen_t len = sizeof(struct sockaddr_in);
    +
         struct servent *sep = NULL;
         const char *me = getMyHostname();
         peer *thisPeer;
         peer *next;
         int fd = theInIcpConnection;
    +
         if (fd >= 0) {
    -	memset(&name, '\0', sizeof(struct sockaddr_in));
    -	if (getsockname(fd, (struct sockaddr *) &name, &len) < 0)
    -	    debug(15, 1) ("getsockname(%d,%p,%p) failed.\n", fd, &name, &len);
    -	for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
    -	    http_port_list *s;
    -	    next = thisPeer->next;
    -	    if (0 != strcmp(thisPeer->host, me))
    -		continue;
    -	    for (s = Config.Sockaddr.http; s; s = s->next) {
    -		if (thisPeer->http_port != ntohs(s->s.sin_port))
    -		    continue;
    -		debug(15, 1) ("WARNING: Peer looks like this host\n");
    -		debug(15, 1) ("         Ignoring %s %s/%d/%d\n",
    -		    neighborTypeStr(thisPeer), thisPeer->host, thisPeer->http_port,
    -		    thisPeer->icp.port);
    -		neighborRemove(thisPeer);
    -	    }
    -	}
    +
    +        memset(&name, '\0', sizeof(struct sockaddr_in));
    +
    +        if (getsockname(fd, (struct sockaddr *) &name, &len) < 0)
    +            debug(15, 1) ("getsockname(%d,%p,%p) failed.\n", fd, &name, &len);
    +
    +        for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
    +            http_port_list *s;
    +            next = thisPeer->next;
    +
    +            if (0 != strcmp(thisPeer->host, me))
    +                continue;
    +
    +            for (s = Config.Sockaddr.http; s; s = s->next) {
    +                if (thisPeer->http_port != ntohs(s->s.sin_port))
    +                    continue;
    +
    +                debug(15, 1) ("WARNING: Peer looks like this host\n");
    +
    +                debug(15, 1) ("         Ignoring %s %s/%d/%d\n",
    +                              neighborTypeStr(thisPeer), thisPeer->host, thisPeer->http_port,
    +                              thisPeer->icp.port);
    +
    +                neighborRemove(thisPeer);
    +            }
    +        }
         }
    +
         peerRefreshDNS((void *) 1);
    +
         if (ICP_INVALID == echo_hdr.opcode) {
    -	echo_hdr.opcode = ICP_SECHO;
    -	echo_hdr.version = ICP_VERSION_CURRENT;
    -	echo_hdr.length = 0;
    -	echo_hdr.reqnum = 0;
    -	echo_hdr.flags = 0;
    -	echo_hdr.pad = 0;
    -	echo_hdr.shostid = name.sin_addr.s_addr;
    -	sep = getservbyname("echo", "udp");
    -	echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
    +        echo_hdr.opcode = ICP_SECHO;
    +        echo_hdr.version = ICP_VERSION_CURRENT;
    +        echo_hdr.length = 0;
    +        echo_hdr.reqnum = 0;
    +        echo_hdr.flags = 0;
    +        echo_hdr.pad = 0;
    +        echo_hdr.shostid = name.sin_addr.s_addr;
    +        sep = getservbyname("echo", "udp");
    +        echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
         }
    +
         first_ping = Config.peers;
         cachemgrRegister("server_list",
    -	"Peer Cache Statistics",
    -	neighborDumpPeers, 0, 1);
    +                     "Peer Cache Statistics",
    +                     neighborDumpPeers, 0, 1);
    +
         if (theInIcpConnection >= 0) {
    -	cachemgrRegister("non_peers",
    -	    "List of Unknown sites sending ICP messages",
    -	    neighborDumpNonPeers, 0, 1);
    +        cachemgrRegister("non_peers",
    +                         "List of Unknown sites sending ICP messages",
    +                         neighborDumpNonPeers, 0, 1);
         }
     }
     
     int
     neighborsUdpPing(request_t * request,
    -    StoreEntry * entry,
    -    IRCB * callback,
    -    void *callback_data,
    -    int *exprep,
    -    int *timeout)
    +                 StoreEntry * entry,
    +                 IRCB * callback,
    +                 void *callback_data,
    +                 int *exprep,
    +                 int *timeout)
     {
         const char *url = storeUrl(entry);
         MemObject *mem = entry->mem_obj;
    @@ -480,120 +594,149 @@ neighborsUdpPing(request_t * request,
         int sibling_timeout = 0, sibling_exprep = 0;
     
         if (Config.peers == NULL)
    -	return 0;
    +        return 0;
    +
         if (theOutIcpConnection < 0)
    -	fatal("neighborsUdpPing: There is no ICP socket!");
    +        fatal("neighborsUdpPing: There is no ICP socket!");
    +
         assert(entry->swap_status == SWAPOUT_NONE);
    +
         mem->start_ping = current_time;
    +
         mem->ping_reply_callback = callback;
    +
         mem->ircb_data = callback_data;
    +
         reqnum = icpSetCacheKey((const cache_key *)entry->key);
    +
         for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
    -	if (p == NULL)
    -	    p = Config.peers;
    -	debug(15, 5) ("neighborsUdpPing: Peer %s\n", p->host);
    -	if (!peerWouldBePinged(p, request))
    -	    continue;		/* next peer */
    -	peers_pinged++;
    -	debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n",
    -	    p->host, url);
    -	if (p->type == PEER_MULTICAST)
    -	    mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
    -	debug(15, 3) ("neighborsUdpPing: key = '%s'\n", entry->getMD5Text());
    -	debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);
    +        if (p == NULL)
    +            p = Config.peers;
    +
    +        debug(15, 5) ("neighborsUdpPing: Peer %s\n", p->host);
    +
    +        if (!peerWouldBePinged(p, request))
    +            continue;		/* next peer */
    +
    +        peers_pinged++;
    +
    +        debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n",
    +                      p->host, url);
    +
    +        if (p->type == PEER_MULTICAST)
    +            mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
    +
    +        debug(15, 3) ("neighborsUdpPing: key = '%s'\n", entry->getMD5Text());
    +
    +        debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);
     
     #if USE_HTCP
    -	if (p->options.htcp) {
    -	    debug(15, 3) ("neighborsUdpPing: sending HTCP query\n");
    -	    htcpQuery(entry, request, p);
    -	} else
    +
    +        if (p->options.htcp) {
    +            debug(15, 3) ("neighborsUdpPing: sending HTCP query\n");
    +            htcpQuery(entry, request, p);
    +        } else
     #endif
    -	if (p->icp.port == echo_port) {
    -	    debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n");
    -	    echo_hdr.reqnum = reqnum;
    -	    query = _icp_common_t::createMessage(ICP_DECHO, 0, url, reqnum, 0);
    -	    icpUdpSend(theOutIcpConnection,
    -		&p->in_addr,
    -		query,
    -		LOG_ICP_QUERY,
    -		0);
    -	} else {
    -	    flags = 0;
    -	    if (Config.onoff.query_icmp)
    -		if (p->icp.version == ICP_VERSION_2)
    -		    flags |= ICP_FLAG_SRC_RTT;
    -	    query = _icp_common_t::createMessage(ICP_QUERY, flags, url, reqnum, 0);
    -	    icpUdpSend(theOutIcpConnection,
    -		&p->in_addr,
    -		query,
    -		LOG_ICP_QUERY,
    -		0);
    -	}
    -	queries_sent++;
    -
    -	p->stats.pings_sent++;
    -	if (p->type == PEER_MULTICAST) {
    -	    /*
    -	     * set a bogus last_reply time so neighborUp() never
    -	     * says a multicast peer is dead.
    -	     */
    -	    p->stats.last_reply = squid_curtime;
    -	    (*exprep) += p->mcast.n_replies_expected;
    -	} else if (neighborUp(p)) {
    -	    /* its alive, expect a reply from it */
    -	    if (neighborType(p, request) == PEER_PARENT) {
    -		parent_exprep++;
    -		parent_timeout += p->stats.rtt;
    -	    } else {
    -		sibling_exprep++;
    -		sibling_timeout += p->stats.rtt;
    -	    }
    -	} else {
    -	    /* Neighbor is dead; ping it anyway, but don't expect a reply */
    -	    /* log it once at the threshold */
    -	    if (p->stats.logged_state == PEER_ALIVE) {
    -		debug(15, 1) ("Detected DEAD %s: %s\n",
    -		    neighborTypeStr(p), p->name);
    -		p->stats.logged_state = PEER_DEAD;
    -	    }
    -	}
    -	p->stats.last_query = squid_curtime;
    -	if (p->stats.probe_start == 0)
    -	    p->stats.probe_start = squid_curtime;
    +            if (p->icp.port == echo_port) {
    +                debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n");
    +                echo_hdr.reqnum = reqnum;
    +                query = _icp_common_t::createMessage(ICP_DECHO, 0, url, reqnum, 0);
    +                icpUdpSend(theOutIcpConnection,
    +                           &p->in_addr,
    +                           query,
    +                           LOG_ICP_QUERY,
    +                           0);
    +            } else {
    +                flags = 0;
    +
    +                if (Config.onoff.query_icmp)
    +                    if (p->icp.version == ICP_VERSION_2)
    +                        flags |= ICP_FLAG_SRC_RTT;
    +
    +                query = _icp_common_t::createMessage(ICP_QUERY, flags, url, reqnum, 0);
    +
    +                icpUdpSend(theOutIcpConnection,
    +                           &p->in_addr,
    +                           query,
    +                           LOG_ICP_QUERY,
    +                           0);
    +            }
    +
    +        queries_sent++;
    +
    +        p->stats.pings_sent++;
    +
    +        if (p->type == PEER_MULTICAST) {
    +            /*
    +             * set a bogus last_reply time so neighborUp() never
    +             * says a multicast peer is dead.
    +             */
    +            p->stats.last_reply = squid_curtime;
    +            (*exprep) += p->mcast.n_replies_expected;
    +        } else if (neighborUp(p)) {
    +            /* its alive, expect a reply from it */
    +
    +            if (neighborType(p, request) == PEER_PARENT) {
    +                parent_exprep++;
    +                parent_timeout += p->stats.rtt;
    +            } else {
    +                sibling_exprep++;
    +                sibling_timeout += p->stats.rtt;
    +            }
    +        } else {
    +            /* Neighbor is dead; ping it anyway, but don't expect a reply */
    +            /* log it once at the threshold */
    +
    +            if (p->stats.logged_state == PEER_ALIVE) {
    +                debug(15, 1) ("Detected DEAD %s: %s\n",
    +                              neighborTypeStr(p), p->name);
    +                p->stats.logged_state = PEER_DEAD;
    +            }
    +        }
    +
    +        p->stats.last_query = squid_curtime;
    +
    +        if (p->stats.probe_start == 0)
    +            p->stats.probe_start = squid_curtime;
         }
    +
         if ((first_ping = first_ping->next) == NULL)
    -	first_ping = Config.peers;
    +        first_ping = Config.peers;
     
     #if ALLOW_SOURCE_PING
         /* only do source_ping if we have neighbors */
         if (Config.npeers) {
    -	const ipcache_addrs *ia = NULL;
    -	struct sockaddr_in to_addr;
    -	char *host = request->host;
    -	if (!Config.onoff.source_ping) {
    -	    debug(15, 6) ("neighborsUdpPing: Source Ping is disabled.\n");
    -	} else if ((ia = ipcache_gethostbyname(host, 0))) {
    -	    debug(15, 6) ("neighborsUdpPing: Source Ping: to %s for '%s'\n",
    -		host, url);
    -	    echo_hdr.reqnum = reqnum;
    -	    if (icmp_sock != -1) {
    -		icmpSourcePing(ia->in_addrs[ia->cur], &echo_hdr, url);
    -	    } else {
    -		to_addr.sin_family = AF_INET;
    -		to_addr.sin_addr = ia->in_addrs[ia->cur];
    -		to_addr.sin_port = htons(echo_port);
    -		query = _icp_common_t::createMessage(ICP_SECHO, 0, url, reqnum, 0);
    -		icpUdpSend(theOutIcpConnection,
    -		    &to_addr,
    -		    query,
    -		    LOG_ICP_QUERY,
    -		    0);
    -	    }
    -	} else {
    -	    debug(15, 6) ("neighborsUdpPing: Source Ping: unknown host: %s\n",
    -		host);
    -	}
    +        const ipcache_addrs *ia = NULL;
    +
    +        struct sockaddr_in to_addr;
    +        char *host = request->host;
    +
    +        if (!Config.onoff.source_ping) {
    +            debug(15, 6) ("neighborsUdpPing: Source Ping is disabled.\n");
    +        } else if ((ia = ipcache_gethostbyname(host, 0))) {
    +            debug(15, 6) ("neighborsUdpPing: Source Ping: to %s for '%s'\n",
    +                          host, url);
    +            echo_hdr.reqnum = reqnum;
    +
    +            if (icmp_sock != -1) {
    +                icmpSourcePing(ia->in_addrs[ia->cur], &echo_hdr, url);
    +            } else {
    +                to_addr.sin_family = AF_INET;
    +                to_addr.sin_addr = ia->in_addrs[ia->cur];
    +                to_addr.sin_port = htons(echo_port);
    +                query = _icp_common_t::createMessage(ICP_SECHO, 0, url, reqnum, 0);
    +                icpUdpSend(theOutIcpConnection,
    +                           &to_addr,
    +                           query,
    +                           LOG_ICP_QUERY,
    +                           0);
    +            }
    +        } else {
    +            debug(15, 6) ("neighborsUdpPing: Source Ping: unknown host: %s\n",
    +                          host);
    +        }
         }
    +
     #endif
         /*
          * How many replies to expect?
    @@ -604,21 +747,24 @@ neighborsUdpPing(request_t * request,
          * If there is a configured timeout, use it
          */
         if (Config.Timeout.icp_query)
    -	*timeout = Config.Timeout.icp_query;
    +        *timeout = Config.Timeout.icp_query;
         else {
    -	if (*exprep > 0) {
    -	    if (parent_exprep)
    -		*timeout = 2 * parent_timeout / parent_exprep;
    -	    else
    -		*timeout = 2 * sibling_timeout / sibling_exprep;
    -	} else
    -	    *timeout = 2000;	/* 2 seconds */
    -	if (Config.Timeout.icp_query_max)
    -	    if (*timeout > Config.Timeout.icp_query_max)
    -		*timeout = Config.Timeout.icp_query_max;
    -	if (*timeout < Config.Timeout.icp_query_min)
    -	    *timeout = Config.Timeout.icp_query_min;
    +        if (*exprep > 0) {
    +            if (parent_exprep)
    +                *timeout = 2 * parent_timeout / parent_exprep;
    +            else
    +                *timeout = 2 * sibling_timeout / sibling_exprep;
    +        } else
    +            *timeout = 2000;	/* 2 seconds */
    +
    +        if (Config.Timeout.icp_query_max)
    +            if (*timeout > Config.Timeout.icp_query_max)
    +                *timeout = Config.Timeout.icp_query_max;
    +
    +        if (*timeout < Config.Timeout.icp_query_min)
    +            *timeout = Config.Timeout.icp_query_min;
         }
    +
         return peers_pinged;
     }
     
    @@ -632,32 +778,40 @@ peerDigestLookup(peer * p, request_t * request)
         assert(request);
         debug(15, 5) ("peerDigestLookup: peer %s\n", p->host);
         /* does the peeer have a valid digest? */
    +
         if (!p->digest) {
    -	debug(15, 5) ("peerDigestLookup: gone!\n");
    -	return LOOKUP_NONE;
    +        debug(15, 5) ("peerDigestLookup: gone!\n");
    +        return LOOKUP_NONE;
         } else if (!peerHTTPOkay(p, request)) {
    -	debug(15, 5) ("peerDigestLookup: !peerHTTPOkay\n");
    -	return LOOKUP_NONE;
    +        debug(15, 5) ("peerDigestLookup: !peerHTTPOkay\n");
    +        return LOOKUP_NONE;
         } else if (p->digest->flags.usable) {
    -	debug(15, 5) ("peerDigestLookup: usable\n");
    -	/* fall through; put here to have common case on top */ ;
    +        debug(15, 5) ("peerDigestLookup: usable\n");
    +        /* fall through; put here to have common case on top */
    +        ;
         } else if (!p->digest->flags.needed) {
    -	debug(15, 5) ("peerDigestLookup: note need\n");
    -	peerDigestNeeded(p->digest);
    -	return LOOKUP_NONE;
    +        debug(15, 5) ("peerDigestLookup: note need\n");
    +        peerDigestNeeded(p->digest);
    +        return LOOKUP_NONE;
         } else {
    -	debug(15, 5) ("peerDigestLookup: !ready && %srequested\n",
    -	    p->digest->flags.requested ? "" : "!");
    -	return LOOKUP_NONE;
    +        debug(15, 5) ("peerDigestLookup: !ready && %srequested\n",
    +                      p->digest->flags.requested ? "" : "!");
    +        return LOOKUP_NONE;
         }
    +
         debug(15, 5) ("peerDigestLookup: OK to lookup peer %s\n", p->host);
         assert(p->digest->cd);
         /* does digest predict a hit? */
    +
         if (!cacheDigestTest(p->digest->cd, key))
    -	return LOOKUP_MISS;
    +        return LOOKUP_MISS;
    +
         debug(15, 5) ("peerDigestLookup: peer %s says HIT!\n", p->host);
    +
         return LOOKUP_HIT;
    +
     #endif
    +
         return LOOKUP_NONE;
     }
     
    @@ -667,6 +821,7 @@ neighborsDigestSelect(request_t * request)
     {
         peer *best_p = NULL;
     #if USE_CACHE_DIGESTS
    +
         const cache_key *key;
         int best_rtt = 0;
         int choice_count = 0;
    @@ -674,41 +829,57 @@ neighborsDigestSelect(request_t * request)
         peer *p;
         int p_rtt;
         int i;
    +
         if (!request->flags.hierarchical)
    -	return NULL;
    +        return NULL;
    +
         key = storeKeyPublicByRequest(request);
    +
         for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
    -	lookup_t lookup;
    -	if (!p)
    -	    p = Config.peers;
    -	if (i == 1)
    -	    first_ping = p;
    -	lookup = peerDigestLookup(p, request);
    -	if (lookup == LOOKUP_NONE)
    -	    continue;
    -	choice_count++;
    -	if (lookup == LOOKUP_MISS)
    -	    continue;
    -	p_rtt = netdbHostRtt(p->host);
    -	debug(15, 5) ("neighborsDigestSelect: peer %s rtt: %d\n",
    -	    p->host, p_rtt);
    -	/* is this peer better than others in terms of rtt ? */
    -	if (!best_p || (p_rtt && p_rtt < best_rtt)) {
    -	    best_p = p;
    -	    best_rtt = p_rtt;
    -	    if (p_rtt)		/* informative choice (aka educated guess) */
    -		ichoice_count++;
    -	    debug(15, 4) ("neighborsDigestSelect: peer %s leads with rtt %d\n",
    -		p->host, best_rtt);
    -	}
    +        lookup_t lookup;
    +
    +        if (!p)
    +            p = Config.peers;
    +
    +        if (i == 1)
    +            first_ping = p;
    +
    +        lookup = peerDigestLookup(p, request);
    +
    +        if (lookup == LOOKUP_NONE)
    +            continue;
    +
    +        choice_count++;
    +
    +        if (lookup == LOOKUP_MISS)
    +            continue;
    +
    +        p_rtt = netdbHostRtt(p->host);
    +
    +        debug(15, 5) ("neighborsDigestSelect: peer %s rtt: %d\n",
    +                      p->host, p_rtt);
    +
    +        /* is this peer better than others in terms of rtt ? */
    +        if (!best_p || (p_rtt && p_rtt < best_rtt)) {
    +            best_p = p;
    +            best_rtt = p_rtt;
    +
    +            if (p_rtt)		/* informative choice (aka educated guess) */
    +                ichoice_count++;
    +
    +            debug(15, 4) ("neighborsDigestSelect: peer %s leads with rtt %d\n",
    +                          p->host, best_rtt);
    +        }
         }
    +
         debug(15, 4) ("neighborsDigestSelect: choices: %d (%d)\n",
    -	choice_count, ichoice_count);
    +                  choice_count, ichoice_count);
         peerNoteDigestLookup(request, best_p,
    -	best_p ? LOOKUP_HIT : (choice_count ? LOOKUP_MISS : LOOKUP_NONE));
    +                         best_p ? LOOKUP_HIT : (choice_count ? LOOKUP_MISS : LOOKUP_NONE));
         request->hier.n_choices = choice_count;
         request->hier.n_ichoices = ichoice_count;
     #endif
    +
         return best_p;
     }
     
    @@ -716,13 +887,17 @@ void
     peerNoteDigestLookup(request_t * request, peer * p, lookup_t lookup)
     {
     #if USE_CACHE_DIGESTS
    +
         if (p)
    -	strncpy(request->hier.cd_host, p->host, sizeof(request->hier.cd_host));
    +        strncpy(request->hier.cd_host, p->host, sizeof(request->hier.cd_host));
         else
    -	*request->hier.cd_host = '\0';
    +        *request->hier.cd_host = '\0';
    +
         request->hier.cd_lookup = lookup;
    +
         debug(15, 4) ("peerNoteDigestLookup: peer %s, lookup: %s\n",
    -	p ? p->host : "", lookup_t_str[lookup]);
    +                  p ? p->host : "", lookup_t_str[lookup]);
    +
     #endif
     }
     
    @@ -730,15 +905,18 @@ static void
     neighborAlive(peer * p, const MemObject * mem, const icp_common_t * header)
     {
         if (p->stats.logged_state == PEER_DEAD && p->tcp_up) {
    -	debug(15, 1) ("Detected REVIVED %s: %s\n",
    -	    neighborTypeStr(p), p->name);
    -	p->stats.logged_state = PEER_ALIVE;
    +        debug(15, 1) ("Detected REVIVED %s: %s\n",
    +                      neighborTypeStr(p), p->name);
    +        p->stats.logged_state = PEER_ALIVE;
         }
    +
         p->stats.last_reply = squid_curtime;
         p->stats.probe_start = 0;
         p->stats.pings_acked++;
    +
         if ((icp_opcode) header->opcode <= ICP_END)
    -	p->icp.counts[header->opcode]++;
    +        p->icp.counts[header->opcode]++;
    +
         p->icp.version = (int) header->version;
     }
     
    @@ -746,18 +924,25 @@ static void
     neighborUpdateRtt(peer * p, MemObject * mem)
     {
         int rtt, rtt_av_factor;
    +
         if (!mem)
    -	return;
    +        return;
    +
         if (!mem->start_ping.tv_sec)
    -	return;
    +        return;
    +
         rtt = tvSubMsec(mem->start_ping, current_time);
    +
         if (rtt < 1 || rtt > 10000)
    -	return;
    +        return;
    +
         rtt_av_factor = RTT_AV_FACTOR;
    +
         if (p->options.weighted_roundrobin)
    -	rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
    +        rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
    +
         p->stats.rtt = intAverage(p->stats.rtt, rtt,
    -	p->stats.pings_acked, rtt_av_factor);
    +                              p->stats.pings_acked, rtt_av_factor);
     }
     
     #if USE_HTCP
    @@ -765,54 +950,67 @@ static void
     neighborAliveHtcp(peer * p, const MemObject * mem, const htcpReplyData * htcp)
     {
         if (p->stats.logged_state == PEER_DEAD && p->tcp_up) {
    -	debug(15, 1) ("Detected REVIVED %s: %s\n",
    -	    neighborTypeStr(p), p->name);
    -	p->stats.logged_state = PEER_ALIVE;
    +        debug(15, 1) ("Detected REVIVED %s: %s\n",
    +                      neighborTypeStr(p), p->name);
    +        p->stats.logged_state = PEER_ALIVE;
         }
    +
         p->stats.last_reply = squid_curtime;
         p->stats.probe_start = 0;
         p->stats.pings_acked++;
         p->htcp.counts[htcp->hit ? 1 : 0]++;
         p->htcp.version = htcp->version;
     }
    +
     #endif
     
     static void
     neighborCountIgnored(peer * p)
     {
         if (p == NULL)
    -	return;
    +        return;
    +
         p->stats.ignored_replies++;
    +
         NLateReplies++;
     }
     
     static peer *non_peers = NULL;
     
     static void
    +
     neighborIgnoreNonPeer(const struct sockaddr_in *from, icp_opcode opcode)
     {
         peer *np;
    -    for (np = non_peers; np; np = np->next) {
    -	if (np->in_addr.sin_addr.s_addr != from->sin_addr.s_addr)
    -	    continue;
    -	if (np->in_addr.sin_port != from->sin_port)
    -	    continue;
    -	break;
    +
    +    for (np = non_peers; np; np = np->next)
    +    {
    +        if (np->in_addr.sin_addr.s_addr != from->sin_addr.s_addr)
    +            continue;
    +
    +        if (np->in_addr.sin_port != from->sin_port)
    +            continue;
    +
    +        break;
         }
    -    if (np == NULL) {
    -	np = (peer *)xcalloc(1, sizeof(peer));
    -	np->in_addr.sin_addr = from->sin_addr;
    -	np->in_addr.sin_port = from->sin_port;
    -	np->icp.port = ntohl(from->sin_port);
    -	np->type = PEER_NONE;
    -	np->host = xstrdup(inet_ntoa(from->sin_addr));
    -	np->next = non_peers;
    -	non_peers = np;
    +
    +    if (np == NULL)
    +    {
    +        np = (peer *)xcalloc(1, sizeof(peer));
    +        np->in_addr.sin_addr = from->sin_addr;
    +        np->in_addr.sin_port = from->sin_port;
    +        np->icp.port = ntohl(from->sin_port);
    +        np->type = PEER_NONE;
    +        np->host = xstrdup(inet_ntoa(from->sin_addr));
    +        np->next = non_peers;
    +        non_peers = np;
         }
    +
         np->icp.counts[opcode]++;
    +
         if (isPowTen(++np->stats.ignored_replies))
    -	debug(15, 1) ("WARNING: Ignored %d replies from non-peer %s\n",
    -	    np->stats.ignored_replies, np->host);
    +        debug(15, 1) ("WARNING: Ignored %d replies from non-peer %s\n",
    +                      np->stats.ignored_replies, np->host);
     }
     
     /* ignoreMulticastReply
    @@ -825,11 +1023,14 @@ static int
     ignoreMulticastReply(peer * p, MemObject * mem)
     {
         if (p == NULL)
    -	return 0;
    +        return 0;
    +
         if (!p->options.mcast_responder)
    -	return 0;
    +        return 0;
    +
         if (peerHTTPOkay(p, mem->request))
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -840,6 +1041,7 @@ ignoreMulticastReply(peer * p, MemObject * mem)
      * If a hit process is already started, then sobeit
      */
     void
    +
     neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct sockaddr_in *from)
     {
         peer *p = NULL;
    @@ -850,105 +1052,134 @@ neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct socka
         icp_opcode opcode = (icp_opcode) header->opcode;
     
         debug(15, 6) ("neighborsUdpAck: opcode %d '%s'\n",
    -	(int) opcode, storeKeyText(key));
    +                  (int) opcode, storeKeyText(key));
    +
         if (NULL != (entry = storeGet(key)))
    -	mem = entry->mem_obj;
    +        mem = entry->mem_obj;
    +
         if ((p = whichPeer(from)))
    -	neighborAlive(p, mem, header);
    +        neighborAlive(p, mem, header);
    +
         if (opcode > ICP_END)
    -	return;
    +        return;
    +
         opcode_d = icp_opcode_str[opcode];
    +
         if (p)
    -	neighborUpdateRtt(p, mem);
    +        neighborUpdateRtt(p, mem);
    +
         /* Does the entry exist? */
    -    if (NULL == entry) {
    -	debug(12, 3) ("neighborsUdpAck: Cache key '%s' not found\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +    if (NULL == entry)
    +    {
    +        debug(12, 3) ("neighborsUdpAck: Cache key '%s' not found\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    +
         /* check if someone is already fetching it */
    -    if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) {
    -	debug(15, 3) ("neighborsUdpAck: '%s' already being fetched.\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +    if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED))
    +    {
    +        debug(15, 3) ("neighborsUdpAck: '%s' already being fetched.\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    -    if (mem == NULL) {
    -	debug(15, 2) ("Ignoring %s for missing mem_obj: %s\n",
    -	    opcode_d, storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +
    +    if (mem == NULL)
    +    {
    +        debug(15, 2) ("Ignoring %s for missing mem_obj: %s\n",
    +                      opcode_d, storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    -    if (entry->ping_status != PING_WAITING) {
    -	debug(15, 2) ("neighborsUdpAck: Late %s for %s\n",
    -	    opcode_d, storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +
    +    if (entry->ping_status != PING_WAITING)
    +    {
    +        debug(15, 2) ("neighborsUdpAck: Late %s for %s\n",
    +                      opcode_d, storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    -    if (entry->lock_count == 0) {
    -	debug(12, 1) ("neighborsUdpAck: '%s' has no locks\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +
    +    if (entry->lock_count == 0)
    +    {
    +        debug(12, 1) ("neighborsUdpAck: '%s' has no locks\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    +
         debug(15, 3) ("neighborsUdpAck: %s for '%s' from %s \n",
    -	opcode_d, storeKeyText(key), p ? p->host : "source");
    -    if (p) {
    -	ntype = neighborType(p, mem->request);
    +                  opcode_d, storeKeyText(key), p ? p->host : "source");
    +
    +    if (p)
    +    {
    +        ntype = neighborType(p, mem->request);
         }
    -    if (ignoreMulticastReply(p, mem)) {
    -	neighborCountIgnored(p);
    -    } else if (opcode == ICP_MISS) {
    -	if (p == NULL) {
    -	    neighborIgnoreNonPeer(from, opcode);
    -	} else {
    -	    mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    -	}
    -    } else if (opcode == ICP_HIT) {
    -	if (p == NULL) {
    -	    neighborIgnoreNonPeer(from, opcode);
    -	} else {
    -	    header->opcode = ICP_HIT;
    -	    mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    -	}
    -    } else if (opcode == ICP_DECHO) {
    -	if (p == NULL) {
    -	    neighborIgnoreNonPeer(from, opcode);
    -	} else if (ntype == PEER_SIBLING) {
    -	    debug_trap("neighborsUdpAck: Found non-ICP cache as SIBLING\n");
    -	    debug_trap("neighborsUdpAck: non-ICP neighbors must be a PARENT\n");
    -	} else {
    -	    mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    -	}
    -    } else if (opcode == ICP_SECHO) {
    -	if (p) {
    -	    debug(15, 1) ("Ignoring SECHO from neighbor %s\n", p->host);
    -	    neighborCountIgnored(p);
    +
    +    if (ignoreMulticastReply(p, mem))
    +    {
    +        neighborCountIgnored(p);
    +    } else if (opcode == ICP_MISS)
    +    {
    +        if (p == NULL) {
    +            neighborIgnoreNonPeer(from, opcode);
    +        } else {
    +            mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    +        }
    +    } else if (opcode == ICP_HIT)
    +    {
    +        if (p == NULL) {
    +            neighborIgnoreNonPeer(from, opcode);
    +        } else {
    +            header->opcode = ICP_HIT;
    +            mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    +        }
    +    } else if (opcode == ICP_DECHO)
    +    {
    +        if (p == NULL) {
    +            neighborIgnoreNonPeer(from, opcode);
    +        } else if (ntype == PEER_SIBLING) {
    +            debug_trap("neighborsUdpAck: Found non-ICP cache as SIBLING\n");
    +            debug_trap("neighborsUdpAck: non-ICP neighbors must be a PARENT\n");
    +        } else {
    +            mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    +        }
    +    } else if (opcode == ICP_SECHO)
    +    {
    +        if (p) {
    +            debug(15, 1) ("Ignoring SECHO from neighbor %s\n", p->host);
    +            neighborCountIgnored(p);
     #if ALLOW_SOURCE_PING
    -	} else if (Config.onoff.source_ping) {
    -	    mem->ping_reply_callback(NULL, ntype, PROTO_ICP, header, mem->ircb_data);
    +
    +        } else if (Config.onoff.source_ping) {
    +            mem->ping_reply_callback(NULL, ntype, PROTO_ICP, header, mem->ircb_data);
     #endif
    -	} else {
    -	    debug(15, 1) ("Unsolicited SECHO from %s\n", inet_ntoa(from->sin_addr));
    -	}
    -    } else if (opcode == ICP_DENIED) {
    -	if (p == NULL) {
    -	    neighborIgnoreNonPeer(from, opcode);
    -	} else if (p->stats.pings_acked > 100) {
    -	    if (100 * p->icp.counts[ICP_DENIED] / p->stats.pings_acked > 95) {
    -		debug(15, 0) ("95%% of replies from '%s' are UDP_DENIED\n", p->host);
    -		debug(15, 0) ("Disabling '%s', please check your configuration.\n", p->host);
    -		neighborRemove(p);
    -		p = NULL;
    -	    } else {
    -		neighborCountIgnored(p);
    -	    }
    -	}
    -    } else if (opcode == ICP_MISS_NOFETCH) {
    -	mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    -    } else {
    -	debug(15, 0) ("neighborsUdpAck: Unexpected ICP reply: %s\n", opcode_d);
    +
    +        } else {
    +            debug(15, 1) ("Unsolicited SECHO from %s\n", inet_ntoa(from->sin_addr));
    +        }
    +    } else if (opcode == ICP_DENIED)
    +    {
    +        if (p == NULL) {
    +            neighborIgnoreNonPeer(from, opcode);
    +        } else if (p->stats.pings_acked > 100) {
    +            if (100 * p->icp.counts[ICP_DENIED] / p->stats.pings_acked > 95) {
    +                debug(15, 0) ("95%% of replies from '%s' are UDP_DENIED\n", p->host);
    +                debug(15, 0) ("Disabling '%s', please check your configuration.\n", p->host);
    +                neighborRemove(p);
    +                p = NULL;
    +            } else {
    +                neighborCountIgnored(p);
    +            }
    +        }
    +    } else if (opcode == ICP_MISS_NOFETCH)
    +    {
    +        mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
    +    } else
    +    {
    +        debug(15, 0) ("neighborsUdpAck: Unexpected ICP reply: %s\n", opcode_d);
         }
     }
     
    @@ -956,10 +1187,12 @@ peer *
     peerFindByName(const char *name)
     {
         peer *p = NULL;
    +
         for (p = Config.peers; p; p = p->next) {
    -	if (!strcasecmp(name, p->name))
    -	    break;
    +        if (!strcasecmp(name, p->name))
    +            break;
         }
    +
         return p;
     }
     
    @@ -967,13 +1200,17 @@ peer *
     peerFindByNameAndPort(const char *name, unsigned short port)
     {
         peer *p = NULL;
    +
         for (p = Config.peers; p; p = p->next) {
    -	if (strcasecmp(name, p->name))
    -	    continue;
    -	if (port != p->http_port)
    -	    continue;
    -	break;
    +        if (strcasecmp(name, p->name))
    +            continue;
    +
    +        if (port != p->http_port)
    +            continue;
    +
    +        break;
         }
    +
         return p;
     }
     
    @@ -981,20 +1218,24 @@ int
     neighborUp(const peer * p)
     {
         if (!p->tcp_up) {
    -	peerProbeConnect((peer *) p);
    -	return 0;
    +        peerProbeConnect((peer *) p);
    +        return 0;
         }
    +
         if (p->options.no_query)
    -	return 1;
    +        return 1;
    +
         if (p->stats.probe_start != 0 &&
    -	squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer)
    -	return 0;
    +            squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer)
    +        return 0;
    +
         /*
          * The peer can not be UP if we don't have any IP addresses
          * for it. 
          */
         if (0 == p->n_addresses)
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -1002,19 +1243,25 @@ void
     peerDestroy(void *data)
     {
         peer *p = (peer *)data;
    +
         struct _domain_ping *l = NULL;
    +
         struct _domain_ping *nl = NULL;
    +
         if (p == NULL)
    -	return;
    +        return;
    +
         for (l = p->peer_domain; l; l = nl) {
    -	nl = l->next;
    -	safe_free(l->domain);
    -	safe_free(l);
    +        nl = l->next;
    +        safe_free(l->domain);
    +        safe_free(l);
         }
    +
         safe_free(p->host);
         safe_free(p->name);
         safe_free(p->domain);
     #if USE_CACHE_DIGESTS
    +
         cbdataReferenceDone(p->digest);
     #endif
     }
    @@ -1031,53 +1278,68 @@ static void
     peerDNSConfigure(const ipcache_addrs * ia, void *data)
     {
         peer *p = (peer *)data;
    +
         struct sockaddr_in *ap;
         int j;
    +
         if (p->n_addresses == 0) {
    -	debug(15, 1) ("Configuring %s %s/%d/%d\n", neighborTypeStr(p),
    -	    p->host, p->http_port, p->icp.port);
    -	if (p->type == PEER_MULTICAST)
    -	    debug(15, 1) ("    Multicast TTL = %d\n", p->mcast.ttl);
    +        debug(15, 1) ("Configuring %s %s/%d/%d\n", neighborTypeStr(p),
    +                      p->host, p->http_port, p->icp.port);
    +
    +        if (p->type == PEER_MULTICAST)
    +            debug(15, 1) ("    Multicast TTL = %d\n", p->mcast.ttl);
         }
    +
         p->n_addresses = 0;
    +
         if (ia == NULL) {
    -	debug(0, 0) ("WARNING: DNS lookup for '%s' failed!\n", p->host);
    -	return;
    +        debug(0, 0) ("WARNING: DNS lookup for '%s' failed!\n", p->host);
    +        return;
         }
    +
         if ((int) ia->count < 1) {
    -	debug(0, 0) ("WARNING: No IP address found for '%s'!\n", p->host);
    -	return;
    +        debug(0, 0) ("WARNING: No IP address found for '%s'!\n", p->host);
    +        return;
         }
    +
         for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) {
    -	p->addresses[j] = ia->in_addrs[j];
    -	debug(15, 2) ("--> IP address #%d: %s\n", j, inet_ntoa(p->addresses[j]));
    -	p->n_addresses++;
    +        p->addresses[j] = ia->in_addrs[j];
    +        debug(15, 2) ("--> IP address #%d: %s\n", j, inet_ntoa(p->addresses[j]));
    +        p->n_addresses++;
         }
    +
         ap = &p->in_addr;
    +
         memset(ap, '\0', sizeof(struct sockaddr_in));
         ap->sin_family = AF_INET;
         ap->sin_addr = p->addresses[0];
         ap->sin_port = htons(p->icp.port);
    +
         if (p->type == PEER_MULTICAST)
    -	peerCountMcastPeersSchedule(p, 10);
    +        peerCountMcastPeersSchedule(p, 10);
    +
         if (p->type != PEER_MULTICAST)
    -	if (!p->options.no_netdb_exchange)
    -	    eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
    +        if (!p->options.no_netdb_exchange)
    +            eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
     }
     
     static void
     peerRefreshDNS(void *data)
     {
         peer *p = NULL;
    +
         if (eventFind(peerRefreshDNS, NULL))
    -	eventDelete(peerRefreshDNS, NULL);
    +        eventDelete(peerRefreshDNS, NULL);
    +
         if (!data && 0 == stat5minClientRequests()) {
    -	/* no recent client traffic, wait a bit */
    -	eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1);
    -	return;
    +        /* no recent client traffic, wait a bit */
    +        eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1);
    +        return;
         }
    +
         for (p = Config.peers; p; p = p->next)
    -	ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
    +        ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
    +
         /* Reconfigure the peers every hour */
         eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 3600.0, 1);
     }
    @@ -1086,16 +1348,19 @@ void
     peerConnectFailed(peer * p)
     {
         p->stats.last_connect_failure = squid_curtime;
    +
         if (!p->tcp_up) {
    -	debug(15, 2) ("TCP connection to %s/%d dead\n", p->host, p->http_port);
    -	return;
    +        debug(15, 2) ("TCP connection to %s/%d dead\n", p->host, p->http_port);
    +        return;
         }
    +
         debug(15, 1) ("TCP connection to %s/%d failed\n", p->host, p->http_port);
         p->tcp_up--;
    +
         if (!p->tcp_up) {
    -	debug(15, 1) ("Detected DEAD %s: %s\n",
    -	    neighborTypeStr(p), p->name);
    -	p->stats.logged_state = PEER_DEAD;
    +        debug(15, 1) ("Detected DEAD %s: %s\n",
    +                      neighborTypeStr(p), p->name);
    +        p->stats.logged_state = PEER_DEAD;
         }
     }
     
    @@ -1103,11 +1368,12 @@ void
     peerConnectSucceded(peer * p)
     {
         if (!p->tcp_up) {
    -	debug(15, 2) ("TCP connection to %s/%d succeded\n", p->host, p->http_port);
    -	debug(15, 1) ("Detected REVIVED %s: %s\n",
    -	    neighborTypeStr(p), p->name);
    -	p->stats.logged_state = PEER_ALIVE;
    +        debug(15, 2) ("TCP connection to %s/%d succeded\n", p->host, p->http_port);
    +        debug(15, 1) ("Detected REVIVED %s: %s\n",
    +                      neighborTypeStr(p), p->name);
    +        p->stats.logged_state = PEER_ALIVE;
         }
    +
         p->tcp_up = PEER_TCP_MAGIC_COUNT;
     }
     
    @@ -1118,16 +1384,23 @@ static void
     peerProbeConnect(peer * p)
     {
         int fd;
    +
         if (p->test_fd != -1)
    -	return;			/* probe already running */
    +        return;			/* probe already running */
    +
         if (squid_curtime - p->stats.last_connect_probe < 1)
    -	return;			/* don't probe to often */
    +        return;			/* don't probe to often */
    +
         fd = comm_open(SOCK_STREAM, 0, getOutgoingAddr(NULL),
    -	0, COMM_NONBLOCKING, p->host);
    +                   0, COMM_NONBLOCKING, p->host);
    +
         if (fd < 0)
    -	return;
    +        return;
    +
         p->test_fd = fd;
    +
         p->stats.last_connect_probe = squid_curtime;
    +
         ipcache_nbgethostbyname(p->host, peerProbeConnect2, p);
     }
     
    @@ -1136,21 +1409,23 @@ peerProbeConnect2(const ipcache_addrs * ianotused, void *data)
     {
         peer *p = (peer *)data;
         commConnectStart(p->test_fd,
    -	p->host,
    -	p->http_port,
    -	peerProbeConnectDone,
    -	p);
    +                     p->host,
    +                     p->http_port,
    +                     peerProbeConnectDone,
    +                     p);
     }
     
     static void
     peerProbeConnectDone(int fd, comm_err_t status, void *data)
     {
         peer *p = (peer*)data;
    +
         if (status == COMM_OK) {
    -	peerConnectSucceded(p);
    +        peerConnectSucceded(p);
         } else {
    -	peerConnectFailed(p);
    +        peerConnectFailed(p);
         }
    +
         comm_close(fd);
         p->test_fd = -1;
         return;
    @@ -1160,11 +1435,13 @@ static void
     peerCountMcastPeersSchedule(peer * p, time_t when)
     {
         if (p->mcast.flags.count_event_pending)
    -	return;
    +        return;
    +
         eventAdd("peerCountMcastPeersStart",
    -	peerCountMcastPeersStart,
    -	p,
    -	(double) when, 1);
    +             peerCountMcastPeersStart,
    +             p,
    +             (double) when, 1);
    +
         p->mcast.flags.count_event_pending = 1;
     }
     
    @@ -1198,15 +1475,15 @@ peerCountMcastPeersStart(void *data)
         reqnum = icpSetCacheKey((const cache_key *)fake->key);
         query = _icp_common_t::createMessage(ICP_QUERY, 0, url, reqnum, 0);
         icpUdpSend(theOutIcpConnection,
    -	&p->in_addr,
    -	query,
    -	LOG_ICP_QUERY,
    -	0);
    +               &p->in_addr,
    +               query,
    +               LOG_ICP_QUERY,
    +               0);
         fake->ping_status = PING_WAITING;
         eventAdd("peerCountMcastPeersDone",
    -	peerCountMcastPeersDone,
    -	psstate,
    -	(double) Config.Timeout.mcast_icp_query, 1);
    +             peerCountMcastPeersDone,
    +             psstate,
    +             (double) Config.Timeout.mcast_icp_query, 1);
         p->mcast.flags.counting = 1;
         peerCountMcastPeersSchedule(p, MCAST_COUNT_RATE);
     }
    @@ -1219,14 +1496,14 @@ peerCountMcastPeersDone(void *data)
         StoreEntry *fake = psstate->entry;
         p->mcast.flags.counting = 0;
         p->mcast.avg_n_members = doubleAverage(p->mcast.avg_n_members,
    -	(double) psstate->ping.n_recv,
    -	++p->mcast.n_times_counted,
    -	10);
    +                                           (double) psstate->ping.n_recv,
    +                                           ++p->mcast.n_times_counted,
    +                                           10);
         debug(15, 1) ("Group %s: %d replies, %4.1f average, RTT %d\n",
    -	p->host,
    -	psstate->ping.n_recv,
    -	p->mcast.avg_n_members,
    -	p->stats.rtt);
    +                  p->host,
    +                  psstate->ping.n_recv,
    +                  p->mcast.avg_n_members,
    +                  p->stats.rtt);
         p->mcast.n_replies_expected = (int) p->mcast.avg_n_members;
         EBIT_SET(fake->flags, ENTRY_ABORTED);
         requestUnlink(fake->mem_obj->request);
    @@ -1251,8 +1528,10 @@ peerCountHandleIcpReply(peer * p, peer_t type, protocol_t proto, void *hdrnotuse
         assert(mem);
         psstate->ping.n_recv++;
         rtt_av_factor = RTT_AV_FACTOR;
    +
         if (p->options.weighted_roundrobin)
    -	rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
    +        rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
    +
         p->stats.rtt = intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
     }
     
    @@ -1272,53 +1551,80 @@ void
     dump_peer_options(StoreEntry * sentry, peer * p)
     {
         if (p->options.proxy_only)
    -	storeAppendPrintf(sentry, " proxy-only");
    +        storeAppendPrintf(sentry, " proxy-only");
    +
         if (p->options.no_query)
    -	storeAppendPrintf(sentry, " no-query");
    +        storeAppendPrintf(sentry, " no-query");
    +
         if (p->options.background_ping)
    -	storeAppendPrintf(sentry, " background-ping");
    +        storeAppendPrintf(sentry, " background-ping");
    +
         if (p->options.no_digest)
    -	storeAppendPrintf(sentry, " no-digest");
    +        storeAppendPrintf(sentry, " no-digest");
    +
         if (p->options.default_parent)
    -	storeAppendPrintf(sentry, " default");
    +        storeAppendPrintf(sentry, " default");
    +
         if (p->options.roundrobin)
    -	storeAppendPrintf(sentry, " round-robin");
    +        storeAppendPrintf(sentry, " round-robin");
    +
         if (p->options.weighted_roundrobin)
    -	storeAppendPrintf(sentry, " weighted-round-robin");
    +        storeAppendPrintf(sentry, " weighted-round-robin");
    +
         if (p->options.mcast_responder)
    -	storeAppendPrintf(sentry, " multicast-responder");
    +        storeAppendPrintf(sentry, " multicast-responder");
    +
         if (p->weight != 1)
    -	storeAppendPrintf(sentry, " weight=%d", p->weight);
    +        storeAppendPrintf(sentry, " weight=%d", p->weight);
    +
         if (p->options.closest_only)
    -	storeAppendPrintf(sentry, " closest-only");
    +        storeAppendPrintf(sentry, " closest-only");
    +
     #if USE_HTCP
    +
         if (p->options.htcp)
    -	storeAppendPrintf(sentry, " htcp");
    +        storeAppendPrintf(sentry, " htcp");
    +
     #endif
    +
         if (p->options.no_netdb_exchange)
    -	storeAppendPrintf(sentry, " no-netdb-exchange");
    +        storeAppendPrintf(sentry, " no-netdb-exchange");
    +
     #if DELAY_POOLS
    +
         if (p->options.no_delay)
    -	storeAppendPrintf(sentry, " no-delay");
    +        storeAppendPrintf(sentry, " no-delay");
    +
     #endif
    +
         if (p->login)
    -	storeAppendPrintf(sentry, " login=%s", p->login);
    +        storeAppendPrintf(sentry, " login=%s", p->login);
    +
         if (p->mcast.ttl > 0)
    -	storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl);
    +        storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl);
    +
         if (p->connect_timeout > 0)
    -	storeAppendPrintf(sentry, " connect-timeout=%d", (int) p->connect_timeout);
    +        storeAppendPrintf(sentry, " connect-timeout=%d", (int) p->connect_timeout);
    +
     #if USE_CACHE_DIGESTS
    +
         if (p->digest_url)
    -	storeAppendPrintf(sentry, " digest-url=%s", p->digest_url);
    +        storeAppendPrintf(sentry, " digest-url=%s", p->digest_url);
    +
     #endif
    +
         if (p->options.allow_miss)
    -	storeAppendPrintf(sentry, " allow-miss");
    +        storeAppendPrintf(sentry, " allow-miss");
    +
         if (p->max_conn > 0)
    -	storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
    +        storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
    +
         if (p->options.originserver)
    -	storeAppendPrintf(sentry, " originserver");
    +        storeAppendPrintf(sentry, " originserver");
    +
         if (p->domain)
    -	storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
    +        storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
    +
         storeAppendPrintf(sentry, "\n");
     }
     
    @@ -1326,90 +1632,114 @@ static void
     dump_peers(StoreEntry * sentry, peer * peers)
     {
         peer *e = NULL;
    +
         struct _domain_ping *d = NULL;
         icp_opcode op;
         int i;
    +
         if (peers == NULL)
    -	storeAppendPrintf(sentry, "There are no neighbors installed.\n");
    +        storeAppendPrintf(sentry, "There are no neighbors installed.\n");
    +
         for (e = peers; e; e = e->next) {
    -	assert(e->host != NULL);
    -	storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
    -	    neighborTypeStr(e),
    -	    e->name);
    -	storeAppendPrintf(sentry, "Host       : %s/%d/%d\n",
    -	    e->host,
    -	    e->http_port,
    -	    e->icp.port);
    -	storeAppendPrintf(sentry, "Flags      :");
    -	dump_peer_options(sentry, e);
    -	for (i = 0; i < e->n_addresses; i++) {
    -	    storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
    -		inet_ntoa(e->addresses[i]));
    -	}
    -	storeAppendPrintf(sentry, "Status     : %s\n",
    -	    neighborUp(e) ? "Up" : "Down");
    -	storeAppendPrintf(sentry, "FETCHES    : %d\n", e->stats.fetches);
    -	storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open);
    -	storeAppendPrintf(sentry, "AVG RTT    : %d msec\n", e->stats.rtt);
    -	if (!e->options.no_query) {
    -	    storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n",
    -		(int) (squid_curtime - e->stats.last_query));
    -	    if (e->stats.last_reply > 0)
    -		storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n",
    -		    (int) (squid_curtime - e->stats.last_reply));
    -	    else
    -		storeAppendPrintf(sentry, "LAST REPLY : none received\n");
    -	    storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent);
    -	    storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
    -		e->stats.pings_acked,
    -		percent(e->stats.pings_acked, e->stats.pings_sent));
    -	}
    -	storeAppendPrintf(sentry, "IGNORED    : %8d %3d%%\n",
    -	    e->stats.ignored_replies,
    -	    percent(e->stats.ignored_replies, e->stats.pings_acked));
    -	if (!e->options.no_query) {
    -	    storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
    +        assert(e->host != NULL);
    +        storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
    +                          neighborTypeStr(e),
    +                          e->name);
    +        storeAppendPrintf(sentry, "Host       : %s/%d/%d\n",
    +                          e->host,
    +                          e->http_port,
    +                          e->icp.port);
    +        storeAppendPrintf(sentry, "Flags      :");
    +        dump_peer_options(sentry, e);
    +
    +        for (i = 0; i < e->n_addresses; i++) {
    +            storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
    +                              inet_ntoa(e->addresses[i]));
    +        }
    +
    +        storeAppendPrintf(sentry, "Status     : %s\n",
    +                          neighborUp(e) ? "Up" : "Down");
    +        storeAppendPrintf(sentry, "FETCHES    : %d\n", e->stats.fetches);
    +        storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open);
    +        storeAppendPrintf(sentry, "AVG RTT    : %d msec\n", e->stats.rtt);
    +
    +        if (!e->options.no_query) {
    +            storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n",
    +                              (int) (squid_curtime - e->stats.last_query));
    +
    +            if (e->stats.last_reply > 0)
    +                storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n",
    +                                  (int) (squid_curtime - e->stats.last_reply));
    +            else
    +                storeAppendPrintf(sentry, "LAST REPLY : none received\n");
    +
    +            storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent);
    +
    +            storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
    +                              e->stats.pings_acked,
    +                              percent(e->stats.pings_acked, e->stats.pings_sent));
    +        }
    +
    +        storeAppendPrintf(sentry, "IGNORED    : %8d %3d%%\n",
    +                          e->stats.ignored_replies,
    +                          percent(e->stats.ignored_replies, e->stats.pings_acked));
    +
    +        if (!e->options.no_query) {
    +            storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
     #if USE_HTCP
    -	    if (e->options.htcp) {
    -		storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
    -		    e->htcp.counts[0],
    -		    percent(e->htcp.counts[0], e->stats.pings_acked));
    -		storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
    -		    e->htcp.counts[1],
    -		    percent(e->htcp.counts[1], e->stats.pings_acked));
    -	    } else {
    +
    +            if (e->options.htcp) {
    +                storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
    +                                  e->htcp.counts[0],
    +                                  percent(e->htcp.counts[0], e->stats.pings_acked));
    +                storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
    +                                  e->htcp.counts[1],
    +                                  percent(e->htcp.counts[1], e->stats.pings_acked));
    +            } else {
     #endif
    -		for (op = ICP_INVALID; op < ICP_END; ++op) {
    -		    if (e->icp.counts[op] == 0)
    -			continue;
    -		    storeAppendPrintf(sentry, "    %12.12s : %8d %3d%%\n",
    -			icp_opcode_str[op],
    -			e->icp.counts[op],
    -			percent(e->icp.counts[op], e->stats.pings_acked));
    -		}
    +
    +                for (op = ICP_INVALID; op < ICP_END; ++op) {
    +                    if (e->icp.counts[op] == 0)
    +                        continue;
    +
    +                    storeAppendPrintf(sentry, "    %12.12s : %8d %3d%%\n",
    +                                      icp_opcode_str[op],
    +                                      e->icp.counts[op],
    +                                      percent(e->icp.counts[op], e->stats.pings_acked));
    +                }
    +
     #if USE_HTCP
    -	    }
    +
    +            }
    +
     #endif
    -	}
    -	if (e->stats.last_connect_failure) {
    -	    storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
    -		mkhttpdlogtime(&(e->stats.last_connect_failure)));
    -	}
    -	if (e->peer_domain != NULL) {
    -	    storeAppendPrintf(sentry, "DOMAIN LIST: ");
    -	    for (d = e->peer_domain; d; d = d->next) {
    -		storeAppendPrintf(sentry, "%s%s ",
    -		    d->do_ping ? null_string : "!", d->domain);
    -	    }
    -	    storeAppendPrintf(sentry, "\n");
    -	}
    -	storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n",
    -	    percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
    +
    +        }
    +
    +        if (e->stats.last_connect_failure) {
    +            storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
    +                              mkhttpdlogtime(&(e->stats.last_connect_failure)));
    +        }
    +
    +        if (e->peer_domain != NULL) {
    +            storeAppendPrintf(sentry, "DOMAIN LIST: ");
    +
    +            for (d = e->peer_domain; d; d = d->next) {
    +                storeAppendPrintf(sentry, "%s%s ",
    +                                  d->do_ping ? null_string : "!", d->domain);
    +            }
    +
    +            storeAppendPrintf(sentry, "\n");
    +        }
    +
    +        storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n",
    +                          percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
         }
     }
     
     #if USE_HTCP
     void
    +
     neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const struct sockaddr_in *from)
     {
         StoreEntry *e = storeGet(key);
    @@ -1417,52 +1747,70 @@ neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const struct soc
         peer *p;
         peer_t ntype = PEER_NONE;
         debug(15, 6) ("neighborsHtcpReply: %s %s\n",
    -	htcp->hit ? "HIT" : "MISS", storeKeyText(key));
    +                  htcp->hit ? "HIT" : "MISS", storeKeyText(key));
    +
         if (NULL != (e = storeGet(key)))
    -	mem = e->mem_obj;
    +        mem = e->mem_obj;
    +
         if ((p = whichPeer(from)))
    -	neighborAliveHtcp(p, mem, htcp);
    +        neighborAliveHtcp(p, mem, htcp);
    +
         /* Does the entry exist? */
    -    if (NULL == e) {
    -	debug(12, 3) ("neighyborsHtcpReply: Cache key '%s' not found\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +    if (NULL == e)
    +    {
    +        debug(12, 3) ("neighyborsHtcpReply: Cache key '%s' not found\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    +
         /* check if someone is already fetching it */
    -    if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) {
    -	debug(15, 3) ("neighborsUdpAck: '%s' already being fetched.\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +    if (EBIT_TEST(e->flags, ENTRY_DISPATCHED))
    +    {
    +        debug(15, 3) ("neighborsUdpAck: '%s' already being fetched.\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    -    if (mem == NULL) {
    -	debug(15, 2) ("Ignoring reply for missing mem_obj: %s\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +
    +    if (mem == NULL)
    +    {
    +        debug(15, 2) ("Ignoring reply for missing mem_obj: %s\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    -    if (e->ping_status != PING_WAITING) {
    -	debug(15, 2) ("neighborsUdpAck: Entry %s is not PING_WAITING\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +
    +    if (e->ping_status != PING_WAITING)
    +    {
    +        debug(15, 2) ("neighborsUdpAck: Entry %s is not PING_WAITING\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    -    if (e->lock_count == 0) {
    -	debug(12, 1) ("neighborsUdpAck: '%s' has no locks\n",
    -	    storeKeyText(key));
    -	neighborCountIgnored(p);
    -	return;
    +
    +    if (e->lock_count == 0)
    +    {
    +        debug(12, 1) ("neighborsUdpAck: '%s' has no locks\n",
    +                      storeKeyText(key));
    +        neighborCountIgnored(p);
    +        return;
         }
    -    if (p) {
    -	ntype = neighborType(p, mem->request);
    -	neighborUpdateRtt(p, mem);
    +
    +    if (p)
    +    {
    +        ntype = neighborType(p, mem->request);
    +        neighborUpdateRtt(p, mem);
         }
    -    if (ignoreMulticastReply(p, mem)) {
    -	neighborCountIgnored(p);
    -	return;
    +
    +    if (ignoreMulticastReply(p, mem))
    +    {
    +        neighborCountIgnored(p);
    +        return;
         }
    +
         debug(15, 3) ("neighborsHtcpReply: e = %p\n", e);
         mem->ping_reply_callback(p, ntype, PROTO_HTCP, htcp, mem->ircb_data);
     }
    +
     #endif
    diff --git a/src/net_db.cc b/src/net_db.cc
    index 27013547e2..6afbdc799e 100644
    --- a/src/net_db.cc
    +++ b/src/net_db.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: net_db.cc,v 1.168 2003/01/23 00:37:24 robertc Exp $
    + * $Id: net_db.cc,v 1.169 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 38    Network Measurement Database
      * AUTHOR: Duane Wessels
    @@ -60,7 +60,8 @@ typedef enum {
         STATE_BODY
     } netdb_conn_state_t;
     
    -typedef struct {
    +typedef struct
    +{
         peer *p;
         StoreEntry *e;
         store_client *sc;
    @@ -70,13 +71,16 @@ typedef struct {
         char buf[NETDB_REQBUF_SZ];
         int buf_ofs;
         netdb_conn_state_t connstate;
    -} netdbExchangeState;
    +}
    +
    +netdbExchangeState;
     
     static hash_table *addr_table = NULL;
     static hash_table *host_table = NULL;
     
     static struct in_addr networkFromInaddr(struct in_addr a);
     static void netdbRelease(netdbEntry * n);
    +
     static void netdbHashInsert(netdbEntry * n, struct in_addr addr);
     static void netdbHashDelete(const char *key);
     static void netdbHostInsert(netdbEntry * n, const char *hostname);
    @@ -102,6 +106,7 @@ static void netdbExchangeDone(void *);
     static wordlist *peer_names = NULL;
     
     static void
    +
     netdbHashInsert(netdbEntry * n, struct in_addr addr)
     {
         xstrncpy(n->network, inet_ntoa(networkFromInaddr(addr)), 16);
    @@ -114,10 +119,12 @@ static void
     netdbHashDelete(const char *key)
     {
         hash_link *hptr = (hash_link *)hash_lookup(addr_table, key);
    +
         if (hptr == NULL) {
    -	debug_trap("netdbHashDelete: key not found");
    -	return;
    +        debug_trap("netdbHashDelete: key not found");
    +        return;
         }
    +
         hash_remove_link(addr_table, hptr);
     }
     
    @@ -143,12 +150,14 @@ netdbHostDelete(const net_db_name * x)
         assert(x->net_db_entry != NULL);
         n = x->net_db_entry;
         n->link_count--;
    +
         for (X = &n->hosts; *X; X = &(*X)->next) {
    -	if (*X == x) {
    -	    *X = x->next;
    -	    break;
    -	}
    +        if (*X == x) {
    +            *X = x->next;
    +            break;
    +        }
         }
    +
         hash_remove_link(host_table, (hash_link *) x);
         xfree(x->hash.key);
         memFree((void *) x, MEM_NET_DB_NAME);
    @@ -166,18 +175,21 @@ netdbRelease(netdbEntry * n)
     {
         net_db_name *x;
         net_db_name *next;
    +
         for (x = n->hosts; x; x = next) {
    -	next = x->next;
    -	netdbHostDelete(x);
    +        next = x->next;
    +        netdbHostDelete(x);
         }
    +
         n->hosts = NULL;
         safe_free(n->peers);
         n->peers = NULL;
         n->n_peers = 0;
         n->n_peers_alloc = 0;
    +
         if (n->link_count == 0) {
    -	netdbHashDelete(n->network);
    -	memFree(n, MEM_NETDBENTRY);
    +        netdbHashDelete(n->network);
    +        memFree(n, MEM_NETDBENTRY);
         }
     }
     
    @@ -186,10 +198,13 @@ netdbLRU(const void *A, const void *B)
     {
         const netdbEntry *const *n1 = (const netdbEntry *const *)A;
         const netdbEntry *const *n2 = (const netdbEntry *const *)B;
    +
         if ((*n1)->last_use_time > (*n2)->last_use_time)
    -	return (1);
    +        return (1);
    +
         if ((*n1)->last_use_time < (*n2)->last_use_time)
    -	return (-1);
    +        return (-1);
    +
         return (0);
     }
     
    @@ -203,25 +218,32 @@ netdbPurgeLRU(void)
         int removed = 0;
         list = (netdbEntry **)xcalloc(memInUse(MEM_NETDBENTRY), sizeof(netdbEntry *));
         hash_first(addr_table);
    +
         while ((n = (netdbEntry *) hash_next(addr_table))) {
    -	assert(list_count < memInUse(MEM_NETDBENTRY));
    -	*(list + list_count) = n;
    -	list_count++;
    +        assert(list_count < memInUse(MEM_NETDBENTRY));
    +        *(list + list_count) = n;
    +        list_count++;
         }
    +
         qsort((char *) list,
    -	list_count,
    -	sizeof(netdbEntry *),
    -	netdbLRU);
    +          list_count,
    +          sizeof(netdbEntry *),
    +          netdbLRU);
    +
         for (k = 0; k < list_count; k++) {
    -	if (memInUse(MEM_NETDBENTRY) < Config.Netdb.low)
    -	    break;
    -	netdbRelease(*(list + k));
    -	removed++;
    +        if (memInUse(MEM_NETDBENTRY) < Config.Netdb.low)
    +            break;
    +
    +        netdbRelease(*(list + k));
    +
    +        removed++;
         }
    +
         xfree(list);
     }
     
     static netdbEntry *
    +
     netdbLookupAddr(struct in_addr addr)
     {
         netdbEntry *n;
    @@ -231,21 +253,27 @@ netdbLookupAddr(struct in_addr addr)
     }
     
     static netdbEntry *
    +
     netdbAdd(struct in_addr addr)
     {
         netdbEntry *n;
    +
         if (memInUse(MEM_NETDBENTRY) > Config.Netdb.high)
    -	netdbPurgeLRU();
    -    if ((n = netdbLookupAddr(addr)) == NULL) {
    -	n = (netdbEntry *)memAllocate(MEM_NETDBENTRY);
    -	netdbHashInsert(n, addr);
    +        netdbPurgeLRU();
    +
    +    if ((n = netdbLookupAddr(addr)) == NULL)
    +    {
    +        n = (netdbEntry *)memAllocate(MEM_NETDBENTRY);
    +        netdbHashInsert(n, addr);
         }
    +
         return n;
     }
     
     static void
     netdbSendPing(const ipcache_addrs * ia, void *data)
     {
    +
         struct in_addr addr;
         char *hostname = (char *)((generic_cbdata *) data)->data;
         netdbEntry *n;
    @@ -253,71 +281,89 @@ netdbSendPing(const ipcache_addrs * ia, void *data)
         net_db_name *x;
         net_db_name **X;
         cbdataFree(data);
    +
         if (ia == NULL) {
    -	xfree(hostname);
    -	return;
    +        xfree(hostname);
    +        return;
         }
    +
         addr = ia->in_addrs[ia->cur];
    +
         if ((n = netdbLookupHost(hostname)) == NULL) {
    -	n = netdbAdd(addr);
    -	netdbHostInsert(n, hostname);
    +        n = netdbAdd(addr);
    +        netdbHostInsert(n, hostname);
         } else if ((na = netdbLookupAddr(addr)) != n) {
    -	/*
    -	 *hostname moved from 'network n' to 'network na'!
    -	 */
    -	if (na == NULL)
    -	    na = netdbAdd(addr);
    -	debug(38, 3) ("netdbSendPing: %s moved from %s to %s\n",
    -	    hostname, n->network, na->network);
    -	x = (net_db_name *) hash_lookup(host_table, hostname);
    -	if (x == NULL) {
    -	    debug(38, 1) ("netdbSendPing: net_db_name list bug: %s not found", hostname);
    -	    xfree(hostname);
    -	    return;
    -	}
    -	/* remove net_db_name from 'network n' linked list */
    -	for (X = &n->hosts; *X; X = &(*X)->next) {
    -	    if (*X == x) {
    -		*X = x->next;
    -		break;
    -	    }
    -	}
    -	n->link_count--;
    -	/* point to 'network na' from host entry */
    -	x->net_db_entry = na;
    -	/* link net_db_name to 'network na' */
    -	x->next = na->hosts;
    -	na->hosts = x;
    -	na->link_count++;
    -	n = na;
    +        /*
    +         *hostname moved from 'network n' to 'network na'!
    +         */
    +
    +        if (na == NULL)
    +            na = netdbAdd(addr);
    +
    +        debug(38, 3) ("netdbSendPing: %s moved from %s to %s\n",
    +                      hostname, n->network, na->network);
    +
    +        x = (net_db_name *) hash_lookup(host_table, hostname);
    +
    +        if (x == NULL) {
    +            debug(38, 1) ("netdbSendPing: net_db_name list bug: %s not found", hostname);
    +            xfree(hostname);
    +            return;
    +        }
    +
    +        /* remove net_db_name from 'network n' linked list */
    +        for (X = &n->hosts; *X; X = &(*X)->next) {
    +            if (*X == x) {
    +                *X = x->next;
    +                break;
    +            }
    +        }
    +
    +        n->link_count--;
    +        /* point to 'network na' from host entry */
    +        x->net_db_entry = na;
    +        /* link net_db_name to 'network na' */
    +        x->next = na->hosts;
    +        na->hosts = x;
    +        na->link_count++;
    +        n = na;
         }
    +
         if (n->next_ping_time <= squid_curtime) {
    -	debug(38, 3) ("netdbSendPing: pinging %s\n", hostname);
    -	icmpDomainPing(addr, hostname);
    -	n->pings_sent++;
    -	n->next_ping_time = squid_curtime + Config.Netdb.period;
    -	n->last_use_time = squid_curtime;
    +        debug(38, 3) ("netdbSendPing: pinging %s\n", hostname);
    +        icmpDomainPing(addr, hostname);
    +        n->pings_sent++;
    +        n->next_ping_time = squid_curtime + Config.Netdb.period;
    +        n->last_use_time = squid_curtime;
         }
    +
         xfree(hostname);
     }
     
     static struct in_addr
    -networkFromInaddr(struct in_addr a)
    +
    +            networkFromInaddr(struct in_addr a)
     {
    +
         struct in_addr b;
         b.s_addr = ntohl(a.s_addr);
     #if USE_CLASSFUL
    +
         if (IN_CLASSC(b.s_addr))
    -	b.s_addr &= IN_CLASSC_NET;
    +        b.s_addr &= IN_CLASSC_NET;
         else if (IN_CLASSB(b.s_addr))
    -	b.s_addr &= IN_CLASSB_NET;
    +        b.s_addr &= IN_CLASSB_NET;
         else if (IN_CLASSA(b.s_addr))
    -	b.s_addr &= IN_CLASSA_NET;
    +        b.s_addr &= IN_CLASSA_NET;
    +
     #else
         /* use /24 for everything */
         b.s_addr &= IN_CLASSC_NET;
    +
     #endif
    +
         b.s_addr = htonl(b.s_addr);
    +
         return b;
     }
     
    @@ -326,12 +372,13 @@ sortByRtt(const void *A, const void *B)
     {
         const netdbEntry *const *n1 = (const netdbEntry *const *)A;
         const netdbEntry *const *n2 = (const netdbEntry *const *)B;
    +
         if ((*n1)->rtt > (*n2)->rtt)
    -	return 1;
    +        return 1;
         else if ((*n1)->rtt < (*n2)->rtt)
    -	return -1;
    +        return -1;
         else
    -	return 0;
    +        return 0;
     }
     
     static net_db_peer *
    @@ -339,10 +386,12 @@ netdbPeerByName(const netdbEntry * n, const char *peername)
     {
         int i;
         net_db_peer *p = n->peers;
    +
         for (i = 0; i < n->n_peers; i++, p++) {
    -	if (!strcmp(p->peername, peername))
    -	    return p;
    +        if (!strcmp(p->peername, peername))
    +            return p;
         }
    +
         return NULL;
     }
     
    @@ -353,22 +402,29 @@ netdbPeerAdd(netdbEntry * n, peer * e)
         net_db_peer *o;
         int osize;
         int i;
    +
         if (n->n_peers == n->n_peers_alloc) {
    -	o = n->peers;
    -	osize = n->n_peers_alloc;
    -	if (n->n_peers_alloc == 0)
    -	    n->n_peers_alloc = 2;
    -	else
    -	    n->n_peers_alloc <<= 1;
    -	debug(38, 3) ("netdbPeerAdd: Growing peer list for '%s' to %d\n",
    -	    n->network, n->n_peers_alloc);
    -	n->peers = (net_db_peer *)xcalloc(n->n_peers_alloc, sizeof(net_db_peer));
    -	for (i = 0; i < osize; i++)
    -	    *(n->peers + i) = *(o + i);
    -	if (osize) {
    -	    safe_free(o);
    -	}
    +        o = n->peers;
    +        osize = n->n_peers_alloc;
    +
    +        if (n->n_peers_alloc == 0)
    +            n->n_peers_alloc = 2;
    +        else
    +            n->n_peers_alloc <<= 1;
    +
    +        debug(38, 3) ("netdbPeerAdd: Growing peer list for '%s' to %d\n",
    +                      n->network, n->n_peers_alloc);
    +
    +        n->peers = (net_db_peer *)xcalloc(n->n_peers_alloc, sizeof(net_db_peer));
    +
    +        for (i = 0; i < osize; i++)
    +            *(n->peers + i) = *(o + i);
    +
    +        if (osize) {
    +            safe_free(o);
    +        }
         }
    +
         p = n->peers + n->n_peers;
         p->peername = netdbPeerName(e->host);
         n->n_peers++;
    @@ -380,12 +436,13 @@ sortPeerByRtt(const void *A, const void *B)
     {
         const net_db_peer *p1 = (net_db_peer *)A;
         const net_db_peer *p2 = (net_db_peer *)B;
    +
         if (p1->rtt > p2->rtt)
    -	return 1;
    +        return 1;
         else if (p1->rtt < p2->rtt)
    -	return -1;
    +        return -1;
         else
    -	return 0;
    +        return 0;
     }
     
     static void
    @@ -395,6 +452,7 @@ netdbSaveState(void *foo)
         Logfile *lf;
         netdbEntry *n;
         net_db_name *x;
    +
         struct timeval start = current_time;
         int count = 0;
         snprintf(path, SQUID_MAXPATHLEN, "%s/netdb_state", storeSwapDir(0));
    @@ -409,32 +467,42 @@ netdbSaveState(void *foo)
          */
         unlink(path);
         lf = logfileOpen(path, 4096, 0);
    +
         if (NULL == lf) {
    -	debug(50, 1) ("netdbSaveState: %s: %s\n", path, xstrerror());
    -	return;
    +        debug(50, 1) ("netdbSaveState: %s: %s\n", path, xstrerror());
    +        return;
         }
    +
         hash_first(addr_table);
    +
         while ((n = (netdbEntry *) hash_next(addr_table))) {
    -	if (n->pings_recv == 0)
    -	    continue;
    -	logfilePrintf(lf, "%s %d %d %10.5f %10.5f %d %d",
    -	    n->network,
    -	    n->pings_sent,
    -	    n->pings_recv,
    -	    n->hops,
    -	    n->rtt,
    -	    (int) n->next_ping_time,
    -	    (int) n->last_use_time);
    -	for (x = n->hosts; x; x = x->next)
    -	    logfilePrintf(lf, " %s", hashKeyStr(&x->hash));
    -	logfilePrintf(lf, "\n");
    -	count++;
    +        if (n->pings_recv == 0)
    +            continue;
    +
    +        logfilePrintf(lf, "%s %d %d %10.5f %10.5f %d %d",
    +                      n->network,
    +                      n->pings_sent,
    +                      n->pings_recv,
    +                      n->hops,
    +                      n->rtt,
    +                      (int) n->next_ping_time,
    +                      (int) n->last_use_time);
    +
    +        for (x = n->hosts; x; x = x->next)
    +            logfilePrintf(lf, " %s", hashKeyStr(&x->hash));
    +
    +        logfilePrintf(lf, "\n");
    +
    +        count++;
    +
     #undef RBUF_SZ
    +
         }
    +
         logfileClose(lf);
         getCurrentTime();
         debug(38, 1) ("NETDB state saved; %d entries, %d msec\n",
    -	count, tvSubMsec(start, current_time));
    +                  count, tvSubMsec(start, current_time));
         eventAddIsh("netdbSaveState", netdbSaveState, NULL, 3600.0, 1);
     }
     
    @@ -445,11 +513,14 @@ netdbReloadState(void)
         char *s;
         int fd;
         int l;
    +
         struct stat sb;
         netdbEntry *n;
         netdbEntry N;
    +
         struct in_addr addr;
         int count = 0;
    +
         struct timeval start = current_time;
         snprintf(path, SQUID_MAXPATHLEN, "%s/netdb_state", storeSwapDir(0));
         /*
    @@ -458,81 +529,113 @@ netdbReloadState(void)
          * 256 FDs are open.
          */
         fd = file_open(path, O_RDONLY | O_TEXT);
    +
         if (fd < 0)
    -	return;
    +        return;
    +
         if (fstat(fd, &sb) < 0) {
    -	file_close(fd);
    -	return;
    +        file_close(fd);
    +        return;
         }
    +
         char *t;
         char *buf = (char *)xcalloc(1, sb.st_size + 1);
         t = buf;
         l = FD_READ_METHOD(fd, buf, sb.st_size);
         file_close(fd);
    +
         if (l <= 0) {
    -	safe_free (buf);
    -	return;
    +        safe_free (buf);
    +        return;
         };
    +
         while ((s = strchr(t, '\n'))) {
    -	char *q;
    -	assert(s - buf < l);
    -	*s = '\0';
    -	memset(&N, '\0', sizeof(netdbEntry));
    -	q = strtok(t, w_space);
    -	t = s + 1;
    -	if (NULL == q)
    -	    continue;
    -	if (!safe_inet_addr(q, &addr))
    -	    continue;
    -	if (netdbLookupAddr(addr) != NULL)	/* no dups! */
    -	    continue;
    -	if ((q = strtok(NULL, w_space)) == NULL)
    -	    continue;
    -	N.pings_sent = atoi(q);
    -	if ((q = strtok(NULL, w_space)) == NULL)
    -	    continue;
    -	N.pings_recv = atoi(q);
    -	if (N.pings_recv == 0)
    -	    continue;
    -	/* give this measurement low weight */
    -	N.pings_sent = 1;
    -	N.pings_recv = 1;
    -	if ((q = strtok(NULL, w_space)) == NULL)
    -	    continue;
    -	N.hops = atof(q);
    -	if ((q = strtok(NULL, w_space)) == NULL)
    -	    continue;
    -	N.rtt = atof(q);
    -	if ((q = strtok(NULL, w_space)) == NULL)
    -	    continue;
    -	N.next_ping_time = (time_t) atoi(q);
    -	if ((q = strtok(NULL, w_space)) == NULL)
    -	    continue;
    -	N.last_use_time = (time_t) atoi(q);
    -	n = (netdbEntry *)memAllocate(MEM_NETDBENTRY);
    -	xmemcpy(n, &N, sizeof(netdbEntry));
    -	netdbHashInsert(n, addr);
    -	while ((q = strtok(NULL, w_space)) != NULL) {
    -	    if (netdbLookupHost(q) != NULL)	/* no dups! */
    -		continue;
    -	    netdbHostInsert(n, q);
    -	}
    -	count++;
    +        char *q;
    +        assert(s - buf < l);
    +        *s = '\0';
    +        memset(&N, '\0', sizeof(netdbEntry));
    +        q = strtok(t, w_space);
    +        t = s + 1;
    +
    +        if (NULL == q)
    +            continue;
    +
    +        if (!safe_inet_addr(q, &addr))
    +            continue;
    +
    +        if (netdbLookupAddr(addr) != NULL)	/* no dups! */
    +            continue;
    +
    +        if ((q = strtok(NULL, w_space)) == NULL)
    +            continue;
    +
    +        N.pings_sent = atoi(q);
    +
    +        if ((q = strtok(NULL, w_space)) == NULL)
    +            continue;
    +
    +        N.pings_recv = atoi(q);
    +
    +        if (N.pings_recv == 0)
    +            continue;
    +
    +        /* give this measurement low weight */
    +        N.pings_sent = 1;
    +
    +        N.pings_recv = 1;
    +
    +        if ((q = strtok(NULL, w_space)) == NULL)
    +            continue;
    +
    +        N.hops = atof(q);
    +
    +        if ((q = strtok(NULL, w_space)) == NULL)
    +            continue;
    +
    +        N.rtt = atof(q);
    +
    +        if ((q = strtok(NULL, w_space)) == NULL)
    +            continue;
    +
    +        N.next_ping_time = (time_t) atoi(q);
    +
    +        if ((q = strtok(NULL, w_space)) == NULL)
    +            continue;
    +
    +        N.last_use_time = (time_t) atoi(q);
    +
    +        n = (netdbEntry *)memAllocate(MEM_NETDBENTRY);
    +
    +        xmemcpy(n, &N, sizeof(netdbEntry));
    +
    +        netdbHashInsert(n, addr);
    +
    +        while ((q = strtok(NULL, w_space)) != NULL) {
    +            if (netdbLookupHost(q) != NULL)	/* no dups! */
    +                continue;
    +
    +            netdbHostInsert(n, q);
    +        }
    +
    +        count++;
         }
    +
         xfree(buf);
         getCurrentTime();
         debug(38, 1) ("NETDB state reloaded; %d entries, %d msec\n",
    -	count, tvSubMsec(start, current_time));
    +                  count, tvSubMsec(start, current_time));
     }
     
     static const char *
     netdbPeerName(const char *name)
     {
         const wordlist *w;
    +
         for (w = peer_names; w; w = w->next) {
    -	if (!strcmp(w->key, name))
    -	    return w->key;
    +        if (!strcmp(w->key, name))
    +            return w->key;
         }
    +
         return wordlistAdd(&peer_names, name);
     }
     
    @@ -559,6 +662,7 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer recievedData)
         netdbExchangeState *ex = (netdbExchangeState *)data;
         int rec_sz = 0;
         off_t o;
    +
         struct in_addr addr;
         double rtt;
         double hops;
    @@ -575,19 +679,22 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer recievedData)
         rec_sz += 1 + sizeof(int);
         rec_sz += 1 + sizeof(int);
         debug(38, 3) ("netdbExchangeHandleReply: %d read bytes\n", (int) recievedData.length);
    +
         if (!cbdataReferenceValid(ex->p)) {
    -	debug(38, 3) ("netdbExchangeHandleReply: Peer became invalid\n");
    -	netdbExchangeDone(ex);
    -	return;
    +        debug(38, 3) ("netdbExchangeHandleReply: Peer became invalid\n");
    +        netdbExchangeDone(ex);
    +        return;
         }
    +
         debug(38, 3) ("netdbExchangeHandleReply: for '%s:%d'\n", ex->p->host, ex->p->http_port);
     
    -    if (recievedData.length == 0 && 
    -	!recievedData.flags.error) {
    -	debug(38, 3) ("netdbExchangeHandleReply: Done\n");
    -	netdbExchangeDone(ex);
    -	return;
    +    if (recievedData.length == 0 &&
    +            !recievedData.flags.error) {
    +        debug(38, 3) ("netdbExchangeHandleReply: Done\n");
    +        netdbExchangeDone(ex);
    +        return;
         }
    +
         p = ex->buf;
     
         /* Get the size of the buffer now */
    @@ -595,87 +702,104 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer recievedData)
         debug(38, 3) ("netdbExchangeHandleReply: %d bytes buf\n", (int) size);
     
         /* Check if we're still doing headers */
    +
         if (ex->connstate == STATE_HEADER) {
     
    -	ex->buf_ofs += recievedData.length;
    -
    -	/* skip reply headers */
    -	if ((hdr_sz = headersEnd(p, ex->buf_ofs))) {
    -	    debug(38, 5) ("netdbExchangeHandleReply: hdr_sz = %d\n", hdr_sz);
    -	    rep = ex->e->getReply();
    -	    assert (0 != rep->sline.status);
    -	    debug(38, 3) ("netdbExchangeHandleReply: reply status %d\n",
    -		rep->sline.status);
    -	    if (HTTP_OK != rep->sline.status) {
    -		netdbExchangeDone(ex);
    -		return;
    -	    }
    -	    assert((size_t)ex->buf_ofs >= hdr_sz);
    -
    -	    /*
    -	     * Now, point p to the part of the buffer where the data
    -	     * starts, and update the size accordingly
    -	     */
    -	    assert(ex->used == 0);
    -	    ex->used = hdr_sz;
    -	    size = ex->buf_ofs - hdr_sz;
    -	    p += hdr_sz;
    -
    -	    /* Finally, set the conn state mode to STATE_BODY */
    -	    ex->connstate = STATE_BODY;
    -	} else {
    -	    StoreIOBuffer tempBuffer;
    -	    tempBuffer.offset = ex->buf_ofs;
    -	    tempBuffer.length = ex->buf_sz - ex->buf_ofs;
    -	    tempBuffer.data = ex->buf + ex->buf_ofs;
    -	    /* Have more headers .. */
    -	    storeClientCopy(ex->sc, ex->e, tempBuffer,
    -		netdbExchangeHandleReply, ex);
    -	    return;
    -	}
    +        ex->buf_ofs += recievedData.length;
    +
    +        /* skip reply headers */
    +
    +        if ((hdr_sz = headersEnd(p, ex->buf_ofs))) {
    +            debug(38, 5) ("netdbExchangeHandleReply: hdr_sz = %d\n", hdr_sz);
    +            rep = ex->e->getReply();
    +            assert (0 != rep->sline.status);
    +            debug(38, 3) ("netdbExchangeHandleReply: reply status %d\n",
    +                          rep->sline.status);
    +
    +            if (HTTP_OK != rep->sline.status) {
    +                netdbExchangeDone(ex);
    +                return;
    +            }
    +
    +            assert((size_t)ex->buf_ofs >= hdr_sz);
    +
    +            /*
    +             * Now, point p to the part of the buffer where the data
    +             * starts, and update the size accordingly
    +             */
    +            assert(ex->used == 0);
    +            ex->used = hdr_sz;
    +            size = ex->buf_ofs - hdr_sz;
    +            p += hdr_sz;
    +
    +            /* Finally, set the conn state mode to STATE_BODY */
    +            ex->connstate = STATE_BODY;
    +        } else {
    +            StoreIOBuffer tempBuffer;
    +            tempBuffer.offset = ex->buf_ofs;
    +            tempBuffer.length = ex->buf_sz - ex->buf_ofs;
    +            tempBuffer.data = ex->buf + ex->buf_ofs;
    +            /* Have more headers .. */
    +            storeClientCopy(ex->sc, ex->e, tempBuffer,
    +                            netdbExchangeHandleReply, ex);
    +            return;
    +        }
         }
    +
         assert(ex->connstate == STATE_BODY);
     
         /* If we get here, we have some body to parse .. */
         debug(38, 5) ("netdbExchangeHandleReply: start parsing loop, size = %d\n",
    -	size);
    +                  size);
    +
         while (size >= rec_sz) {
    -	debug(38, 5) ("netdbExchangeHandleReply: in parsing loop, size = %d\n",
    -	    size);
    -	addr.s_addr = any_addr.s_addr;
    -	hops = rtt = 0.0;
    -	for (o = 0; o < rec_sz;) {
    -	    switch ((int) *(p + o)) {
    -	    case NETDB_EX_NETWORK:
    -		o++;
    -		xmemcpy(&addr.s_addr, p + o, sizeof(addr.s_addr));
    -		o += sizeof(addr.s_addr);
    -		break;
    -	    case NETDB_EX_RTT:
    -		o++;
    -		xmemcpy(&j, p + o, sizeof(int));
    -		o += sizeof(int);
    -		rtt = (double) ntohl(j) / 1000.0;
    -		break;
    -	    case NETDB_EX_HOPS:
    -		o++;
    -		xmemcpy(&j, p + o, sizeof(int));
    -		o += sizeof(int);
    -		hops = (double) ntohl(j) / 1000.0;
    -		break;
    -	    default:
    -		debug(38, 1) ("netdbExchangeHandleReply: corrupt data, aborting\n");
    -		netdbExchangeDone(ex);
    -		return;
    -	    }
    -	}
    -	if (addr.s_addr != any_addr.s_addr && rtt > 0)
    -	    netdbExchangeUpdatePeer(addr, ex->p, rtt, hops);
    -	assert(o == rec_sz);
    -	ex->used += rec_sz;
    -	size -= rec_sz;
    -	p += rec_sz;
    -	nused++;
    +        debug(38, 5) ("netdbExchangeHandleReply: in parsing loop, size = %d\n",
    +                      size);
    +        addr.s_addr = any_addr.s_addr;
    +        hops = rtt = 0.0;
    +
    +        for (o = 0; o < rec_sz;) {
    +            switch ((int) *(p + o)) {
    +
    +            case NETDB_EX_NETWORK:
    +                o++;
    +                xmemcpy(&addr.s_addr, p + o, sizeof(addr.s_addr));
    +                o += sizeof(addr.s_addr);
    +                break;
    +
    +            case NETDB_EX_RTT:
    +                o++;
    +                xmemcpy(&j, p + o, sizeof(int));
    +                o += sizeof(int);
    +                rtt = (double) ntohl(j) / 1000.0;
    +                break;
    +
    +            case NETDB_EX_HOPS:
    +                o++;
    +                xmemcpy(&j, p + o, sizeof(int));
    +                o += sizeof(int);
    +                hops = (double) ntohl(j) / 1000.0;
    +                break;
    +
    +            default:
    +                debug(38, 1) ("netdbExchangeHandleReply: corrupt data, aborting\n");
    +                netdbExchangeDone(ex);
    +                return;
    +            }
    +        }
    +
    +        if (addr.s_addr != any_addr.s_addr && rtt > 0)
    +            netdbExchangeUpdatePeer(addr, ex->p, rtt, hops);
    +
    +        assert(o == rec_sz);
    +
    +        ex->used += rec_sz;
    +
    +        size -= rec_sz;
    +
    +        p += rec_sz;
    +
    +        nused++;
         }
     
         /*
    @@ -689,6 +813,7 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer recievedData)
          * much data over
          */
         memmove(ex->buf, ex->buf + (ex->buf_ofs - size), size);
    +
         ex->buf_ofs = size;
     
         /*
    @@ -707,19 +832,21 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer recievedData)
         debug(38, 3) ("netdbExchangeHandleReply: size left over in this buffer: %d bytes\n", size);
     
         debug(38, 3) ("netdbExchangeHandleReply: used %d entries, (x %d bytes) == %d bytes total\n",
    -	nused, rec_sz, nused * rec_sz);
    +                  nused, rec_sz, nused * rec_sz);
    +
         debug(38, 3) ("netdbExchangeHandleReply: used %ld\n", (long int) ex->used);
    +
         if (EBIT_TEST(ex->e->flags, ENTRY_ABORTED)) {
    -	debug(38, 3) ("netdbExchangeHandleReply: ENTRY_ABORTED\n");
    -	netdbExchangeDone(ex);
    +        debug(38, 3) ("netdbExchangeHandleReply: ENTRY_ABORTED\n");
    +        netdbExchangeDone(ex);
         } else if (ex->e->store_status == STORE_PENDING) {
    -	StoreIOBuffer tempBuffer;
    -	tempBuffer.offset = ex->used;
    -	tempBuffer.length = ex->buf_sz - ex->buf_ofs;
    -	tempBuffer.data = ex->buf + ex->buf_ofs;
    -	debug(38, 3) ("netdbExchangeHandleReply: EOF not recieved\n");
    -	storeClientCopy(ex->sc, ex->e, tempBuffer,
    -	    netdbExchangeHandleReply, ex);
    +        StoreIOBuffer tempBuffer;
    +        tempBuffer.offset = ex->used;
    +        tempBuffer.length = ex->buf_sz - ex->buf_ofs;
    +        tempBuffer.data = ex->buf + ex->buf_ofs;
    +        debug(38, 3) ("netdbExchangeHandleReply: EOF not recieved\n");
    +        storeClientCopy(ex->sc, ex->e, tempBuffer,
    +                        netdbExchangeHandleReply, ex);
         }
     }
     
    @@ -744,17 +871,26 @@ netdbInit(void)
     {
     #if USE_ICMP
         int n;
    +
         if (addr_table)
    -	return;
    +        return;
    +
         n = hashPrime(Config.Netdb.high / 4);
    +
         addr_table = hash_create((HASHCMP *) strcmp, n, hash_string);
    +
         n = hashPrime(3 * Config.Netdb.high / 4);
    +
         host_table = hash_create((HASHCMP *) strcmp, n, hash_string);
    +
         eventAddIsh("netdbSaveState", netdbSaveState, NULL, 3600.0, 1);
    +
         netdbReloadState();
    +
         cachemgrRegister("netdb",
    -	"Network Measurement Database",
    -	netdbDump, 0, 1);
    +                     "Network Measurement Database",
    +                     netdbDump, 0, 1);
    +
     #endif
     }
     
    @@ -764,35 +900,49 @@ netdbPingSite(const char *hostname)
     #if USE_ICMP
         netdbEntry *n;
         generic_cbdata *h;
    +
         if ((n = netdbLookupHost(hostname)) != NULL)
    -	if (n->next_ping_time > squid_curtime)
    -	    return;
    +        if (n->next_ping_time > squid_curtime)
    +            return;
    +
         h = cbdataAlloc(generic_cbdata);
    +
         h->data = xstrdup(hostname);
    +
         ipcache_nbgethostbyname(hostname, netdbSendPing, h);
    +
     #endif
     }
     
     void
    +
     netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt)
     {
     #if USE_ICMP
         netdbEntry *n;
         int N;
         debug(38, 3) ("netdbHandlePingReply: from %s\n", inet_ntoa(from->sin_addr));
    +
         if ((n = netdbLookupAddr(from->sin_addr)) == NULL)
    -	return;
    +        return;
    +
         N = ++n->pings_recv;
    +
         if (N > 5)
    -	N = 5;
    +        N = 5;
    +
         if (rtt < 1)
    -	rtt = 1;
    +        rtt = 1;
    +
         n->hops = ((n->hops * (N - 1)) + hops) / N;
    +
         n->rtt = ((n->rtt * (N - 1)) + rtt) / N;
    +
         debug(38, 3) ("netdbHandlePingReply: %s; rtt=%5.1f  hops=%4.1f\n",
    -	n->network,
    -	n->rtt,
    -	n->hops);
    +                  n->network,
    +                  n->rtt,
    +                  n->hops);
    +
     #endif
     }
     
    @@ -812,14 +962,18 @@ netdbFreeMemory(void)
     }
     
     int
    +
     netdbHops(struct in_addr addr)
     {
     #if USE_ICMP
         netdbEntry *n = netdbLookupAddr(addr);
    -    if (n && n->pings_recv) {
    -	n->last_use_time = squid_curtime;
    -	return (int) (n->hops + 0.5);
    +
    +    if (n && n->pings_recv)
    +    {
    +        n->last_use_time = squid_curtime;
    +        return (int) (n->hops + 0.5);
         }
    +
     #endif
         return 256;
     }
    @@ -837,46 +991,56 @@ netdbDump(StoreEntry * sentry)
         net_db_peer *p;
         storeAppendPrintf(sentry, "Network DB Statistics:\n");
         storeAppendPrintf(sentry, "%-16.16s %9s %7s %5s %s\n",
    -	"Network",
    -	"recv/sent",
    -	"RTT",
    -	"Hops",
    -	"Hostnames");
    +                      "Network",
    +                      "recv/sent",
    +                      "RTT",
    +                      "Hops",
    +                      "Hostnames");
         list = (netdbEntry **)xcalloc(memInUse(MEM_NETDBENTRY), sizeof(netdbEntry *));
         i = 0;
         hash_first(addr_table);
    +
         while ((n = (netdbEntry *) hash_next(addr_table)))
    -	*(list + i++) = n;
    +        *(list + i++) = n;
    +
         if (i != memInUse(MEM_NETDBENTRY))
    -	debug(38, 0) ("WARNING: netdb_addrs count off, found %d, expected %d\n",
    -	    i, memInUse(MEM_NETDBENTRY));
    +        debug(38, 0) ("WARNING: netdb_addrs count off, found %d, expected %d\n",
    +                      i, memInUse(MEM_NETDBENTRY));
    +
         qsort((char *) list,
    -	i,
    -	sizeof(netdbEntry *),
    -	sortByRtt);
    +          i,
    +          sizeof(netdbEntry *),
    +          sortByRtt);
    +
         for (k = 0; k < i; k++) {
    -	n = *(list + k);
    -	storeAppendPrintf(sentry, "%-16.16s %4d/%4d %7.1f %5.1f",
    -	    n->network,
    -	    n->pings_recv,
    -	    n->pings_sent,
    -	    n->rtt,
    -	    n->hops);
    -	for (x = n->hosts; x; x = x->next)
    -	    storeAppendPrintf(sentry, " %s", hashKeyStr(&x->hash));
    -	storeAppendPrintf(sentry, "\n");
    -	p = n->peers;
    -	for (j = 0; j < n->n_peers; j++, p++) {
    -	    storeAppendPrintf(sentry, "    %-22.22s %7.1f %5.1f\n",
    -		p->peername,
    -		p->rtt,
    -		p->hops);
    -	}
    +        n = *(list + k);
    +        storeAppendPrintf(sentry, "%-16.16s %4d/%4d %7.1f %5.1f",
    +                          n->network,
    +                          n->pings_recv,
    +                          n->pings_sent,
    +                          n->rtt,
    +                          n->hops);
    +
    +        for (x = n->hosts; x; x = x->next)
    +            storeAppendPrintf(sentry, " %s", hashKeyStr(&x->hash));
    +
    +        storeAppendPrintf(sentry, "\n");
    +
    +        p = n->peers;
    +
    +        for (j = 0; j < n->n_peers; j++, p++) {
    +            storeAppendPrintf(sentry, "    %-22.22s %7.1f %5.1f\n",
    +                              p->peername,
    +                              p->rtt,
    +                              p->hops);
    +        }
         }
    +
         xfree(list);
     #else
    +
         storeAppendPrintf(sentry,
    -	"NETDB support not compiled into this Squid cache.\n");
    +                      "NETDB support not compiled into this Squid cache.\n");
     #endif
     }
     
    @@ -885,10 +1049,12 @@ netdbHostHops(const char *host)
     {
     #if USE_ICMP
         netdbEntry *n = netdbLookupHost(host);
    +
         if (n) {
    -	n->last_use_time = squid_curtime;
    -	return (int) (n->hops + 0.5);
    +        n->last_use_time = squid_curtime;
    +        return (int) (n->hops + 0.5);
         }
    +
     #endif
         return 0;
     }
    @@ -898,10 +1064,12 @@ netdbHostRtt(const char *host)
     {
     #if USE_ICMP
         netdbEntry *n = netdbLookupHost(host);
    +
         if (n) {
    -	n->last_use_time = squid_curtime;
    -	return (int) (n->rtt + 0.5);
    +        n->last_use_time = squid_curtime;
    +        return (int) (n->rtt + 0.5);
         }
    +
     #endif
         return 0;
     }
    @@ -911,12 +1079,18 @@ netdbHostData(const char *host, int *samp, int *rtt, int *hops)
     {
     #if USE_ICMP
         netdbEntry *n = netdbLookupHost(host);
    +
         if (n == NULL)
    -	return;
    +        return;
    +
         *samp = n->pings_recv;
    +
         *rtt = (int) (n->rtt + 0.5);
    +
         *hops = (int) (n->hops + 0.5);
    +
         n->last_use_time = squid_curtime;
    +
     #endif
     }
     
    @@ -930,59 +1104,82 @@ netdbUpdatePeer(request_t * r, peer * e, int irtt, int ihops)
         net_db_peer *p;
         debug(38, 3) ("netdbUpdatePeer: '%s', %d hops, %d rtt\n", r->host, ihops, irtt);
         n = netdbLookupHost(r->host);
    +
         if (n == NULL) {
    -	debug(38, 3) ("netdbUpdatePeer: host '%s' not found\n", r->host);
    -	return;
    +        debug(38, 3) ("netdbUpdatePeer: host '%s' not found\n", r->host);
    +        return;
         }
    +
         if ((p = netdbPeerByName(n, e->host)) == NULL)
    -	p = netdbPeerAdd(n, e);
    +        p = netdbPeerAdd(n, e);
    +
         p->rtt = rtt;
    +
         p->hops = hops;
    +
         p->expires = squid_curtime + 3600;
    +
         if (n->n_peers < 2)
    -	return;
    +        return;
    +
         qsort((char *) n->peers,
    -	n->n_peers,
    -	sizeof(net_db_peer),
    -	sortPeerByRtt);
    +          n->n_peers,
    +          sizeof(net_db_peer),
    +          sortPeerByRtt);
    +
     #endif
     }
     
     void
    +
     netdbExchangeUpdatePeer(struct in_addr addr, peer * e, double rtt, double hops)
     {
     #if USE_ICMP
         netdbEntry *n;
         net_db_peer *p;
         debug(38, 5) ("netdbExchangeUpdatePeer: '%s', %0.1f hops, %0.1f rtt\n",
    -	inet_ntoa(addr), hops, rtt);
    +                  inet_ntoa(addr), hops, rtt);
         n = netdbLookupAddr(addr);
    +
         if (n == NULL)
    -	n = netdbAdd(addr);
    +        n = netdbAdd(addr);
    +
         assert(NULL != n);
    +
         if ((p = netdbPeerByName(n, e->host)) == NULL)
    -	p = netdbPeerAdd(n, e);
    +        p = netdbPeerAdd(n, e);
    +
         p->rtt = rtt;
    +
         p->hops = hops;
    +
         p->expires = squid_curtime + 3600;	/* XXX ? */
    +
         if (n->n_peers < 2)
    -	return;
    +        return;
    +
         qsort((char *) n->peers,
    -	n->n_peers,
    -	sizeof(net_db_peer),
    -	sortPeerByRtt);
    +          n->n_peers,
    +          sizeof(net_db_peer),
    +          sortPeerByRtt);
    +
     #endif
     }
     
     void
    +
     netdbDeleteAddrNetwork(struct in_addr addr)
     {
     #if USE_ICMP
         netdbEntry *n = netdbLookupAddr(addr);
    +
         if (n == NULL)
    -	return;
    +        return;
    +
         debug(38, 3) ("netdbDeleteAddrNetwork: %s\n", n->network);
    +
         netdbRelease(n);
    +
     #endif
     }
     
    @@ -992,16 +1189,18 @@ netdbBinaryExchange(StoreEntry * s)
         http_reply *reply = httpReplyCreate();
         http_version_t version;
     #if USE_ICMP
    +
         netdbEntry *n;
         int i;
         int j;
         int rec_sz;
         char *buf;
    +
         struct in_addr addr;
         storeBuffer(s);
         httpBuildVersion(&version, 1, 0);
         httpReplySetHeaders(reply, version, HTTP_OK, "OK",
    -	NULL, -1, squid_curtime, -2);
    +                        NULL, -1, squid_curtime, -2);
         httpReplySwapOut(reply, s);
         rec_sz = 0;
         rec_sz += 1 + sizeof(addr.s_addr);
    @@ -1010,43 +1209,62 @@ netdbBinaryExchange(StoreEntry * s)
         buf = (char *)memAllocate(MEM_4K_BUF);
         i = 0;
         hash_first(addr_table);
    +
         while ((n = (netdbEntry *) hash_next(addr_table))) {
    -	if (0.0 == n->rtt)
    -	    continue;
    -	if (n->rtt > 60000)	/* RTT > 1 MIN probably bogus */
    -	    continue;
    -	if (!safe_inet_addr(n->network, &addr))
    -	    continue;
    -	buf[i++] = (char) NETDB_EX_NETWORK;
    -	xmemcpy(&buf[i], &addr.s_addr, sizeof(addr.s_addr));
    -	i += sizeof(addr.s_addr);
    -	buf[i++] = (char) NETDB_EX_RTT;
    -	j = htonl((int) (n->rtt * 1000));
    -	xmemcpy(&buf[i], &j, sizeof(int));
    -	i += sizeof(int);
    -	buf[i++] = (char) NETDB_EX_HOPS;
    -	j = htonl((int) (n->hops * 1000));
    -	xmemcpy(&buf[i], &j, sizeof(int));
    -	i += sizeof(int);
    -	if (i + rec_sz > 4096) {
    -	    storeAppend(s, buf, i);
    -	    i = 0;
    -	}
    +        if (0.0 == n->rtt)
    +            continue;
    +
    +        if (n->rtt > 60000)	/* RTT > 1 MIN probably bogus */
    +            continue;
    +
    +        if (!safe_inet_addr(n->network, &addr))
    +            continue;
    +
    +        buf[i++] = (char) NETDB_EX_NETWORK;
    +
    +        xmemcpy(&buf[i], &addr.s_addr, sizeof(addr.s_addr));
    +
    +        i += sizeof(addr.s_addr);
    +
    +        buf[i++] = (char) NETDB_EX_RTT;
    +
    +        j = htonl((int) (n->rtt * 1000));
    +
    +        xmemcpy(&buf[i], &j, sizeof(int));
    +
    +        i += sizeof(int);
    +
    +        buf[i++] = (char) NETDB_EX_HOPS;
    +
    +        j = htonl((int) (n->hops * 1000));
    +
    +        xmemcpy(&buf[i], &j, sizeof(int));
    +
    +        i += sizeof(int);
    +
    +        if (i + rec_sz > 4096) {
    +            storeAppend(s, buf, i);
    +            i = 0;
    +        }
         }
    +
         if (i > 0) {
    -	storeAppend(s, buf, i);
    -	i = 0;
    +        storeAppend(s, buf, i);
    +        i = 0;
         }
    +
         assert(0 == i);
         storeBufferFlush(s);
         memFree(buf, MEM_4K_BUF);
     #else
    +
         httpBuildVersion(&version, 1, 0);
         httpReplySetHeaders(reply, version, HTTP_BAD_REQUEST, "Bad Request",
    -	NULL, -1, squid_curtime, -2);
    +                        NULL, -1, squid_curtime, -2);
         httpReplySwapOut(reply, s);
         storeAppendPrintf(s, "NETDB support not compiled into this Squid cache.\n");
     #endif
    +
         s->complete();
     }
     
    @@ -1069,10 +1287,12 @@ netdbExchangeStart(void *data)
         debug(38, 3) ("netdbExchangeStart: Requesting '%s'\n", uri);
         assert(NULL != uri);
         ex->r = urlParse(METHOD_GET, uri);
    +
         if (NULL == ex->r) {
    -	debug(38, 1) ("netdbExchangeStart: Bad URI %s\n", uri);
    -	return;
    +        debug(38, 1) ("netdbExchangeStart: Bad URI %s\n", uri);
    +        return;
         }
    +
         requestLink(ex->r);
         assert(NULL != ex->r);
         httpBuildVersion(&ex->r->http_ver, 1, 0);
    @@ -1085,11 +1305,14 @@ netdbExchangeStart(void *data)
         tempBuffer.length = ex->buf_sz;
         tempBuffer.data = ex->buf;
         storeClientCopy(ex->sc, ex->e, tempBuffer,
    -	netdbExchangeHandleReply, ex);
    +                    netdbExchangeHandleReply, ex);
         ex->r->flags.loopdetect = 1;	/* cheat! -- force direct */
    +
         if (p->login)
    -	xstrncpy(ex->r->login, p->login, MAX_LOGIN_SZ);
    +        xstrncpy(ex->r->login, p->login, MAX_LOGIN_SZ);
    +
         fwdStart(-1, ex->e, ex->r);
    +
     #endif
     }
     
    @@ -1103,36 +1326,49 @@ netdbClosestParent(request_t * request)
         net_db_peer *h;
         int i;
         n = netdbLookupHost(request->host);
    +
         if (NULL == n) {
    -	/* try IP addr */
    -	ia = ipcache_gethostbyname(request->host, 0);
    -	if (NULL != ia)
    -	    n = netdbLookupAddr(ia->in_addrs[ia->cur]);
    +        /* try IP addr */
    +        ia = ipcache_gethostbyname(request->host, 0);
    +
    +        if (NULL != ia)
    +            n = netdbLookupAddr(ia->in_addrs[ia->cur]);
         }
    +
         if (NULL == n)
    -	return NULL;
    +        return NULL;
    +
         if (0 == n->n_peers)
    -	return NULL;
    +        return NULL;
    +
         n->last_use_time = squid_curtime;
    -    /* 
    +
    +    /*
          * Find the parent with the least RTT to the origin server.
          * Make sure we don't return a parent who is farther away than
          * we are.  Note, the n->peers list is pre-sorted by RTT.
          */
         for (i = 0; i < n->n_peers; i++) {
    -	h = &n->peers[i];
    -	if (n->rtt > 0)
    -	    if (n->rtt < h->rtt)
    -		break;
    -	p = peerFindByName(h->peername);
    -	if (NULL == p)		/* not found */
    -	    continue;
    -	if (neighborType(p, request) != PEER_PARENT)
    -	    continue;
    -	if (!peerHTTPOkay(p, request))	/* not allowed */
    -	    continue;
    -	return p;
    +        h = &n->peers[i];
    +
    +        if (n->rtt > 0)
    +            if (n->rtt < h->rtt)
    +                break;
    +
    +        p = peerFindByName(h->peername);
    +
    +        if (NULL == p)		/* not found */
    +            continue;
    +
    +        if (neighborType(p, request) != PEER_PARENT)
    +            continue;
    +
    +        if (!peerHTTPOkay(p, request))	/* not allowed */
    +            continue;
    +
    +        return p;
         }
    +
     #endif
         return NULL;
     }
    diff --git a/src/pconn.cc b/src/pconn.cc
    index 9e0e7ccbe1..96b2a734cb 100644
    --- a/src/pconn.cc
    +++ b/src/pconn.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: pconn.cc,v 1.35 2003/01/23 00:37:24 robertc Exp $
    + * $Id: pconn.cc,v 1.36 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 48    Persistent Connections
      * AUTHOR: Duane Wessels
    @@ -37,13 +37,15 @@
     #include "Store.h"
     #include "comm.h"
     
    -struct _pconn {
    +struct _pconn
    +{
         hash_link hash;		/* must be first */
         int *fds;
         int nfds_alloc;
         int nfds;
         char buf[4096];
     };
    +
     typedef struct _pconn pconn;
     
     #define PCONN_FDS_SZ	8	/* pconn set size, increase for better memcache hit rate */
    @@ -55,8 +57,11 @@ static IOCB pconnRead;
     static PF pconnTimeout;
     static const char *pconnKey(const char *host, u_short port);
     static hash_table *table = NULL;
    +
     static struct _pconn *pconnNew(const char *key);
    +
     static void pconnDelete(struct _pconn *p);
    +
     static void pconnRemoveFD(struct _pconn *p, int fd);
     static OBJH pconnHistDump;
     static MemPool *pconn_fds_pool = NULL;
    @@ -73,7 +78,7 @@ pconnKey(const char *host, u_short port)
     }
     
     static struct _pconn *
    -pconnNew(const char *key)
    +            pconnNew(const char *key)
     {
         pconn *p;
         CBDATA_INIT_TYPE(pconn);
    @@ -87,37 +92,47 @@ pconnNew(const char *key)
     }
     
     static void
    +
     pconnDelete(struct _pconn *p)
     {
         debug(48, 3) ("pconnDelete: deleting %s\n", hashKeyStr(&p->hash));
         hash_remove_link(table, (hash_link *) p);
    +
         if (p->nfds_alloc == PCONN_FDS_SZ)
    -	memPoolFree(pconn_fds_pool, p->fds);
    +        memPoolFree(pconn_fds_pool, p->fds);
         else
    -	xfree(p->fds);
    +        xfree(p->fds);
    +
         xfree(p->hash.key);
    +
         cbdataFree(p);
     }
     
     static int
    +
     pconnFindFDIndex (struct _pconn *p, int fd)
     {
         int result;
    -    for (result = 0; result < p->nfds; ++result) {
    -	if (p->fds[result] == fd)
    -	    return result;
    +
    +    for (result = 0; result < p->nfds; ++result)
    +    {
    +        if (p->fds[result] == fd)
    +            return result;
         }
    +
         return p->nfds;
     }
     
     static void
    +
     pconnRemoveFDByIndex (struct _pconn *p, int index)
     {
         for (; index < p->nfds - 1; index++)
    -	p->fds[index] = p->fds[index + 1];
    +        p->fds[index] = p->fds[index + 1];
     }
     
     static void
    +
     pconnPreventHandingOutFD(struct _pconn *p, int fd)
     {
         int i = pconnFindFDIndex (p, fd);
    @@ -127,16 +142,19 @@ pconnPreventHandingOutFD(struct _pconn *p, int fd)
     }
     
     static void
    +
     pconnRemoveFD(struct _pconn *p, int fd)
     {
         pconnPreventHandingOutFD(p, fd);
    +
         if (--p->nfds == 0)
    -	pconnDelete(p);
    +        pconnDelete(p);
     }
     
     static void
     pconnTimeout(int fd, void *data)
     {
    +
         struct _pconn *p = (_pconn *)data;
         assert(table != NULL);
         debug(48, 3) ("pconnTimeout: FD %d %s\n", fd, hashKeyStr(&p->hash));
    @@ -147,15 +165,17 @@ pconnTimeout(int fd, void *data)
     static void
     pconnRead(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
     {
    +
         struct _pconn *p = (_pconn *)data;
         assert(table != NULL);
         /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
    +
         if (flag == COMM_ERR_CLOSING) {
    -	return;
    +        return;
         }
     
         debug(48, 3) ("pconnRead: %d bytes from FD %d, %s\n", (int) len, fd,
    -	hashKeyStr(&p->hash));
    +                  hashKeyStr(&p->hash));
         pconnRemoveFD(p, fd);
         comm_close(fd);
     }
    @@ -165,27 +185,32 @@ pconnHistDump(StoreEntry * e)
     {
         int i;
         storeAppendPrintf(e,
    -	"Client-side persistent connection counts:\n"
    -	"\n"
    -	"\treq/\n"
    -	"\tconn      count\n"
    -	"\t----  ---------\n");
    +                      "Client-side persistent connection counts:\n"
    +                      "\n"
    +                      "\treq/\n"
    +                      "\tconn      count\n"
    +                      "\t----  ---------\n");
    +
         for (i = 0; i < PCONN_HIST_SZ; i++) {
    -	if (client_pconn_hist[i] == 0)
    -	    continue;
    -	storeAppendPrintf(e, "\t%4d  %9d\n", i, client_pconn_hist[i]);
    +        if (client_pconn_hist[i] == 0)
    +            continue;
    +
    +        storeAppendPrintf(e, "\t%4d  %9d\n", i, client_pconn_hist[i]);
         }
    +
         storeAppendPrintf(e,
    -	"\n"
    -	"Server-side persistent connection counts:\n"
    -	"\n"
    -	"\treq/\n"
    -	"\tconn      count\n"
    -	"\t----  ---------\n");
    +                      "\n"
    +                      "Server-side persistent connection counts:\n"
    +                      "\n"
    +                      "\treq/\n"
    +                      "\tconn      count\n"
    +                      "\t----  ---------\n");
    +
         for (i = 0; i < PCONN_HIST_SZ; i++) {
    -	if (server_pconn_hist[i] == 0)
    -	    continue;
    -	storeAppendPrintf(e, "\t%4d  %9d\n", i, server_pconn_hist[i]);
    +        if (server_pconn_hist[i] == 0)
    +            continue;
    +
    +        storeAppendPrintf(e, "\t%4d  %9d\n", i, server_pconn_hist[i]);
         }
     }
     
    @@ -198,49 +223,59 @@ pconnInit(void)
         int i;
         assert(table == NULL);
         table = hash_create((HASHCMP *) strcmp, 229, hash_string);
    +
         for (i = 0; i < PCONN_HIST_SZ; i++) {
    -	client_pconn_hist[i] = 0;
    -	server_pconn_hist[i] = 0;
    +        client_pconn_hist[i] = 0;
    +        server_pconn_hist[i] = 0;
         }
    +
         pconn_fds_pool = memPoolCreate("pconn_fds", PCONN_FDS_SZ * sizeof(int));
     
         cachemgrRegister("pconn",
    -	"Persistent Connection Utilization Histograms",
    -	pconnHistDump, 0, 1);
    +                     "Persistent Connection Utilization Histograms",
    +                     pconnHistDump, 0, 1);
         debug(48, 3) ("persistent connection module initialized\n");
     }
     
     void
     pconnPush(int fd, const char *host, u_short port)
     {
    +
         struct _pconn *p;
         int *old;
         LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10);
         LOCAL_ARRAY(char, desc, FD_DESC_SZ);
    +
         if (fdNFree() < (RESERVED_FD << 1)) {
    -	debug(48, 3) ("pconnPush: Not many unused FDs\n");
    -	comm_close(fd);
    -	return;
    +        debug(48, 3) ("pconnPush: Not many unused FDs\n");
    +        comm_close(fd);
    +        return;
         } else if (shutting_down) {
    -	comm_close(fd);
    -	return;
    +        comm_close(fd);
    +        return;
         }
    +
         assert(table != NULL);
         strcpy(key, pconnKey(host, port));
    +
         p = (struct _pconn *) hash_lookup(table, key);
    +
         if (p == NULL)
    -	p = pconnNew(key);
    +        p = pconnNew(key);
    +
         if (p->nfds == p->nfds_alloc) {
    -	debug(48, 3) ("pconnPush: growing FD array\n");
    -	p->nfds_alloc <<= 1;
    -	old = p->fds;
    -	p->fds = (int *)xmalloc(p->nfds_alloc * sizeof(int));
    -	xmemcpy(p->fds, old, p->nfds * sizeof(int));
    -	if (p->nfds == PCONN_FDS_SZ)
    -	    memPoolFree(pconn_fds_pool, old);
    -	else
    -	    xfree(old);
    +        debug(48, 3) ("pconnPush: growing FD array\n");
    +        p->nfds_alloc <<= 1;
    +        old = p->fds;
    +        p->fds = (int *)xmalloc(p->nfds_alloc * sizeof(int));
    +        xmemcpy(p->fds, old, p->nfds * sizeof(int));
    +
    +        if (p->nfds == PCONN_FDS_SZ)
    +            memPoolFree(pconn_fds_pool, old);
    +        else
    +            xfree(old);
         }
    +
         p->fds[p->nfds++] = fd;
         comm_read(fd, p->buf, BUFSIZ, pconnRead, p);
         commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p);
    @@ -262,6 +297,7 @@ pconnPush(int fd, const char *host, u_short port)
     int
     pconnPop(const char *host, u_short port)
     {
    +
         struct _pconn *p;
         hash_link *hptr;
         int fd = -1;
    @@ -269,20 +305,25 @@ pconnPop(const char *host, u_short port)
         assert(table != NULL);
         strcpy(key, pconnKey(host, port));
         hptr = (hash_link *)hash_lookup(table, key);
    +
         if (hptr != NULL) {
    -	p = (struct _pconn *) hptr;
    -	assert(p->nfds > 0);
    -	for (int i = 0; i < p->nfds; i++) {
    -	    fd = p->fds[0];
    -	    /* If there are pending read callbacks - we're about to close it, so don't issue it! */
    -	    if (!comm_has_pending_read_callback(fd)) {
    -		pconnRemoveFD(p, fd);
    -		comm_read_cancel(fd, pconnRead, p);
    -		commSetTimeout(fd, -1, NULL, NULL);
    -		return fd;
    -	    }
    -	}
    +
    +        p = (struct _pconn *) hptr;
    +        assert(p->nfds > 0);
    +
    +        for (int i = 0; i < p->nfds; i++) {
    +            fd = p->fds[0];
    +            /* If there are pending read callbacks - we're about to close it, so don't issue it! */
    +
    +            if (!comm_has_pending_read_callback(fd)) {
    +                pconnRemoveFD(p, fd);
    +                comm_read_cancel(fd, pconnRead, p);
    +                commSetTimeout(fd, -1, NULL, NULL);
    +                return fd;
    +            }
    +        }
         }
    +
         /* Nothing (valid!) found */
         return fd;
     }
    @@ -291,12 +332,13 @@ void
     pconnHistCount(int what, int i)
     {
         if (i >= PCONN_HIST_SZ)
    -	i = PCONN_HIST_SZ - 1;
    +        i = PCONN_HIST_SZ - 1;
    +
         /* what == 0 for client, 1 for server */
         if (what == 0)
    -	client_pconn_hist[i]++;
    +        client_pconn_hist[i]++;
         else if (what == 1)
    -	server_pconn_hist[i]++;
    +        server_pconn_hist[i]++;
         else
    -	assert(0);
    +        assert(0);
     }
    diff --git a/src/peer_digest.cc b/src/peer_digest.cc
    index d4897133d4..5c3be4da0c 100644
    --- a/src/peer_digest.cc
    +++ b/src/peer_digest.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: peer_digest.cc,v 1.94 2003/01/23 00:37:24 robertc Exp $
    + * $Id: peer_digest.cc,v 1.95 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 72    Peer Digest Routines
      * AUTHOR: Alex Rousskov
    @@ -98,8 +98,10 @@ static void
     peerDigestClean(PeerDigest * pd)
     {
         assert(pd);
    +
         if (pd->cd)
    -	cacheDigestDestroy(pd->cd);
    +        cacheDigestDestroy(pd->cd);
    +
         pd->host.clean();
     }
     
    @@ -128,10 +130,12 @@ peerDigestDestroy(PeerDigest * pd)
         assert(pd);
     
         /* inform peer (if any) that we are gone */
    +
         if (cbdataReferenceValidDone(pd->peer, (void **) &p))
    -	peerNoteDigestGone(p);
    +        peerNoteDigestGone(p);
     
         peerDigestClean(pd);
    +
         cbdataFree(pd);
     }
     
    @@ -155,17 +159,19 @@ static void
     peerDigestDisable(PeerDigest * pd)
     {
         debug(72, 2) ("peerDigestDisable: peer %s disabled for good\n",
    -	pd->host.buf());
    +                  pd->host.buf());
         pd->times.disabled = squid_curtime;
         pd->times.next_check = -1;	/* never */
         pd->flags.usable = 0;
     
         if (pd->cd) {
    -	cacheDigestDestroy(pd->cd);
    -	pd->cd = NULL;
    +        cacheDigestDestroy(pd->cd);
    +        pd->cd = NULL;
         }
    +
         /* we do not destroy the pd itself to preserve its "history" and stats */
     }
    +
     #endif
     
     /* increment retry delay [after an unsuccessful attempt] */
    @@ -174,18 +180,20 @@ peerDigestIncDelay(const PeerDigest * pd)
     {
         assert(pd);
         return pd->times.retry_delay > 0 ?
    -	2 * pd->times.retry_delay :	/* exponential backoff */
    -	PeerDigestReqMinGap;	/* minimal delay */
    +           2 * pd->times.retry_delay :	/* exponential backoff */
    +           PeerDigestReqMinGap;	/* minimal delay */
     }
     
    -/* artificially increases Expires: setting to avoid race conditions 
    +/* artificially increases Expires: setting to avoid race conditions
      * returns the delay till that [increased] expiration time */
     static time_t
     peerDigestNewDelay(const StoreEntry * e)
     {
         assert(e);
    +
         if (e->expires > 0)
    -	return e->expires + PeerDigestReqMinGap - squid_curtime;
    +        return e->expires + PeerDigestReqMinGap - squid_curtime;
    +
         return PeerDigestReqMinGap;
     }
     
    @@ -196,7 +204,7 @@ peerDigestSetCheck(PeerDigest * pd, time_t delay)
         eventAdd("peerDigestCheck", peerDigestCheck, pd, (double) delay, 1);
         pd->times.next_check = squid_curtime + delay;
         debug(72, 3) ("peerDigestSetCheck: will check peer %s in %d secs\n",
    -	pd->host.buf(), (int) delay);
    +                  pd->host.buf(), (int) delay);
     }
     
     /*
    @@ -206,13 +214,13 @@ void
     peerDigestNotePeerGone(PeerDigest * pd)
     {
         if (pd->flags.requested) {
    -	debug(72, 2) ("peerDigest: peer %s gone, will destroy after fetch.\n",
    -	    pd->host.buf());
    -	/* do nothing now, the fetching chain will notice and take action */
    +        debug(72, 2) ("peerDigest: peer %s gone, will destroy after fetch.\n",
    +                      pd->host.buf());
    +        /* do nothing now, the fetching chain will notice and take action */
         } else {
    -	debug(72, 2) ("peerDigest: peer %s is gone, destroying now.\n",
    -	    pd->host.buf());
    -	peerDigestDestroy(pd);
    +        debug(72, 2) ("peerDigest: peer %s is gone, destroying now.\n",
    +                      pd->host.buf());
    +        peerDigestDestroy(pd);
         }
     }
     
    @@ -230,35 +238,39 @@ peerDigestCheck(void *data)
         pd->times.next_check = 0;	/* unknown */
     
         if (!cbdataReferenceValid(pd->peer)) {
    -	peerDigestNotePeerGone(pd);
    -	return;
    +        peerDigestNotePeerGone(pd);
    +        return;
         }
    +
         debug(72, 3) ("peerDigestCheck: peer %s:%d\n", pd->peer->host, pd->peer->http_port);
         debug(72, 3) ("peerDigestCheck: time: %ld, last received: %ld (%+d)\n",
    -	(long int) squid_curtime, (long int) pd->times.received, (int) (squid_curtime - pd->times.received));
    +                  (long int) squid_curtime, (long int) pd->times.received, (int) (squid_curtime - pd->times.received));
     
         /* decide when we should send the request:
          * request now unless too close to other requests */
         req_time = squid_curtime;
     
         /* per-peer limit */
    +
         if (req_time - pd->times.received < PeerDigestReqMinGap) {
    -	debug(72, 2) ("peerDigestCheck: %s, avoiding close peer requests (%d < %d secs).\n",
    -	    pd->host.buf(), (int) (req_time - pd->times.received),
    -	    (int) PeerDigestReqMinGap);
    -	req_time = pd->times.received + PeerDigestReqMinGap;
    +        debug(72, 2) ("peerDigestCheck: %s, avoiding close peer requests (%d < %d secs).\n",
    +                      pd->host.buf(), (int) (req_time - pd->times.received),
    +                      (int) PeerDigestReqMinGap);
    +        req_time = pd->times.received + PeerDigestReqMinGap;
         }
    +
         /* global limit */
         if (req_time - pd_last_req_time < GlobDigestReqMinGap) {
    -	debug(72, 2) ("peerDigestCheck: %s, avoiding close requests (%d < %d secs).\n",
    -	    pd->host.buf(), (int) (req_time - pd_last_req_time),
    -	    (int) GlobDigestReqMinGap);
    -	req_time = pd_last_req_time + GlobDigestReqMinGap;
    +        debug(72, 2) ("peerDigestCheck: %s, avoiding close requests (%d < %d secs).\n",
    +                      pd->host.buf(), (int) (req_time - pd_last_req_time),
    +                      (int) GlobDigestReqMinGap);
    +        req_time = pd_last_req_time + GlobDigestReqMinGap;
         }
    +
         if (req_time <= squid_curtime)
    -	peerDigestRequest(pd);	/* will set pd->flags.requested */
    +        peerDigestRequest(pd);	/* will set pd->flags.requested */
         else
    -	peerDigestSetCheck(pd, req_time - squid_curtime);
    +        peerDigestSetCheck(pd, req_time - squid_curtime);
     }
     
     CBDATA_TYPE(DigestFetchState);
    @@ -279,61 +291,86 @@ peerDigestRequest(PeerDigest * pd)
         pd->flags.requested = 1;
     
         /* compute future request components */
    +
         if (p->digest_url)
    -	url = xstrdup(p->digest_url);
    +        url = xstrdup(p->digest_url);
         else
    -	url = internalRemoteUri(p->host, p->http_port,
    -	    "/squid-internal-periodic/", StoreDigestFileName);
    +        url = internalRemoteUri(p->host, p->http_port,
    +                                "/squid-internal-periodic/", StoreDigestFileName);
     
         req = urlParse(METHOD_GET, url);
    +
         assert(req);
    +
         key = storeKeyPublicByRequest(req);
    +
         debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
     
         /* add custom headers */
         assert(!req->header.len);
    +
         httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr);
    +
         httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html");
    +
         if (p->login)
    -	xstrncpy(req->login, p->login, MAX_LOGIN_SZ);
    +        xstrncpy(req->login, p->login, MAX_LOGIN_SZ);
    +
         /* create fetch state structure */
         CBDATA_INIT_TYPE(DigestFetchState);
    +
         fetch = cbdataAlloc(DigestFetchState);
    +
         fetch->request = requestLink(req);
    +
         fetch->pd = cbdataReference(pd);
    +
         fetch->offset = 0;
    +
         fetch->state = DIGEST_READ_REPLY;
     
         /* update timestamps */
         fetch->start_time = squid_curtime;
    +
         pd->times.requested = squid_curtime;
    +
         pd_last_req_time = squid_curtime;
     
         req->flags.cachable = 1;
    +
         /* the rest is based on clientProcessExpired() */
         req->flags.refresh = 1;
    +
         old_e = fetch->old_entry = storeGet(key);
    +
         if (old_e) {
    -	debug(72, 5) ("peerDigestRequest: found old entry\n");
    -	storeLockObject(old_e);
    -	storeCreateMemObject(old_e, url, url);
    -	fetch->old_sc = storeClientListAdd(old_e, fetch);
    +        debug(72, 5) ("peerDigestRequest: found old entry\n");
    +        storeLockObject(old_e);
    +        storeCreateMemObject(old_e, url, url);
    +        fetch->old_sc = storeClientListAdd(old_e, fetch);
         }
    +
         e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method);
         assert(EBIT_TEST(e->flags, KEY_PRIVATE));
         fetch->sc = storeClientListAdd(e, fetch);
         /* set lastmod to trigger IMS request if possible */
    +
         if (old_e)
    -	e->lastmod = old_e->lastmod;
    +        e->lastmod = old_e->lastmod;
     
         /* push towards peer cache */
         debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n");
    +
         fwdStart(-1, e, req);
    +
         tempBuffer.offset = 0;
    +
         tempBuffer.length = SM_PAGE_SIZE;
    +
         tempBuffer.data = fetch->buf;
    +
         storeClientCopy(fetch->sc, e, tempBuffer,
    -	peerDigestHandleReply, fetch);
    +                    peerDigestHandleReply, fetch);
     }
     
     
    @@ -366,8 +403,9 @@ peerDigestHandleReply(void *data, StoreIOBuffer recievedData)
         assert(fetch->bufofs <= SM_PAGE_SIZE);
     
         /* If we've fetched enough, return */
    +
         if (peerDigestFetchedEnough(fetch, fetch->buf, fetch->bufofs, "peerDigestHandleReply"))
    -	return;
    +        return;
     
         /* Call the right function based on the state */
         /* (Those functions will update the state if needed) */
    @@ -381,39 +419,50 @@ peerDigestHandleReply(void *data, StoreIOBuffer recievedData)
         /* Repeat this loop until we're out of data OR the state changes */
         /* (So keep going if the state has changed and we still have data */
         do {
    -	prevstate = fetch->state;
    -	switch (fetch->state) {
    -	case DIGEST_READ_REPLY:
    -	    retsize = peerDigestFetchReply(fetch, fetch->buf, fetch->bufofs);
    -	    break;
    -	case DIGEST_READ_HEADERS:
    -	    retsize = peerDigestSwapInHeaders(fetch, fetch->buf, fetch->bufofs);
    -	    break;
    -	case DIGEST_READ_CBLOCK:
    -	    retsize = peerDigestSwapInCBlock(fetch, fetch->buf, fetch->bufofs);
    -	    break;
    -	case DIGEST_READ_MASK:
    -	    retsize = peerDigestSwapInMask(fetch, fetch->buf, fetch->bufofs);
    -	    break;
    -	case DIGEST_READ_NONE:
    -	    break;
    -	case DIGEST_READ_DONE:
    -	    goto finish;
    -	    break;
    -	default:
    -	    fatal("Bad digest transfer mode!\n");
    -	}
    -
    -	if (retsize < 0)
    -	    goto finish;
    -	/*
    -	 * The returned size indicates how much of the buffer was read -
    -	 * so move the remainder of the buffer to the beginning
    -	 * and update the bufofs / bufsize
    -	 */
    -	newsize = fetch->bufofs - retsize;
    -	xmemmove(fetch->buf, fetch->buf + retsize, fetch->bufofs - newsize);
    -	fetch->bufofs = newsize;
    +        prevstate = fetch->state;
    +
    +        switch (fetch->state) {
    +
    +        case DIGEST_READ_REPLY:
    +            retsize = peerDigestFetchReply(fetch, fetch->buf, fetch->bufofs);
    +            break;
    +
    +        case DIGEST_READ_HEADERS:
    +            retsize = peerDigestSwapInHeaders(fetch, fetch->buf, fetch->bufofs);
    +            break;
    +
    +        case DIGEST_READ_CBLOCK:
    +            retsize = peerDigestSwapInCBlock(fetch, fetch->buf, fetch->bufofs);
    +            break;
    +
    +        case DIGEST_READ_MASK:
    +            retsize = peerDigestSwapInMask(fetch, fetch->buf, fetch->bufofs);
    +            break;
    +
    +        case DIGEST_READ_NONE:
    +            break;
    +
    +        case DIGEST_READ_DONE:
    +            goto finish;
    +            break;
    +
    +        default:
    +            fatal("Bad digest transfer mode!\n");
    +        }
    +
    +        if (retsize < 0)
    +            goto finish;
    +
    +        /*
    +         * The returned size indicates how much of the buffer was read -
    +         * so move the remainder of the buffer to the beginning
    +         * and update the bufofs / bufsize
    +         */
    +        newsize = fetch->bufofs - retsize;
    +
    +        xmemmove(fetch->buf, fetch->buf + retsize, fetch->bufofs - newsize);
    +
    +        fetch->bufofs = newsize;
     
         } while (cbdataReferenceValid(fetch) && prevstate != fetch->state && fetch->bufofs > 0);
     
    @@ -422,14 +471,15 @@ peerDigestHandleReply(void *data, StoreIOBuffer recievedData)
     
         /* Schedule another copy */
         if (cbdataReferenceValid(fetch)) {
    -	StoreIOBuffer tempBuffer;
    -	tempBuffer.offset = fetch->offset;
    -	tempBuffer.length = SM_PAGE_SIZE - fetch->bufofs;
    -	tempBuffer.data = fetch->buf + fetch->bufofs;
    -	storeClientCopy(fetch->sc, fetch->entry, tempBuffer,
    -	    peerDigestHandleReply, fetch);
    +        StoreIOBuffer tempBuffer;
    +        tempBuffer.offset = fetch->offset;
    +        tempBuffer.length = SM_PAGE_SIZE - fetch->bufofs;
    +        tempBuffer.data = fetch->buf + fetch->bufofs;
    +        storeClientCopy(fetch->sc, fetch->entry, tempBuffer,
    +                        peerDigestHandleReply, fetch);
         }
    -  finish:
    +
    +finish:
         /* Get rid of our reference, we've finished with it for now */
         cbdataReferenceDone(fetch);
     }
    @@ -453,64 +503,78 @@ peerDigestFetchReply(void *data, char *buf, ssize_t size)
         assert(!fetch->offset);
     
         assert(fetch->state == DIGEST_READ_REPLY);
    +
         if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestFetchReply"))
    -	return -1;
    +        return -1;
     
         if ((hdr_size = headersEnd(buf, size))) {
    -	http_status status;
    -	HttpReply const *reply = fetch->entry->getReply();
    -	assert(reply);
    -	assert (reply->sline.status != 0);
    -	status = reply->sline.status;
    -	debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %ld (%+d)\n",
    -	    pd->host.buf(), status,
    -	    (long int) reply->expires, (int) (reply->expires - squid_curtime));
    -
    -	/* this "if" is based on clientHandleIMSReply() */
    -	if (status == HTTP_NOT_MODIFIED) {
    -	    request_t *r = NULL;
    -	    /* our old entry is fine */
    -	    assert(fetch->old_entry);
    -	    if (!fetch->old_entry->mem_obj->request)
    -		fetch->old_entry->mem_obj->request = r =
    -		    requestLink(fetch->entry->mem_obj->request);
    -	    assert(fetch->old_entry->mem_obj->request);
    -	    httpReplyUpdateOnNotModified((HttpReply *)fetch->old_entry->getReply(), reply);
    -	    storeTimestampsSet(fetch->old_entry);
    -	    /* get rid of 304 reply */
    -	    storeUnregister(fetch->sc, fetch->entry, fetch);
    -	    storeUnlockObject(fetch->entry);
    -	    fetch->entry = fetch->old_entry;
    -	    fetch->old_entry = NULL;
    -	    /* preserve request -- we need its size to update counters */
    -	    /* requestUnlink(r); */
    -	    /* fetch->entry->mem_obj->request = NULL; */
    -	} else if (status == HTTP_OK) {
    -	    /* get rid of old entry if any */
    -	    if (fetch->old_entry) {
    -		debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n");
    -		storeUnregister(fetch->old_sc, fetch->old_entry, fetch);
    -		storeReleaseRequest(fetch->old_entry);
    -		storeUnlockObject(fetch->old_entry);
    -		fetch->old_entry = NULL;
    -	    }
    -	} else {
    -	    /* some kind of a bug */
    -	    peerDigestFetchAbort(fetch, buf, httpStatusLineReason(&reply->sline));
    -	    return -1;		/* XXX -1 will abort stuff in ReadReply! */
    -	}
    -	/* must have a ready-to-use store entry if we got here */
    -	/* can we stay with the old in-memory digest? */
    -	if (status == HTTP_NOT_MODIFIED && fetch->pd->cd) {
    -	    peerDigestFetchStop(fetch, buf, "Not modified");
    -	    fetch->state = DIGEST_READ_DONE;
    -	} else {
    -	    fetch->state = DIGEST_READ_HEADERS;
    -	}
    +        http_status status;
    +        HttpReply const *reply = fetch->entry->getReply();
    +        assert(reply);
    +        assert (reply->sline.status != 0);
    +        status = reply->sline.status;
    +        debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %ld (%+d)\n",
    +                      pd->host.buf(), status,
    +                      (long int) reply->expires, (int) (reply->expires - squid_curtime));
    +
    +        /* this "if" is based on clientHandleIMSReply() */
    +
    +        if (status == HTTP_NOT_MODIFIED) {
    +            request_t *r = NULL;
    +            /* our old entry is fine */
    +            assert(fetch->old_entry);
    +
    +            if (!fetch->old_entry->mem_obj->request)
    +                fetch->old_entry->mem_obj->request = r =
    +                                                         requestLink(fetch->entry->mem_obj->request);
    +
    +            assert(fetch->old_entry->mem_obj->request);
    +
    +            httpReplyUpdateOnNotModified((HttpReply *)fetch->old_entry->getReply(), reply);
    +
    +            storeTimestampsSet(fetch->old_entry);
    +
    +            /* get rid of 304 reply */
    +            storeUnregister(fetch->sc, fetch->entry, fetch);
    +
    +            storeUnlockObject(fetch->entry);
    +
    +            fetch->entry = fetch->old_entry;
    +
    +            fetch->old_entry = NULL;
    +
    +            /* preserve request -- we need its size to update counters */
    +            /* requestUnlink(r); */
    +            /* fetch->entry->mem_obj->request = NULL; */
    +        } else if (status == HTTP_OK) {
    +            /* get rid of old entry if any */
    +
    +            if (fetch->old_entry) {
    +                debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n");
    +                storeUnregister(fetch->old_sc, fetch->old_entry, fetch);
    +                storeReleaseRequest(fetch->old_entry);
    +                storeUnlockObject(fetch->old_entry);
    +                fetch->old_entry = NULL;
    +            }
    +        } else {
    +            /* some kind of a bug */
    +            peerDigestFetchAbort(fetch, buf, httpStatusLineReason(&reply->sline));
    +            return -1;		/* XXX -1 will abort stuff in ReadReply! */
    +        }
    +
    +        /* must have a ready-to-use store entry if we got here */
    +        /* can we stay with the old in-memory digest? */
    +        if (status == HTTP_NOT_MODIFIED && fetch->pd->cd) {
    +            peerDigestFetchStop(fetch, buf, "Not modified");
    +            fetch->state = DIGEST_READ_DONE;
    +        } else {
    +            fetch->state = DIGEST_READ_HEADERS;
    +        }
         } else {
    -	/* need more data, do we have space? */
    -	if (size >= SM_PAGE_SIZE)
    -	    peerDigestFetchAbort(fetch, buf, "reply header too big");
    +        /* need more data, do we have space? */
    +
    +        if (size >= SM_PAGE_SIZE)
    +            peerDigestFetchAbort(fetch, buf, "reply header too big");
         }
     
         /* We don't want to actually ack that we've handled anything,
    @@ -526,30 +590,36 @@ peerDigestSwapInHeaders(void *data, char *buf, ssize_t size)
         size_t hdr_size;
     
         assert(fetch->state == DIGEST_READ_HEADERS);
    +
         if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestSwapInHeaders"))
    -	return -1;
    +        return -1;
     
         assert(!fetch->offset);
    +
         if ((hdr_size = headersEnd(buf, size))) {
    -	assert(fetch->entry->getReply());
    -	assert (fetch->entry->getReply()->sline.status != 0);
    -	if (fetch->entry->getReply()->sline.status != HTTP_OK) {
    -	    debug(72, 1) ("peerDigestSwapInHeaders: %s status %d got cached!\n",
    -		fetch->pd->host.buf(), fetch->entry->getReply()->sline.status);
    -	    peerDigestFetchAbort(fetch, buf, "internal status error");
    -	    return -1;
    -	}
    -	fetch->state = DIGEST_READ_CBLOCK;
    -	return hdr_size;	/* Say how much data we read */
    +        assert(fetch->entry->getReply());
    +        assert (fetch->entry->getReply()->sline.status != 0);
    +
    +        if (fetch->entry->getReply()->sline.status != HTTP_OK) {
    +            debug(72, 1) ("peerDigestSwapInHeaders: %s status %d got cached!\n",
    +                          fetch->pd->host.buf(), fetch->entry->getReply()->sline.status);
    +            peerDigestFetchAbort(fetch, buf, "internal status error");
    +            return -1;
    +        }
    +
    +        fetch->state = DIGEST_READ_CBLOCK;
    +        return hdr_size;	/* Say how much data we read */
         } else {
    -	/* need more data, do we have space? */
    -	if (size >= SM_PAGE_SIZE) {
    -	    peerDigestFetchAbort(fetch, buf, "stored header too big");
    -	    return -1;
    -	} else {
    -	    return 0;		/* We need to read more to parse .. */
    -	}
    +        /* need more data, do we have space? */
    +
    +        if (size >= SM_PAGE_SIZE) {
    +            peerDigestFetchAbort(fetch, buf, "stored header too big");
    +            return -1;
    +        } else {
    +            return 0;		/* We need to read more to parse .. */
    +        }
         }
    +
         fatal("peerDigestSwapInHeaders() - shouldn't get here!\n");
     }
     
    @@ -559,34 +629,38 @@ peerDigestSwapInCBlock(void *data, char *buf, ssize_t size)
         DigestFetchState *fetch = (DigestFetchState *)data;
     
         assert(fetch->state == DIGEST_READ_CBLOCK);
    +
         if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestSwapInCBlock"))
    -	return -1;
    +        return -1;
     
         if (size >= (ssize_t)StoreDigestCBlockSize) {
    -	PeerDigest *pd = fetch->pd;
    -	HttpReply const *rep = fetch->entry->getReply();
    -
    -	assert(pd && rep);
    -	if (peerDigestSetCBlock(pd, buf)) {
    -	    /* XXX: soon we will have variable header size */
    -	    /* switch to CD buffer and fetch digest guts */
    -	    buf = NULL;
    -	    assert(pd->cd->mask);
    -	    fetch->state = DIGEST_READ_MASK;
    -	    return StoreDigestCBlockSize;
    -	} else {
    -	    peerDigestFetchAbort(fetch, buf, "invalid digest cblock");
    -	    return -1;
    -	}
    +        PeerDigest *pd = fetch->pd;
    +        HttpReply const *rep = fetch->entry->getReply();
    +
    +        assert(pd && rep);
    +
    +        if (peerDigestSetCBlock(pd, buf)) {
    +            /* XXX: soon we will have variable header size */
    +            /* switch to CD buffer and fetch digest guts */
    +            buf = NULL;
    +            assert(pd->cd->mask);
    +            fetch->state = DIGEST_READ_MASK;
    +            return StoreDigestCBlockSize;
    +        } else {
    +            peerDigestFetchAbort(fetch, buf, "invalid digest cblock");
    +            return -1;
    +        }
         } else {
    -	/* need more data, do we have space? */
    -	if (size >= SM_PAGE_SIZE) {
    -	    peerDigestFetchAbort(fetch, buf, "digest cblock too big");
    -	    return -1;
    -	} else {
    -	    return 0;		/* We need more data */
    -	}
    +        /* need more data, do we have space? */
    +
    +        if (size >= SM_PAGE_SIZE) {
    +            peerDigestFetchAbort(fetch, buf, "digest cblock too big");
    +            return -1;
    +        } else {
    +            return 0;		/* We need more data */
    +        }
         }
    +
         fatal("peerDigestSwapInCBlock(): shouldn't get here!\n");
     }
     
    @@ -606,20 +680,23 @@ peerDigestSwapInMask(void *data, char *buf, ssize_t size)
         xmemcpy(pd->cd->mask + fetch->mask_offset, buf, size);
     
         /* NOTE! buf points to the middle of pd->cd->mask! */
    +
         if (peerDigestFetchedEnough(fetch, NULL, size, "peerDigestSwapInMask"))
    -	return -1;
    +        return -1;
     
         fetch->mask_offset += size;
    +
         if (fetch->mask_offset >= (off_t)pd->cd->mask_size) {
    -	debug(72, 2) ("peerDigestSwapInMask: Done! Got %d, expected %d\n",
    -	    fetch->mask_offset, pd->cd->mask_size);
    -	assert(fetch->mask_offset == (off_t)pd->cd->mask_size);
    -	assert(peerDigestFetchedEnough(fetch, NULL, 0, "peerDigestSwapInMask"));
    -	return -1;		/* XXX! */
    +        debug(72, 2) ("peerDigestSwapInMask: Done! Got %d, expected %d\n",
    +                      fetch->mask_offset, pd->cd->mask_size);
    +        assert(fetch->mask_offset == (off_t)pd->cd->mask_size);
    +        assert(peerDigestFetchedEnough(fetch, NULL, 0, "peerDigestSwapInMask"));
    +        return -1;		/* XXX! */
         } else {
    -	/* We always read everything, so return so */
    -	return size;
    +        /* We always read everything, so return so */
    +        return size;
         }
    +
         fatal("peerDigestSwapInMask(): shouldn't get here!\n");
     }
     
    @@ -637,52 +714,61 @@ peerDigestFetchedEnough(DigestFetchState * fetch, char *buf, ssize_t size, const
          * cases marked with '?!' should not happen */
     
         if (!reason) {
    -	if (!(pd = fetch->pd))
    -	    reason = "peer digest disappeared?!";
    +        if (!(pd = fetch->pd))
    +            reason = "peer digest disappeared?!";
    +
     #if DONT			/* WHY NOT? /HNO */
    -	else if (!cbdataReferenceValid(pd))
    -	    reason = "invalidated peer digest?!";
    +
    +        else if (!cbdataReferenceValid(pd))
    +            reason = "invalidated peer digest?!";
    +
     #endif
    -	else
    -	    host = pd->host.buf();
    +
    +        else
    +            host = pd->host.buf();
         }
    +
         debug(72, 6) ("%s: peer %s, offset: %d size: %d.\n",
    -	step_name, host,
    -	fetch->offset, size);
    +                  step_name, host,
    +                  fetch->offset, size);
     
         /* continue checking (with pd and host known and valid) */
    +
         if (!reason) {
    -	if (!cbdataReferenceValid(pd->peer))
    -	    reason = "peer disappeared";
    -	else if (size < 0)
    -	    reason = "swap failure";
    -	else if (!fetch->entry)
    -	    reason = "swap aborted?!";
    -	else if (EBIT_TEST(fetch->entry->flags, ENTRY_ABORTED))
    -	    reason = "swap aborted";
    +        if (!cbdataReferenceValid(pd->peer))
    +            reason = "peer disappeared";
    +        else if (size < 0)
    +            reason = "swap failure";
    +        else if (!fetch->entry)
    +            reason = "swap aborted?!";
    +        else if (EBIT_TEST(fetch->entry->flags, ENTRY_ABORTED))
    +            reason = "swap aborted";
         }
    +
         /* continue checking (maybe-successful eof case) */
         if (!reason && !size) {
    -	if (!pd->cd)
    -	    reason = "null digest?!";
    -	else if (fetch->mask_offset != (off_t)pd->cd->mask_size)
    -	    reason = "premature end of digest?!";
    -	else if (!peerDigestUseful(pd))
    -	    reason = "useless digest";
    -	else
    -	    reason = no_bug = "success";
    +        if (!pd->cd)
    +            reason = "null digest?!";
    +        else if (fetch->mask_offset != (off_t)pd->cd->mask_size)
    +            reason = "premature end of digest?!";
    +        else if (!peerDigestUseful(pd))
    +            reason = "useless digest";
    +        else
    +            reason = no_bug = "success";
         }
    +
         /* finish if we have a reason */
         if (reason) {
    -	const int level = strstr(reason, "?!") ? 1 : 3;
    -	debug(72, level) ("%s: peer %s, exiting after '%s'\n",
    -	    step_name, host, reason);
    -	peerDigestReqFinish(fetch, buf,
    -	    1, pdcb_valid, pcb_valid, reason, !no_bug);
    +        const int level = strstr(reason, "?!") ? 1 : 3;
    +        debug(72, level) ("%s: peer %s, exiting after '%s'\n",
    +                          step_name, host, reason);
    +        peerDigestReqFinish(fetch, buf,
    +                            1, pdcb_valid, pcb_valid, reason, !no_bug);
         } else {
    -	/* paranoid check */
    -	assert(pdcb_valid && pcb_valid);
    +        /* paranoid check */
    +        assert(pdcb_valid && pcb_valid);
         }
    +
         return reason != NULL;
     }
     
    @@ -693,7 +779,7 @@ peerDigestFetchStop(DigestFetchState * fetch, char *buf, const char *reason)
     {
         assert(reason);
         debug(72, 2) ("peerDigestFetchStop: peer %s, reason: %s\n",
    -	fetch->pd->host.buf(), reason);
    +                  fetch->pd->host.buf(), reason);
         peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 0);
     }
     
    @@ -703,41 +789,47 @@ peerDigestFetchAbort(DigestFetchState * fetch, char *buf, const char *reason)
     {
         assert(reason);
         debug(72, 2) ("peerDigestFetchAbort: peer %s, reason: %s\n",
    -	fetch->pd->host.buf(), reason);
    +                  fetch->pd->host.buf(), reason);
         peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 1);
     }
     
     /* complete the digest transfer, update stats, unlock/release everything */
     static void
     peerDigestReqFinish(DigestFetchState * fetch, char *buf,
    -    int fcb_valid, int pdcb_valid, int pcb_valid,
    -    const char *reason, int err)
    +                    int fcb_valid, int pdcb_valid, int pcb_valid,
    +                    const char *reason, int err)
     {
         assert(reason);
     
         /* must go before peerDigestPDFinish */
    +
         if (pdcb_valid) {
    -	fetch->pd->flags.requested = 0;
    -	fetch->pd->req_result = reason;
    +        fetch->pd->flags.requested = 0;
    +        fetch->pd->req_result = reason;
         }
    +
         /* schedule next check if peer is still out there */
         if (pcb_valid) {
    -	PeerDigest *pd = fetch->pd;
    -	if (err) {
    -	    pd->times.retry_delay = peerDigestIncDelay(pd);
    -	    peerDigestSetCheck(pd, pd->times.retry_delay);
    -	} else {
    -	    pd->times.retry_delay = 0;
    -	    peerDigestSetCheck(pd, peerDigestNewDelay(fetch->entry));
    -	}
    +        PeerDigest *pd = fetch->pd;
    +
    +        if (err) {
    +            pd->times.retry_delay = peerDigestIncDelay(pd);
    +            peerDigestSetCheck(pd, pd->times.retry_delay);
    +        } else {
    +            pd->times.retry_delay = 0;
    +            peerDigestSetCheck(pd, peerDigestNewDelay(fetch->entry));
    +        }
         }
    +
         /* note: order is significant */
         if (fcb_valid)
    -	peerDigestFetchSetStats(fetch);
    +        peerDigestFetchSetStats(fetch);
    +
         if (pdcb_valid)
    -	peerDigestPDFinish(fetch, pcb_valid, err);
    +        peerDigestPDFinish(fetch, pcb_valid, err);
    +
         if (fcb_valid)
    -	peerDigestFetchFinish(fetch, err);
    +        peerDigestFetchFinish(fetch, err);
     }
     
     
    @@ -757,29 +849,32 @@ peerDigestPDFinish(DigestFetchState * fetch, int pcb_valid, int err)
         pd->stats.recv.msgs += fetch->recv.msg;
     
         if (err) {
    -	debug(72, 1) ("%sdisabling (%s) digest from %s\n",
    -	    pcb_valid ? "temporary " : "",
    -	    pd->req_result, host);
    -
    -	if (pd->cd) {
    -	    cacheDigestDestroy(pd->cd);
    -	    pd->cd = NULL;
    -	}
    -	pd->flags.usable = 0;
    -
    -	if (!pcb_valid)
    -	    peerDigestNotePeerGone(pd);
    +        debug(72, 1) ("%sdisabling (%s) digest from %s\n",
    +                      pcb_valid ? "temporary " : "",
    +                      pd->req_result, host);
    +
    +        if (pd->cd) {
    +            cacheDigestDestroy(pd->cd);
    +            pd->cd = NULL;
    +        }
    +
    +        pd->flags.usable = 0;
    +
    +        if (!pcb_valid)
    +            peerDigestNotePeerGone(pd);
         } else {
    -	assert(pcb_valid);
    +        assert(pcb_valid);
    +
    +        pd->flags.usable = 1;
     
    -	pd->flags.usable = 1;
    +        /* XXX: ugly condition, but how? */
     
    -	/* XXX: ugly condition, but how? */
    -	if (fetch->entry->store_status == STORE_OK)
    -	    debug(72, 2) ("re-used old digest from %s\n", host);
    -	else
    -	    debug(72, 2) ("received valid digest from %s\n", host);
    +        if (fetch->entry->store_status == STORE_OK)
    +            debug(72, 2) ("re-used old digest from %s\n", host);
    +        else
    +            debug(72, 2) ("received valid digest from %s\n", host);
         }
    +
         cbdataReferenceDone(fetch->pd);
     }
     
    @@ -791,25 +886,35 @@ peerDigestFetchFinish(DigestFetchState * fetch, int err)
         assert(fetch->entry && fetch->request);
     
         if (fetch->old_entry) {
    -	debug(72, 2) ("peerDigestFetchFinish: deleting old entry\n");
    -	storeUnregister(fetch->sc, fetch->old_entry, fetch);
    -	storeReleaseRequest(fetch->old_entry);
    -	storeUnlockObject(fetch->old_entry);
    -	fetch->old_entry = NULL;
    +        debug(72, 2) ("peerDigestFetchFinish: deleting old entry\n");
    +        storeUnregister(fetch->sc, fetch->old_entry, fetch);
    +        storeReleaseRequest(fetch->old_entry);
    +        storeUnlockObject(fetch->old_entry);
    +        fetch->old_entry = NULL;
         }
    +
         /* update global stats */
         kb_incr(&statCounter.cd.kbytes_sent, (size_t) fetch->sent.bytes);
    +
         kb_incr(&statCounter.cd.kbytes_recv, (size_t) fetch->recv.bytes);
    +
         statCounter.cd.msgs_sent += fetch->sent.msg;
    +
         statCounter.cd.msgs_recv += fetch->recv.msg;
     
         /* unlock everything */
         storeUnregister(fetch->sc, fetch->entry, fetch);
    +
         storeUnlockObject(fetch->entry);
    +
         requestUnlink(fetch->request);
    +
         fetch->entry = NULL;
    +
         fetch->request = NULL;
    +
         assert(fetch->pd == NULL);
    +
         cbdataFree(fetch);
     }
     
    @@ -835,10 +940,10 @@ peerDigestFetchSetStats(DigestFetchState * fetch)
         fetch->resp_time = squid_curtime - fetch->start_time;
     
         debug(72, 3) ("peerDigestFetchFinish: recv %d bytes in %d secs\n",
    -	fetch->recv.bytes, (int) fetch->resp_time);
    +                  fetch->recv.bytes, (int) fetch->resp_time);
         debug(72, 3) ("peerDigestFetchFinish: expires: %ld (%+d), lmt: %ld (%+d)\n",
    -	(long int) fetch->expires, (int) (fetch->expires - squid_curtime),
    -	(long int) fetch->entry->lastmod, (int) (fetch->entry->lastmod - squid_curtime));
    +                  (long int) fetch->expires, (int) (fetch->expires - squid_curtime),
    +                  (long int) fetch->entry->lastmod, (int) (fetch->entry->lastmod - squid_curtime));
     }
     
     
    @@ -858,58 +963,67 @@ peerDigestSetCBlock(PeerDigest * pd, const char *buf)
         cblock.del_count = ntohl(cblock.del_count);
         cblock.mask_size = ntohl(cblock.mask_size);
         debug(72, 2) ("got digest cblock from %s; ver: %d (req: %d)\n",
    -	host, (int) cblock.ver.current, (int) cblock.ver.required);
    +                  host, (int) cblock.ver.current, (int) cblock.ver.required);
         debug(72, 2) ("\t size: %d bytes, e-cnt: %d, e-util: %d%%\n",
    -	cblock.mask_size, cblock.count,
    -	xpercentInt(cblock.count, cblock.capacity));
    +                  cblock.mask_size, cblock.count,
    +                  xpercentInt(cblock.count, cblock.capacity));
         /* check version requirements (both ways) */
    +
         if (cblock.ver.required > CacheDigestVer.current) {
    -	debug(72, 1) ("%s digest requires version %d; have: %d\n",
    -	    host, cblock.ver.required, CacheDigestVer.current);
    -	return 0;
    +        debug(72, 1) ("%s digest requires version %d; have: %d\n",
    +                      host, cblock.ver.required, CacheDigestVer.current);
    +        return 0;
         }
    +
         if (cblock.ver.current < CacheDigestVer.required) {
    -	debug(72, 1) ("%s digest is version %d; we require: %d\n",
    -	    host, cblock.ver.current, CacheDigestVer.required);
    -	return 0;
    +        debug(72, 1) ("%s digest is version %d; we require: %d\n",
    +                      host, cblock.ver.current, CacheDigestVer.required);
    +        return 0;
         }
    +
         /* check consistency */
         if (cblock.ver.required > cblock.ver.current ||
    -	cblock.mask_size <= 0 || cblock.capacity <= 0 ||
    -	cblock.bits_per_entry <= 0 || cblock.hash_func_count <= 0) {
    -	debug(72, 0) ("%s digest cblock is corrupted.\n", host);
    -	return 0;
    +            cblock.mask_size <= 0 || cblock.capacity <= 0 ||
    +            cblock.bits_per_entry <= 0 || cblock.hash_func_count <= 0) {
    +        debug(72, 0) ("%s digest cblock is corrupted.\n", host);
    +        return 0;
         }
    +
         /* check consistency further */
         if ((size_t)cblock.mask_size != cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)) {
    -	debug(72, 0) ("%s digest cblock is corrupted (mask size mismatch: %d ? %d).\n",
    -	    host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry));
    -	return 0;
    +        debug(72, 0) ("%s digest cblock is corrupted (mask size mismatch: %d ? %d).\n",
    +                      host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry));
    +        return 0;
         }
    +
         /* there are some things we cannot do yet */
         if (cblock.hash_func_count != CacheDigestHashFuncCount) {
    -	debug(72, 0) ("%s digest: unsupported #hash functions: %d ? %d.\n",
    -	    host, cblock.hash_func_count, CacheDigestHashFuncCount);
    -	return 0;
    +        debug(72, 0) ("%s digest: unsupported #hash functions: %d ? %d.\n",
    +                      host, cblock.hash_func_count, CacheDigestHashFuncCount);
    +        return 0;
         }
    +
         /*
          * no cblock bugs below this point
          */
         /* check size changes */
         if (pd->cd && cblock.mask_size != (ssize_t)pd->cd->mask_size) {
    -	debug(72, 2) ("%s digest changed size: %d -> %d\n",
    -	    host, cblock.mask_size, pd->cd->mask_size);
    -	freed_size = pd->cd->mask_size;
    -	cacheDigestDestroy(pd->cd);
    -	pd->cd = NULL;
    +        debug(72, 2) ("%s digest changed size: %d -> %d\n",
    +                      host, cblock.mask_size, pd->cd->mask_size);
    +        freed_size = pd->cd->mask_size;
    +        cacheDigestDestroy(pd->cd);
    +        pd->cd = NULL;
         }
    +
         if (!pd->cd) {
    -	debug(72, 2) ("creating %s digest; size: %d (%+d) bytes\n",
    -	    host, cblock.mask_size, (int) (cblock.mask_size - freed_size));
    -	pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry);
    -	if (cblock.mask_size >= freed_size)
    -	    kb_incr(&statCounter.cd.memory, cblock.mask_size - freed_size);
    +        debug(72, 2) ("creating %s digest; size: %d (%+d) bytes\n",
    +                      host, cblock.mask_size, (int) (cblock.mask_size - freed_size));
    +        pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry);
    +
    +        if (cblock.mask_size >= freed_size)
    +            kb_incr(&statCounter.cd.memory, cblock.mask_size - freed_size);
         }
    +
         assert(pd->cd);
         /* these assignments leave us in an inconsistent state until we finish reading the digest */
         pd->cd->count = cblock.count;
    @@ -922,11 +1036,13 @@ peerDigestUseful(const PeerDigest * pd)
     {
         /* TODO: we should calculate the prob of a false hit instead of bit util */
         const int bit_util = cacheDigestBitUtil(pd->cd);
    +
         if (bit_util > 65) {
    -	debug(72, 0) ("Warning: %s peer digest has too many bits on (%d%%).\n",
    -	    pd->host.buf(), bit_util);
    -	return 0;
    +        debug(72, 0) ("Warning: %s peer digest has too many bits on (%d%%).\n",
    +                      pd->host.buf(), bit_util);
    +        return 0;
         }
    +
         return 1;
     }
     
    @@ -961,25 +1077,26 @@ peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e)
     
         storeAppendPrintf(e, "peer digest state:\n");
         storeAppendPrintf(e, "\tneeded: %3s, usable: %3s, requested: %3s\n",
    -	f2s(needed), f2s(usable), f2s(requested));
    +                      f2s(needed), f2s(usable), f2s(requested));
         storeAppendPrintf(e, "\n\tlast retry delay: %d secs\n",
    -	(int) pd->times.retry_delay);
    +                      (int) pd->times.retry_delay);
         storeAppendPrintf(e, "\tlast request response time: %d secs\n",
    -	(int) pd->times.req_delay);
    +                      (int) pd->times.req_delay);
         storeAppendPrintf(e, "\tlast request result: %s\n",
    -	pd->req_result ? pd->req_result : "(none)");
    +                      pd->req_result ? pd->req_result : "(none)");
     
         storeAppendPrintf(e, "\npeer digest traffic:\n");
         storeAppendPrintf(e, "\trequests sent: %d, volume: %d KB\n",
    -	pd->stats.sent.msgs, (int) pd->stats.sent.kbytes.kb);
    +                      pd->stats.sent.msgs, (int) pd->stats.sent.kbytes.kb);
         storeAppendPrintf(e, "\treplies recv:  %d, volume: %d KB\n",
    -	pd->stats.recv.msgs, (int) pd->stats.recv.kbytes.kb);
    +                      pd->stats.recv.msgs, (int) pd->stats.recv.kbytes.kb);
     
         storeAppendPrintf(e, "\npeer digest structure:\n");
    +
         if (pd->cd)
    -	cacheDigestReport(pd->cd, host, e);
    +        cacheDigestReport(pd->cd, host, e);
         else
    -	storeAppendPrintf(e, "\tno in-memory copy\n");
    +        storeAppendPrintf(e, "\tno in-memory copy\n");
     }
     
     #endif
    diff --git a/src/peer_select.cc b/src/peer_select.cc
    index 19bcb95b20..373038d2c0 100644
    --- a/src/peer_select.cc
    +++ b/src/peer_select.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: peer_select.cc,v 1.128 2003/02/21 19:53:02 hno Exp $
    + * $Id: peer_select.cc,v 1.129 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 44    Peer Selection Algorithm
      * AUTHOR: Duane Wessels
    @@ -40,43 +40,46 @@
     #include "ACLChecklist.h"
     
     const char *hier_strings[] =
    -{
    -    "NONE",
    -    "DIRECT",
    -    "SIBLING_HIT",
    -    "PARENT_HIT",
    -    "DEFAULT_PARENT",
    -    "SINGLE_PARENT",
    -    "FIRST_UP_PARENT",
    -    "FIRST_PARENT_MISS",
    -    "CLOSEST_PARENT_MISS",
    -    "CLOSEST_PARENT",
    -    "CLOSEST_DIRECT",
    -    "NO_DIRECT_FAIL",
    -    "SOURCE_FASTEST",
    -    "ROUNDROBIN_PARENT",
    +    {
    +        "NONE",
    +        "DIRECT",
    +        "SIBLING_HIT",
    +        "PARENT_HIT",
    +        "DEFAULT_PARENT",
    +        "SINGLE_PARENT",
    +        "FIRST_UP_PARENT",
    +        "FIRST_PARENT_MISS",
    +        "CLOSEST_PARENT_MISS",
    +        "CLOSEST_PARENT",
    +        "CLOSEST_DIRECT",
    +        "NO_DIRECT_FAIL",
    +        "SOURCE_FASTEST",
    +        "ROUNDROBIN_PARENT",
     #if USE_CACHE_DIGESTS
    -    "CD_PARENT_HIT",
    -    "CD_SIBLING_HIT",
    +        "CD_PARENT_HIT",
    +        "CD_SIBLING_HIT",
     #endif
     #if USE_CARP
    -    "CARP",
    +        "CARP",
     #endif
    -    "ANY_PARENT",
    -    "INVALID CODE"
    -};
    +        "ANY_PARENT",
    +        "INVALID CODE"
    +    };
     
    -static struct {
    +static struct
    +{
         int timeouts;
    -} PeerStats;
    +}
    +
    +PeerStats;
     
     static const char *DirectStr[] =
    -{
    -    "DIRECT_UNKNOWN",
    -    "DIRECT_NO",
    -    "DIRECT_MAYBE",
    -    "DIRECT_YES"
    -};
    +    {
    +        "DIRECT_UNKNOWN",
    +        "DIRECT_NO",
    +        "DIRECT_MAYBE",
    +        "DIRECT_YES"
    +    };
     
     static void peerSelectFoo(ps_state *);
     static void peerPingTimeout(void *data);
    @@ -100,16 +103,19 @@ static void
     peerSelectStateFree(ps_state * psstate)
     {
         if (psstate->acl_checklist) {
    -	debug(44, 1) ("calling aclChecklistFree() from peerSelectStateFree\n");
    -	delete (psstate->acl_checklist);
    +        debug(44, 1) ("calling aclChecklistFree() from peerSelectStateFree\n");
    +        delete (psstate->acl_checklist);
         }
    +
         requestUnlink(psstate->request);
         psstate->request = NULL;
    +
         if (psstate->entry) {
    -	assert(psstate->entry->ping_status != PING_WAITING);
    -	storeUnlockObject(psstate->entry);
    -	psstate->entry = NULL;
    +        assert(psstate->entry->ping_status != PING_WAITING);
    +        storeUnlockObject(psstate->entry);
    +        psstate->entry = NULL;
         }
    +
         cbdataFree(psstate);
     }
     
    @@ -121,39 +127,56 @@ peerSelectIcpPing(request_t * request, int direct, StoreEntry * entry)
         assert(entry->ping_status == PING_NONE);
         assert(direct != DIRECT_YES);
         debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry));
    +
         if (!request->flags.hierarchical && direct != DIRECT_NO)
    -	return 0;
    +        return 0;
    +
         if (EBIT_TEST(entry->flags, KEY_PRIVATE) && !neighbors_do_private_keys)
    -	if (direct != DIRECT_NO)
    -	    return 0;
    +        if (direct != DIRECT_NO)
    +            return 0;
    +
         n = neighborsCount(request);
    +
         debug(44, 3) ("peerSelectIcpPing: counted %d neighbors\n", n);
    +
         return n;
     }
     
     
     void
     peerSelect(request_t * request,
    -    StoreEntry * entry,
    -    PSC * callback,
    -    void *callback_data)
    +           StoreEntry * entry,
    +           PSC * callback,
    +           void *callback_data)
     {
         ps_state *psstate;
    +
         if (entry)
    -	debug(44, 3) ("peerSelect: %s\n", storeUrl(entry));
    +        debug(44, 3) ("peerSelect: %s\n", storeUrl(entry));
         else
    -	debug(44, 3) ("peerSelect: %s\n", RequestMethodStr[request->method]);
    +        debug(44, 3) ("peerSelect: %s\n", RequestMethodStr[request->method]);
    +
         psstate = cbdataAlloc(ps_state);
    +
         psstate->request = requestLink(request);
    +
         psstate->entry = entry;
    +
         psstate->callback = callback;
    +
         psstate->callback_data = cbdataReference(callback_data);
    +
         psstate->direct = DIRECT_UNKNOWN;
    +
     #if USE_CACHE_DIGESTS
    +
         request->hier.peer_select_start = current_time;
    +
     #endif
    +
         if (psstate->entry)
    -	storeLockObject(psstate->entry);
    +        storeLockObject(psstate->entry);
    +
         peerSelectFoo(psstate);
     }
     
    @@ -184,26 +207,33 @@ peerSelectCallback(ps_state * psstate)
         FwdServer *fs = psstate->servers;
         PSC *callback;
         void *cbdata;
    +
         if (entry) {
    -	debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry));
    -	if (entry->ping_status == PING_WAITING)
    -	    eventDelete(peerPingTimeout, psstate);
    -	entry->ping_status = PING_DONE;
    +        debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry));
    +
    +        if (entry->ping_status == PING_WAITING)
    +            eventDelete(peerPingTimeout, psstate);
    +
    +        entry->ping_status = PING_DONE;
         }
    +
         if (fs == NULL) {
    -	debug(44, 1) ("Failed to select source for '%s'\n", storeUrl(entry));
    -	debug(44, 1) ("  always_direct = %d\n", psstate->always_direct);
    -	debug(44, 1) ("   never_direct = %d\n", psstate->never_direct);
    -	debug(44, 1) ("       timedout = %d\n", psstate->ping.timedout);
    +        debug(44, 1) ("Failed to select source for '%s'\n", storeUrl(entry));
    +        debug(44, 1) ("  always_direct = %d\n", psstate->always_direct);
    +        debug(44, 1) ("   never_direct = %d\n", psstate->never_direct);
    +        debug(44, 1) ("       timedout = %d\n", psstate->ping.timedout);
         }
    +
         psstate->ping.stop = current_time;
         psstate->request->hier.ping = psstate->ping;
         callback = psstate->callback;
         psstate->callback = NULL;
    +
         if (cbdataReferenceValidDone(psstate->callback_data, &cbdata)) {
    -	psstate->servers = NULL;
    -	callback(fs, cbdata);
    +        psstate->servers = NULL;
    +        callback(fs, cbdata);
         }
    +
         peerSelectStateFree(psstate);
     }
     
    @@ -213,27 +243,41 @@ peerCheckNetdbDirect(ps_state * psstate)
         peer *p;
         int myrtt;
         int myhops;
    +
         if (psstate->direct == DIRECT_NO)
    -	return 0;
    +        return 0;
    +
         myrtt = netdbHostRtt(psstate->request->host);
    +
         debug(44, 3) ("peerCheckNetdbDirect: MY RTT = %d msec\n", myrtt);
    +
         debug(44, 3) ("peerCheckNetdbDirect: minimum_direct_rtt = %d msec\n",
    -	Config.minDirectRtt);
    +                  Config.minDirectRtt);
    +
         if (myrtt && myrtt <= Config.minDirectRtt)
    -	return 1;
    +        return 1;
    +
         myhops = netdbHostHops(psstate->request->host);
    +
         debug(44, 3) ("peerCheckNetdbDirect: MY hops = %d\n", myhops);
    +
         debug(44, 3) ("peerCheckNetdbDirect: minimum_direct_hops = %d\n",
    -	Config.minDirectHops);
    +                  Config.minDirectHops);
    +
         if (myhops && myhops <= Config.minDirectHops)
    -	return 1;
    +        return 1;
    +
         p = whichPeer(&psstate->closest_parent_miss);
    +
         if (p == NULL)
    -	return 0;
    +        return 0;
    +
         debug(44, 3) ("peerCheckNetdbDirect: closest_parent_miss RTT = %d msec\n",
    -	psstate->ping.p_rtt);
    +                  psstate->ping.p_rtt);
    +
         if (myrtt && myrtt <= psstate->ping.p_rtt)
    -	return 1;
    +        return 1;
    +
         return 0;
     }
     
    @@ -243,68 +287,81 @@ peerSelectFoo(ps_state * ps)
         StoreEntry *entry = ps->entry;
         request_t *request = ps->request;
         debug(44, 3) ("peerSelectFoo: '%s %s'\n",
    -	RequestMethodStr[request->method],
    -	request->host);
    +                  RequestMethodStr[request->method],
    +                  request->host);
    +
         if (ps->direct == DIRECT_UNKNOWN) {
    -	if (ps->always_direct == 0 && Config.accessList.AlwaysDirect) {
    -	    ps->acl_checklist = aclChecklistCreate(
    -		Config.accessList.AlwaysDirect,
    -		request,
    -		NULL);		/* ident */
    -	    ps->acl_checklist->nonBlockingCheck(peerCheckAlwaysDirectDone,
    -		ps);
    -	    return;
    -	} else if (ps->always_direct > 0) {
    -	    ps->direct = DIRECT_YES;
    -	} else if (ps->never_direct == 0 && Config.accessList.NeverDirect) {
    -	    ps->acl_checklist = aclChecklistCreate(
    -		Config.accessList.NeverDirect,
    -		request,
    -		NULL);		/* ident */
    -	    ps->acl_checklist->nonBlockingCheck(peerCheckNeverDirectDone,
    -		ps);
    -	    return;
    -	} else if (ps->never_direct > 0) {
    -	    ps->direct = DIRECT_NO;
    -	} else if (request->flags.accelerated) {
    -	    ps->direct = DIRECT_NO;
    -	} else if (request->flags.loopdetect) {
    -	    ps->direct = DIRECT_YES;
    -	} else if (peerCheckNetdbDirect(ps)) {
    -	    ps->direct = DIRECT_YES;
    -	} else {
    -	    ps->direct = DIRECT_MAYBE;
    -	}
    -	debug(44, 3) ("peerSelectFoo: direct = %s\n",
    -	    DirectStr[ps->direct]);
    +        if (ps->always_direct == 0 && Config.accessList.AlwaysDirect) {
    +            ps->acl_checklist = aclChecklistCreate(
    +                                    Config.accessList.AlwaysDirect,
    +                                    request,
    +                                    NULL);		/* ident */
    +            ps->acl_checklist->nonBlockingCheck(peerCheckAlwaysDirectDone,
    +                                                ps);
    +            return;
    +        } else if (ps->always_direct > 0) {
    +            ps->direct = DIRECT_YES;
    +        } else if (ps->never_direct == 0 && Config.accessList.NeverDirect) {
    +            ps->acl_checklist = aclChecklistCreate(
    +                                    Config.accessList.NeverDirect,
    +                                    request,
    +                                    NULL);		/* ident */
    +            ps->acl_checklist->nonBlockingCheck(peerCheckNeverDirectDone,
    +                                                ps);
    +            return;
    +        } else if (ps->never_direct > 0) {
    +            ps->direct = DIRECT_NO;
    +        } else if (request->flags.accelerated) {
    +            ps->direct = DIRECT_NO;
    +        } else if (request->flags.loopdetect) {
    +            ps->direct = DIRECT_YES;
    +        } else if (peerCheckNetdbDirect(ps)) {
    +            ps->direct = DIRECT_YES;
    +        } else {
    +            ps->direct = DIRECT_MAYBE;
    +        }
    +
    +        debug(44, 3) ("peerSelectFoo: direct = %s\n",
    +                      DirectStr[ps->direct]);
         }
    +
         if (entry == NULL) {
    -	(void) 0;
    +        (void) 0;
         } else if (entry->ping_status == PING_NONE) {
    -	peerGetSomeNeighbor(ps);
    -	if (entry->ping_status == PING_WAITING)
    -	    return;
    +        peerGetSomeNeighbor(ps);
    +
    +        if (entry->ping_status == PING_WAITING)
    +            return;
         } else if (entry->ping_status == PING_WAITING) {
    -	peerGetSomeNeighborReplies(ps);
    -	entry->ping_status = PING_DONE;
    +        peerGetSomeNeighborReplies(ps);
    +        entry->ping_status = PING_DONE;
         }
    +
         switch (ps->direct) {
    +
         case DIRECT_YES:
    -	peerGetSomeDirect(ps);
    -	break;
    +        peerGetSomeDirect(ps);
    +        break;
    +
         case DIRECT_NO:
    -	peerGetSomeParent(ps);
    -	peerGetAllParents(ps);
    -	break;
    +        peerGetSomeParent(ps);
    +        peerGetAllParents(ps);
    +        break;
    +
         default:
    -	if (Config.onoff.prefer_direct)
    -	    peerGetSomeDirect(ps);
    -	if (request->flags.hierarchical || !Config.onoff.nonhierarchical_direct)
    -	    peerGetSomeParent(ps);
    -	if (!Config.onoff.prefer_direct)
    -	    peerGetSomeDirect(ps);
    -	break;
    +
    +        if (Config.onoff.prefer_direct)
    +            peerGetSomeDirect(ps);
    +
    +        if (request->flags.hierarchical || !Config.onoff.nonhierarchical_direct)
    +            peerGetSomeParent(ps);
    +
    +        if (!Config.onoff.prefer_direct)
    +            peerGetSomeDirect(ps);
    +
    +        break;
         }
    +
         peerSelectCallback(ps);
     }
     
    @@ -326,48 +383,55 @@ peerGetSomeNeighbor(ps_state * ps)
         peer *p;
         hier_code code = HIER_NONE;
         assert(entry->ping_status == PING_NONE);
    +
         if (ps->direct == DIRECT_YES) {
    -	entry->ping_status = PING_DONE;
    -	return;
    +        entry->ping_status = PING_DONE;
    +        return;
         }
    +
     #if USE_CACHE_DIGESTS
         if ((p = neighborsDigestSelect(request))) {
    -	if (neighborType(p, request) == PEER_PARENT)
    -	    code = CD_PARENT_HIT;
    -	else
    -	    code = CD_SIBLING_HIT;
    +        if (neighborType(p, request) == PEER_PARENT)
    +            code = CD_PARENT_HIT;
    +        else
    +            code = CD_SIBLING_HIT;
         } else
     #endif
    -    if ((p = netdbClosestParent(request))) {
    -	code = CLOSEST_PARENT;
    -    } else if (peerSelectIcpPing(request, ps->direct, entry)) {
    -	debug(44, 3) ("peerSelect: Doing ICP pings\n");
    -	ps->ping.start = current_time;
    -	ps->ping.n_sent = neighborsUdpPing(request,
    -	    entry,
    -	    peerHandlePingReply,
    -	    ps,
    -	    &ps->ping.n_replies_expected,
    -	    &ps->ping.timeout);
    -	if (ps->ping.n_sent == 0)
    -	    debug(44, 0) ("WARNING: neighborsUdpPing returned 0\n");
    -	debug(44, 3) ("peerSelect: %d ICP replies expected, RTT %d msec\n",
    -	    ps->ping.n_replies_expected, ps->ping.timeout);
    -	if (ps->ping.n_replies_expected > 0) {
    -	    entry->ping_status = PING_WAITING;
    -	    eventAdd("peerPingTimeout",
    -		peerPingTimeout,
    -		ps,
    -		0.001 * ps->ping.timeout,
    -		0);
    -	    return;
    -	}
    -    }
    +        if ((p = netdbClosestParent(request))) {
    +            code = CLOSEST_PARENT;
    +        } else if (peerSelectIcpPing(request, ps->direct, entry)) {
    +            debug(44, 3) ("peerSelect: Doing ICP pings\n");
    +            ps->ping.start = current_time;
    +            ps->ping.n_sent = neighborsUdpPing(request,
    +                                               entry,
    +                                               peerHandlePingReply,
    +                                               ps,
    +                                               &ps->ping.n_replies_expected,
    +                                               &ps->ping.timeout);
    +
    +            if (ps->ping.n_sent == 0)
    +                debug(44, 0) ("WARNING: neighborsUdpPing returned 0\n");
    +
    +            debug(44, 3) ("peerSelect: %d ICP replies expected, RTT %d msec\n",
    +                          ps->ping.n_replies_expected, ps->ping.timeout);
    +
    +            if (ps->ping.n_replies_expected > 0) {
    +                entry->ping_status = PING_WAITING;
    +                eventAdd("peerPingTimeout",
    +                         peerPingTimeout,
    +                         ps,
    +                         0.001 * ps->ping.timeout,
    +                         0);
    +                return;
    +            }
    +        }
    +
         if (code != HIER_NONE) {
    -	assert(p);
    -	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
    -	peerAddFwdServer(&ps->servers, p, code);
    +        assert(p);
    +        debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
    +        peerAddFwdServer(&ps->servers, p, code);
         }
    +
         entry->ping_status = PING_DONE;
     }
     
    @@ -384,30 +448,33 @@ peerGetSomeNeighborReplies(ps_state * ps)
         hier_code code = HIER_NONE;
         assert(ps->entry->ping_status == PING_WAITING);
         assert(ps->direct != DIRECT_YES);
    +
         if (peerCheckNetdbDirect(ps)) {
    -	code = CLOSEST_DIRECT;
    -	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host);
    -	peerAddFwdServer(&ps->servers, NULL, code);
    -	return;
    +        code = CLOSEST_DIRECT;
    +        debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host);
    +        peerAddFwdServer(&ps->servers, NULL, code);
    +        return;
         }
    +
         if ((p = ps->hit)) {
    -	code = ps->hit_type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT;
    +        code = ps->hit_type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT;
         } else
     #if ALLOW_SOURCE_PING
    -    if ((p = ps->secho)) {
    -	code = SOURCE_FASTEST;
    -    } else
    +        if ((p = ps->secho)) {
    +            code = SOURCE_FASTEST;
    +        } else
     #endif
    -    if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) {
    -	p = whichPeer(&ps->closest_parent_miss);
    -	code = CLOSEST_PARENT_MISS;
    -    } else if (ps->first_parent_miss.sin_addr.s_addr != any_addr.s_addr) {
    -	p = whichPeer(&ps->first_parent_miss);
    -	code = FIRST_PARENT_MISS;
    -    }
    +            if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) {
    +                p = whichPeer(&ps->closest_parent_miss);
    +                code = CLOSEST_PARENT_MISS;
    +            } else if (ps->first_parent_miss.sin_addr.s_addr != any_addr.s_addr) {
    +                p = whichPeer(&ps->first_parent_miss);
    +                code = FIRST_PARENT_MISS;
    +            }
    +
         if (p && code != HIER_NONE) {
    -	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
    -	peerAddFwdServer(&ps->servers, p, code);
    +        debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
    +        peerAddFwdServer(&ps->servers, p, code);
         }
     }
     
    @@ -422,12 +489,13 @@ static void
     peerGetSomeDirect(ps_state * ps)
     {
         if (ps->direct == DIRECT_NO)
    -	return;
    +        return;
    +
         if (ps->request->protocol == PROTO_WAIS)
    -	/* Its not really DIRECT, now is it? */
    -	peerAddFwdServer(&ps->servers, Config.Wais._peer, DIRECT);
    +        /* Its not really DIRECT, now is it? */
    +        peerAddFwdServer(&ps->servers, Config.Wais._peer, DIRECT);
         else
    -	peerAddFwdServer(&ps->servers, NULL, DIRECT);
    +        peerAddFwdServer(&ps->servers, NULL, DIRECT);
     }
     
     static void
    @@ -437,28 +505,33 @@ peerGetSomeParent(ps_state * ps)
         request_t *request = ps->request;
         hier_code code = HIER_NONE;
         debug(44, 3) ("peerGetSomeParent: %s %s\n",
    -	RequestMethodStr[request->method],
    -	request->host);
    +                  RequestMethodStr[request->method],
    +                  request->host);
    +
         if (ps->direct == DIRECT_YES)
    -	return;
    +        return;
    +
         if ((p = getDefaultParent(request))) {
    -	code = DEFAULT_PARENT;
    +        code = DEFAULT_PARENT;
     #if USE_CARP
    +
         } else if ((p = carpSelectParent(request))) {
    -	code = CARP;
    +        code = CARP;
     #endif
    +
         } else if ((p = getRoundRobinParent(request))) {
    -	code = ROUNDROBIN_PARENT;
    +        code = ROUNDROBIN_PARENT;
         } else if ((p = getWeightedRoundRobinParent(request))) {
    -	code = ROUNDROBIN_PARENT;
    +        code = ROUNDROBIN_PARENT;
         } else if ((p = getFirstUpParent(request))) {
    -	code = FIRSTUP_PARENT;
    +        code = FIRSTUP_PARENT;
         } else if ((p = getAnyParent(request))) {
    -	code = ANY_OLD_PARENT;
    +        code = ANY_OLD_PARENT;
         }
    +
         if (code != HIER_NONE) {
    -	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
    -	peerAddFwdServer(&ps->servers, p, code);
    +        debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
    +        peerAddFwdServer(&ps->servers, p, code);
         }
     }
     
    @@ -470,24 +543,30 @@ peerGetAllParents(ps_state * ps)
         peer *p;
         request_t *request = ps->request;
         /* Add all alive parents */
    +
         for (p = Config.peers; p; p = p->next) {
    -	/* XXX: neighbors.c lacks a public interface for enumerating
    -	 * parents to a request so we have to dig some here..
    -	 */
    -	if (neighborType(p, request) != PEER_PARENT)
    -	    continue;
    -	if (!peerHTTPOkay(p, request))
    -	    continue;
    -	debug(15, 3) ("peerGetAllParents: adding alive parent %s\n", p->host);
    -	peerAddFwdServer(&ps->servers, p, ANY_OLD_PARENT);
    +        /* XXX: neighbors.c lacks a public interface for enumerating
    +         * parents to a request so we have to dig some here..
    +         */
    +
    +        if (neighborType(p, request) != PEER_PARENT)
    +            continue;
    +
    +        if (!peerHTTPOkay(p, request))
    +            continue;
    +
    +        debug(15, 3) ("peerGetAllParents: adding alive parent %s\n", p->host);
    +
    +        peerAddFwdServer(&ps->servers, p, ANY_OLD_PARENT);
         }
    +
         /* XXX: should add dead parents here, but it is currently
          * not possible to find out which parents are dead or which
          * simply are not configured to handle the request.
          */
         /* Add default parent as a last resort */
         if ((p = getDefaultParent(request))) {
    -	peerAddFwdServer(&ps->servers, p, DEFAULT_PARENT);
    +        peerAddFwdServer(&ps->servers, p, DEFAULT_PARENT);
         }
     }
     
    @@ -496,15 +575,18 @@ peerPingTimeout(void *data)
     {
         ps_state *psstate = (ps_state *)data;
         StoreEntry *entry = psstate->entry;
    +
         if (entry)
    -	debug(44, 3) ("peerPingTimeout: '%s'\n", storeUrl(entry));
    +        debug(44, 3) ("peerPingTimeout: '%s'\n", storeUrl(entry));
    +
         if (!cbdataReferenceValid(psstate->callback_data)) {
    -	/* request aborted */
    -	entry->ping_status = PING_DONE;
    -	cbdataReferenceDone(psstate->callback_data);
    -	peerSelectStateFree(psstate);
    -	return;
    +        /* request aborted */
    +        entry->ping_status = PING_DONE;
    +        cbdataReferenceDone(psstate->callback_data);
    +        peerSelectStateFree(psstate);
    +        return;
         }
    +
         PeerStats.timeouts++;
         psstate->ping.timedout = 1;
         peerSelectFoo(psstate);
    @@ -522,31 +604,39 @@ peerIcpParentMiss(peer * p, icp_common_t * header, ps_state * ps)
     {
         int rtt;
         int hops;
    +
         if (Config.onoff.query_icmp) {
    -	if (header->flags & ICP_FLAG_SRC_RTT) {
    -	    rtt = header->pad & 0xFFFF;
    -	    hops = (header->pad >> 16) & 0xFFFF;
    -	    if (rtt > 0 && rtt < 0xFFFF)
    -		netdbUpdatePeer(ps->request, p, rtt, hops);
    -	    if (rtt && (ps->ping.p_rtt == 0 || rtt < ps->ping.p_rtt)) {
    -		ps->closest_parent_miss = p->in_addr;
    -		ps->ping.p_rtt = rtt;
    -	    }
    -	}
    +        if (header->flags & ICP_FLAG_SRC_RTT) {
    +            rtt = header->pad & 0xFFFF;
    +            hops = (header->pad >> 16) & 0xFFFF;
    +
    +            if (rtt > 0 && rtt < 0xFFFF)
    +                netdbUpdatePeer(ps->request, p, rtt, hops);
    +
    +            if (rtt && (ps->ping.p_rtt == 0 || rtt < ps->ping.p_rtt)) {
    +                ps->closest_parent_miss = p->in_addr;
    +                ps->ping.p_rtt = rtt;
    +            }
    +        }
         }
    +
         /* if closest-only is set, then don't allow FIRST_PARENT_MISS */
         if (p->options.closest_only)
    -	return;
    +        return;
    +
         /* set FIRST_MISS if there is no CLOSEST parent */
         if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr)
    -	return;
    +        return;
    +
         rtt = (tvSubMsec(ps->ping.start, current_time) - p->basetime) / p->weight;
    +
         if (rtt < 1)
    -	rtt = 1;
    +        rtt = 1;
    +
         if (ps->first_parent_miss.sin_addr.s_addr == any_addr.s_addr ||
    -	rtt < ps->ping.w_rtt) {
    -	ps->first_parent_miss = p->in_addr;
    -	ps->ping.w_rtt = rtt;
    +            rtt < ps->ping.w_rtt) {
    +        ps->first_parent_miss = p->in_addr;
    +        ps->ping.w_rtt = rtt;
         }
     }
     
    @@ -556,33 +646,40 @@ peerHandleIcpReply(peer * p, peer_t type, icp_common_t * header, void *data)
         ps_state *psstate = (ps_state *)data;
         icp_opcode op = header->getOpCode();
         debug(44, 3) ("peerHandleIcpReply: %s %s\n",
    -	icp_opcode_str[op],
    -	storeUrl(psstate->entry));
    +                  icp_opcode_str[op],
    +                  storeUrl(psstate->entry));
     #if USE_CACHE_DIGESTS && 0
         /* do cd lookup to count false misses */
    +
         if (p && request)
    -	peerNoteDigestLookup(request, p,
    -	    peerDigestLookup(p, request, psstate->entry));
    +        peerNoteDigestLookup(request, p,
    +                             peerDigestLookup(p, request, psstate->entry));
    +
     #endif
    +
         psstate->ping.n_recv++;
    +
         if (op == ICP_MISS || op == ICP_DECHO) {
    -	if (type == PEER_PARENT)
    -	    peerIcpParentMiss(p, header, psstate);
    +        if (type == PEER_PARENT)
    +            peerIcpParentMiss(p, header, psstate);
         } else if (op == ICP_HIT) {
    -	psstate->hit = p;
    -	psstate->hit_type = type;
    -	peerSelectFoo(psstate);
    -	return;
    +        psstate->hit = p;
    +        psstate->hit_type = type;
    +        peerSelectFoo(psstate);
    +        return;
         }
    +
     #if ALLOW_SOURCE_PING
         else if (op == ICP_SECHO) {
    -	psstate->secho = p;
    -	peerSelectFoo(psstate);
    -	return;
    +        psstate->secho = p;
    +        peerSelectFoo(psstate);
    +        return;
         }
    +
     #endif
         if (psstate->ping.n_recv < psstate->ping.n_replies_expected)
    -	return;
    +        return;
    +
         peerSelectFoo(psstate);
     }
     
    @@ -592,19 +689,23 @@ peerHandleHtcpReply(peer * p, peer_t type, htcpReplyData * htcp, void *data)
     {
         ps_state *psstate = (ps_state *)data;
         debug(44, 3) ("peerHandleIcpReply: %s %s\n",
    -	htcp->hit ? "HIT" : "MISS",
    -	storeUrl(psstate->entry));
    +                  htcp->hit ? "HIT" : "MISS",
    +                  storeUrl(psstate->entry));
         psstate->ping.n_recv++;
    +
         if (htcp->hit) {
    -	psstate->hit = p;
    -	psstate->hit_type = type;
    -	peerSelectFoo(psstate);
    -	return;
    +        psstate->hit = p;
    +        psstate->hit_type = type;
    +        peerSelectFoo(psstate);
    +        return;
         }
    +
         if (type == PEER_PARENT)
    -	peerHtcpParentMiss(p, htcp, psstate);
    +        peerHtcpParentMiss(p, htcp, psstate);
    +
         if (psstate->ping.n_recv < psstate->ping.n_replies_expected)
    -	return;
    +        return;
    +
         peerSelectFoo(psstate);
     }
     
    @@ -613,45 +714,57 @@ peerHtcpParentMiss(peer * p, htcpReplyData * htcp, ps_state * ps)
     {
         int rtt;
         int hops;
    +
         if (Config.onoff.query_icmp) {
    -	if (htcp->cto.rtt > 0) {
    -	    rtt = (int) htcp->cto.rtt * 1000;
    -	    hops = (int) htcp->cto.hops * 1000;
    -	    netdbUpdatePeer(ps->request, p, rtt, hops);
    -	    if (rtt && (ps->ping.p_rtt == 0 || rtt < ps->ping.p_rtt)) {
    -		ps->closest_parent_miss = p->in_addr;
    -		ps->ping.p_rtt = rtt;
    -	    }
    -	}
    +        if (htcp->cto.rtt > 0) {
    +            rtt = (int) htcp->cto.rtt * 1000;
    +            hops = (int) htcp->cto.hops * 1000;
    +            netdbUpdatePeer(ps->request, p, rtt, hops);
    +
    +            if (rtt && (ps->ping.p_rtt == 0 || rtt < ps->ping.p_rtt)) {
    +                ps->closest_parent_miss = p->in_addr;
    +                ps->ping.p_rtt = rtt;
    +            }
    +        }
         }
    +
         /* if closest-only is set, then don't allow FIRST_PARENT_MISS */
         if (p->options.closest_only)
    -	return;
    +        return;
    +
         /* set FIRST_MISS if there is no CLOSEST parent */
         if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr)
    -	return;
    +        return;
    +
         rtt = (tvSubMsec(ps->ping.start, current_time) - p->basetime) / p->weight;
    +
         if (rtt < 1)
    -	rtt = 1;
    +        rtt = 1;
    +
         if (ps->first_parent_miss.sin_addr.s_addr == any_addr.s_addr ||
    -	rtt < ps->ping.w_rtt) {
    -	ps->first_parent_miss = p->in_addr;
    -	ps->ping.w_rtt = rtt;
    +            rtt < ps->ping.w_rtt) {
    +        ps->first_parent_miss = p->in_addr;
    +        ps->ping.w_rtt = rtt;
         }
     }
    +
     #endif
     
     static void
     peerHandlePingReply(peer * p, peer_t type, protocol_t proto, void *pingdata, void *data)
     {
         if (proto == PROTO_ICP)
    -	peerHandleIcpReply(p, type, (icp_common_t *)pingdata, data);
    +        peerHandleIcpReply(p, type, (icp_common_t *)pingdata, data);
    +
     #if USE_HTCP
    +
         else if (proto == PROTO_HTCP)
    -	peerHandleHtcpReply(p, type, (htcpReplyData *)pingdata, data);
    +        peerHandleHtcpReply(p, type, (htcpReplyData *)pingdata, data);
    +
     #endif
    +
         else
    -	debug(44, 1) ("peerHandlePingReply: unknown protocol_t %d\n", (int) proto);
    +        debug(44, 1) ("peerHandlePingReply: unknown protocol_t %d\n", (int) proto);
     }
     
     static void
    @@ -659,11 +772,13 @@ peerAddFwdServer(FwdServer ** FS, peer * p, hier_code code)
     {
         FwdServer *fs = (FwdServer *)memAllocate(MEM_FWD_SERVER);
         debug(44, 5) ("peerAddFwdServer: adding %s %s\n",
    -	p ? p->host : "DIRECT",
    -	hier_strings[code]);
    +                  p ? p->host : "DIRECT",
    +                  hier_strings[code]);
         fs->_peer = cbdataReference(p);
         fs->code = code;
    +
         while (*FS)
    -	FS = &(*FS)->next;
    +        FS = &(*FS)->next;
    +
         *FS = fs;
     }
    diff --git a/src/pinger.cc b/src/pinger.cc
    index 00824e6400..96bfeee92a 100644
    --- a/src/pinger.cc
    +++ b/src/pinger.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: pinger.cc,v 1.49 2003/01/23 00:37:24 robertc Exp $
    + * $Id: pinger.cc,v 1.50 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 42    ICMP Pinger program
      * AUTHOR: Duane Wessels
    @@ -82,39 +82,44 @@
     #define MAX_PKT_SZ (MAX_PAYLOAD + sizeof(struct timeval) + sizeof (char) + sizeof(struct icmphdr) + 1)
     #endif
     
    -typedef struct {
    +typedef struct
    +{
    +
         struct timeval tv;
         unsigned char opcode;
         char payload[MAX_PAYLOAD];
    -} icmpEchoData;
    +}
    +
    +icmpEchoData;
     
     int icmp_ident = -1;
     int icmp_pkts_sent = 0;
     
     static const char *icmpPktStr[] =
    -{
    -    "Echo Reply",
    -    "ICMP 1",
    -    "ICMP 2",
    -    "Destination Unreachable",
    -    "Source Quench",
    -    "Redirect",
    -    "ICMP 6",
    -    "ICMP 7",
    -    "Echo",
    -    "ICMP 9",
    -    "ICMP 10",
    -    "Time Exceeded",
    -    "Parameter Problem",
    -    "Timestamp",
    -    "Timestamp Reply",
    -    "Info Request",
    -    "Info Reply",
    -    "Out of Range Type"
    -};
    +    {
    +        "Echo Reply",
    +        "ICMP 1",
    +        "ICMP 2",
    +        "Destination Unreachable",
    +        "Source Quench",
    +        "Redirect",
    +        "ICMP 6",
    +        "ICMP 7",
    +        "Echo",
    +        "ICMP 9",
    +        "ICMP 10",
    +        "Time Exceeded",
    +        "Parameter Problem",
    +        "Timestamp",
    +        "Timestamp Reply",
    +        "Info Request",
    +        "Info Reply",
    +        "Out of Range Type"
    +    };
     
     static int in_cksum(unsigned short *ptr, int size);
     static void pingerRecv(void);
    +
     static void pingerLog(struct icmphdr *, struct in_addr, int, int);
     static int ipHops(int ttl);
     static void pingerSendtoSquid(pingerReplyData * preply);
    @@ -122,16 +127,21 @@ static void pingerSendtoSquid(pingerReplyData * preply);
     void
     pingerOpen(void)
     {
    +
         struct protoent *proto = NULL;
    +
         if ((proto = getprotobyname("icmp")) == 0) {
    -	debug(42, 0) ("pingerOpen: unknown protocol: icmp\n");
    -	exit(1);
    +        debug(42, 0) ("pingerOpen: unknown protocol: icmp\n");
    +        exit(1);
         }
    +
         icmp_sock = socket(PF_INET, SOCK_RAW, proto->p_proto);
    +
         if (icmp_sock < 0) {
    -	debug(50, 0) ("pingerOpen: icmp_sock: %s\n", xstrerror());
    -	exit(1);
    +        debug(50, 0) ("pingerOpen: icmp_sock: %s\n", xstrerror());
    +        exit(1);
         }
    +
         icmp_ident = getpid() & 0xffff;
         debug(42, 0) ("pinger: ICMP socket opened\n");
     }
    @@ -145,23 +155,31 @@ pingerClose(void)
     }
     
     static void
    +
     pingerSendEcho(struct in_addr to, int opcode, char *payload, int len)
     {
         LOCAL_ARRAY(char, pkt, MAX_PKT_SZ);
    +
         struct icmphdr *icmp = NULL;
         icmpEchoData *echo;
    +
         size_t icmp_pktsize = sizeof(struct icmphdr);
    +
         struct sockaddr_in S;
         memset(pkt, '\0', MAX_PKT_SZ);
    +
         icmp = (struct icmphdr *) (void *) pkt;
     
         /*
          * cevans - beware signed/unsigned issues in untrusted data from
          * the network!!
          */
    -    if (len < 0) {
    -	len = 0;
    +
    +    if (len < 0)
    +    {
    +        len = 0;
         }
    +
         icmp->icmp_type = ICMP_ECHO;
         icmp->icmp_code = 0;
         icmp->icmp_cksum = 0;
    @@ -171,12 +189,17 @@ pingerSendEcho(struct in_addr to, int opcode, char *payload, int len)
         echo->opcode = (unsigned char) opcode;
         echo->tv = current_time;
         icmp_pktsize += sizeof(icmpEchoData) - MAX_PAYLOAD;
    -    if (payload) {
    -	if (len > MAX_PAYLOAD)
    -	    len = MAX_PAYLOAD;
    -	xmemcpy(echo->payload, payload, len);
    -	icmp_pktsize += len;
    +
    +    if (payload)
    +    {
    +        if (len > MAX_PAYLOAD)
    +            len = MAX_PAYLOAD;
    +
    +        xmemcpy(echo->payload, payload, len);
    +
    +        icmp_pktsize += len;
         }
    +
         icmp->icmp_cksum = in_cksum((u_short *) icmp, icmp_pktsize);
         S.sin_family = AF_INET;
         /*
    @@ -186,11 +209,13 @@ pingerSendEcho(struct in_addr to, int opcode, char *payload, int len)
         S.sin_port = 0;
         assert(icmp_pktsize <= MAX_PKT_SZ);
         sendto(icmp_sock,
    -	pkt,
    -	icmp_pktsize,
    -	0,
    -	(struct sockaddr *) &S,
    -	sizeof(struct sockaddr_in));
    +           pkt,
    +           icmp_pktsize,
    +           0,
    +
    +           (struct sockaddr *) &S,
    +
    +           sizeof(struct sockaddr_in));
         pingerLog(icmp, to, 0, 0);
     }
     
    @@ -199,52 +224,84 @@ pingerRecv(void)
     {
         int n;
         socklen_t fromlen;
    +
         struct sockaddr_in from;
         int iphdrlen = 20;
    +
         struct iphdr *ip = NULL;
    +
         struct icmphdr *icmp = NULL;
         static char *pkt = NULL;
    +
         struct timeval now;
         icmpEchoData *echo;
         static pingerReplyData preply;
     
         if (pkt == NULL)
    -	pkt = (char *)xmalloc(MAX_PKT_SZ);
    +        pkt = (char *)xmalloc(MAX_PKT_SZ);
    +
         fromlen = sizeof(from);
    +
         n = recvfrom(icmp_sock,
    -	pkt,
    -	MAX_PKT_SZ,
    -	0,
    -	(struct sockaddr *) &from,
    -	&fromlen);
    +                 pkt,
    +                 MAX_PKT_SZ,
    +                 0,
    +
    +                 (struct sockaddr *) &from,
    +                 &fromlen);
    +
     #if GETTIMEOFDAY_NO_TZP
    +
         gettimeofday(&now);
    +
     #else
    +
         gettimeofday(&now, NULL);
    +
     #endif
    +
         debug(42, 9) ("pingerRecv: %d bytes from %s\n", n, inet_ntoa(from.sin_addr));
    +
         ip = (struct iphdr *) (void *) pkt;
    +
     #if HAVE_STRUCT_IPHDR_IP_HL
    +
         iphdrlen = ip->ip_hl << 2;
    +
     #else /* HAVE_STRUCT_IPHDR_IP_HL */
     #if WORDS_BIGENDIAN
    +
         iphdrlen = (ip->ip_vhl >> 4) << 2;
    +
     #else
    +
         iphdrlen = (ip->ip_vhl & 0xF) << 2;
    +
     #endif
     #endif /* HAVE_STRUCT_IPHDR_IP_HL */
    +
         icmp = (struct icmphdr *) (void *) (pkt + iphdrlen);
    +
         if (icmp->icmp_type != ICMP_ECHOREPLY)
    -	return;
    +        return;
    +
         if (icmp->icmp_id != icmp_ident)
    -	return;
    +        return;
    +
         echo = (icmpEchoData *) (void *) (icmp + 1);
    +
         preply.from = from.sin_addr;
    +
         preply.opcode = echo->opcode;
    +
         preply.hops = ipHops(ip->ip_ttl);
    +
         preply.rtt = tvSubMsec(echo->tv, now);
    +
         preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT_SZ);
    +
         pingerSendtoSquid(&preply);
    +
         pingerLog(icmp, from.sin_addr, preply.rtt, preply.hops);
     }
     
    @@ -256,15 +313,18 @@ in_cksum(unsigned short *ptr, int size)
         unsigned short oddbyte;
         unsigned short answer;
         sum = 0;
    +
         while (size > 1) {
    -	sum += *ptr++;
    -	size -= 2;
    +        sum += *ptr++;
    +        size -= 2;
         }
    +
         if (size == 1) {
    -	oddbyte = 0;
    -	*((unsigned char *) &oddbyte) = *(unsigned char *) ptr;
    -	sum += oddbyte;
    +        oddbyte = 0;
    +        *((unsigned char *) &oddbyte) = *(unsigned char *) ptr;
    +        sum += oddbyte;
         }
    +
         sum = (sum >> 16) + (sum & 0xffff);
         sum += (sum >> 16);
         answer = ~sum;
    @@ -272,31 +332,37 @@ in_cksum(unsigned short *ptr, int size)
     }
     
     static void
    +
     pingerLog(struct icmphdr *icmp, struct in_addr addr, int rtt, int hops)
     {
         debug(42, 2) ("pingerLog: %9d.%06d %-16s %d %-15.15s %dms %d hops\n",
    -	(int) current_time.tv_sec,
    -	(int) current_time.tv_usec,
    -	inet_ntoa(addr),
    -	(int) icmp->icmp_type,
    -	icmpPktStr[icmp->icmp_type],
    -	rtt,
    -	hops);
    +                  (int) current_time.tv_sec,
    +                  (int) current_time.tv_usec,
    +                  inet_ntoa(addr),
    +                  (int) icmp->icmp_type,
    +                  icmpPktStr[icmp->icmp_type],
    +                  rtt,
    +                  hops);
     }
     
     static int
     ipHops(int ttl)
     {
         if (ttl < 33)
    -	return 33 - ttl;
    +        return 33 - ttl;
    +
         if (ttl < 63)
    -	return 63 - ttl;	/* 62 = (64+60)/2 */
    +        return 63 - ttl;	/* 62 = (64+60)/2 */
    +
         if (ttl < 65)
    -	return 65 - ttl;	/* 62 = (64+60)/2 */
    +        return 65 - ttl;	/* 62 = (64+60)/2 */
    +
         if (ttl < 129)
    -	return 129 - ttl;
    +        return 129 - ttl;
    +
         if (ttl < 193)
    -	return 193 - ttl;
    +        return 193 - ttl;
    +
         return 256 - ttl;
     }
     
    @@ -308,25 +374,30 @@ pingerReadRequest(void)
         int guess_size;
         memset(&pecho, '\0', sizeof(pecho));
         n = recv(0, (char *) &pecho, sizeof(pecho), 0);
    +
         if (n < 0)
    -	return n;
    +        return n;
    +
         if (0 == n) {
    -	/* EOF indicator */
    -	fprintf(stderr, "EOF encountered\n");
    -	errno = 0;
    -	return -1;
    +        /* EOF indicator */
    +        fprintf(stderr, "EOF encountered\n");
    +        errno = 0;
    +        return -1;
         }
    +
         guess_size = n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ);
    +
         if (guess_size != pecho.psize) {
    -	fprintf(stderr, "size mismatch, guess=%d psize=%d\n",
    -	    guess_size, pecho.psize);
    -	/* don't process this message, but keep running */
    -	return 0;
    +        fprintf(stderr, "size mismatch, guess=%d psize=%d\n",
    +                guess_size, pecho.psize);
    +        /* don't process this message, but keep running */
    +        return 0;
         }
    +
         pingerSendEcho(pecho.to,
    -	pecho.opcode,
    -	pecho.payload,
    -	pecho.psize);
    +                   pecho.opcode,
    +                   pecho.payload,
    +                   pecho.psize);
         return n;
     }
     
    @@ -334,9 +405,10 @@ static void
     pingerSendtoSquid(pingerReplyData * preply)
     {
         int len = sizeof(pingerReplyData) - MAX_PKT_SZ + preply->psize;
    +
         if (send(1, (char *) preply, len, 0) < 0) {
    -	debug(50, 0) ("pinger: send: %s\n", xstrerror());
    -	exit(1);
    +        debug(50, 0) ("pinger: send: %s\n", xstrerror());
    +        exit(1);
         }
     }
     
    @@ -346,8 +418,10 @@ getCurrentTime(void)
     #if GETTIMEOFDAY_NO_TZP
         gettimeofday(¤t_time);
     #else
    +
         gettimeofday(¤t_time, NULL);
     #endif
    +
         return squid_curtime = current_time.tv_sec;
     }
     
    @@ -357,47 +431,56 @@ main(int argc, char *argv[])
     {
         fd_set R;
         int x;
    +
         struct timeval tv;
         const char *debug_args = "ALL,1";
         char *t;
         time_t last_check_time = 0;
     
    -/*
    - * cevans - do this first. It grabs a raw socket. After this we can
    - * drop privs
    - */
    +    /*
    +     * cevans - do this first. It grabs a raw socket. After this we can
    +     * drop privs
    +     */
         pingerOpen();
         setgid(getgid());
         setuid(getuid());
     
         if ((t = getenv("SQUID_DEBUG")))
    -	debug_args = xstrdup(t);
    +        debug_args = xstrdup(t);
    +
         getCurrentTime();
    +
         _db_init(NULL, debug_args);
     
         for (;;) {
    -	tv.tv_sec = 10;
    -	tv.tv_usec = 0;
    -	FD_ZERO(&R);
    -	FD_SET(0, &R);
    -	FD_SET(icmp_sock, &R);
    -	x = select(icmp_sock + 1, &R, NULL, NULL, &tv);
    -	getCurrentTime();
    -	if (x < 0)
    -	    exit(1);
    -	if (FD_ISSET(0, &R))
    -	    if (pingerReadRequest() < 0) {
    -		debug(42, 0) ("Pinger exiting.\n");
    -		exit(1);
    -	    }
    -	if (FD_ISSET(icmp_sock, &R))
    -	    pingerRecv();
    -	if (10 + last_check_time < squid_curtime) {
    -	    if (send(1, (char *) &tv, 0, 0) < 0)
    -		exit(1);
    -	    last_check_time = squid_curtime;
    -	}
    +        tv.tv_sec = 10;
    +        tv.tv_usec = 0;
    +        FD_ZERO(&R);
    +        FD_SET(0, &R);
    +        FD_SET(icmp_sock, &R);
    +        x = select(icmp_sock + 1, &R, NULL, NULL, &tv);
    +        getCurrentTime();
    +
    +        if (x < 0)
    +            exit(1);
    +
    +        if (FD_ISSET(0, &R))
    +            if (pingerReadRequest() < 0) {
    +                debug(42, 0) ("Pinger exiting.\n");
    +                exit(1);
    +            }
    +
    +        if (FD_ISSET(icmp_sock, &R))
    +            pingerRecv();
    +
    +        if (10 + last_check_time < squid_curtime) {
    +            if (send(1, (char *) &tv, 0, 0) < 0)
    +                exit(1);
    +
    +            last_check_time = squid_curtime;
    +        }
         }
    +
         /* NOTREACHED */
     }
     
    @@ -409,4 +492,5 @@ main(int argc, char *argv[])
         fprintf(stderr, "%s: ICMP support not compiled in.\n", argv[0]);
         return 1;
     }
    +
     #endif /* USE_ICMP */
    diff --git a/src/protos.h b/src/protos.h
    index da446141c3..390ed929ba 100644
    --- a/src/protos.h
    +++ b/src/protos.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: protos.h,v 1.467 2003/02/21 19:53:02 hno Exp $
    + * $Id: protos.h,v 1.468 2003/02/21 22:50:10 robertc Exp $
      *
      *
      * SQUID Web Proxy Cache          http://www.squid-cache.org/
    @@ -77,7 +77,9 @@ SQUIDCEXTERN void parse_eol(char *volatile *var);
     SQUIDCEXTERN void parse_wordlist(wordlist ** list);
     SQUIDCEXTERN void requirePathnameExists(const char *name, const char *path);
     SQUIDCEXTERN void parse_time_t(time_t * var);
    +
     SQUIDCEXTERN void parse_cachedir_options(SwapDir * sd, struct cache_dir_option *options, int reconfiguring);
    +
     SQUIDCEXTERN void dump_cachedir_options(StoreEntry * e, struct cache_dir_option *options, SwapDir const * sd);
     SQUIDCEXTERN void parse_sockaddr_in_list_token(sockaddr_in_list **, char *);
     
    @@ -105,10 +107,13 @@ SQUIDCEXTERN cbdata_type cbdataInternalAddType(cbdata_type type, const char *lab
     /* client_side.c - FD related client side routines */
     
     SQUIDCEXTERN void clientdbInit(void);
    +
     SQUIDCEXTERN void clientdbUpdate(struct in_addr, log_type, protocol_t, size_t);
    +
     SQUIDCEXTERN int clientdbCutoffDenied(struct in_addr);
     SQUIDCEXTERN void clientdbDump(StoreEntry *);
     SQUIDCEXTERN void clientdbFreeMemory(void);
    +
     SQUIDCEXTERN int clientdbEstablished(struct in_addr, int);
     SQUIDCEXTERN void clientOpenListenSockets(void);
     SQUIDCEXTERN void clientHttpConnectionsClose(void);
    @@ -119,6 +124,7 @@ SQUIDCEXTERN void httpRequestFree(void *);
     extern void clientAccessCheck(void *);
     
     /* client_side_reply.c - client side reply related routines (pure logic, no comms) */
    +
     SQUIDCEXTERN void clientSetReplyToError(void *, err_type, http_status, method_t, char const *, struct in_addr *, request_t *, char *, auth_user_request_t * auth_user_request);
     
     /* comm.c */
    @@ -137,22 +143,26 @@ SQUIDCEXTERN void comm_reset_close(int fd);
     SQUIDCEXTERN void comm_lingering_close(int fd);
     #endif
     SQUIDCEXTERN void commConnectStart(int fd, const char *, u_short, CNCB *, void *);
    +
     SQUIDCEXTERN int comm_connect_addr(int sock, const struct sockaddr_in *);
     SQUIDCEXTERN void comm_init(void);
    +
     SQUIDCEXTERN int comm_open(int, int, struct in_addr, u_short port, int, const char *note);
    +
     SQUIDCEXTERN int comm_openex(int, int, struct in_addr, u_short, int, unsigned char TOS, const char *);
     SQUIDCEXTERN u_short comm_local_port(int fd);
     
     SQUIDCEXTERN void commSetSelect(int, unsigned int, PF *, void *, time_t);
     SQUIDCEXTERN void comm_add_close_handler(int fd, PF *, void *);
     SQUIDCEXTERN void comm_remove_close_handler(int fd, PF *, void *);
    +
     SQUIDCEXTERN int comm_udp_sendto(int, const struct sockaddr_in *, int, const void *, int);
     SQUIDCEXTERN void comm_old_write(int fd,
    -    const char *buf,
    -    int size,
    -    CWCB * handler,
    -    void *handler_data,
    -    FREE *);
    +                                 const char *buf,
    +                                 int size,
    +                                 CWCB * handler,
    +                                 void *handler_data,
    +                                 FREE *);
     SQUIDCEXTERN void comm_old_write_mbuf(int fd, MemBuf mb, CWCB * handler, void *handler_data);
     SQUIDCEXTERN void commCallCloseHandlers(int fd);
     SQUIDCEXTERN int commSetTimeout(int fd, int, PF *, void *);
    @@ -228,6 +238,7 @@ SQUIDCEXTERN void dnsSubmit(const char *lookup, HLPCB * callback, void *data);
     SQUIDCEXTERN void idnsInit(void);
     SQUIDCEXTERN void idnsShutdown(void);
     SQUIDCEXTERN void idnsALookup(const char *, IDNSCB *, void *);
    +
     SQUIDCEXTERN void idnsPTRLookup(const struct in_addr, IDNSCB *, void *);
     
     SQUIDCEXTERN void eventAdd(const char *name, EVH * func, void *arg, double when, int);
    @@ -257,10 +268,12 @@ SQUIDCEXTERN void filemapFreeMemory(fileMap *);
     
     
     SQUIDCEXTERN void fqdncache_nbgethostbyaddr(struct in_addr, FQDNH *, void *);
    +
     SQUIDCEXTERN const char *fqdncache_gethostbyaddr(struct in_addr, int flags);
     SQUIDCEXTERN void fqdncache_init(void);
     SQUIDCEXTERN void fqdnStats(StoreEntry *);
     SQUIDCEXTERN void fqdncacheReleaseInvalid(const char *);
    +
     SQUIDCEXTERN const char *fqdnFromAddr(struct in_addr);
     SQUIDCEXTERN int fqdncacheQueueDrain(void);
     SQUIDCEXTERN void fqdncacheFreeMemory(void);
    @@ -282,11 +295,11 @@ SQUIDCEXTERN int httpCachable(method_t);
     SQUIDCEXTERN void httpStart(FwdState *);
     SQUIDCEXTERN void httpParseReplyHeaders(const char *, http_reply *);
     SQUIDCEXTERN mb_size_t httpBuildRequestPrefix(request_t * request,
    -    request_t * orig_request,
    -    StoreEntry * entry,
    -    MemBuf * mb,
    -    int cfd,
    -    http_state_flags);
    +        request_t * orig_request,
    +        StoreEntry * entry,
    +        MemBuf * mb,
    +        int cfd,
    +        http_state_flags);
     SQUIDCEXTERN void httpAnonInitModule(void);
     SQUIDCEXTERN int httpAnonHdrAllowed(http_hdr_type hdr_id);
     SQUIDCEXTERN int httpAnonHdrDenied(http_hdr_type hdr_id);
    @@ -304,12 +317,12 @@ SQUIDCEXTERN void httpStatusLineInit(HttpStatusLine * sline);
     SQUIDCEXTERN void httpStatusLineClean(HttpStatusLine * sline);
     /* set/get values */
     SQUIDCEXTERN void httpStatusLineSet(HttpStatusLine * sline, http_version_t version,
    -    http_status status, const char *reason);
    +                                    http_status status, const char *reason);
     SQUIDCEXTERN const char *httpStatusLineReason(const HttpStatusLine * sline);
     /* parse/pack */
     /* parse a 0-terminating buffer and fill internal structires; returns true on success */
     SQUIDCEXTERN int httpStatusLineParse(HttpStatusLine * sline, const char *start,
    -    const char *end);
    +                                     const char *end);
     /* pack fields using Packer */
     SQUIDCEXTERN void httpStatusLinePackInto(const HttpStatusLine * sline, Packer * p);
     SQUIDCEXTERN const char *httpStatusString(http_status status);
    @@ -422,7 +435,9 @@ SQUIDCEXTERN int httpMsgIsolateHeaders(const char **parse_start, const char **bl
     
     SQUIDCEXTERN void icmpOpen(void);
     SQUIDCEXTERN void icmpClose(void);
    +
     SQUIDCEXTERN void icmpSourcePing(struct in_addr to, const icp_common_t *, const char *url);
    +
     SQUIDCEXTERN void icmpDomainPing(struct in_addr to, const char *domain);
     
     #ifdef SQUID_SNMP
    @@ -432,8 +447,11 @@ SQUIDCEXTERN void snmpConnectionOpen(void);
     SQUIDCEXTERN void snmpConnectionShutdown(void);
     SQUIDCEXTERN void snmpConnectionClose(void);
     SQUIDCEXTERN void snmpDebugOid(int lvl, oid * Name, snint Len);
    +
     SQUIDCEXTERN void addr2oid(struct in_addr addr, oid * Dest);
    +
     SQUIDCEXTERN struct in_addr *oid2addr(oid * id);
    +
     SQUIDCEXTERN struct in_addr *client_entry(struct in_addr *current);
     SQUIDCEXTERN variable_list *snmp_basicFn(variable_list *, snint *);
     SQUIDCEXTERN variable_list *snmp_confFn(variable_list *, snint *);
    @@ -460,8 +478,8 @@ SQUIDCEXTERN void wccpConnectionClose(void);
     #endif /* USE_WCCP */
     
     SQUIDCEXTERN void ipcache_nbgethostbyname(const char *name,
    -    IPH * handler,
    -    void *handlerData);
    +        IPH * handler,
    +        void *handlerData);
     SQUIDCEXTERN EVH ipcache_purgelru;
     SQUIDCEXTERN const ipcache_addrs *ipcache_gethostbyname(const char *, int flags);
     SQUIDCEXTERN void ipcacheInvalidate(const char *);
    @@ -470,7 +488,9 @@ SQUIDCEXTERN void ipcache_init(void);
     SQUIDCEXTERN void stat_ipcache_get(StoreEntry *);
     SQUIDCEXTERN int ipcacheQueueDrain(void);
     SQUIDCEXTERN void ipcacheCycleAddr(const char *name, ipcache_addrs *);
    +
     SQUIDCEXTERN void ipcacheMarkBadAddr(const char *name, struct in_addr);
    +
     SQUIDCEXTERN void ipcacheMarkGoodAddr(const char *name, struct in_addr);
     SQUIDCEXTERN void ipcacheFreeMemory(void);
     SQUIDCEXTERN ipcache_addrs *ipcacheCheckNumeric(const char *name);
    @@ -505,12 +525,13 @@ SQUIDCEXTERN peer *getNextPeer(peer *);
     SQUIDCEXTERN peer *getSingleParent(request_t *);
     SQUIDCEXTERN int neighborsCount(request_t *);
     SQUIDCEXTERN int neighborsUdpPing(request_t *,
    -    StoreEntry *,
    -    IRCB * callback,
    -    void *data,
    -    int *exprep,
    -    int *timeout);
    +                                  StoreEntry *,
    +                                  IRCB * callback,
    +                                  void *data,
    +                                  int *exprep,
    +                                  int *timeout);
     SQUIDCEXTERN void neighborAddAcl(const char *, const char *);
    +
     SQUIDCEXTERN void neighborsUdpAck(const cache_key *, icp_common_t *, const struct sockaddr_in *);
     SQUIDCEXTERN void neighborAdd(const char *, const char *, int, int, int, int, int);
     SQUIDCEXTERN void neighbors_init(void);
    @@ -533,23 +554,29 @@ SQUIDCEXTERN void peerConnectFailed(peer *);
     SQUIDCEXTERN void peerConnectSucceded(peer *);
     SQUIDCEXTERN void dump_peer_options(StoreEntry *, peer *);
     SQUIDCEXTERN int peerHTTPOkay(const peer *, request_t *);
    +
     SQUIDCEXTERN peer *whichPeer(const struct sockaddr_in *from);
     #if USE_HTCP
    +
     SQUIDCEXTERN void neighborsHtcpReply(const cache_key *, htcpReplyData *, const struct sockaddr_in *);
     #endif
     
     SQUIDCEXTERN void netdbInit(void);
    +
     SQUIDCEXTERN void netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt);
     SQUIDCEXTERN void netdbPingSite(const char *hostname);
     SQUIDCEXTERN void netdbDump(StoreEntry *);
    +
     SQUIDCEXTERN int netdbHops(struct in_addr);
     SQUIDCEXTERN void netdbFreeMemory(void);
     SQUIDCEXTERN int netdbHostHops(const char *host);
     SQUIDCEXTERN int netdbHostRtt(const char *host);
     SQUIDCEXTERN void netdbUpdatePeer(request_t *, peer * e, int rtt, int hops);
    +
     SQUIDCEXTERN void netdbDeleteAddrNetwork(struct in_addr addr);
     SQUIDCEXTERN void netdbBinaryExchange(StoreEntry *);
     SQUIDCEXTERN EVH netdbExchangeStart;
    +
     SQUIDCEXTERN void netdbExchangeUpdatePeer(struct in_addr, peer *, double, double);
     SQUIDCEXTERN peer *netdbClosestParent(request_t *);
     SQUIDCEXTERN void netdbHostData(const char *host, int *samp, int *rtt, int *hops);
    @@ -580,6 +607,7 @@ SQUIDCEXTERN void fwdUninit(void);
     SQUIDCEXTERN void fwdLogRotate(void);
     SQUIDCEXTERN void fwdStatus(FwdState *, http_status);
     #endif
    +
     SQUIDCEXTERN struct in_addr getOutgoingAddr(request_t * request);
     unsigned long getOutgoingTOS(request_t * request);
     
    @@ -622,8 +650,9 @@ extern void waisStart(FwdState *);
     
     /* ident.c */
     #if USE_IDENT
    +
     SQUIDCEXTERN void identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer,
    -    IDCB * callback, void *cbdata);
    +                             IDCB * callback, void *cbdata);
     SQUIDCEXTERN void identInit(void);
     #endif
     
    @@ -774,6 +803,7 @@ SQUIDCEXTERN int storeDirGetUFSStats(const char *, int *, int *, int *, int *);
      * store_rebuild.c
      */
     SQUIDCEXTERN void storeRebuildStart(void);
    +
     SQUIDCEXTERN void storeRebuildComplete(struct _store_rebuild_data *);
     SQUIDCEXTERN void storeRebuildProgress(int sd_index, int total, int sofar);
     
    @@ -825,15 +855,20 @@ SQUIDCEXTERN int percent(int, int);
     SQUIDCEXTERN double dpercent(double, double);
     SQUIDCEXTERN void squid_signal(int sig, SIGHDLR *, int flags);
     SQUIDCEXTERN pid_t readPidFile(void);
    +
     SQUIDCEXTERN struct in_addr inaddrFromHostent(const struct hostent *hp);
     SQUIDCEXTERN int intAverage(int, int, int, int);
     SQUIDCEXTERN double doubleAverage(double, double, int, int);
     SQUIDCEXTERN void debug_trap(const char *);
     SQUIDCEXTERN void logsFlush(void);
     SQUIDCEXTERN const char *checkNullString(const char *p);
    +
     SQUIDCEXTERN void squid_getrusage(struct rusage *r);
    +
     SQUIDCEXTERN double rusage_cputime(struct rusage *r);
    +
     SQUIDCEXTERN int rusage_maxrss(struct rusage *r);
    +
     SQUIDCEXTERN int rusage_pagefaults(struct rusage *r);
     SQUIDCEXTERN void releaseServerSockets(void);
     SQUIDCEXTERN void PrintRusage(void);
    @@ -921,11 +956,11 @@ SQUIDCEXTERN void htcpSocketClose(void);
      * ipc.c
      */
     SQUIDCEXTERN int ipcCreate(int type,
    -    const char *prog,
    -    const char *const args[],
    -    const char *name,
    -    int *rfd,
    -    int *wfd);
    +                           const char *prog,
    +                           const char *const args[],
    +                           const char *name,
    +                           int *rfd,
    +                           int *wfd);
     
     /* CacheDigest */
     SQUIDCEXTERN CacheDigest *cacheDigestCreate(int capacity, int bpe);
    @@ -1005,6 +1040,7 @@ SQUIDCEXTERN RemovalPolicy *createRemovalPolicy(RemovalPolicySettings * settings
      */
     
     #ifdef _SQUID_SOLARIS_
    +
     SQUIDCEXTERN int getrusage(int, struct rusage *);
     SQUIDCEXTERN int getpagesize(void);
     SQUIDCEXTERN int gethostname(char *, int);
    diff --git a/src/recv-announce.cc b/src/recv-announce.cc
    index 7482700017..9e7d18b748 100644
    --- a/src/recv-announce.cc
    +++ b/src/recv-announce.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: recv-announce.cc,v 1.25 2003/01/23 00:37:25 robertc Exp $
    + * $Id: recv-announce.cc,v 1.26 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 0     Announcement Server
      * AUTHOR: Harvest Derived
    @@ -66,7 +66,7 @@
      * 
      */
     
    -/* 
    +/*
      * usage: recv-announce logfile
      */
     
    @@ -85,47 +85,53 @@ int
     main(int argc, char *argv[])
     {
         char buf[RECV_BUF_SIZE];
    +
         struct sockaddr_in R;
         socklen_t len;
    +
         struct hostent *hp = NULL;
         char logfile[BUFSIZ];
         char ip[4];
     
         for (len = 0; len < 32; len++) {
    -	signal(len, sig_handle);
    +        signal(len, sig_handle);
         }
     
     
         if (argc > 1)
    -	strcpy(logfile, argv[1]);
    +        strcpy(logfile, argv[1]);
         else
    -	strcpy(logfile, "/tmp/recv-announce.log");
    +        strcpy(logfile, "/tmp/recv-announce.log");
     
         close(1);
    +
         if (open(logfile, O_WRONLY | O_CREAT | O_APPEND, 0660) < 0) {
    -	perror(logfile);
    -	exit(1);
    +        perror(logfile);
    +        exit(1);
         }
    +
         close(2);
         dup(1);
     
     
         for (;;) {
    -	memset(buf, '\0', RECV_BUF_SIZE);
    -	memset(&R, '\0', len = sizeof(R));
    -
    -	if (recvfrom(0, buf, RECV_BUF_SIZE, 0, (sockaddr *)&R, &len) < 0) {
    -	    perror("recv");
    -	    exit(2);
    -	}
    -	xmemcpy(ip, &R.sin_addr.s_addr, 4);
    -	hp = gethostbyaddr(ip, 4, AF_INET);
    -	printf("==============================================================================\n");
    -	printf("Received from %s [%s]\n",
    -	    inet_ntoa(R.sin_addr),
    -	    (hp && hp->h_name) ? hp->h_name : "Unknown");
    -	fputs(buf, stdout);
    -	fflush(stdout);
    +        memset(buf, '\0', RECV_BUF_SIZE);
    +        memset(&R, '\0', len = sizeof(R));
    +
    +        if (recvfrom(0, buf, RECV_BUF_SIZE, 0, (sockaddr *)&R, &len) < 0) {
    +            perror("recv");
    +            exit(2);
    +        }
    +
    +        xmemcpy(ip, &R.sin_addr.s_addr, 4);
    +        hp = gethostbyaddr(ip, 4, AF_INET);
    +        printf("==============================================================================\n");
    +        printf("Received from %s [%s]\n",
    +               inet_ntoa(R.sin_addr),
    +               (hp && hp->h_name) ? hp->h_name : "Unknown");
    +        fputs(buf, stdout);
    +        fflush(stdout);
         }
    +
         return 0;
     }
    diff --git a/src/redirect.cc b/src/redirect.cc
    index c00b9b0bf4..8c07ebf346 100644
    --- a/src/redirect.cc
    +++ b/src/redirect.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: redirect.cc,v 1.95 2003/02/12 06:11:04 robertc Exp $
    + * $Id: redirect.cc,v 1.96 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 61    Redirector
      * AUTHOR: Duane Wessels
    @@ -40,14 +40,18 @@
     #include "ACLChecklist.h"
     #include "HttpRequest.h"
     
    -typedef struct {
    +typedef struct
    +{
         void *data;
         char *orig_url;
    +
         struct in_addr client_addr;
         const char *client_ident;
         const char *method_s;
         RH *handler;
    -} redirectStateData;
    +}
    +
    +redirectStateData;
     
     static HLPCB redirectHandleReply;
     static void redirectStateFree(redirectStateData * r);
    @@ -63,14 +67,18 @@ redirectHandleReply(void *data, char *reply)
         char *t;
         void *cbdata;
         debug(61, 5) ("redirectHandleRead: {%s}\n", reply ? reply : "");
    +
         if (reply) {
    -	if ((t = strchr(reply, ' ')))
    -	    *t = '\0';
    -	if (*reply == '\0')
    -	    reply = NULL;
    +        if ((t = strchr(reply, ' ')))
    +            *t = '\0';
    +
    +        if (*reply == '\0')
    +            reply = NULL;
         }
    +
         if (cbdataReferenceValidDone(r->data, &cbdata))
    -	r->handler(cbdata, reply);
    +        r->handler(cbdata, reply);
    +
         redirectStateFree(r);
     }
     
    @@ -86,9 +94,10 @@ redirectStats(StoreEntry * sentry)
     {
         storeAppendPrintf(sentry, "Redirector Statistics:\n");
         helperStats(sentry, redirectors);
    +
         if (Config.onoff.redirector_bypass)
    -	storeAppendPrintf(sentry, "\nNumber of requests bypassed "
    -	    "because all redirectors were busy: %d\n", n_bypassed);
    +        storeAppendPrintf(sentry, "\nNumber of requests bypassed "
    +                          "because all redirectors were busy: %d\n", n_bypassed);
     }
     
     /**** PUBLIC FUNCTIONS ****/
    @@ -103,49 +112,59 @@ redirectStart(clientHttpRequest * http, RH * handler, void *data)
         assert(http);
         assert(handler);
         debug(61, 5) ("redirectStart: '%s'\n", http->uri);
    +
         if (Config.Program.redirect == NULL) {
    -	handler(data, NULL);
    -	return;
    +        handler(data, NULL);
    +        return;
         }
    +
         if (Config.accessList.redirector) {
    -	ACLChecklist ch;
    -	ch.src_addr = http->conn->peer.sin_addr;
    -	ch.my_addr = http->conn->me.sin_addr;
    -	ch.my_port = ntohs(http->conn->me.sin_port);
    -	ch.request = requestLink(http->request);
    -	if (!aclCheckFast(Config.accessList.redirector, &ch)) {
    -	    /* denied -- bypass redirector */
    -	    handler(data, NULL);
    -	    return;
    -	}
    +        ACLChecklist ch;
    +        ch.src_addr = http->conn->peer.sin_addr;
    +        ch.my_addr = http->conn->me.sin_addr;
    +        ch.my_port = ntohs(http->conn->me.sin_port);
    +        ch.request = requestLink(http->request);
    +
    +        if (!aclCheckFast(Config.accessList.redirector, &ch)) {
    +            /* denied -- bypass redirector */
    +            handler(data, NULL);
    +            return;
    +        }
         }
    +
         if (Config.onoff.redirector_bypass && redirectors->stats.queue_size) {
    -	/* Skip redirector if there is one request queued */
    -	n_bypassed++;
    -	handler(data, NULL);
    -	return;
    +        /* Skip redirector if there is one request queued */
    +        n_bypassed++;
    +        handler(data, NULL);
    +        return;
         }
    +
         r = cbdataAlloc(redirectStateData);
         r->orig_url = xstrdup(http->uri);
         r->client_addr = conn->log_addr;
    +
         if (http->request->auth_user_request)
    -	r->client_ident = authenticateUserRequestUsername(http->request->auth_user_request);
    +        r->client_ident = authenticateUserRequestUsername(http->request->auth_user_request);
         else if (conn->rfc931[0]) {
    -	r->client_ident = conn->rfc931;
    +        r->client_ident = conn->rfc931;
         } else {
    -	r->client_ident = dash_str;
    +        r->client_ident = dash_str;
         }
    +
         r->method_s = RequestMethodStr[http->request->method];
         r->handler = handler;
         r->data = cbdataReference(data);
    +
         if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
    -	fqdn = dash_str;
    +        fqdn = dash_str;
    +
         snprintf(buf, 8192, "%s %s/%s %s %s\n",
    -	r->orig_url,
    -	inet_ntoa(r->client_addr),
    -	fqdn,
    -	r->client_ident,
    -	r->method_s);
    +             r->orig_url,
    +             inet_ntoa(r->client_addr),
    +             fqdn,
    +             r->client_ident,
    +             r->method_s);
    +
         helperSubmit(redirectors, buf, redirectHandleReply, r);
     }
     
    @@ -153,20 +172,27 @@ void
     redirectInit(void)
     {
         static int init = 0;
    +
         if (!Config.Program.redirect)
    -	return;
    +        return;
    +
         if (redirectors == NULL)
    -	redirectors = helperCreate("redirector");
    +        redirectors = helperCreate("redirector");
    +
         redirectors->cmdline = Config.Program.redirect;
    +
         redirectors->n_to_start = Config.redirectChildren;
    +
         redirectors->ipc_type = IPC_STREAM;
    +
         helperOpenServers(redirectors);
    +
         if (!init) {
    -	cachemgrRegister("redirector",
    -	    "URL Redirector Stats",
    -	    redirectStats, 0, 1);
    -	init = 1;
    -	CBDATA_INIT_TYPE(redirectStateData);
    +        cachemgrRegister("redirector",
    +                         "URL Redirector Stats",
    +                         redirectStats, 0, 1);
    +        init = 1;
    +        CBDATA_INIT_TYPE(redirectStateData);
         }
     }
     
    @@ -174,10 +200,14 @@ void
     redirectShutdown(void)
     {
         if (!redirectors)
    -	return;
    +        return;
    +
         helperShutdown(redirectors);
    +
         if (!shutting_down)
    -	return;
    +        return;
    +
         helperFree(redirectors);
    +
         redirectors = NULL;
     }
    diff --git a/src/referer.cc b/src/referer.cc
    index d93441a734..a04bac5f1b 100644
    --- a/src/referer.cc
    +++ b/src/referer.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: referer.cc,v 1.6 2003/01/23 00:37:25 robertc Exp $
    + * $Id: referer.cc,v 1.7 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 40    User-Agent and Referer logging
      * AUTHOR: Joe Ramey  (useragent)
    @@ -45,10 +45,12 @@ refererOpenLog(void)
     {
     #if USE_REFERER_LOG
         assert(NULL == refererlog);
    +
         if (!Config.Log.referer || (0 == strcmp(Config.Log.referer, "none"))) {
    -	debug(40, 1) ("Referer logging is disabled.\n");
    -	return;
    +        debug(40, 1) ("Referer logging is disabled.\n");
    +        return;
         }
    +
         refererlog = logfileOpen(Config.Log.referer, 0, 1);
     #endif
     }
    @@ -57,9 +59,12 @@ void
     refererRotateLog(void)
     {
     #if USE_REFERER_LOG
    +
         if (NULL == refererlog)
    -	return;
    +        return;
    +
         logfileRotate(refererlog);
    +
     #endif
     }
     
    @@ -67,14 +72,17 @@ void
     logReferer(const char *client, const char *referer, const char *uri)
     {
     #if USE_REFERER_LOG
    +
         if (NULL == refererlog)
    -	return;
    +        return;
    +
         logfilePrintf(refererlog, "%9d.%03d %s %s %s\n",
    -	(int) current_time.tv_sec,
    -	(int) current_time.tv_usec / 1000,
    -	client,
    -	referer,
    -	uri ? uri : "-");
    +                  (int) current_time.tv_sec,
    +                  (int) current_time.tv_usec / 1000,
    +                  client,
    +                  referer,
    +                  uri ? uri : "-");
    +
     #endif
     }
     
    @@ -82,9 +90,13 @@ void
     refererCloseLog(void)
     {
     #if USE_REFERER_LOG
    +
         if (NULL == refererlog)
    -	return;
    +        return;
    +
         logfileClose(refererlog);
    +
         refererlog = NULL;
    +
     #endif
     }
    diff --git a/src/refresh.cc b/src/refresh.cc
    index 0020a33e04..9e82642a7d 100644
    --- a/src/refresh.cc
    +++ b/src/refresh.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: refresh.cc,v 1.59 2003/01/23 00:37:25 robertc Exp $
    + * $Id: refresh.cc,v 1.60 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 22    Refresh Calculation
      * AUTHOR: Harvest Derived
    @@ -54,12 +54,21 @@ typedef enum {
         rcCount
     } refreshCountsEnum;
     
    -typedef struct {
    -    unsigned int expires:1;
    -    unsigned int min:1;
    -    unsigned int lmfactor:1;
    +typedef struct
    +{
    +
    +unsigned int expires:
    +    1;
    +
    +unsigned int min:
    +    1;
    +
    +unsigned int lmfactor:
    +    1;
         unsigned int max;
    -} stale_flags;
    +}
    +
    +stale_flags;
     
     /*
      * This enumerated list assigns specific values, ala HTTP/FTP status
    @@ -85,11 +94,14 @@ enum {
         STALE_DEFAULT = 299
     };
     
    -static struct RefreshCounts {
    +static struct RefreshCounts
    +{
         const char *proto;
         int total;
         int status[STALE_DEFAULT + 1];
    -} refreshCounts[rcCount];
    +}
    +
    +refreshCounts[rcCount];
     
     /*
      * Defaults:
    @@ -112,10 +124,12 @@ static const refresh_t *
     refreshLimits(const char *url)
     {
         const refresh_t *R;
    +
         for (R = Config.Refresh; R; R = R->next) {
    -	if (!regexec(&(R->compiled_pattern), url, 0, 0, 0))
    -	    return R;
    +        if (!regexec(&(R->compiled_pattern), url, 0, 0, 0))
    +            return R;
         }
    +
         return NULL;
     }
     
    @@ -123,10 +137,12 @@ static const refresh_t *
     refreshUncompiledPattern(const char *pat)
     {
         const refresh_t *R;
    +
         for (R = Config.Refresh; R; R = R->next) {
    -	if (0 == strcmp(R->pattern, pat))
    -	    return R;
    +        if (0 == strcmp(R->pattern, pat))
    +            return R;
         }
    +
         return NULL;
     }
     
    @@ -150,57 +166,65 @@ refreshStaleness(const StoreEntry * entry, time_t check_time, time_t age, const
         /*
          * Check for an explicit expiration time.
          */
    +
         if (entry->expires > -1) {
    -	sf->expires = 1;
    -	if (entry->expires > check_time) {
    -	    debug(22, 3) ("FRESH: expires %d >= check_time %d \n",
    -		(int) entry->expires, (int) check_time);
    -	    return -1;
    -	} else {
    -	    debug(22, 3) ("STALE: expires %d < check_time %d \n",
    -		(int) entry->expires, (int) check_time);
    -	    return (check_time - entry->expires);
    -	}
    +        sf->expires = 1;
    +
    +        if (entry->expires > check_time) {
    +            debug(22, 3) ("FRESH: expires %d >= check_time %d \n",
    +                          (int) entry->expires, (int) check_time);
    +            return -1;
    +        } else {
    +            debug(22, 3) ("STALE: expires %d < check_time %d \n",
    +                          (int) entry->expires, (int) check_time);
    +            return (check_time - entry->expires);
    +        }
         }
    +
         assert(age >= 0);
         /*
          * Use local heuristics to determine staleness.  Start with the
          * max age from the refresh_pattern rule.
          */
    +
         if (age > R->max) {
    -	debug(22, 3) ("STALE: age %d > max %d \n", (int) age, (int) R->max);
    -	sf->max = 1;
    -	return (age - R->max);
    +        debug(22, 3) ("STALE: age %d > max %d \n", (int) age, (int) R->max);
    +        sf->max = 1;
    +        return (age - R->max);
         }
    +
         /*
          * Try the last-modified factor algorithm.
          */
         if (entry->lastmod > -1 && entry->timestamp > entry->lastmod) {
    -	/*
    -	 * stale_age is the Age of the response when it became/becomes
    -	 * stale according to the last-modified factor algorithm.
    -	 */
    -	time_t stale_age = static_cast((entry->timestamp - entry->lastmod) * R->pct);
    -	sf->lmfactor = 1;
    -	if (age >= stale_age) {
    -	    debug(22, 3) ("STALE: age %d > stale_age %d\n",
    -		(int) age, (int) stale_age);
    -	    return (age - stale_age);
    -	} else {
    -	    debug(22, 3) ("FRESH: age %d <= stale_age %d\n",
    -		(int) age, (int) stale_age);
    -	    return -1;
    -	}
    +        /*
    +         * stale_age is the Age of the response when it became/becomes
    +         * stale according to the last-modified factor algorithm.
    +         */
    +        time_t stale_age = static_cast((entry->timestamp - entry->lastmod) * R->pct);
    +        sf->lmfactor = 1;
    +
    +        if (age >= stale_age) {
    +            debug(22, 3) ("STALE: age %d > stale_age %d\n",
    +                          (int) age, (int) stale_age);
    +            return (age - stale_age);
    +        } else {
    +            debug(22, 3) ("FRESH: age %d <= stale_age %d\n",
    +                          (int) age, (int) stale_age);
    +            return -1;
    +        }
         }
    +
         /*
          * If we are here, staleness is determined by the refresh_pattern
          * configured minimum age.
          */
         if (age <= R->min) {
    -	debug(22, 3) ("FRESH: age %d <= min %d\n", (int) age, (int) R->min);
    -	sf->min = 1;
    -	return -1;
    +        debug(22, 3) ("FRESH: age %d <= min %d\n", (int) age, (int) R->min);
    +        sf->min = 1;
    +        return -1;
         }
    +
         debug(22, 3) ("STALE: age %d > min %d\n", (int) age, (int) R->min);
         return (age - R->min);
     }
    @@ -219,116 +243,143 @@ refreshCheck(const StoreEntry * entry, request_t * request, time_t delta)
         time_t check_time = squid_curtime + delta;
         int staleness;
         stale_flags sf;
    +
         if (entry->mem_obj)
    -	uri = entry->mem_obj->url;
    +        uri = entry->mem_obj->url;
         else if (request)
    -	uri = urlCanonical(request);
    +        uri = urlCanonical(request);
     
         debug(22, 3) ("refreshCheck: '%s'\n", uri ? uri : "");
     
         if (check_time > entry->timestamp)
    -	age = check_time - entry->timestamp;
    +        age = check_time - entry->timestamp;
    +
         R = uri ? refreshLimits(uri) : refreshUncompiledPattern(".");
    +
         if (NULL == R)
    -	R = &DefaultRefresh;
    +        R = &DefaultRefresh;
    +
         memset(&sf, '\0', sizeof(sf));
    +
         staleness = refreshStaleness(entry, check_time, age, R, &sf);
    +
         debug(22, 3) ("Staleness = %d\n", staleness);
     
         debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n",
    -	R->pattern, (int) R->min, (int) (100.0 * R->pct), (int) R->max);
    +                  R->pattern, (int) R->min, (int) (100.0 * R->pct), (int) R->max);
    +
         debug(22, 3) ("refreshCheck: age = %d\n", (int) age);
    +
         debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time));
    +
         debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp));
     
         if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE) && staleness > -1) {
    -	debug(22, 3) ("refreshCheck: YES: Must revalidate stale response\n");
    -	return STALE_MUST_REVALIDATE;
    +        debug(22, 3) ("refreshCheck: YES: Must revalidate stale response\n");
    +        return STALE_MUST_REVALIDATE;
         }
    +
         /* request-specific checks */
         if (request) {
    -	HttpHdrCc *cc = request->cache_control;
    +        HttpHdrCc *cc = request->cache_control;
     #if HTTP_VIOLATIONS
    -	if (!request->flags.nocache_hack) {
    -	    (void) 0;
    -	} else if (R->flags.ignore_reload) {
    -	    /* The clients no-cache header is ignored */
    -	    debug(22, 3) ("refreshCheck: MAYBE: ignore-reload\n");
    -	} else if (R->flags.reload_into_ims || Config.onoff.reload_into_ims) {
    -	    /* The clients no-cache header is changed into a IMS query */
    -	    debug(22, 3) ("refreshCheck: YES: reload-into-ims\n");
    -	    return STALE_RELOAD_INTO_IMS;
    -	} else {
    -	    /* The clients no-cache header is not overridden on this request */
    -	    debug(22, 3) ("refreshCheck: YES: client reload\n");
    -	    request->flags.nocache = 1;
    -	    return STALE_FORCED_RELOAD;
    -	}
    +
    +        if (!request->flags.nocache_hack) {
    +            (void) 0;
    +        } else if (R->flags.ignore_reload) {
    +            /* The clients no-cache header is ignored */
    +            debug(22, 3) ("refreshCheck: MAYBE: ignore-reload\n");
    +        } else if (R->flags.reload_into_ims || Config.onoff.reload_into_ims) {
    +            /* The clients no-cache header is changed into a IMS query */
    +            debug(22, 3) ("refreshCheck: YES: reload-into-ims\n");
    +            return STALE_RELOAD_INTO_IMS;
    +        } else {
    +            /* The clients no-cache header is not overridden on this request */
    +            debug(22, 3) ("refreshCheck: YES: client reload\n");
    +            request->flags.nocache = 1;
    +            return STALE_FORCED_RELOAD;
    +        }
    +
     #endif
    -	if (NULL != cc) {
    -	    if (cc->max_age > -1) {
    +        if (NULL != cc) {
    +            if (cc->max_age > -1) {
     #if HTTP_VIOLATIONS
    -		if (R->flags.ignore_reload && cc->max_age == 0) {
    -		} else
    +                if (R->flags.ignore_reload && cc->max_age == 0) {} else
     #endif
    -		  {
    +                {
     #if 0
    -		    if (cc->max_age == 0) {
    -			debug (22,3) ("refreshCheck: YES: client-max-age = 0\n");
    -			return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
    -		    }
    +
    +                    if (cc->max_age == 0) {
    +                        debug (22,3) ("refreshCheck: YES: client-max-age = 0\n");
    +                        return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
    +                    }
    +
     #endif
    -		if (age > cc->max_age) {
    -		    debug(22, 3) ("refreshCheck: YES: age > client-max-age\n");
    -		    return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
    -		}
    -		  }
    -	    }
    -	    if (EBIT_TEST(cc->mask, CC_MAX_STALE) && staleness > -1) {
    -		if (cc->max_stale < 0) {
    -		    /* max-stale directive without a value */
    -		    debug(22, 3) ("refreshCheck: NO: max-stale wildcard\n");
    -		    return FRESH_REQUEST_MAX_STALE_ALL;
    -		} else if (staleness < cc->max_stale) {
    -		    debug(22, 3) ("refreshCheck: NO: staleness < max-stale\n");
    -		    return FRESH_REQUEST_MAX_STALE_VALUE;
    -		}
    -	    }
    -	}
    +                    if (age > cc->max_age) {
    +                        debug(22, 3) ("refreshCheck: YES: age > client-max-age\n");
    +                        return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
    +                    }
    +                }
    +            }
    +
    +            if (EBIT_TEST(cc->mask, CC_MAX_STALE) && staleness > -1) {
    +                if (cc->max_stale < 0) {
    +                    /* max-stale directive without a value */
    +                    debug(22, 3) ("refreshCheck: NO: max-stale wildcard\n");
    +                    return FRESH_REQUEST_MAX_STALE_ALL;
    +                } else if (staleness < cc->max_stale) {
    +                    debug(22, 3) ("refreshCheck: NO: staleness < max-stale\n");
    +                    return FRESH_REQUEST_MAX_STALE_VALUE;
    +                }
    +            }
    +        }
         }
    +
         if (-1 == staleness) {
    -	if (sf.expires)
    -	    return FRESH_EXPIRES;
    -	assert(!sf.max);
    -	if (sf.lmfactor)
    -	    return FRESH_LMFACTOR_RULE;
    -	assert(sf.min);
    -	return FRESH_MIN_RULE;
    +        if (sf.expires)
    +            return FRESH_EXPIRES;
    +
    +        assert(!sf.max);
    +
    +        if (sf.lmfactor)
    +            return FRESH_LMFACTOR_RULE;
    +
    +        assert(sf.min);
    +
    +        return FRESH_MIN_RULE;
         }
    +
         /*
          * At this point the response is stale, unless one of
          * the override options kicks in.
          */
         if (sf.expires) {
     #if HTTP_VIOLATIONS
    -	if (R->flags.override_expire && age < R->min) {
    -	    debug(22, 3) ("refreshCheck: NO: age < min && override-expire\n");
    -	    return FRESH_OVERRIDE_EXPIRES;
    -	}
    +
    +        if (R->flags.override_expire && age < R->min) {
    +            debug(22, 3) ("refreshCheck: NO: age < min && override-expire\n");
    +            return FRESH_OVERRIDE_EXPIRES;
    +        }
    +
     #endif
    -	return STALE_EXPIRES;
    +        return STALE_EXPIRES;
         }
    +
         if (sf.max)
    -	return STALE_MAX_RULE;
    +        return STALE_MAX_RULE;
    +
         if (sf.lmfactor) {
     #if HTTP_VIOLATIONS
    -	if (R->flags.override_lastmod && age < R->min) {
    -	    debug(22, 3) ("refreshCheck: NO: age < min && override-lastmod\n");
    -	    return FRESH_OVERRIDE_LASTMOD;
    -	}
    +
    +        if (R->flags.override_lastmod && age < R->min) {
    +            debug(22, 3) ("refreshCheck: NO: age < min && override-lastmod\n");
    +            return FRESH_OVERRIDE_LASTMOD;
    +        }
    +
     #endif
    -	return STALE_LMFACTOR_RULE;
    +        return STALE_LMFACTOR_RULE;
         }
    +
         return STALE_DEFAULT;
     }
     
    @@ -344,21 +395,27 @@ refreshIsCachable(const StoreEntry * entry)
         int reason = refreshCheck(entry, NULL, 60);
         refreshCounts[rcStore].total++;
         refreshCounts[rcStore].status[reason]++;
    +
         if (reason < 200)
    -	/* Does not need refresh. This is certainly cachable */
    -	return 1;
    +        /* Does not need refresh. This is certainly cachable */
    +        return 1;
    +
         if (entry->lastmod < 0)
    -	/* Last modified is needed to do a refresh */
    -	return 0;
    +        /* Last modified is needed to do a refresh */
    +        return 0;
    +
         if (entry->mem_obj == NULL)
    -	/* no mem_obj? */
    -	return 1;
    +        /* no mem_obj? */
    +        return 1;
    +
         if (entry->getReply() == NULL)
    -	/* no reply? */
    -	return 1;
    +        /* no reply? */
    +        return 1;
    +
         if (entry->getReply()->content_length == 0)
    -	/* No use refreshing (caching?) 0 byte objects */
    -	return 0;
    +        /* No use refreshing (caching?) 0 byte objects */
    +        return 0;
    +
         /* This seems to be refreshable. Cache it */
         return 1;
     }
    @@ -393,6 +450,7 @@ refreshCheckHTCP(const StoreEntry * entry, request_t * request)
         refreshCounts[rcHTCP].status[reason]++;
         return (reason < 200) ? 0 : 1;
     }
    +
     #endif
     
     #if USE_CACHE_DIGESTS
    @@ -400,12 +458,13 @@ int
     refreshCheckDigest(const StoreEntry * entry, time_t delta)
     {
         int reason = refreshCheck(entry,
    -	entry->mem_obj ? entry->mem_obj->request : NULL,
    -	delta);
    +                              entry->mem_obj ? entry->mem_obj->request : NULL,
    +                              delta);
         refreshCounts[rcCDigest].total++;
         refreshCounts[rcCDigest].status[reason]++;
         return (reason < 200) ? 0 : 1;
     }
    +
     #endif
     
     time_t
    @@ -413,13 +472,15 @@ getMaxAge(const char *url)
     {
         const refresh_t *R;
         debug(22, 3) ("getMaxAge: '%s'\n", url);
    +
         if ((R = refreshLimits(url)))
    -	return R->max;
    +        return R->max;
         else
    -	return REFRESH_DEFAULT_MAX;
    +        return REFRESH_DEFAULT_MAX;
     }
     
     static void
    +
     refreshCountsStats(StoreEntry * sentry, struct RefreshCounts *rc)
     {
         int sum = 0;
    @@ -435,41 +496,41 @@ refreshCountsStats(StoreEntry * sentry, struct RefreshCounts *rc)
     }
     
         refreshCountsStatsEntry(FRESH_REQUEST_MAX_STALE_ALL,
    -	"Fresh: request max-stale wildcard");
    +                            "Fresh: request max-stale wildcard");
         refreshCountsStatsEntry(FRESH_REQUEST_MAX_STALE_VALUE,
    -	"Fresh: request max-stale value");
    +                            "Fresh: request max-stale value");
         refreshCountsStatsEntry(FRESH_EXPIRES,
    -	"Fresh: expires time not reached");
    +                            "Fresh: expires time not reached");
         refreshCountsStatsEntry(FRESH_LMFACTOR_RULE,
    -	"Fresh: refresh_pattern last-mod factor percentage");
    +                            "Fresh: refresh_pattern last-mod factor percentage");
         refreshCountsStatsEntry(FRESH_MIN_RULE,
    -	"Fresh: refresh_pattern min value");
    +                            "Fresh: refresh_pattern min value");
         refreshCountsStatsEntry(FRESH_OVERRIDE_EXPIRES,
    -	"Fresh: refresh_pattern override expires");
    +                            "Fresh: refresh_pattern override expires");
         refreshCountsStatsEntry(FRESH_OVERRIDE_LASTMOD,
    -	"Fresh: refresh_pattern override lastmod");
    +                            "Fresh: refresh_pattern override lastmod");
         refreshCountsStatsEntry(STALE_MUST_REVALIDATE,
    -	"Stale: response has must-revalidate");
    +                            "Stale: response has must-revalidate");
         refreshCountsStatsEntry(STALE_RELOAD_INTO_IMS,
    -	"Stale: changed reload into IMS");
    +                            "Stale: changed reload into IMS");
         refreshCountsStatsEntry(STALE_FORCED_RELOAD,
    -	"Stale: request has no-cache directive");
    +                            "Stale: request has no-cache directive");
         refreshCountsStatsEntry(STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE,
    -	"Stale: age exceeds request max-age value");
    +                            "Stale: age exceeds request max-age value");
         refreshCountsStatsEntry(STALE_EXPIRES,
    -	"Stale: expires time reached");
    +                            "Stale: expires time reached");
         refreshCountsStatsEntry(STALE_MAX_RULE,
    -	"Stale: refresh_pattern max age rule");
    +                            "Stale: refresh_pattern max age rule");
         refreshCountsStatsEntry(STALE_LMFACTOR_RULE,
    -	"Stale: refresh_pattern last-mod factor percentage");
    +                            "Stale: refresh_pattern last-mod factor percentage");
         refreshCountsStatsEntry(STALE_DEFAULT,
    -	"Stale: by default");
    +                            "Stale: by default");
     
         tot = sum;			/* paranoid: "total" line shows 100% if we forgot nothing */
         storeAppendPrintf(sentry, "%6d\t%6.2f\tTOTAL\n",
    -	rc->total, xpercent(rc->total, tot));
    +                      rc->total, xpercent(rc->total, tot));
         \
    -	storeAppendPrintf(sentry, "\n");
    +    storeAppendPrintf(sentry, "\n");
     }
     
     static void
    @@ -479,22 +540,26 @@ refreshStats(StoreEntry * sentry)
         int total = 0;
     
         /* get total usage count */
    +
         for (i = 0; i < rcCount; ++i)
    -	total += refreshCounts[i].total;
    +        total += refreshCounts[i].total;
     
         /* protocol usage histogram */
         storeAppendPrintf(sentry, "\nRefreshCheck calls per protocol\n\n");
    +
         storeAppendPrintf(sentry, "Protocol\t#Calls\t%%Calls\n");
    +
         for (i = 0; i < rcCount; ++i)
    -	storeAppendPrintf(sentry, "%10s\t%6d\t%6.2f\n",
    -	    refreshCounts[i].proto,
    -	    refreshCounts[i].total,
    -	    xpercent(refreshCounts[i].total, total));
    +        storeAppendPrintf(sentry, "%10s\t%6d\t%6.2f\n",
    +                          refreshCounts[i].proto,
    +                          refreshCounts[i].total,
    +                          xpercent(refreshCounts[i].total, total));
     
         /* per protocol histograms */
         storeAppendPrintf(sentry, "\n\nRefreshCheck histograms for various protocols\n");
    +
         for (i = 0; i < rcCount; ++i)
    -	refreshCountsStats(sentry, &refreshCounts[i]);
    +        refreshCountsStats(sentry, &refreshCounts[i]);
     }
     
     void
    @@ -504,17 +569,21 @@ refreshInit(void)
         refreshCounts[rcHTTP].proto = "HTTP";
         refreshCounts[rcICP].proto = "ICP";
     #if USE_HTCP
    +
         refreshCounts[rcHTCP].proto = "HTCP";
     #endif
    +
         refreshCounts[rcStore].proto = "On Store";
     #if USE_CACHE_DIGESTS
    +
         refreshCounts[rcCDigest].proto = "Cache Digests";
     #endif
    +
         cachemgrRegister("refresh",
    -	"Refresh Algorithm Statistics",
    -	refreshStats,
    -	0,
    -	1);
    +                     "Refresh Algorithm Statistics",
    +                     refreshStats,
    +                     0,
    +                     1);
         memset(&DefaultRefresh, '\0', sizeof(DefaultRefresh));
         DefaultRefresh.pattern = "";
         DefaultRefresh.min = REFRESH_DEFAULT_MIN;
    diff --git a/src/repl/heap/store_heap_replacement.cc b/src/repl/heap/store_heap_replacement.cc
    index 48914c1192..ebb9012cde 100644
    --- a/src/repl/heap/store_heap_replacement.cc
    +++ b/src/repl/heap/store_heap_replacement.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_heap_replacement.cc,v 1.11 2003/01/23 00:38:28 robertc Exp $
    + * $Id: store_heap_replacement.cc,v 1.12 2003/02/21 22:50:50 robertc Exp $
      *
      * DEBUG: section 20    Storage Manager Heap-based replacement
      * AUTHOR: John Dilley
    @@ -73,18 +73,23 @@ HeapKeyGen_StoreEntry_LFUDA(void *entry, double heap_age)
         StoreEntry *e = (StoreEntry *)entry;
         heap_key key;
         double tie;
    +
         if (e->lastref <= 0)
    -	tie = 0.0;
    +        tie = 0.0;
         else if (squid_curtime <= e->lastref)
    -	tie = 0.0;
    +        tie = 0.0;
         else
    -	tie = 1.0 - exp((double) (e->lastref - squid_curtime) / 86400.0);
    +        tie = 1.0 - exp((double) (e->lastref - squid_curtime) / 86400.0);
    +
         key = heap_age + (double) e->refcount - tie;
    +
         debug(81, 3) ("HeapKeyGen_StoreEntry_LFUDA: %s refcnt=%d lastref=%ld heap_age=%f tie=%f -> %f\n",
    -	e->getMD5Text(), (int)e->refcount, e->lastref, heap_age, tie, key);
    +                  e->getMD5Text(), (int)e->refcount, e->lastref, heap_age, tie, key);
    +
         if (e->mem_obj && e->mem_obj->url)
    -	debug(81, 3) ("HeapKeyGen_StoreEntry_LFUDA: url=%s\n",
    -	    e->mem_obj->url);
    +        debug(81, 3) ("HeapKeyGen_StoreEntry_LFUDA: url=%s\n",
    +                      e->mem_obj->url);
    +
         return (double) key;
     }
     
    @@ -117,14 +122,16 @@ HeapKeyGen_StoreEntry_GDSF(void *entry, double heap_age)
         double tie = (e->lastref > 1) ? (1.0 / e->lastref) : 1.0;
         key = heap_age + ((double) e->refcount / size) - tie;
         debug(81, 3) ("HeapKeyGen_StoreEntry_GDSF: %s size=%f refcnt=%d lastref=%ld heap_age=%f tie=%f -> %f\n",
    -	e->getMD5Text(), size, (int)e->refcount, e->lastref, heap_age, tie, key);
    +                  e->getMD5Text(), size, (int)e->refcount, e->lastref, heap_age, tie, key);
    +
         if (e->mem_obj && e->mem_obj->url)
    -	debug(81, 3) ("HeapKeyGen_StoreEntry_GDSF: url=%s\n",
    -	    e->mem_obj->url);
    +        debug(81, 3) ("HeapKeyGen_StoreEntry_GDSF: url=%s\n",
    +                      e->mem_obj->url);
    +
         return key;
     }
     
    -/* 
    +/*
      * Key generation function to implement the LRU policy.  Normally
      * one would not do this with a heap -- use the linked list instead.
      * For testing and performance characterization it was useful.
    @@ -136,9 +143,11 @@ HeapKeyGen_StoreEntry_LRU(void *entry, double heap_age)
     {
         StoreEntry *e = (StoreEntry *)entry;
         debug(81, 3) ("HeapKeyGen_StoreEntry_LRU: %s heap_age=%f lastref=%f\n",
    -	e->getMD5Text(), heap_age, (double) e->lastref);
    +                  e->getMD5Text(), heap_age, (double) e->lastref);
    +
         if (e->mem_obj && e->mem_obj->url)
    -	debug(81, 3) ("HeapKeyGen_StoreEntry_LRU: url=%s\n",
    -	    e->mem_obj->url);
    +        debug(81, 3) ("HeapKeyGen_StoreEntry_LRU: url=%s\n",
    +                      e->mem_obj->url);
    +
         return (heap_key) e->lastref;
     }
    diff --git a/src/repl/heap/store_repl_heap.cc b/src/repl/heap/store_repl_heap.cc
    index 41f4c4818a..72e114b4cc 100644
    --- a/src/repl/heap/store_repl_heap.cc
    +++ b/src/repl/heap/store_repl_heap.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_repl_heap.cc,v 1.12 2003/01/23 00:38:28 robertc Exp $
    + * $Id: store_repl_heap.cc,v 1.13 2003/02/21 22:50:50 robertc Exp $
      *
      * DEBUG: section ?     HEAP based removal policies
      * AUTHOR: Henrik Nordstrom
    @@ -51,7 +51,8 @@ REMOVALPOLICYCREATE createRemovalPolicy_heap;
     
     static int nr_heap_policies = 0;
     
    -struct HeapPolicyData {
    +struct HeapPolicyData
    +{
         void setPolicyNode (StoreEntry *, void *) const;
         RemovalPolicy *policy;
         heap *theHeap;
    @@ -59,7 +60,7 @@ struct HeapPolicyData {
         int count;
         int nwalkers;
         enum heap_entry_type {
    -	TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM
    +        TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM
         } type;
     };
     
    @@ -70,10 +71,13 @@ static enum HeapPolicyData::heap_entry_type
     heap_guessType(StoreEntry * entry, RemovalPolicyNode * node)
     {
         if (node == &entry->repl)
    -	return HeapPolicyData::TYPE_STORE_ENTRY;
    +        return HeapPolicyData::TYPE_STORE_ENTRY;
    +
         if (entry->mem_obj && node == &entry->mem_obj->repl)
    -	return HeapPolicyData::TYPE_STORE_MEM;
    +        return HeapPolicyData::TYPE_STORE_MEM;
    +
         fatal("Heap Replacement: Unknown StoreEntry node type");
    +
         return HeapPolicyData::TYPE_UNKNOWN;
     }
     
    @@ -81,9 +85,17 @@ void
     HeapPolicyData::setPolicyNode (StoreEntry *entry, void *value) const
     {
         switch (type) {
    -      case TYPE_STORE_ENTRY: entry->repl.data = value; break ;
    -      case TYPE_STORE_MEM: entry->mem_obj->repl.data = value ; break ;
    -      default: break;
    +
    +    case TYPE_STORE_ENTRY:
    +        entry->repl.data = value;
    +        break ;
    +
    +    case TYPE_STORE_MEM:
    +        entry->mem_obj->repl.data = value ;
    +        break ;
    +
    +    default:
    +        break;
         }
     }
     
    @@ -92,44 +104,57 @@ heap_add(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
     {
         HeapPolicyData *heap = (HeapPolicyData *)policy->_data;
         assert(!node->data);
    +
         if (EBIT_TEST(entry->flags, ENTRY_SPECIAL))
    -	return;			/* We won't manage these.. they messes things up */
    +        return;			/* We won't manage these.. they messes things up */
    +
         node->data = heap_insert(heap->theHeap, entry);
    +
         heap->count += 1;
    +
         if (!heap->type)
    -	heap->type = heap_guessType(entry, node);
    +        heap->type = heap_guessType(entry, node);
    +
         /* Add a little more variance to the aging factor */
         heap->theHeap->age += heap->theHeap->age / 100000000;
     }
     
     static void
     heap_remove(RemovalPolicy * policy, StoreEntry * entry,
    -    RemovalPolicyNode * node)
    +            RemovalPolicyNode * node)
     {
         HeapPolicyData *heap = (HeapPolicyData *)policy->_data;
         heap_node *hnode = (heap_node *)node->data;
    +
         if (!hnode)
    -	return;
    +        return;
    +
         heap_delete(heap->theHeap, hnode);
    +
         node->data = NULL;
    +
         heap->count -= 1;
     }
     
     static void
     heap_referenced(RemovalPolicy * policy, const StoreEntry * entry,
    -    RemovalPolicyNode * node)
    +                RemovalPolicyNode * node)
     {
         HeapPolicyData *heap = (HeapPolicyData *)policy->_data;
         heap_node *hnode = (heap_node *)node->data;
    +
         if (!hnode)
    -	return;
    +        return;
    +
         heap_update(heap->theHeap, hnode, (StoreEntry *) entry);
     }
     
     /** RemovalPolicyWalker **/
     
     typedef struct _HeapWalkData HeapWalkData;
    -struct _HeapWalkData {
    +
    +struct _HeapWalkData
    +{
         size_t current;
     };
     
    @@ -140,9 +165,12 @@ heap_walkNext(RemovalPolicyWalker * walker)
         RemovalPolicy *policy = walker->_policy;
         HeapPolicyData *heap = (HeapPolicyData *)policy->_data;
         StoreEntry *entry;
    +
         if (heap_walk->current >= heap_nodes(heap->theHeap))
    -	return NULL;		/* done */
    +        return NULL;		/* done */
    +
         entry = (StoreEntry *) heap_peep(heap->theHeap, heap_walk->current++);
    +
         return entry;
     }
     
    @@ -178,7 +206,9 @@ heap_walkInit(RemovalPolicy * policy)
     /** RemovalPurgeWalker **/
     
     typedef struct _HeapPurgeData HeapPurgeData;
    -struct _HeapPurgeData {
    +
    +struct _HeapPurgeData
    +{
         link_list *locked_entries;
         heap_key min_age;
     };
    @@ -191,15 +221,21 @@ heap_purgeNext(RemovalPurgeWalker * walker)
         HeapPolicyData *heap = (HeapPolicyData *)policy->_data;
         StoreEntry *entry;
         heap_key age;
    -  try_again:
    +
    +try_again:
    +
         if (!heap_nodes(heap->theHeap) > 0)
    -	return NULL;		/* done */
    +        return NULL;		/* done */
    +
         age = heap_peepminkey(heap->theHeap);
    +
         entry = (StoreEntry *)heap_extractmin(heap->theHeap);
    +
         if (storeEntryLocked(entry)) {
    -	linklistPush(&heap_walker->locked_entries, entry);
    -	goto try_again;
    +        linklistPush(&heap_walker->locked_entries, entry);
    +        goto try_again;
         }
    +
         heap_walker->min_age = age;
         heap->setPolicyNode(entry, NULL);
         return entry;
    @@ -215,18 +251,21 @@ heap_purgeDone(RemovalPurgeWalker * walker)
         assert(strcmp(policy->_type, "heap") == 0);
         assert(heap->nwalkers > 0);
         heap->nwalkers -= 1;
    +
         if (heap_walker->min_age > 0) {
    -	heap->theHeap->age = heap_walker->min_age;
    -	debug(81, 3) ("heap_purgeDone: Heap age set to %f\n",
    -	    (double) heap->theHeap->age);
    +        heap->theHeap->age = heap_walker->min_age;
    +        debug(81, 3) ("heap_purgeDone: Heap age set to %f\n",
    +                      (double) heap->theHeap->age);
         }
    +
         /*
          * Reinsert the locked entries
          */
         while ((entry = (StoreEntry *)linklistShift(&heap_walker->locked_entries))) {
    -	heap_node *node = heap_insert(heap->theHeap, entry);
    -	heap->setPolicyNode(entry, node);
    +        heap_node *node = heap_insert(heap->theHeap, entry);
    +        heap->setPolicyNode(entry, node);
         }
    +
         safe_free(walker->_data);
         cbdataFree(walker);
     }
    @@ -275,39 +314,55 @@ createRemovalPolicy_heap(wordlist * args)
         heap_data = (HeapPolicyData *)xcalloc(1, sizeof(*heap_data));
         /* Initialize the policy data */
         heap_data->policy = policy;
    +
         if (args) {
    -	keytype = args->key;
    -	args = args->next;
    +        keytype = args->key;
    +        args = args->next;
         } else {
    -	debug(81, 1) ("createRemovalPolicy_heap: No key type specified. Using LRU\n");
    -	keytype = "LRU";
    +        debug(81, 1) ("createRemovalPolicy_heap: No key type specified. Using LRU\n");
    +        keytype = "LRU";
         }
    +
         if (!strcmp(keytype, "GDSF"))
    -	heap_data->keyfunc = HeapKeyGen_StoreEntry_GDSF;
    +        heap_data->keyfunc = HeapKeyGen_StoreEntry_GDSF;
         else if (!strcmp(keytype, "LFUDA"))
    -	heap_data->keyfunc = HeapKeyGen_StoreEntry_LFUDA;
    +        heap_data->keyfunc = HeapKeyGen_StoreEntry_LFUDA;
         else if (!strcmp(keytype, "LRU"))
    -	heap_data->keyfunc = HeapKeyGen_StoreEntry_LRU;
    +        heap_data->keyfunc = HeapKeyGen_StoreEntry_LRU;
         else {
    -	debug(81, 0) ("createRemovalPolicy_heap: Unknown key type \"%s\". Using LRU\n",
    -	    keytype);
    -	heap_data->keyfunc = HeapKeyGen_StoreEntry_LRU;
    +        debug(81, 0) ("createRemovalPolicy_heap: Unknown key type \"%s\". Using LRU\n",
    +                      keytype);
    +        heap_data->keyfunc = HeapKeyGen_StoreEntry_LRU;
         }
    +
         /* No additional arguments expected */
         assert(!args);
    +
         heap_data->theHeap = new_heap(1000, heap_data->keyfunc);
    +
         heap_data->theHeap->age = 1.0;
    +
         /* Populate the policy structure */
         policy->_type = "heap";
    +
         policy->_data = heap_data;
    +
         policy->Free = heap_free;
    +
         policy->Add = heap_add;
    +
         policy->Remove = heap_remove;
    +
         policy->Referenced = NULL;
    +
         policy->Dereferenced = heap_referenced;
    +
         policy->WalkInit = heap_walkInit;
    +
         policy->PurgeInit = heap_purgeInit;
    +
         /* Increase policy usage count */
         nr_heap_policies += 0;
    +
         return policy;
     }
    diff --git a/src/repl/lru/store_repl_lru.cc b/src/repl/lru/store_repl_lru.cc
    index 94663f3a0b..751bc355ab 100644
    --- a/src/repl/lru/store_repl_lru.cc
    +++ b/src/repl/lru/store_repl_lru.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_repl_lru.cc,v 1.13 2003/01/23 00:38:29 robertc Exp $
    + * $Id: store_repl_lru.cc,v 1.14 2003/02/21 22:50:50 robertc Exp $
      *
      * DEBUG: section ?     LRU Removal policy
      * AUTHOR: Henrik Nordstrom
    @@ -39,14 +39,15 @@
     
     REMOVALPOLICYCREATE createRemovalPolicy_lru;
     
    -struct LruPolicyData {
    +struct LruPolicyData
    +{
         void setPolicyNode (StoreEntry *, void *) const;
         RemovalPolicy *policy;
         dlink_list list;
         int count;
         int nwalkers;
         enum heap_entry_type {
    -	TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM
    +        TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM
         } type;
     };
     
    @@ -57,10 +58,13 @@ static enum LruPolicyData::heap_entry_type
     repl_guessType(StoreEntry * entry, RemovalPolicyNode * node)
     {
         if (node == &entry->repl)
    -	return LruPolicyData::TYPE_STORE_ENTRY;
    +        return LruPolicyData::TYPE_STORE_ENTRY;
    +
         if (entry->mem_obj && node == &entry->mem_obj->repl)
    -	return LruPolicyData::TYPE_STORE_MEM;
    +        return LruPolicyData::TYPE_STORE_MEM;
    +
         fatal("Heap Replacement: Unknown StoreEntry node type");
    +
         return LruPolicyData::TYPE_UNKNOWN;
     }
     
    @@ -68,14 +72,24 @@ void
     LruPolicyData::setPolicyNode (StoreEntry *entry, void *value) const
     {
         switch (type) {
    -        case TYPE_STORE_ENTRY: entry->repl.data = value; break ;
    -	case TYPE_STORE_MEM: entry->mem_obj->repl.data = value ; break ;
    -	default: break;
    +
    +    case TYPE_STORE_ENTRY:
    +        entry->repl.data = value;
    +        break ;
    +
    +    case TYPE_STORE_MEM:
    +        entry->mem_obj->repl.data = value ;
    +        break ;
    +
    +    default:
    +        break;
         }
     }
     
     typedef struct _LruNode LruNode;
    -struct _LruNode {
    +
    +struct _LruNode
    +{
         /* Note: the dlink_node MUST be the first member of the LruNode
          * structure. This member is later pointer typecasted to LruNode *.
          */
    @@ -94,8 +108,9 @@ lru_add(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
         node->data = lru_node = (LruNode *)memPoolAlloc(lru_node_pool);
         dlinkAddTail(entry, &lru_node->node, &lru->list);
         lru->count += 1;
    +
         if (!lru->type)
    -	lru->type = repl_guessType(entry, node);
    +        lru->type = repl_guessType(entry, node);
     }
     
     static void
    @@ -103,38 +118,50 @@ lru_remove(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
     {
         LruPolicyData *lru = (LruPolicyData *)policy->_data;
         LruNode *lru_node = (LruNode *)node->data;
    +
         if (!lru_node)
    -	return;
    +        return;
    +
         /*
          * It seems to be possible for an entry to exist in the hash
          * but not be in the LRU list, so check for that case rather
          * than suffer a NULL pointer access.
          */
         if (NULL == lru_node->node.data)
    -	return;
    +        return;
    +
         assert(lru_node->node.data == entry);
    +
         node->data = NULL;
    +
         dlinkDelete(&lru_node->node, &lru->list);
    +
         memPoolFree(lru_node_pool, lru_node);
    +
         lru->count -= 1;
     }
     
     static void
     lru_referenced(RemovalPolicy * policy, const StoreEntry * entry,
    -    RemovalPolicyNode * node)
    +               RemovalPolicyNode * node)
     {
         LruPolicyData *lru = (LruPolicyData *)policy->_data;
         LruNode *lru_node = (LruNode *)node->data;
    +
         if (!lru_node)
    -	return;
    +        return;
    +
         dlinkDelete(&lru_node->node, &lru->list);
    +
         dlinkAddTail((void *) entry, &lru_node->node, &lru->list);
     }
     
     /** RemovalPolicyWalker **/
     
     typedef struct _LruWalkData LruWalkData;
    -struct _LruWalkData {
    +
    +struct _LruWalkData
    +{
         LruNode *current;
     };
     
    @@ -143,9 +170,12 @@ lru_walkNext(RemovalPolicyWalker * walker)
     {
         LruWalkData *lru_walk = (LruWalkData *)walker->_data;
         LruNode *lru_node = lru_walk->current;
    +
         if (!lru_node)
    -	return NULL;
    +        return NULL;
    +
         lru_walk->current = (LruNode *) lru_node->node.next;
    +
         return (StoreEntry *) lru_node->node.data;
     }
     
    @@ -181,7 +211,9 @@ lru_walkInit(RemovalPolicy * policy)
     /** RemovalPurgeWalker **/
     
     typedef struct _LruPurgeData LruPurgeData;
    -struct _LruPurgeData {
    +
    +struct _LruPurgeData
    +{
         LruNode *current;
         LruNode *start;
     };
    @@ -194,24 +226,32 @@ lru_purgeNext(RemovalPurgeWalker * walker)
         LruPolicyData *lru = (LruPolicyData *)policy->_data;
         LruNode *lru_node;
         StoreEntry *entry;
    -  try_again:
    +
    +try_again:
         lru_node = lru_walker->current;
    +
         if (!lru_node || walker->scanned >= walker->max_scan)
    -	return NULL;
    +        return NULL;
    +
         walker->scanned += 1;
    +
         lru_walker->current = (LruNode *) lru_node->node.next;
    +
         if (lru_walker->current == lru_walker->start) {
    -	/* Last node found */
    -	lru_walker->current = NULL;
    +        /* Last node found */
    +        lru_walker->current = NULL;
         }
    +
         entry = (StoreEntry *) lru_node->node.data;
         dlinkDelete(&lru_node->node, &lru->list);
    +
         if (storeEntryLocked(entry)) {
    -	/* Shit, it is locked. we can't return this one */
    -	walker->locked++;
    -	dlinkAddTail(entry, &lru_node->node, &lru->list);
    -	goto try_again;
    +        /* Shit, it is locked. we can't return this one */
    +        walker->locked++;
    +        dlinkAddTail(entry, &lru_node->node, &lru->list);
    +        goto try_again;
         }
    +
         memPoolFree(lru_node_pool, lru_node);
         lru->count -= 1;
         lru->setPolicyNode(entry, NULL);
    @@ -254,14 +294,17 @@ lru_stats(RemovalPolicy * policy, StoreEntry * sentry)
         LruPolicyData *lru = (LruPolicyData *)policy->_data;
         LruNode *lru_node = (LruNode *) lru->list.head;
     
    -  again:
    +again:
    +
         if (lru_node) {
    -	StoreEntry *entry = (StoreEntry *) lru_node->node.data;
    -	if (storeEntryLocked(entry)) {
    -	    lru_node = (LruNode *) lru_node->node.next;
    -	    goto again;
    -	}
    -	storeAppendPrintf(sentry, "LRU reference age: %.2f days\n", (double) (squid_curtime - entry->lastref) / (double) (24 * 60 * 60));
    +        StoreEntry *entry = (StoreEntry *) lru_node->node.data;
    +
    +        if (storeEntryLocked(entry)) {
    +            lru_node = (LruNode *) lru_node->node.next;
    +            goto again;
    +        }
    +
    +        storeAppendPrintf(sentry, "LRU reference age: %.2f days\n", (double) (squid_curtime - entry->lastref) / (double) (24 * 60 * 60));
         }
     }
     
    @@ -287,27 +330,43 @@ createRemovalPolicy_lru(wordlist * args)
         /* no arguments expected or understood */
         assert(!args);
         /* Initialize */
    +
         if (!lru_node_pool) {
    -	lru_node_pool = memPoolCreate("LRU policy node", sizeof(LruNode));
    -	memPoolSetChunkSize(lru_node_pool, 512 * 1024);
    +        lru_node_pool = memPoolCreate("LRU policy node", sizeof(LruNode));
    +        memPoolSetChunkSize(lru_node_pool, 512 * 1024);
         }
    +
         /* Allocate the needed structures */
         lru_data = (LruPolicyData *)xcalloc(1, sizeof(*lru_data));
    +
         policy = cbdataAlloc(RemovalPolicy);
    +
         /* Initialize the URL data */
         lru_data->policy = policy;
    +
         /* Populate the policy structure */
         policy->_type = "lru";
    +
         policy->_data = lru_data;
    +
         policy->Free = lru_free;
    +
         policy->Add = lru_add;
    +
         policy->Remove = lru_remove;
    +
         policy->Referenced = lru_referenced;
    +
         policy->Dereferenced = lru_referenced;
    +
         policy->WalkInit = lru_walkInit;
    +
         policy->PurgeInit = lru_purgeInit;
    +
         policy->Stats = lru_stats;
    +
         /* Increase policy usage count */
         nr_lru_policies += 0;
    +
         return policy;
     }
    diff --git a/src/send-announce.cc b/src/send-announce.cc
    index 964f5aa747..83c84e9afc 100644
    --- a/src/send-announce.cc
    +++ b/src/send-announce.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: send-announce.cc,v 1.64 2003/01/23 00:37:25 robertc Exp $
    + * $Id: send-announce.cc,v 1.65 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 27    Cache Announcer
      * AUTHOR: Duane Wessels
    @@ -42,10 +42,13 @@ void
     start_announce(void *datanotused)
     {
         if (0 == Config.onoff.announce)
    -	return;
    +        return;
    +
         if (theOutIcpConnection < 0)
    -	return;
    +        return;
    +
         ipcache_nbgethostbyname(Config.Announce.host, send_announce, NULL);
    +
         eventAdd("send_announce", start_announce, NULL, (double) Config.Announce.period, 1);
     }
     
    @@ -54,6 +57,7 @@ send_announce(const ipcache_addrs * ia, void *junk)
     {
         LOCAL_ARRAY(char, tbuf, 256);
         LOCAL_ARRAY(char, sndbuf, BUFSIZ);
    +
         struct sockaddr_in S;
         char *host = Config.Announce.host;
         char *file = NULL;
    @@ -62,49 +66,57 @@ send_announce(const ipcache_addrs * ia, void *junk)
         int n;
         int fd;
         int x;
    +
         if (ia == NULL) {
    -	debug(27, 1) ("send_announce: Unknown host '%s'\n", host);
    -	return;
    +        debug(27, 1) ("send_announce: Unknown host '%s'\n", host);
    +        return;
         }
    +
         debug(27, 1) ("Sending Announcement to %s\n", host);
         sndbuf[0] = '\0';
         snprintf(tbuf, 256, "cache_version SQUID/%s\n", version_string);
         strcat(sndbuf, tbuf);
         assert(Config.Sockaddr.http);
         snprintf(tbuf, 256, "Running on %s %d %d\n",
    -	getMyHostname(),
    -	getMyPort(),
    -	(int) Config.Port.icp);
    +             getMyHostname(),
    +             getMyPort(),
    +             (int) Config.Port.icp);
         strcat(sndbuf, tbuf);
    +
         if (Config.adminEmail) {
    -	snprintf(tbuf, 256, "cache_admin: %s\n", Config.adminEmail);
    -	strcat(sndbuf, tbuf);
    +        snprintf(tbuf, 256, "cache_admin: %s\n", Config.adminEmail);
    +        strcat(sndbuf, tbuf);
         }
    +
         snprintf(tbuf, 256, "generated %d [%s]\n",
    -	(int) squid_curtime,
    -	mkhttpdlogtime(&squid_curtime));
    +             (int) squid_curtime,
    +             mkhttpdlogtime(&squid_curtime));
         strcat(sndbuf, tbuf);
         l = strlen(sndbuf);
    +
         if ((file = Config.Announce.file) != NULL) {
    -	fd = file_open(file, O_RDONLY | O_TEXT);
    -	if (fd > -1 && (n = FD_READ_METHOD(fd, sndbuf + l, BUFSIZ - l - 1)) > 0) {
    -	    fd_bytes(fd, n, FD_READ);
    -	    l += n;
    -	    sndbuf[l] = '\0';
    -	    file_close(fd);
    -	} else {
    -	    debug(50, 1) ("send_announce: %s: %s\n", file, xstrerror());
    -	}
    +        fd = file_open(file, O_RDONLY | O_TEXT);
    +
    +        if (fd > -1 && (n = FD_READ_METHOD(fd, sndbuf + l, BUFSIZ - l - 1)) > 0) {
    +            fd_bytes(fd, n, FD_READ);
    +            l += n;
    +            sndbuf[l] = '\0';
    +            file_close(fd);
    +        } else {
    +            debug(50, 1) ("send_announce: %s: %s\n", file, xstrerror());
    +        }
         }
    +
         memset(&S, '\0', sizeof(S));
         S.sin_family = AF_INET;
         S.sin_port = htons(port);
         S.sin_addr = ia->in_addrs[0];
         assert(theOutIcpConnection > 0);
         x = comm_udp_sendto(theOutIcpConnection,
    -	&S, sizeof(S),
    -	sndbuf, strlen(sndbuf) + 1);
    +                        &S, sizeof(S),
    +                        sndbuf, strlen(sndbuf) + 1);
    +
         if (x < 0)
    -	debug(27, 1) ("send_announce: FD %d: %s\n", theOutIcpConnection,
    -	    xstrerror());
    +        debug(27, 1) ("send_announce: FD %d: %s\n", theOutIcpConnection,
    +                      xstrerror());
     }
    diff --git a/src/snmp_agent.cc b/src/snmp_agent.cc
    index ed7713a380..b5709a7102 100644
    --- a/src/snmp_agent.cc
    +++ b/src/snmp_agent.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: snmp_agent.cc,v 1.86 2003/01/23 00:37:25 robertc Exp $
    + * $Id: snmp_agent.cc,v 1.87 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 49     SNMP Interface
      * AUTHOR: Kostas Anagnostakis
    @@ -40,9 +40,9 @@
     #include "mem_node.h"
     
     /************************************************************************
    -
    + 
      SQUID MIB Implementation
    -
    + 
      ************************************************************************/
     
     variable_list *
    @@ -52,26 +52,32 @@ snmp_sysFn(variable_list * Var, snint * ErrP)
         debug(49, 5) ("snmp_sysFn: Processing request:\n");
         snmpDebugOid(5, Var->name, Var->name_length);
         *ErrP = SNMP_ERR_NOERROR;
    +
         switch (Var->name[LEN_SQ_SYS]) {
    +
         case SYSVMSIZ:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    mem_node::store_mem_size >> 10,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      mem_node::store_mem_size >> 10,
    +                                      ASN_INTEGER);
    +        break;
    +
         case SYSSTOR:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    store_swap_size,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      store_swap_size,
    +                                      ASN_INTEGER);
    +        break;
    +
         case SYS_UPTIME:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (int)(tvSubDsec(squid_start, current_time) * 100),
    -	    SMI_TIMETICKS);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (int)(tvSubDsec(squid_start, current_time) * 100),
    +                                      SMI_TIMETICKS);
    +        break;
    +
         default:
    -	*ErrP = SNMP_ERR_NOSUCHNAME;
    -	break;
    +        *ErrP = SNMP_ERR_NOSUCHNAME;
    +        break;
         }
    +
         return Answer;
     }
     
    @@ -82,64 +88,85 @@ snmp_confFn(variable_list * Var, snint * ErrP)
         const char *cp = NULL;
         debug(49, 5) ("snmp_confFn: Processing request with magic %d!\n", Var->name[8]);
         *ErrP = SNMP_ERR_NOERROR;
    +
         switch (Var->name[LEN_SQ_CONF]) {
    +
         case CONF_ADMIN:
    -	Answer = snmp_var_new(Var->name, Var->name_length);
    -	Answer->type = ASN_OCTET_STR;
    -	Answer->val_len = strlen(Config.adminEmail);
    -	Answer->val.string = (u_char *) xstrdup(Config.adminEmail);
    -	break;
    +        Answer = snmp_var_new(Var->name, Var->name_length);
    +        Answer->type = ASN_OCTET_STR;
    +        Answer->val_len = strlen(Config.adminEmail);
    +        Answer->val.string = (u_char *) xstrdup(Config.adminEmail);
    +        break;
    +
         case CONF_VERSION:
    -	Answer = snmp_var_new(Var->name, Var->name_length);
    -	Answer->type = ASN_OCTET_STR;
    -	Answer->val_len = strlen(appname);
    -	Answer->val.string = (u_char *) xstrdup(appname);
    -	break;
    +        Answer = snmp_var_new(Var->name, Var->name_length);
    +        Answer->type = ASN_OCTET_STR;
    +        Answer->val_len = strlen(appname);
    +        Answer->val.string = (u_char *) xstrdup(appname);
    +        break;
    +
         case CONF_VERSION_ID:
    -	Answer = snmp_var_new(Var->name, Var->name_length);
    -	Answer->type = ASN_OCTET_STR;
    -	Answer->val_len = strlen(VERSION);
    -	Answer->val.string = (u_char *) xstrdup(VERSION);
    -	break;
    +        Answer = snmp_var_new(Var->name, Var->name_length);
    +        Answer->type = ASN_OCTET_STR;
    +        Answer->val_len = strlen(VERSION);
    +        Answer->val.string = (u_char *) xstrdup(VERSION);
    +        break;
    +
         case CONF_STORAGE:
    -	switch (Var->name[LEN_SQ_CONF + 1]) {
    -	case CONF_ST_MMAXSZ:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) Config.memMaxSize >> 20,
    -		ASN_INTEGER);
    -	    break;
    -	case CONF_ST_SWMAXSZ:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) Config.Swap.maxSize >> 10,
    -		ASN_INTEGER);
    -	    break;
    -	case CONF_ST_SWHIWM:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) Config.Swap.highWaterMark,
    -		ASN_INTEGER);
    -	    break;
    -	case CONF_ST_SWLOWM:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) Config.Swap.lowWaterMark,
    -		ASN_INTEGER);
    -	    break;
    -	default:
    -	    *ErrP = SNMP_ERR_NOSUCHNAME;
    -	    break;
    -	}
    -	break;
    +
    +        switch (Var->name[LEN_SQ_CONF + 1]) {
    +
    +        case CONF_ST_MMAXSZ:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) Config.memMaxSize >> 20,
    +                                          ASN_INTEGER);
    +            break;
    +
    +        case CONF_ST_SWMAXSZ:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) Config.Swap.maxSize >> 10,
    +                                          ASN_INTEGER);
    +            break;
    +
    +        case CONF_ST_SWHIWM:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) Config.Swap.highWaterMark,
    +                                          ASN_INTEGER);
    +            break;
    +
    +        case CONF_ST_SWLOWM:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) Config.Swap.lowWaterMark,
    +                                          ASN_INTEGER);
    +            break;
    +
    +        default:
    +            *ErrP = SNMP_ERR_NOSUCHNAME;
    +            break;
    +        }
    +
    +        break;
    +
         case CONF_LOG_FAC:
    -	Answer = snmp_var_new(Var->name, Var->name_length);
    -	if (!(cp = Config.debugOptions))
    -	    cp = "None";
    -	Answer->type = ASN_OCTET_STR;
    -	Answer->val_len = strlen(cp);
    -	Answer->val.string = (u_char *) xstrdup(cp);
    -	break;
    +        Answer = snmp_var_new(Var->name, Var->name_length);
    +
    +        if (!(cp = Config.debugOptions))
    +            cp = "None";
    +
    +        Answer->type = ASN_OCTET_STR;
    +
    +        Answer->val_len = strlen(cp);
    +
    +        Answer->val.string = (u_char *) xstrdup(cp);
    +
    +        break;
    +
         default:
    -	*ErrP = SNMP_ERR_NOSUCHNAME;
    -	break;
    +        *ErrP = SNMP_ERR_NOSUCHNAME;
    +
    +        break;
         }
    +
         return Answer;
     }
     
    @@ -147,6 +174,7 @@ variable_list *
     snmp_meshPtblFn(variable_list * Var, snint * ErrP)
     {
         variable_list *Answer = NULL;
    +
         struct in_addr *laddr;
         char *cp = NULL;
         peer *p = NULL;
    @@ -154,85 +182,103 @@ snmp_meshPtblFn(variable_list * Var, snint * ErrP)
         debug(49, 5) ("snmp_meshPtblFn: peer %d requested!\n", Var->name[LEN_SQ_MESH + 3]);
         *ErrP = SNMP_ERR_NOERROR;
         laddr = oid2addr(&Var->name[LEN_SQ_MESH + 3]);
    +
         for (p = Config.peers; p != NULL; p = p->next, cnt++)
    -	if (p->in_addr.sin_addr.s_addr == laddr->s_addr)
    -	    break;
    +        if (p->in_addr.sin_addr.s_addr == laddr->s_addr)
    +            break;
    +
         if (p == NULL) {
    -	*ErrP = SNMP_ERR_NOSUCHNAME;
    -	return NULL;
    +        *ErrP = SNMP_ERR_NOSUCHNAME;
    +        return NULL;
         }
    +
         switch (Var->name[LEN_SQ_MESH + 2]) {
    +
         case MESH_PTBL_NAME:
    -	cp = p->host;
    -	Answer = snmp_var_new(Var->name, Var->name_length);
    -	Answer->type = ASN_OCTET_STR;
    -	Answer->val_len = strlen(cp);
    -	Answer->val.string = (u_char *) xstrdup(cp);
    -	break;
    +        cp = p->host;
    +        Answer = snmp_var_new(Var->name, Var->name_length);
    +        Answer->type = ASN_OCTET_STR;
    +        Answer->val_len = strlen(cp);
    +        Answer->val.string = (u_char *) xstrdup(cp);
    +        break;
    +
         case MESH_PTBL_IP:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) p->in_addr.sin_addr.s_addr,
    -	    SMI_IPADDRESS);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) p->in_addr.sin_addr.s_addr,
    +                                      SMI_IPADDRESS);
    +        break;
    +
         case MESH_PTBL_HTTP:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) p->http_port,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) p->http_port,
    +                                      ASN_INTEGER);
    +        break;
    +
         case MESH_PTBL_ICP:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) p->icp.port,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) p->icp.port,
    +                                      ASN_INTEGER);
    +        break;
    +
         case MESH_PTBL_TYPE:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) p->type,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) p->type,
    +                                      ASN_INTEGER);
    +        break;
    +
         case MESH_PTBL_STATE:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) neighborUp(p),
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) neighborUp(p),
    +                                      ASN_INTEGER);
    +        break;
    +
         case MESH_PTBL_SENT:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    p->stats.pings_sent,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      p->stats.pings_sent,
    +                                      ASN_INTEGER);
    +        break;
    +
         case MESH_PTBL_PACKED:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    p->stats.pings_acked,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      p->stats.pings_acked,
    +                                      ASN_INTEGER);
    +        break;
    +
         case MESH_PTBL_FETCHES:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    p->stats.fetches,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      p->stats.fetches,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case MESH_PTBL_RTT:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    p->stats.rtt,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      p->stats.rtt,
    +                                      ASN_INTEGER);
    +        break;
    +
         case MESH_PTBL_IGN:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    p->stats.ignored_replies,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      p->stats.ignored_replies,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case MESH_PTBL_KEEPAL_S:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    p->stats.n_keepalives_sent,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      p->stats.n_keepalives_sent,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case MESH_PTBL_KEEPAL_R:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    p->stats.n_keepalives_recv,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      p->stats.n_keepalives_recv,
    +                                      SMI_COUNTER32);
    +        break;
    +
         default:
    -	*ErrP = SNMP_ERR_NOSUCHNAME;
    -	break;
    +        *ErrP = SNMP_ERR_NOSUCHNAME;
    +        break;
         }
    +
         return Answer;
     }
     
    @@ -240,74 +286,89 @@ variable_list *
     snmp_prfSysFn(variable_list * Var, snint * ErrP)
     {
         variable_list *Answer = NULL;
    +
         static struct rusage rusage;
         debug(49, 5) ("snmp_prfSysFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF + 1]);
         *ErrP = SNMP_ERR_NOERROR;
    +
         switch (Var->name[LEN_SQ_PRF + 1]) {
    +
         case PERF_SYS_PF:
    -	squid_getrusage(&rusage);
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    rusage_pagefaults(&rusage),
    -	    SMI_COUNTER32);
    -	break;
    +        squid_getrusage(&rusage);
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      rusage_pagefaults(&rusage),
    +                                      SMI_COUNTER32);
    +        break;
    +
         case PERF_SYS_NUMR:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    IOStats.Http.reads,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      IOStats.Http.reads,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case PERF_SYS_MEMUSAGE:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) statMemoryAccounted() >> 10,
    -	    ASN_INTEGER);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) statMemoryAccounted() >> 10,
    +                                      ASN_INTEGER);
    +        break;
    +
         case PERF_SYS_CPUTIME:
    -	squid_getrusage(&rusage);
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) rusage_cputime(&rusage),
    -	    ASN_INTEGER);
    -	break;
    +        squid_getrusage(&rusage);
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) rusage_cputime(&rusage),
    +                                      ASN_INTEGER);
    +        break;
    +
         case PERF_SYS_CPUUSAGE:
    -	squid_getrusage(&rusage);
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) dpercent(rusage_cputime(&rusage), tvSubDsec(squid_start, current_time)),
    -	    ASN_INTEGER);
    -	break;
    +        squid_getrusage(&rusage);
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) dpercent(rusage_cputime(&rusage), tvSubDsec(squid_start, current_time)),
    +                                      ASN_INTEGER);
    +        break;
    +
         case PERF_SYS_MAXRESSZ:
    -	squid_getrusage(&rusage);
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) rusage_maxrss(&rusage),
    -	    ASN_INTEGER);
    -	break;
    +        squid_getrusage(&rusage);
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) rusage_maxrss(&rusage),
    +                                      ASN_INTEGER);
    +        break;
    +
         case PERF_SYS_CURLRUEXP:
    -	/* No global LRU info anymore */
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    0,
    -	    SMI_TIMETICKS);
    -	break;
    +        /* No global LRU info anymore */
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      0,
    +                                      SMI_TIMETICKS);
    +        break;
    +
         case PERF_SYS_CURUNLREQ:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) statCounter.unlink.requests,
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) statCounter.unlink.requests,
    +                                      SMI_COUNTER32);
    +        break;
    +
         case PERF_SYS_CURUNUSED_FD:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) Squid_MaxFD - Number_FD,
    -	    SMI_GAUGE32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) Squid_MaxFD - Number_FD,
    +                                      SMI_GAUGE32);
    +        break;
    +
         case PERF_SYS_CURRESERVED_FD:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) RESERVED_FD,
    -	    SMI_GAUGE32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) RESERVED_FD,
    +                                      SMI_GAUGE32);
    +        break;
    +
         case PERF_SYS_NUMOBJCNT:
    -	Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) StoreEntry::inUseCount(),
    -	    SMI_COUNTER32);
    -	break;
    +        Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                      (snint) StoreEntry::inUseCount(),
    +                                      SMI_COUNTER32);
    +        break;
    +
         default:
    -	*ErrP = SNMP_ERR_NOSUCHNAME;
    -	break;
    +        *ErrP = SNMP_ERR_NOSUCHNAME;
    +        break;
         }
    +
         return Answer;
     }
     
    @@ -321,144 +382,185 @@ snmp_prfProtoFn(variable_list * Var, snint * ErrP)
         int minutes;
         debug(49, 5) ("snmp_prfProtoFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF]);
         *ErrP = SNMP_ERR_NOERROR;
    +
         switch (Var->name[LEN_SQ_PRF + 1]) {
    +
         case PERF_PROTOSTAT_AGGR:	/* cacheProtoAggregateStats */
    -	switch (Var->name[LEN_SQ_PRF + 2]) {
    -	case PERF_PROTOSTAT_AGGR_HTTP_REQ:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.client_http.requests,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_HTTP_HITS:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.client_http.hits,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_HTTP_ERRORS:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.client_http.errors,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.client_http.kbytes_in.kb,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.client_http.kbytes_out.kb,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_ICP_S:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.icp.pkts_sent,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_ICP_R:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.icp.pkts_recv,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_ICP_SKB:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.icp.kbytes_sent.kb,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_ICP_RKB:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.icp.kbytes_recv.kb,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_REQ:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.server.all.requests,
    -		SMI_INTEGER);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_ERRORS:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.server.all.errors,
    -		SMI_INTEGER);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_KBYTES_IN:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.server.all.kbytes_in.kb,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_KBYTES_OUT:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.server.all.kbytes_out.kb,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_CURSWAP:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) store_swap_size,
    -		SMI_COUNTER32);
    -	    break;
    -	case PERF_PROTOSTAT_AGGR_CLIENTS:
    -	    Answer = snmp_var_new_integer(Var->name, Var->name_length,
    -		(snint) statCounter.client_http.clients,
    -		SMI_COUNTER32);
    -	    break;
    -	default:
    -	    *ErrP = SNMP_ERR_NOSUCHNAME;
    -	    break;
    -	}
    -	return Answer;
    +
    +        switch (Var->name[LEN_SQ_PRF + 2]) {
    +
    +        case PERF_PROTOSTAT_AGGR_HTTP_REQ:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.client_http.requests,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_HTTP_HITS:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.client_http.hits,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_HTTP_ERRORS:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.client_http.errors,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.client_http.kbytes_in.kb,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.client_http.kbytes_out.kb,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_ICP_S:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.icp.pkts_sent,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_ICP_R:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.icp.pkts_recv,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_ICP_SKB:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.icp.kbytes_sent.kb,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_ICP_RKB:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.icp.kbytes_recv.kb,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_REQ:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.server.all.requests,
    +                                          SMI_INTEGER);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_ERRORS:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.server.all.errors,
    +                                          SMI_INTEGER);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_KBYTES_IN:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.server.all.kbytes_in.kb,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_KBYTES_OUT:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.server.all.kbytes_out.kb,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_CURSWAP:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) store_swap_size,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        case PERF_PROTOSTAT_AGGR_CLIENTS:
    +            Answer = snmp_var_new_integer(Var->name, Var->name_length,
    +                                          (snint) statCounter.client_http.clients,
    +                                          SMI_COUNTER32);
    +            break;
    +
    +        default:
    +            *ErrP = SNMP_ERR_NOSUCHNAME;
    +            break;
    +        }
    +
    +        return Answer;
    +
         case PERF_PROTOSTAT_MEDIAN:
    -	if (Var->name_length == LEN_SQ_PRF + 5)
    -	    minutes = Var->name[LEN_SQ_PRF + 4];
    -	else
    -	    break;
    -	if ((minutes < 1) || (minutes > 60))
    -	    break;
    -	f = snmpStatGet(0);
    -	l = snmpStatGet(minutes);
    -	debug(49, 8) ("median: min= %d, %d l= %p , f = %p\n", minutes,
    -	    Var->name[LEN_SQ_PRF + 3], l, f);
    -	debug(49, 8) ("median: l= %p , f = %p\n", l, f);
    -	switch (Var->name[LEN_SQ_PRF + 3]) {
    -	case PERF_MEDIAN_TIME:
    -	    x = minutes;
    -	    break;
    -	case PERF_MEDIAN_HTTP_ALL:
    -	    x = statHistDeltaMedian(&l->client_http.all_svc_time,
    -		&f->client_http.all_svc_time);
    -	    break;
    -	case PERF_MEDIAN_HTTP_MISS:
    -	    x = statHistDeltaMedian(&l->client_http.miss_svc_time,
    -		&f->client_http.miss_svc_time);
    -	    break;
    -	case PERF_MEDIAN_HTTP_NM:
    -	    x = statHistDeltaMedian(&l->client_http.nm_svc_time,
    -		&f->client_http.nm_svc_time);
    -	    break;
    -	case PERF_MEDIAN_HTTP_HIT:
    -	    x = statHistDeltaMedian(&l->client_http.hit_svc_time,
    -		&f->client_http.hit_svc_time);
    -	    break;
    -	case PERF_MEDIAN_ICP_QUERY:
    -	    x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
    -	    break;
    -	case PERF_MEDIAN_ICP_REPLY:
    -	    x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
    -	    break;
    -	case PERF_MEDIAN_DNS:
    -	    x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
    -	    break;
    -	case PERF_MEDIAN_RHR:
    -	    x = statRequestHitRatio(minutes);
    -	    break;
    -	case PERF_MEDIAN_BHR:
    -	    x = statByteHitRatio(minutes);
    -	    break;
    -	default:
    -	    *ErrP = SNMP_ERR_NOSUCHNAME;
    -	    return NULL;
    -	}
    -	return snmp_var_new_integer(Var->name, Var->name_length,
    -	    (snint) x,
    -	    SMI_INTEGER);
    +
    +        if (Var->name_length == LEN_SQ_PRF + 5)
    +            minutes = Var->name[LEN_SQ_PRF + 4];
    +        else
    +            break;
    +
    +        if ((minutes < 1) || (minutes > 60))
    +            break;
    +
    +        f = snmpStatGet(0);
    +
    +        l = snmpStatGet(minutes);
    +
    +        debug(49, 8) ("median: min= %d, %d l= %p , f = %p\n", minutes,
    +                      Var->name[LEN_SQ_PRF + 3], l, f);
    +
    +        debug(49, 8) ("median: l= %p , f = %p\n", l, f);
    +
    +        switch (Var->name[LEN_SQ_PRF + 3]) {
    +
    +        case PERF_MEDIAN_TIME:
    +            x = minutes;
    +            break;
    +
    +        case PERF_MEDIAN_HTTP_ALL:
    +            x = statHistDeltaMedian(&l->client_http.all_svc_time,
    +                                    &f->client_http.all_svc_time);
    +            break;
    +
    +        case PERF_MEDIAN_HTTP_MISS:
    +            x = statHistDeltaMedian(&l->client_http.miss_svc_time,
    +                                    &f->client_http.miss_svc_time);
    +            break;
    +
    +        case PERF_MEDIAN_HTTP_NM:
    +            x = statHistDeltaMedian(&l->client_http.nm_svc_time,
    +                                    &f->client_http.nm_svc_time);
    +            break;
    +
    +        case PERF_MEDIAN_HTTP_HIT:
    +            x = statHistDeltaMedian(&l->client_http.hit_svc_time,
    +                                    &f->client_http.hit_svc_time);
    +            break;
    +
    +        case PERF_MEDIAN_ICP_QUERY:
    +            x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
    +            break;
    +
    +        case PERF_MEDIAN_ICP_REPLY:
    +            x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
    +            break;
    +
    +        case PERF_MEDIAN_DNS:
    +            x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
    +            break;
    +
    +        case PERF_MEDIAN_RHR:
    +            x = statRequestHitRatio(minutes);
    +            break;
    +
    +        case PERF_MEDIAN_BHR:
    +            x = statByteHitRatio(minutes);
    +            break;
    +
    +        default:
    +            *ErrP = SNMP_ERR_NOSUCHNAME;
    +            return NULL;
    +        }
    +
    +        return snmp_var_new_integer(Var->name, Var->name_length,
    +                                    (snint) x,
    +                                    SMI_INTEGER);
         }
    +
         *ErrP = SNMP_ERR_NOSUCHNAME;
         return NULL;
     }
    diff --git a/src/snmp_core.cc b/src/snmp_core.cc
    index 5d8028a871..dfa8f1572c 100644
    --- a/src/snmp_core.cc
    +++ b/src/snmp_core.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: snmp_core.cc,v 1.61 2003/01/28 01:29:35 robertc Exp $
    + * $Id: snmp_core.cc,v 1.62 2003/02/21 22:50:10 robertc Exp $
      *
      * DEBUG: section 49    SNMP support
      * AUTHOR: Glenn Chisholm
    @@ -43,13 +43,16 @@
     typedef struct _mib_tree_entry mib_tree_entry;
     typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
     
    -struct _mib_tree_entry {
    +struct _mib_tree_entry
    +{
         oid *name;
         int len;
         oid_ParseFn *parsefunction;
         instance_Fn *instancefunction;
         int children;
    +
         struct _mib_tree_entry **leaves;
    +
         struct _mib_tree_entry *parent;
     };
     
    @@ -70,6 +73,7 @@ static oid *peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_Par
     static oid *client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
     static void snmpDecodePacket(snmp_request_t * rq);
     static void snmpConstructReponse(snmp_request_t * rq);
    +
     static struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU);
     static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen);
     static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen);
    @@ -99,248 +103,248 @@ snmpInit(void)
         snmplib_debug_hook = snmpSnmplibDebug;
     
         mib_tree_head = snmpAddNode(snmpCreateOid(1, 1),
    -	1, NULL, NULL, 1,
    -	snmpAddNode(snmpCreateOid(2, 1, 3),
    -	    2, NULL, NULL, 1,
    -	    snmpAddNode(snmpCreateOid(3, 1, 3, 6),
    -		3, NULL, NULL, 1,
    -		snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
    -		    4, NULL, NULL, 1,
    -		    snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
    -			5, NULL, NULL, 1,
    -			snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
    -			    6, NULL, NULL, 1,
    -			    snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
    -				7, NULL, NULL, 1,
    -				snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
    -				    8, NULL, NULL, 5,
    -				    snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
    -					LEN_SQ_SYS, NULL, NULL, 3,
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSVMSIZ),
    -					    LEN_SYS, snmp_sysFn, static_Inst, 0),
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSSTOR),
    -					    LEN_SYS, snmp_sysFn, static_Inst, 0),
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYS_UPTIME),
    -					    LEN_SYS, snmp_sysFn, static_Inst, 0)),
    -				    snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF),
    -					LEN_SQ_CONF, NULL, NULL, 5,
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_ADMIN),
    -					    LEN_SYS, snmp_confFn, static_Inst, 0),
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION),
    -					    LEN_SYS, snmp_confFn, static_Inst, 0),
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION_ID),
    -					    LEN_SYS, snmp_confFn, static_Inst, 0),
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_LOG_FAC),
    -					    LEN_SYS, snmp_confFn, static_Inst, 0),
    -					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_STORAGE),
    -					    LEN_SYS, NULL, NULL, 4,
    -					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_MMAXSZ),
    -						LEN_CONF_ST, snmp_confFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWMAXSZ),
    -						LEN_CONF_ST, snmp_confFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWHIWM),
    -						LEN_CONF_ST, snmp_confFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWLOWM),
    -						LEN_CONF_ST, snmp_confFn, static_Inst, 0))),
    -				    snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF),
    -					LEN_SQ_PRF, NULL, NULL, 2,
    -					snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_SYS),
    -					    LEN_SQ_PRF + 1, NULL, NULL, 11,
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 1),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 2),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 3),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 4),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 5),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 6),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 7),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 8),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 9),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 10),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 11),
    -						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0)),
    -					snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_PROTO),
    -					    LEN_SQ_PRF + 1, NULL, NULL, 2,
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 1),
    -						LEN_SQ_PRF + 2, NULL, NULL, 15,
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 1),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 2),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 3),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 4),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 5),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 6),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 7),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 8),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 9),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 10),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 11),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 12),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 13),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 14),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 15),
    -						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0)),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 2),
    -						LEN_SQ_PRF + 2, NULL, NULL, 1,
    -						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 2, 1),
    -						    LEN_SQ_PRF + 3, NULL, NULL, 10,
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 1),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 2),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 3),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 4),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 5),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 6),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 7),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 8),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 9),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    -						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 10),
    -							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0))))),
    -				    snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET),
    -					LEN_SQ_NET, NULL, NULL, 3,
    -					snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_IP_CACHE),
    -					    LEN_SQ_NET + 1, NULL, NULL, 8,
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_ENT),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_REQ),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_HITS),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_PENDHIT),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_NEGHIT),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_MISS),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_GHBN),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_LOC),
    -						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0)),
    -					snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_FQDN_CACHE),
    -					    LEN_SQ_NET + 1, NULL, NULL, 7,
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_ENT),
    -						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_REQ),
    -						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_HITS),
    -						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_PENDHIT),
    -						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_NEGHIT),
    -						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_MISS),
    -						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_GHBN),
    -						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0)),
    -					snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_DNS_CACHE),
    -					    LEN_SQ_NET + 1, NULL, NULL, 3,
    +                                1, NULL, NULL, 1,
    +                                snmpAddNode(snmpCreateOid(2, 1, 3),
    +                                            2, NULL, NULL, 1,
    +                                            snmpAddNode(snmpCreateOid(3, 1, 3, 6),
    +                                                        3, NULL, NULL, 1,
    +                                                        snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
    +                                                                    4, NULL, NULL, 1,
    +                                                                    snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
    +                                                                                5, NULL, NULL, 1,
    +                                                                                snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
    +                                                                                            6, NULL, NULL, 1,
    +                                                                                            snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
    +                                                                                                        7, NULL, NULL, 1,
    +                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
    +                                                                                                                    8, NULL, NULL, 5,
    +                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
    +                                                                                                                                LEN_SQ_SYS, NULL, NULL, 3,
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSVMSIZ),
    +                                                                                                                                            LEN_SYS, snmp_sysFn, static_Inst, 0),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSSTOR),
    +                                                                                                                                            LEN_SYS, snmp_sysFn, static_Inst, 0),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYS_UPTIME),
    +                                                                                                                                            LEN_SYS, snmp_sysFn, static_Inst, 0)),
    +                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF),
    +                                                                                                                                LEN_SQ_CONF, NULL, NULL, 5,
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_ADMIN),
    +                                                                                                                                            LEN_SYS, snmp_confFn, static_Inst, 0),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION),
    +                                                                                                                                            LEN_SYS, snmp_confFn, static_Inst, 0),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION_ID),
    +                                                                                                                                            LEN_SYS, snmp_confFn, static_Inst, 0),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_LOG_FAC),
    +                                                                                                                                            LEN_SYS, snmp_confFn, static_Inst, 0),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_STORAGE),
    +                                                                                                                                            LEN_SYS, NULL, NULL, 4,
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_MMAXSZ),
    +                                                                                                                                                        LEN_CONF_ST, snmp_confFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWMAXSZ),
    +                                                                                                                                                        LEN_CONF_ST, snmp_confFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWHIWM),
    +                                                                                                                                                        LEN_CONF_ST, snmp_confFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWLOWM),
    +                                                                                                                                                        LEN_CONF_ST, snmp_confFn, static_Inst, 0))),
    +                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF),
    +                                                                                                                                LEN_SQ_PRF, NULL, NULL, 2,
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_SYS),
    +                                                                                                                                            LEN_SQ_PRF + 1, NULL, NULL, 11,
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 1),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 2),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 3),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 4),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 5),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 6),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 7),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 8),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 9),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 10),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 11),
    +                                                                                                                                                        LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0)),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_PROTO),
    +                                                                                                                                            LEN_SQ_PRF + 1, NULL, NULL, 2,
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 1),
    +                                                                                                                                                        LEN_SQ_PRF + 2, NULL, NULL, 15,
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 1),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 2),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 3),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 4),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 5),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 6),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 7),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 8),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 9),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 10),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 11),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 12),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 13),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 14),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 15),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0)),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 2),
    +                                                                                                                                                        LEN_SQ_PRF + 2, NULL, NULL, 1,
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 2, 1),
    +                                                                                                                                                                    LEN_SQ_PRF + 3, NULL, NULL, 10,
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 1),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 2),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 3),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 4),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 5),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 6),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 7),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 8),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 9),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
    +                                                                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 10),
    +                                                                                                                                                                                LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0))))),
    +                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET),
    +                                                                                                                                LEN_SQ_NET, NULL, NULL, 3,
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_IP_CACHE),
    +                                                                                                                                            LEN_SQ_NET + 1, NULL, NULL, 8,
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_ENT),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_REQ),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_HITS),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_PENDHIT),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_NEGHIT),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_MISS),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_GHBN),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_LOC),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0)),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_FQDN_CACHE),
    +                                                                                                                                            LEN_SQ_NET + 1, NULL, NULL, 7,
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_ENT),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_REQ),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_HITS),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_PENDHIT),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_NEGHIT),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_MISS),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_GHBN),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0)),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_DNS_CACHE),
    +                                                                                                                                            LEN_SQ_NET + 1, NULL, NULL, 3,
     #if USE_DNSSERVERS
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
    -						LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
    -						LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
    -						LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0))),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0))),
     #else
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
    -						LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
    -						LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
    -						LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0))),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
    +                                                                                                                                                        LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0))),
     #endif
    -				    snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH),
    -					LEN_SQ_MESH, NULL, NULL, 2,
    -					snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1),
    -					    LEN_SQ_MESH + 1, NULL, NULL, 1,
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1),
    -						LEN_SQ_MESH + 2, NULL, NULL, 13,
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 1),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13),
    -						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0))),
    -					snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2),
    -					    LEN_SQ_MESH + 1, NULL, NULL, 1,
    -					    snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 2, 1),
    -						LEN_SQ_MESH + 2, NULL, NULL, 9,
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 1),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8),
    -						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    -						(mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9),
    -							LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0)))))
    -				)
    -			    )
    -			)
    -		    )
    -		)
    -	    )
    -	)
    -	);
    +                                                                                                                    snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH),
    +                                                                                                                                LEN_SQ_MESH, NULL, NULL, 2,
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1),
    +                                                                                                                                            LEN_SQ_MESH + 1, NULL, NULL, 1,
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1),
    +                                                                                                                                                        LEN_SQ_MESH + 2, NULL, NULL, 13,
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 1),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0))),
    +                                                                                                                                snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2),
    +                                                                                                                                            LEN_SQ_MESH + 1, NULL, NULL, 1,
    +                                                                                                                                            snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 2, 1),
    +                                                                                                                                                        LEN_SQ_MESH + 2, NULL, NULL, 9,
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 1),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8),
    +                                                                                                                                                                    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
    +                                                                                                                                                        (mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9),
    +                                                                                                                                                                                     LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0)))))
    +                                                                                                                   )
    +                                                                                                       )
    +                                                                                           )
    +                                                                               )
    +                                                                   )
    +                                                       )
    +                                           )
    +                               );
     
         debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n");
     }
    @@ -349,57 +353,72 @@ void
     snmpConnectionOpen(void)
     {
         u_short port;
    +
         struct sockaddr_in xaddr;
         socklen_t len;
         int x;
     
         debug(49, 5) ("snmpConnectionOpen: Called\n");
    +
         if ((port = Config.Port.snmp) > (u_short) 0) {
    -	enter_suid();
    -	theInSnmpConnection = comm_open(SOCK_DGRAM,
    -	    0,
    -	    Config.Addrs.snmp_incoming,
    -	    port,
    -	    COMM_NONBLOCKING,
    -	    "SNMP Port");
    -	leave_suid();
    -	if (theInSnmpConnection < 0)
    -	    fatal("Cannot open snmp Port");
    -	commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
    -	debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
    -	    (int) port, theInSnmpConnection);
    -	if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) {
    -	    enter_suid();
    -	    theOutSnmpConnection = comm_open(SOCK_DGRAM,
    -		0,
    -		Config.Addrs.snmp_outgoing,
    -		port,
    -		COMM_NONBLOCKING,
    -		"SNMP Port");
    -	    leave_suid();
    -	    if (theOutSnmpConnection < 0)
    -		fatal("Cannot open Outgoing SNMP Port");
    -	    commSetSelect(theOutSnmpConnection,
    -		COMM_SELECT_READ,
    -		snmpHandleUdp,
    -		NULL, 0);
    -	    debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n",
    -		(int) port, theOutSnmpConnection);
    -	    fd_note(theOutSnmpConnection, "Outgoing SNMP socket");
    -	    fd_note(theInSnmpConnection, "Incoming SNMP socket");
    -	} else {
    -	    theOutSnmpConnection = theInSnmpConnection;
    -	}
    -	memset(&theOutSNMPAddr, '\0', sizeof(struct in_addr));
    -	len = sizeof(struct sockaddr_in);
    -	memset(&xaddr, '\0', len);
    -	x = getsockname(theOutSnmpConnection,
    -	    (struct sockaddr *) &xaddr, &len);
    -	if (x < 0)
    -	    debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
    -		theOutSnmpConnection, xstrerror());
    -	else
    -	    theOutSNMPAddr = xaddr.sin_addr;
    +        enter_suid();
    +        theInSnmpConnection = comm_open(SOCK_DGRAM,
    +                                        0,
    +                                        Config.Addrs.snmp_incoming,
    +                                        port,
    +                                        COMM_NONBLOCKING,
    +                                        "SNMP Port");
    +        leave_suid();
    +
    +        if (theInSnmpConnection < 0)
    +            fatal("Cannot open snmp Port");
    +
    +        commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
    +
    +        debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
    +                     (int) port, theInSnmpConnection);
    +
    +        if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) {
    +            enter_suid();
    +            theOutSnmpConnection = comm_open(SOCK_DGRAM,
    +                                             0,
    +                                             Config.Addrs.snmp_outgoing,
    +                                             port,
    +                                             COMM_NONBLOCKING,
    +                                             "SNMP Port");
    +            leave_suid();
    +
    +            if (theOutSnmpConnection < 0)
    +                fatal("Cannot open Outgoing SNMP Port");
    +
    +            commSetSelect(theOutSnmpConnection,
    +                          COMM_SELECT_READ,
    +                          snmpHandleUdp,
    +                          NULL, 0);
    +
    +            debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n",
    +                         (int) port, theOutSnmpConnection);
    +
    +            fd_note(theOutSnmpConnection, "Outgoing SNMP socket");
    +
    +            fd_note(theInSnmpConnection, "Incoming SNMP socket");
    +        } else {
    +            theOutSnmpConnection = theInSnmpConnection;
    +        }
    +
    +        memset(&theOutSNMPAddr, '\0', sizeof(struct in_addr));
    +
    +        len = sizeof(struct sockaddr_in);
    +        memset(&xaddr, '\0', len);
    +        x = getsockname(theOutSnmpConnection,
    +
    +                        (struct sockaddr *) &xaddr, &len);
    +
    +        if (x < 0)
    +            debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
    +                          theOutSnmpConnection, xstrerror());
    +        else
    +            theOutSNMPAddr = xaddr.sin_addr;
         }
     }
     
    @@ -407,17 +426,20 @@ void
     snmpConnectionShutdown(void)
     {
         if (theInSnmpConnection < 0)
    -	return;
    +        return;
    +
         if (theInSnmpConnection != theOutSnmpConnection) {
    -	debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection);
    -	comm_close(theInSnmpConnection);
    +        debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection);
    +        comm_close(theInSnmpConnection);
         }
    +
         /*
          * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in'
          * and 'out' sockets might be just one FD.  This prevents this
          * function from executing repeatedly.  When we are really ready to
          * exit or restart, main will comm_close the 'out' descriptor.
          */ theInSnmpConnection = -1;
    +
         /*
          * Normally we only write to the outgoing SNMP socket, but we
          * also have a read handler there to catch messages sent to that
    @@ -425,6 +447,7 @@ snmpConnectionShutdown(void)
          * on the outgoing socket.
          */
         assert(theOutSnmpConnection > -1);
    +
         commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
     }
     
    @@ -432,9 +455,10 @@ void
     snmpConnectionClose(void)
     {
         snmpConnectionShutdown();
    +
         if (theOutSnmpConnection > -1) {
    -	debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection);
    -	comm_close(theOutSnmpConnection);
    +        debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection);
    +        comm_close(theOutSnmpConnection);
         }
     }
     
    @@ -449,6 +473,7 @@ void
     snmpHandleUdp(int sock, void *not_used)
     {
         LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
    +
         struct sockaddr_in from;
         socklen_t from_len;
         snmp_request_t *snmp_rq;
    @@ -457,35 +482,38 @@ snmpHandleUdp(int sock, void *not_used)
         debug(49, 5) ("snmpHandleUdp: Called.\n");
     
         commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
    +
         from_len = sizeof(struct sockaddr_in);
         memset(&from, '\0', from_len);
         memset(buf, '\0', SNMP_REQUEST_SIZE);
     
         len = comm_udp_recvfrom(sock,
    -	buf,
    -	SNMP_REQUEST_SIZE,
    -	0,
    -	(struct sockaddr *) &from,
    -	&from_len);
    +                            buf,
    +                            SNMP_REQUEST_SIZE,
    +                            0,
    +
    +                            (struct sockaddr *) &from,
    +                            &from_len);
     
         if (len > 0) {
    -	buf[len] = '\0';
    -	debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
    -	    sock,
    -	    len,
    -	    inet_ntoa(from.sin_addr));
    -
    -	snmp_rq = (snmp_request_t *)xcalloc(1, sizeof(snmp_request_t));
    -	snmp_rq->buf = (u_char *) buf;
    -	snmp_rq->len = len;
    -	snmp_rq->sock = sock;
    -	snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
    -	xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
    -	snmpDecodePacket(snmp_rq);
    -	xfree(snmp_rq->outbuf);
    -	xfree(snmp_rq);
    +        buf[len] = '\0';
    +        debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
    +                      sock,
    +                      len,
    +                      inet_ntoa(from.sin_addr));
    +
    +        snmp_rq = (snmp_request_t *)xcalloc(1, sizeof(snmp_request_t));
    +        snmp_rq->buf = (u_char *) buf;
    +        snmp_rq->len = len;
    +        snmp_rq->sock = sock;
    +        snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
    +
    +        xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
    +        snmpDecodePacket(snmp_rq);
    +        xfree(snmp_rq->outbuf);
    +        xfree(snmp_rq);
         } else {
    -	debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror());
    +        debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror());
         }
     }
     
    @@ -495,7 +523,9 @@ snmpHandleUdp(int sock, void *not_used)
     static void
     snmpDecodePacket(snmp_request_t * rq)
     {
    +
         struct snmp_pdu *PDU;
    +
         struct snmp_session Session;
         u_char *Community;
         u_char *buf = rq->buf;
    @@ -512,19 +542,21 @@ snmpDecodePacket(snmp_request_t * rq)
         checklist.snmp_community = (char *) Community;
     
         if (Community)
    -	allow = aclCheckFast(Config.accessList.snmp, &checklist);
    +        allow = aclCheckFast(Config.accessList.snmp, &checklist);
    +
         if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
    -	rq->community = Community;
    -	rq->PDU = PDU;
    -	debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
    -	snmpConstructReponse(rq);
    +        rq->community = Community;
    +        rq->PDU = PDU;
    +        debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
    +        snmpConstructReponse(rq);
         } else {
    -	debug(49, 1) ("Failed SNMP agent query from : %s.\n",
    -	    inet_ntoa(rq->from.sin_addr));
    -	snmp_free_pdu(PDU);
    +        debug(49, 1) ("Failed SNMP agent query from : %s.\n",
    +                      inet_ntoa(rq->from.sin_addr));
    +        snmp_free_pdu(PDU);
         }
    +
         if (Community)
    -	xfree(Community);
    +        xfree(Community);
     }
     
     /*
    @@ -533,19 +565,22 @@ snmpDecodePacket(snmp_request_t * rq)
     static void
     snmpConstructReponse(snmp_request_t * rq)
     {
    +
         struct snmp_session Session;
    +
         struct snmp_pdu *RespPDU;
     
         debug(49, 5) ("snmpConstructReponse: Called.\n");
         RespPDU = snmpAgentResponse(rq->PDU);
         snmp_free_pdu(rq->PDU);
    +
         if (RespPDU != NULL) {
    -	Session.Version = SNMP_VERSION_1;
    -	Session.community = rq->community;
    -	Session.community_len = strlen((char *) rq->community);
    -	snmp_build(&Session, RespPDU, rq->outbuf, &rq->outlen);
    -	comm_udp_sendto(rq->sock, &rq->from, sizeof(rq->from), rq->outbuf, rq->outlen);
    -	snmp_free_pdu(RespPDU);
    +        Session.Version = SNMP_VERSION_1;
    +        Session.community = rq->community;
    +        Session.community_len = strlen((char *) rq->community);
    +        snmp_build(&Session, RespPDU, rq->outbuf, &rq->outlen);
    +        comm_udp_sendto(rq->sock, &rq->from, sizeof(rq->from), rq->outbuf, rq->outlen);
    +        snmp_free_pdu(RespPDU);
         }
     }
     
    @@ -553,9 +588,12 @@ snmpConstructReponse(snmp_request_t * rq)
      * Decide how to respond to the request, construct a response and
      * return the response to the requester.
      */
    +
     static struct snmp_pdu *
    -snmpAgentResponse(struct snmp_pdu *PDU)
    +
    +            snmpAgentResponse(struct snmp_pdu *PDU)
     {
    +
         struct snmp_pdu *Answer = NULL;
         oid_ParseFn *ParseFn = NULL;
     
    @@ -564,78 +602,85 @@ snmpAgentResponse(struct snmp_pdu *PDU)
     
         debug(49, 5) ("snmpAgentResponse: Called.\n");
     
    -    if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
    -	Answer->reqid = PDU->reqid;
    -	Answer->errindex = 0;
    -	if (PDU->command == SNMP_PDU_GET) {
    -	    variable_list **RespVars;
    -
    -	    RespVars = &(Answer->variables);
    -	    /* Loop through all variables */
    -	    for (VarPtrP = &(PDU->variables);
    -		*VarPtrP;
    -		VarPtrP = &((*VarPtrP)->next_variable)) {
    -		VarPtr = *VarPtrP;
    -
    -		index++;
    -
    -		/* Find the parsing function for this variable */
    -		ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
    -
    -		if (ParseFn == NULL) {
    -		    Answer->errstat = SNMP_ERR_NOSUCHNAME;
    -		    debug(49, 5) ("snmpAgentResponse: No such oid. ");
    -		} else
    -		    VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
    -
    -		/* Was there an error? */
    -		if ((Answer->errstat != SNMP_ERR_NOERROR) ||
    -		    (VarNew == NULL)) {
    -		    Answer->errindex = index;
    -		    debug(49, 5) ("snmpAgentParse: successful.\n");
    -		    /* Just copy the rest of the variables.  Quickly. */
    -		    *RespVars = VarPtr;
    -		    *VarPtrP = NULL;
    -		    return (Answer);
    -		}
    -		/* No error.  Insert this var at the end, and move on to the next.
    -		 */
    -		*RespVars = VarNew;
    -		RespVars = &(VarNew->next_variable);
    -	    }
    -	    return (Answer);
    -	} else if (PDU->command == SNMP_PDU_GETNEXT) {
    -	    oid *NextOidName = NULL;
    -	    int NextOidNameLen = 0;
    -
    -	    ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length,
    -		&(NextOidName), (snint *) & NextOidNameLen);
    -
    -	    if (ParseFn == NULL) {
    -		Answer->errstat = SNMP_ERR_NOSUCHNAME;
    -		debug(49, 5) ("snmpAgentResponse: No such oid: ");
    -		snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length);
    -	    } else {
    -		xfree(PDU->variables->name);
    -		PDU->variables->name = NextOidName;
    -		PDU->variables->name_length = NextOidNameLen;
    -		VarNew = (*ParseFn) (PDU->variables, (snint *) & Answer->errstat);
    -	    }
    -
    -	    /* Was there an error? */
    -	    if (Answer->errstat != SNMP_ERR_NOERROR) {
    -		Answer->errindex = 1;
    -		Answer->variables = PDU->variables;
    -		PDU->variables = NULL;
    -	    } else {
    -		Answer->variables = VarNew;
    -	    }
    -
    -	} else {
    -	    snmp_free_pdu(Answer);
    -	    Answer = NULL;
    -	}
    +    if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE)))
    +    {
    +        Answer->reqid = PDU->reqid;
    +        Answer->errindex = 0;
    +
    +        if (PDU->command == SNMP_PDU_GET) {
    +            variable_list **RespVars;
    +
    +            RespVars = &(Answer->variables);
    +            /* Loop through all variables */
    +
    +            for (VarPtrP = &(PDU->variables);
    +                    *VarPtrP;
    +                    VarPtrP = &((*VarPtrP)->next_variable)) {
    +                VarPtr = *VarPtrP;
    +
    +                index++;
    +
    +                /* Find the parsing function for this variable */
    +                ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
    +
    +                if (ParseFn == NULL) {
    +                    Answer->errstat = SNMP_ERR_NOSUCHNAME;
    +                    debug(49, 5) ("snmpAgentResponse: No such oid. ");
    +                } else
    +                    VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
    +
    +                /* Was there an error? */
    +                if ((Answer->errstat != SNMP_ERR_NOERROR) ||
    +                        (VarNew == NULL)) {
    +                    Answer->errindex = index;
    +                    debug(49, 5) ("snmpAgentParse: successful.\n");
    +                    /* Just copy the rest of the variables.  Quickly. */
    +                    *RespVars = VarPtr;
    +                    *VarPtrP = NULL;
    +                    return (Answer);
    +                }
    +
    +                /* No error.  Insert this var at the end, and move on to the next.
    +                 */
    +                *RespVars = VarNew;
    +
    +                RespVars = &(VarNew->next_variable);
    +            }
    +
    +            return (Answer);
    +        } else if (PDU->command == SNMP_PDU_GETNEXT) {
    +            oid *NextOidName = NULL;
    +            int NextOidNameLen = 0;
    +
    +            ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length,
    +                                   &(NextOidName), (snint *) & NextOidNameLen);
    +
    +            if (ParseFn == NULL) {
    +                Answer->errstat = SNMP_ERR_NOSUCHNAME;
    +                debug(49, 5) ("snmpAgentResponse: No such oid: ");
    +                snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length);
    +            } else {
    +                xfree(PDU->variables->name);
    +                PDU->variables->name = NextOidName;
    +                PDU->variables->name_length = NextOidNameLen;
    +                VarNew = (*ParseFn) (PDU->variables, (snint *) & Answer->errstat);
    +            }
    +
    +            /* Was there an error? */
    +            if (Answer->errstat != SNMP_ERR_NOERROR) {
    +                Answer->errindex = 1;
    +                Answer->variables = PDU->variables;
    +                PDU->variables = NULL;
    +            } else {
    +                Answer->variables = VarNew;
    +            }
    +
    +        } else {
    +            snmp_free_pdu(Answer);
    +            Answer = NULL;
    +        }
         }
    +
         return (Answer);
     }
     
    @@ -652,16 +697,21 @@ snmpTreeGet(oid * Current, snint CurrentLen)
         snmpDebugOid(6, Current, CurrentLen);
     
         mibTreeEntry = mib_tree_head;
    +
         if (Current[count] == mibTreeEntry->name[count]) {
    -	count++;
    -	while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
    -	    mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
    -	    count++;
    -	}
    +        count++;
    +
    +        while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
    +            mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
    +            count++;
    +        }
         }
    +
         if (mibTreeEntry && mibTreeEntry->parsefunction)
    -	Fn = mibTreeEntry->parsefunction;
    +        Fn = mibTreeEntry->parsefunction;
    +
         debug(49, 5) ("snmpTreeGet: return\n");
    +
         return (Fn);
     }
     
    @@ -678,60 +728,74 @@ snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
         snmpDebugOid(6, Current, CurrentLen);
     
         mibTreeEntry = mib_tree_head;
    +
         if (Current[count] == mibTreeEntry->name[count]) {
    -	count++;
    -	while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
    -	    mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
    -	    count++;
    -	}
    -	debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n");
    +        count++;
    +
    +        while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
    +            mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
    +            count++;
    +        }
    +
    +        debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n");
         } else {
    -	return NULL;
    +        return NULL;
         }
    +
         if (mibTreeEntry == mib_tree_last)
    -	return (Fn);
    +        return (Fn);
    +
         if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
    -	*NextLen = CurrentLen;
    -	*Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
    -	if (*Next)
    -	    return (Fn);
    +        *NextLen = CurrentLen;
    +        *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
    +
    +        if (*Next)
    +            return (Fn);
         }
    +
         if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
    -	count--;
    -	nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
    -	if (nextoid) {
    -	    debug(49, 5) ("snmpTreeNext: Next OID found for sibling\n");
    -	    mibTreeEntry = nextoid;
    -	    count++;
    -	} else {
    -	    debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n");
    -	    while (!nextoid) {
    -		count--;
    -		if (mibTreeEntry->parent->parent) {
    -		    nextoid = mibTreeEntry->parent;
    -		    mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
    -		    if (!mibTreeEntry) {
    -			mibTreeEntry = nextoid;
    -			nextoid = NULL;
    -		    }
    -		} else {
    -		    nextoid = mibTreeEntry;
    -		    mibTreeEntry = NULL;
    -		}
    -	    }
    -	}
    +        count--;
    +        nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
    +
    +        if (nextoid) {
    +            debug(49, 5) ("snmpTreeNext: Next OID found for sibling\n");
    +            mibTreeEntry = nextoid;
    +            count++;
    +        } else {
    +            debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n");
    +
    +            while (!nextoid) {
    +                count--;
    +
    +                if (mibTreeEntry->parent->parent) {
    +                    nextoid = mibTreeEntry->parent;
    +                    mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
    +
    +                    if (!mibTreeEntry) {
    +                        mibTreeEntry = nextoid;
    +                        nextoid = NULL;
    +                    }
    +                } else {
    +                    nextoid = mibTreeEntry;
    +                    mibTreeEntry = NULL;
    +                }
    +            }
    +        }
         }
    +
         while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
    -	mibTreeEntry = mibTreeEntry->leaves[0];
    +        mibTreeEntry = mibTreeEntry->leaves[0];
         }
    +
         if (mibTreeEntry) {
    -	*NextLen = mibTreeEntry->len;
    -	*Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
    +        *NextLen = mibTreeEntry->len;
    +        *Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
         }
    +
         if (*Next)
    -	return (Fn);
    +        return (Fn);
         else
    -	return NULL;
    +        return NULL;
     }
     
     static oid *
    @@ -740,11 +804,12 @@ static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn
         oid *instance = NULL;
     
         if (*len <= current->len) {
    -	instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
    -	xmemcpy(instance, name, (sizeof(name) * *len));
    -	instance[*len] = 0;
    -	*len += 1;
    +        instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
    +        xmemcpy(instance, name, (sizeof(name) * *len));
    +        instance[*len] = 0;
    +        *len += 1;
         }
    +
         *Fn = current->parsefunction;
         return (instance);
     }
    @@ -755,23 +820,26 @@ time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
         oid *instance = NULL;
         int identifier = 0, loop = 0;
         int index[TIME_INDEX_LEN] =
    -    {TIME_INDEX};
    +        {TIME_INDEX};
     
         if (*len <= current->len) {
    -	instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
    -	xmemcpy(instance, name, (sizeof(name) * *len));
    -	instance[*len] = *index;
    -	*len += 1;
    +        instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
    +        xmemcpy(instance, name, (sizeof(name) * *len));
    +        instance[*len] = *index;
    +        *len += 1;
         } else {
    -	identifier = name[*len - 1];
    -	while ((identifier != index[loop]) && (loop < TIME_INDEX_LEN))
    -	    loop++;
    -	if (loop < TIME_INDEX_LEN - 1) {
    -	    instance = (oid *)xmalloc(sizeof(name) * (*len));
    -	    xmemcpy(instance, name, (sizeof(name) * *len));
    -	    instance[*len - 1] = index[++loop];
    -	}
    +        identifier = name[*len - 1];
    +
    +        while ((identifier != index[loop]) && (loop < TIME_INDEX_LEN))
    +            loop++;
    +
    +        if (loop < TIME_INDEX_LEN - 1) {
    +            instance = (oid *)xmalloc(sizeof(name) * (*len));
    +            xmemcpy(instance, name, (sizeof(name) * *len));
    +            instance[*len - 1] = index[++loop];
    +        }
         }
    +
         *Fn = current->parsefunction;
         return (instance);
     }
    @@ -782,55 +850,62 @@ peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
         oid *instance = NULL;
         u_char *cp = NULL;
         peer *peers = Config.peers;
    +
         struct in_addr *laddr = NULL;
         char *host_addr = NULL, *current_addr = NULL, *last_addr = NULL;
     
         if (peers == NULL) {
    -	current = current->parent->parent->parent->leaves[1];
    -	while ((current) && (!current->parsefunction))
    -	    current = current->leaves[0];
    -	instance = client_Inst(current->name, len, current, Fn);
    +        current = current->parent->parent->parent->leaves[1];
    +
    +        while ((current) && (!current->parsefunction))
    +            current = current->leaves[0];
    +
    +        instance = client_Inst(current->name, len, current, Fn);
         } else if (*len <= current->len) {
    -	instance = (oid *)xmalloc(sizeof(name) * (*len + 4));
    -	xmemcpy(instance, name, (sizeof(name) * *len));
    -	cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
    -	instance[*len] = *cp++;
    -	instance[*len + 1] = *cp++;
    -	instance[*len + 2] = *cp++;
    -	instance[*len + 3] = *cp++;
    -	*len += 4;
    +        instance = (oid *)xmalloc(sizeof(name) * (*len + 4));
    +        xmemcpy(instance, name, (sizeof(name) * *len));
    +        cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
    +        instance[*len] = *cp++;
    +        instance[*len + 1] = *cp++;
    +        instance[*len + 2] = *cp++;
    +        instance[*len + 3] = *cp++;
    +        *len += 4;
         } else {
    -	laddr = oid2addr(&name[*len - 4]);
    -	host_addr = inet_ntoa(*laddr);
    -	last_addr = (char *)xmalloc(strlen(host_addr));
    -	strncpy(last_addr, host_addr, strlen(host_addr));
    -	current_addr = inet_ntoa(peers->in_addr.sin_addr);
    -	while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) {
    -	    if (peers->next) {
    -		peers = peers->next;
    -		current_addr = inet_ntoa(peers->in_addr.sin_addr);
    -	    } else {
    -		peers = NULL;
    -	    }
    -	}
    -	xfree(last_addr);
    -	if (peers) {
    -	    if (peers->next) {
    -		peers = peers->next;
    -		instance = (oid *)xmalloc(sizeof(name) * (*len));
    -		xmemcpy(instance, name, (sizeof(name) * *len));
    -		cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
    -		instance[*len - 4] = *cp++;
    -		instance[*len - 3] = *cp++;
    -		instance[*len - 2] = *cp++;
    -		instance[*len - 1] = *cp++;
    -	    } else {
    -		return (instance);
    -	    }
    -	} else {
    -	    return (instance);
    -	}
    +        laddr = oid2addr(&name[*len - 4]);
    +        host_addr = inet_ntoa(*laddr);
    +        last_addr = (char *)xmalloc(strlen(host_addr));
    +        strncpy(last_addr, host_addr, strlen(host_addr));
    +        current_addr = inet_ntoa(peers->in_addr.sin_addr);
    +
    +        while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) {
    +            if (peers->next) {
    +                peers = peers->next;
    +                current_addr = inet_ntoa(peers->in_addr.sin_addr);
    +            } else {
    +                peers = NULL;
    +            }
    +        }
    +
    +        xfree(last_addr);
    +
    +        if (peers) {
    +            if (peers->next) {
    +                peers = peers->next;
    +                instance = (oid *)xmalloc(sizeof(name) * (*len));
    +                xmemcpy(instance, name, (sizeof(name) * *len));
    +                cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
    +                instance[*len - 4] = *cp++;
    +                instance[*len - 3] = *cp++;
    +                instance[*len - 2] = *cp++;
    +                instance[*len - 1] = *cp++;
    +            } else {
    +                return (instance);
    +            }
    +        } else {
    +            return (instance);
    +        }
         }
    +
         *Fn = current->parsefunction;
         return (instance);
     }
    @@ -840,33 +915,37 @@ client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn
     {
         oid *instance = NULL;
         u_char *cp = NULL;
    +
         struct in_addr *laddr = NULL;
     
         if (*len <= current->len) {
    -	instance = (oid *)xmalloc(sizeof(name) * (*len + 4));
    -	xmemcpy(instance, name, (sizeof(name) * *len));
    -	laddr = client_entry(NULL);
    -	if (laddr) {
    -	    cp = (u_char *) & (laddr->s_addr);
    -	    instance[*len] = *cp++;
    -	    instance[*len + 1] = *cp++;
    -	    instance[*len + 2] = *cp++;
    -	    instance[*len + 3] = *cp++;
    -	    *len += 4;
    -	}
    +        instance = (oid *)xmalloc(sizeof(name) * (*len + 4));
    +        xmemcpy(instance, name, (sizeof(name) * *len));
    +        laddr = client_entry(NULL);
    +
    +        if (laddr) {
    +            cp = (u_char *) & (laddr->s_addr);
    +            instance[*len] = *cp++;
    +            instance[*len + 1] = *cp++;
    +            instance[*len + 2] = *cp++;
    +            instance[*len + 3] = *cp++;
    +            *len += 4;
    +        }
         } else {
    -	laddr = oid2addr(&name[*len - 4]);
    -	laddr = client_entry(laddr);
    -	if (laddr) {
    -	    instance = (oid *)xmalloc(sizeof(name) * (*len));
    -	    xmemcpy(instance, name, (sizeof(name) * *len));
    -	    cp = (u_char *) & (laddr->s_addr);
    -	    instance[*len - 4] = *cp++;
    -	    instance[*len - 3] = *cp++;
    -	    instance[*len - 2] = *cp++;
    -	    instance[*len - 1] = *cp++;
    -	}
    +        laddr = oid2addr(&name[*len - 4]);
    +        laddr = client_entry(laddr);
    +
    +        if (laddr) {
    +            instance = (oid *)xmalloc(sizeof(name) * (*len));
    +            xmemcpy(instance, name, (sizeof(name) * *len));
    +            cp = (u_char *) & (laddr->s_addr);
    +            instance[*len - 4] = *cp++;
    +            instance[*len - 3] = *cp++;
    +            instance[*len - 2] = *cp++;
    +            instance[*len - 1] = *cp++;
    +        }
         }
    +
         *Fn = current->parsefunction;
         return (instance);
     }
    @@ -880,7 +959,7 @@ client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn
      * Tree utility functions. 
      */
     
    -/* 
    +/*
      * Returns a the sibling object in the tree
      */
     static mib_tree_entry *
    @@ -890,20 +969,23 @@ snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current)
         int count = 0;
     
         while ((!next) && (count < current->children)) {
    -	if (current->leaves[count]->name[len] == entry) {
    -	    next = current->leaves[count];
    -	}
    -	count++;
    +        if (current->leaves[count]->name[len] == entry) {
    +            next = current->leaves[count];
    +        }
    +
    +        count++;
         }
    +
         if (count < current->children) {
    -	next = current->leaves[count];
    +        next = current->leaves[count];
         } else {
    -	next = NULL;
    +        next = NULL;
         }
    +
         return (next);
     }
     
    -/* 
    +/*
      * Returns the requested child object or NULL if it does not exist
      */
     static mib_tree_entry *
    @@ -913,11 +995,13 @@ snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
         int count = 0;
     
         while ((!next) && (count < current->children)) {
    -	if (current->leaves[count]->name[len] == entry) {
    -	    next = current->leaves[count];
    -	}
    -	count++;
    +        if (current->leaves[count]->name[len] == entry) {
    +            next = current->leaves[count];
    +        }
    +
    +        count++;
         }
    +
         return (next);
     }
     
    @@ -929,7 +1013,7 @@ static mib_tree_entry *
     snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...)
     #else
     snmpAddNode(va_alist)
    -     va_dcl
    +va_dcl
     #endif
     {
     #if STDC_HEADERS
    @@ -938,6 +1022,7 @@ snmpAddNode(va_alist)
         mib_tree_entry *entry = NULL;
         va_start(args, children);
     #else
    +
         va_list args;
         oid *name = NULL;
         int len = 0, children = 0, loop;
    @@ -963,18 +1048,21 @@ snmpAddNode(va_alist)
         entry->instancefunction = instancefunction;
         entry->children = children;
     
    -    if (children > 0) {
    -	entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
    -	for (loop = 0; loop < children; loop++) {
    -	    entry->leaves[loop] = va_arg(args, mib_tree_entry *);
    -	    entry->leaves[loop]->parent = entry;
    -	}
    +    if (children > 0)
    +    {
    +        entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
    +
    +        for (loop = 0; loop < children; loop++) {
    +            entry->leaves[loop] = va_arg(args, mib_tree_entry *);
    +            entry->leaves[loop]->parent = entry;
    +        }
         }
    +
         return (entry);
     }
     /* End of tree utility functions */
     
    -/* 
    +/*
      * Returns the list of parameters in an oid
      */
     static oid *
    @@ -982,7 +1070,7 @@ static oid *
     snmpCreateOid(int length,...)
     #else
     snmpCreateOid(va_alist)
    -     va_dcl
    +va_dcl
     #endif
     {
     #if STDC_HEADERS
    @@ -991,6 +1079,7 @@ snmpCreateOid(va_alist)
         int loop;
         va_start(args, length);
     #else
    +
         va_list args;
         int length = 0, loop;
         oid *new_oid;
    @@ -1000,11 +1089,13 @@ snmpCreateOid(va_alist)
     
         new_oid = (oid *)xmalloc(sizeof(oid) * length);
     
    -    if (length > 0) {
    -	for (loop = 0; loop < length; loop++) {
    -	    new_oid[loop] = va_arg(args, int);
    -	}
    +    if (length > 0)
    +    {
    +        for (loop = 0; loop < length; loop++) {
    +            new_oid[loop] = va_arg(args, int);
    +        }
         }
    +
         return (new_oid);
     }
     
    @@ -1019,6 +1110,7 @@ snmpOidDup(oid * A, snint ALen)
         xmemcpy(Ans, A, (sizeof(oid) * ALen));
         return Ans;
     }
    +
     #endif
     
     /*
    @@ -1032,8 +1124,8 @@ snmpDebugOid(int lvl, oid * Name, snint Len)
         objid[0] = '\0';
     
         for (x = 0; x < Len; x++) {
    -	snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
    -	strncat(objid, mbuf, sizeof(objid));
    +        snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
    +        strncat(objid, mbuf, sizeof(objid));
         }
     
         debug(49, lvl) ("   oid = %s\n", objid);
    @@ -1046,6 +1138,7 @@ snmpSnmplibDebug(int lvl, char *buf)
     }
     
     void
    +
     addr2oid(struct in_addr addr, oid * Dest)
     {
         u_char *cp;
    @@ -1057,9 +1150,10 @@ addr2oid(struct in_addr addr, oid * Dest)
     }
     
     struct in_addr
    -       *
    -oid2addr(oid * id)
    +            *
    +            oid2addr(oid * id)
     {
    +
         static struct in_addr laddr;
         u_char *cp = (u_char *) & (laddr.s_addr);
         cp[0] = id[0];
    diff --git a/src/squid.h b/src/squid.h
    index 75db3a3d1e..d0e2e7c923 100644
    --- a/src/squid.h
    +++ b/src/squid.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: squid.h,v 1.229 2003/01/23 00:37:25 robertc Exp $
    + * $Id: squid.h,v 1.230 2003/02/21 22:50:10 robertc Exp $
      *
      * AUTHOR: Duane Wessels
      *
    @@ -248,8 +248,12 @@
      * source code cleaner, so we don't need lots of #ifdefs in other
      * places
      */
    -struct rusage {
    +
    +struct rusage
    +{
    +
         struct timeval ru_stime;
    +
         struct timeval ru_utime;
         int ru_maxrss;
         int ru_majflt;
    @@ -306,11 +310,13 @@ struct rusage {
     
     #ifdef USE_GNUREGEX
     #ifdef __cplusplus
    -extern "C" {
    +extern "C"
    +{
     #endif
     #include "GNUregex.h"
     #ifdef __cplusplus
     }
    +
     #endif
     #elif HAVE_REGEX_H
     #include 
    @@ -396,15 +402,15 @@ extern "C" {
     #define SQUID_NONBLOCK O_NDELAY
     #elif defined(O_NONBLOCK)
     /*
    - * We used to assume O_NONBLOCK was broken on Solaris, but evidence
    - * now indicates that its fine on Solaris 8, and in fact required for
    - * properly detecting EOF on FIFOs.  So now we assume that if 
    - * its defined, it works correctly on all operating systems.
    - */
    +* We used to assume O_NONBLOCK was broken on Solaris, but evidence
    +* now indicates that its fine on Solaris 8, and in fact required for
    +* properly detecting EOF on FIFOs.  So now we assume that if
    +* its defined, it works correctly on all operating systems.
    +*/
     #define SQUID_NONBLOCK O_NONBLOCK
     /*
    - * O_NDELAY is our fallback.
    - */
    +* O_NDELAY is our fallback.
    +*/
     #else
     #define SQUID_NONBLOCK O_NDELAY
     #endif
    diff --git a/src/ssl_support.cc b/src/ssl_support.cc
    index 4bf2594a01..66751787c0 100644
    --- a/src/ssl_support.cc
    +++ b/src/ssl_support.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: ssl_support.cc,v 1.11 2003/02/08 14:55:07 hno Exp $
    + * $Id: ssl_support.cc,v 1.12 2003/02/21 22:50:11 robertc Exp $
      *
      * AUTHOR: Benno Rice
      * DEBUG: section 83    SSL accelerator support
    @@ -48,7 +48,8 @@ ssl_temp_rsa_cb(SSL * ssl, int anInt, int keylen)
         static RSA *rsa = NULL;
     
         if (rsa == NULL)
    -	rsa = RSA_generate_key(512, RSA_F4, NULL, NULL);
    +        rsa = RSA_generate_key(512, RSA_F4, NULL, NULL);
    +
         return rsa;
     }
     
    @@ -63,185 +64,203 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
         X509 *peer_cert = ctx->cert;
     
         X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
    -	sizeof(buffer));
    +                      sizeof(buffer));
     
         if (ok) {
    -	debug(83, 5) ("SSL Certificate signature OK: %s\n", buffer);
    -	if (server) {
    -	    int i;
    -	    int found = 0;
    -	    char cn[1024];
    -	    X509_NAME *name = X509_get_subject_name(peer_cert);
    -	    debug(83, 3) ("Verifying server domain %s to certificate dn %s\n",
    -		server, buffer);
    -	    for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
    -		ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
    -		if (data->length > (int)sizeof(cn) - 1)
    -		    continue;
    -		memcpy(cn, data->data, data->length);
    -		cn[data->length] = '\0';
    -		debug(83, 4) ("Verifying server domain %s to certificate cn %s\n",
    -		    server, cn);
    -		if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
    -		    found = 1;
    -		    break;
    -		}
    -	    }
    -	    if (!found) {
    -		debug(83, 2) ("ERROR: Certificate %s does not match domainname %s\n", buffer, server);
    -		ok = 0;
    -	    }
    -	}
    +        debug(83, 5) ("SSL Certificate signature OK: %s\n", buffer);
    +
    +        if (server) {
    +            int i;
    +            int found = 0;
    +            char cn[1024];
    +            X509_NAME *name = X509_get_subject_name(peer_cert);
    +            debug(83, 3) ("Verifying server domain %s to certificate dn %s\n",
    +                          server, buffer);
    +
    +            for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
    +                ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
    +
    +                if (data->length > (int)sizeof(cn) - 1)
    +                    continue;
    +
    +                memcpy(cn, data->data, data->length);
    +
    +                cn[data->length] = '\0';
    +
    +                debug(83, 4) ("Verifying server domain %s to certificate cn %s\n",
    +                              server, cn);
    +
    +                if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
    +                    found = 1;
    +                    break;
    +                }
    +            }
    +
    +            if (!found) {
    +                debug(83, 2) ("ERROR: Certificate %s does not match domainname %s\n", buffer, server);
    +                ok = 0;
    +            }
    +        }
         } else {
    -	switch (ctx->error) {
    -	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
    -	    debug(83, 5) ("SSL Certficate error: CA not known: %s\n", buffer);
    -	    break;
    -	case X509_V_ERR_CERT_NOT_YET_VALID:
    -	    debug(83, 5) ("SSL Certficate not yet valid: %s\n", buffer);
    -	    break;
    -	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
    -	    debug(83, 5) ("SSL Certificate has illegal \'not before\' field: %s\n", buffer);
    -	    break;
    -	case X509_V_ERR_CERT_HAS_EXPIRED:
    -	    debug(83, 5) ("SSL Certificate expired: %s\n", buffer);
    -	    break;
    -	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
    -	    debug(83, 5) ("SSL Certificate has invalid \'not after\' field: %s\n", buffer);
    -	    break;
    -	default:
    -	    debug(83, 1) ("SSL unknown certificate error %d in %s\n",
    -		ctx->error, buffer);
    -	    break;
    -	}
    -    }
    -    if (!dont_verify_domain && server) {
    +        switch (ctx->error) {
    +
    +        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
    +            debug(83, 5) ("SSL Certficate error: CA not known: %s\n", buffer);
    +            break;
    +
    +        case X509_V_ERR_CERT_NOT_YET_VALID:
    +            debug(83, 5) ("SSL Certficate not yet valid: %s\n", buffer);
    +            break;
    +
    +        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
    +            debug(83, 5) ("SSL Certificate has illegal \'not before\' field: %s\n", buffer);
    +            break;
    +
    +        case X509_V_ERR_CERT_HAS_EXPIRED:
    +            debug(83, 5) ("SSL Certificate expired: %s\n", buffer);
    +            break;
    +
    +        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
    +            debug(83, 5) ("SSL Certificate has invalid \'not after\' field: %s\n", buffer);
    +            break;
    +
    +        default:
    +            debug(83, 1) ("SSL unknown certificate error %d in %s\n",
    +                          ctx->error, buffer);
    +            break;
    +        }
         }
    +
    +if (!dont_verify_domain && server) {}
    +
         return ok;
     }
     
    -static struct ssl_option {
    +static struct ssl_option
    +{
         const char *name;
         long value;
    -} ssl_options[] = {
    +}
    +
    +ssl_options[] = {
     
     #ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
    -    {
    -	"MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG
    -    },
    +                    {
    +                        "MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG
    +                    },
     #endif
     #ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
    -    {
    -	"NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG
    -    },
    +                    {
    +                        "NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG
    +                    },
     #endif
     #ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
    -    {
    -	"NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
    -    },
    +                    {
    +                        "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
    +                    },
     #endif
     #ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
    -    {
    -	"SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
    -    },
    +                    {
    +                        "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
    +                    },
     #endif
     #ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
    -    {
    -	"MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
    -    },
    +                    {
    +                        "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
    +                    },
     #endif
     #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
    -    {
    -	"MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING
    -    },
    +                    {
    +                        "MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING
    +                    },
     #endif
     #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
    -    {
    -	"SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
    -    },
    +                    {
    +                        "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
    +                    },
     #endif
     #ifdef SSL_OP_TLS_D5_BUG
    -    {
    -	"TLS_D5_BUG", SSL_OP_TLS_D5_BUG
    -    },
    +                    {
    +                        "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
    +                    },
     #endif
     #ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
    -    {
    -	"TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
    -    },
    +                    {
    +                        "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
    +                    },
     #endif
     #ifdef SSL_OP_TLS_ROLLBACK_BUG
    -    {
    -	"TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
    -    },
    +                    {
    +                        "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
    +                    },
     #endif
     #ifdef SSL_OP_ALL
    -    {
    -	"ALL", SSL_OP_ALL
    -    },
    +                    {
    +                        "ALL", SSL_OP_ALL
    +                    },
     #endif
     #ifdef SSL_OP_SINGLE_DH_USE
    -    {
    -	"SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
    -    },
    +                    {
    +                        "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
    +                    },
     #endif
     #ifdef SSL_OP_EPHEMERAL_RSA
    -    {
    -	"EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
    -    },
    +                    {
    +                        "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
    +                    },
     #endif
     #ifdef SSL_OP_PKCS1_CHECK_1
    -    {
    -	"PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
    -    },
    +                    {
    +                        "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
    +                    },
     #endif
     #ifdef SSL_OP_PKCS1_CHECK_2
    -    {
    -	"PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
    -    },
    +                    {
    +                        "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
    +                    },
     #endif
     #ifdef SSL_OP_NETSCAPE_CA_DN_BUG
    -    {
    -	"NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
    -    },
    +                    {
    +                        "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
    +                    },
     #endif
     #ifdef SSL_OP_NON_EXPORT_FIRST
    -    {
    -	"NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
    -    },
    +                    {
    +                        "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
    +                    },
     #endif
     #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    -    {
    -	"CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
    -    },
    +                    {
    +                        "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
    +                    },
     #endif
     #ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
    -    {
    -	"NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
    -    },
    +                    {
    +                        "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
    +                    },
     #endif
     #ifdef SSL_OP_NO_SSLv2
    -    {
    -	"NO_SSLv2", SSL_OP_NO_SSLv2
    -    },
    +                    {
    +                        "NO_SSLv2", SSL_OP_NO_SSLv2
    +                    },
     #endif
     #ifdef SSL_OP_NO_SSLv3
    -    {
    -	"NO_SSLv3", SSL_OP_NO_SSLv3
    -    },
    +                    {
    +                        "NO_SSLv3", SSL_OP_NO_SSLv3
    +                    },
     #endif
     #ifdef SSL_OP_NO_TLSv1
    -    {
    -	"NO_TLSv1", SSL_OP_NO_TLSv1
    -    },
    +                    {
    +                        "NO_TLSv1", SSL_OP_NO_TLSv1
    +                    },
     #endif
    -    {
    -	"", 0
    -    },
    -    {
    -	NULL, 0
    -    }
    -};
    +                    {
    +                        "", 0
    +                    },
    +                    {
    +                        NULL, 0
    +                    }
    +                };
     
     static long
     ssl_parse_options(const char *options)
    @@ -251,58 +270,73 @@ ssl_parse_options(const char *options)
         char *option;
     
         if (!options)
    -	goto no_options;
    +        goto no_options;
     
         tmp = xstrdup(options);
    +
         option = strtok(tmp, ":,");
    +
         while (option) {
    -	struct ssl_option *opt = NULL, *opttmp;
    -	long value = 0;
    -	enum {
    -	    MODE_ADD, MODE_REMOVE
    -	} mode;
    -	switch (*option) {
    -	case '!':
    -	case '-':
    -	    mode = MODE_REMOVE;
    -	    option++;
    -	    break;
    -	case '+':
    -	    mode = MODE_ADD;
    -	    option++;
    -	    break;
    -	default:
    -	    mode = MODE_ADD;
    -	    break;
    -	}
    -	for (opttmp = ssl_options; opttmp->name; opttmp++) {
    -	    if (strcmp(opttmp->name, option) == 0) {
    -		opt = opttmp;
    -		break;
    -	    }
    -	}
    -	if (opt)
    -	    value = opt->value;
    -	else if (strncmp(option, "0x", 2) == 0) {
    -	    /* Special case.. hex specification */
    -	    value = strtol(option + 2, NULL, 16);
    -	} else {
    -	    fatalf("Unknown SSL option '%s'", option);
    -	    value = 0;		/* Keep GCC happy */
    -	}
    -	switch (mode) {
    -	case MODE_ADD:
    -	    op |= value;
    -	    break;
    -	case MODE_REMOVE:
    -	    op &= ~value;
    -	    break;
    -	}
    -	option = strtok(NULL, ":,");
    +
    +        struct ssl_option *opt = NULL, *opttmp;
    +        long value = 0;
    +        enum {
    +            MODE_ADD, MODE_REMOVE
    +        } mode;
    +
    +        switch (*option) {
    +
    +        case '!':
    +
    +        case '-':
    +            mode = MODE_REMOVE;
    +            option++;
    +            break;
    +
    +        case '+':
    +            mode = MODE_ADD;
    +            option++;
    +            break;
    +
    +        default:
    +            mode = MODE_ADD;
    +            break;
    +        }
    +
    +        for (opttmp = ssl_options; opttmp->name; opttmp++) {
    +            if (strcmp(opttmp->name, option) == 0) {
    +                opt = opttmp;
    +                break;
    +            }
    +        }
    +
    +        if (opt)
    +            value = opt->value;
    +        else if (strncmp(option, "0x", 2) == 0) {
    +            /* Special case.. hex specification */
    +            value = strtol(option + 2, NULL, 16);
    +        } else {
    +            fatalf("Unknown SSL option '%s'", option);
    +            value = 0;		/* Keep GCC happy */
    +        }
    +
    +        switch (mode) {
    +
    +        case MODE_ADD:
    +            op |= value;
    +            break;
    +
    +        case MODE_REMOVE:
    +            op &= ~value;
    +            break;
    +        }
    +
    +        option = strtok(NULL, ":,");
         }
     
         safe_free(tmp);
    -  no_options:
    +
    +no_options:
         return op;
     }
     
    @@ -319,23 +353,27 @@ ssl_parse_flags(const char *flags)
         char *flag;
     
         if (!flags)
    -	return 0;
    +        return 0;
     
         tmp = xstrdup(flags);
    +
         flag = strtok(tmp, ":,");
    +
         while (flag) {
    -	if (strcmp(flag, "NO_DEFAULT_CA") == 0)
    -	    fl |= SSL_FLAG_NO_DEFAULT_CA;
    -	else if (strcmp(flag, "DELAYED_AUTH") == 0)
    -	    fl |= SSL_FLAG_DELAYED_AUTH;
    -	else if (strcmp(flag, "DONT_VERIFY_PEER") == 0)
    -	    fl |= SSL_FLAG_DONT_VERIFY_PEER;
    -	else if (strcmp(flag, "DONT_VERIFY_DOMAIN") == 0)
    -	    fl |= SSL_FLAG_DONT_VERIFY_DOMAIN;
    -	else
    -	    fatalf("Unknown ssl flag '%s'", flag);
    -	flag = strtok(NULL, ":,");
    +        if (strcmp(flag, "NO_DEFAULT_CA") == 0)
    +            fl |= SSL_FLAG_NO_DEFAULT_CA;
    +        else if (strcmp(flag, "DELAYED_AUTH") == 0)
    +            fl |= SSL_FLAG_DELAYED_AUTH;
    +        else if (strcmp(flag, "DONT_VERIFY_PEER") == 0)
    +            fl |= SSL_FLAG_DONT_VERIFY_PEER;
    +        else if (strcmp(flag, "DONT_VERIFY_DOMAIN") == 0)
    +            fl |= SSL_FLAG_DONT_VERIFY_DOMAIN;
    +        else
    +            fatalf("Unknown ssl flag '%s'", flag);
    +
    +        flag = strtok(NULL, ":,");
         }
    +
         safe_free(tmp);
         return fl;
     }
    @@ -345,28 +383,36 @@ static void
     ssl_initialize(void)
     {
         static int ssl_initialized = 0;
    +
         if (!ssl_initialized) {
    -	ssl_initialized = 1;
    -	SSL_load_error_strings();
    -	SSLeay_add_ssl_algorithms();
    +        ssl_initialized = 1;
    +        SSL_load_error_strings();
    +        SSLeay_add_ssl_algorithms();
     #ifdef HAVE_OPENSSL_ENGINE_H
    -	if (Config.SSL.ssl_engine) {
    -	    ENGINE *e;
    -	    if (!(e = ENGINE_by_id(Config.SSL.ssl_engine))) {
    -		fatalf("Unable to find SSL engine '%s'\n", Config.SSL.ssl_engine);
    -	    }
    -	    if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
    -		int ssl_error = ERR_get_error();
    -		fatalf("Failed to initialise SSL engine: %s\n",
    -		    ERR_error_string(ssl_error, NULL));
    -	    }
    -	}
    +
    +        if (Config.SSL.ssl_engine) {
    +            ENGINE *e;
    +
    +            if (!(e = ENGINE_by_id(Config.SSL.ssl_engine))) {
    +                fatalf("Unable to find SSL engine '%s'\n", Config.SSL.ssl_engine);
    +            }
    +
    +            if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
    +                int ssl_error = ERR_get_error();
    +                fatalf("Failed to initialise SSL engine: %s\n",
    +                       ERR_error_string(ssl_error, NULL));
    +            }
    +        }
    +
     #else
    -	if (Config.SSL.ssl_engine) {
    -	    fatalf("Your OpenSSL has no SSL engine support\n");
    -	}
    +        if (Config.SSL.ssl_engine) {
    +            fatalf("Your OpenSSL has no SSL engine support\n");
    +        }
    +
     #endif
    +
         }
    +
         ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
         ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
     
    @@ -383,107 +429,132 @@ sslCreateServerContext(const char *certfile, const char *keyfile, int version, c
         ssl_initialize();
     
         if (!keyfile)
    -	keyfile = certfile;
    +        keyfile = certfile;
    +
         if (!certfile)
    -	certfile = keyfile;
    +        certfile = keyfile;
    +
         if (!CAfile)
    -	CAfile = clientCA;
    +        CAfile = clientCA;
     
         debug(83, 1) ("Initialising SSL.\n");
    +
         switch (version) {
    +
         case 2:
    -	debug(83, 5) ("Using SSLv2.\n");
    -	method = SSLv2_server_method();
    -	break;
    +        debug(83, 5) ("Using SSLv2.\n");
    +        method = SSLv2_server_method();
    +        break;
    +
         case 3:
    -	debug(83, 5) ("Using SSLv3.\n");
    -	method = SSLv3_server_method();
    -	break;
    +        debug(83, 5) ("Using SSLv3.\n");
    +        method = SSLv3_server_method();
    +        break;
    +
         case 4:
    -	debug(83, 5) ("Using TLSv1.\n");
    -	method = TLSv1_server_method();
    -	break;
    +        debug(83, 5) ("Using TLSv1.\n");
    +        method = TLSv1_server_method();
    +        break;
    +
         case 1:
    +
         default:
    -	debug(83, 5) ("Using SSLv2/SSLv3.\n");
    -	method = SSLv23_server_method();
    -	break;
    +        debug(83, 5) ("Using SSLv2/SSLv3.\n");
    +        method = SSLv23_server_method();
    +        break;
         }
     
         sslContext = SSL_CTX_new(method);
    +
         if (sslContext == NULL) {
    -	ssl_error = ERR_get_error();
    -	fatalf("Failed to allocate SSL context: %s\n",
    -	    ERR_error_string(ssl_error, NULL));
    +        ssl_error = ERR_get_error();
    +        fatalf("Failed to allocate SSL context: %s\n",
    +               ERR_error_string(ssl_error, NULL));
         }
    +
         SSL_CTX_set_options(sslContext, ssl_parse_options(options));
     
         if (cipher) {
    -	debug(83, 5) ("Using chiper suite %s.\n", cipher);
    -	if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
    -	    ssl_error = ERR_get_error();
    -	    fatalf("Failed to set SSL cipher suite '%s': %s\n",
    -		cipher, ERR_error_string(ssl_error, NULL));
    -	}
    +        debug(83, 5) ("Using chiper suite %s.\n", cipher);
    +
    +        if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
    +            ssl_error = ERR_get_error();
    +            fatalf("Failed to set SSL cipher suite '%s': %s\n",
    +                   cipher, ERR_error_string(ssl_error, NULL));
    +        }
         }
    +
         debug(83, 1) ("Using certificate in %s\n", certfile);
    +
         if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
    -	ssl_error = ERR_get_error();
    -	debug(83, 0) ("Failed to acquire SSL certificate '%s': %s\n",
    -	    certfile, ERR_error_string(ssl_error, NULL));
    -	goto error;
    +        ssl_error = ERR_get_error();
    +        debug(83, 0) ("Failed to acquire SSL certificate '%s': %s\n",
    +                      certfile, ERR_error_string(ssl_error, NULL));
    +        goto error;
         }
    +
         debug(83, 1) ("Using private key in %s\n", keyfile);
    +
         if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
    -	ssl_error = ERR_get_error();
    -	debug(83, 0) ("Failed to acquire SSL private key '%s': %s\n",
    -	    keyfile, ERR_error_string(ssl_error, NULL));
    -	goto error;
    +        ssl_error = ERR_get_error();
    +        debug(83, 0) ("Failed to acquire SSL private key '%s': %s\n",
    +                      keyfile, ERR_error_string(ssl_error, NULL));
    +        goto error;
         }
    +
         debug(83, 5) ("Comparing private and public SSL keys.\n");
    +
         if (!SSL_CTX_check_private_key(sslContext)) {
    -	ssl_error = ERR_get_error();
    -	debug(83, 0) ("SSL private key '%s' does not match public key '%s': %s\n",
    -	    certfile, keyfile, ERR_error_string(ssl_error, NULL));
    -	goto error;
    +        ssl_error = ERR_get_error();
    +        debug(83, 0) ("SSL private key '%s' does not match public key '%s': %s\n",
    +                      certfile, keyfile, ERR_error_string(ssl_error, NULL));
    +        goto error;
         }
    +
         debug(83, 9) ("Setting RSA key generation callback.\n");
         SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
     
         debug(83, 9) ("Setting CA certificate locations.\n");
    +
         if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
    -	ssl_error = ERR_get_error();
    -	debug(83, 1) ("Error error setting CA certificate locations: %s\n",
    -	    ERR_error_string(ssl_error, NULL));
    -	debug(83, 1) ("continuing anyway...\n");
    +        ssl_error = ERR_get_error();
    +        debug(83, 1) ("Error error setting CA certificate locations: %s\n",
    +                      ERR_error_string(ssl_error, NULL));
    +        debug(83, 1) ("continuing anyway...\n");
         }
    +
         if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
    -	!SSL_CTX_set_default_verify_paths(sslContext)) {
    -	ssl_error = ERR_get_error();
    -	debug(83, 1) ("Error error setting default CA certificate location: %s\n",
    -	    ERR_error_string(ssl_error, NULL));
    -	debug(83, 1) ("continuing anyway...\n");
    +            !SSL_CTX_set_default_verify_paths(sslContext)) {
    +        ssl_error = ERR_get_error();
    +        debug(83, 1) ("Error error setting default CA certificate location: %s\n",
    +                      ERR_error_string(ssl_error, NULL));
    +        debug(83, 1) ("continuing anyway...\n");
         }
    +
         if (clientCA) {
    -	debug(83, 9) ("Set client certifying authority list.\n");
    -	SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(clientCA));
    -	if (fl & SSL_FLAG_DELAYED_AUTH) {
    -	    debug(83, 9) ("Not requesting client certificates until acl processing requires one\n");
    -	    SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
    -	} else {
    -	    debug(83, 9) ("Requiring client certificates.\n");
    -	    SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
    -	}
    +        debug(83, 9) ("Set client certifying authority list.\n");
    +        SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(clientCA));
    +
    +        if (fl & SSL_FLAG_DELAYED_AUTH) {
    +            debug(83, 9) ("Not requesting client certificates until acl processing requires one\n");
    +            SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
    +        } else {
    +            debug(83, 9) ("Requiring client certificates.\n");
    +            SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
    +        }
         } else {
    -	debug(83, 9) ("Not requiring any client certificates\n");
    -	SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
    +        debug(83, 9) ("Not requiring any client certificates\n");
    +        SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
         }
     
         if (fl & SSL_FLAG_DONT_VERIFY_DOMAIN)
    -	SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
    +        SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
    +
         return sslContext;
    -  error:
    +
    +error:
         SSL_CTX_free(sslContext);
    +
         return NULL;
     }
     
    @@ -498,92 +569,112 @@ sslCreateClientContext(const char *certfile, const char *keyfile, int version, c
         ssl_initialize();
     
         if (!keyfile)
    -	keyfile = certfile;
    +        keyfile = certfile;
    +
         if (!certfile)
    -	certfile = keyfile;
    +        certfile = keyfile;
     
         debug(83, 1) ("Initialising SSL.\n");
    +
         switch (version) {
    +
         case 2:
    -	debug(83, 5) ("Using SSLv2.\n");
    -	method = SSLv2_client_method();
    -	break;
    +        debug(83, 5) ("Using SSLv2.\n");
    +        method = SSLv2_client_method();
    +        break;
    +
         case 3:
    -	debug(83, 5) ("Using SSLv3.\n");
    -	method = SSLv3_client_method();
    -	break;
    +        debug(83, 5) ("Using SSLv3.\n");
    +        method = SSLv3_client_method();
    +        break;
    +
         case 4:
    -	debug(83, 5) ("Using TLSv1.\n");
    -	method = TLSv1_client_method();
    -	break;
    +        debug(83, 5) ("Using TLSv1.\n");
    +        method = TLSv1_client_method();
    +        break;
    +
         case 1:
    +
         default:
    -	debug(83, 5) ("Using SSLv2/SSLv3.\n");
    -	method = SSLv23_client_method();
    -	break;
    +        debug(83, 5) ("Using SSLv2/SSLv3.\n");
    +        method = SSLv23_client_method();
    +        break;
         }
     
         sslContext = SSL_CTX_new(method);
    +
         if (sslContext == NULL) {
    -	ssl_error = ERR_get_error();
    -	fatalf("Failed to allocate SSL context: %s\n",
    -	    ERR_error_string(ssl_error, NULL));
    +        ssl_error = ERR_get_error();
    +        fatalf("Failed to allocate SSL context: %s\n",
    +               ERR_error_string(ssl_error, NULL));
         }
    +
         SSL_CTX_set_options(sslContext, ssl_parse_options(options));
     
         if (cipher) {
    -	debug(83, 5) ("Using chiper suite %s.\n", cipher);
    -	if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
    -	    ssl_error = ERR_get_error();
    -	    fatalf("Failed to set SSL cipher suite '%s': %s\n",
    -		cipher, ERR_error_string(ssl_error, NULL));
    -	}
    +        debug(83, 5) ("Using chiper suite %s.\n", cipher);
    +
    +        if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
    +            ssl_error = ERR_get_error();
    +            fatalf("Failed to set SSL cipher suite '%s': %s\n",
    +                   cipher, ERR_error_string(ssl_error, NULL));
    +        }
         }
    +
         if (certfile) {
    -	debug(83, 1) ("Using certificate in %s\n", certfile);
    -	if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
    -	    ssl_error = ERR_get_error();
    -	    fatalf("Failed to acquire SSL certificate '%s': %s\n",
    -		certfile, ERR_error_string(ssl_error, NULL));
    -	}
    -	debug(83, 1) ("Using private key in %s\n", keyfile);
    -	if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
    -	    ssl_error = ERR_get_error();
    -	    fatalf("Failed to acquire SSL private key '%s': %s\n",
    -		keyfile, ERR_error_string(ssl_error, NULL));
    -	}
    -	debug(83, 5) ("Comparing private and public SSL keys.\n");
    -	if (!SSL_CTX_check_private_key(sslContext)) {
    -	    ssl_error = ERR_get_error();
    -	    fatalf("SSL private key '%s' does not match public key '%s': %s\n",
    -		certfile, keyfile, ERR_error_string(ssl_error, NULL));
    -	}
    +        debug(83, 1) ("Using certificate in %s\n", certfile);
    +
    +        if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
    +            ssl_error = ERR_get_error();
    +            fatalf("Failed to acquire SSL certificate '%s': %s\n",
    +                   certfile, ERR_error_string(ssl_error, NULL));
    +        }
    +
    +        debug(83, 1) ("Using private key in %s\n", keyfile);
    +
    +        if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
    +            ssl_error = ERR_get_error();
    +            fatalf("Failed to acquire SSL private key '%s': %s\n",
    +                   keyfile, ERR_error_string(ssl_error, NULL));
    +        }
    +
    +        debug(83, 5) ("Comparing private and public SSL keys.\n");
    +
    +        if (!SSL_CTX_check_private_key(sslContext)) {
    +            ssl_error = ERR_get_error();
    +            fatalf("SSL private key '%s' does not match public key '%s': %s\n",
    +                   certfile, keyfile, ERR_error_string(ssl_error, NULL));
    +        }
         }
    +
         debug(83, 9) ("Setting RSA key generation callback.\n");
         SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
     
         if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
    -	debug(83, 1) ("NOTICE: Peer certificates are not verified for validity!\n");
    -	SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
    +        debug(83, 1) ("NOTICE: Peer certificates are not verified for validity!\n");
    +        SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
         } else {
    -	debug(83, 9) ("Setting certificate verification callback.\n");
    -	SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
    +        debug(83, 9) ("Setting certificate verification callback.\n");
    +        SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
         }
     
         debug(83, 9) ("Setting CA certificate locations.\n");
    +
         if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
    -	ssl_error = ERR_get_error();
    -	debug(83, 1) ("Error error setting CA certificate locations: %s\n",
    -	    ERR_error_string(ssl_error, NULL));
    -	debug(83, 1) ("continuing anyway...\n");
    +        ssl_error = ERR_get_error();
    +        debug(83, 1) ("Error error setting CA certificate locations: %s\n",
    +                      ERR_error_string(ssl_error, NULL));
    +        debug(83, 1) ("continuing anyway...\n");
         }
    +
         if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
    -	!SSL_CTX_set_default_verify_paths(sslContext)) {
    -	ssl_error = ERR_get_error();
    -	debug(83, 1) ("Error error setting default CA certificate location: %s\n",
    -	    ERR_error_string(ssl_error, NULL));
    -	debug(83, 1) ("continuing anyway...\n");
    +            !SSL_CTX_set_default_verify_paths(sslContext)) {
    +        ssl_error = ERR_get_error();
    +        debug(83, 1) ("Error error setting default CA certificate location: %s\n",
    +                      ERR_error_string(ssl_error, NULL));
    +        debug(83, 1) ("continuing anyway...\n");
         }
    +
         return sslContext;
     }
     
    @@ -595,10 +686,10 @@ ssl_read_method(int fd, char *buf, int len)
         i = SSL_read(fd_table[fd].ssl, buf, len);
     
         if (i > 0 && SSL_pending(fd_table[fd].ssl) > 0) {
    -	debug(83, 2) ("SSL fd %d is pending\n", fd);
    -	fd_table[fd].flags.read_pending = 1;
    +        debug(83, 2) ("SSL fd %d is pending\n", fd);
    +        fd_table[fd].flags.read_pending = 1;
         } else
    -	fd_table[fd].flags.read_pending = 0;
    +        fd_table[fd].flags.read_pending = 0;
     
         return i;
     }
    @@ -613,13 +704,16 @@ void
     ssl_shutdown_method(int fd)
     {
         SSL *ssl = fd_table[fd].ssl;
    +
         if (!fd_table[fd].ssl_shutdown) {
    -	fd_table[fd].ssl_shutdown = 1;
    -	if (Config.SSL.unclean_shutdown)
    -	    SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
    -	else
    -	    SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
    +        fd_table[fd].ssl_shutdown = 1;
    +
    +        if (Config.SSL.unclean_shutdown)
    +            SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
    +        else
    +            SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
         }
    +
         SSL_shutdown(ssl);
     }
     
    @@ -632,16 +726,20 @@ ssl_get_attribute(X509_NAME * name, const char *attribute_name)
         buffer[0] = '\0';
     
         if (strcmp(attribute_name, "DN") == 0) {
    -	X509_NAME_oneline(name, buffer, sizeof(buffer));
    -	goto done;
    +        X509_NAME_oneline(name, buffer, sizeof(buffer));
    +        goto done;
         }
    +
         nid = OBJ_txt2nid((char *) attribute_name);
    +
         if (nid == 0) {
    -	debug(83, 1) ("WARNING: Unknown SSL attribute name '%s'\n", attribute_name);
    -	return NULL;
    +        debug(83, 1) ("WARNING: Unknown SSL attribute name '%s'\n", attribute_name);
    +        return NULL;
         }
    +
         X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
    -  done:
    +
    +done:
         return *buffer ? buffer : NULL;
     }
     
    @@ -652,11 +750,12 @@ sslGetUserAttribute(SSL * ssl, const char *attribute_name)
         X509_NAME *name;
     
         if (!ssl)
    -	return NULL;
    +        return NULL;
     
         cert = SSL_get_peer_certificate(ssl);
    +
         if (!cert)
    -	return NULL;
    +        return NULL;
     
         name = X509_get_issuer_name(cert);
     
    @@ -670,11 +769,12 @@ sslGetCAAttribute(SSL * ssl, const char *attribute_name)
         X509_NAME *name;
     
         if (!ssl)
    -	return NULL;
    +        return NULL;
     
         cert = SSL_get_peer_certificate(ssl);
    +
         if (!cert)
    -	return NULL;
    +        return NULL;
     
         name = X509_get_subject_name(cert);
     
    @@ -691,18 +791,21 @@ sslGetUserEmail(SSL * ssl)
         static char email[128];
     
         if (!ssl)
    -	return NULL;
    +        return NULL;
    +
         cert = SSL_get_peer_certificate(ssl);
    +
         if (!cert)
    -	return NULL;
    +        return NULL;
     
         name = X509_get_subject_name(cert);
     
         if (X509_NAME_get_text_by_NID(name, NID_pkcs9_emailAddress, email, sizeof(email)) > 0)
    -	return email;
    +        return email;
         else
    -	return NULL;
    +        return NULL;
     }
    +
     #endif
     
     const char *
    diff --git a/src/stat.cc b/src/stat.cc
    index 9ecfc1be04..f57e91bbfd 100644
    --- a/src/stat.cc
    +++ b/src/stat.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: stat.cc,v 1.369 2003/01/27 08:35:47 hno Exp $
    + * $Id: stat.cc,v 1.370 2003/02/21 22:50:11 robertc Exp $
      *
      * DEBUG: section 18    Cache Manager Statistics
      * AUTHOR: Harvest Derived
    @@ -50,11 +50,15 @@
     #define DEBUG_OPENFD 1
     
     typedef int STOBJFLT(const StoreEntry *);
    -typedef struct {
    +
    +typedef struct
    +{
         StoreEntry *sentry;
         int bucket;
         STOBJFLT *filter;
    -} StatObjectsState;
    +}
    +
    +StatObjectsState;
     
     /* LOCALS */
     static const char *describeStatuses(const StoreEntry *);
    @@ -109,42 +113,61 @@ statUtilization(StoreEntry * e)
         storeAppendPrintf(e, "Cache Utilisation:\n");
         storeAppendPrintf(e, "\n");
         storeAppendPrintf(e, "Last 5 minutes:\n");
    +
         if (NCountHist >= 5)
    -	statAvgDump(e, 5, 0);
    +        statAvgDump(e, 5, 0);
         else
    -	storeAppendPrintf(e, "(no values recorded yet)\n");
    +        storeAppendPrintf(e, "(no values recorded yet)\n");
    +
         storeAppendPrintf(e, "\n");
    +
         storeAppendPrintf(e, "Last 15 minutes:\n");
    +
         if (NCountHist >= 15)
    -	statAvgDump(e, 15, 0);
    +        statAvgDump(e, 15, 0);
         else
    -	storeAppendPrintf(e, "(no values recorded yet)\n");
    +        storeAppendPrintf(e, "(no values recorded yet)\n");
    +
         storeAppendPrintf(e, "\n");
    +
         storeAppendPrintf(e, "Last hour:\n");
    +
         if (NCountHist >= 60)
    -	statAvgDump(e, 60, 0);
    +        statAvgDump(e, 60, 0);
         else
    -	storeAppendPrintf(e, "(no values recorded yet)\n");
    +        storeAppendPrintf(e, "(no values recorded yet)\n");
    +
         storeAppendPrintf(e, "\n");
    +
         storeAppendPrintf(e, "Last 8 hours:\n");
    +
         if (NCountHourHist >= 8)
    -	statAvgDump(e, 0, 8);
    +        statAvgDump(e, 0, 8);
         else
    -	storeAppendPrintf(e, "(no values recorded yet)\n");
    +        storeAppendPrintf(e, "(no values recorded yet)\n");
    +
         storeAppendPrintf(e, "\n");
    +
         storeAppendPrintf(e, "Last day:\n");
    +
         if (NCountHourHist >= 24)
    -	statAvgDump(e, 0, 24);
    +        statAvgDump(e, 0, 24);
         else
    -	storeAppendPrintf(e, "(no values recorded yet)\n");
    +        storeAppendPrintf(e, "(no values recorded yet)\n");
    +
         storeAppendPrintf(e, "\n");
    +
         storeAppendPrintf(e, "Last 3 days:\n");
    +
         if (NCountHourHist >= 72)
    -	statAvgDump(e, 0, 72);
    +        statAvgDump(e, 0, 72);
         else
    -	storeAppendPrintf(e, "(no values recorded yet)\n");
    +        storeAppendPrintf(e, "(no values recorded yet)\n");
    +
         storeAppendPrintf(e, "\n");
    +
         storeAppendPrintf(e, "Totals since cache startup:\n");
    +
         statCountersDump(e);
     }
     
    @@ -156,48 +179,52 @@ stat_io_get(StoreEntry * sentry)
         storeAppendPrintf(sentry, "HTTP I/O\n");
         storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Http.reads);
         storeAppendPrintf(sentry, "Read Histogram:\n");
    +
         for (i = 0; i < 16; i++) {
    -	storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    -	    i ? (1 << (i - 1)) + 1 : 1,
    -	    1 << i,
    -	    IOStats.Http.read_hist[i],
    -	    percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
    +        storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    +                          i ? (1 << (i - 1)) + 1 : 1,
    +                          1 << i,
    +                          IOStats.Http.read_hist[i],
    +                          percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
         }
     
         storeAppendPrintf(sentry, "\n");
         storeAppendPrintf(sentry, "FTP I/O\n");
         storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Ftp.reads);
         storeAppendPrintf(sentry, "Read Histogram:\n");
    +
         for (i = 0; i < 16; i++) {
    -	storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    -	    i ? (1 << (i - 1)) + 1 : 1,
    -	    1 << i,
    -	    IOStats.Ftp.read_hist[i],
    -	    percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
    +        storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    +                          i ? (1 << (i - 1)) + 1 : 1,
    +                          1 << i,
    +                          IOStats.Ftp.read_hist[i],
    +                          percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
         }
     
         storeAppendPrintf(sentry, "\n");
         storeAppendPrintf(sentry, "Gopher I/O\n");
         storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Gopher.reads);
         storeAppendPrintf(sentry, "Read Histogram:\n");
    +
         for (i = 0; i < 16; i++) {
    -	storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    -	    i ? (1 << (i - 1)) + 1 : 1,
    -	    1 << i,
    -	    IOStats.Gopher.read_hist[i],
    -	    percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
    +        storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    +                          i ? (1 << (i - 1)) + 1 : 1,
    +                          1 << i,
    +                          IOStats.Gopher.read_hist[i],
    +                          percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
         }
     
         storeAppendPrintf(sentry, "\n");
         storeAppendPrintf(sentry, "WAIS I/O\n");
         storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Wais.reads);
         storeAppendPrintf(sentry, "Read Histogram:\n");
    +
         for (i = 0; i < 16; i++) {
    -	storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    -	    i ? (1 << (i - 1)) + 1 : 1,
    -	    1 << i,
    -	    IOStats.Wais.read_hist[i],
    -	    percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads));
    +        storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
    +                          i ? (1 << (i - 1)) + 1 : 1,
    +                          1 << i,
    +                          IOStats.Wais.read_hist[i],
    +                          percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads));
         }
     }
     
    @@ -206,10 +233,10 @@ describeStatuses(const StoreEntry * entry)
     {
         LOCAL_ARRAY(char, buf, 256);
         snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
    -	storeStatusStr[entry->store_status],
    -	memStatusStr[entry->mem_status],
    -	swapStatusStr[entry->swap_status],
    -	pingStatusStr[entry->ping_status]);
    +             storeStatusStr[entry->store_status],
    +             memStatusStr[entry->mem_status],
    +             swapStatusStr[entry->swap_status],
    +             pingStatusStr[entry->ping_status]);
         return buf;
     }
     
    @@ -220,34 +247,49 @@ storeEntryFlags(const StoreEntry * entry)
         int flags = (int) entry->flags;
         char *t;
         buf[0] = '\0';
    +
         if (EBIT_TEST(flags, ENTRY_SPECIAL))
    -	strcat(buf, "SPECIAL,");
    +        strcat(buf, "SPECIAL,");
    +
         if (EBIT_TEST(flags, ENTRY_REVALIDATE))
    -	strcat(buf, "REVALIDATE,");
    +        strcat(buf, "REVALIDATE,");
    +
         if (EBIT_TEST(flags, DELAY_SENDING))
    -	strcat(buf, "DELAY_SENDING,");
    +        strcat(buf, "DELAY_SENDING,");
    +
         if (EBIT_TEST(flags, RELEASE_REQUEST))
    -	strcat(buf, "RELEASE_REQUEST,");
    +        strcat(buf, "RELEASE_REQUEST,");
    +
         if (EBIT_TEST(flags, REFRESH_REQUEST))
    -	strcat(buf, "REFRESH_REQUEST,");
    +        strcat(buf, "REFRESH_REQUEST,");
    +
         if (EBIT_TEST(flags, ENTRY_CACHABLE))
    -	strcat(buf, "CACHABLE,");
    +        strcat(buf, "CACHABLE,");
    +
         if (EBIT_TEST(flags, ENTRY_DISPATCHED))
    -	strcat(buf, "DISPATCHED,");
    +        strcat(buf, "DISPATCHED,");
    +
         if (EBIT_TEST(flags, KEY_PRIVATE))
    -	strcat(buf, "PRIVATE,");
    +        strcat(buf, "PRIVATE,");
    +
         if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
    -	strcat(buf, "FWD_HDR_WAIT,");
    +        strcat(buf, "FWD_HDR_WAIT,");
    +
         if (EBIT_TEST(flags, ENTRY_NEGCACHED))
    -	strcat(buf, "NEGCACHED,");
    +        strcat(buf, "NEGCACHED,");
    +
         if (EBIT_TEST(flags, ENTRY_VALIDATED))
    -	strcat(buf, "VALIDATED,");
    +        strcat(buf, "VALIDATED,");
    +
         if (EBIT_TEST(flags, ENTRY_BAD_LENGTH))
    -	strcat(buf, "BAD_LENGTH,");
    +        strcat(buf, "BAD_LENGTH,");
    +
         if (EBIT_TEST(flags, ENTRY_ABORTED))
    -	strcat(buf, "ABORTED,");
    +        strcat(buf, "ABORTED,");
    +
         if ((t = strrchr(buf, ',')))
    -	*t = '\0';
    +        *t = '\0';
    +
         return buf;
     }
     
    @@ -256,10 +298,10 @@ describeTimestamps(const StoreEntry * entry)
     {
         LOCAL_ARRAY(char, buf, 256);
         snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
    -	(int) entry->timestamp,
    -	(int) entry->lastref,
    -	(int) entry->lastmod,
    -	(int) entry->expires);
    +             (int) entry->timestamp,
    +             (int) entry->lastref,
    +             (int) entry->lastmod,
    +             (int) entry->expires);
         return buf;
     }
     
    @@ -272,13 +314,15 @@ statStoreEntry(StoreEntry * s, StoreEntry * e)
         storeAppendPrintf(s, "\t%s\n", storeEntryFlags(e));
         storeAppendPrintf(s, "\t%s\n", describeTimestamps(e));
         storeAppendPrintf(s, "\t%d locks, %d clients, %d refs\n",
    -	(int) e->lock_count,
    -	storePendingNClients(e),
    -	(int) e->refcount);
    +                      (int) e->lock_count,
    +                      storePendingNClients(e),
    +                      (int) e->refcount);
         storeAppendPrintf(s, "\tSwap Dir %d, File %#08X\n",
    -	e->swap_dirn, e->swap_filen);
    +                      e->swap_dirn, e->swap_filen);
    +
         if (mem != NULL)
    -	mem->stat (s);
    +        mem->stat (s);
    +
         storeAppendPrintf(s, "\n");
     }
     
    @@ -290,29 +334,35 @@ statObjects(void *data)
         StoreEntry *e;
         hash_link *link_ptr = NULL;
         hash_link *link_next = NULL;
    +
         if (state->bucket >= store_hash_buckets) {
    -	state->sentry->complete();
    -	storeUnlockObject(state->sentry);
    -	cbdataFree(state);
    -	return;
    +        state->sentry->complete();
    +        storeUnlockObject(state->sentry);
    +        cbdataFree(state);
    +        return;
         } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
    -	storeUnlockObject(state->sentry);
    -	cbdataFree(state);
    -	return;
    +        storeUnlockObject(state->sentry);
    +        cbdataFree(state);
    +        return;
         } else if (StoreEntry::CheckDeferRead(-1, state->sentry)) {
    -	eventAdd("statObjects", statObjects, state, 0.1, 1);
    -	return;
    +        eventAdd("statObjects", statObjects, state, 0.1, 1);
    +        return;
         }
    +
         storeBuffer(state->sentry);
         debug(49, 3) ("statObjects: Bucket #%d\n", state->bucket);
         link_next = hash_get_bucket(store_table, state->bucket);
    +
         while (NULL != (link_ptr = link_next)) {
    -	link_next = link_ptr->next;
    -	e = (StoreEntry *) link_ptr;
    -	if (state->filter && 0 == state->filter(e))
    -	    continue;
    -	statStoreEntry(state->sentry, e);
    +        link_next = link_ptr->next;
    +        e = (StoreEntry *) link_ptr;
    +
    +        if (state->filter && 0 == state->filter(e))
    +            continue;
    +
    +        statStoreEntry(state->sentry, e);
         }
    +
         state->bucket++;
         eventAdd("statObjects", statObjects, state, 0.0, 1);
         storeBufferFlush(state->sentry);
    @@ -352,9 +402,11 @@ static int
     statObjectsOpenfdFilter(const StoreEntry * e)
     {
         if (e->mem_obj == NULL)
    -	return 0;
    +        return 0;
    +
         if (e->mem_obj->swapout.sio == NULL)
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -371,216 +423,299 @@ static void
     info_get_mallstat(int size, int number, int oldnum, void *data)
     {
         StoreEntry *sentry = (StoreEntry *)data;
    +
         if (number > 0)
    -	storeAppendPrintf(sentry, "%d\t %d\t %d\t %.1f\n", size, number, number - oldnum, xdiv((number - oldnum), xm_deltat));
    +        storeAppendPrintf(sentry, "%d\t %d\t %d\t %.1f\n", size, number, number - oldnum, xdiv((number - oldnum), xm_deltat));
     }
    +
     #endif
     
     static void
     info_get(StoreEntry * sentry)
     {
    +
         struct rusage rusage;
         double cputime;
         double runtime;
     #if HAVE_MSTATS && HAVE_GNUMALLOC_H
    +
         struct mstats ms;
     #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
    +
         struct mallinfo mp;
         int t;
     #endif
     
         runtime = tvSubDsec(squid_start, current_time);
    +
         if (runtime == 0.0)
    -	runtime = 1.0;
    +        runtime = 1.0;
    +
         storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
    -	version_string);
    +                      version_string);
    +
         storeAppendPrintf(sentry, "Start Time:\t%s\n",
    -	mkrfc1123(squid_start.tv_sec));
    +                      mkrfc1123(squid_start.tv_sec));
    +
         storeAppendPrintf(sentry, "Current Time:\t%s\n",
    -	mkrfc1123(current_time.tv_sec));
    +                      mkrfc1123(current_time.tv_sec));
    +
         storeAppendPrintf(sentry, "Connection information for %s:\n",
    -	appname);
    +                      appname);
    +
         storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%u\n",
    -	statCounter.client_http.clients);
    +                      statCounter.client_http.clients);
    +
         storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%u\n",
    -	statCounter.client_http.requests);
    +                      statCounter.client_http.requests);
    +
         storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%u\n",
    -	statCounter.icp.pkts_recv);
    +                      statCounter.icp.pkts_recv);
    +
         storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%u\n",
    -	statCounter.icp.pkts_sent);
    +                      statCounter.icp.pkts_sent);
    +
         storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%u\n",
    -	statCounter.icp.replies_queued);
    +                      statCounter.icp.replies_queued);
    +
         storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f\n",
    -	request_failure_ratio);
    +                      request_failure_ratio);
     
         storeAppendPrintf(sentry, "\tAverage HTTP requests per minute since start:\t%.1f\n",
    -	statCounter.client_http.requests / (runtime / 60.0));
    +                      statCounter.client_http.requests / (runtime / 60.0));
    +
         storeAppendPrintf(sentry, "\tAverage ICP messages per minute since start:\t%.1f\n",
    -	(statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0));
    +                      (statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0));
    +
         storeAppendPrintf(sentry, "\tSelect loop called: %d times, %0.3f ms avg\n",
    -	statCounter.select_loops, 1000.0 * runtime / statCounter.select_loops);
    +                      statCounter.select_loops, 1000.0 * runtime / statCounter.select_loops);
     
         storeAppendPrintf(sentry, "Cache information for %s:\n",
    -	appname);
    +                      appname);
    +
         storeAppendPrintf(sentry, "\tRequest Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
    -	statRequestHitRatio(5),
    -	statRequestHitRatio(60));
    +                      statRequestHitRatio(5),
    +                      statRequestHitRatio(60));
    +
         storeAppendPrintf(sentry, "\tByte Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
    -	statByteHitRatio(5),
    -	statByteHitRatio(60));
    +                      statByteHitRatio(5),
    +                      statByteHitRatio(60));
    +
         storeAppendPrintf(sentry, "\tRequest Memory Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
    -	statRequestHitMemoryRatio(5),
    -	statRequestHitMemoryRatio(60));
    +                      statRequestHitMemoryRatio(5),
    +                      statRequestHitMemoryRatio(60));
    +
         storeAppendPrintf(sentry, "\tRequest Disk Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
    -	statRequestHitDiskRatio(5),
    -	statRequestHitDiskRatio(60));
    +                      statRequestHitDiskRatio(5),
    +                      statRequestHitDiskRatio(60));
    +
         storeAppendPrintf(sentry, "\tStorage Swap size:\t%lu KB\n",
    -	store_swap_size);
    +                      store_swap_size);
    +
         storeAppendPrintf(sentry, "\tStorage Mem size:\t%d KB\n",
    -	(int) (mem_node::store_mem_size >> 10));
    +                      (int) (mem_node::store_mem_size >> 10));
    +
         storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
    -	n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0);
    +                      n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0);
    +
         storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n",
    -	statCounter.unlink.requests);
    +                      statCounter.unlink.requests);
     
         storeAppendPrintf(sentry, "Median Service Times (seconds)  5 min    60 min:\n");
    +
         storeAppendPrintf(sentry, "\tHTTP Requests (All):  %8.5f %8.5f\n",
    -	statMedianSvc(5, MEDIAN_HTTP) / 1000.0,
    -	statMedianSvc(60, MEDIAN_HTTP) / 1000.0);
    +                      statMedianSvc(5, MEDIAN_HTTP) / 1000.0,
    +                      statMedianSvc(60, MEDIAN_HTTP) / 1000.0);
    +
         storeAppendPrintf(sentry, "\tCache Misses:         %8.5f %8.5f\n",
    -	statMedianSvc(5, MEDIAN_MISS) / 1000.0,
    -	statMedianSvc(60, MEDIAN_MISS) / 1000.0);
    +                      statMedianSvc(5, MEDIAN_MISS) / 1000.0,
    +                      statMedianSvc(60, MEDIAN_MISS) / 1000.0);
    +
         storeAppendPrintf(sentry, "\tCache Hits:           %8.5f %8.5f\n",
    -	statMedianSvc(5, MEDIAN_HIT) / 1000.0,
    -	statMedianSvc(60, MEDIAN_HIT) / 1000.0);
    +                      statMedianSvc(5, MEDIAN_HIT) / 1000.0,
    +                      statMedianSvc(60, MEDIAN_HIT) / 1000.0);
    +
         storeAppendPrintf(sentry, "\tNear Hits:            %8.5f %8.5f\n",
    -	statMedianSvc(5, MEDIAN_NH) / 1000.0,
    -	statMedianSvc(60, MEDIAN_NH) / 1000.0);
    +                      statMedianSvc(5, MEDIAN_NH) / 1000.0,
    +                      statMedianSvc(60, MEDIAN_NH) / 1000.0);
    +
         storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
    -	statMedianSvc(5, MEDIAN_NM) / 1000.0,
    -	statMedianSvc(60, MEDIAN_NM) / 1000.0);
    +                      statMedianSvc(5, MEDIAN_NM) / 1000.0,
    +                      statMedianSvc(60, MEDIAN_NM) / 1000.0);
    +
         storeAppendPrintf(sentry, "\tDNS Lookups:          %8.5f %8.5f\n",
    -	statMedianSvc(5, MEDIAN_DNS) / 1000.0,
    -	statMedianSvc(60, MEDIAN_DNS) / 1000.0);
    +                      statMedianSvc(5, MEDIAN_DNS) / 1000.0,
    +                      statMedianSvc(60, MEDIAN_DNS) / 1000.0);
    +
         storeAppendPrintf(sentry, "\tICP Queries:          %8.5f %8.5f\n",
    -	statMedianSvc(5, MEDIAN_ICP_QUERY) / 1000000.0,
    -	statMedianSvc(60, MEDIAN_ICP_QUERY) / 1000000.0);
    +                      statMedianSvc(5, MEDIAN_ICP_QUERY) / 1000000.0,
    +                      statMedianSvc(60, MEDIAN_ICP_QUERY) / 1000000.0);
     
         squid_getrusage(&rusage);
    +
         cputime = rusage_cputime(&rusage);
    +
         storeAppendPrintf(sentry, "Resource usage for %s:\n", appname);
    +
         storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", runtime);
    +
         storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", cputime);
    +
         storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
    -	dpercent(cputime, runtime));
    +                      dpercent(cputime, runtime));
    +
         storeAppendPrintf(sentry, "\tCPU Usage, 5 minute avg:\t%.2f%%\n",
    -	statCPUUsage(5));
    +                      statCPUUsage(5));
    +
         storeAppendPrintf(sentry, "\tCPU Usage, 60 minute avg:\t%.2f%%\n",
    -	statCPUUsage(60));
    +                      statCPUUsage(60));
    +
     #if HAVE_SBRK
    +
         storeAppendPrintf(sentry, "\tProcess Data Segment Size via sbrk(): %d KB\n",
    -	(int) (((char *) sbrk(0) - (char *) sbrk_start) >> 10));
    +                      (int) (((char *) sbrk(0) - (char *) sbrk_start) >> 10));
    +
     #endif
    +
         storeAppendPrintf(sentry, "\tMaximum Resident Size: %d KB\n",
    -	rusage_maxrss(&rusage));
    +                      rusage_maxrss(&rusage));
    +
         storeAppendPrintf(sentry, "\tPage faults with physical i/o: %d\n",
    -	rusage_pagefaults(&rusage));
    +                      rusage_pagefaults(&rusage));
     
     #if HAVE_MSTATS && HAVE_GNUMALLOC_H
    +
         ms = mstats();
    +
         storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",
    -	appname);
    +                      appname);
    +
         storeAppendPrintf(sentry, "\tTotal space in arena:  %6d KB\n",
    -	ms.bytes_total >> 10);
    +                      ms.bytes_total >> 10);
    +
         storeAppendPrintf(sentry, "\tTotal free:            %6d KB %d%%\n",
    -	ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
    +                      ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
    +
     #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
    +
         mp = mallinfo();
    +
         storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",
    -	appname);
    +                      appname);
    +
         storeAppendPrintf(sentry, "\tTotal space in arena:  %6d KB\n",
    -	mp.arena >> 10);
    +                      mp.arena >> 10);
    +
         storeAppendPrintf(sentry, "\tOrdinary blocks:       %6d KB %6d blks\n",
    -	mp.uordblks >> 10, mp.ordblks);
    +                      mp.uordblks >> 10, mp.ordblks);
    +
         storeAppendPrintf(sentry, "\tSmall blocks:          %6d KB %6d blks\n",
    -	mp.usmblks >> 10, mp.smblks);
    +                      mp.usmblks >> 10, mp.smblks);
    +
         storeAppendPrintf(sentry, "\tHolding blocks:        %6d KB %6d blks\n",
    -	mp.hblkhd >> 10, mp.hblks);
    +                      mp.hblkhd >> 10, mp.hblks);
    +
         storeAppendPrintf(sentry, "\tFree Small blocks:     %6d KB\n",
    -	mp.fsmblks >> 10);
    +                      mp.fsmblks >> 10);
    +
         storeAppendPrintf(sentry, "\tFree Ordinary blocks:  %6d KB\n",
    -	mp.fordblks >> 10);
    +                      mp.fordblks >> 10);
    +
         t = mp.uordblks + mp.usmblks + mp.hblkhd;
    +
         storeAppendPrintf(sentry, "\tTotal in use:          %6d KB %d%%\n",
    -	t >> 10, percent(t, mp.arena + mp.hblkhd));
    +                      t >> 10, percent(t, mp.arena + mp.hblkhd));
    +
         t = mp.fsmblks + mp.fordblks;
    +
         storeAppendPrintf(sentry, "\tTotal free:            %6d KB %d%%\n",
    -	t >> 10, percent(t, mp.arena + mp.hblkhd));
    +                      t >> 10, percent(t, mp.arena + mp.hblkhd));
    +
         t = mp.arena + mp.hblkhd;
    +
         storeAppendPrintf(sentry, "\tTotal size:            %6d KB\n",
    -	t >> 10);
    +                      t >> 10);
    +
     #if HAVE_STRUCT_MALLINFO_MXFAST
    +
         storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast);
    +
         storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%d\n",
    -	mp.nlblks);
    +                      mp.nlblks);
    +
         storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%d\n", mp.grain);
    +
         storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%d\n"
    -	,mp.uordbytes);
    +                      ,mp.uordbytes);
    +
         storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%d\n",
    -	mp.allocated);
    +                      mp.allocated);
    +
         storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%d\n",
    -	mp.treeoverhead);
    +                      mp.treeoverhead);
    +
     #endif /* HAVE_STRUCT_MALLINFO_MXFAST */
     #endif /* HAVE_MALLINFO */
    +
         storeAppendPrintf(sentry, "Memory accounted for:\n");
    +
     #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
    +
         storeAppendPrintf(sentry, "\tTotal accounted:       %6d KB %3d%%\n",
    -	statMemoryAccounted() >> 10, percent(statMemoryAccounted(), t));
    +                      statMemoryAccounted() >> 10, percent(statMemoryAccounted(), t));
    +
     #else
    +
         storeAppendPrintf(sentry, "\tTotal accounted:       %6d KB\n",
    -	statMemoryAccounted() >> 10);
    +                      statMemoryAccounted() >> 10);
    +
     #endif
    +
         {
    -	MemPoolGlobalStats mp_stats;
    -	memPoolGetGlobalStats(&mp_stats);
    +        MemPoolGlobalStats mp_stats;
    +        memPoolGetGlobalStats(&mp_stats);
     #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
    -	storeAppendPrintf(sentry, "\tmemPool accounted:     %6d KB %3d%%\n",
    -	    mp_stats.TheMeter->alloc.level >> 10, percent(mp_stats.TheMeter->alloc.level, t));
    -	storeAppendPrintf(sentry, "\tmemPool unaccounted:   %6d KB %3d%%\n",
    -	    (t - mp_stats.TheMeter->alloc.level) >> 10, percent((t - mp_stats.TheMeter->alloc.level), t));
    +
    +        storeAppendPrintf(sentry, "\tmemPool accounted:     %6d KB %3d%%\n",
    +                          mp_stats.TheMeter->alloc.level >> 10, percent(mp_stats.TheMeter->alloc.level, t));
    +        storeAppendPrintf(sentry, "\tmemPool unaccounted:   %6d KB %3d%%\n",
    +                          (t - mp_stats.TheMeter->alloc.level) >> 10, percent((t - mp_stats.TheMeter->alloc.level), t));
     #endif
    -	storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %9.0f\n",
    -	    mp_stats.TheMeter->gb_saved.count);
    -	storeAppendPrintf(sentry, "\tmemPoolFree calls:  %9.0f\n",
    -	    mp_stats.TheMeter->gb_freed.count);
    +
    +        storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %9.0f\n",
    +                          mp_stats.TheMeter->gb_saved.count);
    +        storeAppendPrintf(sentry, "\tmemPoolFree calls:  %9.0f\n",
    +                          mp_stats.TheMeter->gb_freed.count);
         }
    +
         storeAppendPrintf(sentry, "File descriptor usage for %s:\n", appname);
         storeAppendPrintf(sentry, "\tMaximum number of file descriptors:   %4d\n",
    -	Squid_MaxFD);
    +                      Squid_MaxFD);
         storeAppendPrintf(sentry, "\tLargest file desc currently in use:   %4d\n",
    -	Biggest_FD);
    +                      Biggest_FD);
         storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n",
    -	Number_FD);
    +                      Number_FD);
         storeAppendPrintf(sentry, "\tFiles queued for open:                %4d\n",
    -	Opening_FD);
    +                      Opening_FD);
         storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n",
    -	fdNFree());
    +                      fdNFree());
         storeAppendPrintf(sentry, "\tReserved number of file descriptors:  %4d\n",
    -	RESERVED_FD);
    +                      RESERVED_FD);
         storeAppendPrintf(sentry, "\tStore Disk files open:                %4d\n",
    -	store_open_disk_fd);
    +                      store_open_disk_fd);
     
         storeAppendPrintf(sentry, "Internal Data Structures:\n");
         storeAppendPrintf(sentry, "\t%6lu StoreEntries\n",
    -	(unsigned long)StoreEntry::inUseCount());
    +                      (unsigned long)StoreEntry::inUseCount());
         storeAppendPrintf(sentry, "\t%6lu StoreEntries with MemObjects\n",
    -	(unsigned long)MemObject::inUseCount());
    +                      (unsigned long)MemObject::inUseCount());
         storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n",
    -	hot_obj_count);
    +                      hot_obj_count);
         storeAppendPrintf(sentry, "\t%6d on-disk objects\n",
    -	n_disk_objects);
    +                      n_disk_objects);
     
     #if XMALLOC_STATISTICS
    +
         xm_deltat = current_dtime - xm_time;
         xm_time = current_dtime;
         storeAppendPrintf(sentry, "\nMemory allocation statistics\n");
    @@ -602,167 +737,176 @@ statAvgDump(StoreEntry * sentry, int minutes, int hours)
         assert(minutes > 0 || hours > 0);
         f = &CountHist[0];
         l = f;
    +
         if (minutes > 0 && hours == 0) {
    -	/* checking minute readings ... */
    -	if (minutes > N_COUNT_HIST - 1)
    -	    minutes = N_COUNT_HIST - 1;
    -	l = &CountHist[minutes];
    +        /* checking minute readings ... */
    +
    +        if (minutes > N_COUNT_HIST - 1)
    +            minutes = N_COUNT_HIST - 1;
    +
    +        l = &CountHist[minutes];
         } else if (minutes == 0 && hours > 0) {
    -	/* checking hour readings ... */
    -	if (hours > N_COUNT_HOUR_HIST - 1)
    -	    hours = N_COUNT_HOUR_HIST - 1;
    -	l = &CountHourHist[hours];
    +        /* checking hour readings ... */
    +
    +        if (hours > N_COUNT_HOUR_HIST - 1)
    +            hours = N_COUNT_HOUR_HIST - 1;
    +
    +        l = &CountHourHist[hours];
         } else {
    -	debug(18, 1) ("statAvgDump: Invalid args, minutes=%d, hours=%d\n",
    -	    minutes, hours);
    -	return;
    +        debug(18, 1) ("statAvgDump: Invalid args, minutes=%d, hours=%d\n",
    +                      minutes, hours);
    +        return;
         }
    +
         dt = tvSubDsec(l->timestamp, f->timestamp);
         ct = f->cputime - l->cputime;
     
         storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
    -	(int) l->timestamp.tv_sec,
    -	(int) l->timestamp.tv_usec,
    -	mkrfc1123(l->timestamp.tv_sec));
    +                      (int) l->timestamp.tv_sec,
    +                      (int) l->timestamp.tv_usec,
    +                      mkrfc1123(l->timestamp.tv_sec));
         storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
    -	(int) f->timestamp.tv_sec,
    -	(int) f->timestamp.tv_usec,
    -	mkrfc1123(f->timestamp.tv_sec));
    +                      (int) f->timestamp.tv_sec,
    +                      (int) f->timestamp.tv_usec,
    +                      mkrfc1123(f->timestamp.tv_sec));
     
         storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
    -	XAVG(client_http.requests));
    +                      XAVG(client_http.requests));
         storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
    -	XAVG(client_http.hits));
    +                      XAVG(client_http.hits));
         storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
    -	XAVG(client_http.errors));
    +                      XAVG(client_http.errors));
         storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
    -	XAVG(client_http.kbytes_in.kb));
    +                      XAVG(client_http.kbytes_in.kb));
         storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
    -	XAVG(client_http.kbytes_out.kb));
    +                      XAVG(client_http.kbytes_out.kb));
     
         x = statHistDeltaMedian(&l->client_http.all_svc_time,
    -	&f->client_http.all_svc_time);
    +                            &f->client_http.all_svc_time);
         storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
    -	x / 1000.0);
    +                      x / 1000.0);
         x = statHistDeltaMedian(&l->client_http.miss_svc_time,
    -	&f->client_http.miss_svc_time);
    +                            &f->client_http.miss_svc_time);
         storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
    -	x / 1000.0);
    +                      x / 1000.0);
         x = statHistDeltaMedian(&l->client_http.nm_svc_time,
    -	&f->client_http.nm_svc_time);
    +                            &f->client_http.nm_svc_time);
         storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
    -	x / 1000.0);
    +                      x / 1000.0);
         x = statHistDeltaMedian(&l->client_http.nh_svc_time,
    -	&f->client_http.nh_svc_time);
    +                            &f->client_http.nh_svc_time);
         storeAppendPrintf(sentry, "client_http.nh_median_svc_time = %f seconds\n",
    -	x / 1000.0);
    +                      x / 1000.0);
         x = statHistDeltaMedian(&l->client_http.hit_svc_time,
    -	&f->client_http.hit_svc_time);
    +                            &f->client_http.hit_svc_time);
         storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
    -	x / 1000.0);
    +                      x / 1000.0);
     
         storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
    -	XAVG(server.all.requests));
    +                      XAVG(server.all.requests));
         storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
    -	XAVG(server.all.errors));
    +                      XAVG(server.all.errors));
         storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
    -	XAVG(server.all.kbytes_in.kb));
    +                      XAVG(server.all.kbytes_in.kb));
         storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
    -	XAVG(server.all.kbytes_out.kb));
    +                      XAVG(server.all.kbytes_out.kb));
     
         storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
    -	XAVG(server.http.requests));
    +                      XAVG(server.http.requests));
         storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
    -	XAVG(server.http.errors));
    +                      XAVG(server.http.errors));
         storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
    -	XAVG(server.http.kbytes_in.kb));
    +                      XAVG(server.http.kbytes_in.kb));
         storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
    -	XAVG(server.http.kbytes_out.kb));
    +                      XAVG(server.http.kbytes_out.kb));
     
         storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
    -	XAVG(server.ftp.requests));
    +                      XAVG(server.ftp.requests));
         storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
    -	XAVG(server.ftp.errors));
    +                      XAVG(server.ftp.errors));
         storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
    -	XAVG(server.ftp.kbytes_in.kb));
    +                      XAVG(server.ftp.kbytes_in.kb));
         storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
    -	XAVG(server.ftp.kbytes_out.kb));
    +                      XAVG(server.ftp.kbytes_out.kb));
     
         storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
    -	XAVG(server.other.requests));
    +                      XAVG(server.other.requests));
         storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
    -	XAVG(server.other.errors));
    +                      XAVG(server.other.errors));
         storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
    -	XAVG(server.other.kbytes_in.kb));
    +                      XAVG(server.other.kbytes_in.kb));
         storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
    -	XAVG(server.other.kbytes_out.kb));
    +                      XAVG(server.other.kbytes_out.kb));
     
         storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
    -	XAVG(icp.pkts_sent));
    +                      XAVG(icp.pkts_sent));
         storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
    -	XAVG(icp.pkts_recv));
    +                      XAVG(icp.pkts_recv));
         storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n",
    -	XAVG(icp.queries_sent));
    +                      XAVG(icp.queries_sent));
         storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n",
    -	XAVG(icp.replies_sent));
    +                      XAVG(icp.replies_sent));
         storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n",
    -	XAVG(icp.queries_recv));
    +                      XAVG(icp.queries_recv));
         storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n",
    -	XAVG(icp.replies_recv));
    +                      XAVG(icp.replies_recv));
         storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
    -	XAVG(icp.replies_queued));
    +                      XAVG(icp.replies_queued));
         storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n",
    -	XAVG(icp.query_timeouts));
    +                      XAVG(icp.query_timeouts));
         storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
    -	XAVG(icp.kbytes_sent.kb));
    +                      XAVG(icp.kbytes_sent.kb));
         storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
    -	XAVG(icp.kbytes_recv.kb));
    +                      XAVG(icp.kbytes_recv.kb));
         storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n",
    -	XAVG(icp.q_kbytes_sent.kb));
    +                      XAVG(icp.q_kbytes_sent.kb));
         storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n",
    -	XAVG(icp.r_kbytes_sent.kb));
    +                      XAVG(icp.r_kbytes_sent.kb));
         storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n",
    -	XAVG(icp.q_kbytes_recv.kb));
    +                      XAVG(icp.q_kbytes_recv.kb));
         storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n",
    -	XAVG(icp.r_kbytes_recv.kb));
    +                      XAVG(icp.r_kbytes_recv.kb));
         x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
         storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
    -	x / 1000000.0);
    +                      x / 1000000.0);
         x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
         storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
    -	x / 1000000.0);
    +                      x / 1000000.0);
         x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
         storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
    -	x / 1000.0);
    +                      x / 1000.0);
         storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
    -	XAVG(unlink.requests));
    +                      XAVG(unlink.requests));
         storeAppendPrintf(sentry, "page_faults = %f/sec\n",
    -	XAVG(page_faults));
    +                      XAVG(page_faults));
         storeAppendPrintf(sentry, "select_loops = %f/sec\n",
    -	XAVG(select_loops));
    +                      XAVG(select_loops));
         storeAppendPrintf(sentry, "select_fds = %f/sec\n",
    -	XAVG(select_fds));
    +                      XAVG(select_fds));
         storeAppendPrintf(sentry, "average_select_fd_period = %f/fd\n",
    -	f->select_fds > l->select_fds ?
    -	(f->select_time - l->select_time) / (f->select_fds - l->select_fds)
    -	: 0.0);
    +                      f->select_fds > l->select_fds ?
    +                      (f->select_time - l->select_time) / (f->select_fds - l->select_fds)
    +                      : 0.0);
         x = statHistDeltaMedian(&l->select_fds_hist, &f->select_fds_hist);
         storeAppendPrintf(sentry, "median_select_fds = %f\n", x);
         storeAppendPrintf(sentry, "swap.outs = %f/sec\n",
    -	XAVG(swap.outs));
    +                      XAVG(swap.outs));
         storeAppendPrintf(sentry, "swap.ins = %f/sec\n",
    -	XAVG(swap.ins));
    +                      XAVG(swap.ins));
         storeAppendPrintf(sentry, "swap.files_cleaned = %f/sec\n",
    -	XAVG(swap.files_cleaned));
    +                      XAVG(swap.files_cleaned));
         storeAppendPrintf(sentry, "aborted_requests = %f/sec\n",
    -	XAVG(aborted_requests));
    +                      XAVG(aborted_requests));
     
     #if USE_POLL
    +
         storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", XAVG(syscalls.polls));
     #endif
     #if USE_SELECT
    +
         storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", XAVG(syscalls.selects));
     #endif
    +
         storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", XAVG(syscalls.disk.opens));
         storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", XAVG(syscalls.disk.closes));
         storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", XAVG(syscalls.disk.reads));
    @@ -791,63 +935,88 @@ statInit(void)
         int i;
         debug(18, 5) ("statInit: Initializing...\n");
         CBDATA_INIT_TYPE(StatObjectsState);
    +
         for (i = 0; i < N_COUNT_HIST; i++)
    -	statCountersInit(&CountHist[i]);
    +        statCountersInit(&CountHist[i]);
    +
         for (i = 0; i < N_COUNT_HOUR_HIST; i++)
    -	statCountersInit(&CountHourHist[i]);
    +        statCountersInit(&CountHourHist[i]);
    +
         statCountersInit(&statCounter);
    +
         eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
    +
         cachemgrRegister("info",
    -	"General Runtime Information",
    -	info_get, 0, 1);
    +                     "General Runtime Information",
    +                     info_get, 0, 1);
    +
         cachemgrRegister("filedescriptors",
    -	"Process Filedescriptor Allocation",
    -	fde::DumpStats, 0, 1);
    +                     "Process Filedescriptor Allocation",
    +                     fde::DumpStats, 0, 1);
    +
         cachemgrRegister("objects",
    -	"All Cache Objects",
    -	stat_objects_get, 0, 0);
    +                     "All Cache Objects",
    +                     stat_objects_get, 0, 0);
    +
         cachemgrRegister("vm_objects",
    -	"In-Memory and In-Transit Objects",
    -	stat_vmobjects_get, 0, 0);
    +                     "In-Memory and In-Transit Objects",
    +                     stat_vmobjects_get, 0, 0);
    +
     #if DEBUG_OPENFD
    +
         cachemgrRegister("openfd_objects",
    -	"Objects with Swapout files open",
    -	statOpenfdObj, 0, 0);
    +                     "Objects with Swapout files open",
    +                     statOpenfdObj, 0, 0);
    +
     #endif
    +
         cachemgrRegister("io",
    -	"Server-side network read() size histograms",
    -	stat_io_get, 0, 1);
    +                     "Server-side network read() size histograms",
    +                     stat_io_get, 0, 1);
    +
         cachemgrRegister("counters",
    -	"Traffic and Resource Counters",
    -	statCountersDump, 0, 1);
    +                     "Traffic and Resource Counters",
    +                     statCountersDump, 0, 1);
    +
         cachemgrRegister("peer_select",
    -	"Peer Selection Algorithms",
    -	statPeerSelect, 0, 1);
    +                     "Peer Selection Algorithms",
    +                     statPeerSelect, 0, 1);
    +
         cachemgrRegister("digest_stats",
    -	"Cache Digest and ICP blob",
    -	statDigestBlob, 0, 1);
    +                     "Cache Digest and ICP blob",
    +                     statDigestBlob, 0, 1);
    +
         cachemgrRegister("5min",
    -	"5 Minute Average of Counters",
    -	statAvg5min, 0, 1);
    +                     "5 Minute Average of Counters",
    +                     statAvg5min, 0, 1);
    +
         cachemgrRegister("60min",
    -	"60 Minute Average of Counters",
    -	statAvg60min, 0, 1);
    +                     "60 Minute Average of Counters",
    +                     statAvg60min, 0, 1);
    +
         cachemgrRegister("utilization",
    -	"Cache Utilization",
    -	statUtilization, 0, 1);
    +                     "Cache Utilization",
    +                     statUtilization, 0, 1);
    +
     #if STAT_GRAPHS
    +
         cachemgrRegister("graph_variables",
    -	"Display cache metrics graphically",
    -	statGraphDump, 0, 1);
    +                     "Display cache metrics graphically",
    +                     statGraphDump, 0, 1);
    +
     #endif
    +
         cachemgrRegister("histograms",
    -	"Full Histogram Counts",
    -	statCountersHistograms, 0, 1);
    +                     "Full Histogram Counts",
    +                     statCountersHistograms, 0, 1);
    +
         ClientActiveRequests.head = NULL;
    +
         ClientActiveRequests.tail = NULL;
    +
         cachemgrRegister("active_requests",
    -	"Client-side Active Requests",
    -	statClientRequests, 0, 1);
    +                     "Client-side Active Requests",
    +                     statClientRequests, 0, 1);
     }
     
     static void
    @@ -856,6 +1025,7 @@ statAvgTick(void *notused)
         StatCounters *t = &CountHist[0];
         StatCounters *p = &CountHist[1];
         StatCounters *c = &statCounter;
    +
         struct rusage rusage;
         eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
         squid_getrusage(&rusage);
    @@ -869,40 +1039,49 @@ statAvgTick(void *notused)
         NCountHist++;
     
         if ((NCountHist % COUNT_INTERVAL) == 0) {
    -	/* we have an hours worth of readings.  store previous hour */
    -	StatCounters *t = &CountHourHist[0];
    -	StatCounters *p = &CountHourHist[1];
    -	StatCounters *c = &CountHist[N_COUNT_HIST - 1];
    -	statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
    -	xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
    -	statCountersCopy(t, c);
    -	NCountHourHist++;
    +        /* we have an hours worth of readings.  store previous hour */
    +        StatCounters *t = &CountHourHist[0];
    +        StatCounters *p = &CountHourHist[1];
    +        StatCounters *c = &CountHist[N_COUNT_HIST - 1];
    +        statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
    +        xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
    +        statCountersCopy(t, c);
    +        NCountHourHist++;
         }
    +
         if (Config.warnings.high_rptm > 0) {
    -	int i = (int) statMedianSvc(20, MEDIAN_HTTP);
    -	if (Config.warnings.high_rptm < i)
    -	    debug(18, 0) ("WARNING: Median response time is %d milliseconds\n", i);
    +        int i = (int) statMedianSvc(20, MEDIAN_HTTP);
    +
    +        if (Config.warnings.high_rptm < i)
    +            debug(18, 0) ("WARNING: Median response time is %d milliseconds\n", i);
         }
    +
         if (Config.warnings.high_pf) {
    -	int i = (CountHist[0].page_faults - CountHist[1].page_faults);
    -	double dt = tvSubDsec(CountHist[0].timestamp, CountHist[1].timestamp);
    -	if (i > 0 && dt > 0.0) {
    -	    i /= (int) dt;
    -	    if (Config.warnings.high_pf < i)
    -		debug(18, 0) ("WARNING: Page faults occuring at %d/sec\n", i);
    -	}
    +        int i = (CountHist[0].page_faults - CountHist[1].page_faults);
    +        double dt = tvSubDsec(CountHist[0].timestamp, CountHist[1].timestamp);
    +
    +        if (i > 0 && dt > 0.0) {
    +            i /= (int) dt;
    +
    +            if (Config.warnings.high_pf < i)
    +                debug(18, 0) ("WARNING: Page faults occuring at %d/sec\n", i);
    +        }
         }
    +
         if (Config.warnings.high_memory) {
    -	size_t i = 0;
    +        size_t i = 0;
     #if HAVE_MSTATS && HAVE_GNUMALLOC_H
    -	struct mstats ms = mstats();
    -	i = ms.bytes_total;
    +
    +        struct mstats ms = mstats();
    +        i = ms.bytes_total;
     #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
    -	struct mallinfo mp = mallinfo();
    -	i = mp.arena;
    +
    +        struct mallinfo mp = mallinfo();
    +        i = mp.arena;
     #endif
    -	if (Config.warnings.high_memory < i)
    -	    debug(18, 0) ("WARNING: Memory usage at %lu MB\n", (unsigned long int)(i >> 20));
    +
    +        if (Config.warnings.high_memory < i)
    +            debug(18, 0) ("WARNING: Memory usage at %lu MB\n", (unsigned long int)(i >> 20));
         }
     }
     
    @@ -1019,140 +1198,144 @@ static void
     statCountersDump(StoreEntry * sentry)
     {
         StatCounters *f = &statCounter;
    +
         struct rusage rusage;
         squid_getrusage(&rusage);
         f->page_faults = rusage_pagefaults(&rusage);
         f->cputime = rusage_cputime(&rusage);
     
         storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
    -	(int) f->timestamp.tv_sec,
    -	(int) f->timestamp.tv_usec,
    -	mkrfc1123(f->timestamp.tv_sec));
    +                      (int) f->timestamp.tv_sec,
    +                      (int) f->timestamp.tv_usec,
    +                      mkrfc1123(f->timestamp.tv_sec));
         storeAppendPrintf(sentry, "client_http.requests = %d\n",
    -	f->client_http.requests);
    +                      f->client_http.requests);
         storeAppendPrintf(sentry, "client_http.hits = %d\n",
    -	f->client_http.hits);
    +                      f->client_http.hits);
         storeAppendPrintf(sentry, "client_http.errors = %d\n",
    -	f->client_http.errors);
    +                      f->client_http.errors);
         storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n",
    -	(int) f->client_http.kbytes_in.kb);
    +                      (int) f->client_http.kbytes_in.kb);
         storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n",
    -	(int) f->client_http.kbytes_out.kb);
    +                      (int) f->client_http.kbytes_out.kb);
         storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %d\n",
    -	(int) f->client_http.hit_kbytes_out.kb);
    +                      (int) f->client_http.hit_kbytes_out.kb);
     
         storeAppendPrintf(sentry, "server.all.requests = %d\n",
    -	(int) f->server.all.requests);
    +                      (int) f->server.all.requests);
         storeAppendPrintf(sentry, "server.all.errors = %d\n",
    -	(int) f->server.all.errors);
    +                      (int) f->server.all.errors);
         storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n",
    -	(int) f->server.all.kbytes_in.kb);
    +                      (int) f->server.all.kbytes_in.kb);
         storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n",
    -	(int) f->server.all.kbytes_out.kb);
    +                      (int) f->server.all.kbytes_out.kb);
     
         storeAppendPrintf(sentry, "server.http.requests = %d\n",
    -	(int) f->server.http.requests);
    +                      (int) f->server.http.requests);
         storeAppendPrintf(sentry, "server.http.errors = %d\n",
    -	(int) f->server.http.errors);
    +                      (int) f->server.http.errors);
         storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n",
    -	(int) f->server.http.kbytes_in.kb);
    +                      (int) f->server.http.kbytes_in.kb);
         storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n",
    -	(int) f->server.http.kbytes_out.kb);
    +                      (int) f->server.http.kbytes_out.kb);
     
         storeAppendPrintf(sentry, "server.ftp.requests = %d\n",
    -	(int) f->server.ftp.requests);
    +                      (int) f->server.ftp.requests);
         storeAppendPrintf(sentry, "server.ftp.errors = %d\n",
    -	(int) f->server.ftp.errors);
    +                      (int) f->server.ftp.errors);
         storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n",
    -	(int) f->server.ftp.kbytes_in.kb);
    +                      (int) f->server.ftp.kbytes_in.kb);
         storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n",
    -	(int) f->server.ftp.kbytes_out.kb);
    +                      (int) f->server.ftp.kbytes_out.kb);
     
         storeAppendPrintf(sentry, "server.other.requests = %d\n",
    -	(int) f->server.other.requests);
    +                      (int) f->server.other.requests);
         storeAppendPrintf(sentry, "server.other.errors = %d\n",
    -	(int) f->server.other.errors);
    +                      (int) f->server.other.errors);
         storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n",
    -	(int) f->server.other.kbytes_in.kb);
    +                      (int) f->server.other.kbytes_in.kb);
         storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
    -	(int) f->server.other.kbytes_out.kb);
    +                      (int) f->server.other.kbytes_out.kb);
     
         storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
    -	f->icp.pkts_sent);
    +                      f->icp.pkts_sent);
         storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
    -	f->icp.pkts_recv);
    +                      f->icp.pkts_recv);
         storeAppendPrintf(sentry, "icp.queries_sent = %d\n",
    -	f->icp.queries_sent);
    +                      f->icp.queries_sent);
         storeAppendPrintf(sentry, "icp.replies_sent = %d\n",
    -	f->icp.replies_sent);
    +                      f->icp.replies_sent);
         storeAppendPrintf(sentry, "icp.queries_recv = %d\n",
    -	f->icp.queries_recv);
    +                      f->icp.queries_recv);
         storeAppendPrintf(sentry, "icp.replies_recv = %d\n",
    -	f->icp.replies_recv);
    +                      f->icp.replies_recv);
         storeAppendPrintf(sentry, "icp.query_timeouts = %d\n",
    -	f->icp.query_timeouts);
    +                      f->icp.query_timeouts);
         storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
    -	f->icp.replies_queued);
    +                      f->icp.replies_queued);
         storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
    -	(int) f->icp.kbytes_sent.kb);
    +                      (int) f->icp.kbytes_sent.kb);
         storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
    -	(int) f->icp.kbytes_recv.kb);
    +                      (int) f->icp.kbytes_recv.kb);
         storeAppendPrintf(sentry, "icp.q_kbytes_sent = %d\n",
    -	(int) f->icp.q_kbytes_sent.kb);
    +                      (int) f->icp.q_kbytes_sent.kb);
         storeAppendPrintf(sentry, "icp.r_kbytes_sent = %d\n",
    -	(int) f->icp.r_kbytes_sent.kb);
    +                      (int) f->icp.r_kbytes_sent.kb);
         storeAppendPrintf(sentry, "icp.q_kbytes_recv = %d\n",
    -	(int) f->icp.q_kbytes_recv.kb);
    +                      (int) f->icp.q_kbytes_recv.kb);
         storeAppendPrintf(sentry, "icp.r_kbytes_recv = %d\n",
    -	(int) f->icp.r_kbytes_recv.kb);
    +                      (int) f->icp.r_kbytes_recv.kb);
     
     #if USE_CACHE_DIGESTS
    +
         storeAppendPrintf(sentry, "icp.times_used = %d\n",
    -	f->icp.times_used);
    +                      f->icp.times_used);
         storeAppendPrintf(sentry, "cd.times_used = %d\n",
    -	f->cd.times_used);
    +                      f->cd.times_used);
         storeAppendPrintf(sentry, "cd.msgs_sent = %d\n",
    -	f->cd.msgs_sent);
    +                      f->cd.msgs_sent);
         storeAppendPrintf(sentry, "cd.msgs_recv = %d\n",
    -	f->cd.msgs_recv);
    +                      f->cd.msgs_recv);
         storeAppendPrintf(sentry, "cd.memory = %d\n",
    -	(int) f->cd.memory.kb);
    +                      (int) f->cd.memory.kb);
         storeAppendPrintf(sentry, "cd.local_memory = %d\n",
    -	(int) (store_digest ? store_digest->mask_size / 1024 : 0));
    +                      (int) (store_digest ? store_digest->mask_size / 1024 : 0));
         storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n",
    -	(int) f->cd.kbytes_sent.kb);
    +                      (int) f->cd.kbytes_sent.kb);
         storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n",
    -	(int) f->cd.kbytes_recv.kb);
    +                      (int) f->cd.kbytes_recv.kb);
     #endif
     
         storeAppendPrintf(sentry, "unlink.requests = %d\n",
    -	f->unlink.requests);
    +                      f->unlink.requests);
         storeAppendPrintf(sentry, "page_faults = %d\n",
    -	f->page_faults);
    +                      f->page_faults);
         storeAppendPrintf(sentry, "select_loops = %d\n",
    -	f->select_loops);
    +                      f->select_loops);
         storeAppendPrintf(sentry, "cpu_time = %f\n",
    -	f->cputime);
    +                      f->cputime);
         storeAppendPrintf(sentry, "wall_time = %f\n",
    -	tvSubDsec(f->timestamp, current_time));
    +                      tvSubDsec(f->timestamp, current_time));
         storeAppendPrintf(sentry, "swap.outs = %d\n",
    -	f->swap.outs);
    +                      f->swap.outs);
         storeAppendPrintf(sentry, "swap.ins = %d\n",
    -	f->swap.ins);
    +                      f->swap.ins);
         storeAppendPrintf(sentry, "swap.files_cleaned = %d\n",
    -	f->swap.files_cleaned);
    +                      f->swap.files_cleaned);
         storeAppendPrintf(sentry, "aborted_requests = %d\n",
    -	f->aborted_requests);
    +                      f->aborted_requests);
     }
     
     void
     statFreeMemory(void)
     {
         int i;
    +
         for (i = 0; i < N_COUNT_HIST; i++)
    -	statCountersClean(&CountHist[i]);
    +        statCountersClean(&CountHist[i]);
    +
         for (i = 0; i < N_COUNT_HOUR_HIST; i++)
    -	statCountersClean(&CountHourHist[i]);
    +        statCountersClean(&CountHourHist[i]);
     }
     
     static void
    @@ -1167,22 +1350,25 @@ statPeerSelect(StoreEntry * sentry)
         cacheDigestGuessStatsReport(&f->cd.guess, sentry, "all peers");
         /* per-peer */
         storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
    +
         for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
    -	if (peer->digest)
    -	    peerDigestStatsReport(peer->digest, sentry);
    -	else
    -	    storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
    -	storeAppendPrintf(sentry, "\n");
    +        if (peer->digest)
    +            peerDigestStatsReport(peer->digest, sentry);
    +        else
    +            storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
    +
    +        storeAppendPrintf(sentry, "\n");
         }
     
         storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
         storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
    -	f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
    +                      f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
         storeAppendPrintf(sentry, "Icp:          %7d (%3d%%)\n",
    -	f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
    +                      f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
         storeAppendPrintf(sentry, "Total:        %7d (%3d%%)\n",
    -	tot_used, xpercentInt(tot_used, tot_used));
    +                      tot_used, xpercentInt(tot_used, tot_used));
     #else
    +
         storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
     #endif
     }
    @@ -1221,38 +1407,53 @@ statMedianSvc(int interval, int which)
         StatCounters *l;
         double x;
         assert(interval > 0);
    +
         if (interval > N_COUNT_HIST - 1)
    -	interval = N_COUNT_HIST - 1;
    +        interval = N_COUNT_HIST - 1;
    +
         f = &CountHist[0];
    +
         l = &CountHist[interval];
    +
         assert(f);
    +
         assert(l);
    +
         switch (which) {
    +
         case MEDIAN_HTTP:
    -	x = statHistDeltaMedian(&l->client_http.all_svc_time, &f->client_http.all_svc_time);
    -	break;
    +        x = statHistDeltaMedian(&l->client_http.all_svc_time, &f->client_http.all_svc_time);
    +        break;
    +
         case MEDIAN_HIT:
    -	x = statHistDeltaMedian(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time);
    -	break;
    +        x = statHistDeltaMedian(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time);
    +        break;
    +
         case MEDIAN_MISS:
    -	x = statHistDeltaMedian(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time);
    -	break;
    +        x = statHistDeltaMedian(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time);
    +        break;
    +
         case MEDIAN_NM:
    -	x = statHistDeltaMedian(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time);
    -	break;
    +        x = statHistDeltaMedian(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time);
    +        break;
    +
         case MEDIAN_NH:
    -	x = statHistDeltaMedian(&l->client_http.nh_svc_time, &f->client_http.nh_svc_time);
    -	break;
    +        x = statHistDeltaMedian(&l->client_http.nh_svc_time, &f->client_http.nh_svc_time);
    +        break;
    +
         case MEDIAN_ICP_QUERY:
    -	x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
    -	break;
    +        x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
    +        break;
    +
         case MEDIAN_DNS:
    -	x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
    -	break;
    +        x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
    +        break;
    +
         default:
    -	debug(49, 5) ("get_median_val: unknown type.\n");
    -	x = 0;
    +        debug(49, 5) ("get_median_val: unknown type.\n");
    +        x = 0;
         }
    +
         return x;
     }
     
    @@ -1286,45 +1487,46 @@ statCPUUsage(int minutes)
     {
         assert(minutes < N_COUNT_HIST);
         return dpercent(CountHist[0].cputime - CountHist[minutes].cputime,
    -	tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
    +                    tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
     }
     
     extern double
    -statRequestHitRatio(int minutes)
    +    statRequestHitRatio(int minutes)
     {
         assert(minutes < N_COUNT_HIST);
         return dpercent(CountHist[0].client_http.hits -
    -	CountHist[minutes].client_http.hits,
    -	CountHist[0].client_http.requests -
    -	CountHist[minutes].client_http.requests);
    +                    CountHist[minutes].client_http.hits,
    +                    CountHist[0].client_http.requests -
    +                    CountHist[minutes].client_http.requests);
     }
     
     extern double
    -statRequestHitMemoryRatio(int minutes)
    +    statRequestHitMemoryRatio(int minutes)
     {
         assert(minutes < N_COUNT_HIST);
         return dpercent(CountHist[0].client_http.mem_hits -
    -	CountHist[minutes].client_http.mem_hits,
    -	CountHist[0].client_http.hits -
    -	CountHist[minutes].client_http.hits);
    +                    CountHist[minutes].client_http.mem_hits,
    +                    CountHist[0].client_http.hits -
    +                    CountHist[minutes].client_http.hits);
     }
     
     extern double
    -statRequestHitDiskRatio(int minutes)
    +    statRequestHitDiskRatio(int minutes)
     {
         assert(minutes < N_COUNT_HIST);
         return dpercent(CountHist[0].client_http.disk_hits -
    -	CountHist[minutes].client_http.disk_hits,
    -	CountHist[0].client_http.hits -
    -	CountHist[minutes].client_http.hits);
    +                    CountHist[minutes].client_http.disk_hits,
    +                    CountHist[0].client_http.hits -
    +                    CountHist[minutes].client_http.hits);
     }
     
     extern double
    -statByteHitRatio(int minutes)
    +    statByteHitRatio(int minutes)
     {
         size_t s;
         size_t c;
     #if USE_CACHE_DIGESTS
    +
         size_t cd;
     #endif
         /* size_t might be unsigned */
    @@ -1340,14 +1542,18 @@ statByteHitRatio(int minutes)
          * digest bytes out before calculating the byte hit ratio.
          */
         cd = CountHist[0].cd.kbytes_recv.kb - CountHist[minutes].cd.kbytes_recv.kb;
    +
         if (s < cd)
    -	debug(18, 1) ("STRANGE: srv_kbytes=%d, cd_kbytes=%d\n", s, cd);
    +        debug(18, 1) ("STRANGE: srv_kbytes=%d, cd_kbytes=%d\n", s, cd);
    +
         s -= cd;
    +
     #endif
    +
         if (c > s)
    -	return dpercent(c - s, c);
    +        return dpercent(c - s, c);
         else
    -	return (-1.0 * dpercent(s - c, c));
    +        return (-1.0 * dpercent(s - c, c));
     }
     
     static void
    @@ -1358,43 +1564,46 @@ statClientRequests(StoreEntry * s)
         ConnStateData *conn;
         StoreEntry *e;
         int fd;
    +
         for (i = ClientActiveRequests.head; i; i = i->next) {
    -	http = static_cast(i->data);
    -	assert(http);
    -	conn = http->conn;
    -	storeAppendPrintf(s, "Connection: %p\n", conn);
    -	if (conn) {
    -	    fd = conn->fd;
    -	    storeAppendPrintf(s, "\tFD %d, read %d, wrote %d\n", fd,
    -		fd_table[fd].bytes_read, fd_table[fd].bytes_written);
    -	    storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
    -	    storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n",
    -		conn->in.buf, (long int) conn->in.notYetUsed, (long int) conn->in.allocatedSize);
    -	    storeAppendPrintf(s, "\tpeer: %s:%d\n",
    -		inet_ntoa(conn->peer.sin_addr),
    -		ntohs(conn->peer.sin_port));
    -	    storeAppendPrintf(s, "\tme: %s:%d\n",
    -		inet_ntoa(conn->me.sin_addr),
    -		ntohs(conn->me.sin_port));
    -	    storeAppendPrintf(s, "\tnrequests: %d\n",
    -		conn->nrequests);
    -	    storeAppendPrintf(s, "\tdefer: n %d, until %ld\n",
    -		conn->defer.n, (long int) conn->defer.until);
    -	}
    -	storeAppendPrintf(s, "uri %s\n", http->uri);
    -	storeAppendPrintf(s, "logType %s\n", log_tags[http->logType]);
    -	storeAppendPrintf(s, "out.offset %ld, out.size %lu\n",
    -	    (long int) http->out.offset, (unsigned long int) http->out.size);
    -	storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
    -	e = http->entry;
    -	storeAppendPrintf(s, "entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
    -	e = http->old_entry;
    -	storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
    -	storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n",
    -	    (long int) http->start.tv_sec,
    -	    (int) http->start.tv_usec,
    -	    tvSubDsec(http->start, current_time));
    -	storeAppendPrintf(s, "\n");
    +        http = static_cast(i->data);
    +        assert(http);
    +        conn = http->conn;
    +        storeAppendPrintf(s, "Connection: %p\n", conn);
    +
    +        if (conn) {
    +            fd = conn->fd;
    +            storeAppendPrintf(s, "\tFD %d, read %d, wrote %d\n", fd,
    +                              fd_table[fd].bytes_read, fd_table[fd].bytes_written);
    +            storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
    +            storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n",
    +                              conn->in.buf, (long int) conn->in.notYetUsed, (long int) conn->in.allocatedSize);
    +            storeAppendPrintf(s, "\tpeer: %s:%d\n",
    +                              inet_ntoa(conn->peer.sin_addr),
    +                              ntohs(conn->peer.sin_port));
    +            storeAppendPrintf(s, "\tme: %s:%d\n",
    +                              inet_ntoa(conn->me.sin_addr),
    +                              ntohs(conn->me.sin_port));
    +            storeAppendPrintf(s, "\tnrequests: %d\n",
    +                              conn->nrequests);
    +            storeAppendPrintf(s, "\tdefer: n %d, until %ld\n",
    +                              conn->defer.n, (long int) conn->defer.until);
    +        }
    +
    +        storeAppendPrintf(s, "uri %s\n", http->uri);
    +        storeAppendPrintf(s, "logType %s\n", log_tags[http->logType]);
    +        storeAppendPrintf(s, "out.offset %ld, out.size %lu\n",
    +                          (long int) http->out.offset, (unsigned long int) http->out.size);
    +        storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
    +        e = http->entry;
    +        storeAppendPrintf(s, "entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
    +        e = http->old_entry;
    +        storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
    +        storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n",
    +                          (long int) http->start.tv_sec,
    +                          (int) http->start.tv_usec,
    +                          tvSubDsec(http->start, current_time));
    +        storeAppendPrintf(s, "\n");
         }
     }
     
    diff --git a/src/stmem.cc b/src/stmem.cc
    index 4b1b7f584c..fd26673bca 100644
    --- a/src/stmem.cc
    +++ b/src/stmem.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: stmem.cc,v 1.75 2003/02/08 17:43:18 hno Exp $
    + * $Id: stmem.cc,v 1.76 2003/02/21 22:50:11 robertc Exp $
      *
      * DEBUG: section 19    Store Memory Primitives
      * AUTHOR: Harvest Derived
    @@ -42,7 +42,8 @@ int
     mem_hdr::lowestOffset () const
     {
         if (head)
    -	return head->nodeBuffer.offset;
    +        return head->nodeBuffer.offset;
    +
         return 0;
     }
     
    @@ -50,9 +51,12 @@ off_t
     mem_hdr::endOffset () const
     {
         off_t result = 0;
    +
         if (tail)
    -	result = tail->nodeBuffer.offset + tail->nodeBuffer.length;
    +        result = tail->nodeBuffer.offset + tail->nodeBuffer.length;
    +
         assert (result == inmem_hi);
    +
         return result;
     }
     
    @@ -60,8 +64,10 @@ void
     mem_hdr::freeContent()
     {
         while (head)
    -	unlinkHead();
    +        unlinkHead();
    +
         head = tail = NULL;
    +
         inmem_hi = 0;
     }
     
    @@ -79,14 +85,17 @@ int
     mem_hdr::freeDataUpto(int target_offset)
     {
         /* keep the last one to avoid change to other part of code */
    +
         while (head && head != tail &&
    -	((lowestOffset() + head->nodeBuffer.length) <= (size_t)target_offset))
    -	unlinkHead ();
    +            ((lowestOffset() + head->nodeBuffer.length) <= (size_t)target_offset))
    +        unlinkHead ();
    +
         assert (lowestOffset () <= target_offset);
    +
         return lowestOffset ();
     }
     
    -int 
    +int
     mem_hdr::appendToNode(mem_node *aNode, const char *data, int maxLength)
     {
         size_t result = writeAvailable (aNode, aNode->nodeBuffer.offset + aNode->nodeBuffer.length ,maxLength, data);
    @@ -100,7 +109,7 @@ mem_hdr::writeAvailable(mem_node *aNode, size_t location, size_t amount, char co
         assert (location == aNode->nodeBuffer.offset + aNode->nodeBuffer.length);
         /* And we are not at the end of the node */
         assert (aNode->canAccept (location));
    -    
    +
         /* these two can go I think */
         size_t copyOffset = location - aNode->nodeBuffer.offset;
         assert (copyOffset == aNode->nodeBuffer.length);
    @@ -109,11 +118,13 @@ mem_hdr::writeAvailable(mem_node *aNode, size_t location, size_t amount, char co
         xmemcpy(aNode->nodeBuffer.data + aNode->nodeBuffer.length, source, copyLen);
     
         if (inmem_hi <= (off_t) location)
    -	inmem_hi = location + copyLen;
    -    
    +        inmem_hi = location + copyLen;
    +
         /* Adjust the ptr and len according to what was deposited in the page */
         aNode->nodeBuffer.length += copyLen;
    +
         mem_node::store_mem_size += copyLen;
    +
         return copyLen;
     }
     
    @@ -121,22 +132,25 @@ void
     mem_hdr::appendNode (mem_node *aNode)
     {
         assert (aNode->next == NULL);
    +
         if (!head) {
    -	/* The chain is empty */
    -	head = tail = aNode;
    +        /* The chain is empty */
    +        head = tail = aNode;
         } else {
    -	mem_node *pointer = getHighestBlockBeforeLocation(aNode->nodeBuffer.offset);
    -	if (!pointer) {
    -	    /* prepend to list */
    -	    aNode->next = head;
    -	    head = aNode->next;
    -	} else {
    -	    /* Append it to existing chain */
    -	    aNode->next = pointer->next;
    -	    pointer->next = aNode;
    -	    if (tail == pointer)
    -		tail = aNode;
    -	}
    +        mem_node *pointer = getHighestBlockBeforeLocation(aNode->nodeBuffer.offset);
    +
    +        if (!pointer) {
    +            /* prepend to list */
    +            aNode->next = head;
    +            head = aNode->next;
    +        } else {
    +            /* Append it to existing chain */
    +            aNode->next = pointer->next;
    +            pointer->next = aNode;
    +
    +            if (tail == pointer)
    +                tail = aNode;
    +        }
         }
     }
     
    @@ -144,11 +158,13 @@ void
     mem_hdr::makeAppendSpace()
     {
         if (!head) {
    -	appendNode (new mem_node(0));
    -	return;
    +        appendNode (new mem_node(0));
    +        return;
         }
    +
         if (!tail->space())
    -	appendNode (new mem_node (endOffset()));
    +        appendNode (new mem_node (endOffset()));
    +
         assert (tail->space());
     }
     
    @@ -156,14 +172,15 @@ void
     mem_hdr::internalAppend(const char *data, int len)
     {
         debug(19, 6) ("memInternalAppend: len %d\n", len);
    +
         while (len > 0) {
    -	makeAppendSpace();
    +        makeAppendSpace();
     
    -	int copied = appendToNode (tail, data, len);
    -	assert (copied);
    -	
    -	len -= copied;
    -	data += copied;
    +        int copied = appendToNode (tail, data, len);
    +        assert (copied);
    +
    +        len -= copied;
    +        data += copied;
         }
     }
     
    @@ -172,19 +189,24 @@ mem_hdr::getHighestBlockBeforeLocation (size_t location) const
     {
         mem_node *result = head;
         mem_node *prevResult = NULL;
    +
         while (result && result->end() <= location) {
    -	if (!result->next)
    -	    return result;
    -	prevResult = result;
    -	result = result->next;
    -	if (result->contains(location))
    -	    return result;
    +        if (!result->next)
    +            return result;
    +
    +        prevResult = result;
    +
    +        result = result->next;
    +
    +        if (result->contains(location))
    +            return result;
         }
    +
         /* the if here is so we catch 0 offset requests */
         if (result && result->contains(location))
    -	return result;
    -    else 
    -	return prevResult;
    +        return result;
    +    else
    +        return prevResult;
     }
     
     /* returns a mem_node that contains location..
    @@ -194,8 +216,10 @@ mem_node *
     mem_hdr::getBlockContainingLocation (size_t location) const
     {
         mem_node *result = getHighestBlockBeforeLocation(location);
    +
         if (!result || !result->contains(location))
    -	return NULL;
    +        return NULL;
    +
         return result;
     }
     
    @@ -203,17 +227,22 @@ size_t
     mem_hdr::copyAvailable(mem_node *aNode, size_t location, size_t amount, char *target) const
     {
         if (aNode->nodeBuffer.offset > (off_t) location)
    -	return 0;
    +        return 0;
    +
         assert (aNode->nodeBuffer.offset <= (off_t) location);
    +
         assert (aNode->end() > location);
    +
         size_t copyOffset = location - aNode->nodeBuffer.offset;
    +
         size_t copyLen = XMIN (amount, aNode->nodeBuffer.length - copyOffset);
     
         xmemcpy(target, aNode->nodeBuffer.data + copyOffset, copyLen);
    +
         return copyLen;
     }
     
    -/* FIXME: how do we deal with sparse results - 
    +/* FIXME: how do we deal with sparse results -
      * where we have (say)
      * 0-500 and 1000-1500, but are asked for 
      * 0-2000
    @@ -225,40 +254,48 @@ mem_hdr::copy(off_t offset, char *buf, size_t size) const
     {
     
         debug(19, 6) ("memCopy: offset %ld: size %u\n", (long int) offset, size);
    +
         if (head == NULL)
    -	return 0;
    +        return 0;
    +
         /* RC: the next assert is nearly useless */
         assert(size > 0);
     
         /* Seek our way into store */
         mem_node *p = getBlockContainingLocation((size_t)offset);
    +
         if (!p) {
    -	debug(19, 1) ("memCopy: could not find offset %u in memory.\n", (size_t) offset);
    -	/* we shouldn't ever ask for absent offsets */
    -	assert (0);
    -	return 0;
    +        debug(19, 1) ("memCopy: could not find offset %u in memory.\n", (size_t) offset);
    +        /* we shouldn't ever ask for absent offsets */
    +        assert (0);
    +        return 0;
         }
    -    
    +
         size_t bytes_to_go = size;
         char *ptr_to_buf = buf;
         off_t location = offset;
    -    
    +
         /* Start copying begining with this block until
          * we're satiated */
     
         while (p && bytes_to_go > 0) {
    -	size_t bytes_to_copy = copyAvailable (p, 
    -	    location, bytes_to_go, ptr_to_buf);
    -
    -	/* hit a sparse patch */
    -	if (bytes_to_copy == 0)
    -	    return size - bytes_to_go;
    -	
    -	location += bytes_to_copy;
    -	ptr_to_buf += bytes_to_copy;
    -	bytes_to_go -= bytes_to_copy;
    -	p = p->next;
    +        size_t bytes_to_copy = copyAvailable (p,
    +                                              location, bytes_to_go, ptr_to_buf);
    +
    +        /* hit a sparse patch */
    +
    +        if (bytes_to_copy == 0)
    +            return size - bytes_to_go;
    +
    +        location += bytes_to_copy;
    +
    +        ptr_to_buf += bytes_to_copy;
    +
    +        bytes_to_go -= bytes_to_copy;
    +
    +        p = p->next;
         }
    +
         return size - bytes_to_go;
     }
     
    @@ -266,11 +303,14 @@ bool
     mem_hdr::hasContigousContentRange(size_t start, size_t end) const
     {
         size_t currentStart = start;
    +
         while (mem_node *curr = getBlockContainingLocation(currentStart)) {
    -	currentStart = curr->end();
    -	if (currentStart >= end)
    -	    return true;
    +        currentStart = curr->end();
    +
    +        if (currentStart >= end)
    +            return true;
         }
    +
         return false;
     }
     
    @@ -279,15 +319,20 @@ mem_hdr::unionNotEmpty(StoreIOBuffer const &candidate)
     {
         mem_node *low = getHighestBlockBeforeLocation(candidate.offset);
         assert (candidate.offset >= 0);
    +
         if (low && low->end() > (size_t) candidate.offset)
    -	return true;
    +        return true;
    +
         mem_node *high = getHighestBlockBeforeLocation(candidate.offset + candidate.length);
    +
         /* trivial case - we are writing completely beyond the end of the current object */
         if (low == high)
    -	return false;
    +        return false;
    +
         if (high && high->start() < candidate.offset + candidate.length &&
    -	!high->end() > candidate.offset)
    -	return true;
    +            !high->end() > candidate.offset)
    +        return true;
    +
         return false;
     }
     
    @@ -295,26 +340,30 @@ mem_node *
     mem_hdr::nodeToRecieve(off_t offset)
     {
         /* case 1: Nothing in memory */
    +
         if (!head) {
    -	appendNode (new mem_node(offset));
    -	return head;
    +        appendNode (new mem_node(offset));
    +        return head;
         }
     
         /* case 2: location fits within an extant node */
         mem_node *candidate = getHighestBlockBeforeLocation(offset);
    +
         /* case 2: no nodes before it */
         if (!candidate) {
    -	candidate = new mem_node(offset);
    -	appendNode (candidate);
    -	assert (candidate->canAccept(offset));
    +        candidate = new mem_node(offset);
    +        appendNode (candidate);
    +        assert (candidate->canAccept(offset));
         }
     
         if (candidate->canAccept(offset))
    -	return candidate;
    +        return candidate;
     
         /* candidate can't accept, so we need a new node */
         candidate = new mem_node(offset);
    +
         appendNode (candidate);
    +
         /* simpler to write than a indented if */
         return candidate;
     }
    @@ -323,12 +372,12 @@ mem_hdr::nodeToRecieve(off_t offset)
     bool
     mem_hdr::write (StoreIOBuffer const &writeBuffer)
     {
    -//    mem_node *tempNode;
    +    //    mem_node *tempNode;
         debug(19, 6) ("mem_hdr::write: offset %lu len %ld, object end %lu\n", (unsigned long)writeBuffer.offset, (long)writeBuffer.length, (unsigned long)endOffset());
     
         if (unionNotEmpty(writeBuffer)) {
    -	fatal("Attempt to overwrite already in-memory data\n");
    -	return false;
    +        fatal("Attempt to overwrite already in-memory data\n");
    +        return false;
         }
     
         assert (writeBuffer.offset >= 0);
    @@ -337,12 +386,13 @@ mem_hdr::write (StoreIOBuffer const &writeBuffer)
         off_t currentOffset = writeBuffer.offset;
         char *currentSource = writeBuffer.data;
         size_t len = writeBuffer.length;
    +
         while (len && (target = nodeToRecieve(currentOffset))) {
    -	size_t wrote = writeAvailable(target, currentOffset, len, currentSource);
    -	assert (wrote);
    -	len -= wrote;
    -	currentOffset += wrote;
    -	currentSource += wrote;
    +        size_t wrote = writeAvailable(target, currentOffset, len, currentSource);
    +        assert (wrote);
    +        len -= wrote;
    +        currentOffset += wrote;
    +        currentSource += wrote;
         }
     
         return true;
    diff --git a/src/stmem.h b/src/stmem.h
    index 5975f90564..8681901952 100644
    --- a/src/stmem.h
    +++ b/src/stmem.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: stmem.h,v 1.1 2003/01/23 00:37:26 robertc Exp $
    + * $Id: stmem.h,v 1.2 2003/02/21 22:50:11 robertc Exp $
      *
      *
      * SQUID Web Proxy Cache          http://www.squid-cache.org/
    @@ -35,8 +35,12 @@
     #define SQUID_STMEM_H
     
     class mem_node;
    +
     class StoreIOBuffer;
    -class mem_hdr {
    +
    +class mem_hdr
    +{
    +
     public:
         void freeContent();
         int lowestOffset () const;
    @@ -51,6 +55,7 @@ public:
         void internalAppend(const char *data, int len);
         mem_node *head;
         mem_node *tail;
    +
     private:
         void unlinkHead();
         void makeAppendSpace();
    diff --git a/src/store.cc b/src/store.cc
    index 386c31a6ee..444917b93d 100644
    --- a/src/store.cc
    +++ b/src/store.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store.cc,v 1.559 2003/02/13 21:04:51 wessels Exp $
    + * $Id: store.cc,v 1.560 2003/02/21 22:50:11 robertc Exp $
      *
      * DEBUG: section 20    Storage Manager
      * AUTHOR: Harvest Derived
    @@ -54,36 +54,39 @@ static STMCB storeWriteComplete;
     #define STORE_IN_MEM_BUCKETS		(229)
     
     const char *memStatusStr[] =
    -{
    -    "NOT_IN_MEMORY",
    -    "IN_MEMORY"
    -};
    +    {
    +        "NOT_IN_MEMORY",
    +        "IN_MEMORY"
    +    };
     
     const char *pingStatusStr[] =
    -{
    -    "PING_NONE",
    -    "PING_WAITING",
    -    "PING_DONE"
    -};
    +    {
    +        "PING_NONE",
    +        "PING_WAITING",
    +        "PING_DONE"
    +    };
     
     const char *storeStatusStr[] =
    -{
    -    "STORE_OK",
    -    "STORE_PENDING"
    -};
    +    {
    +        "STORE_OK",
    +        "STORE_PENDING"
    +    };
     
     const char *swapStatusStr[] =
    -{
    -    "SWAPOUT_NONE",
    -    "SWAPOUT_WRITING",
    -    "SWAPOUT_DONE"
    -};
    +    {
    +        "SWAPOUT_NONE",
    +        "SWAPOUT_WRITING",
    +        "SWAPOUT_DONE"
    +    };
     
    -typedef struct lock_ctrl_t {
    +typedef struct lock_ctrl_t
    +{
         SIH *callback;
         void *callback_data;
         StoreEntry *e;
    -} lock_ctrl_t;
    +}
    +
    +lock_ctrl_t;
     
     extern OBJH storeIOStats;
     
    @@ -112,10 +115,12 @@ void *
     StoreEntry::operator new (size_t bytecount)
     {
         assert (bytecount == sizeof (StoreEntry));
    +
         if (!pool) {
    -	pool = memPoolCreate ("StoreEntry", bytecount);
    -	memPoolSetChunkSize(pool, 2048 * 1024);
    +        pool = memPoolCreate ("StoreEntry", bytecount);
    +        memPoolSetChunkSize(pool, 2048 * 1024);
         }
    +
         return memPoolAlloc (pool);
     }
     
    @@ -129,9 +134,12 @@ size_t
     StoreEntry::inUseCount()
     {
         if (!pool)
    -	return 0;
    +        return 0;
    +
         MemPoolStats stats;
    +
         memPoolGetStats (&stats, pool);
    +
         return stats.items_inuse;
     }
     
    @@ -152,29 +160,39 @@ int
     StoreEntry::checkDeferRead(int fd) const
     {
         int rc = 0;
    +
         if (mem_obj == NULL)
    -	return 0;
    +        return 0;
    +
     #if URL_CHECKSUM_DEBUG
    +
         mem_obj->checkUrlChecksum();
    +
     #endif
     #if DELAY_POOLS
    +
         if (fd < 0)
    -	(void) 0;
    +        (void) 0;
         else if (! DelayPools::IsNoDelay(fd)) {
    -	int i = mem_obj->mostBytesWanted(INT_MAX);
    -	if (0 == i)
    -	    return 1;
    -	/* was: rc = -(rc != INT_MAX); */
    -	else if (INT_MAX == i)
    -	    rc = 0;
    -	else
    -	    rc = -1;
    +        int i = mem_obj->mostBytesWanted(INT_MAX);
    +
    +        if (0 == i)
    +            return 1;
    +
    +        /* was: rc = -(rc != INT_MAX); */
    +        else if (INT_MAX == i)
    +            rc = 0;
    +        else
    +            rc = -1;
         }
    +
     #endif
         if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
    -	return rc;
    +        return rc;
    +
         if (mem_obj->readAheadPolicyCanRead())
    -	return rc;
    +        return rc;
    +
         return 1;
     }
     
    @@ -182,24 +200,28 @@ store_client_t
     StoreEntry::storeClientType() const
     {
         if (mem_obj->inmem_lo)
    -	return STORE_DISK_CLIENT;
    +        return STORE_DISK_CLIENT;
    +
         if (EBIT_TEST(flags, ENTRY_ABORTED)) {
    -	/* I don't think we should be adding clients to aborted entries */
    -	debug(20, 1) ("storeClientType: adding to ENTRY_ABORTED entry\n");
    -	return STORE_MEM_CLIENT;
    +        /* I don't think we should be adding clients to aborted entries */
    +        debug(20, 1) ("storeClientType: adding to ENTRY_ABORTED entry\n");
    +        return STORE_MEM_CLIENT;
         }
    +
         if (store_status == STORE_OK) {
    -	if (mem_obj->inmem_lo == 0 && !isEmpty())
    -	    return STORE_MEM_CLIENT;
    -	else
    -	    return STORE_DISK_CLIENT;
    +        if (mem_obj->inmem_lo == 0 && !isEmpty())
    +            return STORE_MEM_CLIENT;
    +        else
    +            return STORE_DISK_CLIENT;
         }
    +
         /* here and past, entry is STORE_PENDING */
         /*
          * If this is the first client, let it be the mem client
          */
         if (mem_obj->nclients == 1)
    -	return STORE_MEM_CLIENT;
    +        return STORE_MEM_CLIENT;
    +
         /*
          * If there is no disk file to open yet, we must make this a
          * mem client.  If we can't open the swapin file before writing
    @@ -207,7 +229,8 @@ StoreEntry::storeClientType() const
          * to open it later when we really need it.
          */
         if (swap_status == SWAPOUT_NONE)
    -	return STORE_MEM_CLIENT;
    +        return STORE_MEM_CLIENT;
    +
         /*
          * otherwise, make subsequent clients read from disk so they
          * can not delay the first, and vice-versa.
    @@ -220,12 +243,18 @@ new_StoreEntry(int mem_obj_flag, const char *url, const char *log_url)
     {
         StoreEntry *e = NULL;
         e = new StoreEntry;
    +
         if (mem_obj_flag)
    -	e->mem_obj = new MemObject(url, log_url);
    +        e->mem_obj = new MemObject(url, log_url);
    +
         debug(20, 3) ("newStoreEntry: returning %p\n", e);
    +
         e->expires = e->lastmod = e->lastref = e->timestamp = -1;
    +
         e->swap_filen = -1;
    +
         e->swap_dirn = -1;
    +
         return e;
     }
     
    @@ -244,11 +273,16 @@ destroyStoreEntry(void *data)
         StoreEntry *e = static_cast(data);
         debug(20, 3) ("destroyStoreEntry: destroying %p\n", e);
         assert(e != NULL);
    +
         if (e == NullStoreEntry::getInstance())
    -	return;
    +        return;
    +
         destroy_MemObject(e);
    +
         storeHashDelete(e);
    +
         assert(e->key == NULL);
    +
         delete e;
     }
     
    @@ -258,7 +292,7 @@ void
     storeHashInsert(StoreEntry * e, const cache_key * key)
     {
         debug(20, 3) ("storeHashInsert: Inserting Entry %p key '%s'\n",
    -	e, storeKeyText(key));
    +                  e, storeKeyText(key));
         e->key = storeKeyDup(key);
         hash_join(store_table, e);
     }
    @@ -279,24 +313,29 @@ static void
     storePurgeMem(StoreEntry * e)
     {
         if (e->mem_obj == NULL)
    -	return;
    +        return;
    +
         debug(20, 3) ("storePurgeMem: Freeing memory-copy of %s\n",
    -	e->getMD5Text());
    +                  e->getMD5Text());
    +
         destroy_MemObject(e);
    +
         if (e->swap_status != SWAPOUT_DONE)
    -	storeRelease(e);
    +        storeRelease(e);
     }
     
     static void
     storeEntryReferenced(StoreEntry * e)
     {
         /* Notify the fs that we're referencing this object again */
    +
         if (e->swap_dirn > -1)
    -	INDEXSD(e->swap_dirn)->reference(*e);
    +        INDEXSD(e->swap_dirn)->reference(*e);
    +
         /* Notify the memory cache that we're referencing this object again */
         if (e->mem_obj) {
    -	if (mem_policy->Referenced)
    -	    mem_policy->Referenced(mem_policy, e, &e->mem_obj->repl);
    +        if (mem_policy->Referenced)
    +            mem_policy->Referenced(mem_policy, e, &e->mem_obj->repl);
         }
     }
     
    @@ -304,12 +343,14 @@ static void
     storeEntryDereferenced(StoreEntry * e)
     {
         /* Notify the fs that we're not referencing this object any more */
    +
         if (e->swap_filen > -1)
    -	INDEXSD(e->swap_dirn)->dereference(*e);
    +        INDEXSD(e->swap_dirn)->dereference(*e);
    +
         /* Notify the memory cache that we're not referencing this object any more */
         if (e->mem_obj) {
    -	if (mem_policy->Dereferenced)
    -	    mem_policy->Dereferenced(mem_policy, e, &e->mem_obj->repl);
    +        if (mem_policy->Dereferenced)
    +            mem_policy->Dereferenced(mem_policy, e, &e->mem_obj->repl);
         }
     }
     
    @@ -318,7 +359,7 @@ storeLockObject(StoreEntry * e)
     {
         e->lock_count++;
         debug(20, 3) ("storeLockObject: key '%s' count=%d\n",
    -	e->getMD5Text(), (int) e->lock_count);
    +                  e->getMD5Text(), (int) e->lock_count);
         e->lastref = squid_curtime;
         storeEntryReferenced(e);
     }
    @@ -327,15 +368,19 @@ void
     storeReleaseRequest(StoreEntry * e)
     {
         if (EBIT_TEST(e->flags, RELEASE_REQUEST))
    -	return;
    +        return;
    +
         debug(20, 3) ("storeReleaseRequest: '%s'\n", e->getMD5Text());
    +
         EBIT_SET(e->flags, RELEASE_REQUEST);
    +
         /*
          * Clear cachable flag here because we might get called before
          * anyone else even looks at the cachability flag.  Also, this
          * prevents httpMakePublic from really setting a public key.
          */
         EBIT_CLR(e->flags, ENTRY_CACHABLE);
    +
         storeSetPrivateKey(e);
     }
     
    @@ -346,24 +391,30 @@ storeUnlockObject(StoreEntry * e)
     {
         e->lock_count--;
         debug(20, 3) ("storeUnlockObject: key '%s' count=%d\n",
    -	e->getMD5Text(), e->lock_count);
    +                  e->getMD5Text(), e->lock_count);
    +
         if (e->lock_count)
    -	return (int) e->lock_count;
    +        return (int) e->lock_count;
    +
         if (e->store_status == STORE_PENDING)
    -	EBIT_SET(e->flags, RELEASE_REQUEST);
    +        EBIT_SET(e->flags, RELEASE_REQUEST);
    +
         assert(storePendingNClients(e) == 0);
    +
         if (EBIT_TEST(e->flags, RELEASE_REQUEST))
    -	storeRelease(e);
    +        storeRelease(e);
         else if (storeKeepInMemory(e)) {
    -	storeEntryDereferenced(e);
    -	storeSetMemStatus(e, IN_MEMORY);
    -	e->mem_obj->unlinkRequest();
    +        storeEntryDereferenced(e);
    +        storeSetMemStatus(e, IN_MEMORY);
    +        e->mem_obj->unlinkRequest();
         } else {
    -	storePurgeMem(e);
    -	storeEntryDereferenced(e);
    -	if (EBIT_TEST(e->flags, KEY_PRIVATE))
    -	    debug(20, 1) ("WARNING: %s:%d: found KEY_PRIVATE\n", __FILE__, __LINE__);
    +        storePurgeMem(e);
    +        storeEntryDereferenced(e);
    +
    +        if (EBIT_TEST(e->flags, KEY_PRIVATE))
    +            debug(20, 1) ("WARNING: %s:%d: found KEY_PRIVATE\n", __FILE__, __LINE__);
         }
    +
         return 0;
     }
     
    @@ -384,10 +435,11 @@ StoreEntry::getPublicByRequestMethod  (StoreClient *aClient, request_t * request
     {
         assert (aClient);
         StoreEntry *result = storeGetPublicByRequestMethod( request, method);
    +
         if (!result)
    -	aClient->created (NullStoreEntry::getInstance());
    +        aClient->created (NullStoreEntry::getInstance());
         else
    -	aClient->created (result);
    +        aClient->created (result);
     }
     
     void
    @@ -395,8 +447,10 @@ StoreEntry::getPublicByRequest (StoreClient *aClient, request_t * request)
     {
         assert (aClient);
         StoreEntry *result = storeGetPublicByRequest (request);
    +
         if (!result)
    -	result = NullStoreEntry::getInstance();
    +        result = NullStoreEntry::getInstance();
    +
         aClient->created (result);
     }
     
    @@ -405,8 +459,10 @@ StoreEntry::getPublic (StoreClient *aClient, const char *uri, const method_t met
     {
         assert (aClient);
         StoreEntry *result = storeGetPublic (uri, method);
    +
         if (!result)
    -	result = NullStoreEntry::getInstance();
    +        result = NullStoreEntry::getInstance();
    +
         aClient->created (result);
     }
     
    @@ -426,9 +482,11 @@ StoreEntry *
     storeGetPublicByRequest(request_t * req)
     {
         StoreEntry *e = storeGetPublicByRequestMethod(req, req->method);
    +
         if (e == NULL && req->method == METHOD_HEAD)
    -	/* We can generate a HEAD reply from a cached GET object */
    -	e = storeGetPublicByRequestMethod(req, METHOD_GET);
    +        /* We can generate a HEAD reply from a cached GET object */
    +        e = storeGetPublicByRequestMethod(req, METHOD_GET);
    +
         return e;
     }
     
    @@ -436,8 +494,10 @@ static int
     getKeyCounter(void)
     {
         static int key_counter = 0;
    +
         if (++key_counter < 0)
    -	key_counter = 1;
    +        key_counter = 1;
    +
         return key_counter;
     }
     
    @@ -446,19 +506,24 @@ storeSetPrivateKey(StoreEntry * e)
     {
         const cache_key *newkey;
         MemObject *mem = e->mem_obj;
    +
         if (e->key && EBIT_TEST(e->flags, KEY_PRIVATE))
    -	return;			/* is already private */
    +        return;			/* is already private */
    +
         if (e->key) {
    -	if (e->swap_filen > -1)
    -	    storeDirSwapLog(e, SWAP_LOG_DEL);
    -	storeHashDelete(e);
    +        if (e->swap_filen > -1)
    +            storeDirSwapLog(e, SWAP_LOG_DEL);
    +
    +        storeHashDelete(e);
         }
    +
         if (mem != NULL) {
    -	mem->id = getKeyCounter();
    -	newkey = storeKeyPrivate(mem->url, mem->method, mem->id);
    +        mem->id = getKeyCounter();
    +        newkey = storeKeyPrivate(mem->url, mem->method, mem->id);
         } else {
    -	newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter());
    +        newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter());
         }
    +
         assert(hash_lookup(store_table, newkey) == NULL);
         EBIT_SET(e->flags, KEY_PRIVATE);
         storeHashInsert(e, newkey);
    @@ -470,9 +535,12 @@ storeSetPublicKey(StoreEntry * e)
         StoreEntry *e2 = NULL;
         const cache_key *newkey;
         MemObject *mem = e->mem_obj;
    +
         if (e->key && !EBIT_TEST(e->flags, KEY_PRIVATE))
    -	return;			/* is already public */
    +        return;			/* is already public */
    +
         assert(mem);
    +
         /*
          * We can't make RELEASE_REQUEST objects public.  Depending on
          * when RELEASE_REQUEST gets set, we might not be swapping out
    @@ -484,87 +552,109 @@ storeSetPublicKey(StoreEntry * e)
          * be set, and storeSetPublicKey() should not be called.
          */
     #if MORE_DEBUG_OUTPUT
    +
         if (EBIT_TEST(e->flags, RELEASE_REQUEST))
    -	debug(20, 1) ("assertion failed: RELEASE key %s, url %s\n",
    -	    e->key, mem->url);
    +        debug(20, 1) ("assertion failed: RELEASE key %s, url %s\n",
    +                      e->key, mem->url);
    +
     #endif
    +
         assert(!EBIT_TEST(e->flags, RELEASE_REQUEST));
    +
         if (mem->request) {
    -	StoreEntry *pe;
    -	request_t *request = mem->request;
    -	if (!mem->vary_headers) {
    -	    /* First handle the case where the object no longer varies */
    -	    safe_free(request->vary_headers);
    -	} else {
    -	    if (request->vary_headers && strcmp(request->vary_headers, mem->vary_headers) != 0) {
    -		/* Oops.. the variance has changed. Kill the base object
    -		 * to record the new variance key
    -		 */
    -		safe_free(request->vary_headers);	/* free old "bad" variance key */
    -		pe = storeGetPublic(mem->url, mem->method);
    -		if (pe)
    -		    storeRelease(pe);
    -	    }
    -	    /* Make sure the request knows the variance status */
    -	    if (!request->vary_headers) {
    -		const char *vary = httpMakeVaryMark(request, mem->getReply());
    -		if (vary)
    -		    request->vary_headers = xstrdup(vary);
    -	    }
    -	}
    -	if (mem->vary_headers && !storeGetPublic(mem->url, mem->method)) {
    -	    /* Create "vary" base object */
    -	    http_version_t version;
    -	    String vary;
    -	    pe = storeCreateEntry(mem->url, mem->log_url, request->flags, request->method);
    -	    httpBuildVersion(&version, 1, 0);
    -	    /* We are allowed to do this typecast */
    -	    httpReplySetHeaders((HttpReply *)pe->getReply(), version, HTTP_OK, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000);
    -	    vary = httpHeaderGetList(&mem->getReply()->header, HDR_VARY);
    -	    if (vary.size()) {
    -		/* Again, we own this structure layout */
    -		httpHeaderPutStr((HttpHeader *)&pe->getReply()->header, HDR_VARY, vary.buf());
    -		vary.clean();
    -	    }
    +        StoreEntry *pe;
    +        request_t *request = mem->request;
    +
    +        if (!mem->vary_headers) {
    +            /* First handle the case where the object no longer varies */
    +            safe_free(request->vary_headers);
    +        } else {
    +            if (request->vary_headers && strcmp(request->vary_headers, mem->vary_headers) != 0) {
    +                /* Oops.. the variance has changed. Kill the base object
    +                 * to record the new variance key
    +                 */
    +                safe_free(request->vary_headers);	/* free old "bad" variance key */
    +                pe = storeGetPublic(mem->url, mem->method);
    +
    +                if (pe)
    +                    storeRelease(pe);
    +            }
    +
    +            /* Make sure the request knows the variance status */
    +            if (!request->vary_headers) {
    +                const char *vary = httpMakeVaryMark(request, mem->getReply());
    +
    +                if (vary)
    +                    request->vary_headers = xstrdup(vary);
    +            }
    +        }
    +
    +        if (mem->vary_headers && !storeGetPublic(mem->url, mem->method)) {
    +            /* Create "vary" base object */
    +            http_version_t version;
    +            String vary;
    +            pe = storeCreateEntry(mem->url, mem->log_url, request->flags, request->method);
    +            httpBuildVersion(&version, 1, 0);
    +            /* We are allowed to do this typecast */
    +            httpReplySetHeaders((HttpReply *)pe->getReply(), version, HTTP_OK, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000);
    +            vary = httpHeaderGetList(&mem->getReply()->header, HDR_VARY);
    +
    +            if (vary.size()) {
    +                /* Again, we own this structure layout */
    +                httpHeaderPutStr((HttpHeader *)&pe->getReply()->header, HDR_VARY, vary.buf());
    +                vary.clean();
    +            }
    +
     #if X_ACCELERATOR_VARY
    -	    vary = httpHeaderGetList(&mem->getReply()->header, HDR_X_ACCELERATOR_VARY);
    -	    if (vary.buf()) {
    -		/* Again, we own this structure layout */
    -		httpHeaderPutStr((HttpHeader *)&pe->getReply()->header, HDR_X_ACCELERATOR_VARY, vary.buf());
    -		vary.clean();
    -	    }
    +            vary = httpHeaderGetList(&mem->getReply()->header, HDR_X_ACCELERATOR_VARY);
    +
    +            if (vary.buf()) {
    +                /* Again, we own this structure layout */
    +                httpHeaderPutStr((HttpHeader *)&pe->getReply()->header, HDR_X_ACCELERATOR_VARY, vary.buf());
    +                vary.clean();
    +            }
    +
     #endif
    -	    storeSetPublicKey(pe);
    -           /* TODO: remove this when the metadata is separated */
    -             {
    -               Packer p;
    -               packerToStoreInit(&p, pe);
    -               httpReplyPackHeadersInto(pe->getReply(), &p);
    -               packerClean(&p);
    -             }
    -	    storeBufferFlush(pe);
    -	    storeTimestampsSet(pe);
    -	    pe->complete();
    -	    storeUnlockObject(pe);
    -	}
    -	newkey = storeKeyPublicByRequest(mem->request);
    +            storeSetPublicKey(pe);
    +
    +            /* TODO: remove this when the metadata is separated */
    +            {
    +                Packer p;
    +                packerToStoreInit(&p, pe);
    +                httpReplyPackHeadersInto(pe->getReply(), &p);
    +                packerClean(&p);
    +            }
    +
    +            storeBufferFlush(pe);
    +            storeTimestampsSet(pe);
    +            pe->complete();
    +            storeUnlockObject(pe);
    +        }
    +
    +        newkey = storeKeyPublicByRequest(mem->request);
         } else
    -	newkey = storeKeyPublic(mem->url, mem->method);
    +        newkey = storeKeyPublic(mem->url, mem->method);
    +
         if ((e2 = (StoreEntry *) hash_lookup(store_table, newkey))) {
    -	debug(20, 3) ("storeSetPublicKey: Making old '%s' private.\n", mem->url);
    -	storeSetPrivateKey(e2);
    -	storeRelease(e2);
    -	if (mem->request)
    -	    newkey = storeKeyPublicByRequest(mem->request);
    -	else
    -	    newkey = storeKeyPublic(mem->url, mem->method);
    +        debug(20, 3) ("storeSetPublicKey: Making old '%s' private.\n", mem->url);
    +        storeSetPrivateKey(e2);
    +        storeRelease(e2);
    +
    +        if (mem->request)
    +            newkey = storeKeyPublicByRequest(mem->request);
    +        else
    +            newkey = storeKeyPublic(mem->url, mem->method);
         }
    +
         if (e->key)
    -	storeHashDelete(e);
    +        storeHashDelete(e);
    +
         EBIT_CLR(e->flags, KEY_PRIVATE);
    +
         storeHashInsert(e, newkey);
    +
         if (e->swap_filen > -1)
    -	storeDirSwapLog(e, SWAP_LOG_ADD);
    +        storeDirSwapLog(e, SWAP_LOG_ADD);
     }
     
     StoreEntry *
    @@ -578,17 +668,20 @@ storeCreateEntry(const char *url, const char *log_url, request_flags flags, meth
         e->lock_count = 1;		/* Note lock here w/o calling storeLock() */
         mem = e->mem_obj;
         mem->method = method;
    +
         if (neighbors_do_private_keys || !flags.hierarchical)
    -	storeSetPrivateKey(e);
    +        storeSetPrivateKey(e);
         else
    -	storeSetPublicKey(e);
    +        storeSetPublicKey(e);
    +
         if (flags.cachable) {
    -	EBIT_SET(e->flags, ENTRY_CACHABLE);
    -	EBIT_CLR(e->flags, RELEASE_REQUEST);
    +        EBIT_SET(e->flags, ENTRY_CACHABLE);
    +        EBIT_CLR(e->flags, RELEASE_REQUEST);
         } else {
    -	/* storeReleaseRequest() clears ENTRY_CACHABLE */
    -	storeReleaseRequest(e);
    +        /* storeReleaseRequest() clears ENTRY_CACHABLE */
    +        storeReleaseRequest(e);
         }
    +
         e->store_status = STORE_PENDING;
         storeSetMemStatus(e, NOT_IN_MEMORY);
         e->swap_status = SWAPOUT_NONE;
    @@ -614,8 +707,10 @@ void
     storeWriteComplete (void *data, StoreIOBuffer wroteBuffer)
     {
         StoreEntry *e = (StoreEntry *)data;
    +
         if (EBIT_TEST(e->flags, DELAY_SENDING))
    -       return;
    +        return;
    +
         InvokeHandlers(e);
     }
     
    @@ -626,12 +721,15 @@ StoreEntry::write (StoreIOBuffer writeBuffer)
         assert(writeBuffer.length >= 0);
         /* This assert will change when we teach the store to update */
         assert(store_status == STORE_PENDING);
    +
         if (!writeBuffer.length)
    -	return;
    -    
    +        return;
    +
         debug(20, 5) ("storeWrite: writing %u bytes for '%s'\n",
    -	writeBuffer.length, getMD5Text());
    +                  writeBuffer.length, getMD5Text());
    +
         storeGetMemSpace(writeBuffer.length);
    +
         mem_obj->write (writeBuffer, storeWriteComplete, this);
     }
     
    @@ -656,13 +754,14 @@ void
     storeAppendPrintf(StoreEntry * e, const char *fmt,...)
     #else
     storeAppendPrintf(va_alist)
    -     va_dcl
    +va_dcl
     #endif
     {
     #if STDC_HEADERS
         va_list args;
         va_start(args, fmt);
     #else
    +
         va_list args;
         StoreEntry *e = NULL;
         const char *fmt = NULL;
    @@ -670,6 +769,7 @@ storeAppendPrintf(va_alist)
         e = va_arg(args, StoreEntry *);
         fmt = va_arg(args, char *);
     #endif
    +
         storeAppendVPrintf(e, fmt, args);
         va_end(args);
     }
    @@ -684,30 +784,43 @@ storeAppendVPrintf(StoreEntry * e, const char *fmt, va_list vargs)
         storeAppend(e, buf, strlen(buf));
     }
     
    -struct _store_check_cachable_hist {
    -    struct {
    -	int non_get;
    -	int not_entry_cachable;
    -	int wrong_content_length;
    -	int negative_cached;
    -	int too_big;
    -	int too_small;
    -	int private_key;
    -	int too_many_open_files;
    -	int too_many_open_fds;
    -    } no;
    -    struct {
    -	int Default;
    -    } yes;
    -} store_check_cachable_hist;
    +struct _store_check_cachable_hist
    +{
    +
    +    struct
    +    {
    +        int non_get;
    +        int not_entry_cachable;
    +        int wrong_content_length;
    +        int negative_cached;
    +        int too_big;
    +        int too_small;
    +        int private_key;
    +        int too_many_open_files;
    +        int too_many_open_fds;
    +    }
    +
    +    no;
    +
    +    struct
    +    {
    +        int Default;
    +    }
    +
    +    yes;
    +}
    +
    +store_check_cachable_hist;
     
     int
     storeTooManyDiskFilesOpen(void)
     {
         if (Config.max_open_disk_fds == 0)
    -	return 0;
    +        return 0;
    +
         if (store_open_disk_fd > Config.max_open_disk_fds)
    -	return 1;
    +        return 1;
    +
         return 0;
     }
     
    @@ -715,15 +828,20 @@ static int
     storeCheckTooSmall(StoreEntry * e)
     {
         MemObject * const mem = e->mem_obj;
    +
         if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
    -	return 0;
    +        return 0;
    +
         if (STORE_OK == e->store_status)
    -	if (mem->object_sz < 0 ||
    -	    static_cast(mem->object_sz) < Config.Store.minObjectSize)
    -	    return 1;
    -    if (e->getReply()->content_length > -1)
    -	if (e->getReply()->content_length < (int) Config.Store.minObjectSize)
    -	    return 1;
    +        if (mem->object_sz < 0 ||
    +                static_cast(mem->object_sz)
    +                < Config.Store.minObjectSize)
    +            return 1;
    +    if (e->getReply()
    +            ->content_length > -1)
    +        if (e->getReply()
    +                ->content_length < (int) Config.Store.minObjectSize)
    +            return 1;
         return 0;
     }
     
    @@ -731,52 +849,60 @@ int
     storeCheckCachable(StoreEntry * e)
     {
     #if CACHE_ALL_METHODS
    +
         if (e->mem_obj->method != METHOD_GET) {
    -	debug(20, 2) ("storeCheckCachable: NO: non-GET method\n");
    -	store_check_cachable_hist.no.non_get++;
    +        debug(20, 2) ("storeCheckCachable: NO: non-GET method\n");
    +        store_check_cachable_hist.no.non_get++;
         } else
     #endif
    -    if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
    -	debug(20, 2) ("storeCheckCachable: NO: not cachable\n");
    -	store_check_cachable_hist.no.not_entry_cachable++;
    -    } else if (e->store_status == STORE_OK && EBIT_TEST(e->flags, ENTRY_BAD_LENGTH)) {
    -	debug(20, 2) ("storeCheckCachable: NO: wrong content-length\n");
    -	store_check_cachable_hist.no.wrong_content_length++;
    -    } else if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) {
    -	debug(20, 3) ("storeCheckCachable: NO: negative cached\n");
    -	store_check_cachable_hist.no.negative_cached++;
    -	return 0;		/* avoid release call below */
    -    } else if ((e->getReply()->content_length > 0 &&
    -		static_cast(e->getReply()->content_length) > Config.Store.maxObjectSize) ||
    -	static_cast(e->mem_obj->endOffset()) > Config.Store.maxObjectSize) {
    -	debug(20, 2) ("storeCheckCachable: NO: too big\n");
    -	store_check_cachable_hist.no.too_big++;
    -    } else if (e->getReply()->content_length > (int) Config.Store.maxObjectSize) {
    -	debug(20, 2) ("storeCheckCachable: NO: too big\n");
    -	store_check_cachable_hist.no.too_big++;
    -    } else if (storeCheckTooSmall(e)) {
    -	debug(20, 2) ("storeCheckCachable: NO: too small\n");
    -	store_check_cachable_hist.no.too_small++;
    -    } else if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
    -	debug(20, 3) ("storeCheckCachable: NO: private key\n");
    -	store_check_cachable_hist.no.private_key++;
    -    } else if (e->swap_status != SWAPOUT_NONE) {
    -	/*
    -	 * here we checked the swap_status because the remaining
    -	 * cases are only relevant only if we haven't started swapping
    -	 * out the object yet.
    -	 */
    -	return 1;
    -    } else if (storeTooManyDiskFilesOpen()) {
    -	debug(20, 2) ("storeCheckCachable: NO: too many disk files open\n");
    -	store_check_cachable_hist.no.too_many_open_files++;
    -    } else if (fdNFree() < RESERVED_FD) {
    -	debug(20, 2) ("storeCheckCachable: NO: too many FD's open\n");
    -	store_check_cachable_hist.no.too_many_open_fds++;
    -    } else {
    -	store_check_cachable_hist.yes.Default++;
    -	return 1;
    -    }
    +        if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
    +            debug(20, 2) ("storeCheckCachable: NO: not cachable\n");
    +            store_check_cachable_hist.no.not_entry_cachable++;
    +        } else if (e->store_status == STORE_OK && EBIT_TEST(e->flags, ENTRY_BAD_LENGTH)) {
    +            debug(20, 2) ("storeCheckCachable: NO: wrong content-length\n");
    +            store_check_cachable_hist.no.wrong_content_length++;
    +        } else if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) {
    +            debug(20, 3) ("storeCheckCachable: NO: negative cached\n");
    +            store_check_cachable_hist.no.negative_cached++;
    +            return 0;		/* avoid release call below */
    +        } else if ((e->getReply()->content_length > 0 &&
    +                    static_cast(e->getReply()->content_length)
    +                    > Config.Store.maxObjectSize) ||
    +                   static_cast(e->mem_obj->endOffset()) > Config.Store.maxObjectSize) {
    +            debug(20, 2) ("storeCheckCachable: NO: too big\n");
    +            store_check_cachable_hist.no.too_big++;
    +        } else if (e->getReply()->content_length > (int) Config.Store.maxObjectSize) {
    +            debug(20, 2)
    +            ("storeCheckCachable: NO: too big\n");
    +            store_check_cachable_hist.no.too_big++;
    +        } else if (storeCheckTooSmall(e)) {
    +            debug(20, 2)
    +            ("storeCheckCachable: NO: too small\n");
    +            store_check_cachable_hist.no.too_small++;
    +        } else if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
    +            debug(20, 3)
    +            ("storeCheckCachable: NO: private key\n");
    +            store_check_cachable_hist.no.private_key++;
    +        } else if (e->swap_status != SWAPOUT_NONE) {
    +            /*
    +             * here we checked the swap_status because the remaining
    +             * cases are only relevant only if we haven't started swapping
    +             * out the object yet.
    +             */
    +            return 1;
    +        } else if (storeTooManyDiskFilesOpen()) {
    +            debug(20, 2)
    +            ("storeCheckCachable: NO: too many disk files open\n");
    +            store_check_cachable_hist.no.too_many_open_files++;
    +        } else if (fdNFree() < RESERVED_FD) {
    +            debug(20, 2)
    +            ("storeCheckCachable: NO: too many FD's open\n");
    +            store_check_cachable_hist.no.too_many_open_fds++;
    +        } else {
    +            store_check_cachable_hist.yes.Default++;
    +            return 1;
    +        }
    +
         storeReleaseRequest(e);
         /* storeReleaseRequest() cleared ENTRY_CACHABLE */
         return 0;
    @@ -788,52 +914,59 @@ storeCheckCachableStats(StoreEntry * sentry)
         storeAppendPrintf(sentry, "Category\t Count\n");
     
     #if CACHE_ALL_METHODS
    +
         storeAppendPrintf(sentry, "no.non_get\t%d\n",
    -	store_check_cachable_hist.no.non_get);
    +                      store_check_cachable_hist.no.non_get);
     #endif
    +
         storeAppendPrintf(sentry, "no.not_entry_cachable\t%d\n",
    -	store_check_cachable_hist.no.not_entry_cachable);
    +                      store_check_cachable_hist.no.not_entry_cachable);
         storeAppendPrintf(sentry, "no.wrong_content_length\t%d\n",
    -	store_check_cachable_hist.no.wrong_content_length);
    +                      store_check_cachable_hist.no.wrong_content_length);
         storeAppendPrintf(sentry, "no.negative_cached\t%d\n",
    -	store_check_cachable_hist.no.negative_cached);
    +                      store_check_cachable_hist.no.negative_cached);
         storeAppendPrintf(sentry, "no.too_big\t%d\n",
    -	store_check_cachable_hist.no.too_big);
    +                      store_check_cachable_hist.no.too_big);
         storeAppendPrintf(sentry, "no.too_small\t%d\n",
    -	store_check_cachable_hist.no.too_small);
    +                      store_check_cachable_hist.no.too_small);
         storeAppendPrintf(sentry, "no.private_key\t%d\n",
    -	store_check_cachable_hist.no.private_key);
    +                      store_check_cachable_hist.no.private_key);
         storeAppendPrintf(sentry, "no.too_many_open_files\t%d\n",
    -	store_check_cachable_hist.no.too_many_open_files);
    +                      store_check_cachable_hist.no.too_many_open_files);
         storeAppendPrintf(sentry, "no.too_many_open_fds\t%d\n",
    -	store_check_cachable_hist.no.too_many_open_fds);
    +                      store_check_cachable_hist.no.too_many_open_fds);
         storeAppendPrintf(sentry, "yes.default\t%d\n",
    -	store_check_cachable_hist.yes.Default);
    +                      store_check_cachable_hist.yes.Default);
     }
     
     void
     StoreEntry::complete()
     {
         debug(20, 3) ("storeComplete: '%s'\n", getMD5Text());
    +
         if (store_status != STORE_PENDING) {
    -	/*
    -	 * if we're not STORE_PENDING, then probably we got aborted
    -	 * and there should be NO clients on this entry
    -	 */
    -	assert(EBIT_TEST(flags, ENTRY_ABORTED));
    -	assert(mem_obj->nclients == 0);
    -	return;
    +        /*
    +         * if we're not STORE_PENDING, then probably we got aborted
    +         * and there should be NO clients on this entry
    +         */
    +        assert(EBIT_TEST(flags, ENTRY_ABORTED));
    +        assert(mem_obj->nclients == 0);
    +        return;
         }
    +
         mem_obj->object_sz = mem_obj->endOffset();
         store_status = STORE_OK;
         assert(mem_status == NOT_IN_MEMORY);
    +
         if (!validLength()) {
    -	EBIT_SET(flags, ENTRY_BAD_LENGTH);
    -	storeReleaseRequest(this);
    +        EBIT_SET(flags, ENTRY_BAD_LENGTH);
    +        storeReleaseRequest(this);
         }
    +
     #if USE_CACHE_DIGESTS
         if (mem_obj->request)
    -	mem_obj->request->hier.store_complete_stop = current_time;
    +        mem_obj->request->hier.store_complete_stop = current_time;
    +
     #endif
         /*
          * We used to call InvokeHandlers, then storeSwapOut.  However,
    @@ -873,22 +1006,26 @@ storeAbort(StoreEntry * e)
          */
         mem->object_sz = mem->endOffset();
         /* Notify the server side */
    +
         if (mem->abort.callback) {
    -	eventAdd("mem->abort.callback",
    -	    mem->abort.callback,
    -	    mem->abort.data,
    -	    0.0,
    -	    0);
    -	mem->abort.callback = NULL;
    -	mem->abort.data = NULL;
    +        eventAdd("mem->abort.callback",
    +                 mem->abort.callback,
    +                 mem->abort.data,
    +                 0.0,
    +                 0);
    +        mem->abort.callback = NULL;
    +        mem->abort.data = NULL;
         }
    -    /* XXX Should we reverse these two, so that there is no 
    +
    +    /* XXX Should we reverse these two, so that there is no
          * unneeded disk swapping triggered? 
          */
         /* Notify the client side */
         InvokeHandlers(e);
    +
         /* Close any swapout file */
         storeSwapOutFileClose(e);
    +
         storeUnlockObject(e);	/* unlock */
     }
     
    @@ -901,21 +1038,30 @@ storeGetMemSpace(int size)
         static time_t last_check = 0;
         size_t pages_needed;
         RemovalPurgeWalker *walker;
    +
         if (squid_curtime == last_check)
    -	return;
    +        return;
    +
         last_check = squid_curtime;
    +
         pages_needed = (size / SM_PAGE_SIZE) + 1;
    +
         if (mem_node::InUseCount() + pages_needed < store_pages_max)
    -	return;
    +        return;
    +
         debug(20, 2) ("storeGetMemSpace: Starting, need %d pages\n", pages_needed);
    +
         /* XXX what to set as max_scan here? */
         walker = mem_policy->PurgeInit(mem_policy, 100000);
    +
         while ((e = walker->Next(walker))) {
    -	storePurgeMem(e);
    -	released++;
    -	if (mem_node::InUseCount() + pages_needed < store_pages_max)
    -	    break;
    +        storePurgeMem(e);
    +        released++;
    +
    +        if (mem_node::InUseCount() + pages_needed < store_pages_max)
    +            break;
         }
    +
         walker->Done(walker);
         debug(20, 3) ("storeGetMemSpace stats:\n");
         debug(20, 3) ("  %6d HOT objects\n", hot_obj_count);
    @@ -941,23 +1087,27 @@ storeMaintainSwapSpace(void *datanotused)
     
         PROF_start(storeMaintainSwapSpace);
         /* walk each fs */
    +
         for (i = 0; i < Config.cacheSwap.n_configured; i++) {
    -	/* call the maintain function .. */
    -	SD = INDEXSD(i);
    -	/* XXX FixMe: This should be done "in parallell" on the different
    -	 * cache_dirs, not one at a time.
    -	 */
    -	SD->maintainfs();
    +        /* call the maintain function .. */
    +        SD = INDEXSD(i);
    +        /* XXX FixMe: This should be done "in parallell" on the different
    +         * cache_dirs, not one at a time.
    +         */
    +        SD->maintainfs();
         }
    +
         if (store_swap_size > Config.Swap.maxSize) {
    -	if (squid_curtime - last_warn_time > 10) {
    -	    debug(20, 0) ("WARNING: Disk space over limit: %lu KB > %lu KB\n",
    -		(long unsigned) store_swap_size, (long unsigned) Config.Swap.maxSize);
    -	    last_warn_time = squid_curtime;
    -	}
    +        if (squid_curtime - last_warn_time > 10) {
    +            debug(20, 0) ("WARNING: Disk space over limit: %lu KB > %lu KB\n",
    +                          (long unsigned) store_swap_size, (long unsigned) Config.Swap.maxSize);
    +            last_warn_time = squid_curtime;
    +        }
         }
    +
         /* Reregister a maintain event .. */
         eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1);
    +
         PROF_stop(storeMaintainSwapSpace);
     }
     
    @@ -970,44 +1120,56 @@ storeRelease(StoreEntry * e)
         debug(20, 3) ("storeRelease: Releasing: '%s'\n", e->getMD5Text());
         /* If, for any reason we can't discard this object because of an
          * outstanding request, mark it for pending release */
    +
         if (storeEntryLocked(e)) {
    -	storeExpireNow(e);
    -	debug(20, 3) ("storeRelease: Only setting RELEASE_REQUEST bit\n");
    -	storeReleaseRequest(e);
    -	PROF_stop(storeRelease);
    -	return;
    +        storeExpireNow(e);
    +        debug(20, 3) ("storeRelease: Only setting RELEASE_REQUEST bit\n");
    +        storeReleaseRequest(e);
    +        PROF_stop(storeRelease);
    +        return;
         }
    +
         if (store_dirs_rebuilding && e->swap_filen > -1) {
    -	storeSetPrivateKey(e);
    -	if (e->mem_obj)
    -	    destroy_MemObject(e);
    -	if (e->swap_filen > -1) {
    -	    /*
    -	     * Fake a call to storeLockObject().  When rebuilding is done,
    -	     * we'll just call storeUnlockObject() on these.
    -	     */
    -	    e->lock_count++;
    -	    EBIT_SET(e->flags, RELEASE_REQUEST);
    -	    stackPush(&LateReleaseStack, e);
    -	    PROF_stop(storeRelease);
    -	    return;
    -	} else {
    -	    destroyStoreEntry(e);
    -	}
    +        storeSetPrivateKey(e);
    +
    +        if (e->mem_obj)
    +            destroy_MemObject(e);
    +
    +        if (e->swap_filen > -1) {
    +            /*
    +             * Fake a call to storeLockObject().  When rebuilding is done,
    +             * we'll just call storeUnlockObject() on these.
    +             */
    +            e->lock_count++;
    +            EBIT_SET(e->flags, RELEASE_REQUEST);
    +            stackPush(&LateReleaseStack, e);
    +            PROF_stop(storeRelease);
    +            return;
    +        } else {
    +            destroyStoreEntry(e);
    +        }
         }
    +
         storeLog(STORE_LOG_RELEASE, e);
    +
         if (e->swap_filen > -1) {
    -	storeUnlink(e);
    -	if (e->swap_status == SWAPOUT_DONE)
    -	    if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
    -		storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, -1);
    -	if (!EBIT_TEST(e->flags, KEY_PRIVATE))
    -	    storeDirSwapLog(e, SWAP_LOG_DEL);
    +        storeUnlink(e);
    +
    +        if (e->swap_status == SWAPOUT_DONE)
    +            if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
    +                storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, -1);
    +
    +        if (!EBIT_TEST(e->flags, KEY_PRIVATE))
    +            storeDirSwapLog(e, SWAP_LOG_DEL);
    +
     #if 0
    -	/* From 2.4. I think we do this in storeUnlink? */
    -	storeSwapFileNumberSet(e, -1);
    +        /* From 2.4. I think we do this in storeUnlink? */
    +        storeSwapFileNumberSet(e, -1);
    +
     #endif
    +
         }
    +
         storeSetMemStatus(e, NOT_IN_MEMORY);
         destroyStoreEntry(e);
         PROF_stop(storeRelease);
    @@ -1019,20 +1181,25 @@ storeLateRelease(void *unused)
         StoreEntry *e;
         int i;
         static int n = 0;
    +
         if (store_dirs_rebuilding) {
    -	eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1);
    -	return;
    +        eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1);
    +        return;
         }
    +
         for (i = 0; i < 10; i++) {
    -	e = static_cast(stackPop(&LateReleaseStack));
    -	if (e == NULL) {
    -	    /* done! */
    -	    debug(20, 1) ("storeLateRelease: released %d objects\n", n);
    -	    return;
    -	}
    -	storeUnlockObject(e);
    -	n++;
    +        e = static_cast(stackPop(&LateReleaseStack));
    +
    +        if (e == NULL) {
    +            /* done! */
    +            debug(20, 1) ("storeLateRelease: released %d objects\n", n);
    +            return;
    +        }
    +
    +        storeUnlockObject(e);
    +        n++;
         }
    +
         eventAdd("storeLateRelease", storeLateRelease, NULL, 0.0, 1);
     }
     
    @@ -1041,17 +1208,21 @@ int
     storeEntryLocked(const StoreEntry * e)
     {
         if (e->lock_count)
    -	return 1;
    +        return 1;
    +
         if (e->swap_status == SWAPOUT_WRITING)
    -	return 1;
    +        return 1;
    +
         if (e->store_status == STORE_PENDING)
    -	return 1;
    +        return 1;
    +
         /*
          * SPECIAL, PUBLIC entries should be "locked"
          */
         if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
    -	if (!EBIT_TEST(e->flags, KEY_PRIVATE))
    -	    return 1;
    +        if (!EBIT_TEST(e->flags, KEY_PRIVATE))
    +            return 1;
    +
         return 0;
     }
     
    @@ -1064,37 +1235,46 @@ StoreEntry::validLength() const
         reply = getReply();
         debug(20, 3) ("storeEntryValidLength: Checking '%s'\n", getMD5Text());
         debug(20, 5) ("storeEntryValidLength:     object_len = %d\n",
    -	objectLen(this));
    +                  objectLen(this));
         debug(20, 5) ("storeEntryValidLength:         hdr_sz = %d\n",
    -	reply->hdr_sz);
    +                  reply->hdr_sz);
         debug(20, 5) ("storeEntryValidLength: content_length = %d\n",
    -	reply->content_length);
    +                  reply->content_length);
    +
         if (reply->content_length < 0) {
    -	debug(20, 5) ("storeEntryValidLength: Unspecified content length: %s\n",
    -	    getMD5Text());
    -	return 1;
    +        debug(20, 5) ("storeEntryValidLength: Unspecified content length: %s\n",
    +                      getMD5Text());
    +        return 1;
         }
    +
         if (reply->hdr_sz == 0) {
    -	debug(20, 5) ("storeEntryValidLength: Zero header size: %s\n",
    -	    getMD5Text());
    -	return 1;
    +        debug(20, 5) ("storeEntryValidLength: Zero header size: %s\n",
    +                      getMD5Text());
    +        return 1;
         }
    +
         if (mem_obj->method == METHOD_HEAD) {
    -	debug(20, 5) ("storeEntryValidLength: HEAD request: %s\n",
    -	    getMD5Text());
    -	return 1;
    +        debug(20, 5) ("storeEntryValidLength: HEAD request: %s\n",
    +                      getMD5Text());
    +        return 1;
         }
    +
         if (reply->sline.status == HTTP_NOT_MODIFIED)
    -	return 1;
    +        return 1;
    +
         if (reply->sline.status == HTTP_NO_CONTENT)
    -	return 1;
    +        return 1;
    +
         diff = reply->hdr_sz + reply->content_length - objectLen(this);
    +
         if (diff == 0)
    -	return 1;
    +        return 1;
    +
         debug(20, 3) ("storeEntryValidLength: %d bytes too %s; '%s'\n",
    -	diff < 0 ? -diff : diff,
    -	diff < 0 ? "big" : "small",
    -	getMD5Text());
    +                  diff < 0 ? -diff : diff,
    +                  diff < 0 ? "big" : "small",
    +                  getMD5Text());
    +
         return 0;
     }
     
    @@ -1105,7 +1285,7 @@ storeInitHashValues(void)
         /* Calculate size of hash table (maximum currently 64k buckets).  */
         i = Config.Swap.maxSize / Config.Store.avgObjectSize;
         debug(20, 1) ("Swap maxSize %ld KB, estimated %ld objects\n",
    -	(long int) Config.Swap.maxSize, i);
    +                  (long int) Config.Swap.maxSize, i);
         i /= Config.Store.objectsPerBucket;
         debug(20, 1) ("Target number of buckets: %ld\n", i);
         /* ideally the full scan period should be configurable, for the
    @@ -1122,7 +1302,7 @@ storeInit(void)
         storeKeyInit();
         storeInitHashValues();
         store_table = hash_create(storeKeyHashCmp,
    -	store_hash_buckets, storeKeyHashHash);
    +                              store_hash_buckets, storeKeyHashHash);
         mem_policy = createRemovalPolicy(Config.memPolicy);
         storeDigestInit();
         storeLogOpen();
    @@ -1131,23 +1311,23 @@ storeInit(void)
         storeDirInit();
         storeRebuildStart();
         cachemgrRegister("storedir",
    -	"Store Directory Stats",
    -	storeDirStats, 0, 1);
    +                     "Store Directory Stats",
    +                     storeDirStats, 0, 1);
         cachemgrRegister("store_check_cachable_stats",
    -	"storeCheckCachable() Stats",
    -	storeCheckCachableStats, 0, 1);
    +                     "storeCheckCachable() Stats",
    +                     storeCheckCachableStats, 0, 1);
         cachemgrRegister("store_io",
    -	"Store IO Interface Stats",
    -	storeIOStats, 0, 1);
    +                     "Store IO Interface Stats",
    +                     storeIOStats, 0, 1);
     }
     
     void
     storeConfigure(void)
     {
         store_swap_high = (long) (((float) Config.Swap.maxSize *
    -	    (float) Config.Swap.highWaterMark) / (float) 100);
    +                               (float) Config.Swap.highWaterMark) / (float) 100);
         store_swap_low = (long) (((float) Config.Swap.maxSize *
    -	    (float) Config.Swap.lowWaterMark) / (float) 100);
    +                              (float) Config.Swap.lowWaterMark) / (float) 100);
         store_pages_max = Config.memMaxSize / SM_PAGE_SIZE;
     }
     
    @@ -1155,10 +1335,13 @@ static int
     storeKeepInMemory(const StoreEntry * e)
     {
         MemObject *mem = e->mem_obj;
    +
         if (mem == NULL)
    -	return 0;
    +        return 0;
    +
         if (mem->data_hdr.head == NULL)
    -	return 0;
    +        return 0;
    +
         return mem->inmem_lo == 0;
     }
     
    @@ -1166,11 +1349,14 @@ int
     storeCheckNegativeHit(StoreEntry * e)
     {
         if (!EBIT_TEST(e->flags, ENTRY_NEGCACHED))
    -	return 0;
    +        return 0;
    +
         if (e->expires <= squid_curtime)
    -	return 0;
    +        return 0;
    +
         if (e->store_status != STORE_OK)
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -1188,9 +1374,12 @@ storeFreeMemory(void)
         hashFreeMemory(store_table);
         store_table = NULL;
     #if USE_CACHE_DIGESTS
    +
         if (store_digest)
    -	cacheDigestDestroy(store_digest);
    +        cacheDigestDestroy(store_digest);
    +
     #endif
    +
         store_digest = NULL;
     }
     
    @@ -1198,7 +1387,8 @@ int
     expiresMoreThan(time_t expires, time_t when)
     {
         if (expires < 0)		/* No Expires given */
    -	return 1;
    +        return 1;
    +
         return (expires > (squid_curtime + when));
     }
     
    @@ -1206,12 +1396,15 @@ int
     storeEntryValidToSend(StoreEntry * e)
     {
         if (EBIT_TEST(e->flags, RELEASE_REQUEST))
    -	return 0;
    +        return 0;
    +
         if (EBIT_TEST(e->flags, ENTRY_NEGCACHED))
    -	if (e->expires <= squid_curtime)
    -	    return 0;
    +        if (e->expires <= squid_curtime)
    +            return 0;
    +
         if (EBIT_TEST(e->flags, ENTRY_ABORTED))
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -1230,8 +1423,10 @@ storeTimestampsSet(StoreEntry * entry)
          * are received, not when the whole response has been received.
          */
         /* make sure that 0 <= served_date <= squid_curtime */
    +
         if (served_date < 0 || served_date > squid_curtime)
    -	served_date = squid_curtime;
    +        served_date = squid_curtime;
    +
         /*
          * Compensate with Age header if origin server clock is ahead
          * of us and there is a cache in between us and the origin
    @@ -1239,10 +1434,13 @@ storeTimestampsSet(StoreEntry * entry)
          * squid_curtime because it results in a negative served_date.
          */
         if (age > squid_curtime - served_date)
    -	if (squid_curtime > age)
    -	    served_date = squid_curtime - age;
    +        if (squid_curtime > age)
    +            served_date = squid_curtime - age;
    +
         entry->expires = reply->expires;
    +
         entry->lastmod = reply->last_modified;
    +
         entry->timestamp = served_date;
     }
     
    @@ -1293,31 +1491,38 @@ void
     storeSetMemStatus(StoreEntry * e, mem_status_t new_status)
     {
         MemObject *mem = e->mem_obj;
    +
         if (new_status == e->mem_status)
    -	return;
    +        return;
    +
         assert(mem != NULL);
    +
         if (new_status == IN_MEMORY) {
    -	assert(mem->inmem_lo == 0);
    -	if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
    -	    debug(20, 4) ("storeSetMemStatus: not inserting special %s into policy\n",
    -		mem->url);
    -	} else {
    -	    mem_policy->Add(mem_policy, e, &mem->repl);
    -	    debug(20, 4) ("storeSetMemStatus: inserted mem node %s\n",
    -		mem->url);
    -	}
    -	hot_obj_count++;
    +        assert(mem->inmem_lo == 0);
    +
    +        if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
    +            debug(20, 4) ("storeSetMemStatus: not inserting special %s into policy\n",
    +                          mem->url);
    +        } else {
    +            mem_policy->Add(mem_policy, e, &mem->repl);
    +            debug(20, 4) ("storeSetMemStatus: inserted mem node %s\n",
    +                          mem->url);
    +        }
    +
    +        hot_obj_count++;
         } else {
    -	if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
    -	    debug(20, 4) ("storeSetMemStatus: special entry %s\n",
    -		mem->url);
    -	} else {
    -	    mem_policy->Remove(mem_policy, e, &mem->repl);
    -	    debug(20, 4) ("storeSetMemStatus: removed mem node %s\n",
    -		mem->url);
    -	}
    -	hot_obj_count--;
    +        if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
    +            debug(20, 4) ("storeSetMemStatus: special entry %s\n",
    +                          mem->url);
    +        } else {
    +            mem_policy->Remove(mem_policy, e, &mem->repl);
    +            debug(20, 4) ("storeSetMemStatus: removed mem node %s\n",
    +                          mem->url);
    +        }
    +
    +        hot_obj_count--;
         }
    +
         e->mem_status = new_status;
     }
     
    @@ -1325,18 +1530,19 @@ const char *
     storeUrl(const StoreEntry * e)
     {
         if (e == NULL)
    -	return "[null_entry]";
    +        return "[null_entry]";
         else if (e->mem_obj == NULL)
    -	return "[null_mem_obj]";
    +        return "[null_mem_obj]";
         else
    -	return e->mem_obj->url;
    +        return e->mem_obj->url;
     }
     
     void
     storeCreateMemObject(StoreEntry * e, const char *url, const char *log_url)
     {
         if (e->mem_obj)
    -	return;
    +        return;
    +
         e->mem_obj = new MemObject(url, log_url);
     }
     
    @@ -1375,7 +1581,8 @@ HttpReply const *
     StoreEntry::getReply () const
     {
         if (NULL == mem_obj)
    -	return NULL;
    +        return NULL;
    +
         return mem_obj->getReply();
     }
     
    @@ -1415,8 +1622,8 @@ storeFsDone(void)
         int i = 0;
     
         while (storefs_list[i].typestr != NULL) {
    -	storefs_list[i].donefunc();
    -	i++;
    +        storefs_list[i].donefunc();
    +        i++;
         }
     }
     
    @@ -1429,13 +1636,18 @@ StoreEntry::FsAdd(const char *type, STSETUP * setup)
     {
         int i;
         /* find the number of currently known storefs types */
    +
         for (i = 0; storefs_list && storefs_list[i].typestr; i++) {
    -	assert(strcmp(storefs_list[i].typestr, type) != 0);
    +        assert(strcmp(storefs_list[i].typestr, type) != 0);
         }
    +
         /* add the new type */
         storefs_list = static_cast(xrealloc(storefs_list, (i + 2) * sizeof(storefs_entry_t)));
    +
         memset(&storefs_list[i + 1], 0, sizeof(storefs_entry_t));
    +
         storefs_list[i].typestr = type;
    +
         /* Call the FS to set up capabilities and initialize the FS driver */
         setup(&storefs_list[i]);
     }
    @@ -1448,13 +1660,18 @@ storeReplAdd(const char *type, REMOVALPOLICYCREATE * create)
     {
         int i;
         /* find the number of currently known repl types */
    +
         for (i = 0; storerepl_list && storerepl_list[i].typestr; i++) {
    -	assert(strcmp(storerepl_list[i].typestr, type) != 0);
    +        assert(strcmp(storerepl_list[i].typestr, type) != 0);
         }
    +
         /* add the new type */
         storerepl_list = static_cast(xrealloc(storerepl_list, (i + 2) * sizeof(storerepl_entry_t)));
    +
         memset(&storerepl_list[i + 1], 0, sizeof(storerepl_entry_t));
    +
         storerepl_list[i].typestr = type;
    +
         storerepl_list[i].create = create;
     }
     
    @@ -1465,10 +1682,12 @@ RemovalPolicy *
     createRemovalPolicy(RemovalPolicySettings * settings)
     {
         storerepl_entry_t *r;
    +
         for (r = storerepl_list; r && r->typestr; r++) {
    -	if (strcmp(r->typestr, settings->type) == 0)
    -	    return r->create(settings->args);
    +        if (strcmp(r->typestr, settings->type) == 0)
    +            return r->create(settings->args);
         }
    +
         debug(20, 1) ("ERROR: Unknown policy %s\n", settings->type);
         debug(20, 1) ("ERROR: Be sure to have set cache_replacement_policy\n");
         debug(20, 1) ("ERROR:   and memory_replacement_policy in squid.conf!\n");
    @@ -1481,18 +1700,20 @@ void
     storeSwapFileNumberSet(StoreEntry * e, sfileno filn)
     {
         if (e->swap_file_number == filn)
    -	return;
    +        return;
    +
         if (filn < 0) {
    -	assert(-1 == filn);
    -	storeDirMapBitReset(e->swap_file_number);
    -	storeDirLRUDelete(e);
    -	e->swap_file_number = -1;
    +        assert(-1 == filn);
    +        storeDirMapBitReset(e->swap_file_number);
    +        storeDirLRUDelete(e);
    +        e->swap_file_number = -1;
         } else {
    -	assert(-1 == e->swap_file_number);
    -	storeDirMapBitSet(e->swap_file_number = filn);
    -	storeDirLRUAdd(e);
    +        assert(-1 == e->swap_file_number);
    +        storeDirMapBitSet(e->swap_file_number = filn);
    +        storeDirLRUAdd(e);
         }
     }
    +
     #endif
     
     /* Replace a store entry with
    @@ -1505,12 +1726,15 @@ storeEntryReplaceObject(StoreEntry * e, HttpReply * rep)
         HttpReply *myrep;
         Packer p;
         debug(20, 3) ("storeEntryReplaceObject: %s\n", storeUrl(e));
    +
         if (!mem) {
    -       debug (20,0)("Attempt to replace object with no in-memory representation\n");
    -       return;
    +        debug (20,0)("Attempt to replace object with no in-memory representation\n");
    +        return;
         }
    +
         /* TODO: check that there is at most 1 store client ? */
         myrep = (HttpReply *)e->getReply(); /* we are allowed to do this */
    +
         /* move info to the mem_obj->reply */
         httpReplyAbsorb(myrep, rep);
     
    @@ -1518,13 +1742,18 @@ storeEntryReplaceObject(StoreEntry * e, HttpReply * rep)
         /* TODO: mark the length of the headers ? */
         /* We ONLY want the headers */
         packerToStoreInit(&p, e);
    +
         assert (e->isEmpty());
    +
         httpReplyPackHeadersInto(e->getReply(), &p);
    +
         myrep->hdr_sz = e->mem_obj->endOffset();
    +
         httpBodyPackInto(&e->getReply()->body, &p);
    +
         packerClean(&p);
     }
    - 
    +
     
     char const *
     StoreEntry::getSerialisedMetaData()
    @@ -1544,16 +1773,19 @@ StoreEntry::swapoutPossible()
         /* should we swap something out to disk? */
         debug(20, 7) ("storeSwapOut: %s\n", storeUrl(this));
         debug(20, 7) ("storeSwapOut: store_status = %s\n",
    -	storeStatusStr[store_status]);
    +                  storeStatusStr[store_status]);
    +
         if (EBIT_TEST(flags, ENTRY_ABORTED)) {
    -	assert(EBIT_TEST(flags, RELEASE_REQUEST));
    -	storeSwapOutFileClose(this);
    -	return false;
    +        assert(EBIT_TEST(flags, RELEASE_REQUEST));
    +        storeSwapOutFileClose(this);
    +        return false;
         }
    +
         if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
    -	debug(20, 3) ("storeSwapOut: %s SPECIAL\n", storeUrl(this));
    -	return false;
    +        debug(20, 3) ("storeSwapOut: %s SPECIAL\n", storeUrl(this));
    +        return false;
         }
    +
         return true;
     }
     
    @@ -1561,21 +1793,24 @@ void
     StoreEntry::trimMemory()
     {
         if (mem_obj->policyLowestOffsetToKeep() == 0)
    -	/* Nothing to do */
    -	return;
    +        /* Nothing to do */
    +        return;
    +
         assert (mem_obj->policyLowestOffsetToKeep() > 0);
    +
         if (!storeSwapOutAble(this)) {
    -	/*
    -	 * Its not swap-able, and we're about to delete a chunk,
    -	 * so we must make it PRIVATE.  This is tricky/ugly because
    -	 * for the most part, we treat swapable == cachable here.
    -	 */
    -	storeReleaseRequest(this);
    -	mem_obj->trimUnSwappable ();
    +        /*
    +         * Its not swap-able, and we're about to delete a chunk,
    +         * so we must make it PRIVATE.  This is tricky/ugly because
    +         * for the most part, we treat swapable == cachable here.
    +         */
    +        storeReleaseRequest(this);
    +        mem_obj->trimUnSwappable ();
         } else {
    -	mem_obj->trimSwappable ();
    +        mem_obj->trimSwappable ();
         }
     }
    +
     /* NullStoreEntry */
     
     NullStoreEntry NullStoreEntry::_instance;
    diff --git a/src/store_client.cc b/src/store_client.cc
    index 174cc3f1b9..684e52b61d 100644
    --- a/src/store_client.cc
    +++ b/src/store_client.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_client.cc,v 1.123 2003/02/06 23:13:00 robertc Exp $
    + * $Id: store_client.cc,v 1.124 2003/02/21 22:50:11 robertc Exp $
      *
      * DEBUG: section 90    Storage Manager Client-Side Interface
      * AUTHOR: Duane Wessels
    @@ -97,11 +97,14 @@ storeClientListSearch(const MemObject * mem, void *data)
     {
         dlink_node *node;
         store_client *sc = NULL;
    +
         for (node = mem->clients.head; node; node = node->next) {
    -	sc = node->data;
    -	if (sc->owner == data)
    -	    return sc;
    +        sc = node->data;
    +
    +        if (sc->owner == data)
    +            return sc;
         }
    +
         return NULL;
     }
     
    @@ -110,6 +113,7 @@ storeClientIsThisAClient(store_client * sc, void *someClient)
     {
         return sc->owner == someClient;
     }
    +
     #endif
     
     /* add client with fd to client list */
    @@ -120,12 +124,17 @@ storeClientListAdd(StoreEntry * e, void *data)
         store_client *sc;
         assert(mem);
     #if STORE_CLIENT_LIST_DEBUG
    +
         if (storeClientListSearch(mem, data) != NULL)
    -	/* XXX die! */
    -	assert(1 == 0);
    +        /* XXX die! */
    +        assert(1 == 0);
    +
     #endif
    +
         sc = new store_client (e);
    +
         mem->addClient(sc);
    +
         return sc;
     }
     
    @@ -133,12 +142,14 @@ void
     store_client::callback(ssize_t sz, bool error)
     {
         StoreIOBuffer result (sz, 0 ,copyInto.data);
    +
         if (sz < 0) {
    -	result.flags.error = 1;
    -	result.length = 0;
    +        result.flags.error = 1;
    +        result.length = 0;
         } else {
    -	result.flags.error = error ? 1 : 0;
    +        result.flags.error = error ? 1 : 0;
         }
    +
         result.offset = cmp_offset;
         assert(callbackPending());
         cmp_offset = copyInto.offset + sz;
    @@ -146,8 +157,10 @@ store_client::callback(ssize_t sz, bool error)
         void *cbdata = _callback.callback_data;
         _callback = Callback(NULL, NULL);
         copyInto.data = NULL;
    +
         if (cbdataReferenceValid(cbdata))
    -	temphandler(cbdata, result);
    +        temphandler(cbdata, result);
    +
         cbdataReferenceDone(cbdata);
     }
     
    @@ -158,41 +171,46 @@ storeClientCopyEvent(void *data)
         debug(90, 3)("storeClientCopyEvent: Running\n");
         assert (sc->flags.copy_event_pending);
         sc->flags.copy_event_pending = 0;
    +
         if (!sc->callbackPending())
    -	return;
    +        return;
    +
         storeClientCopy2(sc->entry, sc);
     }
     
     store_client::store_client(StoreEntry *e) : entry (e)
     #if DELAY_POOLS
    -  , delayId()
    +        , delayId()
     #endif
    -  , type (e->storeClientType())
    -  ,  object_ok(true)
    +        , type (e->storeClientType())
    +        ,  object_ok(true)
     {
         cmp_offset = 0;
         flags.disk_io_pending = 0;
         entry->refcount++;
    +
         if (getType() == STORE_DISK_CLIENT)
    -	/* assert we'll be able to get the data we want */
    -	/* maybe we should open swapin_fd here */
    -	assert(entry->swap_filen > -1 || storeSwapOutAble(entry));
    +        /* assert we'll be able to get the data we want */
    +        /* maybe we should open swapin_fd here */
    +        assert(entry->swap_filen > -1 || storeSwapOutAble(entry));
    +
     #if STORE_CLIENT_LIST_DEBUG
    +
         owner = cbdataReference(data);
    +
     #endif
     }
     
     store_client::~store_client()
    -{
    -}
    +{}
     
     /* copy bytes requested by the client */
     void
     storeClientCopy(store_client * sc,
    -    StoreEntry * e,
    -    StoreIOBuffer copyInto,
    -    STCB * callback,
    -    void *data)
    +                StoreEntry * e,
    +                StoreIOBuffer copyInto,
    +                STCB * callback,
    +                void *data)
     {
         assert (sc != NULL);
         sc->copy(e, copyInto,callback,data);
    @@ -200,25 +218,28 @@ storeClientCopy(store_client * sc,
     
     void
     store_client::copy(StoreEntry * anEntry,
    -		       StoreIOBuffer copyRequest,
    -		           STCB * callback_fn,
    -			       void *data)
    +                   StoreIOBuffer copyRequest,
    +                   STCB * callback_fn,
    +                   void *data)
     {
         assert (anEntry == entry);
         assert (callback_fn);
         assert (data);
         assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED));
         debug(90, 3)("store_client::copy: %s, from %lu, for length %d, cb %p, cbdata %p",
    -	entry->getMD5Text(),
    -	(unsigned long) copyRequest.offset,
    -	(int) copyRequest.length,
    -	callback_fn,
    -	data);
    +                 entry->getMD5Text(),
    +                 (unsigned long) copyRequest.offset,
    +                 (int) copyRequest.length,
    +                 callback_fn,
    +                 data);
     #if STORE_CLIENT_LIST_DEBUG
    +
         assert(this == storeClientListSearch(entry->mem_obj, data));
     #endif
    +
         assert(!callbackPending());
     #if ONLYCONTIGUOUSREQUESTS
    +
         assert(cmp_offset == copyRequest.offset);
     #endif
         /* range requests will skip into the body */
    @@ -244,12 +265,16 @@ static int
     storeClientNoMoreToSend(StoreEntry * e, store_client * sc)
     {
         ssize_t len;
    +
         if (e->store_status == STORE_PENDING)
    -	return 0;
    +        return 0;
    +
         if ((len = objectLen(e)) < 0)
    -	return 0;
    +        return 0;
    +
         if (sc->copyInto.offset < len)
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -259,19 +284,23 @@ storeClientCopy2(StoreEntry * e, store_client * sc)
         /* reentrancy not allowed  - note this could lead to
          * dropped events
          */
    +
         if (sc->flags.copy_event_pending) {
    -	return;
    +        return;
         }
    +
         if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
    -	debug(90, 5)("storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set\n");
    -	return;
    +        debug(90, 5)("storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set\n");
    +        return;
         }
    +
         if (sc->flags.store_copying) {
    -	sc->flags.copy_event_pending = 1;
    -	debug(90, 3)("storeClientCopy2: Queueing storeClientCopyEvent()\n");
    -	eventAdd("storeClientCopyEvent", storeClientCopyEvent, sc, 0.0, 0);
    -	return;
    +        sc->flags.copy_event_pending = 1;
    +        debug(90, 3)("storeClientCopy2: Queueing storeClientCopyEvent()\n");
    +        eventAdd("storeClientCopyEvent", storeClientCopyEvent, sc, 0.0, 0);
    +        return;
         }
    +
         debug(90, 3)("storeClientCopy2: %s\n", e->getMD5Text());
         assert(sc->callbackPending());
         /*
    @@ -302,17 +331,19 @@ store_client::doCopy(StoreEntry *anEntry)
         debug(33, 5)("store_client::doCopy: co: %lu, hi: %ld\n", (unsigned long) copyInto.offset, (long int) mem->endOffset());
     
         if (storeClientNoMoreToSend(entry, this)) {
    -	/* There is no more to send! */
    -	callback(0);
    -	flags.store_copying = 0;
    -	return;
    +        /* There is no more to send! */
    +        callback(0);
    +        flags.store_copying = 0;
    +        return;
         }
    +
         /* Check that we actually have data */
         if (anEntry->store_status == STORE_PENDING && copyInto.offset >= mem->endOffset()) {
    -	debug(90, 3)("store_client::doCopy: Waiting for more\n");
    -	flags.store_copying = 0;
    -	return;
    +        debug(90, 3)("store_client::doCopy: Waiting for more\n");
    +        flags.store_copying = 0;
    +        return;
         }
    +
         /*
          * Slight weirdness here.  We open a swapin file for any
          * STORE_DISK_CLIENT, even if we can copy the requested chunk
    @@ -326,46 +357,55 @@ store_client::doCopy(StoreEntry *anEntry)
          */
     
         if (STORE_DISK_CLIENT == getType() && NULL == swapin_sio.getRaw()) {
    -	debug(90, 3)("store_client::doCopy: Need to open swap in file\n");
    -	/* gotta open the swapin file */
    -	if (storeTooManyDiskFilesOpen()) {
    -	    /* yuck -- this causes a TCP_SWAPFAIL_MISS on the client side */
    -	    fail();
    -	    flags.store_copying = 0;
    -	    return;
    -	} else if (!flags.disk_io_pending) {
    -	    /* Don't set store_io_pending here */
    -	    storeSwapInStart(this);
    -	    if (NULL == swapin_sio.getRaw()) {
    -		fail();
    -		flags.store_copying = 0;
    -		return;
    -	    }
    -	    /*
    -	     * If the open succeeds we either copy from memory, or
    -	     * schedule a disk read in the next block.
    -	     */
    -	} else {
    -	    debug (90, 1)("WARNING: Averted multiple fd operation (1)\n");
    -	    flags.store_copying = 0;
    -	    return;
    -	}
    +        debug(90, 3)("store_client::doCopy: Need to open swap in file\n");
    +        /* gotta open the swapin file */
    +
    +        if (storeTooManyDiskFilesOpen()) {
    +            /* yuck -- this causes a TCP_SWAPFAIL_MISS on the client side */
    +            fail();
    +            flags.store_copying = 0;
    +            return;
    +        } else if (!flags.disk_io_pending) {
    +            /* Don't set store_io_pending here */
    +            storeSwapInStart(this);
    +
    +            if (NULL == swapin_sio.getRaw()) {
    +                fail();
    +                flags.store_copying = 0;
    +                return;
    +            }
    +
    +            /*
    +             * If the open succeeds we either copy from memory, or
    +             * schedule a disk read in the next block.
    +             */
    +        } else {
    +            debug (90, 1)("WARNING: Averted multiple fd operation (1)\n");
    +            flags.store_copying = 0;
    +            return;
    +        }
         }
    +
         if (copyInto.offset >= mem->inmem_lo && copyInto.offset < mem->endOffset()) {
    -	/* What the client wants is in memory */
    -	/* Old style */
    -	debug(90, 3)("store_client::doCopy: Copying normal from memory\n");
    -	size_t sz = mem->data_hdr.copy(copyInto.offset, copyInto.data,
    -	    copyInto.length);
    -	callback(sz);
    -	flags.store_copying = 0;
    -	return;
    +        /* What the client wants is in memory */
    +        /* Old style */
    +        debug(90, 3)("store_client::doCopy: Copying normal from memory\n");
    +        size_t sz = mem->data_hdr.copy(copyInto.offset, copyInto.data,
    +                                       copyInto.length);
    +        callback(sz);
    +        flags.store_copying = 0;
    +        return;
         }
    +
         /* What the client wants is not in memory. Schedule a disk read */
         assert(STORE_DISK_CLIENT == getType());
    +
         assert(!flags.disk_io_pending);
    +
         debug(90, 3)("store_client::doCopy: reading from STORE\n");
    +
         fileRead();
    +
         flags.store_copying = 0;
     }
     
    @@ -377,16 +417,18 @@ store_client::fileRead()
         assert(callbackPending());
         assert(!flags.disk_io_pending);
         flags.disk_io_pending = 1;
    +
         if (mem->swap_hdr_sz != 0)
    -	if (entry->swap_status == SWAPOUT_WRITING)
    -	    assert(mem->swapout.sio->offset() > copyInto.offset + (off_t)mem->swap_hdr_sz);
    +        if (entry->swap_status == SWAPOUT_WRITING)
    +            assert(mem->swapout.sio->offset() > copyInto.offset + (off_t)mem->swap_hdr_sz);
    +
         storeRead(swapin_sio,
    -	      copyInto.data,
    -	      copyInto.length,
    -	      copyInto.offset + mem->swap_hdr_sz,
    -	      mem->swap_hdr_sz == 0 ? storeClientReadHeader
    -	      : storeClientReadBody,
    -	      this);
    +              copyInto.data,
    +              copyInto.length,
    +              copyInto.offset + mem->swap_hdr_sz,
    +              mem->swap_hdr_sz == 0 ? storeClientReadHeader
    +              : storeClientReadBody,
    +              this);
     }
     
     static void
    @@ -397,16 +439,18 @@ storeClientReadBody(void *data, const char *buf, ssize_t len)
         sc->flags.disk_io_pending = 0;
         assert(sc->callbackPending());
         debug(90, 3)("storeClientReadBody: len %d", (int) len);
    +
         if (sc->copyInto.offset == 0 && len > 0 && sc->entry->getReply()->sline.status == 0)
    -	/* Our structure ! */
    -	if (!httpReplyParse((HttpReply *)sc->entry->getReply(), sc->copyInto.data, headersEnd(sc->copyInto.data, len))) {
    -	    debug (90,0)("Could not parse headers from on disk object\n");
    -	}
    +        /* Our structure ! */
    +        if (!httpReplyParse((HttpReply *)sc->entry->getReply(), sc->copyInto.data, headersEnd(sc->copyInto.data, len))) {
    +            debug (90,0)("Could not parse headers from on disk object\n");
    +        }
    +
         sc->callback(len);
     }
     
     void
    -store_client::fail() 
    +store_client::fail()
     {
         object_ok = false;
         callback(0, true);
    @@ -423,35 +467,42 @@ void
     store_client::unpackHeader(char const *buf, ssize_t len)
     {
         debug(90, 3)("store_client::unpackHeader: len %d", (int) len);
    +
         if (len < 0) {
    -	debug(90, 3)("store_client::unpackHeader: %s", xstrerror());
    -	fail();
    -	return;
    +        debug(90, 3)("store_client::unpackHeader: %s", xstrerror());
    +        fail();
    +        return;
         }
    +
         int swap_hdr_sz = 0;
         StoreMetaUnpacker aBuilder(buf, len, &swap_hdr_sz);
    +
         if (!aBuilder.isBufferSane()) {
    -	/* oops, bad disk file? */
    -	debug(90, 1) ("WARNING: swapfile header inconsistent with available data\n");
    -	fail();
    -	return;
    +        /* oops, bad disk file? */
    +        debug(90, 1) ("WARNING: swapfile header inconsistent with available data\n");
    +        fail();
    +        return;
         }
    +
         tlv *tlv_list = aBuilder.createStoreMeta ();
    +
         if (tlv_list == NULL) {
    -	debug(90, 1) ("WARNING: failed to unpack meta data\n");
    -	fail();
    -	return;
    +        debug(90, 1) ("WARNING: failed to unpack meta data\n");
    +        fail();
    +        return;
         }
    +
         /*
          * Check the meta data and make sure we got the right object.
          */
         for (tlv *t = tlv_list; t; t = t->next) {
    -	if (!t->checkConsistency(entry)) {
    -	    storeSwapTLVFree(tlv_list);
    -	    fail();
    -	    return;
    -	}
    +        if (!t->checkConsistency(entry)) {
    +            storeSwapTLVFree(tlv_list);
    +            fail();
    +            return;
    +        }
         }
    +
         storeSwapTLVFree(tlv_list);
     
         entry->mem_obj->swap_hdr_sz = swap_hdr_sz;
    @@ -463,38 +514,43 @@ void
     store_client::readHeader(char const *buf, ssize_t len)
     {
         MemObject *const mem = entry->mem_obj;
    -    
    +
         assert(flags.disk_io_pending);
         flags.disk_io_pending = 0;
         assert(callbackPending());
     
         unpackHeader (buf, len);
    +
         if (!object_ok)
    -	return;
    -    
    +        return;
    +
         /*
          * If our last read got some data the client wants, then give
          * it to them, otherwise schedule another read.
          */
         size_t body_sz = len - mem->swap_hdr_sz;
    +
         if (static_cast(copyInto.offset) < body_sz) {
    -	/*
    -	 * we have (part of) what they want
    -	 */
    -	size_t copy_sz = XMIN(copyInto.length, body_sz);
    -	debug(90, 3) ("storeClientReadHeader: copying %d bytes of body\n",
    -	    (int) copy_sz);
    -	xmemmove(copyInto.data, copyInto.data + mem->swap_hdr_sz, copy_sz);
    -       if (copyInto.offset == 0 && len > 0 && entry->getReply()->sline.status == 0)
    -           /* Our structure ! */
    -           if (!httpReplyParse((HttpReply *)entry->getReply(), copyInto.data,
    -               headersEnd(copyInto.data, copy_sz))) {
    -               debug (90,0)("could not parse headers from on disk structure!\n");
    -           }
    +        /*
    +         * we have (part of) what they want
    +         */
    +        size_t copy_sz = XMIN(copyInto.length, body_sz)
    +                         ;
    +        debug(90, 3) ("storeClientReadHeader: copying %d bytes of body\n",
    +                      (int) copy_sz);
    +        xmemmove(copyInto.data, copyInto.data + mem->swap_hdr_sz, copy_sz);
    +
    +        if (copyInto.offset == 0 && len > 0 && entry->getReply()->sline.status == 0)
    +            /* Our structure ! */
    +            if (!httpReplyParse((HttpReply *)entry->getReply(), copyInto.data,
    +                                headersEnd(copyInto.data, copy_sz))) {
    +                debug (90,0)("could not parse headers from on disk structure!\n");
    +            }
     
             callback(copy_sz);
    -	return;
    +        return;
         }
    +
         /*
          * we don't have what the client wants, but at least we now
          * know the swap header size.
    @@ -509,15 +565,21 @@ storeClientCopyPending(store_client * sc, StoreEntry * e, void *data)
         assert(sc == storeClientListSearch(e->mem_obj, data));
     #endif
     #ifndef SILLY_CODE
    +
         assert(sc);
     #endif
    +
         assert(sc->entry == e);
     #if SILLY_CODE
    +
         if (sc == NULL)
    -	return 0;
    +        return 0;
    +
     #endif
    +
         if (!sc->callbackPending())
    -	return 0;
    +        return 0;
    +
         return 1;
     }
     
    @@ -530,48 +592,64 @@ storeUnregister(store_client * sc, StoreEntry * e, void *data)
     {
         MemObject *mem = e->mem_obj;
     #if STORE_CLIENT_LIST_DEBUG
    +
         assert(sc == storeClientListSearch(e->mem_obj, data));
     #endif
    +
         if (mem == NULL)
    -	return 0;
    +        return 0;
    +
         debug(90, 3) ("storeUnregister: called for '%s'\n", e->getMD5Text());
    +
         if (sc == NULL) {
    -	debug(90, 3) ("storeUnregister: No matching client for '%s'\n", e->getMD5Text());
    -	return 0;
    +        debug(90, 3) ("storeUnregister: No matching client for '%s'\n", e->getMD5Text());
    +        return 0;
         }
    +
         if (mem->clients.head == NULL) {
    -	debug(90, 3) ("storeUnregister: Consistency failure - store client being unregistered is not in the mem object's list for '%s'\n", e->getMD5Text());
    -	return 0;
    +        debug(90, 3) ("storeUnregister: Consistency failure - store client being unregistered is not in the mem object's list for '%s'\n", e->getMD5Text());
    +        return 0;
         }
    +
         if (sc == mem->clients.head->data) {
    -	/*
    -	 * If we are unregistering the _first_ client for this
    -	 * entry, then we have to reset the client FD to -1.
    -	 */
    -	mem->fd = -1;
    +        /*
    +         * If we are unregistering the _first_ client for this
    +         * entry, then we have to reset the client FD to -1.
    +         */
    +        mem->fd = -1;
         }
    +
         dlinkDelete(&sc->node, &mem->clients);
         mem->nclients--;
    +
         if (e->store_status == STORE_OK && e->swap_status != SWAPOUT_DONE)
    -	storeSwapOut(e);
    +        storeSwapOut(e);
    +
         if (sc->swapin_sio.getRaw()) {
    -	storeClose(sc->swapin_sio);
    -	sc->swapin_sio = NULL;
    -	statCounter.swap.ins++;
    +        storeClose(sc->swapin_sio);
    +        sc->swapin_sio = NULL;
    +        statCounter.swap.ins++;
         }
    -    if (sc->callbackPending()){
    -	/* callback with ssize = -1 to indicate unexpected termination */
    -	debug(90, 3) ("storeUnregister: store_client for %s has a callback\n",
    -	    mem->url);
    -	sc->fail();
    +
    +    if (sc->callbackPending()) {
    +        /* callback with ssize = -1 to indicate unexpected termination */
    +        debug(90, 3) ("storeUnregister: store_client for %s has a callback\n",
    +                      mem->url);
    +        sc->fail();
         }
    +
     #if STORE_CLIENT_LIST_DEBUG
         cbdataReferenceDone(sc->owner);
    +
     #endif
    +
         delete sc;
    +
         assert(e->lock_count > 0);
    +
         if (mem->nclients == 0)
    -	CheckQuickAbort(e);
    +        CheckQuickAbort(e);
    +
         return 1;
     }
     
    @@ -595,15 +673,19 @@ InvokeHandlers(StoreEntry * e)
     
         debug(90, 3) ("InvokeHandlers: %s\n", e->getMD5Text());
         /* walk the entire list looking for valid callbacks */
    +
         for (node = mem->clients.head; node; node = nx) {
    -	sc = (store_client *)node->data;
    -	nx = node->next;
    -	debug(90, 3) ("InvokeHandlers: checking client #%d\n", i++);
    -	if (!sc->callbackPending())
    -	    continue;
    -	if (sc->flags.disk_io_pending)
    -	    continue;
    -	storeClientCopy2(e, sc);
    +        sc = (store_client *)node->data;
    +        nx = node->next;
    +        debug(90, 3) ("InvokeHandlers: checking client #%d\n", i++);
    +
    +        if (!sc->callbackPending())
    +            continue;
    +
    +        if (sc->flags.disk_io_pending)
    +            continue;
    +
    +        storeClientCopy2(e, sc);
         }
     }
     
    @@ -626,42 +708,52 @@ CheckQuickAbort2(StoreEntry * entry)
         MemObject * const mem = entry->mem_obj;
         assert(mem);
         debug(90, 3) ("CheckQuickAbort2: entry=%p, mem=%p\n", entry, mem);
    +
         if (mem->request && !mem->request->flags.cachable) {
    -	debug(90, 3) ("CheckQuickAbort2: YES !mem->request->flags.cachable\n");
    -	return 1;
    +        debug(90, 3) ("CheckQuickAbort2: YES !mem->request->flags.cachable\n");
    +        return 1;
         }
    +
         if (EBIT_TEST(entry->flags, KEY_PRIVATE)) {
    -	debug(90, 3) ("CheckQuickAbort2: YES KEY_PRIVATE\n");
    -	return 1;
    +        debug(90, 3) ("CheckQuickAbort2: YES KEY_PRIVATE\n");
    +        return 1;
         }
    +
         expectlen = entry->getReply()->content_length + entry->getReply()->hdr_sz;
         assert (entry->getReply()->content_length + entry->getReply()->hdr_sz >= 0);
         curlen = (size_t) mem->endOffset ();
         minlen = (size_t) Config.quickAbort.min << 10;
    +
         if (minlen < 0) {
    -	debug(90, 3) ("CheckQuickAbort2: NO disabled\n");
    -	return 0;
    +        debug(90, 3) ("CheckQuickAbort2: NO disabled\n");
    +        return 0;
         }
    +
         if (curlen > expectlen) {
    -	debug(90, 3) ("CheckQuickAbort2: YES bad content length\n");
    -	return 1;
    +        debug(90, 3) ("CheckQuickAbort2: YES bad content length\n");
    +        return 1;
         }
    +
         if ((expectlen - curlen) < minlen) {
    -	debug(90, 3) ("CheckQuickAbort2: NO only little more left\n");
    -	return 0;
    +        debug(90, 3) ("CheckQuickAbort2: NO only little more left\n");
    +        return 0;
         }
    +
         if ((expectlen - curlen) > (Config.quickAbort.max << 10)) {
    -	debug(90, 3) ("CheckQuickAbort2: YES too much left to go\n");
    -	return 1;
    +        debug(90, 3) ("CheckQuickAbort2: YES too much left to go\n");
    +        return 1;
         }
    +
         if (expectlen < 100) {
    -	debug(90, 3) ("CheckQuickAbort2: NO avoid FPE\n");
    -	return 0;
    +        debug(90, 3) ("CheckQuickAbort2: NO avoid FPE\n");
    +        return 0;
         }
    +
         if ((curlen / (expectlen / 100)) > (size_t)Config.quickAbort.pct) {
    -	debug(90, 3) ("CheckQuickAbort2: NO past point of no return\n");
    -	return 0;
    +        debug(90, 3) ("CheckQuickAbort2: NO past point of no return\n");
    +        return 0;
         }
    +
         debug(90, 3) ("CheckQuickAbort2: YES default, returning 1\n");
         return 1;
     }
    @@ -670,14 +762,19 @@ static void
     CheckQuickAbort(StoreEntry * entry)
     {
         assert (entry);
    +
         if (storePendingNClients(entry) > 0)
    -	return;
    +        return;
    +
         if (entry->store_status != STORE_PENDING)
    -	return;
    +        return;
    +
         if (EBIT_TEST(entry->flags, ENTRY_SPECIAL))
    -	return;
    +        return;
    +
         if (CheckQuickAbort2(entry) == 0)
    -	return;
    +        return;
    +
         storeAbort(entry);
     }
     
    @@ -685,19 +782,27 @@ void
     store_client::dumpStats(StoreEntry * output, int clientNumber) const
     {
         if (callbackPending())
    -	return;
    +        return;
    +
         storeAppendPrintf(output, "\tClient #%d, %p\n", clientNumber, _callback.callback_data);
    +
         storeAppendPrintf(output, "\t\tcopy_offset: %lu\n",
    -	(unsigned long) copyInto.offset);
    +                      (unsigned long) copyInto.offset);
    +
         storeAppendPrintf(output, "\t\tcopy_size: %d\n",
    -	(int) copyInto.length);
    +                      (int) copyInto.length);
    +
         storeAppendPrintf(output, "\t\tflags:");
    +
         if (flags.disk_io_pending)
    -	storeAppendPrintf(output, " disk_io_pending");
    +        storeAppendPrintf(output, " disk_io_pending");
    +
         if (flags.store_copying)
    -	storeAppendPrintf(output, " store_copying");
    +        storeAppendPrintf(output, " store_copying");
    +
         if (flags.copy_event_pending)
    -	storeAppendPrintf(output, " copy_event_pending");
    +        storeAppendPrintf(output, " copy_event_pending");
    +
         storeAppendPrintf(output, "\n");
     }
     
    @@ -715,4 +820,5 @@ store_client::setDelayId(DelayId delay_id)
     {
         delayId = delay_id;
     }
    +
     #endif
    diff --git a/src/store_digest.cc b/src/store_digest.cc
    index f12cafa27b..31f2f20836 100644
    --- a/src/store_digest.cc
    +++ b/src/store_digest.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_digest.cc,v 1.55 2003/01/23 00:37:26 robertc Exp $
    + * $Id: store_digest.cc,v 1.56 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 71    Store Digest Manager
      * AUTHOR: Alex Rousskov
    @@ -52,7 +52,8 @@
      * local types
      */
     
    -typedef struct {
    +typedef struct
    +{
         StoreDigestCBlock cblock;
         int rebuild_lock;		/* bucket number */
         generic_cbdata *rewrite_lock;	/* points to store entry with the digest */
    @@ -60,16 +61,21 @@ typedef struct {
         int rewrite_offset;
         int rebuild_count;
         int rewrite_count;
    -} StoreDigestState;
    +}
     
    -typedef struct {
    +StoreDigestState;
    +
    +typedef struct
    +{
         int del_count;		/* #store entries deleted from store_digest */
         int del_lost_count;		/* #store entries not found in store_digest on delete */
         int add_count;		/* #store entries accepted to store_digest */
         int add_coll_count;		/* #accepted entries that collided with existing ones */
         int rej_count;		/* #store entries not accepted to store_digest */
         int rej_coll_count;		/* #not accepted entries that collided with existing ones */
    -} StoreDigestStats;
    +}
    +
    +StoreDigestStats;
     
     /* local vars */
     static StoreDigestState sd_state;
    @@ -102,17 +108,19 @@ storeDigestInit(void)
         const int cap = storeDigestCalcCap();
     
         if (!Config.onoff.digest_generation) {
    -	store_digest = NULL;
    -	debug(71, 3) ("Local cache digest generation disabled\n");
    -	return;
    +        store_digest = NULL;
    +        debug(71, 3) ("Local cache digest generation disabled\n");
    +        return;
         }
    +
         store_digest = cacheDigestCreate(cap, Config.digest.bits_per_entry);
         debug(71, 1) ("Local cache digest enabled; rebuild/rewrite every %d/%d sec\n",
    -	(int) Config.digest.rebuild_period, (int) Config.digest.rewrite_period);
    +                  (int) Config.digest.rebuild_period, (int) Config.digest.rewrite_period);
         memset(&sd_state, 0, sizeof(sd_state));
         cachemgrRegister("store_digest", "Store Digest",
    -	storeDigestReport, 0, 1);
    +                     storeDigestReport, 0, 1);
     #else
    +
         store_digest = NULL;
         debug(71, 3) ("Local cache digest is 'off'\n");
     #endif
    @@ -123,10 +131,12 @@ void
     storeDigestNoteStoreReady(void)
     {
     #if USE_CACHE_DIGESTS
    +
         if (Config.onoff.digest_generation) {
    -	storeDigestRebuildStart(NULL);
    -	storeDigestRewriteStart(NULL);
    +        storeDigestRebuildStart(NULL);
    +        storeDigestRewriteStart(NULL);
         }
    +
     #endif
     }
     
    @@ -134,24 +144,28 @@ void
     storeDigestDel(const StoreEntry * entry)
     {
     #if USE_CACHE_DIGESTS
    +
         if (!Config.onoff.digest_generation) {
    -	return;
    +        return;
         }
    +
         assert(entry && store_digest);
         debug(71, 6) ("storeDigestDel: checking entry, key: %s\n",
    -	entry->getMD5Text());
    +                  entry->getMD5Text());
    +
         if (!EBIT_TEST(entry->flags, KEY_PRIVATE)) {
    -	if (!cacheDigestTest(store_digest,  (const cache_key *)entry->key)) {
    -	    sd_stats.del_lost_count++;
    -	    debug(71, 6) ("storeDigestDel: lost entry, key: %s url: %s\n",
    -		entry->getMD5Text(), storeUrl(entry));
    -	} else {
    -	    sd_stats.del_count++;
    -	    cacheDigestDel(store_digest,  (const cache_key *)entry->key);
    -	    debug(71, 6) ("storeDigestDel: deled entry, key: %s\n",
    -		entry->getMD5Text());
    -	}
    +        if (!cacheDigestTest(store_digest,  (const cache_key *)entry->key)) {
    +            sd_stats.del_lost_count++;
    +            debug(71, 6) ("storeDigestDel: lost entry, key: %s url: %s\n",
    +                          entry->getMD5Text(), storeUrl(entry));
    +        } else {
    +            sd_stats.del_count++;
    +            cacheDigestDel(store_digest,  (const cache_key *)entry->key);
    +            debug(71, 6) ("storeDigestDel: deled entry, key: %s\n",
    +                          entry->getMD5Text());
    +        }
         }
    +
     #endif
     }
     
    @@ -159,22 +173,25 @@ void
     storeDigestReport(StoreEntry * e)
     {
     #if USE_CACHE_DIGESTS
    +
         if (!Config.onoff.digest_generation) {
    -	return;
    +        return;
         }
    +
         if (store_digest) {
    -	cacheDigestReport(store_digest, "store", e);
    -	storeAppendPrintf(e, "\t added: %d rejected: %d ( %.2f %%) del-ed: %d\n",
    -	    sd_stats.add_count,
    -	    sd_stats.rej_count,
    -	    xpercent(sd_stats.rej_count, sd_stats.rej_count + sd_stats.add_count),
    -	    sd_stats.del_count);
    -	storeAppendPrintf(e, "\t collisions: on add: %.2f %% on rej: %.2f %%\n",
    -	    xpercent(sd_stats.add_coll_count, sd_stats.add_count),
    -	    xpercent(sd_stats.rej_coll_count, sd_stats.rej_count));
    +        cacheDigestReport(store_digest, "store", e);
    +        storeAppendPrintf(e, "\t added: %d rejected: %d ( %.2f %%) del-ed: %d\n",
    +                          sd_stats.add_count,
    +                          sd_stats.rej_count,
    +                          xpercent(sd_stats.rej_count, sd_stats.rej_count + sd_stats.add_count),
    +                          sd_stats.del_count);
    +        storeAppendPrintf(e, "\t collisions: on add: %.2f %% on rej: %.2f %%\n",
    +                          xpercent(sd_stats.add_coll_count, sd_stats.add_count),
    +                          xpercent(sd_stats.rej_coll_count, sd_stats.rej_count));
         } else {
    -	storeAppendPrintf(e, "store digest: disabled.\n");
    +        storeAppendPrintf(e, "store digest: disabled.\n");
         }
    +
     #endif
     }
     
    @@ -191,41 +208,49 @@ storeDigestAddable(const StoreEntry * e)
         /* add some stats! XXX */
     
         debug(71, 6) ("storeDigestAddable: checking entry, key: %s\n",
    -	e->getMD5Text());
    +                  e->getMD5Text());
     
         /* check various entry flags (mimics storeCheckCachable XXX) */
    +
         if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
    -	debug(71, 6) ("storeDigestAddable: NO: not cachable\n");
    -	return 0;
    +        debug(71, 6) ("storeDigestAddable: NO: not cachable\n");
    +        return 0;
         }
    +
         if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
    -	debug(71, 6) ("storeDigestAddable: NO: private key\n");
    -	return 0;
    +        debug(71, 6) ("storeDigestAddable: NO: private key\n");
    +        return 0;
         }
    +
         if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) {
    -	debug(71, 6) ("storeDigestAddable: NO: negative cached\n");
    -	return 0;
    +        debug(71, 6) ("storeDigestAddable: NO: negative cached\n");
    +        return 0;
         }
    +
         if (EBIT_TEST(e->flags, RELEASE_REQUEST)) {
    -	debug(71, 6) ("storeDigestAddable: NO: release requested\n");
    -	return 0;
    +        debug(71, 6) ("storeDigestAddable: NO: release requested\n");
    +        return 0;
         }
    +
         if (e->store_status == STORE_OK && EBIT_TEST(e->flags, ENTRY_BAD_LENGTH)) {
    -	debug(71, 6) ("storeDigestAddable: NO: wrong content-length\n");
    -	return 0;
    +        debug(71, 6) ("storeDigestAddable: NO: wrong content-length\n");
    +        return 0;
         }
    +
         /* do not digest huge objects */
         if (e->swap_file_sz > Config.Store.maxObjectSize) {
    -	debug(71, 6) ("storeDigestAddable: NO: too big\n");
    -	return 0;
    +        debug(71, 6) ("storeDigestAddable: NO: too big\n");
    +        return 0;
         }
    +
         /* still here? check staleness */
         /* Note: We should use the time of the next rebuild, not (cur_time+period) */
         if (refreshCheckDigest(e, Config.digest.rebuild_period)) {
    -	debug(71, 6) ("storeDigestAdd: entry expires within %d secs, ignoring\n",
    -	    (int) Config.digest.rebuild_period);
    -	return 0;
    +        debug(71, 6) ("storeDigestAdd: entry expires within %d secs, ignoring\n",
    +                      (int) Config.digest.rebuild_period);
    +        return 0;
         }
    +
         /*
          * idea: how about also skipping very fresh (thus, potentially
          * unstable) entries? Should be configurable through
    @@ -237,8 +262,10 @@ storeDigestAddable(const StoreEntry * e)
          */
     #if OLD_UNUSED_CODE		/* This code isn't applicable anymore, we can't fix it atm either :( */
         if ((squid_curtime + Config.digest.rebuild_period) - e->lastref > storeExpiredReferenceAge())
    -	return 0;
    +        return 0;
    +
     #endif
    +
         return 1;
     }
     
    @@ -248,16 +275,20 @@ storeDigestAdd(const StoreEntry * entry)
         assert(entry && store_digest);
     
         if (storeDigestAddable(entry)) {
    -	sd_stats.add_count++;
    -	if (cacheDigestTest(store_digest, (const cache_key *)entry->key))
    -	    sd_stats.add_coll_count++;
    -	cacheDigestAdd(store_digest,  (const cache_key *)entry->key);
    -	debug(71, 6) ("storeDigestAdd: added entry, key: %s\n",
    -	    entry->getMD5Text());
    +        sd_stats.add_count++;
    +
    +        if (cacheDigestTest(store_digest, (const cache_key *)entry->key))
    +            sd_stats.add_coll_count++;
    +
    +        cacheDigestAdd(store_digest,  (const cache_key *)entry->key);
    +
    +        debug(71, 6) ("storeDigestAdd: added entry, key: %s\n",
    +                      entry->getMD5Text());
         } else {
    -	sd_stats.rej_count++;
    -	if (cacheDigestTest(store_digest,  (const cache_key *)entry->key))
    -	    sd_stats.rej_coll_count++;
    +        sd_stats.rej_count++;
    +
    +        if (cacheDigestTest(store_digest,  (const cache_key *)entry->key))
    +            sd_stats.rej_coll_count++;
         }
     }
     
    @@ -267,16 +298,20 @@ storeDigestRebuildStart(void *datanotused)
     {
         assert(store_digest);
         /* prevent overlapping if rebuild schedule is too tight */
    +
         if (sd_state.rebuild_lock) {
    -	debug(71, 1) ("storeDigestRebuildStart: overlap detected, consider increasing rebuild period\n");
    -	return;
    +        debug(71, 1) ("storeDigestRebuildStart: overlap detected, consider increasing rebuild period\n");
    +        return;
         }
    +
         sd_state.rebuild_lock = 1;
         debug(71, 2) ("storeDigestRebuildStart: rebuild #%d\n", sd_state.rebuild_count + 1);
    +
         if (sd_state.rewrite_lock) {
    -	debug(71, 2) ("storeDigestRebuildStart: waiting for Rewrite to finish.\n");
    -	return;
    +        debug(71, 2) ("storeDigestRebuildStart: waiting for Rewrite to finish.\n");
    +        return;
         }
    +
         storeDigestRebuildResume();
     }
     
    @@ -288,9 +323,12 @@ storeDigestRebuildResume(void)
         assert(!sd_state.rewrite_lock);
         sd_state.rebuild_offset = 0;
         /* resize or clear */
    +
         if (!storeDigestResize())
    -	cacheDigestClear(store_digest);		/* not clean()! */
    +        cacheDigestClear(store_digest);		/* not clean()! */
    +
         memset(&sd_stats, 0, sizeof(sd_stats));
    +
         eventAdd("storeDigestRebuildStep", storeDigestRebuildStep, NULL, 0.0, 1);
     }
     
    @@ -303,10 +341,11 @@ storeDigestRebuildFinish(void)
         sd_state.rebuild_count++;
         debug(71, 2) ("storeDigestRebuildFinish: done.\n");
         eventAdd("storeDigestRebuildStart", storeDigestRebuildStart, NULL, (double)
    -	Config.digest.rebuild_period, 1);
    +             Config.digest.rebuild_period, 1);
         /* resume pending Rewrite if any */
    +
         if (sd_state.rewrite_lock)
    -	storeDigestRewriteResume();
    +        storeDigestRewriteResume();
     }
     
     /* recalculate a few hash buckets per invocation; schedules next step */
    @@ -314,24 +353,30 @@ static void
     storeDigestRebuildStep(void *datanotused)
     {
         int bcount = (int) ceil((double) store_hash_buckets *
    -	(double) Config.digest.rebuild_chunk_percentage / 100.0);
    +                            (double) Config.digest.rebuild_chunk_percentage / 100.0);
         assert(sd_state.rebuild_lock);
    +
         if (sd_state.rebuild_offset + bcount > store_hash_buckets)
    -	bcount = store_hash_buckets - sd_state.rebuild_offset;
    +        bcount = store_hash_buckets - sd_state.rebuild_offset;
    +
         debug(71, 3) ("storeDigestRebuildStep: buckets: %d offset: %d chunk: %d buckets\n",
    -	store_hash_buckets, sd_state.rebuild_offset, bcount);
    +                  store_hash_buckets, sd_state.rebuild_offset, bcount);
    +
         while (bcount--) {
    -	hash_link *link_ptr = hash_get_bucket(store_table, sd_state.rebuild_offset);
    -	for (; link_ptr; link_ptr = link_ptr->next) {
    -	    storeDigestAdd((StoreEntry *) link_ptr);
    -	}
    -	sd_state.rebuild_offset++;
    +        hash_link *link_ptr = hash_get_bucket(store_table, sd_state.rebuild_offset);
    +
    +        for (; link_ptr; link_ptr = link_ptr->next) {
    +            storeDigestAdd((StoreEntry *) link_ptr);
    +        }
    +
    +        sd_state.rebuild_offset++;
         }
    +
         /* are we done ? */
         if (sd_state.rebuild_offset >= store_hash_buckets)
    -	storeDigestRebuildFinish();
    +        storeDigestRebuildFinish();
         else
    -	eventAdd("storeDigestRebuildStep", storeDigestRebuildStep, NULL, 0.0, 1);
    +        eventAdd("storeDigestRebuildStep", storeDigestRebuildStep, NULL, 0.0, 1);
     }
     
     
    @@ -345,10 +390,12 @@ storeDigestRewriteStart(void *datanotused)
     
         assert(store_digest);
         /* prevent overlapping if rewrite schedule is too tight */
    +
         if (sd_state.rewrite_lock) {
    -	debug(71, 1) ("storeDigestRewrite: overlap detected, consider increasing rewrite period\n");
    -	return;
    +        debug(71, 1) ("storeDigestRewrite: overlap detected, consider increasing rewrite period\n");
    +        return;
         }
    +
         debug(71, 2) ("storeDigestRewrite: start rewrite #%d\n", sd_state.rewrite_count + 1);
         /* make new store entry */
         url = internalLocalUri("/squid-internal-periodic/", StoreDigestFileName);
    @@ -360,10 +407,12 @@ storeDigestRewriteStart(void *datanotused)
         debug(71, 3) ("storeDigestRewrite: url: %s key: %s\n", url, e->getMD5Text());
         e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
         /* wait for rebuild (if any) to finish */
    +
         if (sd_state.rebuild_lock) {
    -	debug(71, 2) ("storeDigestRewriteStart: waiting for rebuild to finish.\n");
    -	return;
    +        debug(71, 2) ("storeDigestRewriteStart: waiting for rebuild to finish.\n");
    +        return;
         }
    +
         storeDigestRewriteResume();
     }
     
    @@ -384,10 +433,10 @@ storeDigestRewriteResume(void)
         HttpReply *rep = httpReplyCreate ();
         httpBuildVersion(&version, 1, 0);
         httpReplySetHeaders(rep, version, HTTP_OK, "Cache Digest OK",
    -	"application/cache-digest", store_digest->mask_size + sizeof(sd_state.cblock),
    -	squid_curtime, squid_curtime + Config.digest.rewrite_period);
    +                        "application/cache-digest", store_digest->mask_size + sizeof(sd_state.cblock),
    +                        squid_curtime, squid_curtime + Config.digest.rewrite_period);
         debug(71, 3) ("storeDigestRewrite: entry expires on %ld (%+d)\n",
    -	(long int) rep->expires, (int) (rep->expires - squid_curtime));
    +                  (long int) rep->expires, (int) (rep->expires - squid_curtime));
         storeBuffer(e);
         httpReplySwapOut(rep, e);
         storeDigestCBlockSwapOut(e);
    @@ -403,7 +452,7 @@ storeDigestRewriteFinish(StoreEntry * e)
         e->complete();
         storeTimestampsSet(e);
         debug(71, 2) ("storeDigestRewriteFinish: digest expires at %ld (%+d)\n",
    -	(long int) e->expires, (int) (e->expires - squid_curtime));
    +                  (long int) e->expires, (int) (e->expires - squid_curtime));
         /* is this the write order? @?@ */
         e->mem_obj->unlinkRequest();
         storeUnlockObject(e);
    @@ -411,10 +460,11 @@ storeDigestRewriteFinish(StoreEntry * e)
         sd_state.rewrite_lock = NULL;
         sd_state.rewrite_count++;
         eventAdd("storeDigestRewriteStart", storeDigestRewriteStart, NULL, (double)
    -	Config.digest.rewrite_period, 1);
    +             Config.digest.rewrite_period, 1);
         /* resume pending Rebuild if any */
    +
         if (sd_state.rebuild_lock)
    -	storeDigestRebuildResume();
    +        storeDigestRebuildResume();
     }
     
     /* swaps out one digest "chunk" per invocation; schedules next swap out */
    @@ -427,17 +477,22 @@ storeDigestSwapOutStep(void *data)
         e = (StoreEntry *) ((generic_cbdata *) data)->data;
         assert(e);
         /* _add_ check that nothing bad happened while we were waiting @?@ @?@ */
    +
         if ((size_t)(sd_state.rewrite_offset + chunk_size) > store_digest->mask_size)
    -	chunk_size = store_digest->mask_size - sd_state.rewrite_offset;
    +        chunk_size = store_digest->mask_size - sd_state.rewrite_offset;
    +
         storeAppend(e, store_digest->mask + sd_state.rewrite_offset, chunk_size);
    +
         debug(71, 3) ("storeDigestSwapOutStep: size: %d offset: %d chunk: %d bytes\n",
    -	store_digest->mask_size, sd_state.rewrite_offset, chunk_size);
    +                  store_digest->mask_size, sd_state.rewrite_offset, chunk_size);
    +
         sd_state.rewrite_offset += chunk_size;
    +
         /* are we done ? */
         if ((size_t)sd_state.rewrite_offset >= store_digest->mask_size)
    -	storeDigestRewriteFinish(e);
    +        storeDigestRewriteFinish(e);
         else
    -	eventAdd("storeDigestSwapOutStep", storeDigestSwapOutStep, data, 0.0, 1);
    +        eventAdd("storeDigestSwapOutStep", storeDigestSwapOutStep, data, 0.0, 1);
     }
     
     static void
    @@ -451,7 +506,7 @@ storeDigestCBlockSwapOut(StoreEntry * e)
         sd_state.cblock.del_count = htonl(store_digest->del_count);
         sd_state.cblock.mask_size = htonl(store_digest->mask_size);
         sd_state.cblock.bits_per_entry = (unsigned char)
    -	Config.digest.bits_per_entry;
    +                                     Config.digest.bits_per_entry;
         sd_state.cblock.hash_func_count = (unsigned char) CacheDigestHashFuncCount;
         storeAppend(e, (char *) &sd_state.cblock, sizeof(sd_state.cblock));
     }
    @@ -470,9 +525,11 @@ storeDigestCalcCap(void)
         const int e_count = StoreEntry::inUseCount();
         int cap = e_count ? e_count : hi_cap;
         debug(71, 2) ("storeDigestCalcCap: have: %d, want %d entries; limits: [%d, %d]\n",
    -	e_count, cap, lo_cap, hi_cap);
    +                  e_count, cap, lo_cap, hi_cap);
    +
         if (cap < lo_cap)
    -	cap = lo_cap;
    +        cap = lo_cap;
    +
         /* do not enforce hi_cap limit, average-based estimation may be wrong
          *if (cap > hi_cap)
          *  cap = hi_cap; 
    @@ -489,16 +546,17 @@ storeDigestResize(void)
         assert(store_digest);
         diff = abs(cap - store_digest->capacity);
         debug(71, 2) ("storeDigestResize: %d -> %d; change: %d (%d%%)\n",
    -	store_digest->capacity, cap, diff,
    -	xpercentInt(diff, store_digest->capacity));
    +                  store_digest->capacity, cap, diff,
    +                  xpercentInt(diff, store_digest->capacity));
         /* avoid minor adjustments */
    +
         if (diff <= store_digest->capacity / 10) {
    -	debug(71, 2) ("storeDigestResize: small change, will not resize.\n");
    -	return 0;
    +        debug(71, 2) ("storeDigestResize: small change, will not resize.\n");
    +        return 0;
         } else {
    -	debug(71, 2) ("storeDigestResize: big change, resizing.\n");
    -	cacheDigestChangeCap(store_digest, cap);
    -	return 1;
    +        debug(71, 2) ("storeDigestResize: big change, resizing.\n");
    +        cacheDigestChangeCap(store_digest, cap);
    +        return 1;
         }
     }
     
    diff --git a/src/store_dir.cc b/src/store_dir.cc
    index ba74804348..76debfa0c4 100644
    --- a/src/store_dir.cc
    +++ b/src/store_dir.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_dir.cc,v 1.144 2003/02/04 22:25:16 robertc Exp $
    + * $Id: store_dir.cc,v 1.145 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 47    Store Directory Routines
      * AUTHOR: Duane Wessels
    @@ -63,32 +63,40 @@ void
     storeDirInit(void)
     {
         int i;
    +
         for (i = 0; i < Config.cacheSwap.n_configured; i++)
    -	INDEXSD(i)->init();
    +        INDEXSD(i)->init();
    +
         if (0 == strcasecmp(Config.store_dir_select_algorithm, "round-robin")) {
    -	storeDirSelectSwapDir = storeDirSelectSwapDirRoundRobin;
    -	debug(47, 1) ("Using Round Robin store dir selection\n");
    +        storeDirSelectSwapDir = storeDirSelectSwapDirRoundRobin;
    +        debug(47, 1) ("Using Round Robin store dir selection\n");
         } else {
    -	storeDirSelectSwapDir = storeDirSelectSwapDirLeastLoad;
    -	debug(47, 1) ("Using Least Load store dir selection\n");
    +        storeDirSelectSwapDir = storeDirSelectSwapDirLeastLoad;
    +        debug(47, 1) ("Using Least Load store dir selection\n");
         }
     }
     
     void
     startOneStoreCreation(SwapDir &swapDir)
     {
    -    /* 
    +    /*
          * On Windows, fork() is not available.
          * The following is a workaround for create store directories sequentially
          * when running on native Windows port.
          */
     #ifndef _SQUID_MSWIN_
    +
         if (fork())
    -	return;
    +        return;
    +
     #endif
    +
         swapDir.newFileSystem();
    +
     #ifndef _SQUID_MSWIN_
    +
         exit(0);
    +
     #endif
     }
     
    @@ -96,17 +104,24 @@ void
     storeCreateSwapDirectories(void)
     {
         for (int i = 0; i < Config.cacheSwap.n_configured; i++)
    -	startOneStoreCreation(*INDEXSD(i));
    +        startOneStoreCreation(*INDEXSD(i));
    +
     #ifndef _SQUID_MSWIN_
    +
         pid_t pid;
    +
         do {
    -	int status;
    +        int status;
     #ifdef _SQUID_NEXT_
    -	pid = wait3(&status, WNOHANG, NULL);
    +
    +        pid = wait3(&status, WNOHANG, NULL);
     #else
    -	pid = waitpid(-1, &status, 0);
    +
    +        pid = waitpid(-1, &status, 0);
     #endif
    +
         } while (pid > 0 || (pid < 0 && errno == EINTR));
    +
     #endif
     }
     
    @@ -124,24 +139,25 @@ storeDirValidSwapDirSize(int swapdir, ssize_t objsize)
         /*
          * If the swapdir's max_obj_size is -1, then it definitely can
          */
    +
         if (INDEXSD(swapdir)->max_objsize == -1)
    -	return 1;
    +        return 1;
     
         /*
          * If the object size is -1, then if the storedir isn't -1 we
          * can't store it
          */
         if ((objsize == -1) &&
    -	(INDEXSD(swapdir)->max_objsize != -1))
    -	return 0;
    +            (INDEXSD(swapdir)->max_objsize != -1))
    +        return 0;
     
         /*
          * Else, make sure that the max object size is larger than objsize
          */
         if (INDEXSD(swapdir)->max_objsize > objsize)
    -	return 1;
    +        return 1;
         else
    -	return 0;
    +        return 0;
     }
     
     
    @@ -158,23 +174,32 @@ storeDirSelectSwapDirRoundRobin(const StoreEntry * e)
         int load;
         SwapDir *sd;
         ssize_t objsize = (ssize_t) objectLen(e);
    +
         for (i = 0; i <= Config.cacheSwap.n_configured; i++) {
    -	if (++dirn >= Config.cacheSwap.n_configured)
    -	    dirn = 0;
    -	sd = INDEXSD(dirn);
    -	if (sd->flags.read_only)
    -	    continue;
    -	if (sd->cur_size > sd->max_size)
    -	    continue;
    -	if (!storeDirValidSwapDirSize(i, objsize))
    -	    continue;
    -	/* check for error or overload condition */
    -	load = sd->canStore(*e);
    -	if (load < 0 || load > 1000) {
    -	    continue;
    -	}
    -	return dirn;
    +        if (++dirn >= Config.cacheSwap.n_configured)
    +            dirn = 0;
    +
    +        sd = INDEXSD(dirn);
    +
    +        if (sd->flags.read_only)
    +            continue;
    +
    +        if (sd->cur_size > sd->max_size)
    +            continue;
    +
    +        if (!storeDirValidSwapDirSize(i, objsize))
    +            continue;
    +
    +        /* check for error or overload condition */
    +        load = sd->canStore(*e);
    +
    +        if (load < 0 || load > 1000) {
    +            continue;
    +        }
    +
    +        return dirn;
         }
    +
         return -1;
     }
     
    @@ -205,41 +230,55 @@ storeDirSelectSwapDirLeastLoad(const StoreEntry * e)
     
         /* Calculate the object size */
         objsize = (ssize_t) objectLen(e);
    +
         if (objsize != -1)
    -	objsize += e->mem_obj->swap_hdr_sz;
    +        objsize += e->mem_obj->swap_hdr_sz;
    +
         for (i = 0; i < Config.cacheSwap.n_configured; i++) {
    -	SD = INDEXSD(i);
    -	SD->flags.selected = 0;
    -	load = SD->canStore(*e);
    -	if (load < 0 || load > 1000) {
    -	    continue;
    -	}
    -	if (!storeDirValidSwapDirSize(i, objsize))
    -	    continue;
    -	if (SD->flags.read_only)
    -	    continue;
    -	if (SD->cur_size > SD->max_size)
    -	    continue;
    -	if (load > least_load)
    -	    continue;
    -	cur_free = SD->max_size - SD->cur_size;
    -	/* If the load is equal, then look in more details */
    -	if (load == least_load) {
    -	    /* closest max_objsize fit */
    -	    if (least_objsize != -1)
    -		if (SD->max_objsize > least_objsize || SD->max_objsize == -1)
    -		    continue;
    -	    /* most free */
    -	    if (cur_free < most_free)
    -		continue;
    -	}
    -	least_load = load;
    -	least_objsize = SD->max_objsize;
    -	most_free = cur_free;
    -	dirn = i;
    +        SD = INDEXSD(i);
    +        SD->flags.selected = 0;
    +        load = SD->canStore(*e);
    +
    +        if (load < 0 || load > 1000) {
    +            continue;
    +        }
    +
    +        if (!storeDirValidSwapDirSize(i, objsize))
    +            continue;
    +
    +        if (SD->flags.read_only)
    +            continue;
    +
    +        if (SD->cur_size > SD->max_size)
    +            continue;
    +
    +        if (load > least_load)
    +            continue;
    +
    +        cur_free = SD->max_size - SD->cur_size;
    +
    +        /* If the load is equal, then look in more details */
    +        if (load == least_load) {
    +            /* closest max_objsize fit */
    +
    +            if (least_objsize != -1)
    +                if (SD->max_objsize > least_objsize || SD->max_objsize == -1)
    +                    continue;
    +
    +            /* most free */
    +            if (cur_free < most_free)
    +                continue;
    +        }
    +
    +        least_load = load;
    +        least_objsize = SD->max_objsize;
    +        most_free = cur_free;
    +        dirn = i;
         }
    +
         if (dirn >= 0)
    -	INDEXSD(dirn)->flags.selected = 1;
    +        INDEXSD(dirn)->flags.selected = 1;
    +
         return dirn;
     }
     
    @@ -270,14 +309,18 @@ storeDirSwapLog(const StoreEntry * e, int op)
         /*
          * icons and such; don't write them to the swap log
          */
    +
         if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
    -	return;
    +        return;
    +
         assert(op > SWAP_LOG_NOP && op < SWAP_LOG_MAX);
    +
         debug(20, 3) ("storeDirSwapLog: %s %s %d %08X\n",
    -	swap_log_op_str[op],
    -	e->getMD5Text(),
    -	e->swap_dirn,
    -	e->swap_filen);
    +                  swap_log_op_str[op],
    +                  e->getMD5Text(),
    +                  e->swap_dirn,
    +                  e->swap_filen);
    +
         INDEXSD(e->swap_dirn)->logEntry(*e, op);
     }
     
    @@ -288,10 +331,11 @@ storeDirUpdateSwapSize(SwapDir * SD, size_t size, int sign)
         int k = (blks * SD->fs.blksize >> 10) * sign;
         SD->cur_size += k;
         store_swap_size += k;
    +
         if (sign > 0)
    -	n_disk_objects++;
    +        n_disk_objects++;
         else if (sign < 0)
    -	n_disk_objects--;
    +        n_disk_objects--;
     }
     
     void
    @@ -303,30 +347,33 @@ storeDirStats(StoreEntry * sentry)
     
         storeAppendPrintf(sentry, "Store Directory Statistics:\n");
         storeAppendPrintf(sentry, "Store Entries          : %lu\n",
    -	(unsigned long int)StoreEntry::inUseCount());
    +                      (unsigned long int)StoreEntry::inUseCount());
         storeAppendPrintf(sentry, "Maximum Swap Size      : %8ld KB\n",
    -	(long int) Config.Swap.maxSize);
    +                      (long int) Config.Swap.maxSize);
         storeAppendPrintf(sentry, "Current Store Swap Size: %8lu KB\n",
    -	store_swap_size);
    +                      store_swap_size);
         storeAppendPrintf(sentry, "Current Capacity       : %d%% used, %d%% free\n",
    -	percent((int) store_swap_size, (int) Config.Swap.maxSize),
    -	percent((int) (Config.Swap.maxSize - store_swap_size), (int) Config.Swap.maxSize));
    +                      percent((int) store_swap_size, (int) Config.Swap.maxSize),
    +                      percent((int) (Config.Swap.maxSize - store_swap_size), (int) Config.Swap.maxSize));
         /* FIXME Here we should output memory statistics */
     
         /* Now go through each swapdir, calling its statfs routine */
    +
         for (i = 0; i < Config.cacheSwap.n_configured; i++) {
    -	storeAppendPrintf(sentry, "\n");
    -	SD = INDEXSD(i);
    -	storeAppendPrintf(sentry, "Store Directory #%d (%s): %s\n", i, SD->type,
    -	    storeSwapDir(i));
    -	storeAppendPrintf(sentry, "FS Block Size %d Bytes\n",
    -	    SD->fs.blksize);
    -	SD->statfs(*sentry);
    -	if (SD->repl) {
    -	    storeAppendPrintf(sentry, "Removal policy: %s\n", SD->repl->_type);
    -	    if (SD->repl->Stats)
    -		SD->repl->Stats(SD->repl, sentry);
    -	}
    +        storeAppendPrintf(sentry, "\n");
    +        SD = INDEXSD(i);
    +        storeAppendPrintf(sentry, "Store Directory #%d (%s): %s\n", i, SD->type,
    +                          storeSwapDir(i));
    +        storeAppendPrintf(sentry, "FS Block Size %d Bytes\n",
    +                          SD->fs.blksize);
    +        SD->statfs(*sentry);
    +
    +        if (SD->repl) {
    +            storeAppendPrintf(sentry, "Removal policy: %s\n", SD->repl->_type);
    +
    +            if (SD->repl->Stats)
    +                SD->repl->Stats(SD->repl, sentry);
    +        }
         }
     }
     
    @@ -336,11 +383,12 @@ storeDirConfigure(void)
         SwapDir *SD;
         int i;
         Config.Swap.maxSize = 0;
    +
         for (i = 0; i < Config.cacheSwap.n_configured; i++) {
    -	SD = INDEXSD(i);
    -	Config.Swap.maxSize += SD->max_size;
    -	SD->low_size = (int) (((float) SD->max_size *
    -		(float) Config.Swap.lowWaterMark) / 100.0);
    +        SD = INDEXSD(i);
    +        Config.Swap.maxSize += SD->max_size;
    +        SD->low_size = (int) (((float) SD->max_size *
    +                               (float) Config.Swap.lowWaterMark) / 100.0);
         }
     }
     
    @@ -349,25 +397,28 @@ storeDirDiskFull(sdirno dirn)
     {
         SwapDir *SD = INDEXSD(dirn);
         assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
    +
         if (SD->cur_size >= SD->max_size)
    -	return;
    +        return;
    +
         SD->max_size = SD->cur_size;
    +
         debug(20, 1) ("WARNING: Shrinking cache_dir #%d to %d KB\n",
    -	dirn, SD->cur_size);
    +                  dirn, SD->cur_size);
     }
     
     void
     storeDirOpenSwapLogs(void)
     {
         for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
    -	INDEXSD(dirn)->openLog();
    +        INDEXSD(dirn)->openLog();
     }
     
     void
     storeDirCloseSwapLogs(void)
     {
         for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
    -	INDEXSD(dirn)->closeLog();
    +        INDEXSD(dirn)->closeLog();
     }
     
     /*
    @@ -384,58 +435,79 @@ storeDirWriteCleanLogs(int reopen)
     {
         const StoreEntry *e = NULL;
         int n = 0;
    +
         struct timeval start;
         double dt;
         SwapDir *sd;
         int dirn;
         int notdone = 1;
    +
         if (store_dirs_rebuilding) {
    -	debug(20, 1) ("Not currently OK to rewrite swap log.\n");
    -	debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.\n");
    -	return 0;
    +        debug(20, 1) ("Not currently OK to rewrite swap log.\n");
    +        debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.\n");
    +        return 0;
         }
    +
         debug(20, 1) ("storeDirWriteCleanLogs: Starting...\n");
         getCurrentTime();
         start = current_time;
    +
         for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
    -	sd = INDEXSD(dirn);
    -	if (sd->writeCleanStart() < 0) {
    -	    debug(20, 1) ("log.clean.start() failed for dir #%d\n", sd->index);
    -	    continue;
    -	}
    +        sd = INDEXSD(dirn);
    +
    +        if (sd->writeCleanStart() < 0) {
    +            debug(20, 1) ("log.clean.start() failed for dir #%d\n", sd->index);
    +            continue;
    +        }
         }
    +
         /* This writes all logs in parallel. It seems to me to be more efficient
          * to write them sequentially. - RBC 20021214
          */
         while (notdone) {
    -	notdone = 0;
    -	for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
    -	    sd = INDEXSD(dirn);
    -	    if (NULL == sd->cleanLog)
    -		continue;
    -	    e = sd->cleanLog->nextEntry();
    -	    if (!e)
    -		continue;
    -	    notdone = 1;
    -	    if (!sd->canLog(*e))
    -		continue;
    -	    sd->cleanLog->write(*e);
    -	    if ((++n & 0xFFFF) == 0) {
    -		getCurrentTime();
    -		debug(20, 1) ("  %7d entries written so far.\n", n);
    -	    }
    -	}
    +        notdone = 0;
    +
    +        for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
    +            sd = INDEXSD(dirn);
    +
    +            if (NULL == sd->cleanLog)
    +                continue;
    +
    +            e = sd->cleanLog->nextEntry();
    +
    +            if (!e)
    +                continue;
    +
    +            notdone = 1;
    +
    +            if (!sd->canLog(*e))
    +                continue;
    +
    +            sd->cleanLog->write(*e);
    +
    +            if ((++n & 0xFFFF) == 0) {
    +                getCurrentTime();
    +                debug(20, 1) ("  %7d entries written so far.\n", n);
    +            }
    +        }
         }
    +
         /* Flush */
         for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++)
    -	INDEXSD(dirn)->writeCleanDone();
    +        INDEXSD(dirn)->writeCleanDone();
    +
         if (reopen)
    -	storeDirOpenSwapLogs();
    +        storeDirOpenSwapLogs();
    +
         getCurrentTime();
    +
         dt = tvSubDsec(start, current_time);
    +
         debug(20, 1) ("  Finished.  Wrote %d entries.\n", n);
    +
         debug(20, 1) ("  Took %3.1f seconds (%6.1f entries/sec).\n",
    -	dt, (double) n / (dt > 0.0 ? dt : 1.0));
    +                  dt, (double) n / (dt > 0.0 ? dt : 1.0));
    +
         return n;
     }
     
    @@ -446,7 +518,7 @@ void
     storeDirSync(void)
     {
         for (int i = 0; i < Config.cacheSwap.n_configured; ++i)
    -	INDEXSD(i)->sync();
    +        INDEXSD(i)->sync();
     }
     
     /*
    @@ -458,16 +530,22 @@ storeDirCallback(void)
         int i, j;
         SwapDir *SD;
         static int ndir = 0;
    +
         do {
    -	j = 0;
    -	for (i = 0; i < Config.cacheSwap.n_configured; i++) {
    -	    if (ndir >= Config.cacheSwap.n_configured)
    -		ndir = ndir % Config.cacheSwap.n_configured;
    -	    SD = INDEXSD(ndir);
    -	    ++ndir;
    -	    j += SD->callback();
    -	}
    +        j = 0;
    +
    +        for (i = 0; i < Config.cacheSwap.n_configured; i++) {
    +            if (ndir >= Config.cacheSwap.n_configured)
    +                ndir = ndir % Config.cacheSwap.n_configured;
    +
    +            SD = INDEXSD(ndir);
    +
    +            ++ndir;
    +
    +            j += SD->callback();
    +        }
         } while (j > 0);
    +
         ndir++;
     }
     
    @@ -475,27 +553,35 @@ int
     storeDirGetBlkSize(const char *path, int *blksize)
     {
     #if HAVE_STATVFS
    +
         struct statvfs sfs;
    +
         if (statvfs(path, &sfs)) {
    -	debug(50, 1) ("%s: %s\n", path, xstrerror());
    -	*blksize = 2048;
    -	return 1;
    +        debug(50, 1) ("%s: %s\n", path, xstrerror());
    +        *blksize = 2048;
    +        return 1;
         }
    +
         *blksize = (int) sfs.f_frsize;
     #else
    +
         struct statfs sfs;
    +
         if (statfs(path, &sfs)) {
    -	debug(50, 1) ("%s: %s\n", path, xstrerror());
    -	*blksize = 2048;
    -	return 1;
    +        debug(50, 1) ("%s: %s\n", path, xstrerror());
    +        *blksize = 2048;
    +        return 1;
         }
    +
         *blksize = (int) sfs.f_bsize;
     #endif
         /*
          * Sanity check; make sure we have a meaningful value.
          */
    +
         if (*blksize < 512)
    -	*blksize = 2048;
    +        *blksize = 2048;
    +
         return 0;
     }
     
    @@ -506,25 +592,32 @@ int
     storeDirGetUFSStats(const char *path, int *totl_kb, int *free_kb, int *totl_in, int *free_in)
     {
     #if HAVE_STATVFS
    +
         struct statvfs sfs;
    +
         if (statvfs(path, &sfs)) {
    -	debug(50, 1) ("%s: %s\n", path, xstrerror());
    -	return 1;
    +        debug(50, 1) ("%s: %s\n", path, xstrerror());
    +        return 1;
         }
    +
         *totl_kb = (int) fsbtoblk(sfs.f_blocks, sfs.f_frsize, 1024);
         *free_kb = (int) fsbtoblk(sfs.f_bfree, sfs.f_frsize, 1024);
         *totl_in = (int) sfs.f_files;
         *free_in = (int) sfs.f_ffree;
     #else
    +
         struct statfs sfs;
    +
         if (statfs(path, &sfs)) {
    -	debug(50, 1) ("%s: %s\n", path, xstrerror());
    -	return 1;
    +        debug(50, 1) ("%s: %s\n", path, xstrerror());
    +        return 1;
         }
    +
         *totl_kb = (int) fsbtoblk(sfs.f_blocks, sfs.f_bsize, 1024);
         *free_kb = (int) fsbtoblk(sfs.f_bfree, sfs.f_bsize, 1024);
         *totl_in = (int) sfs.f_files;
         *free_in = (int) sfs.f_ffree;
     #endif
    +
         return 0;
     }
    diff --git a/src/store_io.cc b/src/store_io.cc
    index 61f6762893..43b1c60226 100644
    --- a/src/store_io.cc
    +++ b/src/store_io.cc
    @@ -3,14 +3,21 @@
     #include "MemObject.h"
     #include "SwapDir.h"
     
    -static struct {
    -    struct {
    -	int calls;
    -	int select_fail;
    -	int create_fail;
    -	int success;
    -    } create;
    -} store_io_stats;
    +static struct
    +{
    +
    +    struct
    +    {
    +        int calls;
    +        int select_fail;
    +        int create_fail;
    +        int success;
    +    }
    +
    +    create;
    +}
    +
    +store_io_stats;
     
     OBJH storeIOStats;
     
    @@ -31,28 +38,33 @@ storeCreate(StoreEntry * e, STIOCB * file_callback, STIOCB * close_callback, voi
         store_io_stats.create.calls++;
         /* This is just done for logging purposes */
         objsize = objectLen(e);
    +
         if (objsize != -1)
    -	objsize += e->mem_obj->swap_hdr_sz;
    +        objsize += e->mem_obj->swap_hdr_sz;
     
         /*
          * Pick the swapdir
          * We assume that the header has been packed by now ..
          */
         dirn = storeDirSelectSwapDir(e);
    +
         if (dirn == -1) {
    -	debug(20, 2) ("storeCreate: no valid swapdirs for this object\n");
    -	store_io_stats.create.select_fail++;
    -	return NULL;
    +        debug(20, 2) ("storeCreate: no valid swapdirs for this object\n");
    +        store_io_stats.create.select_fail++;
    +        return NULL;
         }
    +
         debug(20, 2) ("storeCreate: Selected dir '%d' for obj size '%ld'\n", dirn, (long int) objsize);
         SD = INDEXSD(dirn);
     
         /* Now that we have a fs to use, call its storeCreate function */
         StoreIOState::Pointer sio = SD->createStoreIO(*e, file_callback, close_callback, callback_data);
    +
         if (sio == NULL)
    -	store_io_stats.create.create_fail++;
    +        store_io_stats.create.create_fail++;
         else
    -	store_io_stats.create.success++;
    +        store_io_stats.create.success++;
    +
         return sio;
     }
     
    @@ -61,7 +73,7 @@ storeCreate(StoreEntry * e, STIOCB * file_callback, STIOCB * close_callback, voi
      */
     StoreIOState::Pointer
     storeOpen(StoreEntry * e, STFNCB * file_callback, STIOCB * callback,
    -    void *callback_data)
    +          void *callback_data)
     {
         return INDEXSD(e->swap_dirn)->openStoreIO(*e, file_callback, callback, callback_data);
     }
    @@ -70,8 +82,10 @@ void
     storeClose(StoreIOState::Pointer sio)
     {
         if (sio->flags.closing)
    -	return;
    +        return;
    +
         sio->flags.closing = 1;
    +
         sio->close();
     }
     
    diff --git a/src/store_key_md5.cc b/src/store_key_md5.cc
    index c1ff825022..a073a0ac50 100644
    --- a/src/store_key_md5.cc
    +++ b/src/store_key_md5.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_key_md5.cc,v 1.28 2003/01/23 00:37:26 robertc Exp $
    + * $Id: store_key_md5.cc,v 1.29 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 20    Storage Manager MD5 Cache Keys
      * AUTHOR: Duane Wessels
    @@ -42,8 +42,10 @@ storeKeyText(const unsigned char *key)
     {
         static char buf[MD5_DIGEST_CHARS * 2+1];
         int i;
    +
         for (i = 0; i < MD5_DIGEST_CHARS; i++)
    -	snprintf(&buf[i*2],sizeof(buf) - i*2, "%02X", *(key + i));
    +        snprintf(&buf[i*2],sizeof(buf) - i*2, "%02X", *(key + i));
    +
         return buf;
     }
     
    @@ -54,12 +56,14 @@ storeKeyScan(const char *buf)
         int i;
         int j = 0;
         char t[3];
    +
         for (i = 0; i < MD5_DIGEST_CHARS; i++) {
    -	t[0] = *(buf + (j++));
    -	t[1] = *(buf + (j++));
    -	t[2] = '\0';
    -	*(digest + i) = (unsigned char) strtol(t, NULL, 16);
    +        t[0] = *(buf + (j++));
    +        t[1] = *(buf + (j++));
    +        t[2] = '\0';
    +        *(digest + i) = (unsigned char) strtol(t, NULL, 16);
         }
    +
         return digest;
     }
     
    @@ -69,12 +73,15 @@ storeKeyHashCmp(const void *a, const void *b)
         const unsigned char *A = (const unsigned char *)a;
         const unsigned char *B = (const unsigned char *)b;
         int i;
    +
         for (i = 0; i < MD5_DIGEST_CHARS; i++) {
    -	if (A[i] < B[i])
    -	    return -1;
    -	if (A[i] > B[i])
    -	    return 1;
    +        if (A[i] < B[i])
    +            return -1;
    +
    +        if (A[i] > B[i])
    +            return 1;
         }
    +
         return 0;
     }
     
    @@ -84,9 +91,9 @@ storeKeyHashHash(const void *key, unsigned int n)
         /* note, n must be a power of 2! */
         const unsigned char *digest = (const unsigned char *)key;
         unsigned int i = digest[0]
    -    | digest[1] << 8
    -    | digest[2] << 16
    -    | digest[3] << 24;
    +                     | digest[1] << 8
    +                     | digest[2] << 16
    +                     | digest[3] << 24;
         return (i & (--n));
     }
     
    @@ -97,7 +104,7 @@ storeKeyPrivate(const char *url, method_t method, int id)
         MD5_CTX M;
         assert(id > 0);
         debug(20, 3) ("storeKeyPrivate: %s %s\n",
    -	RequestMethodStr[method], url);
    +                  RequestMethodStr[method], url);
         MD5Init(&M);
         MD5Update(&M, (unsigned char *) &id, sizeof(id));
         MD5Update(&M, (unsigned char *) &method, sizeof(method));
    @@ -135,9 +142,12 @@ storeKeyPublicByRequestMethod(request_t * request, const method_t method)
         MD5Init(&M);
         MD5Update(&M, &m, sizeof(m));
         MD5Update(&M, (unsigned char *) url, strlen(url));
    +
         if (request->vary_headers)
    -	MD5Update(&M, (unsigned char *) request->vary_headers, strlen(request->vary_headers));
    +        MD5Update(&M, (unsigned char *) request->vary_headers, strlen(request->vary_headers));
    +
         MD5Final(digest, &M);
    +
         return digest;
     }
     
    @@ -166,8 +176,10 @@ int
     storeKeyHashBuckets(int nbuckets)
     {
         int n = 0x2000;
    +
         while (n < nbuckets)
    -	n <<= 1;
    +        n <<= 1;
    +
         return n;
     }
     
    @@ -175,9 +187,9 @@ int
     storeKeyNull(const cache_key * key)
     {
         if (memcmp(key, null_key, MD5_DIGEST_CHARS) == 0)
    -	return 1;
    +        return 1;
         else
    -	return 0;
    +        return 0;
     }
     
     void
    diff --git a/src/store_log.cc b/src/store_log.cc
    index fae1b94cc8..f7d225fb81 100644
    --- a/src/store_log.cc
    +++ b/src/store_log.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_log.cc,v 1.26 2003/01/23 00:37:27 robertc Exp $
    + * $Id: store_log.cc,v 1.27 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 20    Storage Manager Logging Functions
      * AUTHOR: Duane Wessels
    @@ -38,13 +38,13 @@
     #include "MemObject.h"
     
     static const char *storeLogTags[] =
    -{
    -    "CREATE",
    -    "SWAPIN",
    -    "SWAPOUT",
    -    "RELEASE",
    -    "SO_FAIL",
    -};
    +    {
    +        "CREATE",
    +        "SWAPIN",
    +        "SWAPOUT",
    +        "RELEASE",
    +        "SO_FAIL",
    +    };
     
     static Logfile *storelog = NULL;
     
    @@ -53,49 +53,55 @@ storeLog(int tag, const StoreEntry * e)
     {
         MemObject *mem = e->mem_obj;
         HttpReply const *reply;
    +
         if (NULL == storelog)
    -	return;
    +        return;
    +
     #if UNUSED_CODE
    +
         if (EBIT_TEST(e->flags, ENTRY_DONT_LOG))
    -	return;
    +        return;
    +
     #endif
    +
         if (mem != NULL) {
    -	if (mem->log_url == NULL) {
    -	    debug(20, 1) ("storeLog: NULL log_url for %s\n", mem->url);
    -	    mem->dump();
    -	    mem->log_url = xstrdup(mem->url);
    -	}
    -	reply = e->getReply();
    -	/*
    -	 * XXX Ok, where should we print the dir number here?
    -	 * Because if we print it before the swap file number, it'll break
    -	 * the existing log format.
    -	 */
    -	logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s %4d %9d %9d %9d %s %d/%d %s %s\n",
    -	    (int) current_time.tv_sec,
    -	    (int) current_time.tv_usec / 1000,
    -	    storeLogTags[tag],
    -	    e->swap_dirn,
    -	    e->swap_filen,
    -	    e->getMD5Text(),
    -	    reply->sline.status,
    -	    (int) reply->date,
    -	    (int) reply->last_modified,
    -	    (int) reply->expires,
    -	    reply->content_type.size() ? reply->content_type.buf() : "unknown",
    -	    reply->content_length,
    -	    contentLen(e),
    -	    RequestMethodStr[mem->method],
    -	    mem->log_url);
    +        if (mem->log_url == NULL) {
    +            debug(20, 1) ("storeLog: NULL log_url for %s\n", mem->url);
    +            mem->dump();
    +            mem->log_url = xstrdup(mem->url);
    +        }
    +
    +        reply = e->getReply();
    +        /*
    +         * XXX Ok, where should we print the dir number here?
    +         * Because if we print it before the swap file number, it'll break
    +         * the existing log format.
    +         */
    +        logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s %4d %9d %9d %9d %s %d/%d %s %s\n",
    +                      (int) current_time.tv_sec,
    +                      (int) current_time.tv_usec / 1000,
    +                      storeLogTags[tag],
    +                      e->swap_dirn,
    +                      e->swap_filen,
    +                      e->getMD5Text(),
    +                      reply->sline.status,
    +                      (int) reply->date,
    +                      (int) reply->last_modified,
    +                      (int) reply->expires,
    +                      reply->content_type.size() ? reply->content_type.buf() : "unknown",
    +                      reply->content_length,
    +                      contentLen(e),
    +                      RequestMethodStr[mem->method],
    +                      mem->log_url);
         } else {
    -	/* no mem object. Most RELEASE cases */
    -	logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s   ?         ?         ?         ? ?/? ?/? ? ?\n",
    -	    (int) current_time.tv_sec,
    -	    (int) current_time.tv_usec / 1000,
    -	    storeLogTags[tag],
    -	    e->swap_dirn,
    -	    e->swap_filen,
    -	    e->getMD5Text());
    +        /* no mem object. Most RELEASE cases */
    +        logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s   ?         ?         ?         ? ?/? ?/? ? ?\n",
    +                      (int) current_time.tv_sec,
    +                      (int) current_time.tv_usec / 1000,
    +                      storeLogTags[tag],
    +                      e->swap_dirn,
    +                      e->swap_filen,
    +                      e->getMD5Text());
         }
     }
     
    @@ -103,7 +109,8 @@ void
     storeLogRotate(void)
     {
         if (NULL == storelog)
    -	return;
    +        return;
    +
         logfileRotate(storelog);
     }
     
    @@ -111,8 +118,10 @@ void
     storeLogClose(void)
     {
         if (NULL == storelog)
    -	return;
    +        return;
    +
         logfileClose(storelog);
    +
         storelog = NULL;
     }
     
    @@ -120,8 +129,9 @@ void
     storeLogOpen(void)
     {
         if (strcmp(Config.Log.store, "none") == 0) {
    -	debug(20, 1) ("Store logging disabled\n");
    -	return;
    +        debug(20, 1) ("Store logging disabled\n");
    +        return;
         }
    +
         storelog = logfileOpen(Config.Log.store, 0, 1);
     }
    diff --git a/src/store_rebuild.cc b/src/store_rebuild.cc
    index fe14ced8ae..9384ba30a3 100644
    --- a/src/store_rebuild.cc
    +++ b/src/store_rebuild.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_rebuild.cc,v 1.80 2003/01/23 00:37:27 robertc Exp $
    + * $Id: store_rebuild.cc,v 1.81 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 20    Store Rebuild Routines
      * AUTHOR: Duane Wessels
    @@ -38,15 +38,19 @@
     #include "SwapDir.h"
     
     static struct _store_rebuild_data counts;
    +
     static struct timeval rebuild_start;
     static void storeCleanup(void *);
     
    -typedef struct {
    +typedef struct
    +{
         /* total number of "swap.state" entries that will be read */
         int total;
         /* number of entries read so far */
         int scanned;
    -} store_rebuild_progress;
    +}
    +
    +store_rebuild_progress;
     
     static store_rebuild_progress *RebuildProgress = NULL;
     
    @@ -68,49 +72,63 @@ storeCleanup(void *datanotused)
         hash_link *link_ptr = NULL;
         hash_link *link_next = NULL;
         validnum_start = validnum;
    +
         while (validnum - validnum_start < 500) {
    -	if (++bucketnum >= store_hash_buckets) {
    -	    debug(20, 1) ("  Completed Validation Procedure\n");
    -	    debug(20, 1) ("  Validated %d Entries\n", validnum);
    -	    debug(20, 1) ("  store_swap_size = %luk\n", store_swap_size);
    -	    store_dirs_rebuilding--;
    -	    assert(0 == store_dirs_rebuilding);
    -	    if (opt_store_doublecheck)
    -		assert(store_errors == 0);
    -	    if (store_digest)
    -		storeDigestNoteStoreReady();
    -	    return;
    -	}
    -	link_next = hash_get_bucket(store_table, bucketnum);
    -	while (NULL != (link_ptr = link_next)) {
    -	    link_next = link_ptr->next;
    -	    e = (StoreEntry *) link_ptr;
    -	    if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
    -		continue;
    -	    /*
    -	     * Calling storeRelease() has no effect because we're
    -	     * still in 'store_rebuilding' state
    -	     */
    -	    if (e->swap_filen < 0)
    -		continue;
    -	    if (opt_store_doublecheck)
    -		if (storeCleanupDoubleCheck(e))
    -		    store_errors++;
    -	    EBIT_SET(e->flags, ENTRY_VALIDATED);
    -	    /*
    -	     * Only set the file bit if we know its a valid entry
    -	     * otherwise, set it in the validation procedure
    -	     */
    -	    storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, 1);
    -	    if ((++validnum & 0x3FFFF) == 0)
    -		debug(20, 1) ("  %7d Entries Validated so far.\n", validnum);
    -	}
    +        if (++bucketnum >= store_hash_buckets) {
    +            debug(20, 1) ("  Completed Validation Procedure\n");
    +            debug(20, 1) ("  Validated %d Entries\n", validnum);
    +            debug(20, 1) ("  store_swap_size = %luk\n", store_swap_size);
    +            store_dirs_rebuilding--;
    +            assert(0 == store_dirs_rebuilding);
    +
    +            if (opt_store_doublecheck)
    +                assert(store_errors == 0);
    +
    +            if (store_digest)
    +                storeDigestNoteStoreReady();
    +
    +            return;
    +        }
    +
    +        link_next = hash_get_bucket(store_table, bucketnum);
    +
    +        while (NULL != (link_ptr = link_next)) {
    +            link_next = link_ptr->next;
    +            e = (StoreEntry *) link_ptr;
    +
    +            if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
    +                continue;
    +
    +            /*
    +             * Calling storeRelease() has no effect because we're
    +             * still in 'store_rebuilding' state
    +             */
    +            if (e->swap_filen < 0)
    +                continue;
    +
    +            if (opt_store_doublecheck)
    +                if (storeCleanupDoubleCheck(e))
    +                    store_errors++;
    +
    +            EBIT_SET(e->flags, ENTRY_VALIDATED);
    +
    +            /*
    +             * Only set the file bit if we know its a valid entry
    +             * otherwise, set it in the validation procedure
    +             */
    +            storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, 1);
    +
    +            if ((++validnum & 0x3FFFF) == 0)
    +                debug(20, 1) ("  %7d Entries Validated so far.\n", validnum);
    +        }
         }
    +
         eventAdd("storeCleanup", storeCleanup, NULL, 0.0, 1);
     }
     
     /* meta data recreated from disk image in swap directory */
     void
    +
     storeRebuildComplete(struct _store_rebuild_data *dc)
     {
         double dt;
    @@ -129,23 +147,39 @@ storeRebuildComplete(struct _store_rebuild_data *dc)
          * or scanning all cache_dirs.  Now report the stats and start
          * the validation (storeCleanup()) thread.
          */
    +
         if (store_dirs_rebuilding > 1)
    -	return;
    +        return;
    +
         dt = tvSubDsec(rebuild_start, current_time);
    +
         debug(20, 1) ("Finished rebuilding storage from disk.\n");
    +
         debug(20, 1) ("  %7d Entries scanned\n", counts.scancount);
    +
         debug(20, 1) ("  %7d Invalid entries.\n", counts.invalid);
    +
         debug(20, 1) ("  %7d With invalid flags.\n", counts.badflags);
    +
         debug(20, 1) ("  %7d Objects loaded.\n", counts.objcount);
    +
         debug(20, 1) ("  %7d Objects expired.\n", counts.expcount);
    +
         debug(20, 1) ("  %7d Objects cancelled.\n", counts.cancelcount);
    +
         debug(20, 1) ("  %7d Duplicate URLs purged.\n", counts.dupcount);
    +
         debug(20, 1) ("  %7d Swapfile clashes avoided.\n", counts.clashcount);
    +
         debug(20, 1) ("  Took %3.1f seconds (%6.1f objects/sec).\n", dt,
    -	(double) counts.objcount / (dt > 0.0 ? dt : 1.0));
    +                  (double) counts.objcount / (dt > 0.0 ? dt : 1.0));
    +
         debug(20, 1) ("Beginning Validation Procedure\n");
    +
         eventAdd("storeCleanup", storeCleanup, NULL, 0.0, 1);
    +
         xfree(RebuildProgress);
    +
         RebuildProgress = NULL;
     }
     
    @@ -166,7 +200,7 @@ storeRebuildStart(void)
          * occurs in storeCleanup(), when it is finished.
          */
         RebuildProgress = (store_rebuild_progress *)xcalloc(Config.cacheSwap.n_configured,
    -	sizeof(store_rebuild_progress));
    +                      sizeof(store_rebuild_progress));
     }
     
     /*
    @@ -179,20 +213,28 @@ storeRebuildProgress(int sd_index, int total, int sofar)
         static time_t last_report = 0;
         double n = 0.0;
         double d = 0.0;
    +
         if (sd_index < 0)
    -	return;
    +        return;
    +
         if (sd_index >= Config.cacheSwap.n_configured)
    -	return;
    +        return;
    +
         if (NULL == RebuildProgress)
    -	return;
    +        return;
    +
         RebuildProgress[sd_index].total = total;
    +
         RebuildProgress[sd_index].scanned = sofar;
    +
         if (squid_curtime - last_report < 15)
    -	return;
    +        return;
    +
         for (sd_index = 0; sd_index < Config.cacheSwap.n_configured; sd_index++) {
    -	n += (double) RebuildProgress[sd_index].scanned;
    -	d += (double) RebuildProgress[sd_index].total;
    +        n += (double) RebuildProgress[sd_index].scanned;
    +        d += (double) RebuildProgress[sd_index].total;
         }
    +
         debug(20, 1) ("Store rebuilding is %4.1f%% complete\n", 100.0 * n / d);
         last_report = squid_curtime;
     }
    diff --git a/src/store_swapin.cc b/src/store_swapin.cc
    index d40aa494bf..0a149a9e5f 100644
    --- a/src/store_swapin.cc
    +++ b/src/store_swapin.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_swapin.cc,v 1.34 2003/01/23 00:37:27 robertc Exp $
    + * $Id: store_swapin.cc,v 1.35 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 20    Storage Manager Swapin Functions
      * AUTHOR: Duane Wessels
    @@ -45,24 +45,29 @@ storeSwapInStart(store_client * sc)
     {
         StoreEntry *e = sc->entry;
         assert(e->mem_status == NOT_IN_MEMORY);
    +
         if (!EBIT_TEST(e->flags, ENTRY_VALIDATED)) {
    -	/* We're still reloading and haven't validated this entry yet */
    -	return;
    +        /* We're still reloading and haven't validated this entry yet */
    +        return;
         }
    +
         debug(20, 3) ("storeSwapInStart: called for %d %08X %s \n",
    -	e->swap_dirn, e->swap_filen, e->getMD5Text());
    +                  e->swap_dirn, e->swap_filen, e->getMD5Text());
    +
         if (e->swap_status != SWAPOUT_WRITING && e->swap_status != SWAPOUT_DONE) {
    -	debug(20, 1) ("storeSwapInStart: bad swap_status (%s)\n",
    -	    swapStatusStr[e->swap_status]);
    -	return;
    +        debug(20, 1) ("storeSwapInStart: bad swap_status (%s)\n",
    +                      swapStatusStr[e->swap_status]);
    +        return;
         }
    +
         if (e->swap_filen < 0) {
    -	debug(20, 1) ("storeSwapInStart: swap_filen < 0\n");
    -	return;
    +        debug(20, 1) ("storeSwapInStart: swap_filen < 0\n");
    +        return;
         }
    +
         assert(e->mem_obj != NULL);
         debug(20, 3) ("storeSwapInStart: Opening fileno %08X\n",
    -	e->swap_filen);
    +                  e->swap_filen);
         sc->swapin_sio = storeOpen(e, storeSwapInFileNotify, storeSwapInFileClosed, sc);
     }
     
    @@ -71,13 +76,15 @@ storeSwapInFileClosed(void *data, int errflag, storeIOState * sio)
     {
         store_client *sc = (store_client *)data;
         debug(20, 3) ("storeSwapInFileClosed: sio=%p, errflag=%d\n",
    -	sio, errflag);
    +                  sio, errflag);
         sc->swapin_sio = NULL;
         /* why this assert */
    +
         if (sc->callbackPending()) {
    -	assert (errflag <= 0);
    +        assert (errflag <= 0);
             sc->callback(0, errflag ? true : false);
         }
    +
         statCounter.swap.ins++;
     }
     
    diff --git a/src/store_swapmeta.cc b/src/store_swapmeta.cc
    index 0f83bd9636..c0a8bc7cae 100644
    --- a/src/store_swapmeta.cc
    +++ b/src/store_swapmeta.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_swapmeta.cc,v 1.20 2003/01/23 00:37:27 robertc Exp $
    + * $Id: store_swapmeta.cc,v 1.21 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 20    Storage Manager Swapfile Metadata
      * AUTHOR: Kostas Anagnostakis
    @@ -43,10 +43,11 @@ void
     storeSwapTLVFree(tlv * n)
     {
         tlv *t;
    +
         while ((t = n) != NULL) {
    -	n = t->next;
    -	xfree(t->value);
    -	t->deleteSelf();
    +        n = t->next;
    +        xfree(t->value);
    +        t->deleteSelf();
         }
     }
     
    @@ -65,32 +66,42 @@ storeSwapMetaBuild(StoreEntry * e)
         url = storeUrl(e);
         debug(20, 3) ("storeSwapMetaBuild: %s\n", url);
         tlv *t = StoreMeta::Factory (STORE_META_KEY,MD5_DIGEST_CHARS, e->key);
    +
         if (!t) {
    -	storeSwapTLVFree(TLV);
    -	return NULL;
    +        storeSwapTLVFree(TLV);
    +        return NULL;
         }
    +
         T = StoreMeta::Add(T, t);
         t = StoreMeta::Factory(STORE_META_STD,STORE_HDR_METASIZE,&e->timestamp);
    +
         if (!t) {
    -	storeSwapTLVFree(TLV);
    -	return NULL;
    +        storeSwapTLVFree(TLV);
    +        return NULL;
         }
    +
         T = StoreMeta::Add(T, t);
         t = StoreMeta::Factory(STORE_META_URL, strlen(url) + 1, url);
    +
         if (!t) {
    -	storeSwapTLVFree(TLV);
    -	return NULL;
    +        storeSwapTLVFree(TLV);
    +        return NULL;
         }
    +
         T = StoreMeta::Add(T, t);
         vary = e->mem_obj->vary_headers;
    +
         if (vary) {
    -	t =StoreMeta::Factory(STORE_META_VARY_HEADERS, strlen(vary) + 1, vary);
    -	if (!t) {
    -	    storeSwapTLVFree(TLV);
    -	    return NULL;
    -	}
    -	StoreMeta::Add (T, t);
    +        t =StoreMeta::Factory(STORE_META_VARY_HEADERS, strlen(vary) + 1, vary);
    +
    +        if (!t) {
    +            storeSwapTLVFree(TLV);
    +            return NULL;
    +        }
    +
    +        StoreMeta::Add (T, t);
         }
    +
         return TLV;
     }
     
    @@ -104,20 +115,28 @@ storeSwapMetaPack(tlv * tlv_list, int *length)
         assert(length != NULL);
         buflen++;			/* STORE_META_OK */
         buflen += sizeof(int);	/* size of header to follow */
    +
         for (t = tlv_list; t; t = t->next)
    -	buflen += sizeof(char) + sizeof(int) + t->length;
    +        buflen += sizeof(char) + sizeof(int) + t->length;
    +
         buflen++;			/* STORE_META_END */
    +
         buf = (char *)xmalloc(buflen);
    +
         buf[j++] = (char) STORE_META_OK;
    +
         xmemcpy(&buf[j], &buflen, sizeof(int));
    +
         j += sizeof(int);
    +
         for (t = tlv_list; t; t = t->next) {
    -	buf[j++] = t->getType();
    -	xmemcpy(&buf[j], &t->length, sizeof(int));
    -	j += sizeof(int);
    -	xmemcpy(&buf[j], t->value, t->length);
    -	j += t->length;
    +        buf[j++] = t->getType();
    +        xmemcpy(&buf[j], &t->length, sizeof(int));
    +        j += sizeof(int);
    +        xmemcpy(&buf[j], t->value, t->length);
    +        j += t->length;
         }
    +
         buf[j++] = (char) STORE_META_END;
         assert((int) j == buflen);
         *length = buflen;
    diff --git a/src/store_swapout.cc b/src/store_swapout.cc
    index acd8d5be23..2636fe4d5b 100644
    --- a/src/store_swapout.cc
    +++ b/src/store_swapout.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: store_swapout.cc,v 1.92 2003/01/23 00:37:27 robertc Exp $
    + * $Id: store_swapout.cc,v 1.93 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 20    Storage Manager Swapout Functions
      * AUTHOR: Duane Wessels
    @@ -56,7 +56,7 @@ storeSwapOutStart(StoreEntry * e)
          * metadata there is to store
          */
         debug(20, 5) ("storeSwapOutStart: Begin SwapOut '%s' to dirno %d, fileno %08X\n",
    -	storeUrl(e), e->swap_dirn, e->swap_filen);
    +                  storeUrl(e), e->swap_dirn, e->swap_filen);
         e->swap_status = SWAPOUT_WRITING;
         /* If we start swapping out objects with OutOfBand Metadata,
          * then this code needs changing
    @@ -65,12 +65,14 @@ storeSwapOutStart(StoreEntry * e)
         generic_cbdata *c = cbdataAlloc(generic_cbdata);
         c->data = e;
         sio = storeCreate(e, storeSwapOutFileNotify, storeSwapOutFileClosed, c);
    +
         if (NULL == sio.getRaw()) {
    -	e->swap_status = SWAPOUT_NONE;
    -	cbdataFree(c);
    -	storeLog(STORE_LOG_SWAPOUTFAIL, e);
    -	return;
    +        e->swap_status = SWAPOUT_NONE;
    +        cbdataFree(c);
    +        storeLog(STORE_LOG_SWAPOUTFAIL, e);
    +        return;
         }
    +
         mem->swapout.sio = sio;
         /* Don't lock until after create, or the replacement
          * code might get confused */
    @@ -108,46 +110,56 @@ static void
     doPages(StoreEntry *anEntry)
     {
         MemObject *mem = anEntry->mem_obj;
    +
         do {
    -	/*
    -	 * Evil hack time.
    -	 * We are paging out to disk in page size chunks. however, later on when
    -	 * we update the queue position, we might not have a page (I *think*),
    -	 * so we do the actual page update here.
    -	 */
    -
    -	if (mem->swapout.memnode == NULL) {
    -	    /* We need to swap out the first page */
    -	    mem->swapout.memnode = mem->data_hdr.head;
    -	} else {
    -	    /* We need to swap out the next page */
    -	    mem->swapout.memnode = mem->swapout.memnode->next;
    -	}
    -	/*
    -	 * Get the length of this buffer. We are assuming(!) that the buffer
    -	 * length won't change on this buffer, or things are going to be very
    -	 * strange. I think that after the copy to a buffer is done, the buffer
    -	 * size should stay fixed regardless so that this code isn't confused,
    -	 * but we can look at this at a later date or whenever the code results
    -	 * in bad swapouts, whichever happens first. :-)
    -	 */
    -	ssize_t swap_buf_len = mem->swapout.memnode->nodeBuffer.length;
    -
    -	debug(20, 3) ("storeSwapOut: swap_buf_len = %d\n", (int) swap_buf_len);
    -	assert(swap_buf_len > 0);
    -	debug(20, 3) ("storeSwapOut: swapping out %ld bytes from %ld\n",
    -	    (long int) swap_buf_len, (long int) mem->swapout.queue_offset);
    -	mem->swapout.queue_offset += swap_buf_len;
    -	storeIOWrite(mem->swapout.sio, mem->swapout.memnode->data, swap_buf_len, -1, NULL);
    -	/* the storeWrite() call might generate an error */
    -	if (anEntry->swap_status != SWAPOUT_WRITING)
    -	    break;
    -	ssize_t swapout_size = (ssize_t) (mem->endOffset() - mem->swapout.queue_offset);
    -	if (anEntry->store_status == STORE_PENDING)
    -	    if (swapout_size < SM_PAGE_SIZE)
    -		break;
    -	if (swapout_size <= 0)
    -	    return;
    +        /*
    +         * Evil hack time.
    +         * We are paging out to disk in page size chunks. however, later on when
    +         * we update the queue position, we might not have a page (I *think*),
    +         * so we do the actual page update here.
    +         */
    +
    +        if (mem->swapout.memnode == NULL) {
    +            /* We need to swap out the first page */
    +            mem->swapout.memnode = mem->data_hdr.head;
    +        } else {
    +            /* We need to swap out the next page */
    +            mem->swapout.memnode = mem->swapout.memnode->next;
    +        }
    +
    +        /*
    +         * Get the length of this buffer. We are assuming(!) that the buffer
    +         * length won't change on this buffer, or things are going to be very
    +         * strange. I think that after the copy to a buffer is done, the buffer
    +         * size should stay fixed regardless so that this code isn't confused,
    +         * but we can look at this at a later date or whenever the code results
    +         * in bad swapouts, whichever happens first. :-)
    +         */
    +        ssize_t swap_buf_len = mem->swapout.memnode->nodeBuffer.length;
    +
    +        debug(20, 3) ("storeSwapOut: swap_buf_len = %d\n", (int) swap_buf_len);
    +
    +        assert(swap_buf_len > 0);
    +
    +        debug(20, 3) ("storeSwapOut: swapping out %ld bytes from %ld\n",
    +                      (long int) swap_buf_len, (long int) mem->swapout.queue_offset);
    +
    +        mem->swapout.queue_offset += swap_buf_len;
    +
    +        storeIOWrite(mem->swapout.sio, mem->swapout.memnode->data, swap_buf_len, -1, NULL);
    +
    +        /* the storeWrite() call might generate an error */
    +        if (anEntry->swap_status != SWAPOUT_WRITING)
    +            break;
    +
    +        ssize_t swapout_size = (ssize_t) (mem->endOffset() - mem->swapout.queue_offset);
    +
    +        if (anEntry->store_status == STORE_PENDING)
    +            if (swapout_size < SM_PAGE_SIZE)
    +                break;
    +
    +        if (swapout_size <= 0)
    +            return;
         } while (true);
     }
     
    @@ -159,100 +171,124 @@ void
     storeSwapOut(StoreEntry * e)
     {
         if (!e->mem_obj)
    -	return;
    +        return;
    +
         if (!e->swapoutPossible())
    -	return;
    +        return;
     
         MemObject *mem = e->mem_obj;
     
         debug(20, 7) ("storeSwapOut: mem->inmem_lo = %d\n",
    -	(int) mem->inmem_lo);
    +                  (int) mem->inmem_lo);
    +
         debug(20, 7) ("storeSwapOut: mem->endOffset() = %d\n",
    -	(int) mem->endOffset());
    +                  (int) mem->endOffset());
    +
         debug(20, 7) ("storeSwapOut: swapout.queue_offset = %d\n",
    -	(int) mem->swapout.queue_offset);
    +                  (int) mem->swapout.queue_offset);
    +
         if (mem->swapout.sio.getRaw())
    -	debug(20, 7) ("storeSwapOut: storeOffset() = %d\n",
    -	    (int) mem->swapout.sio->offset());
    -    
    +        debug(20, 7) ("storeSwapOut: storeOffset() = %d\n",
    +                      (int) mem->swapout.sio->offset());
    +
         ssize_t swapout_maxsize = (ssize_t) (mem->endOffset() - mem->swapout.queue_offset);
    +
         assert(swapout_maxsize >= 0);
    +
         off_t const lowest_offset = mem->lowestMemReaderOffset();
    -    
    +
         debug(20, 7) ("storeSwapOut: lowest_offset = %d\n",
    -	(int) lowest_offset);
    +                  (int) lowest_offset);
    +
         /*
          * Grab the swapout_size and check to see whether we're going to defer
          * the swapout based upon size
          */
         if ((e->store_status != STORE_OK) && (swapout_maxsize < store_maxobjsize)) {
    -	/*
    -	 * NOTE: the store_maxobjsize here is the max of optional
    -	 * max-size values from 'cache_dir' lines.  It is not the
    -	 * same as 'maximum_object_size'.  By default, store_maxobjsize
    -	 * will be set to -1.  However, I am worried that this
    -	 * deferance may consume a lot of memory in some cases.
    -	 * It would be good to make this decision based on reply
    -	 * content-length, rather than wait to accumulate huge
    -	 * amounts of object data in memory.
    -	 */
    -	debug(20, 5) ("storeSwapOut: Deferring starting swapping out\n");
    -	return;
    +        /*
    +         * NOTE: the store_maxobjsize here is the max of optional
    +         * max-size values from 'cache_dir' lines.  It is not the
    +         * same as 'maximum_object_size'.  By default, store_maxobjsize
    +         * will be set to -1.  However, I am worried that this
    +         * deferance may consume a lot of memory in some cases.
    +         * It would be good to make this decision based on reply
    +         * content-length, rather than wait to accumulate huge
    +         * amounts of object data in memory.
    +         */
    +        debug(20, 5) ("storeSwapOut: Deferring starting swapping out\n");
    +        return;
         }
    +
         e->trimMemory();
     #if SIZEOF_OFF_T == 4
    +
         if (mem->endOffset() > 0x7FFF0000) {
    -	debug(20, 0) ("WARNING: preventing off_t overflow for %s\n", storeUrl(e));
    -	storeAbort(e);
    -	return;
    +        debug(20, 0) ("WARNING: preventing off_t overflow for %s\n", storeUrl(e));
    +        storeAbort(e);
    +        return;
         }
    +
     #endif
         if (e->swap_status == SWAPOUT_WRITING)
    -	assert(mem->inmem_lo <=  (off_t)mem->objectBytesOnDisk() );
    +        assert(mem->inmem_lo <=  (off_t)mem->objectBytesOnDisk() );
    +
         if (!storeSwapOutAble(e))
    -	return;
    +        return;
    +
         debug(20, 7) ("storeSwapOut: swapout_size = %d\n",
    -	(int) swapout_maxsize);
    +                  (int) swapout_maxsize);
    +
         if (swapout_maxsize == 0) {
    -	if (e->store_status == STORE_OK)
    -	    storeSwapOutFileClose(e);
    -	return;			/* Nevermore! */
    +        if (e->store_status == STORE_OK)
    +            storeSwapOutFileClose(e);
    +
    +        return;			/* Nevermore! */
         }
    +
         if (e->store_status == STORE_PENDING) {
    -	/* wait for a full block to write */
    -	if (swapout_maxsize < SM_PAGE_SIZE)
    -	    return;
    -	/*
    -	 * Wait until we are below the disk FD limit, only if the
    -	 * next server-side read won't be deferred.
    -	 */
    -	if (storeTooManyDiskFilesOpen() && !StoreEntry::CheckDeferRead(-1, e))
    -	    return;
    +        /* wait for a full block to write */
    +
    +        if (swapout_maxsize < SM_PAGE_SIZE)
    +            return;
    +
    +        /*
    +         * Wait until we are below the disk FD limit, only if the
    +         * next server-side read won't be deferred.
    +         */
    +        if (storeTooManyDiskFilesOpen() && !StoreEntry::CheckDeferRead(-1, e))
    +            return;
         }
    +
         /* Ok, we have stuff to swap out.  Is there a swapout.sio open? */
         if (e->swap_status == SWAPOUT_NONE) {
    -	assert(mem->swapout.sio == NULL);
    -	assert(mem->inmem_lo == 0);
    -	if (storeCheckCachable(e))
    -	    storeSwapOutStart(e);
    -	else
    -	    return;
    -	/* ENTRY_CACHABLE will be cleared and we'll never get here again */
    +        assert(mem->swapout.sio == NULL);
    +        assert(mem->inmem_lo == 0);
    +
    +        if (storeCheckCachable(e))
    +            storeSwapOutStart(e);
    +        else
    +            return;
    +
    +        /* ENTRY_CACHABLE will be cleared and we'll never get here again */
         }
    +
         if (mem->swapout.sio == NULL)
    -	return;
    +        return;
    +
         doPages(e);
    +
         if (NULL == mem->swapout.sio.getRaw())
    -	/* oops, we're not swapping out any more */
    -	return;
    +        /* oops, we're not swapping out any more */
    +        return;
    +
         if (e->store_status == STORE_OK) {
    -	/*
    -	 * If the state is STORE_OK, then all data must have been given
    -	 * to the filesystem at this point because storeSwapOut() is
    -	 * not going to be called again for this entry.
    -	 */
    -	assert(mem->endOffset() == mem->swapout.queue_offset);
    -	storeSwapOutFileClose(e);
    +        /*
    +         * If the state is STORE_OK, then all data must have been given
    +         * to the filesystem at this point because storeSwapOut() is
    +         * not going to be called again for this entry.
    +         */
    +        assert(mem->endOffset() == mem->swapout.queue_offset);
    +        storeSwapOutFileClose(e);
         }
     }
     
    @@ -263,8 +299,10 @@ storeSwapOutFileClose(StoreEntry * e)
         assert(mem != NULL);
         debug(20, 3) ("storeSwapOutFileClose: %s\n", e->getMD5Text());
         debug(20, 3) ("storeSwapOutFileClose: sio = %p\n", mem->swapout.sio.getRaw());
    +
         if (mem->swapout.sio == NULL)
    -	return;
    +        return;
    +
         storeClose(mem->swapout.sio);
     }
     
    @@ -276,33 +314,43 @@ storeSwapOutFileClosed(void *data, int errflag, storeIOState * sio)
         MemObject *mem = e->mem_obj;
         assert(e->swap_status == SWAPOUT_WRITING);
         cbdataFree(c);
    +
         if (errflag) {
    -	debug(20, 1) ("storeSwapOutFileClosed: dirno %d, swapfile %08X, errflag=%d\n\t%s\n",
    -	    e->swap_dirn, e->swap_filen, errflag, xstrerror());
    -	if (errflag == DISK_NO_SPACE_LEFT) {
    -	    storeDirDiskFull(e->swap_dirn);
    -	    storeDirConfigure();
    -	    storeConfigure();
    -	}
    -	if (e->swap_filen > 0)
    -	    storeUnlink(e);
    -	e->swap_filen = -1;
    -	e->swap_dirn = -1;
    -	e->swap_status = SWAPOUT_NONE;
    -	storeReleaseRequest(e);
    +        debug(20, 1) ("storeSwapOutFileClosed: dirno %d, swapfile %08X, errflag=%d\n\t%s\n",
    +                      e->swap_dirn, e->swap_filen, errflag, xstrerror());
    +
    +        if (errflag == DISK_NO_SPACE_LEFT) {
    +            storeDirDiskFull(e->swap_dirn);
    +            storeDirConfigure();
    +            storeConfigure();
    +        }
    +
    +        if (e->swap_filen > 0)
    +            storeUnlink(e);
    +
    +        e->swap_filen = -1;
    +
    +        e->swap_dirn = -1;
    +
    +        e->swap_status = SWAPOUT_NONE;
    +
    +        storeReleaseRequest(e);
         } else {
    -	/* swapping complete */
    -	debug(20, 3) ("storeSwapOutFileClosed: SwapOut complete: '%s' to %d, %08X\n",
    -	    storeUrl(e), e->swap_dirn, e->swap_filen);
    -	e->swap_file_sz = objectLen(e) + mem->swap_hdr_sz;
    -	e->swap_status = SWAPOUT_DONE;
    -	storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, 1);
    -	if (storeCheckCachable(e)) {
    -	    storeLog(STORE_LOG_SWAPOUT, e);
    -	    storeDirSwapLog(e, SWAP_LOG_ADD);
    -	}
    -	statCounter.swap.outs++;
    +        /* swapping complete */
    +        debug(20, 3) ("storeSwapOutFileClosed: SwapOut complete: '%s' to %d, %08X\n",
    +                      storeUrl(e), e->swap_dirn, e->swap_filen);
    +        e->swap_file_sz = objectLen(e) + mem->swap_hdr_sz;
    +        e->swap_status = SWAPOUT_DONE;
    +        storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, 1);
    +
    +        if (storeCheckCachable(e)) {
    +            storeLog(STORE_LOG_SWAPOUT, e);
    +            storeDirSwapLog(e, SWAP_LOG_ADD);
    +        }
    +
    +        statCounter.swap.outs++;
         }
    +
         debug(20, 3) ("storeSwapOutFileClosed: %s:%d\n", __FILE__, __LINE__);
         mem->swapout.sio = NULL;
         storeUnlockObject(e);
    @@ -315,10 +363,13 @@ int
     storeSwapOutAble(const StoreEntry * e)
     {
         dlink_node *node;
    +
         if (e->mem_obj->swapout.sio.getRaw() != NULL)
    -	return 1;
    +        return 1;
    +
         if (e->mem_obj->inmem_lo > 0)
    -	return 0;
    +        return 0;
    +
         /*
          * If there are DISK clients, we must write to disk
          * even if its not cachable
    @@ -326,15 +377,19 @@ storeSwapOutAble(const StoreEntry * e)
          * therefore this should be an assert?
          */
         for (node = e->mem_obj->clients.head; node; node = node->next) {
    -	if (((store_client *) node->data)->getType() == STORE_DISK_CLIENT)
    -	    return 1;
    +        if (((store_client *) node->data)->getType() == STORE_DISK_CLIENT)
    +            return 1;
         }
    +
         /* Don't pollute the disk with icons and other special entries */
         if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
    -	return 0;
    +        return 0;
    +
         if (!EBIT_TEST(e->flags, ENTRY_CACHABLE))
    -	return 0;
    +        return 0;
    +
         if (!e->mem_obj->isContiguous())
    -	return 0;
    +        return 0;
    +
         return 1;
     }
    diff --git a/src/structs.h b/src/structs.h
    index e9f47ad52a..edb477303a 100644
    --- a/src/structs.h
    +++ b/src/structs.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: structs.h,v 1.451 2003/02/21 19:53:02 hno Exp $
    + * $Id: structs.h,v 1.452 2003/02/21 22:50:12 robertc Exp $
      *
      *
      * SQUID Web Proxy Cache          http://www.squid-cache.org/
    @@ -36,36 +36,48 @@
     
     #include "config.h"
     
    -struct _dlink_node {
    +struct _dlink_node
    +{
         void *data;
         dlink_node *prev;
         dlink_node *next;
     };
     
    -struct _dlink_list {
    +struct _dlink_list
    +{
         dlink_node *head;
         dlink_node *tail;
     };
     
    -struct _acl_user_ip_data {
    +struct _acl_user_ip_data
    +{
         size_t max;
    -    struct {
    -	unsigned int strict:1;
    -    } flags;
    +
    +    struct
    +    {
    +
    +unsigned int strict:
    +        1;
    +    }
    +
    +    flags;
     };
     
    -struct _acl_name_list {
    +struct _acl_name_list
    +{
         char name[ACL_NAME_SZ];
         acl_name_list *next;
     };
     
    -struct _acl_proxy_auth_match_cache {
    +struct _acl_proxy_auth_match_cache
    +{
         dlink_node link;
         int matchrv;
         void *acl_data;
     };
     
    -struct _acl_deny_info_list {
    +struct _acl_deny_info_list
    +{
         err_type err_page_id;
         char *err_page_name;
         acl_name_list *acl_list;
    @@ -74,7 +86,8 @@ struct _acl_deny_info_list {
     
     #if USE_ARP_ACL
     
    -struct _acl_arp_data {
    +struct _acl_arp_data
    +{
         char eth[6];
     };
     
    @@ -82,32 +95,39 @@ struct _acl_arp_data {
     
     
     class acl_access;
    -struct _header_mangler {
    +
    +struct _header_mangler
    +{
         acl_access *access_list;
         char *replacement;
     };
     
    -struct _body_size {
    +struct _body_size
    +{
         dlink_node node;
         acl_access *access_list;
         size_t maxsize;
     };
     
    -struct _http_version_t {
    +struct _http_version_t
    +{
         unsigned int major;
         unsigned int minor;
     };
     
     #if SQUID_SNMP
     
    -struct _snmp_request_t {
    +struct _snmp_request_t
    +{
         u_char *buf;
         u_char *outbuf;
         int len;
         int sock;
         long reqid;
         int outlen;
    +
         struct sockaddr_in from;
    +
         struct snmp_pdu *PDU;
         ACLChecklist *acl_checklist;
         u_char *community;
    @@ -118,64 +138,84 @@ struct _snmp_request_t {
     typedef class ACL acl;
     
     
    -struct _acl_address {
    +struct _acl_address
    +{
         acl_address *next;
         acl_list *aclList;
    +
         struct in_addr addr;
     };
     
    -struct _acl_tos {
    +struct _acl_tos
    +{
         acl_tos *next;
         acl_list *aclList;
         int tos;
     };
     
    -struct _wordlist {
    +struct _wordlist
    +{
         char *key;
         wordlist *next;
     };
     
    -struct _intlist {
    +struct _intlist
    +{
         int i;
         intlist *next;
     };
     
    -struct _intrange {
    +struct _intrange
    +{
         int i;
         int j;
         intrange *next;
     };
     
    -struct _ushortlist {
    +struct _ushortlist
    +{
         u_short i;
         ushortlist *next;
     };
     
    -struct _relist {
    +struct _relist
    +{
         char *pattern;
         regex_t regex;
         relist *next;
     };
     
    -struct _sockaddr_in_list {
    +struct _sockaddr_in_list
    +{
    +
         struct sockaddr_in s;
         sockaddr_in_list *next;
     };
     
    -struct _http_port_list {
    +struct _http_port_list
    +{
         http_port_list *next;
    +
         struct sockaddr_in s;
         char *protocol;		/* protocol name */
         char *name;			/* visible name */
         char *defaultsite;		/* default web site */
    -    unsigned int transparent:1;	/* transparent proxy */
    -    unsigned int accel:1;	/* HTTP accelerator */
    -    unsigned int vhost:1;	/* uses host header */
    +
    +unsigned int transparent:
    +    1;	/* transparent proxy */
    +
    +unsigned int accel:
    +    1;	/* HTTP accelerator */
    +
    +unsigned int vhost:
    +    1;	/* uses host header */
         int vport;			/* virtual port support, -1 for dynamic, >0 static*/
     };
     
     #if USE_SSL
    -struct _https_port_list {
    +
    +struct _https_port_list
    +{
         http_port_list http;	/* must be first */
         char *cert;
         char *key;
    @@ -188,40 +228,56 @@ struct _https_port_list {
         char *sslflags;
         SSL_CTX *sslContext;
     };
    +
     #endif
     
     #if DELAY_POOLS
     #include "DelayConfig.h"
     #endif
     
    -struct _authConfig {
    +struct _authConfig
    +{
         authScheme *schemes;
         int n_allocated;
         int n_configured;
     };
     
    -struct _RemovalPolicySettings {
    +struct _RemovalPolicySettings
    +{
         char *type;
         wordlist *args;
     };
     
    -struct _SquidConfig {
    -    struct {
    -	size_t maxSize;
    -	int highWaterMark;
    -	int lowWaterMark;
    -    } Swap;
    +struct _SquidConfig
    +{
    +
    +    struct
    +    {
    +        size_t maxSize;
    +        int highWaterMark;
    +        int lowWaterMark;
    +    }
    +
    +    Swap;
         size_t memMaxSize;
    -    struct {
    -	char *relayHost;
    -	u_short relayPort;
    -	peer *_peer;
    -    } Wais;
    -    struct {
    -	size_t min;
    -	int pct;
    -	size_t max;
    -    } quickAbort;
    +
    +    struct
    +    {
    +        char *relayHost;
    +        u_short relayPort;
    +        peer *_peer;
    +    }
    +
    +    Wais;
    +
    +    struct
    +    {
    +        size_t min;
    +        int pct;
    +        size_t max;
    +    }
    +
    +    quickAbort;
         size_t readAheadGap;
         RemovalPolicySettings *replPolicy;
         RemovalPolicySettings *memPolicy;
    @@ -230,96 +286,146 @@ struct _SquidConfig {
         time_t positiveDnsTtl;
         time_t shutdownLifetime;
         time_t backgroundPingRate;
    -    struct {
    -	time_t read;
    -	time_t lifetime;
    -	time_t connect;
    -	time_t peer_connect;
    -	time_t request;
    -	time_t persistent_request;
    -	time_t pconn;
    -	time_t siteSelect;
    -	time_t deadPeer;
    -	int icp_query;		/* msec */
    -	int icp_query_max;	/* msec */
    -	int icp_query_min;	/* msec */
    -	int mcast_icp_query;	/* msec */
    +
    +    struct
    +    {
    +        time_t read;
    +        time_t lifetime;
    +        time_t connect;
    +        time_t peer_connect;
    +        time_t request;
    +        time_t persistent_request;
    +        time_t pconn;
    +        time_t siteSelect;
    +        time_t deadPeer;
    +        int icp_query;		/* msec */
    +        int icp_query_max;	/* msec */
    +        int icp_query_min;	/* msec */
    +        int mcast_icp_query;	/* msec */
     #if USE_IDENT
    -	time_t ident;
    +
    +        time_t ident;
     #endif
     #if !USE_DNSSERVERS
    -	time_t idns_retransmit;
    -	time_t idns_query;
    +
    +        time_t idns_retransmit;
    +        time_t idns_query;
     #endif
    -    } Timeout;
    +
    +    }
    +
    +    Timeout;
         size_t maxRequestHeaderSize;
         size_t maxRequestBodySize;
         dlink_list ReplyBodySize;
    -    struct {
    -	u_short icp;
    +
    +    struct
    +    {
    +        u_short icp;
     #if USE_HTCP
    -	u_short htcp;
    +
    +        u_short htcp;
     #endif
     #if SQUID_SNMP
    -	u_short snmp;
    +
    +        u_short snmp;
     #endif
    -    } Port;
    -    struct {
    -	http_port_list *http;
    +
    +    }
    +
    +    Port;
    +
    +    struct
    +    {
    +        http_port_list *http;
     #if USE_SSL
    -	https_port_list *https;
    +
    +        https_port_list *https;
     #endif
    -    } Sockaddr;
    +
    +    }
    +
    +    Sockaddr;
     #if SQUID_SNMP
    -    struct {
    -	char *configFile;
    -	char *agentInfo;
    -    } Snmp;
    +
    +    struct
    +    {
    +        char *configFile;
    +        char *agentInfo;
    +    }
    +
    +    Snmp;
     #endif
     #if USE_WCCP
    -    struct {
    -	struct in_addr router;
    -	struct in_addr incoming;
    -	struct in_addr outgoing;
    -	int version;
    -    } Wccp;
    +
    +    struct
    +    {
    +
    +        struct in_addr router;
    +
    +        struct in_addr incoming;
    +
    +        struct in_addr outgoing;
    +        int version;
    +    }
    +
    +    Wccp;
     #endif
    +
         char *as_whois_server;
    -    struct {
    -	char *log;
    -	char *access;
    -	char *store;
    -	char *swap;
    +
    +    struct
    +    {
    +        char *log;
    +        char *access;
    +        char *store;
    +        char *swap;
     #if USE_USERAGENT_LOG
    -	char *useragent;
    +
    +        char *useragent;
     #endif
     #if USE_REFERER_LOG
    -	char *referer;
    +
    +        char *referer;
     #endif
     #if WIP_FWD_LOG
    -	char *forward;
    +
    +        char *forward;
     #endif
    -	int rotateNumber;
    -    } Log;
    +
    +        int rotateNumber;
    +    }
    +
    +    Log;
         char *adminEmail;
         char *effectiveUser;
         char *effectiveGroup;
    -    struct {
    +
    +    struct
    +    {
     #if USE_DNSSERVERS
    -	char *dnsserver;
    +        char *dnsserver;
     #endif
    -	wordlist *redirect;
    +
    +        wordlist *redirect;
     #if USE_ICMP
    -	char *pinger;
    +
    +        char *pinger;
     #endif
     #if USE_UNLINKD
    -	char *unlinkd;
    +
    +        char *unlinkd;
     #endif
    -	char *diskd;
    -    } Program;
    +
    +        char *diskd;
    +    }
    +
    +    Program;
     #if USE_DNSSERVERS
    +
         int dnsChildren;
     #endif
    +
         int redirectChildren;
         time_t authenticateGCInterval;
         time_t authenticateTTL;
    @@ -334,21 +440,34 @@ struct _SquidConfig {
         char *uniqueHostname;
         wordlist *hostnameAliases;
         char *errHtmlText;
    -    struct {
    -	char *host;
    -	char *file;
    -	time_t period;
    -	u_short port;
    -    } Announce;
    -    struct {
    -	struct in_addr udp_incoming;
    -	struct in_addr udp_outgoing;
    +
    +    struct
    +    {
    +        char *host;
    +        char *file;
    +        time_t period;
    +        u_short port;
    +    }
    +
    +    Announce;
    +
    +    struct
    +    {
    +
    +        struct in_addr udp_incoming;
    +
    +        struct in_addr udp_outgoing;
     #if SQUID_SNMP
    -	struct in_addr snmp_incoming;
    -	struct in_addr snmp_outgoing;
    +
    +        struct in_addr snmp_incoming;
    +
    +        struct in_addr snmp_outgoing;
     #endif
    -	struct in_addr client_netmask;
    -    } Addrs;
    +
    +        struct in_addr client_netmask;
    +    }
    +
    +    Addrs;
         size_t tcpRcvBufsz;
         size_t udpMaxHitObjsz;
         wordlist *hierarchy_stoplist;
    @@ -357,199 +476,290 @@ struct _SquidConfig {
         wordlist *dns_nameservers;
         peer *peers;
         int npeers;
    -    struct {
    -	int size;
    -	int low;
    -	int high;
    -    } ipcache;
    -    struct {
    -	int size;
    -    } fqdncache;
    +
    +    struct
    +    {
    +        int size;
    +        int low;
    +        int high;
    +    }
    +
    +    ipcache;
    +
    +    struct
    +    {
    +        int size;
    +    }
    +
    +    fqdncache;
         int minDirectHops;
         int minDirectRtt;
         cachemgr_passwd *passwd_list;
    -    struct {
    -	int objectsPerBucket;
    -	size_t avgObjectSize;
    -	size_t maxObjectSize;
    -	size_t minObjectSize;
    -	size_t maxInMemObjSize;
    -    } Store;
    -    struct {
    -	int high;
    -	int low;
    -	time_t period;
    -    } Netdb;
    -    struct {
    -	int log_udp;
    +
    +    struct
    +    {
    +        int objectsPerBucket;
    +        size_t avgObjectSize;
    +        size_t maxObjectSize;
    +        size_t minObjectSize;
    +        size_t maxInMemObjSize;
    +    }
    +
    +    Store;
    +
    +    struct
    +    {
    +        int high;
    +        int low;
    +        time_t period;
    +    }
    +
    +    Netdb;
    +
    +    struct
    +    {
    +        int log_udp;
     #if USE_DNSSERVERS
    -	int res_defnames;
    +
    +        int res_defnames;
     #endif
    -	int anonymizer;
    -	int client_db;
    -	int query_icmp;
    -	int icp_hit_stale;
    -	int buffered_logs;
    +
    +        int anonymizer;
    +        int client_db;
    +        int query_icmp;
    +        int icp_hit_stale;
    +        int buffered_logs;
     #if ALLOW_SOURCE_PING
    -	int source_ping;
    +
    +        int source_ping;
     #endif
    -	int common_log;
    -	int log_mime_hdrs;
    -	int log_fqdn;
    -	int announce;
    -	int mem_pools;
    -	int test_reachability;
    -	int half_closed_clients;
    +
    +        int common_log;
    +        int log_mime_hdrs;
    +        int log_fqdn;
    +        int announce;
    +        int mem_pools;
    +        int test_reachability;
    +        int half_closed_clients;
     #if HTTP_VIOLATIONS
    -	int reload_into_ims;
    +
    +        int reload_into_ims;
     #endif
    -	int offline;
    -	int redir_rewrites_host;
    -	int prefer_direct;
    -	int nonhierarchical_direct;
    -	int strip_query_terms;
    -	int redirector_bypass;
    -	int ignore_unknown_nameservers;
    -	int client_pconns;
    -	int server_pconns;
    +
    +        int offline;
    +        int redir_rewrites_host;
    +        int prefer_direct;
    +        int nonhierarchical_direct;
    +        int strip_query_terms;
    +        int redirector_bypass;
    +        int ignore_unknown_nameservers;
    +        int client_pconns;
    +        int server_pconns;
     #if USE_CACHE_DIGESTS
    -	int digest_generation;
    +
    +        int digest_generation;
     #endif
    -	int log_ip_on_direct;
    -	int ie_refresh;
    -	int vary_ignore_expire;
    -	int pipeline_prefetch;
    -	int request_entities;
    -	int check_hostnames;
    -	int via;
    -	int emailErrData;
    -    } onoff;
    +
    +        int log_ip_on_direct;
    +        int ie_refresh;
    +        int vary_ignore_expire;
    +        int pipeline_prefetch;
    +        int request_entities;
    +        int check_hostnames;
    +        int via;
    +        int emailErrData;
    +    }
    +
    +    onoff;
         acl *aclList;
    -    struct {
    -	acl_access *http;
    -	acl_access *icp;
    -	acl_access *miss;
    -	acl_access *NeverDirect;
    -	acl_access *AlwaysDirect;
    -	acl_access *ASlists;
    -	acl_access *noCache;
    +
    +    struct
    +    {
    +        acl_access *http;
    +        acl_access *icp;
    +        acl_access *miss;
    +        acl_access *NeverDirect;
    +        acl_access *AlwaysDirect;
    +        acl_access *ASlists;
    +        acl_access *noCache;
     #if SQUID_SNMP
    -	acl_access *snmp;
    +
    +        acl_access *snmp;
     #endif
    -	acl_access *brokenPosts;
    +
    +        acl_access *brokenPosts;
     #if USE_IDENT
    -	acl_access *identLookup;
    +
    +        acl_access *identLookup;
     #endif
    -	acl_access *redirector;
    -	acl_access *reply;
    -	acl_address *outgoing_address;
    -	acl_tos *outgoing_tos;
    -    } accessList;
    +
    +        acl_access *redirector;
    +        acl_access *reply;
    +        acl_address *outgoing_address;
    +        acl_tos *outgoing_tos;
    +    }
    +
    +    accessList;
         acl_deny_info_list *denyInfoList;
         authConfig authConfiguration;
    -    struct {
    -	size_t list_width;
    -	int list_wrap;
    -	char *anon_user;
    -	int passive;
    -	int sanitycheck;
    -    } Ftp;
    +
    +    struct
    +    {
    +        size_t list_width;
    +        int list_wrap;
    +        char *anon_user;
    +        int passive;
    +        int sanitycheck;
    +    }
    +
    +    Ftp;
         refresh_t *Refresh;
    -    struct _cacheSwap {
    -	SwapDir **swapDirs;
    -	int n_allocated;
    -	int n_configured;
    -    } cacheSwap;
    -    struct {
    -	char *directory;
    -    } icons;
    +
    +    struct _cacheSwap
    +    {
    +        SwapDir **swapDirs;
    +        int n_allocated;
    +        int n_configured;
    +    }
    +
    +    cacheSwap;
    +
    +    struct
    +    {
    +        char *directory;
    +    }
    +
    +    icons;
         char *errorDirectory;
    -    struct {
    -	time_t timeout;
    -	int maxtries;
    -    } retry;
    -    struct {
    -	size_t limit;
    -    } MemPools;
    +
    +    struct
    +    {
    +        time_t timeout;
    +        int maxtries;
    +    }
    +
    +    retry;
    +
    +    struct
    +    {
    +        size_t limit;
    +    }
    +
    +    MemPools;
     #if DELAY_POOLS
    +
         DelayConfig Delay;
     #endif
    -    struct {
    -	int icp_average;
    -	int dns_average;
    -	int http_average;
    -	int icp_min_poll;
    -	int dns_min_poll;
    -	int http_min_poll;
    -    } comm_incoming;
    +
    +    struct
    +    {
    +        int icp_average;
    +        int dns_average;
    +        int http_average;
    +        int icp_min_poll;
    +        int dns_min_poll;
    +        int http_min_poll;
    +    }
    +
    +    comm_incoming;
         int max_open_disk_fds;
         int uri_whitespace;
         size_t rangeOffsetLimit;
     #if MULTICAST_MISS_STREAM
    -    struct {
    -	struct in_addr addr;
    -	int ttl;
    -	unsigned short port;
    -	char *encode_key;
    -    } mcast_miss;
    +
    +    struct
    +    {
    +
    +        struct in_addr addr;
    +        int ttl;
    +        unsigned short port;
    +        char *encode_key;
    +    }
    +
    +    mcast_miss;
     #endif
    +
         header_mangler header_access[HDR_ENUM_END];
         char *coredump_dir;
         char *chroot_dir;
     #if USE_CACHE_DIGESTS
    -    struct {
    -	int bits_per_entry;
    -	time_t rebuild_period;
    -	time_t rewrite_period;
    -	size_t swapout_chunk_size;
    -	int rebuild_chunk_percentage;
    -    } digest;
    +
    +    struct
    +    {
    +        int bits_per_entry;
    +        time_t rebuild_period;
    +        time_t rewrite_period;
    +        size_t swapout_chunk_size;
    +        int rebuild_chunk_percentage;
    +    }
    +
    +    digest;
     #endif
     #if USE_SSL
    -    struct {
    -	int unclean_shutdown;
    -	char *ssl_engine;
    -    } SSL;
    +
    +    struct
    +    {
    +        int unclean_shutdown;
    +        char *ssl_engine;
    +    }
    +
    +    SSL;
     #endif
    +
         wordlist *ext_methods;
    -    struct {
    -	int high_rptm;
    -	int high_pf;
    -	size_t high_memory;
    -    } warnings;
    +
    +    struct
    +    {
    +        int high_rptm;
    +        int high_pf;
    +        size_t high_memory;
    +    }
    +
    +    warnings;
         char *store_dir_select_algorithm;
         int sleep_after_fork;	/* microseconds */
         external_acl *externalAclHelperList;
     #if USE_SSL
    -    struct {
    -	char *cert;
    -	char *key;
    -	int version;
    -	char *options;
    -	char *cipher;
    -	char *cafile;
    -	char *capath;
    -	char *flags;
    -	SSL_CTX *sslContext;
    -    } ssl_client;
    +
    +    struct
    +    {
    +        char *cert;
    +        char *key;
    +        int version;
    +        char *options;
    +        char *cipher;
    +        char *cafile;
    +        char *capath;
    +        char *flags;
    +        SSL_CTX *sslContext;
    +    }
    +
    +    ssl_client;
     #endif
     };
     
    -struct _SquidConfig2 {
    -    struct {
    -	int enable_purge;
    -    } onoff;
    +struct _SquidConfig2
    +{
    +
    +    struct
    +    {
    +        int enable_purge;
    +    }
    +
    +    onoff;
         uid_t effectiveUserID;
         gid_t effectiveGroupID;
     };
     
    -struct _close_handler {
    +struct _close_handler
    +{
         PF *handler;
         void *data;
         close_handler *next;
     };
     
    -struct _dread_ctrl {
    +struct _dread_ctrl
    +{
         int fd;
         off_t offset;
         int req_len;
    @@ -559,7 +769,8 @@ struct _dread_ctrl {
         void *client_data;
     };
     
    -struct _dnsserver_t {
    +struct _dnsserver_t
    +{
         int id;
         int inpipe;
         int outpipe;
    @@ -567,11 +778,13 @@ struct _dnsserver_t {
         off_t offset;
         size_t size;
         char ip_inbuf[DNS_INBUF_SZ];
    +
         struct timeval dispatch_time;
         void *data;
     };
     
    -struct _dwrite_q {
    +struct _dwrite_q
    +{
         off_t file_offset;
         char *buf;
         int len;
    @@ -585,12 +798,15 @@ struct _dwrite_q {
      * this struct is likely to change
      * Note: "str" points to memory in HttpHeaderEntry (for now)
      *       so ETags should be used as tmp variables only (for now) */
    -struct _ETag {
    +
    +struct _ETag
    +{
         const char *str;		/* quoted-string */
         int weak;			/* true if it is a weak validator */
     };
     
    -struct _fde_disk {
    +struct _fde_disk
    +{
         DWCB *wrt_handle;
         void *wrt_handle_data;
         dwrite_q *write_q;
    @@ -598,7 +814,8 @@ struct _fde_disk {
         off_t offset;
     };
     
    -struct _fileMap {
    +struct _fileMap
    +{
         int max_n_files;
         int n_files_in_map;
         int toggle;
    @@ -607,7 +824,9 @@ struct _fileMap {
     };
     
     /* see Packer.c for description */
    -struct _Packer {
    +
    +struct _Packer
    +{
         /* protected, use interface functions instead */
         append_f append;
         vprintf_f vprintf;
    @@ -615,7 +834,9 @@ struct _Packer {
     };
     
     /* http status line */
    -struct _HttpStatusLine {
    +
    +struct _HttpStatusLine
    +{
         /* public, read only */
         http_version_t version;
         const char *reason;		/* points to a _constant_ string (default or supplied), never free()d */
    @@ -627,20 +848,26 @@ struct _HttpStatusLine {
      * known a priory (e.g., error messages).
      */
     #include "MemBuf.h"
    -struct _HttpBody {
    +
    +struct _HttpBody
    +{
         /* private */
         MemBuf mb;
     };
     
     #include "SquidString.h"
     /* http header extention field */
    -struct _HttpHdrExtField {
    +
    +struct _HttpHdrExtField
    +{
         String name;		/* field-name  from HTTP/1.1 (no column after name) */
         String value;		/* field-value from HTTP/1.1 */
     };
     
     /* http cache control header field */
    -struct _HttpHdrCc {
    +
    +struct _HttpHdrCc
    +{
         int mask;
         int max_age;
         int s_maxage;
    @@ -648,14 +875,18 @@ struct _HttpHdrCc {
     };
     
     /* some fields can hold either time or etag specs (e.g. If-Range) */
    -struct _TimeOrTag {
    +
    +struct _TimeOrTag
    +{
         ETag tag;			/* entity tag */
         time_t time;
         int valid;			/* true if struct is usable */
     };
     
     /* per field statistics */
    -struct _HttpHeaderFieldStat {
    +
    +struct _HttpHeaderFieldStat
    +{
         int aliveCount;		/* created but not destroyed (count) */
         int seenCount;		/* #fields we've seen */
         int parsCount;		/* #parsing attempts */
    @@ -664,20 +895,24 @@ struct _HttpHeaderFieldStat {
     };
     
     /* compiled version of HttpHeaderFieldAttrs plus stats */
    -struct _HttpHeaderFieldInfo {
    +
    +struct _HttpHeaderFieldInfo
    +{
         http_hdr_type id;
         String name;
         field_type type;
         HttpHeaderFieldStat stat;
     };
     
    -struct _HttpHeaderEntry {
    +struct _HttpHeaderEntry
    +{
         http_hdr_type id;
         String name;
         String value;
     };
     
    -struct _HttpHeader {
    +struct _HttpHeader
    +{
         /* protected, do not use these, use interface functions instead */
         Array entries;		/* parsed fields in raw format */
         HttpHeaderMask mask;	/* bit set <=> entry present */
    @@ -686,7 +921,9 @@ struct _HttpHeader {
     };
     
     class HttpHdrContRange;
    -struct _HttpReply {
    +
    +struct _HttpReply
    +{
         /* unsupported, writable, may disappear/change in the future */
         int hdr_sz;			/* sums _stored_ status-line, headers, and  */
     
    @@ -710,17 +947,33 @@ struct _HttpReply {
         size_t maxBodySize;
     };
     
    -struct _http_state_flags {
    -    unsigned int proxying:1;
    -    unsigned int keepalive:1;
    -    unsigned int only_if_cached:1;
    -    unsigned int headers_pushed:1;
    -    unsigned int front_end_https:2;
    -    unsigned int originpeer:1;
    +struct _http_state_flags
    +{
    +
    +unsigned int proxying:
    +    1;
    +
    +unsigned int keepalive:
    +    1;
    +
    +unsigned int only_if_cached:
    +    1;
    +
    +unsigned int headers_pushed:
    +    1;
    +
    +unsigned int front_end_https:
    +    2;
    +
    +unsigned int originpeer:
    +    1;
     };
     
    -struct _ping_data {
    +struct _ping_data
    +{
    +
         struct timeval start;
    +
         struct timeval stop;
         int n_sent;
         int n_recv;
    @@ -731,7 +984,8 @@ struct _ping_data {
         int p_rtt;
     };
     
    -struct _HierarchyLogEntry {
    +struct _HierarchyLogEntry
    +{
         hier_code code;
         char host[SQUIDHOSTNAMELEN];
         ping_data ping;
    @@ -739,81 +993,131 @@ struct _HierarchyLogEntry {
         lookup_t cd_lookup;		/* cd prediction: none, miss, hit */
         int n_choices;		/* #peers we selected from (cd only) */
         int n_ichoices;		/* #peers with known rtt we selected from (cd only) */
    +
         struct timeval peer_select_start;
    +
         struct timeval store_complete_stop;
     };
     
    -struct _AccessLogEntry {
    +struct _AccessLogEntry
    +{
         const char *url;
    -    struct {
    -	method_t method;
    -	int code;
    -	const char *content_type;
    -	http_version_t version;
    -    } http;
    -    struct {
    -	icp_opcode opcode;
    -    } icp;
    -    struct {
    -	struct in_addr caddr;
    -	size_t size;
    -	log_type code;
    -	int msec;
    -	const char *rfc931;
    -	const char *authuser;
    +
    +    struct
    +    {
    +        method_t method;
    +        int code;
    +        const char *content_type;
    +        http_version_t version;
    +    }
    +
    +    http;
    +
    +    struct
    +    {
    +        icp_opcode opcode;
    +    }
    +
    +    icp;
    +
    +    struct
    +    {
    +
    +        struct in_addr caddr;
    +        size_t size;
    +        log_type code;
    +        int msec;
    +        const char *rfc931;
    +        const char *authuser;
     #if USE_SSL
    -	const char *ssluser;
    +
    +        const char *ssluser;
     #endif
    -    } cache;
    -    struct {
    -	char *request;
    -	char *reply;
    -    } headers;
    -    struct {
    -	const char *method_str;
    -    } _private;
    +
    +    }
    +
    +    cache;
    +
    +    struct
    +    {
    +        char *request;
    +        char *reply;
    +    }
    +
    +    headers;
    +
    +    struct
    +    {
    +        const char *method_str;
    +    }
    +
    +    _private;
         HierarchyLogEntry hier;
     };
     
    -struct _ConnStateData {
    +struct _ConnStateData
    +{
         int fd;
    -    struct {
    -	char *buf;
    -	size_t notYetUsed;
    -	size_t allocatedSize;
    -    } in;
    -    struct {
    -	size_t size_left;	/* How much body left to process */
    -	request_t *request;	/* Parameters passed to clientReadBody */
    -	char *buf;
    -	size_t bufsize;
    -	CBCB *callback;
    -	void *cbdata;
    -    } body;
    -    auth_type_t auth_type;	/* Is this connection based authentication ? if so 
    -				 * what type it is. */
    +
    +    struct
    +    {
    +        char *buf;
    +        size_t notYetUsed;
    +        size_t allocatedSize;
    +    }
    +
    +    in;
    +
    +    struct
    +    {
    +        size_t size_left;	/* How much body left to process */
    +        request_t *request;	/* Parameters passed to clientReadBody */
    +        char *buf;
    +        size_t bufsize;
    +        CBCB *callback;
    +        void *cbdata;
    +    }
    +
    +    body;
    +    auth_type_t auth_type;	/* Is this connection based authentication ? if so
    +    		        				 * what type it is. */
         /* note this is ONLY connection based because NTLM is against HTTP spec */
         /* the user details for connection based authentication */
         auth_user_request_t *auth_user_request;
         void *currentobject;	/* used by the owner of the connection. Opaque otherwise */
    +
         struct sockaddr_in peer;
    +
         struct sockaddr_in me;
    +
         struct in_addr log_addr;
         char rfc931[USER_IDENT_SZ];
         int nrequests;
    -    struct {
    -	int n;
    -	time_t until;
    -    } defer;
    -    struct {
    -	int readMoreRequests:1;
    -    } flags;
    +
    +    struct
    +    {
    +        int n;
    +        time_t until;
    +    }
    +
    +    defer;
    +
    +    struct
    +    {
    +
    +int readMoreRequests:
    +        1;
    +    }
    +
    +    flags;
         bool reading;
         http_port_list *port;
         int transparent;
     };
     
    -struct _ipcache_addrs {
    +struct _ipcache_addrs
    +{
    +
         struct in_addr *in_addrs;
         unsigned char *bad_mask;
         unsigned char count;
    @@ -821,26 +1125,32 @@ struct _ipcache_addrs {
         unsigned char badcount;
     };
     
    -struct _domain_ping {
    +struct _domain_ping
    +{
         char *domain;
         int do_ping;		/* boolean */
         domain_ping *next;
     };
     
    -struct _domain_type {
    +struct _domain_type
    +{
         char *domain;
         peer_t type;
         domain_type *next;
     };
     
     #if USE_CACHE_DIGESTS
    -struct _Version {
    +
    +struct _Version
    +{
         short int current;		/* current version */
         short int required;		/* minimal version that can safely handle current version */
     };
     
     /* digest control block; used for transmission and storage */
    -struct _StoreDigestCBlock {
    +
    +struct _StoreDigestCBlock
    +{
         Version ver;
         int capacity;
         int count;
    @@ -852,7 +1162,8 @@ struct _StoreDigestCBlock {
         int reserved[32 - 6];
     };
     
    -struct _DigestFetchState {
    +struct _DigestFetchState
    +{
         PeerDigest *pd;
         StoreEntry *entry;
         StoreEntry *old_entry;
    @@ -864,17 +1175,23 @@ struct _DigestFetchState {
         time_t start_time;
         time_t resp_time;
         time_t expires;
    -    struct {
    -	int msg;
    -	int bytes;
    -    } sent, recv;
    +
    +    struct
    +    {
    +        int msg;
    +        int bytes;
    +    }
    +
    +    sent, recv;
         char buf[SM_PAGE_SIZE];
         ssize_t bufofs;
         digest_read_state_t state;
     };
     
     /* statistics for cache digests and other hit "predictors" */
    -struct _cd_guess_stats {
    +
    +struct _cd_guess_stats
    +{
         /* public, read-only */
         int true_hits;
         int false_hits;
    @@ -883,117 +1200,205 @@ struct _cd_guess_stats {
         int close_hits;		/* tmp, remove it later */
     };
     
    -struct _PeerDigest {
    +struct _PeerDigest
    +{
    +
         struct _peer *peer;			/* pointer back to peer structure, argh */
         CacheDigest *cd;		/* actual digest structure */
         String host;		/* copy of peer->host */
         const char *req_result;	/* text status of the last request */
    -    struct {
    -	unsigned int needed:1;	/* there were requests for this digest */
    -	unsigned int usable:1;	/* can be used for lookups */
    -	unsigned int requested:1;	/* in process of receiving [fresh] digest */
    -    } flags;
    -    struct {
    -	/* all times are absolute unless augmented with _delay */
    -	time_t initialized;	/* creation */
    -	time_t needed;		/* first lookup/use by a peer */
    -	time_t next_check;	/* next scheduled check/refresh event */
    -	time_t retry_delay;	/* delay before re-checking _invalid_ digest */
    -	time_t requested;	/* requested a fresh copy of a digest */
    -	time_t req_delay;	/* last request response time */
    -	time_t received;	/* received the current copy of a digest */
    -	time_t disabled;	/* disabled for good */
    -    } times;
    -    struct {
    -	cd_guess_stats guess;
    -	int used_count;
    -	struct {
    -	    int msgs;
    -	    kb_t kbytes;
    -	} sent, recv;
    -    } stats;
    +
    +    struct
    +    {
    +
    +unsigned int needed:
    +        1;	/* there were requests for this digest */
    +
    +unsigned int usable:
    +        1;	/* can be used for lookups */
    +
    +unsigned int requested:
    +        1;	/* in process of receiving [fresh] digest */
    +    }
    +
    +    flags;
    +
    +    struct
    +    {
    +        /* all times are absolute unless augmented with _delay */
    +        time_t initialized;	/* creation */
    +        time_t needed;		/* first lookup/use by a peer */
    +        time_t next_check;	/* next scheduled check/refresh event */
    +        time_t retry_delay;	/* delay before re-checking _invalid_ digest */
    +        time_t requested;	/* requested a fresh copy of a digest */
    +        time_t req_delay;	/* last request response time */
    +        time_t received;	/* received the current copy of a digest */
    +        time_t disabled;	/* disabled for good */
    +    }
    +
    +    times;
    +
    +    struct
    +    {
    +        cd_guess_stats guess;
    +        int used_count;
    +
    +        struct
    +        {
    +            int msgs;
    +            kb_t kbytes;
    +        }
    +
    +        sent, recv;
    +    }
    +
    +    stats;
     };
     
     #endif
     
    -struct _peer {
    +struct _peer
    +{
         char *name;
         char *host;
         peer_t type;
    +
         struct sockaddr_in in_addr;
    -    struct {
    -	int pings_sent;
    -	int pings_acked;
    -	int fetches;
    -	int rtt;
    -	int ignored_replies;
    -	int n_keepalives_sent;
    -	int n_keepalives_recv;
    -	time_t probe_start;
    -	time_t last_query;
    -	time_t last_reply;
    -	time_t last_connect_failure;
    -	time_t last_connect_probe;
    -	int logged_state;	/* so we can print dead/revived msgs */
    -	int conn_open;		/* current opened connections */
    -    } stats;
    -    struct {
    -	int version;
    -	int counts[ICP_END];
    -	u_short port;
    -    } icp;
    +
    +    struct
    +    {
    +        int pings_sent;
    +        int pings_acked;
    +        int fetches;
    +        int rtt;
    +        int ignored_replies;
    +        int n_keepalives_sent;
    +        int n_keepalives_recv;
    +        time_t probe_start;
    +        time_t last_query;
    +        time_t last_reply;
    +        time_t last_connect_failure;
    +        time_t last_connect_probe;
    +        int logged_state;	/* so we can print dead/revived msgs */
    +        int conn_open;		/* current opened connections */
    +    }
    +
    +    stats;
    +
    +    struct
    +    {
    +        int version;
    +        int counts[ICP_END];
    +        u_short port;
    +    }
    +
    +    icp;
     #if USE_HTCP
    -    struct {
    -	double version;
    -	int counts[2];
    -	u_short port;
    -    } htcp;
    +
    +    struct
    +    {
    +        double version;
    +        int counts[2];
    +        u_short port;
    +    }
    +
    +    htcp;
     #endif
    +
         u_short http_port;
         domain_ping *peer_domain;
         domain_type *typelist;
         acl_access *access;
    -    struct {
    -	unsigned int proxy_only:1;
    -	unsigned int no_query:1;
    -	unsigned int background_ping:1;
    -	unsigned int no_digest:1;
    -	unsigned int default_parent:1;
    -	unsigned int roundrobin:1;
    -	unsigned int weighted_roundrobin:1;
    -	unsigned int mcast_responder:1;
    -	unsigned int closest_only:1;
    +
    +    struct
    +    {
    +
    +unsigned int proxy_only:
    +        1;
    +
    +unsigned int no_query:
    +        1;
    +
    +unsigned int background_ping:
    +        1;
    +
    +unsigned int no_digest:
    +        1;
    +
    +unsigned int default_parent:
    +        1;
    +
    +unsigned int roundrobin:
    +        1;
    +
    +unsigned int weighted_roundrobin:
    +        1;
    +
    +unsigned int mcast_responder:
    +        1;
    +
    +unsigned int closest_only:
    +        1;
     #if USE_HTCP
    -	unsigned int htcp:1;
    +
    +unsigned int htcp:
    +        1;
     #endif
    -	unsigned int no_netdb_exchange:1;
    +
    +unsigned int no_netdb_exchange:
    +        1;
     #if DELAY_POOLS
    -	unsigned int no_delay:1;
    +
    +unsigned int no_delay:
    +        1;
     #endif
    -	unsigned int allow_miss:1;
    +
    +unsigned int allow_miss:
    +        1;
     #if USE_CARP
    -	unsigned int carp:1;
    +
    +unsigned int carp:
    +        1;
     #endif
    -	unsigned int originserver:1;
    -    } options;
    +
    +unsigned int originserver:
    +        1;
    +    }
    +
    +    options;
         int weight;
         int basetime;
    -    struct {
    -	double avg_n_members;
    -	int n_times_counted;
    -	int n_replies_expected;
    -	int ttl;
    -	int id;
    -	struct {
    -	    unsigned int count_event_pending:1;
    -	    unsigned int counting:1;
    -	} flags;
    -    } mcast;
    +
    +    struct
    +    {
    +        double avg_n_members;
    +        int n_times_counted;
    +        int n_replies_expected;
    +        int ttl;
    +        int id;
    +
    +        struct
    +        {
    +
    +unsigned int count_event_pending:
    +            1;
    +
    +unsigned int counting:
    +            1;
    +        }
    +
    +        flags;
    +    }
    +
    +    mcast;
     #if USE_CACHE_DIGESTS
    +
         PeerDigest *digest;
         char *digest_url;
     #endif
    +
         int tcp_up;			/* 0 if a connect() fails */
    +
         struct in_addr addresses[10];
         int n_addresses;
         int rr_count;
    @@ -1001,17 +1406,23 @@ struct _peer {
         peer *next;
         int test_fd;
     #if USE_CARP
    -    struct {
    -	unsigned int hash;
    -	double load_multiplier;
    -	double load_factor;	/* normalized weight value */
    -    } carp;
    +
    +    struct
    +    {
    +        unsigned int hash;
    +        double load_multiplier;
    +        double load_factor;	/* normalized weight value */
    +    }
    +
    +    carp;
     #endif
    +
         char *login;		/* Proxy authorization */
         time_t connect_timeout;
         int max_conn;
         char *domain;		/* Forced domain */
     #if USE_SSL
    +
         int use_ssl;
         char *sslcert;
         char *sslkey;
    @@ -1024,23 +1435,27 @@ struct _peer {
         char *ssldomain;
         SSL_CTX *sslContext;
     #endif
    +
         int front_end_https;
     };
     
    -struct _net_db_name {
    +struct _net_db_name
    +{
         hash_link hash;		/* must be first */
         net_db_name *next;
         netdbEntry *net_db_entry;
     };
     
    -struct _net_db_peer {
    +struct _net_db_peer
    +{
         const char *peername;
         double hops;
         double rtt;
         time_t expires;
     };
     
    -struct _netdbEntry {
    +struct _netdbEntry
    +{
         hash_link hash;		/* must be first */
         char network[16];
         int pings_sent;
    @@ -1056,7 +1471,8 @@ struct _netdbEntry {
         int n_peers;
     };
     
    -struct _ps_state {
    +struct _ps_state
    +{
         request_t *request;
         StoreEntry *entry;
         int always_direct;
    @@ -1072,7 +1488,9 @@ struct _ps_state {
          * the peer * based on the address when we are finally ready to
          * reference the peer structure.
          */
    +
         struct sockaddr_in first_parent_miss;
    +
         struct sockaddr_in closest_parent_miss;
         /*
          * ->hit and ->secho can be peer* because they should only be
    @@ -1081,21 +1499,28 @@ struct _ps_state {
         peer *hit;
         peer_t hit_type;
     #if ALLOW_SOURCE_PING
    +
         peer *secho;
     #endif
    +
         ping_data ping;
         ACLChecklist *acl_checklist;
     };
     
     #if USE_ICMP
    -struct _pingerEchoData {
    +
    +struct _pingerEchoData
    +{
    +
         struct in_addr to;
         unsigned char opcode;
         int psize;
         char payload[PINGER_PAYLOAD_SZ];
     };
     
    -struct _pingerReplyData {
    +struct _pingerReplyData
    +{
    +
         struct in_addr from;
         unsigned char opcode;
         int rtt;
    @@ -1106,23 +1531,30 @@ struct _pingerReplyData {
     
     #endif
     
    -struct _iostats {
    -    struct {
    -	int reads;
    -	int reads_deferred;
    -	int read_hist[16];
    -	int writes;
    -	int write_hist[16];
    -    } Http, Ftp, Gopher, Wais;
    +struct _iostats
    +{
    +
    +    struct
    +    {
    +        int reads;
    +        int reads_deferred;
    +        int read_hist[16];
    +        int writes;
    +        int write_hist[16];
    +    }
    +
    +    Http, Ftp, Gopher, Wais;
     };
     
     /* Removal policies */
     
    -struct _RemovalPolicyNode {
    +struct _RemovalPolicyNode
    +{
         void *data;
     };
     
    -struct _RemovalPolicy {
    +struct _RemovalPolicy
    +{
         const char *_type;
         void *_data;
         void (*Free) (RemovalPolicy * policy);
    @@ -1135,14 +1567,16 @@ struct _RemovalPolicy {
         void (*Stats) (RemovalPolicy * policy, StoreEntry * entry);
     };
     
    -struct _RemovalPolicyWalker {
    +struct _RemovalPolicyWalker
    +{
         RemovalPolicy *_policy;
         void *_data;
         const StoreEntry *(*Next) (RemovalPolicyWalker * walker);
         void (*Done) (RemovalPolicyWalker * walker);
     };
     
    -struct _RemovalPurgeWalker {
    +struct _RemovalPurgeWalker
    +{
         RemovalPolicy *_policy;
         void *_data;
         int scanned, max_scan, locked;
    @@ -1154,49 +1588,96 @@ struct _RemovalPurgeWalker {
      * SO, we stop globals.c seeing it 
      */
     #ifdef __cplusplus
    -struct request_flags {
    +
    +struct request_flags
    +{
         request_flags():range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),accelerated(0),internal(0),internalclient(0),body_sent(0),destinationIPLookedUp_(0)
    -      {
    +    {
     #if HTTP_VIOLATIONS
    -	nocache_hack = 1;
    +        nocache_hack = 1;
     #endif
    -      }
    -    unsigned int range:1;
    -    unsigned int nocache:1;
    -    unsigned int ims:1;
    -    unsigned int auth:1;
    -    unsigned int cachable:1;
    -    unsigned int hierarchical:1;
    -    unsigned int loopdetect:1;
    -    unsigned int proxy_keepalive:1;
    -    unsigned int proxying:1;	/* this should be killed, also in httpstateflags */
    -    unsigned int refresh:1;
    -    unsigned int redirected:1;
    -    unsigned int need_validation:1;
    +
    +    }
    +
    +unsigned int range:
    +    1;
    +
    +unsigned int nocache:
    +    1;
    +
    +unsigned int ims:
    +    1;
    +
    +unsigned int auth:
    +    1;
    +
    +unsigned int cachable:
    +    1;
    +
    +unsigned int hierarchical:
    +    1;
    +
    +unsigned int loopdetect:
    +    1;
    +
    +unsigned int proxy_keepalive:
    +    1;
    +
    +unsigned int proxying:
    +    1;	/* this should be killed, also in httpstateflags */
    +
    +unsigned int refresh:
    +    1;
    +
    +unsigned int redirected:
    +    1;
    +
    +unsigned int need_validation:
    +    1;
     #if HTTP_VIOLATIONS
    -    unsigned int nocache_hack:1;	/* for changing/ignoring no-cache requests */
    +
    +unsigned int nocache_hack:
    +    1;	/* for changing/ignoring no-cache requests */
     #endif
    -    unsigned int accelerated:1;
    -    unsigned int internal:1;
    -    unsigned int internalclient:1;
    -    unsigned int body_sent:1;
    +
    +unsigned int accelerated:
    +    1;
    +
    +unsigned int internal:
    +    1;
    +
    +unsigned int internalclient:
    +    1;
    +
    +unsigned int body_sent:
    +    1;
         bool resetTCP() const;
         void setResetTCP();
         void clearResetTCP();
         void destinationIPLookupCompleted();
         bool destinationIPLookedUp() const;
    +
     private:
    -    unsigned int reset_tcp:1;
    -    unsigned int destinationIPLookedUp_:1;
    +
    +unsigned int reset_tcp:
    +    1;
    +
    +unsigned int destinationIPLookedUp_:
    +    1;
     };
     
    -struct _link_list {
    +struct _link_list
    +{
         void *ptr;
    +
         struct _link_list *next;
     };
     
     class HttpHdrRange;
    -class request_t {
    +
    +class request_t
    +{
    +
     public:
         bool multipartRangeRequest() const;
     
    @@ -1217,7 +1698,9 @@ public:
         int imslen;
         int max_forwards;
         /* these in_addr's could probably be sockaddr_in's */
    +
         struct in_addr client_addr;
    +
         struct in_addr my_addr;
         unsigned short my_port;
         HttpHeader header;
    @@ -1230,32 +1713,52 @@ public:
         const char *vary_headers;	/* Used when varying entities are detected. Changes how the store key is calculated */
         char *peer_domain;		/* Configured peer forceddomain */
     };
    +
     #endif
    -struct _cachemgr_passwd {
    +
    +struct _cachemgr_passwd
    +{
         char *passwd;
         wordlist *actions;
         cachemgr_passwd *next;
     };
     
    -struct _refresh_t {
    +struct _refresh_t
    +{
         const char *pattern;
         regex_t compiled_pattern;
         time_t min;
         double pct;
         time_t max;
         refresh_t *next;
    -    struct {
    -	unsigned int icase:1;
    +
    +    struct
    +    {
    +
    +unsigned int icase:
    +        1;
     #if HTTP_VIOLATIONS
    -	unsigned int override_expire:1;
    -	unsigned int override_lastmod:1;
    -	unsigned int reload_into_ims:1;
    -	unsigned int ignore_reload:1;
    +
    +unsigned int override_expire:
    +        1;
    +
    +unsigned int override_lastmod:
    +        1;
    +
    +unsigned int reload_into_ims:
    +        1;
    +
    +unsigned int ignore_reload:
    +        1;
     #endif
    -    } flags;
    +
    +    }
    +
    +    flags;
     };
     
    -struct _CommWriteStateData {
    +struct _CommWriteStateData
    +{
         char *buf;
         size_t size;
         off_t offset;
    @@ -1264,7 +1767,8 @@ struct _CommWriteStateData {
         FREE *free_func;
     };
     
    -struct _ErrorState {
    +struct _ErrorState
    +{
         err_type type;
         int page_id;
         http_status httpStatus;
    @@ -1276,18 +1780,29 @@ struct _ErrorState {
         u_short port;
         char *dnsserver_msg;
         time_t ttl;
    +
         struct in_addr src_addr;
         char *redirect_url;
         ERCB *callback;
         void *callback_data;
    -    struct {
    -	unsigned int flag_cbdata:1;
    -    } flags;
    -    struct {
    -	wordlist *server_msg;
    -	char *request;
    -	char *reply;
    -    } ftp;
    +
    +    struct
    +    {
    +
    +unsigned int flag_cbdata:
    +        1;
    +    }
    +
    +    flags;
    +
    +    struct
    +    {
    +        wordlist *server_msg;
    +        char *request;
    +        char *reply;
    +    }
    +
    +    ftp;
         char *request_hdrs;
     };
     
    @@ -1295,7 +1810,9 @@ struct _ErrorState {
      * "very generic" histogram; 
      * see important comments on hbase_f restrictions in StatHist.c
      */
    -struct _StatHist {
    +
    +struct _StatHist
    +{
         int *bins;
         int capacity;
         double min;
    @@ -1309,120 +1826,178 @@ struct _StatHist {
      * if you add a field to StatCounters, 
      * you MUST sync statCountersInitSpecial, statCountersClean, and statCountersCopy
      */
    -struct _StatCounters {
    -    struct {
    -	int clients;
    -	int requests;
    -	int hits;
    -	int mem_hits;
    -	int disk_hits;
    -	int errors;
    -	kb_t kbytes_in;
    -	kb_t kbytes_out;
    -	kb_t hit_kbytes_out;
    -	StatHist miss_svc_time;
    -	StatHist nm_svc_time;
    -	StatHist nh_svc_time;
    -	StatHist hit_svc_time;
    -	StatHist all_svc_time;
    -    } client_http;
    -    struct {
    -	struct {
    -	    int requests;
    -	    int errors;
    -	    kb_t kbytes_in;
    -	    kb_t kbytes_out;
    -	} all , http, ftp, other;
    -    } server;
    -    struct {
    -	int pkts_sent;
    -	int queries_sent;
    -	int replies_sent;
    -	int pkts_recv;
    -	int queries_recv;
    -	int replies_recv;
    -	int hits_sent;
    -	int hits_recv;
    -	int replies_queued;
    -	int replies_dropped;
    -	kb_t kbytes_sent;
    -	kb_t q_kbytes_sent;
    -	kb_t r_kbytes_sent;
    -	kb_t kbytes_recv;
    -	kb_t q_kbytes_recv;
    -	kb_t r_kbytes_recv;
    -	StatHist query_svc_time;
    -	StatHist reply_svc_time;
    -	int query_timeouts;
    -	int times_used;
    -    } icp;
    -    struct {
    -	int requests;
    -    } unlink;
    -    struct {
    -	StatHist svc_time;
    -    } dns;
    -    struct {
    -	int times_used;
    -	kb_t kbytes_sent;
    -	kb_t kbytes_recv;
    -	kb_t memory;
    -	int msgs_sent;
    -	int msgs_recv;
    +
    +struct _StatCounters
    +{
    +
    +    struct
    +    {
    +        int clients;
    +        int requests;
    +        int hits;
    +        int mem_hits;
    +        int disk_hits;
    +        int errors;
    +        kb_t kbytes_in;
    +        kb_t kbytes_out;
    +        kb_t hit_kbytes_out;
    +        StatHist miss_svc_time;
    +        StatHist nm_svc_time;
    +        StatHist nh_svc_time;
    +        StatHist hit_svc_time;
    +        StatHist all_svc_time;
    +    }
    +
    +    client_http;
    +
    +    struct
    +    {
    +
    +        struct
    +        {
    +            int requests;
    +            int errors;
    +            kb_t kbytes_in;
    +            kb_t kbytes_out;
    +        }
    +
    +        all , http, ftp, other;
    +    }
    +
    +    server;
    +
    +    struct
    +    {
    +        int pkts_sent;
    +        int queries_sent;
    +        int replies_sent;
    +        int pkts_recv;
    +        int queries_recv;
    +        int replies_recv;
    +        int hits_sent;
    +        int hits_recv;
    +        int replies_queued;
    +        int replies_dropped;
    +        kb_t kbytes_sent;
    +        kb_t q_kbytes_sent;
    +        kb_t r_kbytes_sent;
    +        kb_t kbytes_recv;
    +        kb_t q_kbytes_recv;
    +        kb_t r_kbytes_recv;
    +        StatHist query_svc_time;
    +        StatHist reply_svc_time;
    +        int query_timeouts;
    +        int times_used;
    +    }
    +
    +    icp;
    +
    +    struct
    +    {
    +        int requests;
    +    }
    +
    +    unlink;
    +
    +    struct
    +    {
    +        StatHist svc_time;
    +    }
    +
    +    dns;
    +
    +    struct
    +    {
    +        int times_used;
    +        kb_t kbytes_sent;
    +        kb_t kbytes_recv;
    +        kb_t memory;
    +        int msgs_sent;
    +        int msgs_recv;
     #if USE_CACHE_DIGESTS
    -	cd_guess_stats guess;
    +
    +        cd_guess_stats guess;
     #endif
    -	StatHist on_xition_count;
    -    } cd;
    -    struct {
    -	int times_used;
    -    } netdb;
    +
    +        StatHist on_xition_count;
    +    }
    +
    +    cd;
    +
    +    struct
    +    {
    +        int times_used;
    +    }
    +
    +    netdb;
         int page_faults;
         int select_loops;
         int select_fds;
         double select_time;
         double cputime;
    +
         struct timeval timestamp;
         StatHist comm_icp_incoming;
         StatHist comm_dns_incoming;
         StatHist comm_http_incoming;
         StatHist select_fds_hist;
    -    struct {
    -	struct {
    -	    int opens;
    -	    int closes;
    -	    int reads;
    -	    int writes;
    -	    int seeks;
    -	    int unlinks;
    -	} disk;
    -	struct {
    -	    int accepts;
    -	    int sockets;
    -	    int connects;
    -	    int binds;
    -	    int closes;
    -	    int reads;
    -	    int writes;
    -	    int recvfroms;
    -	    int sendtos;
    -	} sock;
    +
    +    struct
    +    {
    +
    +        struct
    +        {
    +            int opens;
    +            int closes;
    +            int reads;
    +            int writes;
    +            int seeks;
    +            int unlinks;
    +        }
    +
    +        disk;
    +
    +        struct
    +        {
    +            int accepts;
    +            int sockets;
    +            int connects;
    +            int binds;
    +            int closes;
    +            int reads;
    +            int writes;
    +            int recvfroms;
    +            int sendtos;
    +        }
    +
    +        sock;
     #if HAVE_POLL
    -	int polls;
    +
    +        int polls;
     #else
    -	int selects;
    +
    +        int selects;
     #endif
    -    } syscalls;
    +
    +    }
    +
    +    syscalls;
         int aborted_requests;
    -    struct {
    -	int files_cleaned;
    -	int outs;
    -	int ins;
    -    } swap;
    +
    +    struct
    +    {
    +        int files_cleaned;
    +        int outs;
    +        int ins;
    +    }
    +
    +    swap;
     };
     
     /* per header statistics */
    -struct _HttpHeaderStat {
    +
    +struct _HttpHeaderStat
    +{
         const char *label;
         HttpHeaderMask *owner_mask;
     
    @@ -1440,7 +2015,9 @@ struct _HttpHeaderStat {
      * Do we need to have the dirn in here? I don't think so, since we already
      * know the dirn .. 
      */
    -struct _storeSwapLogData {
    +
    +struct _storeSwapLogData
    +{
         char op;
         sfileno swap_filen;
         time_t timestamp;
    @@ -1453,25 +2030,36 @@ struct _storeSwapLogData {
         unsigned char key[MD5_DIGEST_CHARS];
     };
     
    -struct _ClientInfo {
    +struct _ClientInfo
    +{
         hash_link hash;		/* must be first */
    +
         struct in_addr addr;
    -    struct {
    -	int result_hist[LOG_TYPE_MAX];
    -	int n_requests;
    -	kb_t kbytes_in;
    -	kb_t kbytes_out;
    -	kb_t hit_kbytes_out;
    -    } Http, Icp;
    -    struct {
    -	time_t time;
    -	int n_req;
    -	int n_denied;
    -    } cutoff;
    +
    +    struct
    +    {
    +        int result_hist[LOG_TYPE_MAX];
    +        int n_requests;
    +        kb_t kbytes_in;
    +        kb_t kbytes_out;
    +        kb_t hit_kbytes_out;
    +    }
    +
    +    Http, Icp;
    +
    +    struct
    +    {
    +        time_t time;
    +        int n_req;
    +        int n_denied;
    +    }
    +
    +    cutoff;
         int n_established;		/* number of current established connections */
     };
     
    -struct _CacheDigest {
    +struct _CacheDigest
    +{
         /* public, read-only */
         char *mask;			/* bit mask */
         size_t mask_size;		/* mask size in bytes */
    @@ -1481,13 +2069,15 @@ struct _CacheDigest {
         int del_count;		/* number of deletions performed so far */
     };
     
    -struct _FwdServer {
    +struct _FwdServer
    +{
         peer *_peer;		/* NULL --> origin server */
         hier_code code;
         FwdServer *next;
     };
     
    -struct _FwdState {
    +struct _FwdState
    +{
         int client_fd;
         StoreEntry *entry;
         request_t *request;
    @@ -1497,47 +2087,65 @@ struct _FwdState {
         time_t start;
         int n_tries;
     #if WIP_FWD_LOG
    +
         http_status last_status;
     #endif
    -    struct {
    -	unsigned int dont_retry:1;
    -	unsigned int ftp_pasv_failed:1;
    -    } flags;
    +
    +    struct
    +    {
    +
    +unsigned int dont_retry:
    +        1;
    +
    +unsigned int ftp_pasv_failed:
    +        1;
    +    }
    +
    +    flags;
     };
     
     #if USE_HTCP
    -struct _htcpReplyData {
    +
    +struct _htcpReplyData
    +{
         int hit;
         HttpHeader hdr;
         u_int32_t msg_id;
         double version;
    -    struct {
    -	/* cache-to-origin */
    -	double rtt;
    -	int samp;
    -	int hops;
    -    } cto;
    +
    +    struct
    +    {
    +        /* cache-to-origin */
    +        double rtt;
    +        int samp;
    +        int hops;
    +    }
    +
    +    cto;
     };
     
     #endif
     
     
    -struct _helper_request {
    +struct _helper_request
    +{
         char *buf;
         HLPCB *callback;
         void *data;
     };
     
    -struct _helper_stateful_request {
    +struct _helper_stateful_request
    +{
         char *buf;
         HLPSCB *callback;
         int placeholder;		/* if 1, this is a dummy request waiting for a stateful helper
    -				 * to become available for deferred requests.*/
    +    		        				 * to become available for deferred requests.*/
         void *data;
     };
     
     
    -struct _helper {
    +struct _helper
    +{
         wordlist *cmdline;
         dlink_list servers;
         dlink_list queue;
    @@ -1546,15 +2154,20 @@ struct _helper {
         int n_running;
         int ipc_type;
         time_t last_queue_warn;
    -    struct {
    -	int requests;
    -	int replies;
    -	int queue_size;
    -	int avg_svc_time;
    -    } stats;
    +
    +    struct
    +    {
    +        int requests;
    +        int replies;
    +        int queue_size;
    +        int avg_svc_time;
    +    }
    +
    +    stats;
     };
     
    -struct _helper_stateful {
    +struct _helper_stateful
    +{
         wordlist *cmdline;
         dlink_list servers;
         dlink_list queue;
    @@ -1566,15 +2179,20 @@ struct _helper_stateful {
         HLPSAVAIL *IsAvailable;
         HLPSONEQ *OnEmptyQueue;
         time_t last_queue_warn;
    -    struct {
    -	int requests;
    -	int replies;
    -	int queue_size;
    -	int avg_svc_time;
    -    } stats;
    +
    +    struct
    +    {
    +        int requests;
    +        int replies;
    +        int queue_size;
    +        int avg_svc_time;
    +    }
    +
    +    stats;
     };
     
    -struct _helper_server {
    +struct _helper_server
    +{
         int index;
         int pid;
         int rfd;
    @@ -1582,24 +2200,43 @@ struct _helper_server {
         char *buf;
         size_t buf_sz;
         off_t offset;
    +
         struct timeval dispatch_time;
    +
         struct timeval answer_time;
         dlink_node link;
         helper *parent;
         helper_request *request;
    -    struct _helper_flags {
    -	unsigned int alive:1;
    -	unsigned int busy:1;
    -	unsigned int closing:1;
    -	unsigned int shutdown:1;
    -    } flags;
    -    struct {
    -	int uses;
    -    } stats;
    +
    +    struct _helper_flags
    +    {
    +
    +unsigned int alive:
    +        1;
    +
    +unsigned int busy:
    +        1;
    +
    +unsigned int closing:
    +        1;
    +
    +unsigned int shutdown:
    +        1;
    +    }
    +
    +    flags;
    +
    +    struct
    +    {
    +        int uses;
    +    }
    +
    +    stats;
     };
     
     
    -struct _helper_stateful_server {
    +struct _helper_stateful_server
    +{
         int index;
         int pid;
         int rfd;
    @@ -1607,26 +2244,44 @@ struct _helper_stateful_server {
         char *buf;
         size_t buf_sz;
         off_t offset;
    +
         struct timeval dispatch_time;
    +
         struct timeval answer_time;
         dlink_node link;
         dlink_list queue;
         statefulhelper *parent;
         helper_stateful_request *request;
    -    struct _helper_stateful_flags {
    -	unsigned int alive:1;
    -	unsigned int busy:1;
    -	unsigned int closing:1;
    -	unsigned int shutdown:1;
    -	stateful_helper_reserve_t reserved;
    -    } flags;
    -    struct {
    -	int uses;
    -	int submits;
    -	int releases;
    -	int deferbyfunc;
    -	int deferbycb;
    -    } stats;
    +
    +    struct _helper_stateful_flags
    +    {
    +
    +unsigned int alive:
    +        1;
    +
    +unsigned int busy:
    +        1;
    +
    +unsigned int closing:
    +        1;
    +
    +unsigned int shutdown:
    +        1;
    +        stateful_helper_reserve_t reserved;
    +    }
    +
    +    flags;
    +
    +    struct
    +    {
    +        int uses;
    +        int submits;
    +        int releases;
    +        int deferbyfunc;
    +        int deferbycb;
    +    }
    +
    +    stats;
         int deferred_requests;	/* current number of deferred requests */
         void *data;			/* State data used by the calling routines */
     };
    @@ -1635,11 +2290,14 @@ struct _helper_stateful_server {
      * use this when you need to pass callback data to a blocking
      * operation, but you don't want to add that pointer to cbdata
      */
    -struct _generic_cbdata {
    +
    +struct _generic_cbdata
    +{
         void *data;
     };
     
    -struct _store_rebuild_data {
    +struct _store_rebuild_data
    +{
         int objcount;		/* # objects successfully reloaded */
         int expcount;		/* # objects expired */
         int scancount;		/* # entries scanned or read from state file */
    @@ -1656,7 +2314,8 @@ struct _store_rebuild_data {
      * This defines an fs type
      */
     
    -struct _storefs_entry {
    +struct _storefs_entry
    +{
         const char *typestr;
         STFSSHUTDOWN *donefunc;
         STFSNEW *newfunc;
    @@ -1666,7 +2325,8 @@ struct _storefs_entry {
      * This defines an repl type
      */
     
    -struct _storerepl_entry {
    +struct _storerepl_entry
    +{
         const char *typestr;
         REMOVALPOLICYCREATE *create;
     };
    @@ -1675,32 +2335,45 @@ struct _storerepl_entry {
      * Async disk IO - this defines a async disk io queue
      */
     
    -struct _diskd_queue {
    +struct _diskd_queue
    +{
         int smsgid;			/* send sysvmsg id */
         int rmsgid;			/* recv sysvmsg id */
         int wfd;			/* queue file descriptor ? */
         int away;			/* number of requests away */
         int sent_count;		/* number of messages sent */
         int recv_count;		/* number of messages received */
    -    struct {
    -	char *buf;		/* shm buffer */
    -	link_list *stack;
    -	int id;			/* sysvshm id */
    -    } shm;
    +
    +    struct
    +    {
    +        char *buf;		/* shm buffer */
    +        link_list *stack;
    +        int id;			/* sysvshm id */
    +    }
    +
    +    shm;
     };
     
    -struct _Logfile {
    +struct _Logfile
    +{
         int fd;
         char path[MAXPATHLEN];
         char *buf;
         size_t bufsz;
         off_t offset;
    -    struct {
    -	unsigned int fatal:1;
    -    } flags;
    +
    +    struct
    +    {
    +
    +unsigned int fatal:
    +        1;
    +    }
    +
    +    flags;
     };
     
    -struct cache_dir_option {
    +struct cache_dir_option
    +{
         const char *name;
         void (*parse) (SwapDir * sd, const char *option, const char *value, int reconfiguring);
         void (*dump) (StoreEntry * e, const char *option, SwapDir const * sd);
    diff --git a/src/test_cache_digest.cc b/src/test_cache_digest.cc
    index 9560ae2149..1cb66584fa 100644
    --- a/src/test_cache_digest.cc
    +++ b/src/test_cache_digest.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: test_cache_digest.cc,v 1.29 2003/01/23 00:37:27 robertc Exp $
    + * $Id: test_cache_digest.cc,v 1.30 2003/02/21 22:50:12 robertc Exp $
      *
      * AUTHOR: Alex Rousskov
      *
    @@ -38,16 +38,21 @@
     
     #include "squid.h"
     
    -typedef struct {
    +typedef struct
    +{
         int query_count;
         int true_hit_count;
         int true_miss_count;
         int false_hit_count;
         int false_miss_count;
    -} CacheQueryStats;
    +}
    +
    +CacheQueryStats;
     
     typedef struct _Cache Cache;
    -struct _Cache {
    +
    +struct _Cache
    +{
         const char *name;
         hash_table *hash;
         CacheDigest *digest;
    @@ -60,27 +65,37 @@ struct _Cache {
     };
     
     
    -typedef struct _CacheEntry {
    +typedef struct _CacheEntry
    +{
         const cache_key *key;
    +
         struct _CacheEntry *next;
         unsigned char key_arr[MD5_DIGEST_CHARS];
         /* storeSwapLogData s; */
    -} CacheEntry;
    +}
    +
    +CacheEntry;
     
     /* parsed access log entry */
    -typedef struct {
    +
    +typedef struct
    +{
         cache_key key[MD5_DIGEST_CHARS];
         time_t timestamp;
         short int use_icp;		/* true/false */
    -} RawAccessLogEntry;
    +}
    +
    +RawAccessLogEntry;
     
     typedef enum {
         frError = -2, frMore = -1, frEof = 0, frOk = 1
     } fr_result;
    +
     typedef struct _FileIterator FileIterator;
     typedef fr_result(*FI_READER) (FileIterator * fi);
     
    -struct _FileIterator {
    +struct _FileIterator
    +{
         const char *fname;
         FILE *file;
         time_t inner_time;		/* timestamp of the current entry */
    @@ -97,35 +112,37 @@ static time_t cur_time = -1;	/* timestamp of the current log entry */
     
     /* copied from url.c */
     const char *RequestMethodStr[] =
    -{
    -    "NONE",
    -    "GET",
    -    "POST",
    -    "PUT",
    -    "HEAD",
    -    "CONNECT",
    -    "TRACE",
    -    "PURGE"
    -};
    +    {
    +        "NONE",
    +        "GET",
    +        "POST",
    +        "PUT",
    +        "HEAD",
    +        "CONNECT",
    +        "TRACE",
    +        "PURGE"
    +    };
    +
     /* copied from url.c */
     static method_t
     methodStrToId(const char *s)
     {
         if (strcasecmp(s, "GET") == 0) {
    -	return METHOD_GET;
    +        return METHOD_GET;
         } else if (strcasecmp(s, "POST") == 0) {
    -	return METHOD_POST;
    +        return METHOD_POST;
         } else if (strcasecmp(s, "PUT") == 0) {
    -	return METHOD_PUT;
    +        return METHOD_PUT;
         } else if (strcasecmp(s, "HEAD") == 0) {
    -	return METHOD_HEAD;
    +        return METHOD_HEAD;
         } else if (strcasecmp(s, "CONNECT") == 0) {
    -	return METHOD_CONNECT;
    +        return METHOD_CONNECT;
         } else if (strcasecmp(s, "TRACE") == 0) {
    -	return METHOD_TRACE;
    +        return METHOD_TRACE;
         } else if (strcasecmp(s, "PURGE") == 0) {
    -	return METHOD_PURGE;
    +        return METHOD_PURGE;
         }
    +
         return METHOD_NONE;
     }
     
    @@ -141,12 +158,15 @@ fileIteratorCreate(const char *fname, FI_READER reader)
         fi->fname = fname;
         fi->reader = reader;
         fi->file = fopen(fname, "r");
    +
         if (!fi->file) {
    -	fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno));
    -	return NULL;
    +        fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno));
    +        return NULL;
         } else
    -	fprintf(stderr, "opened %s\n", fname);
    +        fprintf(stderr, "opened %s\n", fname);
    +
         fileIteratorAdvance(fi);
    +
         return fi;
     }
     
    @@ -154,10 +174,12 @@ static void
     fileIteratorDestroy(FileIterator * fi)
     {
         assert(fi);
    +
         if (fi->file) {
    -	fclose(fi->file);
    -	fprintf(stderr, "closed %s\n", fi->fname);
    +        fclose(fi->file);
    +        fprintf(stderr, "closed %s\n", fi->fname);
         }
    +
         xfree(fi->entry);
         xfree(fi);
     }
    @@ -175,31 +197,35 @@ fileIteratorAdvance(FileIterator * fi)
     {
         int res;
         assert(fi);
    +
         do {
    -	const time_t last_time = fi->inner_time;
    -	fi->inner_time = -1;
    -	res = fi->reader(fi);
    -	fi->line_count++;
    -	if (fi->inner_time < 0)
    -	    fi->inner_time = last_time;
    -	else
    -	    fi->inner_time += fi->time_offset;
    -	if (res == frError)
    -	    fi->bad_line_count++;
    -	else if (res == frEof) {
    -	    fprintf(stderr, "exhausted %s (%d entries) at %s",
    -		fi->fname, fi->line_count, ctime(&fi->inner_time));
    -	    fi->inner_time = -1;
    -	} else if (fi->inner_time < last_time) {
    -	    assert(last_time >= 0);
    -	    fi->time_warp_count++;
    -	    fi->inner_time = last_time;
    -	}
    -	/* report progress */
    -	if (!(fi->line_count % 50000))
    -	    fprintf(stderr, "%s scanned %d K entries (%d bad) at %s",
    -		fi->fname, fi->line_count / 1000, fi->bad_line_count,
    -		ctime(&fi->inner_time));
    +        const time_t last_time = fi->inner_time;
    +        fi->inner_time = -1;
    +        res = fi->reader(fi);
    +        fi->line_count++;
    +
    +        if (fi->inner_time < 0)
    +            fi->inner_time = last_time;
    +        else
    +            fi->inner_time += fi->time_offset;
    +
    +        if (res == frError)
    +            fi->bad_line_count++;
    +        else if (res == frEof) {
    +            fprintf(stderr, "exhausted %s (%d entries) at %s",
    +                    fi->fname, fi->line_count, ctime(&fi->inner_time));
    +            fi->inner_time = -1;
    +        } else if (fi->inner_time < last_time) {
    +            assert(last_time >= 0);
    +            fi->time_warp_count++;
    +            fi->inner_time = last_time;
    +        }
    +
    +        /* report progress */
    +        if (!(fi->line_count % 50000))
    +            fprintf(stderr, "%s scanned %d K entries (%d bad) at %s",
    +                    fi->fname, fi->line_count / 1000, fi->bad_line_count,
    +                    ctime(&fi->inner_time));
         } while (res < 0);
     }
     
    @@ -246,14 +272,18 @@ cacheDestroy(Cache * cache)
         hash = cache->hash;
         /* destroy hash table contents */
         hash_first(hash);
    +
         while ((e = (CacheEntry *)hash_next(hash))) {
    -	hash_remove_link(hash, (hash_link *) e);
    -	cacheEntryDestroy(e);
    +        hash_remove_link(hash, (hash_link *) e);
    +        cacheEntryDestroy(e);
         }
    +
         /* destroy the hash table itself */
         hashFreeMemory(hash);
    +
         if (cache->digest)
    -	cacheDigestDestroy(cache->digest);
    +        cacheDigestDestroy(cache->digest);
    +
         xfree(cache);
     }
     
    @@ -263,39 +293,49 @@ cacheResetDigest(Cache * cache)
     {
         CacheEntry *e = NULL;
         hash_table *hash;
    +
         struct timeval t_start, t_end;
     
         assert(cache);
         fprintf(stderr, "%s: init-ing digest with %d entries\n", cache->name, cache->count);
    +
         if (cache->digest)
    -	cacheDigestDestroy(cache->digest);
    +        cacheDigestDestroy(cache->digest);
    +
         hash = cache->hash;
    +
         cache->digest = cacheDigestCreate(cache->count + 1, 6);
    +
         if (!cache->count)
    -	return;
    +        return;
    +
         gettimeofday(&t_start, NULL);
    +
         hash_first(hash);
    +
         while ((e = (CacheEntry *)hash_next(hash))) {
    -	cacheDigestAdd(cache->digest, e->key);
    +        cacheDigestAdd(cache->digest, e->key);
         }
    +
         gettimeofday(&t_end, NULL);
         assert(cache->digest->count == cache->count);
         fprintf(stderr, "%s: init-ed  digest with %d entries\n",
    -	cache->name, cache->digest->count);
    +            cache->name, cache->digest->count);
         fprintf(stderr, "%s: init took: %f sec, %f sec/M\n",
    -	cache->name,
    -	tvSubDsec(t_start, t_end),
    -	(double) 1e6 * tvSubDsec(t_start, t_end) / cache->count);
    +            cache->name,
    +            tvSubDsec(t_start, t_end),
    +            (double) 1e6 * tvSubDsec(t_start, t_end) / cache->count);
         /* check how long it takes to traverse the hash */
         gettimeofday(&t_start, NULL);
         hash_first(hash);
    -    for (e = (CacheEntry *)hash_next(hash); e; e = (CacheEntry *)hash_next(hash)) {
    -    }
    +
    +    for (e = (CacheEntry *)hash_next(hash); e; e = (CacheEntry *)hash_next(hash)) {}
    +
         gettimeofday(&t_end, NULL);
         fprintf(stderr, "%s: hash scan took: %f sec, %f sec/M\n",
    -	cache->name,
    -	tvSubDsec(t_start, t_end),
    -	(double) 1e6 * tvSubDsec(t_start, t_end) / cache->count);
    +            cache->name,
    +            tvSubDsec(t_start, t_end),
    +            (double) 1e6 * tvSubDsec(t_start, t_end) / cache->count);
     }
     
     static void
    @@ -305,16 +345,17 @@ cacheQueryPeer(Cache * cache, const cache_key * key)
         const int we_think_we_have_it = cacheDigestTest(cache->digest, key);
     
         cache->qstats.query_count++;
    +
         if (peer_has_it) {
    -	if (we_think_we_have_it)
    -	    cache->qstats.true_hit_count++;
    -	else
    -	    cache->qstats.false_miss_count++;
    +        if (we_think_we_have_it)
    +            cache->qstats.true_hit_count++;
    +        else
    +            cache->qstats.false_miss_count++;
         } else {
    -	if (we_think_we_have_it)
    -	    cache->qstats.false_hit_count++;
    -	else
    -	    cache->qstats.true_miss_count++;
    +        if (we_think_we_have_it)
    +            cache->qstats.false_hit_count++;
    +        else
    +            cache->qstats.true_miss_count++;
         }
     }
     
    @@ -322,31 +363,31 @@ static void
     cacheQueryReport(Cache * cache, CacheQueryStats * stats)
     {
         fprintf(stdout, "%s: peer queries: %d (%d%%)\n",
    -	cache->name,
    -	stats->query_count, xpercentInt(stats->query_count, cache->req_count)
    -	);
    +            cache->name,
    +            stats->query_count, xpercentInt(stats->query_count, cache->req_count)
    +           );
         fprintf(stdout, "%s: t-hit: %d (%d%%) t-miss: %d (%d%%) t-*: %d (%d%%)\n",
    -	cache->name,
    -	stats->true_hit_count, xpercentInt(stats->true_hit_count, stats->query_count),
    -	stats->true_miss_count, xpercentInt(stats->true_miss_count, stats->query_count),
    -	stats->true_hit_count + stats->true_miss_count,
    -	xpercentInt(stats->true_hit_count + stats->true_miss_count, stats->query_count)
    -	);
    +            cache->name,
    +            stats->true_hit_count, xpercentInt(stats->true_hit_count, stats->query_count),
    +            stats->true_miss_count, xpercentInt(stats->true_miss_count, stats->query_count),
    +            stats->true_hit_count + stats->true_miss_count,
    +            xpercentInt(stats->true_hit_count + stats->true_miss_count, stats->query_count)
    +           );
         fprintf(stdout, "%s: f-hit: %d (%d%%) f-miss: %d (%d%%) f-*: %d (%d%%)\n",
    -	cache->name,
    -	stats->false_hit_count, xpercentInt(stats->false_hit_count, stats->query_count),
    -	stats->false_miss_count, xpercentInt(stats->false_miss_count, stats->query_count),
    -	stats->false_hit_count + stats->false_miss_count,
    -	xpercentInt(stats->false_hit_count + stats->false_miss_count, stats->query_count)
    -	);
    +            cache->name,
    +            stats->false_hit_count, xpercentInt(stats->false_hit_count, stats->query_count),
    +            stats->false_miss_count, xpercentInt(stats->false_miss_count, stats->query_count),
    +            stats->false_hit_count + stats->false_miss_count,
    +            xpercentInt(stats->false_hit_count + stats->false_miss_count, stats->query_count)
    +           );
     }
     
     static void
     cacheReport(Cache * cache)
     {
         fprintf(stdout, "%s: entries: %d reqs: %d bad-add: %d bad-del: %d\n",
    -	cache->name, cache->count, cache->req_count,
    -	cache->bad_add_count, cache->bad_del_count);
    +            cache->name, cache->count, cache->req_count,
    +            cache->bad_add_count, cache->bad_del_count);
     
     }
     
    @@ -355,24 +396,31 @@ cacheFetch(Cache * cache, const RawAccessLogEntry * e)
     {
         assert(e);
         cache->req_count++;
    +
         if (e->use_icp)
    -	cacheQueryPeer(cache, e->key);
    +        cacheQueryPeer(cache, e->key);
     }
     
     static fr_result
     swapStateReader(FileIterator * fi)
     {
         storeSwapLogData *entry;
    +
         if (!fi->entry)
    -	fi->entry = xcalloc(1, sizeof(storeSwapLogData));
    +        fi->entry = xcalloc(1, sizeof(storeSwapLogData));
    +
         entry = (storeSwapLogData *)fi->entry;
    +
         if (fread(entry, sizeof(*entry), 1, fi->file) != 1)
    -	return frEof;
    +        return frEof;
    +
         fi->inner_time = entry->lastref;
    +
         if (entry->op != SWAP_LOG_ADD && entry->op != SWAP_LOG_DEL) {
    -	fprintf(stderr, "%s:%d: unknown swap log action\n", fi->fname, fi->line_count);
    -	exit(-3);
    +        fprintf(stderr, "%s:%d: unknown swap log action\n", fi->fname, fi->line_count);
    +        exit(-3);
         }
    +
         return frOk;
     }
     
    @@ -387,57 +435,76 @@ accessLogReader(FileIterator * fi)
         char *hier = NULL;
     
         assert(fi);
    +
         if (!fi->entry)
    -	fi->entry = xcalloc(1, sizeof(RawAccessLogEntry));
    +        fi->entry = xcalloc(1, sizeof(RawAccessLogEntry));
         else
    -	memset(fi->entry, 0, sizeof(RawAccessLogEntry));
    +        memset(fi->entry, 0, sizeof(RawAccessLogEntry));
    +
         entry = (RawAccessLogEntry*)fi->entry;
    +
         if (!fgets(buf, sizeof(buf), fi->file))
    -	return frEof;		/* eof */
    +        return frEof;		/* eof */
    +
         entry->timestamp = fi->inner_time = (time_t) atoi(buf);
    +
         url = strstr(buf, "://");
    +
         hier = url ? strstr(url, " - ") : NULL;
     
         if (!url || !hier) {
    -	/*fprintf(stderr, "%s:%d: strange access log entry '%s'\n", 
    -	 * fname, scanned_count, buf); */
    -	return frError;
    +        /*fprintf(stderr, "%s:%d: strange access log entry '%s'\n",
    +         * fname, scanned_count, buf); */
    +        return frError;
         }
    +
         method = url;
    +
         while (!isdigit(*method)) {
    -	if (*method == ' ')
    -	    *method = '\0';
    -	--method;
    +        if (*method == ' ')
    +            *method = '\0';
    +
    +        --method;
         }
    +
         method += 2;
         method_id = methodStrToId(method);
    +
         if (method_id == METHOD_NONE) {
    -	/*fprintf(stderr, "%s:%d: invalid method %s in '%s'\n", 
    -	 * fname, scanned_count, method, buf); */
    -	return frError;
    +        /*fprintf(stderr, "%s:%d: invalid method %s in '%s'\n",
    +         * fname, scanned_count, method, buf); */
    +        return frError;
         }
    +
         while (*url)
    -	url--;
    +        url--;
    +
         url++;
    +
         *hier = '\0';
    +
         hier += 3;
    +
         *strchr(hier, '/') = '\0';
    +
         /*fprintf(stdout, "%s:%d: %s %s %s\n",
          * fname, count, method, url, hier); */
         entry->use_icp = strcmp(hier, "NONE");
    +
         /* no ICP lookup for these status codes */
    -/*      strcmp(hier, "NONE") &&
    - * strcmp(hier, "DIRECT") &&
    - * strcmp(hier, "FIREWALL_IP_DIRECT") &&
    - * strcmp(hier, "LOCAL_IP_DIRECT") &&
    - * strcmp(hier, "NO_DIRECT_FAIL") &&
    - * strcmp(hier, "NO_PARENT_DIRECT") &&
    - * strcmp(hier, "SINGLE_PARENT") &&
    - * strcmp(hier, "PASSTHROUGH_PARENT") &&
    - * strcmp(hier, "SSL_PARENT_MISS") &&
    - * strcmp(hier, "DEFAULT_PARENT");
    - */
    +    /*      strcmp(hier, "NONE") &&
    +     * strcmp(hier, "DIRECT") &&
    +     * strcmp(hier, "FIREWALL_IP_DIRECT") &&
    +     * strcmp(hier, "LOCAL_IP_DIRECT") &&
    +     * strcmp(hier, "NO_DIRECT_FAIL") &&
    +     * strcmp(hier, "NO_PARENT_DIRECT") &&
    +     * strcmp(hier, "SINGLE_PARENT") &&
    +     * strcmp(hier, "PASSTHROUGH_PARENT") &&
    +     * strcmp(hier, "SSL_PARENT_MISS") &&
    +     * strcmp(hier, "DEFAULT_PARENT");
    +     */
         xmemcpy(entry->key, storeKeyPublic(url, method_id), sizeof(entry->key));
    +
         /*fprintf(stdout, "%s:%d: %s %s %s %s\n",
          * fname, count, method, storeKeyText(entry->key), url, hier); */
         return frOk;
    @@ -448,15 +515,19 @@ static void
     cachePurge(Cache * cache, storeSwapLogData * s, int update_digest)
     {
         CacheEntry *olde = (CacheEntry *) hash_lookup(cache->hash, s->key);
    +
         if (!olde) {
    -	cache->bad_del_count++;
    +        cache->bad_del_count++;
         } else {
    -	assert(cache->count);
    -	hash_remove_link(cache->hash, (hash_link *) olde);
    -	if (update_digest)
    -	    cacheDigestDel(cache->digest, s->key);
    -	cacheEntryDestroy(olde);
    -	cache->count--;
    +        assert(cache->count);
    +        hash_remove_link(cache->hash, (hash_link *) olde);
    +
    +        if (update_digest)
    +            cacheDigestDel(cache->digest, s->key);
    +
    +        cacheEntryDestroy(olde);
    +
    +        cache->count--;
         }
     }
     
    @@ -464,14 +535,16 @@ static void
     cacheStore(Cache * cache, storeSwapLogData * s, int update_digest)
     {
         CacheEntry *olde = (CacheEntry *) hash_lookup(cache->hash, s->key);
    +
         if (olde) {
    -	cache->bad_add_count++;
    +        cache->bad_add_count++;
         } else {
    -	CacheEntry *e = cacheEntryCreate(s);
    -	hash_join(cache->hash, (hash_link *)&e->key);
    -	cache->count++;
    -	if (update_digest)
    -	    cacheDigestAdd(cache->digest, e->key);
    +        CacheEntry *e = cacheEntryCreate(s);
    +        hash_join(cache->hash, (hash_link *)&e->key);
    +        cache->count++;
    +
    +        if (update_digest)
    +            cacheDigestAdd(cache->digest, e->key);
         }
     }
     
    @@ -479,14 +552,17 @@ static void
     cacheUpdateStore(Cache * cache, storeSwapLogData * s, int update_digest)
     {
         switch (s->op) {
    +
         case SWAP_LOG_ADD:
    -	cacheStore(cache, s, update_digest);
    -	break;
    +        cacheStore(cache, s, update_digest);
    +        break;
    +
         case SWAP_LOG_DEL:
    -	cachePurge(cache, s, update_digest);
    -	break;
    +        cachePurge(cache, s, update_digest);
    +        break;
    +
         default:
    -	assert(0);
    +        assert(0);
         }
     }
     
    @@ -494,7 +570,7 @@ static int
     usage(const char *prg_name)
     {
         fprintf(stderr, "usage: %s   ...\n",
    -	prg_name);
    +            prg_name);
         return -1;
     }
     
    @@ -509,41 +585,55 @@ main(int argc, char *argv[])
         int i;
     
         if (argc < 3)
    -	return usage(argv[0]);
    +        return usage(argv[0]);
     
         them = cacheCreate("them");
    +
         us = cacheCreate("us");
    +
         them->peer = us;
    +
         us->peer = them;
     
         fis = (FileIterator **)xcalloc(fi_count, sizeof(FileIterator *));
    +
         /* init iterators with files */
         fis[0] = fileIteratorCreate(argv[1], accessLogReader);
    +
         for (i = 2; i < argc; ++i)
    -	fis[i - 1] = fileIteratorCreate(argv[i], swapStateReader);
    +        fis[i - 1] = fileIteratorCreate(argv[i], swapStateReader);
    +
         /* check that all files were found */
         for (i = 0; i < fi_count; ++i)
    -	if (!fis[i])
    -	    return -2;
    +        if (!fis[i])
    +            return -2;
    +
         /* read prefix to get start-up contents of the peer cache */
         ready_time = -1;
    +
         for (i = 1; i < fi_count; ++i) {
    -	FileIterator *fi = fis[i];
    -	while (fi->inner_time > 0) {
    -	    if (((storeSwapLogData *) fi->entry)->op == SWAP_LOG_DEL) {
    -		cachePurge(them, (storeSwapLogData *)fi->entry, 0);
    -		if (ready_time < 0)
    -		    ready_time = fi->inner_time;
    -	    } else {
    -		if (ready_time > 0 && fi->inner_time > ready_time)
    -		    break;
    -		cacheStore(them, (storeSwapLogData *)fi->entry, 0);
    -	    }
    -	    fileIteratorAdvance(fi);
    -	}
    +        FileIterator *fi = fis[i];
    +
    +        while (fi->inner_time > 0) {
    +            if (((storeSwapLogData *) fi->entry)->op == SWAP_LOG_DEL) {
    +                cachePurge(them, (storeSwapLogData *)fi->entry, 0);
    +
    +                if (ready_time < 0)
    +                    ready_time = fi->inner_time;
    +            } else {
    +                if (ready_time > 0 && fi->inner_time > ready_time)
    +                    break;
    +
    +                cacheStore(them, (storeSwapLogData *)fi->entry, 0);
    +            }
    +
    +            fileIteratorAdvance(fi);
    +        }
         }
    +
         /* digest peer cache content */
         cacheResetDigest(them);
    +
         us->digest = cacheDigestClone(them->digest);	/* @netw@ */
     
         /* shift the time in access log to match ready_time */
    @@ -551,39 +641,48 @@ main(int argc, char *argv[])
     
         /* iterate, use the iterator with the smallest positive inner_time */
         cur_time = -1;
    +
         do {
    -	int next_i = -1;
    -	time_t next_time = -1;
    -	active_fi_count = 0;
    -	for (i = 0; i < fi_count; ++i) {
    -	    if (fis[i]->inner_time >= 0) {
    -		if (!active_fi_count || fis[i]->inner_time < next_time) {
    -		    next_i = i;
    -		    next_time = fis[i]->inner_time;
    -		}
    -		active_fi_count++;
    -	    }
    -	}
    -	if (next_i >= 0) {
    -	    cur_time = next_time;
    -	    /*fprintf(stderr, "%2d time: %d %s", next_i, (int)cur_time, ctime(&cur_time)); */
    -	    if (next_i == 0)
    -		cacheFetch(us, (RawAccessLogEntry *)fis[next_i]->entry);
    -	    else
    -		cacheUpdateStore(them, (storeSwapLogData *)fis[next_i]->entry, 1);
    -	    fileIteratorAdvance(fis[next_i]);
    -	}
    +        int next_i = -1;
    +        time_t next_time = -1;
    +        active_fi_count = 0;
    +
    +        for (i = 0; i < fi_count; ++i) {
    +            if (fis[i]->inner_time >= 0) {
    +                if (!active_fi_count || fis[i]->inner_time < next_time) {
    +                    next_i = i;
    +                    next_time = fis[i]->inner_time;
    +                }
    +
    +                active_fi_count++;
    +            }
    +        }
    +
    +        if (next_i >= 0) {
    +            cur_time = next_time;
    +            /*fprintf(stderr, "%2d time: %d %s", next_i, (int)cur_time, ctime(&cur_time)); */
    +
    +            if (next_i == 0)
    +                cacheFetch(us, (RawAccessLogEntry *)fis[next_i]->entry);
    +            else
    +                cacheUpdateStore(them, (storeSwapLogData *)fis[next_i]->entry, 1);
    +
    +            fileIteratorAdvance(fis[next_i]);
    +        }
         } while (active_fi_count);
     
         /* report */
         cacheReport(them);
    +
         cacheReport(us);
    +
         cacheQueryReport(us, &us->qstats);
     
         /* clean */
         for (i = 0; i < argc - 1; ++i) {
    -	fileIteratorDestroy(fis[i]);
    +        fileIteratorDestroy(fis[i]);
         }
    +
         xfree(fis);
         cacheDestroy(them);
         cacheDestroy(us);
    diff --git a/src/tools.cc b/src/tools.cc
    index 00fbb99d87..6babb3dc14 100644
    --- a/src/tools.cc
    +++ b/src/tools.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: tools.cc,v 1.232 2003/02/21 19:53:02 hno Exp $
    + * $Id: tools.cc,v 1.233 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 21    Misc Functions
      * AUTHOR: Harvest Derived
    @@ -70,14 +70,17 @@ releaseServerSockets(void)
     {
         int i;
         /* Release the main ports as early as possible */
    +
         for (i = 0; i < NHttpSockets; i++) {
    -	if (HttpSockets[i] >= 0)
    -	    close(HttpSockets[i]);
    +        if (HttpSockets[i] >= 0)
    +            close(HttpSockets[i]);
         }
    +
         if (theInIcpConnection >= 0)
    -	close(theInIcpConnection);
    +        close(theInIcpConnection);
    +
         if (theOutIcpConnection >= 0 && theOutIcpConnection != theInIcpConnection)
    -	close(theOutIcpConnection);
    +        close(theOutIcpConnection);
     }
     
     static char *
    @@ -94,25 +97,40 @@ mail_warranty(void)
         FILE *fp = NULL;
         static char command[256];
     #if HAVE_MKSTEMP
    +
         char filename[] = "/tmp/squid-XXXXXX";
         int tfd = mkstemp(filename);
    +
         if (tfd < 0)
    -	return;
    +        return;
    +
         if ((fp = fdopen(tfd, "w")) == NULL)
    -	return;
    +        return;
    +
     #else
    +
         char *filename;
    +
         if ((filename = tempnam(NULL, appname)) == NULL)
    -	return;
    +        return;
    +
         if ((fp = fopen(filename, "w")) == NULL)
    -	return;
    +        return;
    +
     #endif
    +
         fprintf(fp, "From: %s\n", appname);
    +
         fprintf(fp, "To: %s\n", Config.adminEmail);
    +
         fprintf(fp, "Subject: %s\n", dead_msg());
    +
         fclose(fp);
    +
         snprintf(command, 256, "mail %s < %s", Config.adminEmail, filename);
    +
         system(command);		/* XXX should avoid system(3) */
    +
         unlink(filename);
     }
     
    @@ -120,77 +138,105 @@ void
     dumpMallocStats(void)
     {
     #if HAVE_MSTATS && HAVE_GNUMALLOC_H
    +
         struct mstats ms = mstats();
         fprintf(debug_log, "\ttotal space in arena:  %6d KB\n",
    -	(int) (ms.bytes_total >> 10));
    +            (int) (ms.bytes_total >> 10));
         fprintf(debug_log, "\tTotal free:            %6d KB %d%%\n",
    -	(int) (ms.bytes_free >> 10),
    -	percent(ms.bytes_free, ms.bytes_total));
    +            (int) (ms.bytes_free >> 10),
    +            percent(ms.bytes_free, ms.bytes_total));
     #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
    +
         struct mallinfo mp;
         int t;
    +
         if (!do_mallinfo)
    -	return;
    +        return;
    +
         mp = mallinfo();
    +
         fprintf(debug_log, "Memory usage for %s via mallinfo():\n", appname);
    +
         fprintf(debug_log, "\ttotal space in arena:  %6d KB\n",
    -	mp.arena >> 10);
    +            mp.arena >> 10);
    +
         fprintf(debug_log, "\tOrdinary blocks:       %6d KB %6d blks\n",
    -	mp.uordblks >> 10, mp.ordblks);
    +            mp.uordblks >> 10, mp.ordblks);
    +
         fprintf(debug_log, "\tSmall blocks:          %6d KB %6d blks\n",
    -	mp.usmblks >> 10, mp.smblks);
    +            mp.usmblks >> 10, mp.smblks);
    +
         fprintf(debug_log, "\tHolding blocks:        %6d KB %6d blks\n",
    -	mp.hblkhd >> 10, mp.hblks);
    +            mp.hblkhd >> 10, mp.hblks);
    +
         fprintf(debug_log, "\tFree Small blocks:     %6d KB\n",
    -	mp.fsmblks >> 10);
    +            mp.fsmblks >> 10);
    +
         fprintf(debug_log, "\tFree Ordinary blocks:  %6d KB\n",
    -	mp.fordblks >> 10);
    +            mp.fordblks >> 10);
    +
         t = mp.uordblks + mp.usmblks + mp.hblkhd;
    +
         fprintf(debug_log, "\tTotal in use:          %6d KB %d%%\n",
    -	t >> 10, percent(t, mp.arena));
    +            t >> 10, percent(t, mp.arena));
    +
         t = mp.fsmblks + mp.fordblks;
    +
         fprintf(debug_log, "\tTotal free:            %6d KB %d%%\n",
    -	t >> 10, percent(t, mp.arena));
    +            t >> 10, percent(t, mp.arena));
    +
     #if HAVE_STRUCT_MALLINFO_MXFAST
    +
         fprintf(debug_log, "\tmax size of small blocks:\t%d\n",
    -	mp.mxfast);
    +            mp.mxfast);
    +
         fprintf(debug_log, "\tnumber of small blocks in a holding block:\t%d\n",
    -	mp.nlblks);
    +            mp.nlblks);
    +
         fprintf(debug_log, "\tsmall block rounding factor:\t%d\n",
    -	mp.grain);
    +            mp.grain);
    +
         fprintf(debug_log, "\tspace (including overhead) allocated in ord. blks:\t%d\n",
    -	mp.uordbytes);
    +            mp.uordbytes);
    +
         fprintf(debug_log, "\tnumber of ordinary blocks allocated:\t%d\n",
    -	mp.allocated);
    +            mp.allocated);
    +
         fprintf(debug_log, "\tbytes used in maintaining the free tree:\t%d\n",
    -	mp.treeoverhead);
    +            mp.treeoverhead);
    +
     #endif /* HAVE_STRUCT_MALLINFO_MXFAST */
     #endif /* HAVE_MALLINFO */
     }
     
     void
    +
     squid_getrusage(struct rusage *r)
     {
    +
         memset(r, '\0', sizeof(struct rusage));
     #if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
     #ifdef _SQUID_SOLARIS_
         /* Solaris 2.5 has getrusage() permission bug -- Arjan de Vet */
         enter_suid();
     #endif
    +
         getrusage(RUSAGE_SELF, r);
     #ifdef _SQUID_SOLARIS_
    +
         leave_suid();
     #endif
     #endif
     }
     
     double
    +
     rusage_cputime(struct rusage *r)
     {
         return (double) r->ru_stime.tv_sec +
    -	(double) r->ru_utime.tv_sec +
    -	(double) r->ru_stime.tv_usec / 1000000.0 +
    -	(double) r->ru_utime.tv_usec / 1000000.0;
    +           (double) r->ru_utime.tv_sec +
    +           (double) r->ru_stime.tv_usec / 1000000.0 +
    +           (double) r->ru_utime.tv_usec / 1000000.0;
     }
     
     /* Hack for some HP-UX preprocessors */
    @@ -199,31 +245,40 @@ rusage_cputime(struct rusage *r)
     #endif
     
     int
    +
     rusage_maxrss(struct rusage *r)
     {
     #if defined(_SQUID_SGI_) && _ABIAPI
         return r->ru_pad[0];
     #elif defined(_SQUID_SGI_)
    +
         return r->ru_maxrss;
     #elif defined(_SQUID_OSF_)
    +
         return r->ru_maxrss;
     #elif defined(BSD4_4)
    +
         return r->ru_maxrss;
     #elif defined(HAVE_GETPAGESIZE) && HAVE_GETPAGESIZE != 0
    +
         return (r->ru_maxrss * getpagesize()) >> 10;
     #elif defined(PAGESIZE)
    +
         return (r->ru_maxrss * PAGESIZE) >> 10;
     #else
    +
         return r->ru_maxrss;
     #endif
     }
     
     int
    +
     rusage_pagefaults(struct rusage *r)
     {
     #if defined(_SQUID_SGI_) && _ABIAPI
         return r->ru_pad[5];
     #else
    +
         return r->ru_majflt;
     #endif
     }
    @@ -232,16 +287,17 @@ rusage_pagefaults(struct rusage *r)
     void
     PrintRusage(void)
     {
    +
         struct rusage rusage;
         squid_getrusage(&rusage);
         fprintf(debug_log, "CPU Usage: %.3f seconds = %.3f user + %.3f sys\n",
    -	rusage_cputime(&rusage),
    -	rusage.ru_utime.tv_sec + ((double) rusage.ru_utime.tv_usec / 1000000.0),
    -	rusage.ru_stime.tv_sec + ((double) rusage.ru_stime.tv_usec / 1000000.0));
    +            rusage_cputime(&rusage),
    +            rusage.ru_utime.tv_sec + ((double) rusage.ru_utime.tv_usec / 1000000.0),
    +            rusage.ru_stime.tv_sec + ((double) rusage.ru_stime.tv_usec / 1000000.0));
         fprintf(debug_log, "Maximum Resident Size: %d KB\n",
    -	rusage_maxrss(&rusage));
    +            rusage_maxrss(&rusage));
         fprintf(debug_log, "Page faults with physical i/o: %d\n",
    -	rusage_pagefaults(&rusage));
    +            rusage_pagefaults(&rusage));
     }
     
     
    @@ -249,56 +305,69 @@ void
     death(int sig)
     {
         if (sig == SIGSEGV)
    -	fprintf(debug_log, "FATAL: Received Segment Violation...dying.\n");
    +        fprintf(debug_log, "FATAL: Received Segment Violation...dying.\n");
         else if (sig == SIGBUS)
    -	fprintf(debug_log, "FATAL: Received Bus Error...dying.\n");
    +        fprintf(debug_log, "FATAL: Received Bus Error...dying.\n");
         else
    -	fprintf(debug_log, "FATAL: Received signal %d...dying.\n", sig);
    +        fprintf(debug_log, "FATAL: Received signal %d...dying.\n", sig);
     
     #ifdef PRINT_STACK_TRACE
     #ifdef _SQUID_HPUX_
         {
    -	extern void U_STACK_TRACE(void);	/* link with -lcl */
    -	fflush(debug_log);
    -	dup2(fileno(debug_log), 2);
    -	U_STACK_TRACE();
    +        extern void U_STACK_TRACE(void);	/* link with -lcl */
    +        fflush(debug_log);
    +        dup2(fileno(debug_log), 2);
    +        U_STACK_TRACE();
         }
    +
     #endif /* _SQUID_HPUX_ */
     #ifdef _SQUID_SOLARIS_
         {				/* get ftp://opcom.sun.ca/pub/tars/opcom_stack.tar.gz and */
    -	extern void opcom_stack_trace(void);	/* link with -lopcom_stack */
    -	fflush(debug_log);
    -	dup2(fileno(debug_log), fileno(stdout));
    -	opcom_stack_trace();
    -	fflush(stdout);
    +        extern void opcom_stack_trace(void);	/* link with -lopcom_stack */
    +        fflush(debug_log);
    +        dup2(fileno(debug_log), fileno(stdout));
    +        opcom_stack_trace();
    +        fflush(stdout);
         }
    +
     #endif /* _SQUID_SOLARIS_ */
     #if HAVE_BACKTRACE_SYMBOLS_FD
         {
    -	static void *(callarray[8192]);
    -	int n;
    -	n = backtrace(callarray, 8192);
    -	backtrace_symbols_fd(callarray, n, fileno(debug_log));
    +        static void *(callarray[8192]);
    +        int n;
    +        n = backtrace(callarray, 8192);
    +        backtrace_symbols_fd(callarray, n, fileno(debug_log));
         }
    +
     #endif
     #endif /* PRINT_STACK_TRACE */
     
     #if SA_RESETHAND == 0
         signal(SIGSEGV, SIG_DFL);
    +
         signal(SIGBUS, SIG_DFL);
    +
         signal(sig, SIG_DFL);
    +
     #endif
    +
         releaseServerSockets();
    +
         storeDirWriteCleanLogs(0);
    +
         PrintRusage();
    +
         dumpMallocStats();
    +
         if (squid_curtime - SQUID_RELEASE_TIME < 864000) {
    -	/* skip if more than 10 days old */
    -	if (Config.adminEmail)
    -	    mail_warranty();
    -	else
    -	    puts(dead_msg());
    +        /* skip if more than 10 days old */
    +
    +        if (Config.adminEmail)
    +            mail_warranty();
    +        else
    +            puts(dead_msg());
         }
    +
         abort();
     }
     
    @@ -308,23 +377,30 @@ sigusr2_handle(int sig)
     {
         static int state = 0;
         /* no debug() here; bad things happen if the signal is delivered during _db_print() */
    +
         if (state == 0) {
     #ifndef MEM_GEN_TRACE
    -	_db_init(Config.Log.log, "ALL,10");
    +        _db_init(Config.Log.log, "ALL,10");
     #else
    -	log_trace_done();
    +
    +        log_trace_done();
     #endif
    -	state = 1;
    +
    +        state = 1;
         } else {
     #ifndef MEM_GEN_TRACE
    -	_db_init(Config.Log.log, Config.debugOptions);
    +        _db_init(Config.Log.log, Config.debugOptions);
     #else
    -	log_trace_init("/tmp/squid.alloc");
    +
    +        log_trace_init("/tmp/squid.alloc");
     #endif
    -	state = 0;
    +
    +        state = 0;
         }
    +
     #if !HAVE_SIGACTION
         signal(sig, sigusr2_handle);	/* reinstall */
    +
     #endif
     }
     
    @@ -334,13 +410,19 @@ fatal_common(const char *message)
     #if HAVE_SYSLOG
         syslog(LOG_ALERT, "%s", message);
     #endif
    +
         fprintf(debug_log, "FATAL: %s\n", message);
    +
         if (opt_debug_stderr > 0 && debug_log != stderr)
    -	fprintf(stderr, "FATAL: %s\n", message);
    +        fprintf(stderr, "FATAL: %s\n", message);
    +
         fprintf(debug_log, "Squid Cache (Version %s): Terminated abnormally.\n",
    -	version_string);
    +            version_string);
    +
         fflush(debug_log);
    +
         PrintRusage();
    +
         dumpMallocStats();
     }
     
    @@ -352,13 +434,16 @@ fatal(const char *message)
         /* check for store_dirs_rebuilding because fatal() is often
          * used in early initialization phases, long before we ever
          * get to the store log. */
    +
         if (0 == store_dirs_rebuilding)
    -	storeDirWriteCleanLogs(0);
    +        storeDirWriteCleanLogs(0);
    +
         fatal_common(message);
    +
         if (shutting_down)
    -	exit(0);
    +        exit(0);
         else
    -	abort();
    +        abort();
     }
     
     /* printf-style interface for fatal */
    @@ -371,13 +456,14 @@ fatalf(const char *fmt,...)
     #else
     void
     fatalf(va_alist)
    -     va_dcl
    +va_dcl
     {
         va_list args;
         const char *fmt = NULL;
         va_start(args);
         fmt = va_arg(args, char *);
     #endif
    +
         fatalvf(fmt, args);
         va_end(args);
     }
    @@ -385,8 +471,7 @@ fatalf(va_alist)
     
     /* used by fatalf */
     static void
    -fatalvf(const char *fmt, va_list args)
    -{
    +fatalvf(const char *fmt, va_list args) {
         static char fatal_str[BUFSIZ];
         vsnprintf(fatal_str, sizeof(fatal_str), fmt, args);
         fatal(fatal_str);
    @@ -394,47 +479,59 @@ fatalvf(const char *fmt, va_list args)
     
     /* fatal with dumping core */
     void
    -fatal_dump(const char *message)
    -{
    +fatal_dump(const char *message) {
         failure_notify = NULL;
         releaseServerSockets();
    +
         if (message)
    -	fatal_common(message);
    +        fatal_common(message);
    +
         if (opt_catch_signals)
    -	storeDirWriteCleanLogs(0);
    +        storeDirWriteCleanLogs(0);
    +
         abort();
     }
     
     void
    -debug_trap(const char *message)
    -{
    +debug_trap(const char *message) {
         if (!opt_catch_signals)
    -	fatal_dump(message);
    +        fatal_dump(message);
    +
         _db_print("WARNING: %s\n", message);
     }
     
     void
    -sig_child(int sig)
    -{
    +sig_child(int sig) {
     #ifdef _SQUID_NEXT_
         union wait status;
     #else
    +
         int status;
     #endif
    +
         pid_t pid;
     
         do {
     #ifdef _SQUID_NEXT_
    -	pid = wait3(&status, WNOHANG, NULL);
    +        pid = wait3(&status, WNOHANG, NULL);
     #else
    -	pid = waitpid(-1, &status, WNOHANG);
    +
    +        pid = waitpid(-1, &status, WNOHANG);
     #endif
    -	/* no debug() here; bad things happen if the signal is delivered during _db_print() */
    +        /* no debug() here; bad things happen if the signal is delivered during _db_print() */
     #if HAVE_SIGACTION
    +
         } while (pid > 0);
    +
     #else
    -    } while (pid > 0 || (pid < 0 && errno == EINTR));
    +
    +    }
    +
    +    while (pid > 0 || (pid < 0 && errno == EINTR))
    +
    +        ;
         signal(sig, sig_child);
    +
     #endif
     }
     
    @@ -443,59 +540,75 @@ getMyHostname(void)
     {
         LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1);
         static int present = 0;
    +
         const struct hostent *h = NULL;
    +
         struct in_addr sa;
    +
         if (Config.visibleHostname != NULL)
    -	return Config.visibleHostname;
    +        return Config.visibleHostname;
    +
         if (present)
    -	return host;
    +        return host;
    +
         host[0] = '\0';
    +
         memcpy(&sa, &any_addr, sizeof(sa));
    +
         if (Config.Sockaddr.http && sa.s_addr == any_addr.s_addr)
    -	memcpy(&sa, &Config.Sockaddr.http->s.sin_addr, sizeof(sa));
    +        memcpy(&sa, &Config.Sockaddr.http->s.sin_addr, sizeof(sa));
    +
     #if USE_SSL
    +
         if (Config.Sockaddr.https && sa.s_addr == any_addr.s_addr)
    -	memcpy(&sa, &Config.Sockaddr.https->http.s.sin_addr, sizeof(sa));
    +        memcpy(&sa, &Config.Sockaddr.https->http.s.sin_addr, sizeof(sa));
    +
     #endif
         /*
          * If the first http_port address has a specific address, try a
          * reverse DNS lookup on it.
          */
         if (sa.s_addr != any_addr.s_addr) {
    -	h = gethostbyaddr((char *) &sa,
    -	    sizeof(sa), AF_INET);
    -	if (h != NULL) {
    -	    /* DNS lookup successful */
    -	    /* use the official name from DNS lookup */
    -	    xstrncpy(host, h->h_name, SQUIDHOSTNAMELEN);
    -	    debug(50, 4) ("getMyHostname: resolved %s to '%s'\n",
    -		inet_ntoa(sa),
    -		host);
    -	    present = 1;
    -	    if (strchr(host, '.'))
    -		return host;
    -
    -	}
    -	debug(50, 1) ("WARNING: failed to resolve %s to a fully qualified hostname\n",
    -	    inet_ntoa(sa));
    +        h = gethostbyaddr((char *) &sa,
    +                          sizeof(sa), AF_INET);
    +
    +        if (h != NULL) {
    +            /* DNS lookup successful */
    +            /* use the official name from DNS lookup */
    +            xstrncpy(host, h->h_name, SQUIDHOSTNAMELEN);
    +            debug(50, 4) ("getMyHostname: resolved %s to '%s'\n",
    +                          inet_ntoa(sa),
    +                          host);
    +            present = 1;
    +
    +            if (strchr(host, '.'))
    +                return host;
    +
    +        }
    +
    +        debug(50, 1) ("WARNING: failed to resolve %s to a fully qualified hostname\n",
    +                      inet_ntoa(sa));
         }
    +
         /*
          * Get the host name and store it in host to return
          */
         if (gethostname(host, SQUIDHOSTNAMELEN) < 0) {
    -	debug(50, 1) ("WARNING: gethostname failed: %s\n", xstrerror());
    +        debug(50, 1) ("WARNING: gethostname failed: %s\n", xstrerror());
         } else if ((h = gethostbyname(host)) == NULL) {
    -	debug(50, 1) ("WARNING: gethostbyname failed for %s\n", host);
    +        debug(50, 1) ("WARNING: gethostbyname failed for %s\n", host);
         } else {
    -	debug(50, 6) ("getMyHostname: '%s' resolved into '%s'\n",
    -	    host, h->h_name);
    -	/* DNS lookup successful */
    -	/* use the official name from DNS lookup */
    -	xstrncpy(host, h->h_name, SQUIDHOSTNAMELEN);
    -	present = 1;
    -	if (strchr(host, '.'))
    -	    return host;
    +        debug(50, 6) ("getMyHostname: '%s' resolved into '%s'\n",
    +                      host, h->h_name);
    +        /* DNS lookup successful */
    +        /* use the official name from DNS lookup */
    +        xstrncpy(host, h->h_name, SQUIDHOSTNAMELEN);
    +        present = 1;
    +
    +        if (strchr(host, '.'))
    +            return host;
         }
    +
         fatal("Could not determine fully qualified hostname.  Please set 'visible_hostname'\n");
         return NULL;		/* keep compiler happy */
     }
    @@ -510,8 +623,9 @@ void
     safeunlink(const char *s, int quiet)
     {
         statCounter.syscalls.disk.unlinks++;
    +
         if (unlink(s) < 0 && !quiet)
    -	debug(50, 1) ("safeunlink: Couldn't delete %s: %s\n", s, xstrerror());
    +        debug(50, 1) ("safeunlink: Couldn't delete %s: %s\n", s, xstrerror());
     }
     
     /* leave a privilegied section. (Give up any privilegies)
    @@ -523,27 +637,41 @@ void
     leave_suid(void)
     {
         debug(21, 3) ("leave_suid: PID %d called\n", (int) getpid());
    +
         if (geteuid() != 0)
    -	return;
    +        return;
    +
         /* Started as a root, check suid option */
         if (Config.effectiveUser == NULL)
    -	return;
    +        return;
    +
     #if HAVE_SETGROUPS
    +
         setgroups(1, &Config2.effectiveGroupID);
    +
     #endif
    +
         if (setgid(Config2.effectiveGroupID) < 0)
    -	debug(50, 0) ("ALERT: setgid: %s\n", xstrerror());
    +        debug(50, 0) ("ALERT: setgid: %s\n", xstrerror());
    +
         debug(21, 3) ("leave_suid: PID %d giving up root, becoming '%s'\n",
    -	(int) getpid(), Config.effectiveUser);
    +                  (int) getpid(), Config.effectiveUser);
    +
     #if HAVE_SETRESUID
    +
         if (setresuid(Config2.effectiveUserID, Config2.effectiveUserID, 0) < 0)
    -	debug(50, 0) ("ALERT: setresuid: %s\n", xstrerror());
    +        debug(50, 0) ("ALERT: setresuid: %s\n", xstrerror());
    +
     #elif HAVE_SETEUID
    +
         if (seteuid(Config2.effectiveUserID) < 0)
    -	debug(50, 0) ("ALERT: seteuid: %s\n", xstrerror());
    +        debug(50, 0) ("ALERT: seteuid: %s\n", xstrerror());
    +
     #else
    +
         if (setuid(Config2.effectiveUserID) < 0)
    -	debug(50, 0) ("ALERT: setuid: %s\n", xstrerror());
    +        debug(50, 0) ("ALERT: setuid: %s\n", xstrerror());
    +
     #endif
     }
     
    @@ -553,8 +681,10 @@ enter_suid(void)
     {
         debug(21, 3) ("enter_suid: PID %d taking root priveleges\n", (int) getpid());
     #if HAVE_SETRESUID
    +
         setresuid((uid_t)-1, 0, (uid_t)-1);
     #else
    +
         setuid(0);
     #endif
     }
    @@ -570,12 +700,17 @@ no_suid(void)
         uid = geteuid();
         debug(21, 3) ("leave_suid: PID %d giving up root priveleges forever\n", (int) getpid());
     #if HAVE_SETRESUID
    +
         if (setresuid(uid, uid, uid) < 0)
    -	debug(50, 1) ("no_suid: setresuid: %s\n", xstrerror());
    +        debug(50, 1) ("no_suid: setresuid: %s\n", xstrerror());
    +
     #else
    +
         setuid(0);
    +
         if (setuid(uid) < 0)
    -	debug(50, 1) ("no_suid: setuid: %s\n", xstrerror());
    +        debug(50, 1) ("no_suid: setuid: %s\n", xstrerror());
    +
     #endif
     }
     
    @@ -586,20 +721,29 @@ writePidFile(void)
         const char *f = NULL;
         mode_t old_umask;
         char buf[32];
    +
         if ((f = Config.pidFilename) == NULL)
    -	return;
    +        return;
    +
         if (!strcmp(Config.pidFilename, "none"))
    -	return;
    +        return;
    +
         enter_suid();
    +
         old_umask = umask(022);
    +
         fd = file_open(f, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT);
    +
         umask(old_umask);
    +
         leave_suid();
    +
         if (fd < 0) {
    -	debug(50, 0) ("%s: %s\n", f, xstrerror());
    -	debug_trap("Could not write pid file");
    -	return;
    +        debug(50, 0) ("%s: %s\n", f, xstrerror());
    +        debug_trap("Could not write pid file");
    +        return;
         }
    +
         snprintf(buf, 32, "%d\n", (int) getpid());
         FD_WRITE_METHOD(fd, buf, strlen(buf));
         file_close(fd);
    @@ -615,22 +759,27 @@ readPidFile(void)
         int i;
     
         if (f == NULL || !strcmp(Config.pidFilename, "none")) {
    -	fprintf(stderr, "%s: ERROR: No pid file name defined\n", appname);
    -	exit(1);
    +        fprintf(stderr, "%s: ERROR: No pid file name defined\n", appname);
    +        exit(1);
         }
    +
         pid_fp = fopen(f, "r");
    +
         if (pid_fp != NULL) {
    -	pid = 0;
    -	if (fscanf(pid_fp, "%d", &i) == 1)
    -	    pid = (pid_t) i;
    -	fclose(pid_fp);
    +        pid = 0;
    +
    +        if (fscanf(pid_fp, "%d", &i) == 1)
    +            pid = (pid_t) i;
    +
    +        fclose(pid_fp);
         } else {
    -	if (errno != ENOENT) {
    -	    fprintf(stderr, "%s: ERROR: Could not read pid file\n", appname);
    -	    fprintf(stderr, "\t%s: %s\n", f, xstrerror());
    -	    exit(1);
    -	}
    +        if (errno != ENOENT) {
    +            fprintf(stderr, "%s: ERROR: Could not read pid file\n", appname);
    +            fprintf(stderr, "\t%s: %s\n", f, xstrerror());
    +            exit(1);
    +        }
         }
    +
         return pid;
     }
     
    @@ -641,61 +790,75 @@ setMaxFD(void)
     #if HAVE_SETRLIMIT
         /* try to use as many file descriptors as possible */
         /* System V uses RLIMIT_NOFILE and BSD uses RLIMIT_OFILE */
    +
         struct rlimit rl;
     #if defined(RLIMIT_NOFILE)
    +
         if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
    -	debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
    +        debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
         } else {
    -	rl.rlim_cur = Squid_MaxFD;
    -	if (rl.rlim_cur > rl.rlim_max)
    -	    Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
    -	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
    -	    snprintf(tmp_error_buf, ERROR_BUF_SZ,
    -		"setrlimit: RLIMIT_NOFILE: %s", xstrerror());
    -	    fatal_dump(tmp_error_buf);
    -	}
    +        rl.rlim_cur = Squid_MaxFD;
    +
    +        if (rl.rlim_cur > rl.rlim_max)
    +            Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
    +
    +        if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
    +            snprintf(tmp_error_buf, ERROR_BUF_SZ,
    +                     "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
    +            fatal_dump(tmp_error_buf);
    +        }
         }
    +
     #elif defined(RLIMIT_OFILE)
         if (getrlimit(RLIMIT_OFILE, &rl) < 0) {
    -	debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
    +        debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
         } else {
    -	rl.rlim_cur = Squid_MaxFD;
    -	if (rl.rlim_cur > rl.rlim_max)
    -	    Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
    -	if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
    -	    snprintf(tmp_error_buf, ERROR_BUF_SZ,
    -		"setrlimit: RLIMIT_OFILE: %s", xstrerror());
    -	    fatal_dump(tmp_error_buf);
    -	}
    +        rl.rlim_cur = Squid_MaxFD;
    +
    +        if (rl.rlim_cur > rl.rlim_max)
    +            Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
    +
    +        if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
    +            snprintf(tmp_error_buf, ERROR_BUF_SZ,
    +                     "setrlimit: RLIMIT_OFILE: %s", xstrerror());
    +            fatal_dump(tmp_error_buf);
    +        }
         }
    +
     #endif
     #else /* HAVE_SETRLIMIT */
         debug(21, 1) ("setMaxFD: Cannot increase: setrlimit() not supported on this system\n");
    +
     #endif /* HAVE_SETRLIMIT */
     
     #if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
    +
         if (getrlimit(RLIMIT_DATA, &rl) < 0) {
    -	debug(50, 0) ("getrlimit: RLIMIT_DATA: %s\n", xstrerror());
    +        debug(50, 0) ("getrlimit: RLIMIT_DATA: %s\n", xstrerror());
         } else if (rl.rlim_max > rl.rlim_cur) {
    -	rl.rlim_cur = rl.rlim_max;	/* set it to the max */
    -	if (setrlimit(RLIMIT_DATA, &rl) < 0) {
    -	    snprintf(tmp_error_buf, ERROR_BUF_SZ,
    -		"setrlimit: RLIMIT_DATA: %s", xstrerror());
    -	    fatal_dump(tmp_error_buf);
    -	}
    +        rl.rlim_cur = rl.rlim_max;	/* set it to the max */
    +
    +        if (setrlimit(RLIMIT_DATA, &rl) < 0) {
    +            snprintf(tmp_error_buf, ERROR_BUF_SZ,
    +                     "setrlimit: RLIMIT_DATA: %s", xstrerror());
    +            fatal_dump(tmp_error_buf);
    +        }
         }
    +
     #endif /* RLIMIT_DATA */
     #if HAVE_SETRLIMIT && defined(RLIMIT_VMEM)
         if (getrlimit(RLIMIT_VMEM, &rl) < 0) {
    -	debug(50, 0) ("getrlimit: RLIMIT_VMEM: %s\n", xstrerror());
    +        debug(50, 0) ("getrlimit: RLIMIT_VMEM: %s\n", xstrerror());
         } else if (rl.rlim_max > rl.rlim_cur) {
    -	rl.rlim_cur = rl.rlim_max;	/* set it to the max */
    -	if (setrlimit(RLIMIT_VMEM, &rl) < 0) {
    -	    snprintf(tmp_error_buf, ERROR_BUF_SZ,
    -		"setrlimit: RLIMIT_VMEM: %s", xstrerror());
    -	    fatal_dump(tmp_error_buf);
    -	}
    +        rl.rlim_cur = rl.rlim_max;	/* set it to the max */
    +
    +        if (setrlimit(RLIMIT_VMEM, &rl) < 0) {
    +            snprintf(tmp_error_buf, ERROR_BUF_SZ,
    +                     "setrlimit: RLIMIT_VMEM: %s", xstrerror());
    +            fatal_dump(tmp_error_buf);
    +        }
         }
    +
     #endif /* RLIMIT_VMEM */
     }
     
    @@ -705,10 +868,12 @@ getCurrentTime(void)
     #if GETTIMEOFDAY_NO_TZP
         gettimeofday(¤t_time);
     #else
    +
         gettimeofday(¤t_time, NULL);
     #endif
    +
         current_dtime = (double) current_time.tv_sec +
    -	(double) current_time.tv_usec / 1000000.0;
    +                    (double) current_time.tv_usec / 1000000.0;
         return squid_curtime = current_time.tv_sec;
     }
     
    @@ -728,20 +893,27 @@ void
     squid_signal(int sig, SIGHDLR * func, int flags)
     {
     #if HAVE_SIGACTION
    +
         struct sigaction sa;
         sa.sa_handler = func;
         sa.sa_flags = flags;
         sigemptyset(&sa.sa_mask);
    +
         if (sigaction(sig, &sa, NULL) < 0)
    -	debug(50, 0) ("sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
    +        debug(50, 0) ("sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
    +
     #else
    +
         signal(sig, func);
    +
     #endif
     }
     
     struct in_addr
    -inaddrFromHostent(const struct hostent *hp)
    +
    +            inaddrFromHostent(const struct hostent *hp)
     {
    +
         struct in_addr s;
         xmemcpy(&s.s_addr, hp->h_addr, sizeof(s.s_addr));
         return s;
    @@ -751,7 +923,8 @@ double
     doubleAverage(double cur, double newD, int N, int max)
     {
         if (N > max)
    -	N = max;
    +        N = max;
    +
         return (cur * (N - 1.0) + newD) / N;
     }
     
    @@ -759,7 +932,8 @@ int
     intAverage(int cur, int newI, int n, int max)
     {
         if (n > max)
    -	n = max;
    +        n = max;
    +
         return (cur * (n - 1) + newI) / n;
     }
     
    @@ -767,7 +941,7 @@ void
     logsFlush(void)
     {
         if (debug_log)
    -	fflush(debug_log);
    +        fflush(debug_log);
     }
     
     const char *
    @@ -780,7 +954,8 @@ dlink_node *
     dlinkNodeNew()
     {
         if (dlink_node_pool == NULL)
    -	dlink_node_pool = memPoolCreate("Dlink list nodes", sizeof(dlink_node));
    +        dlink_node_pool = memPoolCreate("Dlink list nodes", sizeof(dlink_node));
    +
         /* where should we call memPoolDestroy(dlink_node_pool); */
         return (dlink_node *)memPoolAlloc(dlink_node_pool);
     }
    @@ -790,7 +965,8 @@ void
     dlinkNodeDelete(dlink_node * m)
     {
         if (m == NULL)
    -	return;
    +        return;
    +
         memPoolFree(dlink_node_pool, m);
     }
     
    @@ -800,11 +976,14 @@ dlinkAdd(void *data, dlink_node * m, dlink_list * list)
         m->data = data;
         m->prev = NULL;
         m->next = list->head;
    +
         if (list->head)
    -	list->head->prev = m;
    +        list->head->prev = m;
    +
         list->head = m;
    +
         if (list->tail == NULL)
    -	list->tail = m;
    +        list->tail = m;
     }
     
     void
    @@ -813,12 +992,14 @@ dlinkAddAfter(void *data, dlink_node * m, dlink_node * n, dlink_list * list)
         m->data = data;
         m->prev = n;
         m->next = n->next;
    +
         if (n->next)
    -	n->next->prev = m;
    +        n->next->prev = m;
         else {
    -	assert(list->tail == n);
    -	list->tail = m;
    +        assert(list->tail == n);
    +        list->tail = m;
         }
    +
         n->next = m;
     }
     
    @@ -828,24 +1009,31 @@ dlinkAddTail(void *data, dlink_node * m, dlink_list * list)
         m->data = data;
         m->next = NULL;
         m->prev = list->tail;
    +
         if (list->tail)
    -	list->tail->next = m;
    +        list->tail->next = m;
    +
         list->tail = m;
    +
         if (list->head == NULL)
    -	list->head = m;
    +        list->head = m;
     }
     
     void
     dlinkDelete(dlink_node * m, dlink_list * list)
     {
         if (m->next)
    -	m->next->prev = m->prev;
    +        m->next->prev = m->prev;
    +
         if (m->prev)
    -	m->prev->next = m->next;
    +        m->prev->next = m->next;
    +
         if (m == list->head)
    -	list->head = m->next;
    +        list->head = m->next;
    +
         if (m == list->tail)
    -	list->tail = m->prev;
    +        list->tail = m->prev;
    +
         m->next = m->prev = NULL;
     }
     
    @@ -883,8 +1071,10 @@ linklistPush(link_list ** L, void *p)
         link_list *l = (link_list *)memAllocate(MEM_LINK_LIST);
         l->next = NULL;
         l->ptr = p;
    +
         while (*L)
    -	L = &(*L)->next;
    +        L = &(*L)->next;
    +
         *L = l;
     }
     
    @@ -893,12 +1083,18 @@ linklistShift(link_list ** L)
     {
         void *p;
         link_list *l;
    +
         if (NULL == *L)
    -	return NULL;
    +        return NULL;
    +
         l = *L;
    +
         p = l->ptr;
    +
         *L = (*L)->next;
    +
         memFree(l, MEM_LINK_LIST);
    +
         return p;
     }
     
    @@ -912,12 +1108,18 @@ xrename(const char *from, const char *to)
     {
         debug(21, 2) ("xrename: renaming %s to %s\n", from, to);
     #ifdef _SQUID_MSWIN_
    -    remove(to);
    +
    +    remove
    +        (to);
    +
     #endif
    +
         if (0 == rename(from, to))
    -	return 0;
    +        return 0;
    +
         debug(21, errno == ENOENT ? 2 : 1) ("xrename: Cannot rename %s to %s: %s\n",
    -	from, to, xstrerror());
    +                                        from, to, xstrerror());
    +
         return -1;
     }
     
    @@ -925,12 +1127,15 @@ int
     stringHasCntl(const char *s)
     {
         unsigned char c;
    +
         while ((c = (unsigned char) *s++) != '\0') {
    -	if (c <= 0x1f)
    -	    return 1;
    -	if (c >= 0x7f && c <= 0x9f)
    -	    return 1;
    +        if (c <= 0x1f)
    +            return 1;
    +
    +        if (c >= 0x7f && c <= 0x9f)
    +            return 1;
         }
    +
         return 0;
     }
     
    @@ -944,58 +1149,83 @@ parseEtcHosts(void)
         char *lt = buf;
     
         if (NULL == Config.etcHostsPath)
    -	return;
    +        return;
    +
         if (0 == strcmp(Config.etcHostsPath, "none"))
    -	return;
    +        return;
    +
         fp = fopen(Config.etcHostsPath, "r");
    +
         if (fp == NULL) {
    -	debug(1, 1) ("parseEtcHosts: %s: %s\n",
    -	    Config.etcHostsPath, xstrerror());
    -	return;
    +        debug(1, 1) ("parseEtcHosts: %s: %s\n",
    +                     Config.etcHostsPath, xstrerror());
    +        return;
         }
    +
     #if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_)
         setmode(fileno(fp), O_TEXT);
    +
     #endif
    +
         while (fgets(buf, 1024, fp)) {	/* for each line */
    -	wordlist *hosts = NULL;
    -	char *addr;
    -	if (buf[0] == '#')	/* MS-windows likes to add comments */
    -	    continue;
    -	lt = buf;
    -	addr = buf;
    -	debug(1, 5) ("etc_hosts: line is '%s'\n", buf);
    -	nt = strpbrk(lt, w_space);
    -	if (nt == NULL)		/* empty line */
    -	    continue;
    -	*nt = '\0';		/* null-terminate the address */
    -	debug(1, 5) ("etc_hosts: address is '%s'\n", addr);
    -	lt = nt + 1;
    -	while ((nt = strpbrk(lt, w_space))) {
    -	    char *host = NULL;
    -	    if (nt == lt) {	/* multiple spaces */
    -		debug(1, 5) ("etc_hosts: multiple spaces, skipping\n");
    -		lt = nt + 1;
    -		continue;
    -	    }
    -	    *nt = '\0';
    -	    debug(1, 5) ("etc_hosts: got hostname '%s'\n", lt);
    -	    if (Config.appendDomain && !strchr(lt, '.')) {
    -		/* I know it's ugly, but it's only at reconfig */
    -		strncpy(buf2, lt, 512);
    -		strncat(buf2, Config.appendDomain, 512 - strlen(lt));
    -		host = buf2;
    -	    } else {
    -		host = lt;
    -	    }
    -	    if (ipcacheAddEntryFromHosts(host, addr) != 0)
    -		goto skip;	/* invalid address, continuing is useless */
    -	    wordlistAdd(&hosts, host);
    -	    lt = nt + 1;
    -	}
    -	fqdncacheAddEntryFromHosts(addr, hosts);
    -      skip:
    -	wordlistDestroy(&hosts);
    +        wordlist *hosts = NULL;
    +        char *addr;
    +
    +        if (buf[0] == '#')	/* MS-windows likes to add comments */
    +            continue;
    +
    +        lt = buf;
    +
    +        addr = buf;
    +
    +        debug(1, 5) ("etc_hosts: line is '%s'\n", buf);
    +
    +        nt = strpbrk(lt, w_space);
    +
    +        if (nt == NULL)		/* empty line */
    +            continue;
    +
    +        *nt = '\0';		/* null-terminate the address */
    +
    +        debug(1, 5) ("etc_hosts: address is '%s'\n", addr);
    +
    +        lt = nt + 1;
    +
    +        while ((nt = strpbrk(lt, w_space))) {
    +            char *host = NULL;
    +
    +            if (nt == lt) {	/* multiple spaces */
    +                debug(1, 5) ("etc_hosts: multiple spaces, skipping\n");
    +                lt = nt + 1;
    +                continue;
    +            }
    +
    +            *nt = '\0';
    +            debug(1, 5) ("etc_hosts: got hostname '%s'\n", lt);
    +
    +            if (Config.appendDomain && !strchr(lt, '.')) {
    +                /* I know it's ugly, but it's only at reconfig */
    +                strncpy(buf2, lt, 512);
    +                strncat(buf2, Config.appendDomain, 512 - strlen(lt));
    +                host = buf2;
    +            } else {
    +                host = lt;
    +            }
    +
    +            if (ipcacheAddEntryFromHosts(host, addr) != 0)
    +                goto skip;	/* invalid address, continuing is useless */
    +
    +            wordlistAdd(&hosts, host);
    +
    +            lt = nt + 1;
    +        }
    +
    +        fqdncacheAddEntryFromHosts(addr, hosts);
    +
    +skip:
    +        wordlistDestroy(&hosts);
         }
    +
         fclose (fp);
     }
     
    @@ -1003,12 +1233,17 @@ int
     getMyPort(void)
     {
         if (Config.Sockaddr.http)
    -	return ntohs(Config.Sockaddr.http->s.sin_port);
    +        return ntohs(Config.Sockaddr.http->s.sin_port);
    +
     #if USE_SSL
    +
         if (Config.Sockaddr.https)
    -	return ntohs(Config.Sockaddr.https->http.s.sin_port);
    +        return ntohs(Config.Sockaddr.https->http.s.sin_port);
    +
     #endif
    +
         fatal("No port defined");
    +
         return 0;			/* NOT REACHED */
     }
     
    @@ -1024,39 +1259,55 @@ strwordtok(char *buf, char **t)
         unsigned char *d;
         unsigned char ch;
         int quoted = 0;
    +
         if (!p)
    -	p = (unsigned char *) *t;
    +        p = (unsigned char *) *t;
    +
         if (!p)
    -	goto error;
    +        goto error;
    +
         while (*p && isspace(*p))
    -	p++;
    +        p++;
    +
         if (!*p)
    -	goto error;
    +        goto error;
    +
         word = d = p;
    +
         while ((ch = *p)) {
    -	switch (ch) {
    -	case '\\':
    -	    p++;
    -	    *d++ = ch = *p;
    -	    if (ch)
    -		p++;
    -	    break;
    -	case '"':
    -	    quoted = !quoted;
    -	    p++;
    -	    break;
    -	default:
    -	    if (!quoted && isspace(*p)) {
    -		p++;
    -		goto done;
    -	    }
    -	    *d++ = *p++;
    -	    break;
    -	}
    +        switch (ch) {
    +
    +        case '\\':
    +            p++;
    +            *d++ = ch = *p;
    +
    +            if (ch)
    +                p++;
    +
    +            break;
    +
    +        case '"':
    +            quoted = !quoted;
    +
    +            p++;
    +
    +            break;
    +
    +        default:
    +            if (!quoted && isspace(*p)) {
    +                p++;
    +                goto done;
    +            }
    +
    +            *d++ = *p++;
    +            break;
    +        }
         }
    -  done:
    +
    +done:
         *d++ = '\0';
    -  error:
    +
    +error:
         *t = (char *) p;
         return (char *) word;
     }
    @@ -1068,20 +1319,24 @@ void
     strwordquote(MemBuf * mb, const char *str)
     {
         int quoted = 0;
    +
         if (strchr(str, ' ')) {
    -	quoted = 1;
    -	memBufAppend(mb, "\"", 1);
    +        quoted = 1;
    +        memBufAppend(mb, "\"", 1);
         }
    +
         while (*str) {
    -	int l = strcspn(str, "\"\\");
    -	memBufAppend(mb, str, l);
    -	str += l;
    -	while (*str == '"' || *str == '\\') {
    -	    memBufAppend(mb, "\\", 1);
    -	    memBufAppend(mb, str, 1);
    -	    str++;
    -	}
    +        int l = strcspn(str, "\"\\");
    +        memBufAppend(mb, str, l);
    +        str += l;
    +
    +        while (*str == '"' || *str == '\\') {
    +            memBufAppend(mb, "\\", 1);
    +            memBufAppend(mb, str, 1);
    +            str++;
    +        }
         }
    +
         if (quoted)
    -	memBufAppend(mb, "\"", 1);
    +        memBufAppend(mb, "\"", 1);
     }
    diff --git a/src/tunnel.cc b/src/tunnel.cc
    index e312e46b82..8cbbf1d0e9 100644
    --- a/src/tunnel.cc
    +++ b/src/tunnel.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: tunnel.cc,v 1.135 2003/02/12 06:11:05 robertc Exp $
    + * $Id: tunnel.cc,v 1.136 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 26    Secure Sockets Layer Proxy
      * AUTHOR: Duane Wessels
    @@ -43,23 +43,31 @@
     #include "DelayId.h"
     #endif
     
    -typedef struct {
    +typedef struct
    +{
         char *url;
         char *host;			/* either request->host or proxy host */
         u_short port;
         request_t *request;
         FwdServer *servers;
    -    struct {
    -	int fd;
    -	int len;
    -	char *buf;
    -    } client, server;
    +
    +    struct
    +    {
    +        int fd;
    +        int len;
    +        char *buf;
    +    }
    +
    +    client, server;
         size_t *size_ptr;		/* pointer to size in an ConnStateData for logging */
         int *status_ptr;		/* pointer to status for logging */
     #if DELAY_POOLS
    +
         DelayId delayId;
     #endif
    -} SslStateData;
    +}
    +
    +SslStateData;
     
     static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
     
    @@ -87,8 +95,9 @@ sslServerClosed(int fd, void *data)
         debug(26, 3) ("sslServerClosed: FD %d\n", fd);
         assert(fd == sslState->server.fd);
         sslState->server.fd = -1;
    +
         if (sslState->client.fd == -1)
    -	sslStateFree(sslState);
    +        sslStateFree(sslState);
     }
     
     static void
    @@ -98,8 +107,9 @@ sslClientClosed(int fd, void *data)
         debug(26, 3) ("sslClientClosed: FD %d\n", fd);
         assert(fd == sslState->client.fd);
         sslState->client.fd = -1;
    +
         if (sslState->server.fd == -1)
    -	sslStateFree(sslState);
    +        sslStateFree(sslState);
     }
     
     static void
    @@ -125,12 +135,16 @@ sslDeferServerRead(int fdnotused, void *data)
     {
         SslStateData *s = (SslStateData *)data;
         int i = s->delayId.bytesWanted(0, INT_MAX);
    +
         if (i == INT_MAX)
    -	return 0;
    +        return 0;
    +
         if (i == 0)
    -	return 1;
    +        return 1;
    +
         return -1;
     }
    +
     #endif
     
     
    @@ -143,35 +157,45 @@ sslReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, voi
         assert(fd == sslState->server.fd);
         errno = 0;
     #if DELAY_POOLS
    +
         len = sslState->delayId.bytesWanted(1, len);
     #endif
         /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
    +
         if (errcode == COMM_ERR_CLOSING) {
             return;
         }
    +
         debug(26, 3) ("sslReadServer: FD %d, read   %d bytes\n", fd, (int)len);
    +
         if (len > 0) {
     #if DELAY_POOLS
    -	sslState->delayId.bytesIn(len);
    +        sslState->delayId.bytesIn(len);
     #endif
    -	kb_incr(&statCounter.server.all.kbytes_in, len);
    -	kb_incr(&statCounter.server.other.kbytes_in, len);
    -	sslState->server.len += len;
    +
    +        kb_incr(&statCounter.server.all.kbytes_in, len);
    +        kb_incr(&statCounter.server.other.kbytes_in, len);
    +        sslState->server.len += len;
         }
    +
         cbdataInternalLock(sslState);	/* ??? should be locked by the caller... */
    +
         if (len < 0) {
    -	debug(50, ignoreErrno(errno) ? 3 : 1)
    -	    ("sslReadServer: FD %d: read failure: %s\n", fd, xstrerror());
    -	if (!ignoreErrno(errno))
    -	    comm_close(fd);
    +        debug(50, ignoreErrno(errno) ? 3 : 1)
    +        ("sslReadServer: FD %d: read failure: %s\n", fd, xstrerror());
    +
    +        if (!ignoreErrno(errno))
    +            comm_close(fd);
         } else if (len == 0) {
    -	comm_close(sslState->server.fd);
    -	/* Only close the remote end if we've finished queueing data to it */
    +        comm_close(sslState->server.fd);
    +        /* Only close the remote end if we've finished queueing data to it */
    +
             if (sslState->server.len == 0 && sslState->client.fd != -1) {
    -	    comm_close(sslState->client.fd);
    +            comm_close(sslState->client.fd);
             }
         } else if (cbdataReferenceValid(sslState))
    -	comm_write(sslState->client.fd, sslState->server.buf, len, sslWriteClientDone, sslState);
    +        comm_write(sslState->client.fd, sslState->server.buf, len, sslWriteClientDone, sslState);
    +
         cbdataInternalUnlock(sslState);	/* ??? */
     }
     
    @@ -183,38 +207,50 @@ sslReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, voi
         assert(fd == sslState->client.fd);
     
         /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
    +
         if (errcode == COMM_ERR_CLOSING) {
             return;
         }
     
         debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", fd, (int) len);
    +
         if (len > 0) {
    -	kb_incr(&statCounter.client_http.kbytes_in, len);
    -	sslState->client.len += len;
    +        kb_incr(&statCounter.client_http.kbytes_in, len);
    +        sslState->client.len += len;
         }
    +
         cbdataInternalLock(sslState);	/* ??? should be locked by the caller... */
    +
         if (len < 0) {
    -	int level = 1;
    +        int level = 1;
     #ifdef ECONNRESET
    -	if (xerrno == ECONNRESET)
    -	    level = 2;
    +
    +        if (xerrno == ECONNRESET)
    +            level = 2;
    +
     #endif
    -	if (ignoreErrno(xerrno))
    -	    level = 3;
    +
    +        if (ignoreErrno(xerrno))
    +            level = 3;
    +
             /* XXX xstrerror() should be changed to take errno as an arg! */
             errno = xerrno;
    -	debug(50, level) ("sslReadClient: FD %d: read failure: %s\n",
    -	    fd, xstrerror());
    -	if (!ignoreErrno(xerrno))
    -	    comm_close(fd);
    +
    +        debug(50, level) ("sslReadClient: FD %d: read failure: %s\n",
    +                          fd, xstrerror());
    +
    +        if (!ignoreErrno(xerrno))
    +            comm_close(fd);
         } else if (len == 0) {
             comm_close(sslState->client.fd);
    -	/* Only close the remote end if we've finished queueing data to it */
    +        /* Only close the remote end if we've finished queueing data to it */
    +
             if (sslState->client.len == 0 && sslState->server.fd != -1) {
    -	    comm_close(sslState->server.fd);
    +            comm_close(sslState->server.fd);
             }
         } else if (cbdataReferenceValid(sslState))
    -	comm_write(sslState->server.fd, sslState->client.buf, len, sslWriteServerDone, sslState);
    +        comm_write(sslState->server.fd, sslState->client.buf, len, sslWriteServerDone, sslState);
    +
         cbdataInternalUnlock(sslState);	/* ??? */
     }
     
    @@ -226,35 +262,43 @@ sslWriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, v
         assert(fd == sslState->server.fd);
         debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", fd, (int)len);
         /* Valid data */
    +
         if (len > 0) {
    -	kb_incr(&statCounter.server.all.kbytes_out, len);
    -	kb_incr(&statCounter.server.other.kbytes_out, len);
    -	assert(len == (size_t)sslState->client.len);
    -	sslState->client.len = 0;
    +        kb_incr(&statCounter.server.all.kbytes_out, len);
    +        kb_incr(&statCounter.server.other.kbytes_out, len);
    +        assert(len == (size_t)sslState->client.len);
    +        sslState->client.len = 0;
         }
    +
         /* EOF */
         if (len == 0) {
             comm_close(sslState->server.fd);
             return;
         }
    +
         /* If the other end has closed, so should we */
         if (sslState->client.fd == -1) {
    -	comm_close(sslState->server.fd);
    -	return;
    +        comm_close(sslState->server.fd);
    +        return;
         }
    +
         cbdataInternalLock(sslState);	/* ??? should be locked by the caller... */
         /* Error? */
    +
         if (len < 0) {
    -	debug(50, ignoreErrno(errno) ? 3 : 1)
    -	    ("sslWriteServer: FD %d: write failure: %s.\n", fd, xstrerror());
    -	if (!ignoreErrno(errno))
    -	    comm_close(fd);
    +        debug(50, ignoreErrno(errno) ? 3 : 1)
    +        ("sslWriteServer: FD %d: write failure: %s.\n", fd, xstrerror());
    +
    +        if (!ignoreErrno(errno))
    +            comm_close(fd);
         }
    +
         if (cbdataReferenceValid(sslState)) {
             assert(sslState->client.len == 0);
             comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF,
    -          sslReadClient, sslState);
    +                  sslReadClient, sslState);
         }
    +
         cbdataInternalUnlock(sslState);	/* ??? */
     }
     
    @@ -265,37 +309,46 @@ sslWriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, v
         SslStateData *sslState = (SslStateData *)data;
         assert(fd == sslState->client.fd);
         debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", fd, (int)len);
    +
         if (len > 0) {
    -	kb_incr(&statCounter.client_http.kbytes_out, len);
    -	assert(len == (size_t)sslState->server.len);
    -	sslState->server.len =0;
    -	/* increment total object size */
    -	if (sslState->size_ptr)
    -	    *sslState->size_ptr += len;
    +        kb_incr(&statCounter.client_http.kbytes_out, len);
    +        assert(len == (size_t)sslState->server.len);
    +        sslState->server.len =0;
    +        /* increment total object size */
    +
    +        if (sslState->size_ptr)
    +            *sslState->size_ptr += len;
         }
    +
         /* EOF */
         if (len == 0) {
             comm_close(sslState->client.fd);
             return;
         }
    +
         /* If the other end has closed, so should we */
         if (sslState->server.fd == -1) {
    -	comm_close(sslState->client.fd);
    -	return;
    +        comm_close(sslState->client.fd);
    +        return;
         }
    +
         cbdataInternalLock(sslState);	/* ??? should be locked by the caller... */
         /* Error? */
    +
         if (len < 0) {
    -	debug(50, ignoreErrno(errno) ? 3 : 1)
    -	    ("sslWriteClient: FD %d: write failure: %s.\n", fd, xstrerror());
    -	if (!ignoreErrno(errno))
    -	    comm_close(fd);
    +        debug(50, ignoreErrno(errno) ? 3 : 1)
    +        ("sslWriteClient: FD %d: write failure: %s.\n", fd, xstrerror());
    +
    +        if (!ignoreErrno(errno))
    +            comm_close(fd);
         }
    +
         if (cbdataReferenceValid(sslState)) {
             assert(sslState->server.len == 0);
             comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF,
    -            sslReadServer, sslState);
    +                  sslReadServer, sslState);
         }
    +
         cbdataInternalUnlock(sslState);	/* ??? */
     }
     
    @@ -306,28 +359,33 @@ sslTimeout(int fd, void *data)
         debug(26, 3) ("sslTimeout: FD %d\n", fd);
         /* Temporary lock to protect our own feets (comm_close -> sslClientClosed -> Free) */
         cbdataInternalLock(sslState);
    +
         if (sslState->client.fd > -1)
    -	comm_close(sslState->client.fd);
    +        comm_close(sslState->client.fd);
    +
         if (sslState->server.fd > -1)
    -	comm_close(sslState->server.fd);
    +        comm_close(sslState->server.fd);
    +
         cbdataInternalUnlock(sslState);
     }
     
     static void
     sslConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
     {
    -	SslStateData *sslState = (SslStateData *)data;
    -	if (flag != COMM_OK) {
    -		sslErrorComplete(fd, data, 0);
    -		return;
    -	}
    -        if (cbdataReferenceValid(sslState)) {
    -            assert(sslState->server.len == 0);
    -            comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF,
    -              sslReadServer, sslState);
    -            comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF,
    -              sslReadClient, sslState);
    -        }
    +    SslStateData *sslState = (SslStateData *)data;
    +
    +    if (flag != COMM_OK) {
    +        sslErrorComplete(fd, data, 0);
    +        return;
    +    }
    +
    +    if (cbdataReferenceValid(sslState)) {
    +        assert(sslState->server.len == 0);
    +        comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF,
    +                  sslReadServer, sslState);
    +        comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF,
    +                  sslReadClient, sslState);
    +    }
     }
     
     
    @@ -337,18 +395,20 @@ sslConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrn
     static void
     sslProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, void *data)
     {
    -	SslStateData *sslState = (SslStateData *)data;
    -	if (flag != COMM_OK) {
    -		sslErrorComplete(fd, data, 0);
    -		return;
    -	}
    -        if (cbdataReferenceValid(sslState)) {
    -            assert(sslState->server.len == 0);
    -            comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF,
    -              sslReadServer, sslState);
    -            comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF,
    -              sslReadClient, sslState);
    -        }
    +    SslStateData *sslState = (SslStateData *)data;
    +
    +    if (flag != COMM_OK) {
    +        sslErrorComplete(fd, data, 0);
    +        return;
    +    }
    +
    +    if (cbdataReferenceValid(sslState)) {
    +        assert(sslState->server.len == 0);
    +        comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF,
    +                  sslReadServer, sslState);
    +        comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF,
    +                  sslReadClient, sslState);
    +    }
     }
     
     static void
    @@ -358,7 +418,7 @@ sslConnected(int fd, void *data)
         debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState);
         *sslState->status_ptr = HTTP_OK;
         comm_write(sslState->client.fd, conn_established, strlen(conn_established),
    -      sslConnectedWriteDone, sslState);
    +               sslConnectedWriteDone, sslState);
     }
     
     static void
    @@ -366,10 +426,12 @@ sslErrorComplete(int fdnotused, void *data, size_t sizenotused)
     {
         SslStateData *sslState = (SslStateData *)data;
         assert(sslState != NULL);
    +
         if (sslState->client.fd > -1)
    -	comm_close(sslState->client.fd);
    +        comm_close(sslState->client.fd);
    +
         if (sslState->server.fd > -1)
    -	comm_close(sslState->server.fd);
    +        comm_close(sslState->server.fd);
     }
     
     
    @@ -379,47 +441,52 @@ sslConnectDone(int fdnotused, comm_err_t status, void *data)
         SslStateData *sslState = (SslStateData *)data;
         request_t *request = sslState->request;
         ErrorState *err = NULL;
    +
         if (sslState->servers->_peer)
    -	hierarchyNote(&sslState->request->hier, sslState->servers->code,
    -	    sslState->servers->_peer->host);
    +        hierarchyNote(&sslState->request->hier, sslState->servers->code,
    +                      sslState->servers->_peer->host);
         else if (Config.onoff.log_ip_on_direct)
    -	hierarchyNote(&sslState->request->hier, sslState->servers->code,
    -	    fd_table[sslState->server.fd].ipaddr);
    +        hierarchyNote(&sslState->request->hier, sslState->servers->code,
    +                      fd_table[sslState->server.fd].ipaddr);
         else
    -	hierarchyNote(&sslState->request->hier, sslState->servers->code,
    -	    sslState->host);
    +        hierarchyNote(&sslState->request->hier, sslState->servers->code,
    +                      sslState->host);
    +
         if (status == COMM_ERR_DNS) {
    -	debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host);
    -	err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND);
    -	*sslState->status_ptr = HTTP_NOT_FOUND;
    -	err->request = requestLink(request);
    -	err->dnsserver_msg = xstrdup(dns_error_message);
    -	err->callback = sslErrorComplete;
    -	err->callback_data = sslState;
    -	errorSend(sslState->client.fd, err);
    +        debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host);
    +        err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND);
    +        *sslState->status_ptr = HTTP_NOT_FOUND;
    +        err->request = requestLink(request);
    +        err->dnsserver_msg = xstrdup(dns_error_message);
    +        err->callback = sslErrorComplete;
    +        err->callback_data = sslState;
    +        errorSend(sslState->client.fd, err);
         } else if (status != COMM_OK) {
    -	err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
    -	*sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
    -	err->xerrno = errno;
    -	err->host = xstrdup(sslState->host);
    -	err->port = sslState->port;
    -	err->request = requestLink(request);
    -	err->callback = sslErrorComplete;
    -	err->callback_data = sslState;
    -	errorSend(sslState->client.fd, err);
    +        err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
    +        *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
    +        err->xerrno = errno;
    +        err->host = xstrdup(sslState->host);
    +        err->port = sslState->port;
    +        err->request = requestLink(request);
    +        err->callback = sslErrorComplete;
    +        err->callback_data = sslState;
    +        errorSend(sslState->client.fd, err);
         } else {
    -	if (sslState->servers->_peer)
    -	    sslProxyConnected(sslState->server.fd, sslState);
    -	else {
    -	    sslConnected(sslState->server.fd, sslState);
    -	}
    -	commSetTimeout(sslState->server.fd,
    -	    Config.Timeout.read,
    -	    sslTimeout,
    -	    sslState);
    +        if (sslState->servers->_peer)
    +            sslProxyConnected(sslState->server.fd, sslState);
    +        else {
    +            sslConnected(sslState->server.fd, sslState);
    +        }
    +
    +        commSetTimeout(sslState->server.fd,
    +                       Config.Timeout.read,
    +                       sslTimeout,
    +                       sslState);
     #if DELAY_POOLS
    -	commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
    +
    +        commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
     #endif
    +
         }
     }
     
    @@ -440,51 +507,58 @@ sslStart(clientHttpRequest * http, size_t * size_ptr, int *status_ptr)
          * from peer_digest.c, asn.c, netdb.c, etc and should always
          * be allowed.  yuck, I know.
          */
    +
         if (request->client_addr.s_addr != no_addr.s_addr) {
    -	/*
    -	 * Check if this host is allowed to fetch MISSES from us (miss_access)
    -	 */
    -	ACLChecklist ch;
    -	ch.src_addr = request->client_addr;
    -	ch.my_addr = request->my_addr;
    -	ch.my_port = request->my_port;
    -	ch.request = requestLink(request);
    -	answer = aclCheckFast(Config.accessList.miss, &ch);
    -	if (answer == 0) {
    -	    err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN);
    -	    *status_ptr = HTTP_FORBIDDEN;
    -	    err->request = requestLink(request);
    -	    err->src_addr = request->client_addr;
    -	    errorSend(fd, err);
    -	    return;
    -	}
    +        /*
    +         * Check if this host is allowed to fetch MISSES from us (miss_access)
    +         */
    +        ACLChecklist ch;
    +        ch.src_addr = request->client_addr;
    +        ch.my_addr = request->my_addr;
    +        ch.my_port = request->my_port;
    +        ch.request = requestLink(request);
    +        answer = aclCheckFast(Config.accessList.miss, &ch);
    +
    +        if (answer == 0) {
    +            err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN);
    +            *status_ptr = HTTP_FORBIDDEN;
    +            err->request = requestLink(request);
    +            err->src_addr = request->client_addr;
    +            errorSend(fd, err);
    +            return;
    +        }
         }
    +
         debug(26, 3) ("sslStart: '%s %s'\n",
    -	RequestMethodStr[request->method], url);
    +                  RequestMethodStr[request->method], url);
         statCounter.server.all.requests++;
         statCounter.server.other.requests++;
         /* Create socket. */
         sock = comm_openex(SOCK_STREAM,
    -	0,
    -	getOutgoingAddr(request),
    -	0,
    -	COMM_NONBLOCKING,
    -	getOutgoingTOS(request),
    -	url);
    +                       0,
    +                       getOutgoingAddr(request),
    +                       0,
    +                       COMM_NONBLOCKING,
    +                       getOutgoingTOS(request),
    +                       url);
    +
         if (sock == COMM_ERROR) {
    -	debug(26, 4) ("sslStart: Failed because we're out of sockets.\n");
    -	err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
    -	*status_ptr = HTTP_INTERNAL_SERVER_ERROR;
    -	err->xerrno = errno;
    -	err->request = requestLink(request);
    -	errorSend(fd, err);
    -	return;
    +        debug(26, 4) ("sslStart: Failed because we're out of sockets.\n");
    +        err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
    +        *status_ptr = HTTP_INTERNAL_SERVER_ERROR;
    +        err->xerrno = errno;
    +        err->request = requestLink(request);
    +        errorSend(fd, err);
    +        return;
         }
    +
         CBDATA_INIT_TYPE(SslStateData);
         sslState = cbdataAlloc(SslStateData);
     #if DELAY_POOLS
    +
         sslState->delayId = DelayId::DelayClient(http);
     #endif
    +
         sslState->url = xstrdup(url);
         sslState->request = requestLink(request);
         sslState->size_ptr = size_ptr;
    @@ -494,23 +568,23 @@ sslStart(clientHttpRequest * http, size_t * size_ptr, int *status_ptr)
         sslState->server.buf = (char *)xmalloc(SQUID_TCP_SO_RCVBUF);
         sslState->client.buf = (char *)xmalloc(SQUID_TCP_SO_RCVBUF);
         comm_add_close_handler(sslState->server.fd,
    -	sslServerClosed,
    -	sslState);
    +                           sslServerClosed,
    +                           sslState);
         comm_add_close_handler(sslState->client.fd,
    -	sslClientClosed,
    -	sslState);
    +                           sslClientClosed,
    +                           sslState);
         commSetTimeout(sslState->client.fd,
    -	Config.Timeout.lifetime,
    -	sslTimeout,
    -	sslState);
    +                   Config.Timeout.lifetime,
    +                   sslTimeout,
    +                   sslState);
         commSetTimeout(sslState->server.fd,
    -	Config.Timeout.connect,
    -	sslTimeout,
    -	sslState);
    +                   Config.Timeout.connect,
    +                   sslTimeout,
    +                   sslState);
         peerSelect(request,
    -	NULL,
    -	sslPeerSelectComplete,
    -	sslState);
    +               NULL,
    +               sslPeerSelectComplete,
    +               sslState);
         /*
          * Disable the client read handler until peer selection is complete
          * Take control away from client_side.c.
    @@ -532,10 +606,10 @@ sslProxyConnected(int fd, void *data)
         memBufDefInit(&mb);
         memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url);
         httpBuildRequestHeader(sslState->request,
    -	sslState->request,
    -	NULL,			/* StoreEntry */
    -	&hdr_out,
    -	flags);			/* flags */
    +                           sslState->request,
    +                           NULL,			/* StoreEntry */
    +                           &hdr_out,
    +                           flags);			/* flags */
         packerToMemInit(&p, &mb);
         httpHeaderPackInto(&hdr_out, &p);
         httpHeaderClean(&hdr_out);
    @@ -545,9 +619,9 @@ sslProxyConnected(int fd, void *data)
         comm_old_write_mbuf(sslState->server.fd, mb, sslProxyConnectedWriteDone, sslState);
     
         commSetTimeout(sslState->server.fd,
    -	Config.Timeout.read,
    -	sslTimeout,
    -	sslState);
    +                   Config.Timeout.read,
    +                   sslTimeout,
    +                   sslState);
     }
     
     static void
    @@ -556,43 +630,49 @@ sslPeerSelectComplete(FwdServer * fs, void *data)
         SslStateData *sslState = (SslStateData *)data;
         request_t *request = sslState->request;
         peer *g = NULL;
    +
         if (fs == NULL) {
    -	ErrorState *err;
    -	err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
    -	*sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
    -	err->request = requestLink(sslState->request);
    -	err->callback = sslErrorComplete;
    -	err->callback_data = sslState;
    -	errorSend(sslState->client.fd, err);
    -	return;
    +        ErrorState *err;
    +        err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
    +        *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
    +        err->request = requestLink(sslState->request);
    +        err->callback = sslErrorComplete;
    +        err->callback_data = sslState;
    +        errorSend(sslState->client.fd, err);
    +        return;
         }
    +
         sslState->servers = fs;
         sslState->host = fs->_peer ? fs->_peer->host : request->host;
    +
         if (fs->_peer == NULL) {
    -	sslState->port = request->port;
    +        sslState->port = request->port;
         } else if (fs->_peer->http_port != 0) {
    -	sslState->port = fs->_peer->http_port;
    +        sslState->port = fs->_peer->http_port;
         } else if ((g = peerFindByName(fs->_peer->host))) {
    -	sslState->port = g->http_port;
    +        sslState->port = g->http_port;
         } else {
    -	sslState->port = CACHE_HTTP_PORT;
    +        sslState->port = CACHE_HTTP_PORT;
         }
    +
         if (fs->_peer) {
    -	sslState->request->peer_login = fs->_peer->login;
    -	sslState->request->flags.proxying = 1;
    +        sslState->request->peer_login = fs->_peer->login;
    +        sslState->request->flags.proxying = 1;
         } else {
    -	sslState->request->peer_login = NULL;
    -	sslState->request->flags.proxying = 0;
    +        sslState->request->peer_login = NULL;
    +        sslState->request->flags.proxying = 0;
         }
    +
     #if DELAY_POOLS
         /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
         if (g && g->options.no_delay && sslState->delayId) {
    -	sslState->delayId = DelayId();
    +        sslState->delayId = DelayId();
         }
    +
     #endif
         commConnectStart(sslState->server.fd,
    -	sslState->host,
    -	sslState->port,
    -	sslConnectDone,
    -	sslState);
    +                     sslState->host,
    +                     sslState->port,
    +                     sslConnectDone,
    +                     sslState);
     }
    diff --git a/src/typedefs.h b/src/typedefs.h
    index e35071bb24..8c404ef24d 100644
    --- a/src/typedefs.h
    +++ b/src/typedefs.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: typedefs.h,v 1.152 2003/02/21 19:53:02 hno Exp $
    + * $Id: typedefs.h,v 1.153 2003/02/21 22:50:12 robertc Exp $
      *
      *
      * SQUID Web Proxy Cache          http://www.squid-cache.org/
    @@ -42,132 +42,252 @@ typedef unsigned int swap_status_t;
     typedef signed int sfileno;
     typedef signed int sdirno;
     
    -typedef struct {
    +typedef struct
    +{
         size_t bytes;
         size_t kb;
    -} kb_t;
    +}
    +
    +kb_t;
     
     typedef struct _acl_time_data acl_time_data;
    +
     typedef struct _acl_name_list acl_name_list;
    +
     typedef struct _acl_deny_info_list acl_deny_info_list;
    +
     typedef struct AuthUser auth_user_t;
    +
     class AuthUserRequest;
     typedef AuthUserRequest auth_user_request_t;
    +
     typedef struct AuthUserHashPointer auth_user_hash_pointer;
    +
     typedef struct AuthUserIP auth_user_ip_t;
    +
     typedef struct _acl_proxy_auth_match_cache acl_proxy_auth_match_cache;
    +
     typedef struct _authscheme_entry authscheme_entry_t;
    +
     typedef struct _authScheme authScheme;
    +
     typedef struct _acl_user_ip_data acl_user_ip_data;
    +
     typedef struct _acl_arp_data acl_arp_data;
    +
     typedef struct _acl_snmp_comm acl_snmp_comm;
    +
     typedef class ACLList acl_list;
    +
     typedef struct _acl_address acl_address;
    +
     typedef struct _acl_tos acl_tos;
    +
     class ACLChecklist;
    +
     typedef struct _wordlist wordlist;
    +
     typedef struct _intlist intlist;
    +
     typedef struct _intrange intrange;
    +
     typedef struct _ushortlist ushortlist;
    +
     typedef struct _relist relist;
    +
     typedef struct _sockaddr_in_list sockaddr_in_list;
    +
     typedef struct _http_port_list http_port_list;
    +
     typedef struct _https_port_list https_port_list;
    +
     typedef struct _SquidConfig SquidConfig;
    +
     typedef struct _SquidConfig2 SquidConfig2;
    +
     typedef struct _close_handler close_handler;
    +
     typedef struct _dread_ctrl dread_ctrl;
    +
     typedef struct _dnsserver_t dnsserver_t;
    +
     typedef struct _dwrite_q dwrite_q;
    +
     typedef struct _ETag ETag;
    +
     class fde;
    +
     typedef struct _fileMap fileMap;
    +
     typedef struct _HttpReply http_reply;
    +
     typedef struct _HttpStatusLine HttpStatusLine;
    +
     typedef struct _HttpHeaderFieldAttrs HttpHeaderFieldAttrs;
    +
     typedef struct _HttpHeaderFieldInfo HttpHeaderFieldInfo;
    +
     typedef struct _HttpHeader HttpHeader;
    +
     typedef struct _HttpHdrCc HttpHdrCc;
    +
     typedef struct _HttpHdrSc HttpHdrSc;
    +
     typedef struct _HttpHdrScTarget HttpHdrScTarget;
    +
     typedef struct _TimeOrTag TimeOrTag;
    +
     typedef struct _HttpHeaderEntry HttpHeaderEntry;
    +
     typedef struct _HttpHeaderFieldStat HttpHeaderFieldStat;
    +
     typedef struct _HttpHeaderStat HttpHeaderStat;
    +
     typedef struct _HttpBody HttpBody;
    +
     typedef struct _HttpReply HttpReply;
    +
     typedef struct _ConnStateData ConnStateData;
    +
     typedef struct _ConnCloseHelperData ConnCloseHelperData;
    +
     typedef struct _ipcache_addrs ipcache_addrs;
    +
     typedef struct _domain_ping domain_ping;
    +
     typedef struct _domain_type domain_type;
    +
     typedef struct _DynPool DynPool;
    +
     typedef struct _Packer Packer;
    +
     typedef struct _StoreDigestCBlock StoreDigestCBlock;
    +
     typedef struct _DigestFetchState DigestFetchState;
    +
     typedef struct _PeerDigest PeerDigest;
    +
     typedef struct _peer peer;
    +
     typedef struct _net_db_name net_db_name;
    +
     typedef struct _net_db_peer net_db_peer;
    +
     typedef struct _netdbEntry netdbEntry;
    +
     typedef struct _ping_data ping_data;
    +
     typedef struct _ps_state ps_state;
    +
     typedef struct _HierarchyLogEntry HierarchyLogEntry;
    +
     typedef struct _pingerEchoData pingerEchoData;
    +
     typedef struct _pingerReplyData pingerReplyData;
    +
     typedef struct _icp_common_t icp_common_t;
    +
     typedef struct _Meta_data Meta_data;
    +
     typedef struct _iostats iostats;
    +
     class MemBuf;
    +
     class store_client;
    +
     class StoreEntry;
    +
     class SwapDir;
    +
     typedef struct _helper_flags helper_flags;
    +
     typedef struct _helper_stateful_flags helper_stateful_flags;
    +
     typedef struct _http_state_flags http_state_flags;
    +
     typedef struct _header_mangler header_mangler;
    +
     typedef struct _body_size body_size;
    +
     class request_t;
    +
     typedef struct _AccessLogEntry AccessLogEntry;
    +
     typedef struct _cachemgr_passwd cachemgr_passwd;
    +
     typedef struct _refresh_t refresh_t;
    +
     typedef struct _CommWriteStateData CommWriteStateData;
    +
     typedef struct _ErrorState ErrorState;
    +
     typedef struct _dlink_node dlink_node;
    +
     typedef struct _dlink_list dlink_list;
    +
     typedef struct _StatCounters StatCounters;
    +
     typedef struct _storeSwapLogData storeSwapLogData;
    +
     typedef struct _authConfig authConfig;
    +
     typedef struct _cacheSwap cacheSwap;
    +
     typedef struct _StatHist StatHist;
    +
     typedef struct _ClientInfo ClientInfo;
    +
     typedef struct _cd_guess_stats cd_guess_stats;
    +
     typedef struct _CacheDigest CacheDigest;
    +
     typedef struct _Version Version;
    +
     typedef struct _FwdState FwdState;
    +
     typedef struct _FwdServer FwdServer;
    +
     typedef struct _helper helper;
    +
     typedef struct _helper_stateful statefulhelper;
    +
     typedef struct _helper_server helper_server;
    +
     typedef struct _helper_stateful_server helper_stateful_server;
    +
     typedef struct _helper_request helper_request;
    +
     typedef struct _helper_stateful_request helper_stateful_request;
    +
     typedef struct _generic_cbdata generic_cbdata;
    +
     class storeIOState;
    +
     typedef struct _link_list link_list;
    +
     typedef struct _storefs_entry storefs_entry_t;
    +
     typedef struct _storerepl_entry storerepl_entry_t;
    +
     typedef struct _diskd_queue diskd_queue;
    +
     typedef struct _Logfile Logfile;
    +
     typedef struct _RemovalPolicy RemovalPolicy;
    +
     typedef struct _RemovalPolicyWalker RemovalPolicyWalker;
    +
     typedef struct _RemovalPurgeWalker RemovalPurgeWalker;
    +
     typedef struct _RemovalPolicyNode RemovalPolicyNode;
    +
     typedef struct _RemovalPolicySettings RemovalPolicySettings;
    +
     typedef struct _http_version_t http_version_t;
     
     #if SQUID_SNMP
     typedef variable_list *(oid_ParseFn) (variable_list *, snint *);
    +
     typedef struct _snmp_request_t snmp_request_t;
     #endif
     
    @@ -183,7 +303,7 @@ typedef void PF(int, void *);
     
     /* disk.c / diskd.c callback typedefs */
     typedef void DRCB(int, const char *buf, int size, int errflag, void *data);
    -							/* Disk read CB */
    +/* Disk read CB */
     typedef void DWCB(int, int, size_t, void *);	/* disk write CB */
     typedef void DOCB(int, int errflag, void *data);	/* disk open CB */
     typedef void DCCB(int, int errflag, void *data);	/* disk close CB */
    @@ -253,6 +373,7 @@ typedef char HttpHeaderMask[8];
     typedef void (*ObjPackMethod) (void *obj, Packer * p);
     
     #if USE_HTCP
    +
     typedef struct _htcpReplyData htcpReplyData;
     #endif
     
    @@ -261,6 +382,7 @@ typedef RemovalPolicy *REMOVALPOLICYCREATE(wordlist * args);
     typedef int STDIRSELECT(const StoreEntry *);
     
     typedef struct _external_acl external_acl;
    +
     typedef struct _external_acl_entry external_acl_entry;
     
     #endif /* SQUID_TYPEDEFS_H */
    diff --git a/src/ufscommon.cc b/src/ufscommon.cc
    index 8e72f494c4..dd00c3c4be 100644
    --- a/src/ufscommon.cc
    +++ b/src/ufscommon.cc
    @@ -1,5 +1,5 @@
     /*
    - * $Id: ufscommon.cc,v 1.8 2003/01/23 20:59:10 robertc Exp $
    + * $Id: ufscommon.cc,v 1.9 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 47    Store Directory Routines
      * AUTHOR: Duane Wessels
    @@ -53,7 +53,7 @@ RebuildState::operator new (size_t size)
         cbdataReference(result);
         return result;
     }
    - 
    +
     void
     RebuildState::operator delete (void *address)
     {
    @@ -86,20 +86,26 @@ RebuildState::RebuildFromDirectory(void *data)
     struct InitStoreEntry : public unary_function
     {
         InitStoreEntry(StoreEntry *anEntry, cache_key *aKey):what(anEntry),index(aKey){}
    -    void operator()(StoreMeta const &x) {
    -	    switch (x.getType()) {
    -	    case STORE_META_KEY:
    -		assert(x.length == MD5_DIGEST_CHARS);
    -		xmemcpy(index, x.value, MD5_DIGEST_CHARS);
    -		break;
    -	    case STORE_META_STD:
    -		assert(x.length == STORE_HDR_METASIZE);
    -		xmemcpy(&what->timestamp, x.value, STORE_HDR_METASIZE);
    -		break;
    -	    default:
    -		break;
    -	    }
    +
    +    void operator()(StoreMeta const &x)
    +    {
    +        switch (x.getType()) {
    +
    +        case STORE_META_KEY:
    +            assert(x.length == MD5_DIGEST_CHARS);
    +            xmemcpy(index, x.value, MD5_DIGEST_CHARS);
    +            break;
    +
    +        case STORE_META_STD:
    +            assert(x.length == STORE_HDR_METASIZE);
    +            xmemcpy(&what->timestamp, x.value, STORE_HDR_METASIZE);
    +            break;
    +
    +        default:
    +            break;
    +        }
         }
    +
         StoreEntry *what;
         cache_key *index;
     };
    @@ -111,126 +117,152 @@ RebuildState::rebuildFromDirectory()
         currentEntry(NULL);
         StoreEntry tmpe;
         cache_key key[MD5_DIGEST_CHARS];
    +
         struct stat sb;
         int swap_hdr_len;
         int fd = -1;
         StoreMeta *tlv_list;
         assert(this != NULL);
         debug(47, 3) ("commonUfsDirRebuildFromDirectory: DIR #%d\n", sd->index);
    +
         for (int count = 0; count < speed; count++) {
    -	assert(fd == -1);
    -	sfileno filn = 0;
    -	int size;
    -	fd = getNextFile(&filn, &size);
    -	if (fd == -2) {
    -	    debug(47, 1) ("Done scanning %s swaplog (%d entries)\n",
    -		sd->path, n_read);
    -	    deleteSelf();
    -	    return;
    -	} else if (fd < 0) {
    -	    continue;
    -	}
    -	assert(fd > -1);
    -	/* lets get file stats here */
    -	if (fstat(fd, &sb) < 0) {
    -	    debug(47, 1) ("commonUfsDirRebuildFromDirectory: fstat(FD %d): %s\n",
    -		fd, xstrerror());
    -	    file_close(fd);
    -	    store_open_disk_fd--;
    -	    fd = -1;
    -	    continue;
    -	}
    -	if ((++counts.scancount & 0xFFFF) == 0)
    -	    debug(47, 3) ("  %s %7d files opened so far.\n",
    -		sd->path, counts.scancount);
    -	debug(47, 9) ("file_in: fd=%d %08X\n", fd, filn);
    -	statCounter.syscalls.disk.reads++;
    -	int len;
    -	if ((len = FD_READ_METHOD(fd, hdr_buf, SM_PAGE_SIZE)) < 0) {
    -	    debug(47, 1) ("commonUfsDirRebuildFromDirectory: read(FD %d): %s\n",
    -		fd, xstrerror());
    -	    file_close(fd);
    -	    store_open_disk_fd--;
    -	    fd = -1;
    -	    continue;
    -	}
    -	file_close(fd);
    -	store_open_disk_fd--;
    -	fd = -1;
    -	swap_hdr_len = 0;
    +        assert(fd == -1);
    +        sfileno filn = 0;
    +        int size;
    +        fd = getNextFile(&filn, &size);
    +
    +        if (fd == -2) {
    +            debug(47, 1) ("Done scanning %s swaplog (%d entries)\n",
    +                          sd->path, n_read);
    +            deleteSelf();
    +            return;
    +        } else if (fd < 0) {
    +            continue;
    +        }
    +
    +        assert(fd > -1);
    +        /* lets get file stats here */
    +
    +        if (fstat(fd, &sb) < 0) {
    +            debug(47, 1) ("commonUfsDirRebuildFromDirectory: fstat(FD %d): %s\n",
    +                          fd, xstrerror());
    +            file_close(fd);
    +            store_open_disk_fd--;
    +            fd = -1;
    +            continue;
    +        }
    +
    +        if ((++counts.scancount & 0xFFFF) == 0)
    +            debug(47, 3) ("  %s %7d files opened so far.\n",
    +                          sd->path, counts.scancount);
    +
    +        debug(47, 9) ("file_in: fd=%d %08X\n", fd, filn);
    +
    +        statCounter.syscalls.disk.reads++;
    +
    +        int len;
    +
    +        if ((len = FD_READ_METHOD(fd, hdr_buf, SM_PAGE_SIZE)) < 0) {
    +            debug(47, 1) ("commonUfsDirRebuildFromDirectory: read(FD %d): %s\n",
    +                          fd, xstrerror());
    +            file_close(fd);
    +            store_open_disk_fd--;
    +            fd = -1;
    +            continue;
    +        }
    +
    +        file_close(fd);
    +        store_open_disk_fd--;
    +        fd = -1;
    +        swap_hdr_len = 0;
     #if USE_TRUNCATE
    -	if (sb.st_size == 0)
    -	    continue;
    +
    +        if (sb.st_size == 0)
    +            continue;
    +
     #endif
    +
             StoreMetaUnpacker aBuilder(hdr_buf, len, &swap_hdr_len);
    -	if (!aBuilder.isBufferSane()) {
    -	    debug(47, 1) ("commonUfsDirRebuildFromDirectory: Swap data buffer length is not sane.\n");
    -	    /* XXX shouldn't this be a call to commonUfsUnlink ? */
    -	    sd->unlinkFile ( filn);
    -	    continue;
    -	}
    +
    +        if (!aBuilder.isBufferSane()) {
    +            debug(47, 1) ("commonUfsDirRebuildFromDirectory: Swap data buffer length is not sane.\n");
    +            /* XXX shouldn't this be a call to commonUfsUnlink ? */
    +            sd->unlinkFile ( filn);
    +            continue;
    +        }
    +
             tlv_list = aBuilder.createStoreMeta ();
    -	if (tlv_list == NULL) {
    -	    debug(47, 1) ("commonUfsDirRebuildFromDirectory: failed to get meta data\n");
    -	    /* XXX shouldn't this be a call to commonUfsUnlink ? */
    -	    sd->unlinkFile (filn);
    -	    continue;
    -	}
    -	debug(47, 3) ("commonUfsDirRebuildFromDirectory: successful swap meta unpacking\n");
    -	memset(key, '\0', MD5_DIGEST_CHARS);
    -	memset(&tmpe, '\0', sizeof(StoreEntry));
    -	InitStoreEntry visitor(&tmpe, key);
    -	for_each(*tlv_list, visitor);
    -	storeSwapTLVFree(tlv_list);
    -	tlv_list = NULL;
    -	if (storeKeyNull(key)) {
    -	    debug(47, 1) ("commonUfsDirRebuildFromDirectory: NULL key\n");
    -	    sd->unlinkFile(filn);
    -	    continue;
    -	}
    -	tmpe.key = key;
    -	/* check sizes */
    -	if (tmpe.swap_file_sz == 0) {
    -	    tmpe.swap_file_sz = (size_t) sb.st_size;
    -	} else if (tmpe.swap_file_sz == (size_t)(sb.st_size - swap_hdr_len)) {
    -	    tmpe.swap_file_sz = (size_t) sb.st_size;
    -	} else if (tmpe.swap_file_sz != (size_t)sb.st_size) {
    -	    debug(47, 1) ("commonUfsDirRebuildFromDirectory: SIZE MISMATCH %ld!=%ld\n",
    -		(long int) tmpe.swap_file_sz, (long int) sb.st_size);
    -	    sd->unlinkFile(filn);
    -	    continue;
    -	}
    -	if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) {
    -	    sd->unlinkFile(filn);
    -	    counts.badflags++;
    -	    continue;
    -	}
    -	e = storeGet(key);
    -	if (e && e->lastref >= tmpe.lastref) {
    -	    /* key already exists, current entry is newer */
    -	    /* keep old, ignore new */
    -	    counts.dupcount++;
    -	    continue;
    -	} else if (NULL != e) {
    -	    /* URL already exists, this swapfile not being used */
    -	    /* junk old, load new */
    -	    storeRelease(e);	/* release old entry */
    -	    counts.dupcount++;
    -	}
    -	counts.objcount++;
    -	storeEntryDump(&tmpe, 5);
    -	e = sd->addDiskRestore(key,
    -	    filn,
    -	    tmpe.swap_file_sz,
    -	    tmpe.expires,
    -	    tmpe.timestamp,
    -	    tmpe.lastref,
    -	    tmpe.lastmod,
    -	    tmpe.refcount,	/* refcount */
    -	    tmpe.flags,		/* flags */
    -	    (int) flags.clean);
    -	storeDirSwapLog(e, SWAP_LOG_ADD);
    +
    +        if (tlv_list == NULL) {
    +            debug(47, 1) ("commonUfsDirRebuildFromDirectory: failed to get meta data\n");
    +            /* XXX shouldn't this be a call to commonUfsUnlink ? */
    +            sd->unlinkFile (filn);
    +            continue;
    +        }
    +
    +        debug(47, 3) ("commonUfsDirRebuildFromDirectory: successful swap meta unpacking\n");
    +        memset(key, '\0', MD5_DIGEST_CHARS);
    +        memset(&tmpe, '\0', sizeof(StoreEntry));
    +        InitStoreEntry visitor(&tmpe, key);
    +        for_each(*tlv_list, visitor);
    +        storeSwapTLVFree(tlv_list);
    +        tlv_list = NULL;
    +
    +        if (storeKeyNull(key)) {
    +            debug(47, 1) ("commonUfsDirRebuildFromDirectory: NULL key\n");
    +            sd->unlinkFile(filn);
    +            continue;
    +        }
    +
    +        tmpe.key = key;
    +        /* check sizes */
    +
    +        if (tmpe.swap_file_sz == 0) {
    +            tmpe.swap_file_sz = (size_t) sb.st_size;
    +        } else if (tmpe.swap_file_sz == (size_t)(sb.st_size - swap_hdr_len)) {
    +            tmpe.swap_file_sz = (size_t) sb.st_size;
    +        } else if (tmpe.swap_file_sz != (size_t)sb.st_size) {
    +            debug(47, 1) ("commonUfsDirRebuildFromDirectory: SIZE MISMATCH %ld!=%ld\n",
    +                          (long int) tmpe.swap_file_sz, (long int) sb.st_size);
    +            sd->unlinkFile(filn);
    +            continue;
    +        }
    +
    +        if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) {
    +            sd->unlinkFile(filn);
    +            counts.badflags++;
    +            continue;
    +        }
    +
    +        e = storeGet(key);
    +
    +        if (e && e->lastref >= tmpe.lastref) {
    +            /* key already exists, current entry is newer */
    +            /* keep old, ignore new */
    +            counts.dupcount++;
    +            continue;
    +        } else if (NULL != e) {
    +            /* URL already exists, this swapfile not being used */
    +            /* junk old, load new */
    +            storeRelease(e);	/* release old entry */
    +            counts.dupcount++;
    +        }
    +
    +        counts.objcount++;
    +        storeEntryDump(&tmpe, 5);
    +        e = sd->addDiskRestore(key,
    +                               filn,
    +                               tmpe.swap_file_sz,
    +                               tmpe.expires,
    +                               tmpe.timestamp,
    +                               tmpe.lastref,
    +                               tmpe.lastmod,
    +                               tmpe.refcount,	/* refcount */
    +                               tmpe.flags,		/* flags */
    +                               (int) flags.clean);
    +        storeDirSwapLog(e, SWAP_LOG_ADD);
         }
    +
         eventAdd("storeRebuild", RebuildFromDirectory, this, 0.0, 1);
     }
     
    @@ -259,171 +291,201 @@ RebuildState::rebuildFromSwapLog()
         currentEntry (NULL);
         double x;
         /* load a number of objects per invocation */
    +
         for (int count = 0; count < speed; count++) {
             storeSwapLogData s;
             size_t ss = sizeof(storeSwapLogData);
    -	if (fread(&s, ss, 1, log) != 1) {
    -	    debug(47, 1) ("Done reading %s swaplog (%d entries)\n",
    -		sd->path, n_read);
    -	    fclose(log);
    -	    log = NULL;
    -	    delete this;
    -	    return;
    -	}
    -	n_read++;
    -	if (s.op <= SWAP_LOG_NOP)
    -	    continue;
    -	if (s.op >= SWAP_LOG_MAX)
    -	    continue;
    -	/*
    -	 * BC: during 2.4 development, we changed the way swap file
    -	 * numbers are assigned and stored.  The high 16 bits used
    -	 * to encode the SD index number.  There used to be a call
    -	 * to storeDirProperFileno here that re-assigned the index 
    -	 * bits.  Now, for backwards compatibility, we just need
    -	 * to mask it off.
    -	 */
    -	s.swap_filen &= 0x00FFFFFF;
    -	debug(47, 3) ("commonUfsDirRebuildFromSwapLog: %s %s %08X\n",
    -	    swap_log_op_str[(int) s.op],
    -	    storeKeyText(s.key),
    -	    s.swap_filen);
    -	if (s.op == SWAP_LOG_ADD) {
    -	    (void) 0;
    -	} else if (s.op == SWAP_LOG_DEL) {
    -	    /* Delete unless we already have a newer copy */
    -	    currentEntry (storeGet(s.key));
    -	    if (currentEntry() != NULL && s.lastref > e->lastref) {
    -		/*
    -		 * Make sure we don't unlink the file, it might be
    -		 * in use by a subsequent entry.  Also note that
    -		 * we don't have to subtract from store_swap_size
    -		 * because adding to store_swap_size happens in
    -		 * the cleanup procedure.
    -		 */
    -		storeExpireNow(currentEntry());
    -		storeReleaseRequest(currentEntry());
    -		if (currentEntry()->swap_filen > -1) {
    -		    UFSSwapDir *sdForThisEntry = dynamic_cast(INDEXSD(currentEntry()->swap_dirn));
    -		    assert (sdForThisEntry);
    -		    sdForThisEntry->replacementRemove(currentEntry());
    -		    sdForThisEntry->mapBitReset(currentEntry()->swap_filen);
    -		    currentEntry()->swap_filen = -1;
    -		    currentEntry()->swap_dirn = -1;
    -		}
    -		storeRelease(currentEntry());
    -		counts.objcount--;
    -		counts.cancelcount++;
    -	    }
    -	    continue;
    -	} else {
    -	    x = ::log(++counts.bad_log_op) / ::log(10.0);
    -	    if (0.0 == x - (double) (int) x)
    -		debug(47, 1) ("WARNING: %d invalid swap log entries found\n",
    -		    counts.bad_log_op);
    -	    counts.invalid++;
    -	    continue;
    -	}
    -	if ((++counts.scancount & 0xFFF) == 0) {
    -	    struct stat sb;
    -	    if (0 == fstat(fileno(log), &sb))
    -		storeRebuildProgress(sd->index,
    -		    (int) sb.st_size / ss, n_read);
    -	}
    -	if (!sd->validFileno(s.swap_filen, 0)) {
    -	    counts.invalid++;
    -	    continue;
    -	}
    -	if (EBIT_TEST(s.flags, KEY_PRIVATE)) {
    -	    counts.badflags++;
    -	    continue;
    -	}
    -	currentEntry(storeGet(s.key));
    +
    +        if (fread(&s, ss, 1, log) != 1) {
    +            debug(47, 1) ("Done reading %s swaplog (%d entries)\n",
    +                          sd->path, n_read);
    +            fclose(log);
    +            log = NULL;
    +            delete this;
    +            return;
    +        }
    +
    +        n_read++;
    +
    +        if (s.op <= SWAP_LOG_NOP)
    +            continue;
    +
    +        if (s.op >= SWAP_LOG_MAX)
    +            continue;
    +
    +        /*
    +         * BC: during 2.4 development, we changed the way swap file
    +         * numbers are assigned and stored.  The high 16 bits used
    +         * to encode the SD index number.  There used to be a call
    +         * to storeDirProperFileno here that re-assigned the index 
    +         * bits.  Now, for backwards compatibility, we just need
    +         * to mask it off.
    +         */
    +        s.swap_filen &= 0x00FFFFFF;
    +
    +        debug(47, 3) ("commonUfsDirRebuildFromSwapLog: %s %s %08X\n",
    +                      swap_log_op_str[(int) s.op],
    +                      storeKeyText(s.key),
    +                      s.swap_filen);
    +
    +        if (s.op == SWAP_LOG_ADD) {
    +            (void) 0;
    +        } else if (s.op == SWAP_LOG_DEL) {
    +            /* Delete unless we already have a newer copy */
    +            currentEntry (storeGet(s.key));
    +
    +            if (currentEntry() != NULL && s.lastref > e->lastref) {
    +                /*
    +                 * Make sure we don't unlink the file, it might be
    +                 * in use by a subsequent entry.  Also note that
    +                 * we don't have to subtract from store_swap_size
    +                 * because adding to store_swap_size happens in
    +                 * the cleanup procedure.
    +                 */
    +                storeExpireNow(currentEntry());
    +                storeReleaseRequest(currentEntry());
    +
    +                if (currentEntry()->swap_filen > -1) {
    +                    UFSSwapDir *sdForThisEntry = dynamic_cast(INDEXSD(currentEntry()->swap_dirn));
    +                    assert (sdForThisEntry);
    +                    sdForThisEntry->replacementRemove(currentEntry());
    +                    sdForThisEntry->mapBitReset(currentEntry()->swap_filen);
    +                    currentEntry()->swap_filen = -1;
    +                    currentEntry()->swap_dirn = -1;
    +                }
    +
    +                storeRelease(currentEntry());
    +                counts.objcount--;
    +                counts.cancelcount++;
    +            }
    +
    +            continue;
    +        } else {
    +            x = ::log(++counts.bad_log_op) / ::log(10.0);
    +
    +            if (0.0 == x - (double) (int) x)
    +                debug(47, 1) ("WARNING: %d invalid swap log entries found\n",
    +                              counts.bad_log_op);
    +
    +            counts.invalid++;
    +
    +            continue;
    +        }
    +
    +        if ((++counts.scancount & 0xFFF) == 0) {
    +
    +            struct stat sb;
    +
    +            if (0 == fstat(fileno(log), &sb))
    +                storeRebuildProgress(sd->index,
    +                                     (int) sb.st_size / ss, n_read);
    +        }
    +
    +        if (!sd->validFileno(s.swap_filen, 0)) {
    +            counts.invalid++;
    +            continue;
    +        }
    +
    +        if (EBIT_TEST(s.flags, KEY_PRIVATE)) {
    +            counts.badflags++;
    +            continue;
    +        }
    +
    +        currentEntry(storeGet(s.key));
             int used;			/* is swapfile already in use? */
    -	used = sd->mapBitTest(s.swap_filen);
    -	/* If this URL already exists in the cache, does the swap log
    -	 * appear to have a newer entry?  Compare 'lastref' from the
    -	 * swap log to e->lastref. */
    -    	/* is the log entry newer than current entry? */
    -	int disk_entry_newer = currentEntry() ? (s.lastref > currentEntry()->lastref ? 1 : 0) : 0;
    -	if (used && !disk_entry_newer) {
    -	    /* log entry is old, ignore it */
    -	    counts.clashcount++;
    -	    continue;
    -	} else if (used && currentEntry() && currentEntry()->swap_filen == s.swap_filen && currentEntry()->swap_dirn == sd->index) {
    -	    /* swapfile taken, same URL, newer, update meta */
    -	    if (currentEntry()->store_status == STORE_OK) {
    -		currentEntry()->lastref = s.timestamp;
    -		currentEntry()->timestamp = s.timestamp;
    -		currentEntry()->expires = s.expires;
    -		currentEntry()->lastmod = s.lastmod;
    -		currentEntry()->flags = s.flags;
    -		currentEntry()->refcount += s.refcount;
    -		sd->dereference(*currentEntry());
    -	    } else {
    -		debug_trap("commonUfsDirRebuildFromSwapLog: bad condition");
    -		debug(47, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);
    -	    }
    -	    continue;
    -	} else if (used) {
    -	    /* swapfile in use, not by this URL, log entry is newer */
    -	    /* This is sorta bad: the log entry should NOT be newer at this
    -	     * point.  If the log is dirty, the filesize check should have
    -	     * caught this.  If the log is clean, there should never be a
    -	     * newer entry. */
    -	    debug(47, 1) ("WARNING: newer swaplog entry for dirno %d, fileno %08X\n",
    -		sd->index, s.swap_filen);
    -	    /* I'm tempted to remove the swapfile here just to be safe,
    -	     * but there is a bad race condition in the NOVM version if
    -	     * the swapfile has recently been opened for writing, but
    -	     * not yet opened for reading.  Because we can't map
    -	     * swapfiles back to StoreEntrys, we don't know the state
    -	     * of the entry using that file.  */
    -	    /* We'll assume the existing entry is valid, probably because
    -	     * were in a slow rebuild and the the swap file number got taken
    -	     * and the validation procedure hasn't run. */
    -	    assert(flags.need_to_validate);
    -	    counts.clashcount++;
    -	    continue;
    -	} else if (currentEntry() && !disk_entry_newer) {
    -	    /* key already exists, current entry is newer */
    -	    /* keep old, ignore new */
    -	    counts.dupcount++;
    -	    continue;
    -	} else if (currentEntry()) {
    -	    /* key already exists, this swapfile not being used */
    -	    /* junk old, load new */
    -	    storeExpireNow(currentEntry());
    -	    storeReleaseRequest(currentEntry());
    -	    if (currentEntry()->swap_filen > -1) {
    -		UFSSwapDir *sdForThisEntry = dynamic_cast(INDEXSD(currentEntry()->swap_dirn));
    -		sdForThisEntry->replacementRemove(currentEntry());
    -		/* Make sure we don't actually unlink the file */
    -		sdForThisEntry->mapBitReset(currentEntry()->swap_filen);
    -		currentEntry()->swap_filen = -1;
    -		currentEntry()->swap_dirn = -1;
    -	    }
    -	    storeRelease(currentEntry());
    -	    counts.dupcount++;
    -	} else {
    -	    /* URL doesnt exist, swapfile not in use */
    -	    /* load new */
    -	    (void) 0;
    -	}
    -	/* update store_swap_size */
    -	counts.objcount++;
    -	currentEntry(sd->addDiskRestore(s.key,
    -	    s.swap_filen,
    -	    s.swap_file_sz,
    -	    s.expires,
    -	    s.timestamp,
    -	    s.lastref,
    -	    s.lastmod,
    -	    s.refcount,
    -	    s.flags,
    -	    (int) flags.clean));
    -	storeDirSwapLog(currentEntry(), SWAP_LOG_ADD);
    +        used = sd->mapBitTest(s.swap_filen);
    +        /* If this URL already exists in the cache, does the swap log
    +         * appear to have a newer entry?  Compare 'lastref' from the
    +         * swap log to e->lastref. */
    +        /* is the log entry newer than current entry? */
    +        int disk_entry_newer = currentEntry() ? (s.lastref > currentEntry()->lastref ? 1 : 0) : 0;
    +
    +        if (used && !disk_entry_newer) {
    +            /* log entry is old, ignore it */
    +            counts.clashcount++;
    +            continue;
    +        } else if (used && currentEntry() && currentEntry()->swap_filen == s.swap_filen && currentEntry()->swap_dirn == sd->index) {
    +            /* swapfile taken, same URL, newer, update meta */
    +
    +            if (currentEntry()->store_status == STORE_OK) {
    +                currentEntry()->lastref = s.timestamp;
    +                currentEntry()->timestamp = s.timestamp;
    +                currentEntry()->expires = s.expires;
    +                currentEntry()->lastmod = s.lastmod;
    +                currentEntry()->flags = s.flags;
    +                currentEntry()->refcount += s.refcount;
    +                sd->dereference(*currentEntry());
    +            } else {
    +                debug_trap("commonUfsDirRebuildFromSwapLog: bad condition");
    +                debug(47, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);
    +            }
    +
    +            continue;
    +        } else if (used) {
    +            /* swapfile in use, not by this URL, log entry is newer */
    +            /* This is sorta bad: the log entry should NOT be newer at this
    +             * point.  If the log is dirty, the filesize check should have
    +             * caught this.  If the log is clean, there should never be a
    +             * newer entry. */
    +            debug(47, 1) ("WARNING: newer swaplog entry for dirno %d, fileno %08X\n",
    +                          sd->index, s.swap_filen);
    +            /* I'm tempted to remove the swapfile here just to be safe,
    +             * but there is a bad race condition in the NOVM version if
    +             * the swapfile has recently been opened for writing, but
    +             * not yet opened for reading.  Because we can't map
    +             * swapfiles back to StoreEntrys, we don't know the state
    +             * of the entry using that file.  */
    +            /* We'll assume the existing entry is valid, probably because
    +             * were in a slow rebuild and the the swap file number got taken
    +             * and the validation procedure hasn't run. */
    +            assert(flags.need_to_validate);
    +            counts.clashcount++;
    +            continue;
    +        } else if (currentEntry() && !disk_entry_newer) {
    +            /* key already exists, current entry is newer */
    +            /* keep old, ignore new */
    +            counts.dupcount++;
    +            continue;
    +        } else if (currentEntry()) {
    +            /* key already exists, this swapfile not being used */
    +            /* junk old, load new */
    +            storeExpireNow(currentEntry());
    +            storeReleaseRequest(currentEntry());
    +
    +            if (currentEntry()->swap_filen > -1) {
    +                UFSSwapDir *sdForThisEntry = dynamic_cast(INDEXSD(currentEntry()->swap_dirn));
    +                sdForThisEntry->replacementRemove(currentEntry());
    +                /* Make sure we don't actually unlink the file */
    +                sdForThisEntry->mapBitReset(currentEntry()->swap_filen);
    +                currentEntry()->swap_filen = -1;
    +                currentEntry()->swap_dirn = -1;
    +            }
    +
    +            storeRelease(currentEntry());
    +            counts.dupcount++;
    +        } else {
    +            /* URL doesnt exist, swapfile not in use */
    +            /* load new */
    +            (void) 0;
    +        }
    +
    +        /* update store_swap_size */
    +        counts.objcount++;
    +
    +        currentEntry(sd->addDiskRestore(s.key,
    +                                        s.swap_filen,
    +                                        s.swap_file_sz,
    +                                        s.expires,
    +                                        s.timestamp,
    +                                        s.lastref,
    +                                        s.lastmod,
    +                                        s.refcount,
    +                                        s.flags,
    +                                        (int) flags.clean));
    +
    +        storeDirSwapLog(currentEntry(), SWAP_LOG_ADD);
         }
    +
         eventAdd("storeRebuild", RebuildFromSwapLog, this, 0.0, 1);
     }
     
    @@ -433,79 +495,105 @@ RebuildState::getNextFile(sfileno * filn_p, int *size)
         int fd = -1;
         int dirs_opened = 0;
         debug(47, 3) ("commonUfsDirGetNextFile: flag=%d, %d: /%02X/%02X\n",
    -	flags.init,
    -	sd->index,
    -	curlvl1,
    -	curlvl2);
    +                  flags.init,
    +                  sd->index,
    +                  curlvl1,
    +                  curlvl2);
    +
         if (done)
    -	return -2;
    +        return -2;
    +
         while (fd < 0 && done == 0) {
    -	fd = -1;
    -	if (0 == flags.init) {	/* initialize, open first file */
    -	    done = 0;
    -	    curlvl1 = 0;
    -	    curlvl2 = 0;
    -	    in_dir = 0;
    -	    flags.init = 1;
    -	    assert(Config.cacheSwap.n_configured > 0);
    -	}
    -	if (0 == in_dir) {	/* we need to read in a new directory */
    -	    snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X",
    -		sd->path,
    -		curlvl1, curlvl2);
    -	    if (dirs_opened)
    -		return -1;
    -	    td = opendir(fullpath);
    -	    dirs_opened++;
    -	    if (td == NULL) {
    -		debug(47, 1) ("commonUfsDirGetNextFile: opendir: %s: %s\n",
    -		    fullpath, xstrerror());
    -	    } else {
    -		entry = readdir(td);	/* skip . and .. */
    -		entry = readdir(td);
    -		if (entry == NULL && errno == ENOENT)
    -		    debug(47, 1) ("commonUfsDirGetNextFile: directory does not exist!.\n");
    -		debug(47, 3) ("commonUfsDirGetNextFile: Directory %s\n", fullpath);
    -	    }
    -	}
    -	if (td != NULL && (entry = readdir(td)) != NULL) {
    -	    in_dir++;
    -	    if (sscanf(entry->d_name, "%x", &fn) != 1) {
    -		debug(47, 3) ("commonUfsDirGetNextFile: invalid %s\n",
    -		    entry->d_name);
    -		continue;
    -	    }
    -	    if (!UFSSwapDir::FilenoBelongsHere(fn, sd->index, curlvl1, curlvl2)) {
    -		debug(47, 3) ("commonUfsDirGetNextFile: %08X does not belong in %d/%d/%d\n",
    -		    fn, sd->index, curlvl1, curlvl2);
    -		continue;
    -	    }
    -	    if (sd->mapBitTest(fn)) {
    -		debug(47, 3) ("commonUfsDirGetNextFile: Locked, continuing with next.\n");
    -		continue;
    -	    }
    -	    snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%s",
    -		fullpath, entry->d_name);
    -	    debug(47, 3) ("commonUfsDirGetNextFile: Opening %s\n", fullfilename);
    -	    fd = file_open(fullfilename, O_RDONLY | O_BINARY);
    -	    if (fd < 0)
    -		debug(47, 1) ("commonUfsDirGetNextFile: %s: %s\n", fullfilename, xstrerror());
    -	    else
    -		store_open_disk_fd++;
    -	    continue;
    -	}
    -	if (td != NULL)
    -	    closedir(td);
    -	td = NULL;
    -	in_dir = 0;
    -	if (sd->validL2(++curlvl2))
    -	    continue;
    -	curlvl2 = 0;
    -	if (sd->validL1(++curlvl1))
    -	    continue;
    -	curlvl1 = 0;
    -	done = 1;
    +        fd = -1;
    +
    +        if (0 == flags.init) {	/* initialize, open first file */
    +            done = 0;
    +            curlvl1 = 0;
    +            curlvl2 = 0;
    +            in_dir = 0;
    +            flags.init = 1;
    +            assert(Config.cacheSwap.n_configured > 0);
    +        }
    +
    +        if (0 == in_dir) {	/* we need to read in a new directory */
    +            snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X",
    +                     sd->path,
    +                     curlvl1, curlvl2);
    +
    +            if (dirs_opened)
    +                return -1;
    +
    +            td = opendir(fullpath);
    +
    +            dirs_opened++;
    +
    +            if (td == NULL) {
    +                debug(47, 1) ("commonUfsDirGetNextFile: opendir: %s: %s\n",
    +                              fullpath, xstrerror());
    +            } else {
    +                entry = readdir(td);	/* skip . and .. */
    +                entry = readdir(td);
    +
    +                if (entry == NULL && errno == ENOENT)
    +                    debug(47, 1) ("commonUfsDirGetNextFile: directory does not exist!.\n");
    +
    +                debug(47, 3) ("commonUfsDirGetNextFile: Directory %s\n", fullpath);
    +            }
    +        }
    +
    +        if (td != NULL && (entry = readdir(td)) != NULL) {
    +            in_dir++;
    +
    +            if (sscanf(entry->d_name, "%x", &fn) != 1) {
    +                debug(47, 3) ("commonUfsDirGetNextFile: invalid %s\n",
    +                              entry->d_name);
    +                continue;
    +            }
    +
    +            if (!UFSSwapDir::FilenoBelongsHere(fn, sd->index, curlvl1, curlvl2)) {
    +                debug(47, 3) ("commonUfsDirGetNextFile: %08X does not belong in %d/%d/%d\n",
    +                              fn, sd->index, curlvl1, curlvl2);
    +                continue;
    +            }
    +
    +            if (sd->mapBitTest(fn)) {
    +                debug(47, 3) ("commonUfsDirGetNextFile: Locked, continuing with next.\n");
    +                continue;
    +            }
    +
    +            snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%s",
    +                     fullpath, entry->d_name);
    +            debug(47, 3) ("commonUfsDirGetNextFile: Opening %s\n", fullfilename);
    +            fd = file_open(fullfilename, O_RDONLY | O_BINARY);
    +
    +            if (fd < 0)
    +                debug(47, 1) ("commonUfsDirGetNextFile: %s: %s\n", fullfilename, xstrerror());
    +            else
    +                store_open_disk_fd++;
    +
    +            continue;
    +        }
    +
    +        if (td != NULL)
    +            closedir(td);
    +
    +        td = NULL;
    +
    +        in_dir = 0;
    +
    +        if (sd->validL2(++curlvl2))
    +            continue;
    +
    +        curlvl2 = 0;
    +
    +        if (sd->validL1(++curlvl1))
    +            continue;
    +
    +        curlvl1 = 0;
    +
    +        done = 1;
         }
    +
         *filn_p = fn;
         return fd;
     }
    diff --git a/src/ufscommon.h b/src/ufscommon.h
    index df07246174..fd1e443ca2 100644
    --- a/src/ufscommon.h
    +++ b/src/ufscommon.h
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: ufscommon.h,v 1.4 2003/01/23 20:59:10 robertc Exp $
    + * $Id: ufscommon.h,v 1.5 2003/02/21 22:50:12 robertc Exp $
      *
      * SQUID Web Proxy Cache          http://www.squid-cache.org/
      * ----------------------------------------------------------
    @@ -45,59 +45,61 @@ FREE storeSwapLogDataFree;
     
     class UFSStrategy;
     
    -class UFSSwapDir : public SwapDir {
    +class UFSSwapDir : public SwapDir
    +{
    +
     public:
    -  static int IsUFSDir(SwapDir* sd);
    -  static int DirClean(int swap_index);
    -  static int FilenoBelongsHere(int fn, int F0, int F1, int F2);
    -
    -  UFSSwapDir();
    -  virtual void init();
    -  virtual void newFileSystem();
    -  virtual void dump(StoreEntry &) const;
    -  ~UFSSwapDir();
    -  virtual bool doubleCheck(StoreEntry &);
    -  virtual void unlink(StoreEntry &) = 0;
    -  virtual void statfs(StoreEntry &)const;
    -  virtual void maintainfs();
    -  virtual int canStore(StoreEntry const &)const = 0;
    -  virtual void reference(StoreEntry &);
    -  virtual void dereference(StoreEntry &);
    -  virtual StoreIOState::Pointer createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
    -  virtual StoreIOState::Pointer openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
    -  virtual void openLog();
    -  virtual void closeLog();
    -  virtual int writeCleanStart();
    -  virtual void writeCleanDone();
    -  virtual void logEntry(const StoreEntry & e, int op) const;
    -  virtual void parse(int index, char *path);
    -  virtual void reconfigure(int, char *);
    -
    -  void unlinkFile(sfileno f);
    -  virtual void unlinkFile (char const *) = 0;
    -  // move down when unlink is a virtual method
    -//protected:
    -  UFSStrategy *IO;
    -  char *fullPath(sfileno, char *) const;
    -  /* temp */
    -  void closeTmpSwapLog();
    -  FILE *openTmpSwapLog(int *clean_flag, int *zero_flag);
    -  char *swapSubDir(int subdirn) const;
    -  int mapBitTest(sfileno filn);
    -  void mapBitReset(sfileno filn);
    -  void mapBitSet(sfileno filn);
    -  StoreEntry *addDiskRestore(const cache_key * key,
    -    sfileno file_number,
    -    size_t swap_file_sz,
    -    time_t expires,
    -    time_t timestamp,
    -    time_t lastref,
    -    time_t lastmod,
    -    u_int32_t refcount,
    -    u_int16_t flags,
    -    int clean);
    -  int validFileno(sfileno filn, int flag) const;
    -  int mapBitAllocate();
    +    static int IsUFSDir(SwapDir* sd);
    +    static int DirClean(int swap_index);
    +    static int FilenoBelongsHere(int fn, int F0, int F1, int F2);
    +
    +    UFSSwapDir();
    +    virtual void init();
    +    virtual void newFileSystem();
    +    virtual void dump(StoreEntry &) const;
    +    ~UFSSwapDir();
    +    virtual bool doubleCheck(StoreEntry &);
    +    virtual void unlink(StoreEntry &) = 0;
    +    virtual void statfs(StoreEntry &)const;
    +    virtual void maintainfs();
    +    virtual int canStore(StoreEntry const &)const = 0;
    +    virtual void reference(StoreEntry &);
    +    virtual void dereference(StoreEntry &);
    +    virtual StoreIOState::Pointer createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
    +    virtual StoreIOState::Pointer openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
    +    virtual void openLog();
    +    virtual void closeLog();
    +    virtual int writeCleanStart();
    +    virtual void writeCleanDone();
    +    virtual void logEntry(const StoreEntry & e, int op) const;
    +    virtual void parse(int index, char *path);
    +    virtual void reconfigure(int, char *);
    +
    +    void unlinkFile(sfileno f);
    +    virtual void unlinkFile (char const *) = 0;
    +    // move down when unlink is a virtual method
    +    //protected:
    +    UFSStrategy *IO;
    +    char *fullPath(sfileno, char *) const;
    +    /* temp */
    +    void closeTmpSwapLog();
    +    FILE *openTmpSwapLog(int *clean_flag, int *zero_flag);
    +    char *swapSubDir(int subdirn) const;
    +    int mapBitTest(sfileno filn);
    +    void mapBitReset(sfileno filn);
    +    void mapBitSet(sfileno filn);
    +    StoreEntry *addDiskRestore(const cache_key * key,
    +                               sfileno file_number,
    +                               size_t swap_file_sz,
    +                               time_t expires,
    +                               time_t timestamp,
    +                               time_t lastref,
    +                               time_t lastmod,
    +                               u_int32_t refcount,
    +                               u_int16_t flags,
    +                               int clean);
    +    int validFileno(sfileno filn, int flag) const;
    +    int mapBitAllocate();
         void *fsdata;
     
         bool validL2(int) const;
    @@ -105,31 +107,35 @@ public:
     
         void replacementAdd(StoreEntry *e);
         void replacementRemove(StoreEntry *e);
    +
     protected:
         fileMap *map;
         int suggest;
         int l1;
         int l2;
    +
     private:
         static int NumberOfUFSDirs;
         static int * UFSDirToGlobalDirMapping;
         bool pathIsDirectory(const char *path)const;
         int swaplog_fd;
    -  static EVH CleanEvent;
    -  void initBitmap();
    -  bool verifyCacheDirs();
    -  void rebuild();
    -  int createDirectory(const char *path, int);
    -  void createSwapSubDirs();
    -  void dumpEntry(StoreEntry &) const;
    -  char *logFile(char const *ext = NULL)const;
    +    static EVH CleanEvent;
    +    void initBitmap();
    +    bool verifyCacheDirs();
    +    void rebuild();
    +    int createDirectory(const char *path, int);
    +    void createSwapSubDirs();
    +    void dumpEntry(StoreEntry &) const;
    +    char *logFile(char const *ext = NULL)const;
     
     };
     
     #include "RefCount.h"
     
    -class IORequestor : public RefCountable{
    -  public:
    +class IORequestor : public RefCountable
    +{
    +
    +public:
         typedef RefCount Pointer;
         virtual void ioCompletedNotification() = 0;
         virtual void closeCompleted() = 0;
    @@ -137,8 +143,10 @@ class IORequestor : public RefCountable{
         virtual void writeCompleted(int errflag, size_t len) = 0;
     };
     
    -class DiskFile : public RefCountable {
    -  public:
    +class DiskFile : public RefCountable
    +{
    +
    +public:
         typedef RefCount Pointer;
         virtual void deleteSelf() const = 0;
         virtual void open (int, mode_t, IORequestor::Pointer) = 0;
    @@ -147,37 +155,46 @@ class DiskFile : public RefCountable {
         virtual void write(char const *buf, size_t size, off_t offset, FREE *free_func) = 0;
         virtual bool canRead() const = 0;
         virtual bool canWrite() const {return true;}
    +
         /* During miogration only */
         virtual int getFD() const {return -1;}
    +
         virtual bool error() const = 0;
     };
     
     /* UFS dir specific IO calls */
    +
     class UFSStrategy
     {
    +
     public:
    -  virtual bool shedLoad() = 0;
    -  virtual void deleteSelf() const = 0;
    -  virtual void openFailed(){}
    -  virtual int load(){return -1;}
    -  virtual StoreIOState::Pointer createState(SwapDir *, StoreEntry *, STIOCB *, void *)const = 0;
    -  /* UFS specific */
    -  virtual DiskFile::Pointer newFile (char const *path) = 0;
    -  StoreIOState::Pointer open(SwapDir *, StoreEntry *, STFNCB *,
    -    STIOCB *, void *);
    -  StoreIOState::Pointer create(SwapDir *, StoreEntry *, STFNCB *,
    -    STIOCB *, void *);
    -  /* virtual void strategyStats(StoreEntry *sentry) const = 0; */
    -  /* virtual void dumpCacheDirParams(StoreEntry * e, const char *option) const = 0; */
    +    virtual bool shedLoad() = 0;
    +    virtual void deleteSelf() const = 0;
    +    virtual void openFailed(){}
    +
    +    virtual int load(){return -1;}
    +
    +    virtual StoreIOState::Pointer createState(SwapDir *, StoreEntry *, STIOCB *, void *)const = 0;
    +    /* UFS specific */
    +    virtual DiskFile::Pointer newFile (char const *path) = 0;
    +    StoreIOState::Pointer open(SwapDir *, StoreEntry *, STFNCB *,
    +                               STIOCB *, void *);
    +    StoreIOState::Pointer create(SwapDir *, StoreEntry *, STFNCB *,
    +                                 STIOCB *, void *);
    +    /* virtual void strategyStats(StoreEntry *sentry) const = 0; */
    +    /* virtual void dumpCacheDirParams(StoreEntry * e, const char *option) const = 0; */
     };
     
     /* Common ufs-store-dir logic */
    -class UFSStoreState : public storeIOState, public IORequestor {
    -  public:
    +
    +class UFSStoreState : public storeIOState, public IORequestor
    +{
    +
    +public:
         virtual void deleteSelf() const = 0;
         UFSStoreState();
         ~UFSStoreState();
    -// protected:
    +    // protected:
         DiskFile::Pointer theFile;
         bool opening;
         bool creating;
    @@ -186,30 +203,40 @@ class UFSStoreState : public storeIOState, public IORequestor {
         bool writing;
         void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data);
         void write(char const *buf, size_t size, off_t offset, FREE * free_func);
    -  protected:
    -    class _queued_read {
    -      public:
    -	void *operator new(size_t);
    -	void operator delete (void *);
    -	char *buf;
    -	size_t size;
    -	off_t offset;
    -	STRCB *callback;
    -	void *callback_data;
    -      private:
    -	static MemPool *Pool;
    +
    +protected:
    +
    +    class _queued_read
    +    {
    +
    +    public:
    +        void *operator new(size_t);
    +        void operator delete (void *);
    +        char *buf;
    +        size_t size;
    +        off_t offset;
    +        STRCB *callback;
    +        void *callback_data;
    +
    +    private:
    +        static MemPool *Pool;
         };
    -    class _queued_write {
    -      public:
    -	void *operator new(size_t);
    -	void operator delete (void *);
    -	char const *buf;
    -	size_t size;
    -	off_t offset;
    -	FREE *free_func;
    -      private:
    -	static MemPool *Pool;
    +
    +    class _queued_write
    +    {
    +
    +    public:
    +        void *operator new(size_t);
    +        void operator delete (void *);
    +        char const *buf;
    +        size_t size;
    +        off_t offset;
    +        FREE *free_func;
    +
    +    private:
    +        static MemPool *Pool;
         };
    +
         link_list *pending_reads;
         link_list *pending_writes;
         void queueRead(char *, size_t, off_t, STRCB *, void *);
    @@ -219,7 +246,9 @@ class UFSStoreState : public storeIOState, public IORequestor {
         char *read_buf;
     };
     
    -class RebuildState : public RefCountable {
    +class RebuildState : public RefCountable
    +{
    +
     public:
         void *operator new(size_t);
         void operator delete(void *);
    @@ -235,19 +264,32 @@ public:
         int speed;
         int curlvl1;
         int curlvl2;
    -    struct {
    -	unsigned int need_to_validate:1;
    -	unsigned int clean:1;
    -	unsigned int init:1;
    -    } flags;
    +
    +    struct
    +    {
    +
    +unsigned int need_to_validate:
    +        1;
    +
    +unsigned int clean:
    +        1;
    +
    +unsigned int init:
    +        1;
    +    }
    +
    +    flags;
         int done;
         int in_dir;
         int fn;
    +
         struct dirent *entry;
         DIR *td;
         char fullpath[SQUID_MAXPATHLEN];
         char fullfilename[SQUID_MAXPATHLEN];
    +
         struct _store_rebuild_data counts;
    +
     private:
         CBDATA_CLASS(RebuildState);
         void rebuildFromDirectory();
    diff --git a/src/ufsdump.cc b/src/ufsdump.cc
    index 454fdbb4a3..cd8e75a809 100644
    --- a/src/ufsdump.cc
    +++ b/src/ufsdump.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: ufsdump.cc,v 1.1 2003/01/23 00:37:27 robertc Exp $
    + * $Id: ufsdump.cc,v 1.2 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 0     UFS Store Dump
      * AUTHOR: Robert Collins
    @@ -55,17 +55,21 @@ struct DumpStoreMeta : public unary_function
         void operator()(StoreMeta const &x)
         {
             switch (x.getType()) {
    -            case STORE_META_KEY:
    -	        std::cout << "MD5: " << storeKeyText((const cache_key *)x.value) << std::endl;
    -                break;
    -            case STORE_META_STD:
    -                break;
    -            case STORE_META_URL:
    -                assert (((char *)x.value)[x.length - 1] == 0);
    -                std::cout << "URL: " << (char *)x.value << std::endl;
    -            default:
    -                break;
    -            }
    +
    +        case STORE_META_KEY:
    +            std::cout << "MD5: " << storeKeyText((const cache_key *)x.value) << std::endl;
    +            break;
    +
    +        case STORE_META_STD:
    +            break;
    +
    +        case STORE_META_URL:
    +            assert (((char *)x.value)[x.length - 1] == 0);
    +            std::cout << "URL: " << (char *)x.value << std::endl;
    +
    +        default:
    +            break;
    +        }
         }
     };
     
    @@ -109,8 +113,9 @@ main(int argc, char *argv[])
     
             memset(&anEntry, '\0', sizeof(StoreEntry));
     
    -	DumpStoreMeta dumper;
    -	for_each(*metadata, dumper);
    +        DumpStoreMeta dumper;
    +
    +        for_each(*metadata, dumper);
     
     
             return 0;
    diff --git a/src/unlinkd.cc b/src/unlinkd.cc
    index 19aee3f011..cb78da6acd 100644
    --- a/src/unlinkd.cc
    +++ b/src/unlinkd.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: unlinkd.cc,v 1.51 2003/02/14 15:37:43 wessels Exp $
    + * $Id: unlinkd.cc,v 1.52 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 2     Unlink Daemon
      * AUTHOR: Duane Wessels
    @@ -51,19 +51,27 @@ main(int argc, char *argv[])
         setbuf(stdout, NULL);
         close(2);
         open("/dev/null", O_RDWR);
    +
         while (fgets(buf, UNLINK_BUF_LEN, stdin)) {
    -	if ((t = strchr(buf, '\n')))
    -	    *t = '\0';
    +        if ((t = strchr(buf, '\n')))
    +            *t = '\0';
    +
     #if USE_TRUNCATE
    -	x = truncate(buf, 0);
    +
    +        x = truncate(buf, 0);
    +
     #else
    -	x = unlink(buf);
    +
    +        x = unlink(buf);
    +
     #endif
    -	if (x < 0)
    -	    printf("ERR\n");
    -	else
    -	    printf("OK\n");
    +
    +        if (x < 0)
    +            printf("ERR\n");
    +        else
    +            printf("OK\n");
         }
    +
         exit(0);
     }
     
    @@ -85,67 +93,77 @@ unlinkdUnlink(const char *path)
         int l;
         int x;
         static int queuelen = 0;
    +
         if (unlinkd_wfd < 0) {
    -	debug_trap("unlinkdUnlink: unlinkd_wfd < 0");
    -	safeunlink(path, 0);
    -	return;
    +        debug_trap("unlinkdUnlink: unlinkd_wfd < 0");
    +        safeunlink(path, 0);
    +        return;
         }
    +
         /*
    -     * If the queue length is greater than our limit, then
    -     * we pause for up to 100ms, hoping that unlinkd
    -     * has some feedback for us.  Maybe it just needs a slice
    -     * of the CPU's time.
    -     */
    +    * If the queue length is greater than our limit, then
    +    * we pause for up to 100ms, hoping that unlinkd
    +    * has some feedback for us.  Maybe it just needs a slice
    +    * of the CPU's time.
    +    */
         if (queuelen >= UNLINKD_QUEUE_LIMIT) {
    -	struct timeval to;
    -	fd_set R;
    -	FD_ZERO(&R);
    -	FD_SET(unlinkd_rfd, &R);
    -	to.tv_sec = 0;
    -	to.tv_usec = 100000;
    -	select(unlinkd_rfd + 1, &R, NULL, NULL, &to);
    +
    +        struct timeval to;
    +        fd_set R;
    +        FD_ZERO(&R);
    +        FD_SET(unlinkd_rfd, &R);
    +        to.tv_sec = 0;
    +        to.tv_usec = 100000;
    +        select(unlinkd_rfd + 1, &R, NULL, NULL, &to);
         }
    +
         /*
    -     * If there is at least one outstanding unlink request, then
    -     * try to read a response.  If there's nothing to read we'll
    -     * get an EWOULDBLOCK or whatever.  If we get a response, then
    -     * decrement the queue size by the number of newlines read.
    -     */
    +    * If there is at least one outstanding unlink request, then
    +    * try to read a response.  If there's nothing to read we'll
    +    * get an EWOULDBLOCK or whatever.  If we get a response, then
    +    * decrement the queue size by the number of newlines read.
    +    */
         if (queuelen > 0) {
    -	int x;
    -	int i;
    -	char rbuf[512];
    -	x = read(unlinkd_rfd, rbuf, 511);
    -	if (x > 0) {
    -	    rbuf[x] = '\0';
    -	    for (i = 0; i < x; i++)
    -		if ('\n' == rbuf[i])
    -		    queuelen--;
    -	    assert(queuelen >= 0);
    -	}
    +        int x;
    +        int i;
    +        char rbuf[512];
    +        x = read(unlinkd_rfd, rbuf, 511);
    +
    +        if (x > 0) {
    +            rbuf[x] = '\0';
    +
    +            for (i = 0; i < x; i++)
    +                if ('\n' == rbuf[i])
    +                    queuelen--;
    +
    +            assert(queuelen >= 0);
    +        }
         }
    +
         l = strlen(path);
         assert(l < MAXPATHLEN);
         xstrncpy(buf, path, MAXPATHLEN);
         buf[l++] = '\n';
         x = write(unlinkd_wfd, buf, l);
    +
         if (x < 0) {
    -	debug(2, 1) ("unlinkdUnlink: write FD %d failed: %s\n",
    -	    unlinkd_wfd, xstrerror());
    -	safeunlink(path, 0);
    -	return;
    +        debug(2, 1) ("unlinkdUnlink: write FD %d failed: %s\n",
    +                     unlinkd_wfd, xstrerror());
    +        safeunlink(path, 0);
    +        return;
         } else if (x != l) {
    -	debug(2, 1) ("unlinkdUnlink: FD %d only wrote %d of %d bytes\n",
    -	    unlinkd_wfd, x, l);
    -	safeunlink(path, 0);
    -	return;
    +        debug(2, 1) ("unlinkdUnlink: FD %d only wrote %d of %d bytes\n",
    +                     unlinkd_wfd, x, l);
    +        safeunlink(path, 0);
    +        return;
         }
    +
         statCounter.unlink.requests++;
         /*
    -     * Increment this syscalls counter here, even though the syscall
    -     * is executed by the helper process.  We try to be consistent
    -     * in counting unlink operations.
    -     */
    +    * Increment this syscalls counter here, even though the syscall
    +    * is executed by the helper process.  We try to be consistent
    +    * in counting unlink operations.
    +    */
         statCounter.syscalls.disk.unlinks++;
         queuelen++;
     }
    @@ -154,12 +172,17 @@ void
     unlinkdClose(void)
     {
         if (unlinkd_wfd < 0)
    -	return;
    +        return;
    +
         debug(2, 1) ("Closing unlinkd pipe on FD %d\n", unlinkd_wfd);
    +
         file_close(unlinkd_wfd);
    +
         if (unlinkd_wfd != unlinkd_rfd)
    -	file_close(unlinkd_rfd);
    +        file_close(unlinkd_rfd);
    +
         unlinkd_wfd = -1;
    +
         unlinkd_rfd = -1;
     }
     
    @@ -168,6 +191,7 @@ unlinkdInit(void)
     {
         int x;
         const char *args[2];
    +
         struct timeval slp;
         args[0] = "(unlinkd)";
         args[1] = NULL;
    @@ -175,16 +199,17 @@ unlinkdInit(void)
         /* pipes and poll() don't get along on DUNIX -DW */
         x = ipcCreate(IPC_STREAM,
     #else
    -    /* We currently need to use FIFO.. see below */
    -    x = ipcCreate(IPC_FIFO,
    +/* We currently need to use FIFO.. see below */
    +x = ipcCreate(IPC_FIFO,
     #endif
    -	Config.Program.unlinkd,
    -	args,
    -	"unlinkd",
    -	&unlinkd_rfd,
    -	&unlinkd_wfd);
    +                  Config.Program.unlinkd,
    +                  args,
    +                  "unlinkd",
    +                  &unlinkd_rfd,
    +                  &unlinkd_wfd);
    +
         if (x < 0)
    -	fatal("Failed to create unlinkd subprocess");
    +        fatal("Failed to create unlinkd subprocess");
         slp.tv_sec = 0;
         slp.tv_usec = 250000;
         select(0, NULL, NULL, NULL, &slp);
    @@ -193,15 +218,15 @@ unlinkdInit(void)
         commSetTimeout(unlinkd_rfd, -1, NULL, NULL);
         commSetTimeout(unlinkd_wfd, -1, NULL, NULL);
         /*
    -     * unlinkd_rfd should already be non-blocking because of
    -     * ipcCreate.  We change unlinkd_wfd to blocking mode because
    -     * we never want to lose an unlink request, and we don't have
    -     * code to retry if we get EWOULDBLOCK.  Unfortunately, we can
    -     * do this only for the IPC_FIFO case.
    -     */
    +    * unlinkd_rfd should already be non-blocking because of
    +    * ipcCreate.  We change unlinkd_wfd to blocking mode because
    +    * we never want to lose an unlink request, and we don't have
    +    * code to retry if we get EWOULDBLOCK.  Unfortunately, we can
    +    * do this only for the IPC_FIFO case.
    +    */
         assert(fd_table[unlinkd_rfd].flags.nonblocking);
         if (FD_PIPE == fd_table[unlinkd_wfd].type)
    -	commUnsetNonBlocking(unlinkd_wfd);
    +        commUnsetNonBlocking(unlinkd_wfd);
         debug(2, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd);
     }
     
    diff --git a/src/url.cc b/src/url.cc
    index 1b381dc649..cf9833f504 100644
    --- a/src/url.cc
    +++ b/src/url.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: url.cc,v 1.142 2003/01/23 00:37:29 robertc Exp $
    + * $Id: url.cc,v 1.143 2003/02/21 22:50:12 robertc Exp $
      *
      * DEBUG: section 23    URL Parsing
      * AUTHOR: Duane Wessels
    @@ -37,90 +37,91 @@
     #include "HttpRequest.h"
     
     const char *RequestMethodStr[] =
    -{
    -    "NONE",
    -    "GET",
    -    "POST",
    -    "PUT",
    -    "HEAD",
    -    "CONNECT",
    -    "TRACE",
    -    "PURGE",
    -    "OPTIONS",
    -    "DELETE",
    -    "PROPFIND",
    -    "PROPPATCH",
    -    "MKCOL",
    -    "COPY",
    -    "MOVE",
    -    "LOCK",
    -    "UNLOCK",
    -    "BMOVE",
    -    "BDELETE",
    -    "BPROPFIND",
    -    "BPROPPATCH",
    -    "BCOPY",
    -    "SEARCH",
    -    "SUBSCRIBE",
    -    "UNSUBSCRIBE",
    -    "POLL",
    -    "%EXT00",
    -    "%EXT01",
    -    "%EXT02",
    -    "%EXT03",
    -    "%EXT04",
    -    "%EXT05",
    -    "%EXT06",
    -    "%EXT07",
    -    "%EXT08",
    -    "%EXT09",
    -    "%EXT10",
    -    "%EXT11",
    -    "%EXT12",
    -    "%EXT13",
    -    "%EXT14",
    -    "%EXT15",
    -    "%EXT16",
    -    "%EXT17",
    -    "%EXT18",
    -    "%EXT19",
    -    "ERROR"
    -};
    +    {
    +        "NONE",
    +        "GET",
    +        "POST",
    +        "PUT",
    +        "HEAD",
    +        "CONNECT",
    +        "TRACE",
    +        "PURGE",
    +        "OPTIONS",
    +        "DELETE",
    +        "PROPFIND",
    +        "PROPPATCH",
    +        "MKCOL",
    +        "COPY",
    +        "MOVE",
    +        "LOCK",
    +        "UNLOCK",
    +        "BMOVE",
    +        "BDELETE",
    +        "BPROPFIND",
    +        "BPROPPATCH",
    +        "BCOPY",
    +        "SEARCH",
    +        "SUBSCRIBE",
    +        "UNSUBSCRIBE",
    +        "POLL",
    +        "%EXT00",
    +        "%EXT01",
    +        "%EXT02",
    +        "%EXT03",
    +        "%EXT04",
    +        "%EXT05",
    +        "%EXT06",
    +        "%EXT07",
    +        "%EXT08",
    +        "%EXT09",
    +        "%EXT10",
    +        "%EXT11",
    +        "%EXT12",
    +        "%EXT13",
    +        "%EXT14",
    +        "%EXT15",
    +        "%EXT16",
    +        "%EXT17",
    +        "%EXT18",
    +        "%EXT19",
    +        "ERROR"
    +    };
     
     const char *ProtocolStr[] =
    -{
    -    "NONE",
    -    "http",
    -    "ftp",
    -    "gopher",
    -    "wais",
    -    "cache_object",
    -    "icp",
    +    {
    +        "NONE",
    +        "http",
    +        "ftp",
    +        "gopher",
    +        "wais",
    +        "cache_object",
    +        "icp",
     #if USE_HTCP
    -    "htcp",
    +        "htcp",
     #endif
    -    "urn",
    -    "whois",
    -    "internal",
    -    "https",
    -    "TOTAL"
    -};
    +        "urn",
    +        "whois",
    +        "internal",
    +        "https",
    +        "TOTAL"
    +    };
     
     static request_t *urnParse(method_t method, char *urn);
     #if CHECK_HOSTNAMES
     static const char *const valid_hostname_chars =
     #if ALLOW_HOSTNAME_UNDERSCORES
    -"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    -"abcdefghijklmnopqrstuvwxyz"
    -"0123456789-._";
    +    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    +    "abcdefghijklmnopqrstuvwxyz"
    +    "0123456789-._";
     #else
    -"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    -"abcdefghijklmnopqrstuvwxyz"
    -"0123456789-.";
    +    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    +    "abcdefghijklmnopqrstuvwxyz"
    +    "0123456789-."
    +    ;
     #endif
     #endif /* CHECK_HOSTNAMES */
     
    -/* convert %xx in url string to a character 
    +/* convert %xx in url string to a character
      * Allocate a new string and return a pointer to converted string */
     
     char *
    @@ -131,20 +132,24 @@ url_convert_hex(char *org_url, int allocate)
         char *s = NULL;
         char *t = NULL;
         url = allocate ? (char *) xstrdup(org_url) : org_url;
    +
         if ((int) strlen(url) < 3 || !strchr(url, '%'))
    -	return url;
    +        return url;
    +
         for (s = t = url; *s; s++) {
    -	if (*s == '%' && *(s + 1) && *(s + 2)) {
    -	    code[0] = *(++s);
    -	    code[1] = *(++s);
    -	    *t++ = (char) strtol(code, NULL, 16);
    -	} else {
    -	    *t++ = *s;
    -	}
    +        if (*s == '%' && *(s + 1) && *(s + 2)) {
    +            code[0] = *(++s);
    +            code[1] = *(++s);
    +            *t++ = (char) strtol(code, NULL, 16);
    +        } else {
    +            *t++ = *s;
    +        }
         }
    +
         do {
    -	*t++ = *s;
    +        *t++ = *s;
         } while (*s++);
    +
         return url;
     }
     
    @@ -193,12 +198,15 @@ urlParseMethod(const char *s)
          * match one of the extension method placeholders,
          * which have the form %EXT[0-9][0-9]
          */
    +
         if (*s == '%')
    -	return METHOD_NONE;
    +        return METHOD_NONE;
    +
         for (++method; method < METHOD_ENUM_END; ++method) {
    -	if (0 == strcasecmp(s, RequestMethodStr[method]))
    -	    return method;
    +        if (0 == strcasecmp(s, RequestMethodStr[method]))
    +            return method;
         }
    +
         return METHOD_NONE;
     }
     
    @@ -207,26 +215,37 @@ protocol_t
     urlParseProtocol(const char *s)
     {
         /* test common stuff first */
    +
         if (strcasecmp(s, "http") == 0)
    -	return PROTO_HTTP;
    +        return PROTO_HTTP;
    +
         if (strcasecmp(s, "ftp") == 0)
    -	return PROTO_FTP;
    +        return PROTO_FTP;
    +
         if (strcasecmp(s, "https") == 0)
    -	return PROTO_HTTPS;
    +        return PROTO_HTTPS;
    +
         if (strcasecmp(s, "file") == 0)
    -	return PROTO_FTP;
    +        return PROTO_FTP;
    +
         if (strcasecmp(s, "gopher") == 0)
    -	return PROTO_GOPHER;
    +        return PROTO_GOPHER;
    +
         if (strcasecmp(s, "wais") == 0)
    -	return PROTO_WAIS;
    +        return PROTO_WAIS;
    +
         if (strcasecmp(s, "cache_object") == 0)
    -	return PROTO_CACHEOBJ;
    +        return PROTO_CACHEOBJ;
    +
         if (strcasecmp(s, "urn") == 0)
    -	return PROTO_URN;
    +        return PROTO_URN;
    +
         if (strcasecmp(s, "whois") == 0)
    -	return PROTO_WHOIS;
    +        return PROTO_WHOIS;
    +
         if (strcasecmp(s, "internal") == 0)
    -	return PROTO_INTERNAL;
    +        return PROTO_INTERNAL;
    +
         return PROTO_NONE;
     }
     
    @@ -235,23 +254,32 @@ int
     urlDefaultPort(protocol_t p)
     {
         switch (p) {
    +
         case PROTO_HTTP:
    -	return 80;
    +        return 80;
    +
         case PROTO_HTTPS:
    -	return 443;
    +        return 443;
    +
         case PROTO_FTP:
    -	return 21;
    +        return 21;
    +
         case PROTO_GOPHER:
    -	return 70;
    +        return 70;
    +
         case PROTO_WAIS:
    -	return 210;
    +        return 210;
    +
         case PROTO_CACHEOBJ:
    +
         case PROTO_INTERNAL:
    -	return CACHE_HTTP_PORT;
    +        return CACHE_HTTP_PORT;
    +
         case PROTO_WHOIS:
    -	return 43;
    +        return 43;
    +
         default:
    -	return 0;
    +        return 0;
         }
     }
     
    @@ -271,101 +299,132 @@ urlParse(method_t method, char *url)
         proto[0] = host[0] = urlpath[0] = login[0] = '\0';
     
         if ((l = strlen(url)) + Config.appendDomainLen > (MAX_URL - 1)) {
    -	/* terminate so it doesn't overflow other buffers */
    -	*(url + (MAX_URL >> 1)) = '\0';
    -	debug(23, 1) ("urlParse: URL too large (%d bytes)\n", l);
    -	return NULL;
    +        /* terminate so it doesn't overflow other buffers */
    +        *(url + (MAX_URL >> 1)) = '\0';
    +        debug(23, 1) ("urlParse: URL too large (%d bytes)\n", l);
    +        return NULL;
         }
    +
         if (method == METHOD_CONNECT) {
    -	port = CONNECT_PORT;
    -	if (sscanf(url, "%[^:]:%d", host, &port) < 1)
    -	    return NULL;
    +        port = CONNECT_PORT;
    +
    +        if (sscanf(url, "%[^:]:%d", host, &port) < 1)
    +            return NULL;
         } else if (!strncmp(url, "urn:", 4)) {
    -	return urnParse(method, url);
    +        return urnParse(method, url);
         } else {
    -	if (sscanf(url, "%[^:]://%[^/]%[^\r\n]", proto, host, urlpath) < 2)
    -	    return NULL;
    -	protocol = urlParseProtocol(proto);
    -	port = urlDefaultPort(protocol);
    -	/* Is there any login informaiton? */
    -	if ((t = strrchr(host, '@'))) {
    -	    strcpy((char *) login, (char *) host);
    -	    t = strrchr(login, '@');
    -	    *t = 0;
    -	    strcpy((char *) host, t + 1);
    -	}
    -	if ((t = strrchr(host, ':'))) {
    -	    *t++ = '\0';
    -	    if (*t != '\0')
    -		port = atoi(t);
    -	}
    +        if (sscanf(url, "%[^:]://%[^/]%[^\r\n]", proto, host, urlpath) < 2)
    +            return NULL;
    +
    +        protocol = urlParseProtocol(proto);
    +
    +        port = urlDefaultPort(protocol);
    +
    +        /* Is there any login informaiton? */
    +        if ((t = strrchr(host, '@'))) {
    +            strcpy((char *) login, (char *) host);
    +            t = strrchr(login, '@');
    +            *t = 0;
    +            strcpy((char *) host, t + 1);
    +        }
    +
    +        if ((t = strrchr(host, ':'))) {
    +            *t++ = '\0';
    +
    +            if (*t != '\0')
    +                port = atoi(t);
    +        }
         }
    +
         for (t = host; *t; t++)
    -	*t = xtolower(*t);
    +        *t = xtolower(*t);
    +
         if (stringHasWhitespace(host)) {
    -	if (URI_WHITESPACE_STRIP == Config.uri_whitespace) {
    -	    t = q = host;
    -	    while (*t) {
    -		if (!xisspace(*t))
    -		    *q++ = *t;
    -		t++;
    -	    }
    -	    *q = '\0';
    -	}
    +        if (URI_WHITESPACE_STRIP == Config.uri_whitespace) {
    +            t = q = host;
    +
    +            while (*t) {
    +                if (!xisspace(*t))
    +                    *q++ = *t;
    +
    +                t++;
    +            }
    +
    +            *q = '\0';
    +        }
         }
    +
     #if CHECK_HOSTNAMES
         if (Config.onoff.check_hostnames && strspn(host, valid_hostname_chars) != strlen(host)) {
    -	debug(23, 1) ("urlParse: Illegal character in hostname '%s'\n", host);
    -	return NULL;
    +        debug(23, 1) ("urlParse: Illegal character in hostname '%s'\n", host);
    +        return NULL;
         }
    +
     #endif
     #if DONT_DO_THIS_IT_BREAKS_SEMANTIC_TRANSPARENCY
         /* remove trailing dots from hostnames */
         while ((l = strlen(host)) > 0 && host[--l] == '.')
    -	host[l] = '\0';
    +        host[l] = '\0';
    +
         /* remove duplicate dots */
         while ((t = strstr(host, "..")))
    -	xmemmove(t, t + 1, strlen(t));
    +        xmemmove(t, t + 1, strlen(t));
    +
     #endif
    +
         if (Config.appendDomain && !strchr(host, '.'))
    -	strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN);
    +        strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN);
    +
         if (port < 1 || port > 65535) {
    -	debug(23, 3) ("urlParse: Invalid port '%d'\n", port);
    -	return NULL;
    +        debug(23, 3) ("urlParse: Invalid port '%d'\n", port);
    +        return NULL;
         }
    +
     #ifdef HARDCODE_DENY_PORTS
         /* These ports are filtered in the default squid.conf, but
          * maybe someone wants them hardcoded... */
         if (port == 7 || port == 9 || port == 19) {
    -	debug(23, 0) ("urlParse: Deny access to port %d\n", port);
    -	return NULL;
    +        debug(23, 0) ("urlParse: Deny access to port %d\n", port);
    +        return NULL;
         }
    +
     #endif
         if (stringHasWhitespace(urlpath)) {
    -	debug(23, 2) ("urlParse: URI has whitespace: {%s}\n", url);
    -	switch (Config.uri_whitespace) {
    -	case URI_WHITESPACE_DENY:
    -	    return NULL;
    -	case URI_WHITESPACE_ALLOW:
    -	    break;
    -	case URI_WHITESPACE_ENCODE:
    -	    t = rfc1738_escape_unescaped(urlpath);
    -	    xstrncpy(urlpath, t, MAX_URL);
    -	    break;
    -	case URI_WHITESPACE_CHOP:
    -	    *(urlpath + strcspn(urlpath, w_space)) = '\0';
    -	    break;
    -	case URI_WHITESPACE_STRIP:
    -	default:
    -	    t = q = urlpath;
    -	    while (*t) {
    -		if (!xisspace(*t))
    -		    *q++ = *t;
    -		t++;
    -	    }
    -	    *q = '\0';
    -	}
    +        debug(23, 2) ("urlParse: URI has whitespace: {%s}\n", url);
    +
    +        switch (Config.uri_whitespace) {
    +
    +        case URI_WHITESPACE_DENY:
    +            return NULL;
    +
    +        case URI_WHITESPACE_ALLOW:
    +            break;
    +
    +        case URI_WHITESPACE_ENCODE:
    +            t = rfc1738_escape_unescaped(urlpath);
    +            xstrncpy(urlpath, t, MAX_URL);
    +            break;
    +
    +        case URI_WHITESPACE_CHOP:
    +            *(urlpath + strcspn(urlpath, w_space)) = '\0';
    +            break;
    +
    +        case URI_WHITESPACE_STRIP:
    +
    +        default:
    +            t = q = urlpath;
    +
    +            while (*t) {
    +                if (!xisspace(*t))
    +                    *q++ = *t;
    +
    +                t++;
    +            }
    +
    +            *q = '\0';
    +        }
         }
    +
         request = requestCreate(method, protocol, urlpath);
         xstrncpy(request->host, host, SQUIDHOSTNAMELEN);
         xstrncpy(request->login, login, MAX_LOGIN_SZ);
    @@ -385,29 +444,37 @@ urlCanonical(request_t * request)
     {
         LOCAL_ARRAY(char, portbuf, 32);
         LOCAL_ARRAY(char, urlbuf, MAX_URL);
    +
         if (request->canonical)
    -	return request->canonical;
    +        return request->canonical;
    +
         if (request->protocol == PROTO_URN) {
    -	snprintf(urlbuf, MAX_URL, "urn:%s", request->urlpath.buf());
    +        snprintf(urlbuf, MAX_URL, "urn:%s", request->urlpath.buf());
         } else {
    -	switch (request->method) {
    -	case METHOD_CONNECT:
    -	    snprintf(urlbuf, MAX_URL, "%s:%d", request->host, request->port);
    -	    break;
    -	default:
    -	    portbuf[0] = '\0';
    -	    if (request->port != urlDefaultPort(request->protocol))
    -		snprintf(portbuf, 32, ":%d", request->port);
    -	    snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s%s",
    -		ProtocolStr[request->protocol],
    -		request->login,
    -		*request->login ? "@" : null_string,
    -		request->host,
    -		portbuf,
    -		request->urlpath.buf());
    -	    break;
    -	}
    +        switch (request->method) {
    +
    +        case METHOD_CONNECT:
    +            snprintf(urlbuf, MAX_URL, "%s:%d", request->host, request->port);
    +            break;
    +
    +        default:
    +            portbuf[0] = '\0';
    +
    +            if (request->port != urlDefaultPort(request->protocol))
    +                snprintf(portbuf, 32, ":%d", request->port);
    +
    +            snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s%s",
    +                     ProtocolStr[request->protocol],
    +                     request->login,
    +                     *request->login ? "@" : null_string,
    +                     request->host,
    +                     portbuf,
    +                     request->urlpath.buf());
    +
    +            break;
    +        }
         }
    +
         return (request->canonical = xstrdup(urlbuf));
     }
     
    @@ -418,41 +485,54 @@ urlCanonicalClean(const request_t * request)
         LOCAL_ARRAY(char, portbuf, 32);
         LOCAL_ARRAY(char, loginbuf, MAX_LOGIN_SZ + 1);
         char *t;
    +
         if (request->protocol == PROTO_URN) {
    -	snprintf(buf, MAX_URL, "urn:%s", request->urlpath.buf());
    +        snprintf(buf, MAX_URL, "urn:%s", request->urlpath.buf());
         } else {
    -	switch (request->method) {
    -	case METHOD_CONNECT:
    -	    snprintf(buf, MAX_URL, "%s:%d", request->host, request->port);
    -	    break;
    -	default:
    -	    portbuf[0] = '\0';
    -	    if (request->port != urlDefaultPort(request->protocol))
    -		snprintf(portbuf, 32, ":%d", request->port);
    -	    loginbuf[0] = '\0';
    -	    if ((int) strlen(request->login) > 0) {
    -		strcpy(loginbuf, request->login);
    -		if ((t = strchr(loginbuf, ':')))
    -		    *t = '\0';
    -		strcat(loginbuf, "@");
    -	    }
    -	    snprintf(buf, MAX_URL, "%s://%s%s%s%s",
    -		ProtocolStr[request->protocol],
    -		loginbuf,
    -		request->host,
    -		portbuf,
    -		request->urlpath.buf());
    -	    /*
    -	     * strip arguments AFTER a question-mark
    -	     */
    -	    if (Config.onoff.strip_query_terms)
    -		if ((t = strchr(buf, '?')))
    -		    *(++t) = '\0';
    -	    break;
    -	}
    +        switch (request->method) {
    +
    +        case METHOD_CONNECT:
    +            snprintf(buf, MAX_URL, "%s:%d", request->host, request->port);
    +            break;
    +
    +        default:
    +            portbuf[0] = '\0';
    +
    +            if (request->port != urlDefaultPort(request->protocol))
    +                snprintf(portbuf, 32, ":%d", request->port);
    +
    +            loginbuf[0] = '\0';
    +
    +            if ((int) strlen(request->login) > 0) {
    +                strcpy(loginbuf, request->login);
    +
    +                if ((t = strchr(loginbuf, ':')))
    +                    *t = '\0';
    +
    +                strcat(loginbuf, "@");
    +            }
    +
    +            snprintf(buf, MAX_URL, "%s://%s%s%s%s",
    +                     ProtocolStr[request->protocol],
    +                     loginbuf,
    +                     request->host,
    +                     portbuf,
    +                     request->urlpath.buf());
    +            /*
    +             * strip arguments AFTER a question-mark
    +             */
    +
    +            if (Config.onoff.strip_query_terms)
    +                if ((t = strchr(buf, '?')))
    +                    *(++t) = '\0';
    +
    +            break;
    +        }
         }
    +
         if (stringHasCntl(buf))
    -	xstrncpy(buf, rfc1738_escape_unescaped(buf), MAX_URL);
    +        xstrncpy(buf, rfc1738_escape_unescaped(buf), MAX_URL);
    +
         return buf;
     }
     
    @@ -483,47 +563,56 @@ matchDomainName(const char *h, const char *d)
     {
         int dl;
         int hl;
    +
         while ('.' == *h)
    -	h++;
    +        h++;
    +
         hl = strlen(h);
    +
         dl = strlen(d);
    +
         /*
          * Start at the ends of the two strings and work towards the
          * beginning.
          */
         while (xtolower(h[--hl]) == xtolower(d[--dl])) {
    -	if (hl == 0 && dl == 0) {
    -	    /*
    -	     * We made it all the way to the beginning of both
    -	     * strings without finding any difference.
    -	     */
    -	    return 0;
    -	}
    -	if (0 == hl) {
    -	    /* 
    -	     * The host string is shorter than the domain string.
    -	     * There is only one case when this can be a match.
    -	     * If the domain is just one character longer, and if
    -	     * that character is a leading '.' then we call it a
    -	     * match.
    -	     */
    -	    if (1 == dl && '.' == d[0])
    -		return 0;
    -	    else
    -		return -1;
    -	}
    -	if (0 == dl) {
    -	    /*
    -	     * The domain string is shorter than the host string.
    -	     * This is a match only if the first domain character
    -	     * is a leading '.'.
    -	     */
    -	    if ('.' == d[0])
    -		return 0;
    -	    else
    -		return 1;
    -	}
    +        if (hl == 0 && dl == 0) {
    +            /*
    +             * We made it all the way to the beginning of both
    +             * strings without finding any difference.
    +             */
    +            return 0;
    +        }
    +
    +        if (0 == hl) {
    +            /*
    +             * The host string is shorter than the domain string.
    +             * There is only one case when this can be a match.
    +             * If the domain is just one character longer, and if
    +             * that character is a leading '.' then we call it a
    +             * match.
    +             */
    +
    +            if (1 == dl && '.' == d[0])
    +                return 0;
    +            else
    +                return -1;
    +        }
    +
    +        if (0 == dl) {
    +            /*
    +             * The domain string is shorter than the host string.
    +             * This is a match only if the first domain character
    +             * is a leading '.'.
    +             */
    +
    +            if ('.' == d[0])
    +                return 0;
    +            else
    +                return 1;
    +        }
         }
    +
         /*
          * We found different characters in the same position (from the end).
          */
    @@ -533,9 +622,11 @@ matchDomainName(const char *h, const char *d)
          * be greater than ".foo.com" even though '-' is less than '.'.
          */
         if ('.' == d[dl])
    -	return 1;
    +        return 1;
    +
         if ('.' == h[hl])
    -	return -1;
    +        return -1;
    +
         return (xtolower(h[hl]) - xtolower(d[dl]));
     }
     
    @@ -544,45 +635,65 @@ urlCheckRequest(const request_t * r)
     {
         int rc = 0;
         /* protocol "independent" methods */
    +
         if (r->method == METHOD_CONNECT)
    -	return 1;
    +        return 1;
    +
         if (r->method == METHOD_TRACE)
    -	return 1;
    +        return 1;
    +
         if (r->method == METHOD_PURGE)
    -	return 1;
    +        return 1;
    +
         /* does method match the protocol? */
         switch (r->protocol) {
    +
         case PROTO_URN:
    +
         case PROTO_HTTP:
    +
         case PROTO_CACHEOBJ:
    -	rc = 1;
    -	break;
    +        rc = 1;
    +        break;
    +
         case PROTO_FTP:
    -	if (r->method == METHOD_PUT)
    -	    rc = 1;
    +
    +        if (r->method == METHOD_PUT)
    +            rc = 1;
    +
         case PROTO_GOPHER:
    +
         case PROTO_WAIS:
    +
         case PROTO_WHOIS:
    -	if (r->method == METHOD_GET)
    -	    rc = 1;
    -	else if (r->method == METHOD_HEAD)
    -	    rc = 1;
    -	break;
    +        if (r->method == METHOD_GET)
    +            rc = 1;
    +        else if (r->method == METHOD_HEAD)
    +            rc = 1;
    +
    +        break;
    +
         case PROTO_HTTPS:
     #ifdef USE_SSL
    -	rc = 1;
    -	break;
    +
    +        rc = 1;
    +
    +        break;
    +
     #else
    -	/*
    -	 * Squid can't originate an SSL connection, so it should
    -	 * never receive an "https:" URL.  It should always be
    -	 * CONNECT instead.
    -	 */
    -	rc = 0;
    +        /*
    +        * Squid can't originate an SSL connection, so it should
    +        * never receive an "https:" URL.  It should always be
    +        * CONNECT instead.
    +        */
    +        rc = 0;
    +
     #endif
    +
         default:
    -	break;
    +        break;
         }
    +
         return rc;
     }
     
    @@ -600,20 +711,28 @@ urlHostname(const char *url)
         LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN);
         char *t;
         host[0] = '\0';
    +
         if (NULL == (t = strchr(url, ':')))
    -	return NULL;
    +        return NULL;
    +
         t++;
    +
         while (*t != '\0' && *t == '/')
    -	t++;
    +        t++;
    +
         xstrncpy(host, t, SQUIDHOSTNAMELEN);
    +
         if ((t = strchr(host, '/')))
    -	*t = '\0';
    +        *t = '\0';
    +
         if ((t = strchr(host, ':')))
    -	*t = '\0';
    +        *t = '\0';
    +
         if ((t = strrchr(host, '@'))) {
    -	t++;
    -	xmemmove(host, t, strlen(t) + 1);
    +        t++;
    +        xmemmove(host, t, strlen(t) + 1);
         }
    +
         return host;
     }
     
    @@ -621,18 +740,24 @@ static void
     urlExtMethodAdd(const char *mstr)
     {
         method_t method = METHOD_NONE;
    +
         for (++method; method < METHOD_ENUM_END; ++method) {
    -	if (0 == strcmp(mstr, RequestMethodStr[method])) {
    -	    debug(23, 2) ("Extension method '%s' already exists\n", mstr);
    -	    return;
    -	}
    -	if (0 != strncmp("%EXT", RequestMethodStr[method], 4))
    -	    continue;
    -	/* Don't free statically allocated "%EXTnn" string */
    -	RequestMethodStr[method] = xstrdup(mstr);
    -	debug(23, 1) ("Extension method '%s' added, enum=%d\n", mstr, (int) method);
    -	return;
    +        if (0 == strcmp(mstr, RequestMethodStr[method])) {
    +            debug(23, 2) ("Extension method '%s' already exists\n", mstr);
    +            return;
    +        }
    +
    +        if (0 != strncmp("%EXT", RequestMethodStr[method], 4))
    +            continue;
    +
    +        /* Don't free statically allocated "%EXTnn" string */
    +        RequestMethodStr[method] = xstrdup(mstr);
    +
    +        debug(23, 1) ("Extension method '%s' added, enum=%d\n", mstr, (int) method);
    +
    +        return;
         }
    +
         debug(23, 1) ("WARNING: Could not add new extension method '%s' due to lack of array space\n", mstr);
     }
     
    @@ -640,11 +765,15 @@ void
     urlExtMethodConfigure(void)
     {
         wordlist *w = Config.ext_methods;
    +
         while (w) {
    -	char *s;
    -	for (s = w->key; *s; s++)
    -	    *s = xtoupper(*s);
    -	urlExtMethodAdd(w->key);
    -	w = w->next;
    +        char *s;
    +
    +        for (s = w->key; *s; s++)
    +            *s = xtoupper(*s);
    +
    +        urlExtMethodAdd(w->key);
    +
    +        w = w->next;
         }
     }
    diff --git a/src/urn.cc b/src/urn.cc
    index c110ad5591..3dba79d2f5 100644
    --- a/src/urn.cc
    +++ b/src/urn.cc
    @@ -1,6 +1,6 @@
     
     /*
    - * $Id: urn.cc,v 1.81 2003/01/23 00:37:29 robertc Exp $
    + * $Id: urn.cc,v 1.82 2003/02/21 22:50:13 robertc Exp $
      *
      * DEBUG: section 52    URN Parsing
      * AUTHOR: Kostas Anagnostakis
    @@ -41,7 +41,9 @@
     
     #define	URN_REQBUF_SZ	4096
     
    -class UrnState : public StoreClient {
    +class UrnState : public StoreClient
    +{
    +
     public:
         void created (StoreEntry *newEntry);
         void *operator new (size_t byteCount);
    @@ -54,30 +56,44 @@ public:
         void createUriResRequest (String &uri);
     
         virtual ~UrnState();
    -      
    -    
    +
    +
         StoreEntry *entry;
         store_client *sc;
         StoreEntry *urlres_e;
         request_t *request;
         request_t *urlres_r;
    -    struct {
    -	unsigned int force_menu:1;
    -    } flags;
    +
    +    struct
    +    {
    +
    +unsigned int force_menu:
    +        1;
    +    }
    +
    +    flags;
         char reqbuf[URN_REQBUF_SZ];
         int reqofs;
    +
     private:
         char *urlres;
     };
     
    -typedef struct {
    +typedef struct
    +{
         char *url;
         char *host;
         int rtt;
    -    struct {
    -	int cached;
    -    } flags;
    -} url_entry;
    +
    +    struct
    +    {
    +        int cached;
    +    }
    +
    +    flags;
    +}
    +
    +url_entry;
     
     static STCB urnHandleReply;
     static url_entry *urnParseReply(const char *inbuf, method_t);
    @@ -88,11 +104,11 @@ CBDATA_TYPE(UrnState);
     void *
     UrnState::operator new (size_t byteCount)
     {
    -     /* derived classes with different sizes must implement their own new */
    +    /* derived classes with different sizes must implement their own new */
         assert (byteCount == sizeof (UrnState));
         CBDATA_INIT_TYPE(UrnState);
         return cbdataAlloc(UrnState);
    -		
    +
     }
     
     void
    @@ -116,28 +132,39 @@ urnFindMinRtt(url_entry * urls, method_t m, int *rtt_ret)
         int urlcnt = 0;
         debug(52, 3) ("urnFindMinRtt\n");
         assert(urls != NULL);
    +
         for (i = 0; NULL != urls[i].url; i++)
    -	urlcnt++;
    +        urlcnt++;
    +
         debug(53, 3) ("urnFindMinRtt: Counted %d URLs\n", i);
    +
         if (1 == urlcnt) {
    -	debug(52, 3) ("urnFindMinRtt: Only one URL - return it!\n");
    -	return urls;
    +        debug(52, 3) ("urnFindMinRtt: Only one URL - return it!\n");
    +        return urls;
         }
    +
         for (i = 0; i < urlcnt; i++) {
    -	u = &urls[i];
    -	debug(52, 3) ("urnFindMinRtt: %s rtt=%d\n", u->host, u->rtt);
    -	if (u->rtt == 0)
    -	    continue;
    -	if (u->rtt > min_rtt && min_rtt != 0)
    -	    continue;
    -	min_rtt = u->rtt;
    -	min_u = u;
    +        u = &urls[i];
    +        debug(52, 3) ("urnFindMinRtt: %s rtt=%d\n", u->host, u->rtt);
    +
    +        if (u->rtt == 0)
    +            continue;
    +
    +        if (u->rtt > min_rtt && min_rtt != 0)
    +            continue;
    +
    +        min_rtt = u->rtt;
    +
    +        min_u = u;
         }
    +
         if (rtt_ret)
    -	*rtt_ret = min_rtt;
    +        *rtt_ret = min_rtt;
    +
         debug(52, 1) ("urnFindMinRtt: Returning '%s' RTT %d\n",
    -	min_u ? min_u->url : "NONE",
    -	min_rtt);
    +                  min_u ? min_u->url : "NONE",
    +                  min_rtt);
    +
         return min_u;
     }
     
    @@ -146,13 +173,15 @@ UrnState::getHost (String &urlpath)
     {
         char * result;
         char const *t;
    +
         if ((t = strChr(urlpath, ':')) != NULL) {
    -	strSet(urlpath, t, '\0');
    -	result = xstrdup(urlpath.buf());
    -	strSet(urlpath, t, ':');
    +        strSet(urlpath, t, '\0');
    +        result = xstrdup(urlpath.buf());
    +        strSet(urlpath, t, ':');
         } else {
    -	result = xstrdup(urlpath.buf());
    +        result = xstrdup(urlpath.buf());
         }
    +
         return result;
     }
     
    @@ -165,9 +194,9 @@ UrnState::RequestNeedsMenu(request_t *r)
     void
     UrnState::updateRequestURL(request_t *r, char const *newPath)
     {
    -     char *new_path = xstrdup (newPath);
    -     r->urlpath = new_path;
    -     xfree(new_path);
    +    char *new_path = xstrdup (newPath);
    +    r->urlpath = new_path;
    +    xfree(new_path);
     }
     
     void
    @@ -186,19 +215,21 @@ void
     UrnState::setUriResFromRequest(request_t *r)
     {
         if (RequestNeedsMenu(r)) {
    -	updateRequestURL(r, r->urlpath.buf() + 5);
    -	flags.force_menu = 1;
    +        updateRequestURL(r, r->urlpath.buf() + 5);
    +        flags.force_menu = 1;
         }
    - 
    +
         createUriResRequest (r->urlpath);
    +
         if (urlres_r == NULL) {
    -	debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres);
    -	ErrorState *err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
    -	err->url = urlres;
    -	urlres = NULL;
    -	errorAppendEntry(entry, err);
    -	return;
    +        debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres);
    +        ErrorState *err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
    +        err->url = urlres;
    +        urlres = NULL;
    +        errorAppendEntry(entry, err);
    +        return;
         }
    +
         requestLink(urlres_r);
         httpHeaderPutStr(&urlres_r->header, HDR_ACCEPT, "text/plain");
     }
    @@ -211,8 +242,10 @@ UrnState::start(request_t * r, StoreEntry * e)
         request = requestLink(r);
         storeLockObject(entry);
         setUriResFromRequest(r);
    +
         if (urlres_r == NULL)
    -	return;
    +        return;
    +
         StoreEntry::getPublic (this, urlres, METHOD_GET);
     }
     
    @@ -220,23 +253,25 @@ void
     UrnState::created(StoreEntry *newEntry)
     {
         urlres_e = newEntry;
    +
         if (urlres_e->isNull()) {
    -	urlres_e = storeCreateEntry(urlres, urlres, request_flags(), METHOD_GET);
    -	sc = storeClientListAdd(urlres_e, this);
    -	fwdStart(-1, urlres_e, urlres_r);
    +        urlres_e = storeCreateEntry(urlres, urlres, request_flags(), METHOD_GET);
    +        sc = storeClientListAdd(urlres_e, this);
    +        fwdStart(-1, urlres_e, urlres_r);
         } else {
    -	storeLockObject(urlres_e);
    -	sc = storeClientListAdd(urlres_e, this);
    +        storeLockObject(urlres_e);
    +        sc = storeClientListAdd(urlres_e, this);
         }
    +
         reqofs = 0;
         StoreIOBuffer tempBuffer;
         tempBuffer.offset = reqofs;
         tempBuffer.length = URN_REQBUF_SZ;
         tempBuffer.data = reqbuf;
         storeClientCopy(sc, urlres_e,
    -	tempBuffer,
    -	urnHandleReply,
    -	this);
    +                    tempBuffer,
    +                    urnHandleReply,
    +                    this);
     }
     
     void
    @@ -251,14 +286,15 @@ url_entry_sort(const void *A, const void *B)
     {
         const url_entry *u1 = (const url_entry *)A;
         const url_entry *u2 = (const url_entry *)B;
    +
         if (u2->rtt == u1->rtt)
    -	return 0;
    +        return 0;
         else if (0 == u1->rtt)
    -	return 1;
    +        return 1;
         else if (0 == u2->rtt)
    -	return -1;
    +        return -1;
         else
    -	return u1->rtt - u2->rtt;
    +        return u1->rtt - u2->rtt;
     }
     
     /* TODO: use the clientStream support for this */
    @@ -283,119 +319,143 @@ urnHandleReply(void *data, StoreIOBuffer result)
         StoreIOBuffer tempBuffer;
     
         debug(52, 3) ("urnHandleReply: Called with size=%u.\n", (unsigned int)result.length);
    +
         if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) {
    -	goto error;
    +        goto error;
         }
    +
         if (result.length == 0) {
    -	goto error;
    +        goto error;
         } else if (result.flags.error < 0) {
    -	goto error;
    +        goto error;
         }
    +
         /* Update reqofs to point to where in the buffer we'd be */
         urnState->reqofs += result.length;
     
         /* Handle reqofs being bigger than normal */
         if (urnState->reqofs >= URN_REQBUF_SZ) {
    -	goto error;
    +        goto error;
         }
    +
         /* If we haven't received the entire object (urn), copy more */
         if (urlres_e->store_status == STORE_PENDING &&
    -	urnState->reqofs < URN_REQBUF_SZ) {
    -	tempBuffer.offset = urnState->reqofs;
    -	tempBuffer.length = URN_REQBUF_SZ;
    -	tempBuffer.data = urnState->reqbuf + urnState->reqofs;
    -	storeClientCopy(urnState->sc, urlres_e,
    -	    tempBuffer,
    -	    urnHandleReply,
    -	    urnState);
    -	return;
    +            urnState->reqofs < URN_REQBUF_SZ) {
    +        tempBuffer.offset = urnState->reqofs;
    +        tempBuffer.length = URN_REQBUF_SZ;
    +        tempBuffer.data = urnState->reqbuf + urnState->reqofs;
    +        storeClientCopy(urnState->sc, urlres_e,
    +                        tempBuffer,
    +                        urnHandleReply,
    +                        urnState);
    +        return;
         }
    +
         /* we know its STORE_OK */
         k = headersEnd(buf, urnState->reqofs);
    +
         if (0 == k) {
    -	debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n",
    -	    storeUrl(e));
    -	goto error;
    +        debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n",
    +                      storeUrl(e));
    +        goto error;
         }
    +
         s = buf + k;
         assert(urlres_e->getReply());
         rep = httpReplyCreate ();
         httpReplyParse(rep, buf, k);
         debug(52, 3) ("reply exists, code=%d.\n",
    -       rep->sline.status);
    +                  rep->sline.status);
    +
         if (rep->sline.status != HTTP_OK) {
    -	debug(52, 3) ("urnHandleReply: failed.\n");
    -	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
    -	err->request = requestLink(urnState->request);
    -	err->url = xstrdup(storeUrl(e));
    -	errorAppendEntry(e, err);
    -	httpReplyDestroy(rep);
    -	goto error;
    +        debug(52, 3) ("urnHandleReply: failed.\n");
    +        err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
    +        err->request = requestLink(urnState->request);
    +        err->url = xstrdup(storeUrl(e));
    +        errorAppendEntry(e, err);
    +        httpReplyDestroy(rep);
    +        goto error;
         }
    +
         httpReplyDestroy(rep);
    +
         while (xisspace(*s))
    -	s++;
    +        s++;
    +
         urls = urnParseReply(s, urnState->request->method);
    +
         for (i = 0; NULL != urls[i].url; i++)
    -	urlcnt++;
    +        urlcnt++;
    +
         debug(53, 3) ("urnFindMinRtt: Counted %d URLs\n", i);
    +
         if (urls == NULL) {		/* unkown URN error */
    -	debug(52, 3) ("urnTranslateDone: unknown URN %s\n", storeUrl(e));
    -	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
    -	err->request = requestLink(urnState->request);
    -	err->url = xstrdup(storeUrl(e));
    -	errorAppendEntry(e, err);
    -	goto error;
    +        debug(52, 3) ("urnTranslateDone: unknown URN %s\n", storeUrl(e));
    +        err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
    +        err->request = requestLink(urnState->request);
    +        err->url = xstrdup(storeUrl(e));
    +        errorAppendEntry(e, err);
    +        goto error;
         }
    +
         min_u = urnFindMinRtt(urls, urnState->request->method, NULL);
         qsort(urls, urlcnt, sizeof(*urls), url_entry_sort);
         storeBuffer(e);
         memBufDefInit(&mb);
         memBufPrintf(&mb,
    -	"Select URL for %s\n"
    -	"\n"
    -	"

    Select URL for %s

    \n" - "\n", storeUrl(e), storeUrl(e)); + "Select URL for %s\n" + "\n" + "

    Select URL for %s

    \n" + "
    \n", storeUrl(e), storeUrl(e)); + for (i = 0; i < urlcnt; i++) { - u = &urls[i]; - debug(52, 3) ("URL {%s}\n", u->url); - memBufPrintf(&mb, - "", u->url, u->url); - if (urls[i].rtt > 0) - memBufPrintf(&mb, - "", u->rtt); - else - memBufPrintf(&mb, ""); - memBufPrintf(&mb, - "\n", u->flags.cached ? " [cached]" : " "); + u = &urls[i]; + debug(52, 3) ("URL {%s}\n", u->url); + memBufPrintf(&mb, + "", u->url, u->url); + + if (urls[i].rtt > 0) + memBufPrintf(&mb, + "", u->rtt); + else + memBufPrintf(&mb, ""); + + memBufPrintf(&mb, + "\n", u->flags.cached ? " [cached]" : " "); } + memBufPrintf(&mb, - "
    %s%4d msUnknown%s
    %s%4d msUnknown%s
    " - "
    \n" - "
    \n" - "Generated by %s@%s\n" - "
    \n", - full_appname_string, getMyHostname()); + "" + "
    \n" + "
    \n" + "Generated by %s@%s\n" + "
    \n", + full_appname_string, getMyHostname()); rep = httpReplyCreate(); httpBuildVersion(&version, 1, 0); httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL, - "text/html", mb.size, 0, squid_curtime); + "text/html", mb.size, 0, squid_curtime); + if (urnState->flags.force_menu) { - debug(51, 3) ("urnHandleReply: forcing menu\n"); + debug(51, 3) ("urnHandleReply: forcing menu\n"); } else if (min_u) { - httpHeaderPutStr(&rep->header, HDR_LOCATION, min_u->url); + httpHeaderPutStr(&rep->header, HDR_LOCATION, min_u->url); } + httpBodySet(&rep->body, &mb); httpReplySwapOut(rep, e); e->complete(); + for (i = 0; i < urlcnt; i++) { - safe_free(urls[i].url); - safe_free(urls[i].host); + safe_free(urls[i].url); + safe_free(urls[i].host); } + safe_free(urls); /* mb was absorbed in httpBodySet call, so we must not clean it */ storeUnregister(urnState->sc, urlres_e, urnState); - error: + +error: storeUnlockObject(urlres_e); storeUnlockObject(urnState->entry); requestUnlink(urnState->request); @@ -417,30 +477,38 @@ urnParseReply(const char *inbuf, method_t m) int i = 0; debug(52, 3) ("urnParseReply\n"); list = (url_entry *)xcalloc(n + 1, sizeof(*list)); + for (token = strtok(buf, crlf); token; token = strtok(NULL, crlf)) { - debug(52, 3) ("urnParseReply: got '%s'\n", token); - if (i == n) { - old = list; - n <<= 2; - list = (url_entry *)xcalloc(n + 1, sizeof(*list)); - xmemcpy(list, old, i * sizeof(*list)); - safe_free(old); - } - url = xstrdup(token); - host = urlHostname(url); - if (NULL == host) - continue; - rtt = netdbHostRtt(host); - if (0 == rtt) { - debug(52, 3) ("urnParseReply: Pinging %s\n", host); - netdbPingSite(host); - } - list[i].url = url; - list[i].host = xstrdup(host); - list[i].rtt = rtt; - list[i].flags.cached = storeGetPublic(url, m) ? 1 : 0; - i++; + debug(52, 3) ("urnParseReply: got '%s'\n", token); + + if (i == n) { + old = list; + n <<= 2; + list = (url_entry *)xcalloc(n + 1, sizeof(*list)); + xmemcpy(list, old, i * sizeof(*list)); + safe_free(old); + } + + url = xstrdup(token); + host = urlHostname(url); + + if (NULL == host) + continue; + + rtt = netdbHostRtt(host); + + if (0 == rtt) { + debug(52, 3) ("urnParseReply: Pinging %s\n", host); + netdbPingSite(host); + } + + list[i].url = url; + list[i].host = xstrdup(host); + list[i].rtt = rtt; + list[i].flags.cached = storeGetPublic(url, m) ? 1 : 0; + i++; } + debug(52, 3) ("urnParseReply: Found %d URLs\n", i); return list; } diff --git a/src/useragent.cc b/src/useragent.cc index 83e400d616..88ace159a4 100644 --- a/src/useragent.cc +++ b/src/useragent.cc @@ -1,6 +1,6 @@ /* - * $Id: useragent.cc,v 1.27 2003/01/23 00:37:29 robertc Exp $ + * $Id: useragent.cc,v 1.28 2003/02/21 22:50:13 robertc Exp $ * * DEBUG: section 40 User-Agent logging * AUTHOR: Joe Ramey @@ -44,10 +44,12 @@ useragentOpenLog(void) { #if USE_USERAGENT_LOG assert(NULL == useragentlog); + if (!Config.Log.useragent || (0 == strcmp(Config.Log.useragent, "none"))) { - debug(40, 1) ("User-Agent logging is disabled.\n"); - return; + debug(40, 1) ("User-Agent logging is disabled.\n"); + return; } + useragentlog = logfileOpen(Config.Log.useragent, 0, 1); #endif } @@ -56,9 +58,12 @@ void useragentRotateLog(void) { #if USE_USERAGENT_LOG + if (NULL == useragentlog) - return; + return; + logfileRotate(useragentlog); + #endif } @@ -69,17 +74,20 @@ logUserAgent(const char *client, const char *agent) static time_t last_time = 0; static char time_str[128]; const char *s; + if (NULL == useragentlog) - return; + return; + if (squid_curtime != last_time) { - s = mkhttpdlogtime(&squid_curtime); - strcpy(time_str, s); - last_time = squid_curtime; + s = mkhttpdlogtime(&squid_curtime); + strcpy(time_str, s); + last_time = squid_curtime; } + logfilePrintf(useragentlog, "%s [%s] \"%s\"\n", - client, - time_str, - agent); + client, + time_str, + agent); #endif } @@ -87,9 +95,13 @@ void useragentLogClose(void) { #if USE_USERAGENT_LOG + if (NULL == useragentlog) - return; + return; + logfileClose(useragentlog); + useragentlog = NULL; + #endif } diff --git a/src/wais.cc b/src/wais.cc index 3188e12559..f1a4163519 100644 --- a/src/wais.cc +++ b/src/wais.cc @@ -1,6 +1,6 @@ /* - * $Id: wais.cc,v 1.146 2003/02/05 10:36:56 robertc Exp $ + * $Id: wais.cc,v 1.147 2003/02/21 22:50:13 robertc Exp $ * * DEBUG: section 24 WAIS Relay * AUTHOR: Harvest Derived @@ -40,7 +40,9 @@ #include "DelayPools.h" #endif -class WaisStateData { +class WaisStateData +{ + public: int fd; StoreEntry *entry; @@ -63,10 +65,14 @@ static void waisStateFree(int fdnotused, void *data) { WaisStateData *waisState = (WaisStateData *)data; + if (waisState == NULL) - return; + return; + storeUnlockObject(waisState->entry); + requestUnlink(waisState->request); + cbdataFree(waisState); } @@ -77,12 +83,14 @@ waisTimeout(int fd, void *data) WaisStateData *waisState = (WaisStateData *)data; StoreEntry *entry = waisState->entry; debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); + if (entry->store_status == STORE_PENDING) { - if (!waisState->dataWritten) { - fwdFail(waisState->fwd, - errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); - } + if (!waisState->dataWritten) { + fwdFail(waisState->fwd, + errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); + } } + comm_close(fd); } @@ -97,70 +105,83 @@ waisReadReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void * int bin; size_t read_sz; #if DELAY_POOLS + DelayId delayId = entry->mem_obj->mostBytesAllowed(); #endif /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ + if (flag == COMM_ERR_CLOSING) { return; } if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - comm_close(fd); - return; + comm_close(fd); + return; } + errno = 0; read_sz = BUFSIZ; + if (flag == COMM_OK && len > 0) { #if DELAY_POOLS - delayId.bytesIn(len); + delayId.bytesIn(len); #endif - kb_incr(&statCounter.server.all.kbytes_in, len); - kb_incr(&statCounter.server.other.kbytes_in, len); + + kb_incr(&statCounter.server.all.kbytes_in, len); + kb_incr(&statCounter.server.other.kbytes_in, len); } + #if DELAY_POOLS read_sz = delayId.bytesWanted(1, read_sz); + #endif + debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd, (int)len); + if (flag == COMM_OK && len > 0) { - commSetTimeout(fd, Config.Timeout.read, NULL, NULL); - IOStats.Wais.reads++; - for (clen = len - 1, bin = 0; clen; bin++) - clen >>= 1; - IOStats.Wais.read_hist[bin]++; + commSetTimeout(fd, Config.Timeout.read, NULL, NULL); + IOStats.Wais.reads++; + + for (clen = len - 1, bin = 0; clen; bin++) + clen >>= 1; + + IOStats.Wais.read_hist[bin]++; } + if (flag != COMM_OK || len < 0) { - debug(50, 1) ("waisReadReply: FD %d: read failure: %s.\n", - fd, xstrerror()); - if (ignoreErrno(xerrno)) { - /* reinstall handlers */ - /* XXX This may loop forever */ + debug(50, 1) ("waisReadReply: FD %d: read failure: %s.\n", + fd, xstrerror()); + + if (ignoreErrno(xerrno)) { + /* reinstall handlers */ + /* XXX This may loop forever */ comm_read(fd, waisState->buf, read_sz, waisReadReply, waisState); - } else { - ErrorState *err; - EBIT_CLR(entry->flags, ENTRY_CACHABLE); - storeReleaseRequest(entry); - err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); - err->xerrno = errno; - err->request = requestLink(waisState->request); - errorAppendEntry(entry, err); - comm_close(fd); - } + } else { + ErrorState *err; + EBIT_CLR(entry->flags, ENTRY_CACHABLE); + storeReleaseRequest(entry); + err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); + err->xerrno = errno; + err->request = requestLink(waisState->request); + errorAppendEntry(entry, err); + comm_close(fd); + } } else if (flag == COMM_OK && len == 0 && !waisState->dataWritten) { - ErrorState *err; - err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE); - err->xerrno = errno; - err->request = requestLink(waisState->request); - errorAppendEntry(entry, err); - comm_close(fd); + ErrorState *err; + err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE); + err->xerrno = errno; + err->request = requestLink(waisState->request); + errorAppendEntry(entry, err); + comm_close(fd); } else if (flag == COMM_OK && len == 0) { - /* Connection closed; retrieval done. */ - entry->expires = squid_curtime; - fwdComplete(waisState->fwd); - comm_close(fd); + /* Connection closed; retrieval done. */ + entry->expires = squid_curtime; + fwdComplete(waisState->fwd); + comm_close(fd); } else { - waisState->dataWritten = 1; - storeAppend(entry, buf, len); + waisState->dataWritten = 1; + storeAppend(entry, buf, len); comm_read(fd, waisState->buf, read_sz, waisReadReply, waisState); } } @@ -173,25 +194,28 @@ waisSendComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag, void WaisStateData *waisState = (WaisStateData *)data; StoreEntry *entry = waisState->entry; debug(24, 5) ("waisSendComplete: FD %d size: %d errflag: %d\n", - fd, (int) size, errflag); + fd, (int) size, errflag); + if (size > 0) { - fd_bytes(fd, size, FD_WRITE); - kb_incr(&statCounter.server.all.kbytes_out, size); - kb_incr(&statCounter.server.other.kbytes_out, size); + fd_bytes(fd, size, FD_WRITE); + kb_incr(&statCounter.server.all.kbytes_out, size); + kb_incr(&statCounter.server.other.kbytes_out, size); } + if (errflag == COMM_ERR_CLOSING) - return; + return; + if (errflag) { - ErrorState *err; - err = errorCon(ERR_WRITE_ERROR, HTTP_SERVICE_UNAVAILABLE); - err->xerrno = errno; - err->request = requestLink(waisState->request); - errorAppendEntry(entry, err); - comm_close(fd); + ErrorState *err; + err = errorCon(ERR_WRITE_ERROR, HTTP_SERVICE_UNAVAILABLE); + err->xerrno = errno; + err->request = requestLink(waisState->request); + errorAppendEntry(entry, err); + comm_close(fd); } else { - /* Schedule read reply. */ + /* Schedule read reply. */ comm_read(fd, waisState->buf, BUFSIZ, waisReadReply, waisState); - commSetDefer(fd, StoreEntry::CheckDeferRead, entry); + commSetDefer(fd, StoreEntry::CheckDeferRead, entry); } } @@ -205,17 +229,21 @@ waisSendRequest(int fd, void *data) debug(24, 5) ("waisSendRequest: FD %d\n", fd); memBufDefInit(&mb); memBufPrintf(&mb, "%s %s HTTP/1.0\r\n", Method, waisState->url); + if (waisState->request_hdr) { - Packer p; - packerToMemInit(&p, &mb); - httpHeaderPackInto(waisState->request_hdr, &p); - packerClean(&p); + Packer p; + packerToMemInit(&p, &mb); + httpHeaderPackInto(waisState->request_hdr, &p); + packerClean(&p); } + memBufPrintf(&mb, "\r\n"); debug(24, 6) ("waisSendRequest: buf: %s\n", mb.buf); comm_old_write_mbuf(fd, mb, waisSendComplete, waisState); + if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE)) - storeSetPublicKey(waisState->entry); /* Make it public */ + storeSetPublicKey(waisState->entry); /* Make it public */ + EBIT_CLR(waisState->entry->flags, ENTRY_FWD_HDR_WAIT); } diff --git a/src/wccp.cc b/src/wccp.cc index 0688265d28..93b19c14e7 100644 --- a/src/wccp.cc +++ b/src/wccp.cc @@ -1,6 +1,6 @@ /* - * $Id: wccp.cc,v 1.32 2003/01/23 00:37:29 robertc Exp $ + * $Id: wccp.cc,v 1.33 2003/02/21 22:50:13 robertc Exp $ * * DEBUG: section 80 WCCP Support * AUTHOR: Glenn Chisholm @@ -49,7 +49,8 @@ #define WCCP_I_SEE_YOU 8 #define WCCP_ASSIGN_BUCKET 9 -struct wccp_here_i_am_t { +struct wccp_here_i_am_t +{ int type; int version; int revision; @@ -58,23 +59,28 @@ struct wccp_here_i_am_t { int id; }; -struct wccp_cache_entry_t { +struct wccp_cache_entry_t +{ + struct in_addr ip_addr; int revision; char hash[WCCP_HASH_SIZE]; int reserved; }; -struct wccp_i_see_you_t { +struct wccp_i_see_you_t +{ int type; int version; int change; int id; int number; + struct wccp_cache_entry_t wccp_cache_entry[WCCP_ACTIVE_CACHES]; }; -struct wccp_assign_bucket_t { +struct wccp_assign_bucket_t +{ int type; int id; int number; @@ -82,11 +88,14 @@ struct wccp_assign_bucket_t { static int theInWccpConnection = -1; static int theOutWccpConnection = -1; + static struct wccp_here_i_am_t wccp_here_i_am; + static struct wccp_i_see_you_t wccp_i_see_you; static int change; static int last_assign_buckets_change; static unsigned int number_caches; + static struct in_addr local_ip; static PF wccpHandleUdp; @@ -112,68 +121,87 @@ wccpInit(void) wccp_here_i_am.revision = htonl(WCCP_REVISION); change = 0; last_assign_buckets_change = 0; + if (Config.Wccp.router.s_addr != any_addr.s_addr) - if (!eventFind(wccpHereIam, NULL)) - eventAdd("wccpHereIam", wccpHereIam, NULL, 5.0, 1); + if (!eventFind(wccpHereIam, NULL)) + eventAdd("wccpHereIam", wccpHereIam, NULL, 5.0, 1); } void wccpConnectionOpen(void) { u_short port = WCCP_PORT; + struct sockaddr_in router, local; socklen_t local_len, router_len; debug(80, 5) ("wccpConnectionOpen: Called\n"); + if (Config.Wccp.router.s_addr == any_addr.s_addr) { - debug(1, 1) ("WCCP Disabled.\n"); - return; + debug(1, 1) ("WCCP Disabled.\n"); + return; } + theInWccpConnection = comm_open(SOCK_DGRAM, - 0, - Config.Wccp.incoming, - port, - COMM_NONBLOCKING, - "WCCP Socket"); + 0, + Config.Wccp.incoming, + port, + COMM_NONBLOCKING, + "WCCP Socket"); + if (theInWccpConnection < 0) - fatal("Cannot open WCCP Port"); + fatal("Cannot open WCCP Port"); + commSetSelect(theInWccpConnection, - COMM_SELECT_READ, - wccpHandleUdp, - NULL, - 0); + COMM_SELECT_READ, + wccpHandleUdp, + NULL, + 0); + debug(1, 1) ("Accepting WCCP messages on port %d, FD %d.\n", - (int) port, theInWccpConnection); + (int) port, theInWccpConnection); + if (Config.Wccp.outgoing.s_addr != no_addr.s_addr) { - theOutWccpConnection = comm_open(SOCK_DGRAM, - 0, - Config.Wccp.outgoing, - port, - COMM_NONBLOCKING, - "WCCP Socket"); - if (theOutWccpConnection < 0) - fatal("Cannot open Outgoing WCCP Port"); - commSetSelect(theOutWccpConnection, - COMM_SELECT_READ, - wccpHandleUdp, - NULL, 0); - debug(1, 1) ("Outgoing WCCP messages on port %d, FD %d.\n", - (int) port, theOutWccpConnection); - fd_note(theOutWccpConnection, "Outgoing WCCP socket"); - fd_note(theInWccpConnection, "Incoming WCCP socket"); + theOutWccpConnection = comm_open(SOCK_DGRAM, + 0, + Config.Wccp.outgoing, + port, + COMM_NONBLOCKING, + "WCCP Socket"); + + if (theOutWccpConnection < 0) + fatal("Cannot open Outgoing WCCP Port"); + + commSetSelect(theOutWccpConnection, + COMM_SELECT_READ, + wccpHandleUdp, + NULL, 0); + + debug(1, 1) ("Outgoing WCCP messages on port %d, FD %d.\n", + (int) port, theOutWccpConnection); + + fd_note(theOutWccpConnection, "Outgoing WCCP socket"); + + fd_note(theInWccpConnection, "Incoming WCCP socket"); } else { - theOutWccpConnection = theInWccpConnection; + theOutWccpConnection = theInWccpConnection; } + router_len = sizeof(router); memset(&router, '\0', router_len); router.sin_family = AF_INET; router.sin_port = htons(port); router.sin_addr = Config.Wccp.router; + if (connect(theOutWccpConnection, (struct sockaddr *) &router, router_len)) - fatal("Unable to connect WCCP out socket"); + fatal("Unable to connect WCCP out socket"); + local_len = sizeof(local); + memset(&local, '\0', local_len); + if (getsockname(theOutWccpConnection, (struct sockaddr *) &local, &local_len)) - fatal("Unable to getsockname on WCCP out socket"); + fatal("Unable to getsockname on WCCP out socket"); + local_ip.s_addr = local.sin_addr.s_addr; } @@ -181,12 +209,14 @@ void wccpConnectionShutdown(void) { if (theInWccpConnection < 0) - return; + return; + if (theInWccpConnection != theOutWccpConnection) { - debug(80, 1) ("FD %d Closing WCCP socket\n", theInWccpConnection); - comm_close(theInWccpConnection); - theInWccpConnection = -1; + debug(80, 1) ("FD %d Closing WCCP socket\n", theInWccpConnection); + comm_close(theInWccpConnection); + theInWccpConnection = -1; } + assert(theOutWccpConnection > -1); commSetSelect(theOutWccpConnection, COMM_SELECT_READ, NULL, NULL, 0); } @@ -195,22 +225,24 @@ void wccpConnectionClose(void) { wccpConnectionShutdown(); + if (theOutWccpConnection > -1) { - debug(80, 1) ("FD %d Closing WCCP socket\n", theOutWccpConnection); - comm_close(theOutWccpConnection); + debug(80, 1) ("FD %d Closing WCCP socket\n", theOutWccpConnection); + comm_close(theOutWccpConnection); } } -/* +/* * Functions for handling the requests. */ -/* +/* * Accept the UDP packet */ static void wccpHandleUdp(int sock, void *not_used) { + struct sockaddr_in from; socklen_t from_len; int len; @@ -218,54 +250,63 @@ wccpHandleUdp(int sock, void *not_used) debug(80, 6) ("wccpHandleUdp: Called.\n"); commSetSelect(sock, COMM_SELECT_READ, wccpHandleUdp, NULL, 0); + from_len = sizeof(struct sockaddr_in); memset(&from, '\0', from_len); memset(&wccp_i_see_you, '\0', sizeof(wccp_i_see_you)); len = comm_udp_recvfrom(sock, - (void *) &wccp_i_see_you, - WCCP_RESPONSE_SIZE, - 0, - (struct sockaddr *) &from, - &from_len); + (void *) &wccp_i_see_you, + WCCP_RESPONSE_SIZE, + 0, + + (struct sockaddr *) &from, + &from_len); debug(80, 3) ("wccpHandleUdp: %d bytes WCCP pkt from %s: type=%u, version=%u, change=%u, id=%u, number=%u\n", - len, - inet_ntoa(from.sin_addr), - (unsigned) ntohl(wccp_i_see_you.type), - (unsigned) ntohl(wccp_i_see_you.version), - (unsigned) ntohl(wccp_i_see_you.change), - (unsigned) ntohl(wccp_i_see_you.id), - (unsigned) ntohl(wccp_i_see_you.number)); + len, + inet_ntoa(from.sin_addr), + (unsigned) ntohl(wccp_i_see_you.type), + (unsigned) ntohl(wccp_i_see_you.version), + (unsigned) ntohl(wccp_i_see_you.change), + (unsigned) ntohl(wccp_i_see_you.id), + (unsigned) ntohl(wccp_i_see_you.number)); + if (len < 0) - return; + return; + if (Config.Wccp.router.s_addr != from.sin_addr.s_addr) - return; + return; + if (ntohl(wccp_i_see_you.version) != (unsigned)Config.Wccp.version) - return; + return; + if (ntohl(wccp_i_see_you.type) != WCCP_I_SEE_YOU) - return; + return; + if ((0 == change) && (number_caches == ntohl(wccp_i_see_you.number))) { - if (last_assign_buckets_change == wccp_i_see_you.change) { - /* - * After a WCCP_ASSIGN_BUCKET message, the router should - * update the change value. If not, maybe the route didn't - * receive our WCCP_ASSIGN_BUCKET message, so send it again. - * - * Don't update change here. Instead, fall through to - * the next block to call wccpAssignBuckets() again. - */ - (void) 0; - } else { - change = wccp_i_see_you.change; - return; - } + if (last_assign_buckets_change == wccp_i_see_you.change) { + /* + * After a WCCP_ASSIGN_BUCKET message, the router should + * update the change value. If not, maybe the route didn't + * receive our WCCP_ASSIGN_BUCKET message, so send it again. + * + * Don't update change here. Instead, fall through to + * the next block to call wccpAssignBuckets() again. + */ + (void) 0; + } else { + change = wccp_i_see_you.change; + return; + } } + if (change != wccp_i_see_you.change) { - change = wccp_i_see_you.change; - if (wccpLowestIP() && wccp_i_see_you.number) { - last_assign_buckets_change = change; - wccpAssignBuckets(); - } + change = wccp_i_see_you.change; + + if (wccpLowestIP() && wccp_i_see_you.number) { + last_assign_buckets_change = change; + wccpAssignBuckets(); + } } } @@ -273,10 +314,12 @@ static int wccpLowestIP(void) { unsigned int loop; + for (loop = 0; loop < ntohl(wccp_i_see_you.number); loop++) { - if (wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr < local_ip.s_addr) - return 0; + if (wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr < local_ip.s_addr) + return 0; } + return 1; } @@ -287,17 +330,18 @@ wccpHereIam(void *voidnotused) wccp_here_i_am.id = wccp_i_see_you.id; comm_udp_send(theOutWccpConnection, - &wccp_here_i_am, - sizeof(wccp_here_i_am), - 0); + &wccp_here_i_am, + sizeof(wccp_here_i_am), + 0); if (!eventFind(wccpHereIam, NULL)) - eventAdd("wccpHereIam", wccpHereIam, NULL, 10.0, 1); + eventAdd("wccpHereIam", wccpHereIam, NULL, 10.0, 1); } static void wccpAssignBuckets(void) { + struct wccp_assign_bucket_t *wccp_assign_bucket; int wab_len; char *buckets; @@ -310,43 +354,54 @@ wccpAssignBuckets(void) debug(80, 6) ("wccpAssignBuckets: Called\n"); number_caches = ntohl(wccp_i_see_you.number); + if (number_caches > WCCP_ACTIVE_CACHES) - number_caches = WCCP_ACTIVE_CACHES; + number_caches = WCCP_ACTIVE_CACHES; + wab_len = sizeof(struct wccp_assign_bucket_t); + cache_len = WCCP_CACHE_LEN * number_caches; buf = (char *)xmalloc(wab_len + - WCCP_BUCKETS + - cache_len); + WCCP_BUCKETS + + cache_len); + wccp_assign_bucket = (struct wccp_assign_bucket_t *) buf; + caches = (int *) (buf + wab_len); + buckets = buf + wab_len + cache_len; memset(wccp_assign_bucket, '\0', sizeof(wccp_assign_bucket)); + memset(buckets, 0xFF, WCCP_BUCKETS); buckets_per_cache = WCCP_BUCKETS / number_caches; + for (loop = 0; loop < number_caches; loop++) { - int i; - xmemcpy(&caches[loop], - &wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr, - sizeof(*caches)); - for (i = 0; i < buckets_per_cache; i++) { - assert(bucket < WCCP_BUCKETS); - buckets[bucket++] = loop; - } + int i; + xmemcpy(&caches[loop], + &wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr, + sizeof(*caches)); + + for (i = 0; i < buckets_per_cache; i++) { + assert(bucket < WCCP_BUCKETS); + buckets[bucket++] = loop; + } } + while (bucket < WCCP_BUCKETS) { - buckets[bucket++] = number_caches - 1; + buckets[bucket++] = number_caches - 1; } + wccp_assign_bucket->type = htonl(WCCP_ASSIGN_BUCKET); wccp_assign_bucket->id = wccp_i_see_you.id; wccp_assign_bucket->number = wccp_i_see_you.number; comm_udp_send(theOutWccpConnection, - buf, - wab_len + WCCP_BUCKETS + cache_len, - 0); + buf, + wab_len + WCCP_BUCKETS + cache_len, + 0); change = 0; xfree(buf); } diff --git a/src/whois.cc b/src/whois.cc index 92fcef80c9..d5ec26b159 100644 --- a/src/whois.cc +++ b/src/whois.cc @@ -1,6 +1,6 @@ /* - * $Id: whois.cc,v 1.23 2003/01/23 00:37:29 robertc Exp $ + * $Id: whois.cc,v 1.24 2003/02/21 22:50:13 robertc Exp $ * * DEBUG: section 75 WHOIS protocol * AUTHOR: Duane Wessels, Kostas Anagnostakis @@ -40,7 +40,9 @@ #define WHOIS_PORT 43 -class WhoisState { +class WhoisState +{ + public: void readReply (int fd, char *buf, size_t len, comm_err_t flag, int xerrno); void setReplyToOK(StoreEntry *entry); @@ -62,7 +64,7 @@ CBDATA_TYPE(WhoisState); static void whoisWriteComplete(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data) { - xfree(buf); + xfree(buf); } void @@ -108,11 +110,11 @@ whoisReadReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void void WhoisState::setReplyToOK(StoreEntry *entry) { - HttpReply *reply = httpReplyCreate(); - http_version_t version; - httpBuildVersion(&version, 1, 0); - httpReplySetHeaders(reply, version, HTTP_OK, NULL, NULL, 0, 0, -1); - storeEntryReplaceObject (entry, reply); + HttpReply *reply = httpReplyCreate(); + http_version_t version; + httpBuildVersion(&version, 1, 0); + httpReplySetHeaders(reply, version, HTTP_OK, NULL, NULL, 0, 0, -1); + storeEntryReplaceObject (entry, reply); } void @@ -121,6 +123,7 @@ WhoisState::readReply (int fd, char *buf, size_t len, comm_err_t flag, int xerrn int do_next_read = 0; /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ + if (flag == COMM_ERR_CLOSING) { return; } @@ -128,41 +131,54 @@ WhoisState::readReply (int fd, char *buf, size_t len, comm_err_t flag, int xerrn buf[len] = '\0'; debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, (int)len); debug(75, 5) ("{%s}\n", buf); + if (flag == COMM_OK && len > 0) { - if (!dataWritten) - setReplyToOK(entry); - kb_incr(&statCounter.server.all.kbytes_in, len); - kb_incr(&statCounter.server.http.kbytes_in, len); - /* No range support, we always grab it all */ - dataWritten = 1; - storeAppend(entry, buf, len); + if (!dataWritten) + setReplyToOK(entry); + + kb_incr(&statCounter.server.all.kbytes_in, len); + + kb_incr(&statCounter.server.http.kbytes_in, len); + + /* No range support, we always grab it all */ + dataWritten = 1; + + storeAppend(entry, buf, len); + do_next_read = 1; } else if (flag != COMM_OK || len < 0) { - debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n", - fd, xstrerror()); - if (ignoreErrno(errno)) { + debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n", + fd, xstrerror()); + + if (ignoreErrno(errno)) { do_next_read = 1; - } else if (!dataWritten) { - ErrorState *err; - err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); - err->xerrno = errno; - fwdFail(fwd, err); - comm_close(fd); + } else if (!dataWritten) { + ErrorState *err; + err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); + err->xerrno = errno; + fwdFail(fwd, err); + comm_close(fd); do_next_read = 0; - } else { - comm_close(fd); + } else { + comm_close(fd); do_next_read = 0; - } + } } else { - storeTimestampsSet(entry); - storeBufferFlush(entry); - if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) - storeSetPublicKey(entry); - fwdComplete(fwd); - debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry)); - comm_close(fd); + storeTimestampsSet(entry); + storeBufferFlush(entry); + + if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) + storeSetPublicKey(entry); + + fwdComplete(fwd); + + debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry)); + + comm_close(fd); + do_next_read = 0; } + if (do_next_read) comm_read(fd, buf, BUFSIZ, whoisReadReply, this); } diff --git a/src/win32.cc b/src/win32.cc index b49116d068..9f9170c266 100644 --- a/src/win32.cc +++ b/src/win32.cc @@ -1,6 +1,6 @@ /* - * $Id: win32.cc,v 1.6 2003/01/23 00:37:29 robertc Exp $ + * $Id: win32.cc,v 1.7 2003/02/21 22:50:13 robertc Exp $ * * * * * * * * * Legal stuff * * * * * * * * @@ -43,46 +43,61 @@ GetOSVersion() memset(&osvi, '\0', sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx((OSVERSIONINFO *) & osvi); + switch (osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_NT: - if (osvi.dwMajorVersion <= 4) { - WIN32_OS_string = xstrdup("Windows NT"); - return _WIN_OS_WINNT; - } - if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) { - WIN32_OS_string = xstrdup("Windows 2000"); - return _WIN_OS_WIN2K; - } - if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1)) { - WIN32_OS_string = xstrdup("Windows XP"); - return _WIN_OS_WINXP; - } - if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)) { - WIN32_OS_string = xstrdup("Windows .NET"); - return _WIN_OS_WINNET; - } - break; + + if (osvi.dwMajorVersion <= 4) { + WIN32_OS_string = xstrdup("Windows NT"); + return _WIN_OS_WINNT; + } + + if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) { + WIN32_OS_string = xstrdup("Windows 2000"); + return _WIN_OS_WIN2K; + } + + if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1)) { + WIN32_OS_string = xstrdup("Windows XP"); + return _WIN_OS_WINXP; + } + + if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)) { + WIN32_OS_string = xstrdup("Windows .NET"); + return _WIN_OS_WINNET; + } + + break; + case VER_PLATFORM_WIN32_WINDOWS: - if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0)) { - WIN32_OS_string = xstrdup("Windows 95"); - return _WIN_OS_WIN95; - } - if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 10)) { - WIN32_OS_string = xstrdup("Windows 98"); - return _WIN_OS_WIN98; - } - if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 90)) { - WIN32_OS_string = xstrdup("Windows Me"); - return _WIN_OS_WINME; - } - break; + + if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0)) { + WIN32_OS_string = xstrdup("Windows 95"); + return _WIN_OS_WIN95; + } + + if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 10)) { + WIN32_OS_string = xstrdup("Windows 98"); + return _WIN_OS_WIN98; + } + + if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 90)) { + WIN32_OS_string = xstrdup("Windows Me"); + return _WIN_OS_WINME; + } + + break; + case VER_PLATFORM_WIN32s: - WIN32_OS_string = xstrdup("Windows 3.1 with WIN32S"); - return _WIN_OS_WIN32S; - break; + WIN32_OS_string = xstrdup("Windows 3.1 with WIN32S"); + return _WIN_OS_WIN32S; + break; + default: - break; + break; } + WIN32_OS_string = xstrdup("Unknown Windows system"); return _WIN_OS_UNKNOWN; } @@ -101,10 +116,14 @@ int WIN32_Subsystem_Init() { WIN32_OS_version = GetOSVersion(); + if ((WIN32_OS_version == _WIN_OS_UNKNOWN) || (WIN32_OS_version == _WIN_OS_WIN32S)) - return 1; + return 1; + if (atexit(WIN32_Exit) != 0) - return 1; + return 1; + return 0; } + #endif