/*
- * $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/
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);
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;
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);
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<Prototype const *> * Registry;
- static void *Initialized;
- typedef Vector<Prototype const*>::iterator iterator;
- typedef Vector<Prototype const*>::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<Prototype const *> * Registry;
+ static void *Initialized;
+ typedef Vector<Prototype const*>::iterator iterator;
+ typedef Vector<Prototype const*>::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;
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;
int op;
acl *_acl;
ACLList *next;
- private:
+
+private:
static MemPool *Pool;
};
/*
- * $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/
#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 */
/*
- * $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/
#include "ACLRequestHeaderStrategy.h"
#include "ACLStrategised.h"
-class ACLBrowser {
- private:
+class ACLBrowser
+{
+
+private:
static ACL::Prototype RegistryProtoype;
static ACLStrategised<char const *> RegistryEntry_;
};
/*
- * $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/
class ACLCertificateStrategy : public ACLMatchStrategy<SSL *>
{
- public:
+
+public:
virtual int match (ACLData<MatchType> * &, 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<SSL*> UserRegistryEntry_;
static ACL::Prototype CARegistryProtoype;
/*
- * $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
{
/* 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);
}
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<class T>
ACLCertificateData::~ACLCertificateData()
{
safe_free (attribute);
+
if (values)
- values->destroy(xRefFree);
-}
+ values->destroy(xRefFree);
+}
template<class T>
inline int
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;
}
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);
}
}
/*
- * $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/
#include "ACLData.h"
#include "ssl_support.h"
-class ACLCertificateData : public ACLData<SSL *> {
- public:
+class ACLCertificateData : public ACLData<SSL *>
+{
+
+public:
void *operator new(size_t);
void operator delete(void *);
virtual void deleteSelf() const;
wordlist *dump();
void parse();
virtual ACLData<SSL *> *clone() const;
-
+
char *attribute;
SplayNode<char *> *values;
- private:
+
+private:
static MemPool *Pool;
SSLGETATTRIBUTE *sslAttributeCall;
};
/*
- * $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
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;
}
}
{
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);
}
currentAnswer(accessList->allow);
/* does the current AND clause match */
bool match = matchAclList(accessList->aclList);
+
if (match)
- markFinished();
+ markFinished();
else
- checkForAsync();
+ checkForAsync();
}
void
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;
cbdataReference(result);
return result;
}
-
+
void
ACLChecklist::operator delete (void *address)
{
}
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));
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);
}
void
ACLChecklist::NullState::checkForAsync(ACLChecklist *) const
-{
-}
+ {}
ACLChecklist::NullState ACLChecklist::NullState::_instance;
/*
- * $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/
#include "typedefs.h"
-class ACLChecklist {
- public:
+class ACLChecklist
+{
+
+public:
/* State class.
* This abstract class defines the behaviour of
* 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;
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;
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;
void markDestinationDomainChecked();
bool sourceDomainChecked() const;
void markSourceDomainChecked();
+
private:
CBDATA_CLASS(ACLChecklist);
ConnStateData *conn_; /* hack for ident and NTLM */
};
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 */
/*
- * $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/
#define SQUID_ACLDATA_H
template <class M>
-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;
/*
- * $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
{
/* 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);
}
}
ACLDestinationDomain::ACLDestinationDomain(ACLData<char const *> *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)
{
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");
}
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);
}
}
/*
- * $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/
#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;
ACLDestinationDomain(ACLData<char const *> *, 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;
{
/* 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);
}
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);
}
}
#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_;
/*
- * $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
{
/* 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);
}
ACLDomainData::~ACLDomainData()
{
if (domains)
- domains->destroy(xRefFree);
-}
+ domains->destroy(xRefFree);
+}
template<class T>
inline int
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;
}
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;
}
ACLDomainData::parse()
{
char *t = NULL;
+
while ((t = strtokFile())) {
- Tolower(t);
- domains = domains->insert(xstrdup(t), aclDomainCompare);
+ Tolower(t);
+ domains = domains->insert(xstrdup(t), aclDomainCompare);
}
}
/*
- * $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/
#include "ACL.h"
#include "ACLData.h"
-class ACLDomainData : public ACLData<char const *> {
- public:
+class ACLDomainData : public ACLData<char const *>
+{
+
+public:
void *operator new(size_t);
void operator delete(void *);
virtual void deleteSelf() const;
wordlist *dump();
void parse();
virtual ACLData<char const *> *clone() const;
-
+
SplayNode<char *> *domains;
- private:
+
+private:
static MemPool *Pool;
};
wordlist **W = static_cast<wordlist **>(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);
}
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);
}
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;
}
}
{
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;
}
* 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;
}
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;
+ }
}
}
}
int
+
ACLIP::match(struct in_addr &clientip)
{
static acl_ip_data ClientAddress (any_addr, any_addr, no_addr, NULL);
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;
}
{
/* 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);
}
}
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){}
#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<acl_ip_data *> 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);
};
{
/* 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);
}
}
ACLIdent::ACLIdent(ACLData<char const *> *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)
{
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;
}
}
{
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();
}
}
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();
}
#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;
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_;
/*
- * $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/
#include "ACLData.h"
/* Perhaps this should live in ACL? */
+
template<class M>
-class ACLMatchStrategy {
- public:
+
+class ACLMatchStrategy
+{
+
+public:
typedef M MatchType;
virtual int match (ACLData<M> * &, ACLChecklist *) = 0;
virtual bool requiresRequest() const {return false;}
- virtual ~ACLMatchStrategy(){}
-};
+
+ virtual ~ACLMatchStrategy(){}}
+
+;
#endif /* SQUID_ACLMATCHSTRATEGY_H */
{
/* 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);
}
#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;
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_;
{
/* 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);
}
}
ACLProxyAuth::ACLProxyAuth(ACLData<char const *> *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)
{
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();
}
ACLProxyAuth::match(ACLChecklist *checklist)
{
int ti;
+
if ((ti = checklist->authenticated()) != 1)
- return ti;
+ return ti;
+
ti = matchProxyAuth(checklist);
+
return ti;
}
{
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 */
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();
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;
}
#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;
ACLProxyAuth(ACLData<char const *> *, 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_;
/*
- * $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/
#include "ACLRequestHeaderStrategy.h"
#include "ACLStrategised.h"
-class ACLReferer {
- private:
+class ACLReferer
+{
+
+private:
static ACL::Prototype RegistryProtoype;
static ACLStrategised<char const *> RegistryEntry_;
};
/*
- * $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
{
/* 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);
}
ACLRegexData::~ACLRegexData()
{
aclDestroyRegexList(data);
-}
+}
bool
ACLRegexData::match(char const *user)
/*
- * $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/
#define SQUID_ACLREGEXDATA_H
#include "ACLData.h"
-class ACLRegexData : public ACLData<char const *> {
- public:
+class ACLRegexData : public ACLData<char const *>
+{
+
+public:
void *operator new(size_t);
void operator delete(void *);
virtual void deleteSelf() const;
virtual wordlist *dump();
virtual void parse();
virtual ACLData<char const *> *clone() const;
- private:
+
+private:
static MemPool *Pool;
relist *data;
};
/*
- * $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/
#include "ACLMatchStrategy.h"
template <http_hdr_type header>
+
class ACLRequestHeaderStrategy : public ACLMatchStrategy<char const *>
{
- public:
+
+public:
virtual int match (ACLData<char const *> * &, 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 &);
};
ACLRequestHeaderStrategy<header>::match (ACLData<char const *> * &data, ACLChecklist *checklist)
{
char const *theHeader = httpHeaderGetStr(&checklist->request->header, header);
+
if (NULL == theHeader)
- return 0;
+ return 0;
+
return data->match(theHeader);
}
/*
- * $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/
#include "ACLStrategised.h"
#include "ACLChecklist.h"
-class ACLRequestMIMEType {
- private:
+class ACLRequestMIMEType
+{
+
+private:
static ACL::Prototype RegistryProtoype;
static ACLStrategised<char const *> RegistryEntry_;
};
ACLRequestHeaderStrategy<HDR_CONTENT_TYPE>::match (ACLData<char const *> * &data, ACLChecklist *checklist)
{
char const *theHeader = httpHeaderGetStr(&checklist->request->header, HDR_CONTENT_TYPE);
+
if (NULL == theHeader)
- theHeader = "";
+ theHeader = "";
+
return data->match(theHeader);
}
/*
- * $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
{
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");
}
/*
- * $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/
class ACLSourceDomainStrategy : public ACLMatchStrategy<char const *>
{
- public:
+
+public:
virtual int match (ACLData<MatchType> * &, 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<char const *> LiteralRegistryEntry_;
static ACL::Prototype RegexRegistryProtoype;
{
/* 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);
}
#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_;
/*
- * $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/
#include "ACLMatchStrategy.h"
template <class M>
-class ACLStrategised : public ACL {
- public:
+
+class ACLStrategised : public ACL
+{
+
+public:
typedef M MatchType;
void *operator new(size_t);
void operator delete(void *);
ACLStrategised(ACLData<MatchType> *, ACLMatchStrategy<MatchType> *, 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<MatchType> *data;
char const *type_;
{
/* derived classes with different sizes must implement their own new */
assert (byteCount == sizeof (ACLStrategised<MatchType>));
+
if (!Pool)
- Pool = memPoolCreate("ACLStrategised", sizeof (ACLStrategised<MatchType>));
+ Pool = memPoolCreate("ACLStrategised", sizeof (ACLStrategised<MatchType>));
+
return memPoolAlloc(Pool);
}
template <class MatchType>
ACLStrategised<MatchType>::ACLStrategised(ACLData<MatchType> *newData, ACLMatchStrategy<MatchType> *theStrategy, char const *theType) : data (newData), type_(theType), matcher(theStrategy) {}
+
template <class MatchType>
ACLStrategised<MatchType>::ACLStrategised (ACLStrategised const &old) : data (old.data->clone()), type_(old.type_), matcher (old.matcher)
-{
-}
+{}
+
template <class MatchType>
ACLStrategised<MatchType> &
ACLStrategised<MatchType>::operator= (ACLStrategised const &rhs)
/*
- * $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/
class ACLTimeStrategy : public ACLMatchStrategy<time_t>
{
- public:
+
+public:
virtual int match (ACLData<MatchType> * &, 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<time_t> RegistryEntry_;
};
/*
- * $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
{
/* 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);
}
}
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&
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;
}
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;
}
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;
}
/*
- * $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/
#include "ACL.h"
#include "ACLData.h"
-class ACLTimeData : public ACLData<time_t> {
- public:
+class ACLTimeData : public ACLData<time_t>
+{
+
+public:
void *operator new(size_t);
void operator delete(void *);
virtual void deleteSelf() const;
wordlist *dump();
void parse();
virtual ACLData<time_t> *clone() const;
-
- private:
+
+private:
static MemPool *Pool;
int weekbits;
int start;
/*
- * $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/
class ACLUrlStrategy : public ACLMatchStrategy<char const *>
{
- public:
+
+public:
virtual int match (ACLData<char const *> * &, 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<char const *> RegistryEntry_;
/*
- * $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/
class ACLUrlPathStrategy : public ACLMatchStrategy<char const *>
{
- public:
+
+public:
virtual int match (ACLData<char const *> * &, 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<char const *> RegistryEntry_;
{
/* 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);
}
ACLUserData::~ACLUserData()
{
if (names)
- names->destroy(xRefFree);
-}
+ names->destroy(xRefFree);
+}
template<class T>
inline int
SplayNode<char *> *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;
}
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;
}
{
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);
}
}
#include "ACL.h"
#include "ACLData.h"
-class ACLUserData : public ACLData<char const *> {
- public:
+class ACLUserData : public ACLData<char const *>
+{
+
+public:
void *operator new(size_t);
void operator delete(void *);
virtual void deleteSelf() const;
wordlist *dump();
void parse();
virtual ACLData<char const *> *clone() const;
-
+
SplayNode<char *> *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;
};
/*
- * $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
#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);
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 *
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
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++;
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;
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++;
}
}
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
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
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
/*
- * $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 <robertc@squid-cache.org>
* 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 */
/*
- * $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 <robertc@squid-cache.org>
#include "DelayIdComposite.h"
class StoreEntry;
+
class AuthUserRequest;
-class CompositePoolNode : public RefCountable, public Updateable {
+
+class CompositePoolNode : public RefCountable, public Updateable
+{
+
public:
typedef RefCount<CompositePoolNode> 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 */
/*
- * $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/
#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_ */
/*
- * $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
#ifndef _SQUIDCONNECTIONDETAIL_H_
#define _SQUIDCONNECTIONDETAIL_H_
-class ConnectionDetail {
- public:
+class ConnectionDetail
+{
+
+public:
+
struct sockaddr_in me;
+
struct sockaddr_in peer;
};
/*
- * $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
#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 */
/*
- * $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 <robertc@squid-cache.org>
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
DelayBucket::init (DelaySpec const &rate)
{
level() = (int) (((double)rate.max_bytes *
- Config.Delay.initial) / 100);
+ Config.Delay.initial) / 100);
}
-
+
#endif
/*
- * $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/
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_;
};
/*
- * $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 <robertc@squid-cache.org>
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_);
{
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();
}
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);
}
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
/*
- * $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/
#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();
/*
- * $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 <robertc@squid-cache.org>
*/
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)
return pool_ == rhs.pool_ && compositeId == rhs.compositeId;
}
-DelayId::operator bool() const
+DelayId::operator bool() const
{
return pool_ || compositeId.getRaw();
}
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();
}
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;
}
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
/*
- * $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/
class ClientHttpRequest;
#include "DelayIdComposite.h"
-class DelayId {
- public:
+class DelayId
+{
+
+public:
static DelayId DelayClient (ClientHttpRequest *);
DelayId ();
DelayId (unsigned short);
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 */
/*
- * $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 <robertc@squid-cache.org>
#include "squid.h"
#include "RefCount.h"
-class DelayIdComposite : public RefCountable {
+class DelayIdComposite : public RefCountable
+{
+
public:
typedef RefCount<DelayIdComposite> Pointer;
virtual void deleteSelf() const = 0;
virtual inline ~DelayIdComposite(){}
+
virtual int bytesWanted (int min, int max) const =0;
virtual void bytesIn(int qty) = 0;
};
/*
- * $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 <robertc@squid-cache.org>
DelayPool::~DelayPool()
{
if (pool)
- freeData();
+ freeData();
+
if (access)
- aclDestroyAccessList(&access);
+ aclDestroyAccessList(&access);
}
void
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_);
}
/*
- * $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 <robertc@squid-cache.org>
#include "CompositePoolNode.h"
class StoreEntry;
+
class CommonPool;
+
class acl_access;
-class DelayPool {
- public:
+class DelayPool
+{
+
+public:
DelayPool();
~DelayPool();
void freeData();
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 */
/*
- * $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/
#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);
static void deregisterForUpdates (Updateable *);
static long MemoryUsed;
static DelayPool *delay_data;
- private:
+
+private:
static void Stats(StoreEntry *);
static void InitDelayData();
static time_t LastUpdate;
static void FreeDelayData ();
static Vector<Updateable *> toUpdate;
};
+
#endif /* SQUID_DELAYPOOLS_H */
/*
- * $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 <robertc@squid-cache.org>
#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);
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
/*
- * $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/
#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;
/*
- * $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 <robertc@squid-cache.org>
void
DelayUserFree(DelayUserBucket::Pointer &)
-{
-}
+{}
void
DelayUserStatsWalkee(DelayUserBucket::Pointer const ¤t, void *state)
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");
}
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)
{
/* This doesn't change the value of the DelayUserBucket, so is safe */
const_cast<DelayUserBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
}
+
void
DelayUser::update(int incr)
{
}
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);
}
{
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);
}
{
theBucket->theBucket.bytesIn(qty);
}
+
#endif
/*
- * $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 <robertc@squid-cache.org>
#include "Array.h"
#include "splay.h"
-class DelayUserBucket : public RefCountable {
- public:
+class DelayUserBucket : public RefCountable
+{
+
+public:
typedef RefCount<DelayUserBucket> Pointer;
void *operator new(size_t);
void operator delete (void *);
virtual void deleteSelf() const {delete this;}
+
void stats(StoreEntry *)const;
DelayUserBucket(AuthUser *);
~DelayUserBucket();
AuthUser *authUser;
};
-class DelayUser : public CompositePoolNode {
+class DelayUser : public CompositePoolNode
+{
+
public:
typedef RefCount<DelayUser> Pointer;
void *operator new(size_t);
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<DelayUserBucket::Pointer> buckets;
};
+
#endif /* DELAYUSER_H */
/*
- * $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 <robertc@squid-cache.org>
}
DelayVector::~DelayVector()
-{
-}
+{}
void
DelayVector::stats(StoreEntry * sentry)
{
iterator pos = pools.begin();
+
while (pos != pools.end()) {
- (*pos)->stats(sentry);
- ++pos;
+ (*pos)->stats(sentry);
+ ++pos;
}
}
DelayVector::dump(StoreEntry *entry) const
{
const_iterator pos = pools.begin();
+
while (pos != pools.end()) {
- (*pos)->dump(entry);
- ++pos;
+ (*pos)->dump(entry);
+ ++pos;
}
}
DelayVector::update(int incr)
{
iterator pos = pools.begin();
+
while (pos != pools.end()) {
- (*pos)->update(incr);
- ++pos;
+ (*pos)->update(incr);
+ ++pos;
}
}
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);
{
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;
}
}
{
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;
}
DelayVector::Id::bytesIn(int qty)
{
iterator pos = ids.begin();
+
while (pos != ids.end()) {
- (*pos)->bytesIn(qty);
- ++pos;
+ (*pos)->bytesIn(qty);
+ ++pos;
}
}
+
#endif
/*
- * $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/
#include "CompositePoolNode.h"
-class DelayVector : public CompositePoolNode{
+class DelayVector : public CompositePoolNode
+{
+
public:
typedef RefCount<DelayVector> Pointer;
void *operator new(size_t);
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<DelayIdComposite::Pointer> ids;
- typedef Vector<DelayIdComposite::Pointer>::iterator iterator;
- typedef Vector<DelayIdComposite::Pointer>::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<DelayIdComposite::Pointer> ids;
+ typedef Vector<DelayIdComposite::Pointer>::iterator iterator;
+ typedef Vector<DelayIdComposite::Pointer>::const_iterator const_iterator;
};
+
Vector<CompositePoolNode::Pointer> pools;
typedef Vector<CompositePoolNode::Pointer>::iterator iterator;
typedef Vector<CompositePoolNode::Pointer>::const_iterator const_iterator;
/*
- * $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
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;
}
/*
- * $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/
#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 */
/*
- * $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/
#define SQUID_GENERIC_H
template <class _Arg, class _Result>
-struct unary_function {
+
+struct unary_function
+{
typedef _Arg argument_type;
typedef _Result result_type;
};
T& for_each(L const &head, T& visitor)
{
for (L const *node = &head; node; node=node->next)
- visitor(*node);
+ visitor(*node);
+
return visitor;
}
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;
}
/*
- * $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
httpBodyClean(HttpBody * body)
{
assert(body);
+
if (!memBufIsNull(&body->mb))
- memBufClean(&body->mb);
+ memBufClean(&body->mb);
}
/* set body by absorbing mb */
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
{
return body->mb.buf ? body->mb.buf : "";
}
+
#endif
/*
- * $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
/* 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)
httpHdrCcParseCreate(const String * str)
{
HttpHdrCc *cc = httpHdrCcCreate();
+
if (!httpHdrCcParseInit(cc, str)) {
- httpHdrCcDestroy(cc);
- cc = NULL;
+ httpHdrCcDestroy(cc);
+ cc = NULL;
}
+
return cc;
}
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;
}
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++;
+ }
}
}
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;
}
{
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 */
{
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
{
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
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));
}
/*
- * $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
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;
}
/* 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);
}
/*
httpHdrContRangeParseCreate(const char *str)
{
HttpHdrContRange *r = httpHdrContRangeCreate();
+
if (!httpHdrContRangeParseInit(r, str)) {
- httpHdrContRangeDestroy(r);
- r = NULL;
+ httpHdrContRangeDestroy(r);
+ r = NULL;
}
+
return r;
}
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;
}
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
/*
- * $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/
#include "HttpHeaderRange.h"
/* http content-range header field */
-class HttpHdrContRange {
+
+class HttpHdrContRange
+{
+
public:
HttpHdrRangeSpec spec;
ssize_t elength; /* entity length, not content length */
/*
- * $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
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);
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 */
/* 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
{
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());
}
/*
- * $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
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);
}
{
delete this;
}
-
+
HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition){}
/* parses range-spec and returns new object on success */
HttpHdrRangeSpec::Create(const char *field, int flen)
{
HttpHdrRangeSpec spec;
+
if (!spec.parseInit(field, flen))
- return NULL;
+ return NULL;
+
return new HttpHdrRangeSpec(spec);
}
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;
}
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
*/
{
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);
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;
}
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);
}
{
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;
}
++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;
}
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());
}
{
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;
}
}
* 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());
}
HttpHdrRange::getCanonizedSpecs (Vector<HttpHdrRangeSpec *> ©)
{
/* 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"
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);
}
getCanonizedSpecs(goods);
merge (goods);
debug(64, 3) ("HttpHdrRange::canonize: finished with %d specs\n",
- specs.count);
+ specs.count);
return specs.count > 0;
}
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;
}
/* 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;
}
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;
}
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.
*/
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;
}
HttpHdrRangeIter::currentSpec() const
{
if (pos.incrementable())
- return *pos;
+ return *pos;
+
return NULL;
}
HttpHdrRangeIter::updateSpec()
{
assert (debt_size == 0);
+
if (pos.incrementable()) {
- debt(currentSpec()->length);
+ debt(currentSpec()->length);
}
}
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;
}
/*
- * $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
* 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)
*/
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;
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
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);
}
debug(55, 7) ("appending hdr: %p += %p\n", dest, src);
while ((e = httpHeaderGetEntry(src, &pos))) {
- httpHeaderAddEntry(dest, httpHeaderEntryClone(e));
+ httpHeaderAddEntry(dest, httpHeaderEntryClone(e));
}
}
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));
}
}
debug(55, 7) ("parsing hdr: (%p)\n%s\n", hdr, getStringPrefix(header_start, header_end));
HttpHeaderStats[hdr->owner].parsedCount++;
/* commonn format headers are "<name>:[ws]<value>" lines delimited by <CRLF> */
+
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 <CRLF> */
- 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 <CRLF> */
+
+ 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 */
}
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 */
{
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;
}
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 */
}
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;
}
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;
}
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;
}
-/* appends an entry;
+/* appends an entry;
* does not call httpHeaderEntryClone() so one should not reuse "*e"
*/
void
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;
}
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;
}
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;
}
/* 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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
{
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;
}
* 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;
}
{
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;
}
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);
}
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;
}
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;
}
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;
}
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);
}
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;
}
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());
}
}
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));
}
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;
}
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", "<br>");
+ httpHeaderStatDump(HttpHeaderStats + i, e);
+ storeAppendPrintf(e, "%s\n", "<br>");
}
+
/* 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);
}
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;
}
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);
}
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;
}
/*
- * $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/
#include "HttpHeaderRange.h"
/* constant attributes of http header fields */
-struct _HttpHeaderFieldAttrs {
+
+struct _HttpHeaderFieldAttrs
+{
const char *name;
http_hdr_type id;
field_type type;
/*
- * $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/
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<ssize_t> HttpRange;
static ssize_t const UnknownPosition;
-
+
HttpHdrRangeSpec();
static HttpHdrRangeSpec *Create(const char *field, int fieldLen);
bool mergeWith(const HttpHdrRangeSpec * donor);
ssize_t offset;
ssize_t length;
+
private:
static MemPool *Pool;
};
* 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 *);
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);
ssize_t lowestOffset(ssize_t) const;
bool offsetLimitExceeded() const;
Vector<HttpHdrRangeSpec *> specs;
+
private:
static MemPool *Pool;
void getCanonizedSpecs (Vector<HttpHdrRangeSpec *> ©);
};
/* data for iterating thru range specs */
-class HttpHdrRangeIter {
- public:
+
+class HttpHdrRangeIter
+{
+
+public:
HttpHdrRange::iterator pos;
const HttpHdrRangeSpec *currentSpec() const;
void updateSpec();
String boundary; /* boundary for multipart responses */
bool valid;
};
+
#endif /* SQUID_HTTPHEADERRANGE_H */
/*
- * $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
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;
}
httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * table, int count)
{
int i;
+
for (i = 0; i < count; ++i)
- table[i].name.clean();
+ table[i].name.clean();
+
xfree(table);
}
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]);
}
}
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;
id = va_arg(args, http_hdr_type);
fmt = va_arg(args, char *);
#endif
+
httpHeaderPutStrvf(hdr, id, fmt, args);
va_end(args);
}
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;
}
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;
}
*/
#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
}
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));
}
{
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;
}
{
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;
}
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
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
/*
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;
{
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);
}
/*
- * $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
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
* 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");
}
}
/*
- * $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
/* 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)
{
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;
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;
/* 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;
}
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);
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;
}
* 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;
}
httpReplyHdrCacheClean(rep);
/* update raw headers */
httpHeaderUpdate(&rep->header, &freshRep->header,
- (const HttpHeaderMask *) &Denied304HeadersMask);
+ (const HttpHeaderMask *) &Denied304HeadersMask);
/* init cache */
httpReplyHdrCacheInit(rep);
}
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;
}
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);
}
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);
}
/*
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;
}
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;
}
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;
}
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;
}
}
/*
- * $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/
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 */
/*
- * $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
request_t *req = static_cast<request_t *>(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;
}
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);
}
requestUnlink(request_t * request)
{
if (!request)
- return;
+ return;
+
assert(request->link_count > 0);
+
if (--request->link_count > 0)
- return;
+ return;
+
requestDestroy(request);
}
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;
}
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 */
{
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;
}
/*
{
assert(e);
/* check connection header */
+
if (strConn && strListIsMember(strConn, e->name.buf(), ','))
- return 0;
+ return 0;
+
return 1;
}
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
}
/*
- * $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
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 */
{
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 */
}
{
/* 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;
}
/*
- * $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/
* 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) */
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;
#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;
};
#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);
/*
- * $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
#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;
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
* 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;
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
/*
- * $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/
#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 */
/*
- * $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
#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 */
/*
- * $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
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)
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;
}
}
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;
}
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 */
}
}
#else
void
memBufPrintf(va_alist)
- va_dcl
+va_dcl
{
va_list args;
MemBuf *mb = NULL;
mb = va_arg(args, MemBuf *);
fmt = va_arg(args, char *);
#endif
+
memBufVPrintf(mb, fmt, args);
va_end(args);
}
/* 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--;
}
}
* (you still can read-access .buf and .size)
*/
FREE *
-memBufFreeFunc(MemBuf * mb)
-{
+memBufFreeFunc(MemBuf * mb) {
FREE *ff;
assert(mb);
assert(mb->buf);
/* 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;
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 */
/* 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");
}
/*
- * $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/
/* 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;
/* 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) */
/*
- * $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
xmemcpy(&ck, digest, sizeof(ck));
return ck;
}
+
#endif
MemPool *MemObject::pool = NULL;
{
/* 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);
}
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;
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);
}
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 *
struct LowestMemReader : public unary_function<store_client, void>
{
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<store_client, void>
{
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;
};
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);
}
size_t
MemObject::size() const
{
- if (object_sz < 0)
- return endOffset();
+ if (object_sz < 0)
+ return endOffset();
+
return object_sz;
}
LowestMemReader lowest (endOffset() + 1);
for_each (clients, lowest);
-
+
return lowest.current;
}
{
assert(chksum == url_checksum(url));
}
+
#endif
/*
* 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);
}
* 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;
}
* 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;
}
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;
}
#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
}
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
/*
- * $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/
#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 *);
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;
bool isContiguous() const;
int mostBytesWanted(int max) const;
#if DELAY_POOLS
+
DelayId mostBytesAllowed() const;
#endif
#if URL_CHECKSUM_DEBUG
+
void checkUrlChecksum() const;
#endif
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;
/*
- * $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 <robertc@squid-cache.org>
{
delete this;
}
+
#endif
/*
- * $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 <robertc@squid-cache.org>
#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 */
/*
- * $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
#else
void
packerPrintf(va_alist)
- va_dcl
+va_dcl
{
va_list args;
Packer *p = NULL;
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);
/*
- * $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
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);
}
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);
}
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
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);
}
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;
+ }
}
}
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);
xprof_chk_overhead(int samples)
{
while (samples--) {
- PROF_start(PROF_OVERHEAD);
- PROF_stop(PROF_OVERHEAD);
+ PROF_start(PROF_OVERHEAD);
+ PROF_stop(PROF_OVERHEAD);
}
}
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);
}
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);
/*
- * $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
#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 *);
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_;
/*
- * $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
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;
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);
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));
}
{
assert(Dest && Orig);
assert(Dest->bins);
+
if (Dest->capacity == Orig->capacity)
- statHistCopy(Dest, Orig);
+ statHistCopy(Dest, Orig);
}
void
{
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;
}
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);
}
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
{
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;
}
}
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
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);
}
/*
- * $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/
#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);
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;
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;
};
/*
- * $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/
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
#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 *);
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 *);
/*
- * $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/
#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;
/*
- * $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
#include "squid.h"
#include "StoreIOState.h"
-
+
void *
storeIOState::operator new (size_t amount)
{
return (void *)1;
}
-void
+void
storeIOState::operator delete (void *address){assert (0);}
storeIOState::storeIOState()
storeIOState::~storeIOState()
{
if (read.callback_data)
- cbdataReferenceDone(read.callback_data);
+ cbdataReferenceDone(read.callback_data);
+
if (callback_data)
- cbdataReferenceDone(callback_data);
+ cbdataReferenceDone(callback_data);
}
/*
- * $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/
#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 */
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 */
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<storeIOState> Pointer;
};
/*
- * $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
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;
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;
}
{
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);
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();
}
}
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;
}
/*
- * $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/
#define SQUID_TYPELENGTHVALUE_H
class StoreEntry;
+
typedef class StoreMeta tlv;
-class StoreMeta {
+
+class StoreMeta
+{
+
public:
virtual void deleteSelf() = 0;
static bool validType(char);
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:
};
/*
- * $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
{
/* 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);
}
delete this;
}
-bool
+bool
StoreMetaMD5::validLength(int len) const
{
return len == MD5_DIGEST_CHARS;
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;
}
/*
- * $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/
#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;
/*
- * $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
{
/* 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);
}
/*
- * $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/
#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;
};
/*
- * $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
{
/* 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);
}
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;
}
/*
- * $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/
#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;
};
/*
- * $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
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;
}
{
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;
}
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;
}
/*
- * $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/
#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();
/*
- * $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
{
/* 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);
}
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;
}
/*
- * $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/
#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;
};
/*
- * $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
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)
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)
{
String::clean()
{
assert(this);
+
if (buf_)
- memFreeString(size_, buf_);
+ memFreeString(size_, buf_);
+
len_ = 0;
+
size_ = 0;
+
buf_ = NULL;
}
{
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);
}
}
/*
- * $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
return result;
}
-SwapDir::~SwapDir() {
+SwapDir::~SwapDir()
+{
xfree(path);
}
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;
}
/*
- * $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/
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;
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 */
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 */
/*
- * $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
#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);
#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. */
int i;
char *buf;
char *buf_cursor;
+
if (header == NULL) {
- buf = static_cast<char *>(xcalloc(1, 1));
- *buf = '\0';
- return buf;
+ buf = static_cast<char *>(xcalloc(1, 1));
+ *buf = '\0';
+ return buf;
}
+
buf = static_cast<char *>(xcalloc(1, (strlen(header) * 3) + 1));
buf_cursor = buf;
/*
* 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;
}
int i;
char *buf;
char *buf_cursor;
+
if (header == NULL) {
- buf = static_cast<char *>(xcalloc(1, 1));
- *buf = '\0';
- return buf;
+ buf = static_cast<char *>(xcalloc(1, 1));
+ *buf = '\0';
+ return buf;
}
+
buf = static_cast<char *>(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;
}
accessLogFormatName(const char *name)
{
if (NULL == name)
- return NULL;
+ return NULL;
+
return username_quote(name);
}
{
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);
}
{
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);
}
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
}
#if FORW_VIA_DB
fvdbClear();
#endif
+
if (NULL == logfile)
- return;
+ return;
+
logfileRotate(logfile);
+
#if HEADERS_LOG
+
logfileRotate(headerslog);
+
#endif
}
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;
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;
}
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 <fvdb_entry *>(xcalloc(1, sizeof(fvdb_entry)));
- fv->hash.key = xstrdup(key);
- hash_join(hash, &fv->hash);
+ fv = static_cast <fvdb_entry *>(xcalloc(1, sizeof(fvdb_entry)));
+ fv->hash.key = xstrdup(key);
+ hash_join(hash, &fv->hash);
}
+
fv->n++;
}
{
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));
}
}
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);
}
}
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);
}
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;
}
/*
- * $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
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);
#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;
{
/* 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);
}
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;
}
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";
}
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;
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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
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().
/*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;
}
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;
}
}
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;
}
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;
}
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;
}
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
/* 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;
}
}
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;
}
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);
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);
}
}
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");
}
aclDestroyUserMaxIP(void *data)
{
acl_user_ip_data **acldata = (acl_user_ip_data **)data;
+
if (*acldata)
- cbdataFree(*acldata);
+ cbdataFree(*acldata);
+
*acldata = NULL;
}
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
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;
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;
}
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;
}
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
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;
}
}
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);
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;
}
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
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;
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;
}
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);
}
}
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();
}
}
{
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;
}
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;
}
{
intrange *w = NULL;
intrange *n = NULL;
+
for (w = list; w; w = n) {
- n = w->next;
- safe_free(w);
+ n = w->next;
+ safe_free(w);
}
}
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;
}
{
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;
}
{
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;
}
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;
}
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;
}
{
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;
}
{
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;
}
ACL::containsPURGE() const
{
if (aclMatchInteger((intlist *)data, METHOD_PURGE))
- return true;
+ return true;
+
return false;
}
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;
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;
}
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);
}
}
/* 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;
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;
}
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);
}
{
/* 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);
}
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 ();
}
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;
}
ACL::Prototype::registerMe ()
{
if (!Registry || (Initialized != ((char *)Registry - 5)) ) {
- /* TODO: extract this */
- /* Not initialised */
- Registry = new Vector <ACL::Prototype const *>;
- Initialized = (char *)Registry - 5;
+ /* TODO: extract this */
+ /* Not initialised */
+ Registry = new Vector <ACL::Prototype const *>;
+ 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");
}
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;
}
/*
- * $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
/* END of definitions for radix tree entries */
/* Head for ip to asn radix tree */
+
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;
};
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;
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);
/* PUBLIC */
int
+
asnMatchIp(void *data, struct in_addr addr)
{
unsigned long lh;
+
struct squid_radix_node *rn;
as_info *e;
m_int m_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;
}
{
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();
}
}
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 */
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);
}
asnFreeMemory(void)
{
squid_rn_walktree(AS_tree_head, destroyRadixNode, AS_tree_head);
+
destroyRadixNode((struct squid_radix_node *) 0, (void *) AS_tree_head);
}
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
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;
}
/*
* around for the next request
*/
leftoversz = (asState->reqofs + result.length) - (s - buf);
+
assert(leftoversz >= 0);
/*
* 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);
}
}
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;
}
{
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);
}
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;
}
/*
- * $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
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");
}
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;
}
authenticateBasicAuthenticated(auth_user_request_t * auth_user_request)
{
basic_data *basic_auth = static_cast<basic_data *>(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;
}
{
return strcmp(u1->username, u2->username);
}
+
#endif
/* log a basic user in
basic_auth = static_cast<basic_data *>(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<basic_data *>(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;
}
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);
}
}
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;
}
{
basic_data *basic_auth = static_cast<basic_data *>(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;
}
char *t = NULL;
void *cbdata;
debug(29, 9) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : "<NULL>");
+
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<basic_data *>(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);
}
auth_basic_config *config = static_cast<auth_basic_config *>(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);
}
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<auth_basic_config *>(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<auth_basic_config *>(scheme->scheme_data);
+ basicConfig->authenticateChildren = 5;
+ basicConfig->credentialsTTL = 2 * 60 * 60; /* two hours */
}
+
basicConfig = static_cast<auth_basic_config *>(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);
}
}
authenticateBasicUsername(auth_user_t const * auth_user)
{
basic_data *basic_auth = static_cast<basic_data *>(auth_user->scheme_data);
+
if (basic_auth)
- return basic_auth->username;
+ return basic_auth->username;
+
return NULL;
}
#if UNUSED_CODE
static void
authBasicDataFree(basic_data * basic_auth)
-{
-}
+{}
#endif
{
AuthUserHashPointer *usernamehash;
debug(29, 9) ("authBasicAuthUserFindUsername: Looking for user '%s'\n", username);
+
if (username && (usernamehash = static_cast<AuthUserHashPointer *>(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<AuthUserHashPointer *>(usernamehash->next);
- }
+ while (usernamehash) {
+ if ((authUserHashPointerUser(usernamehash)->auth_type == AUTH_BASIC) &&
+ !strcmp(username, (char const *)usernamehash->key))
+ return authUserHashPointerUser(usernamehash);
+
+ usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
+ }
}
+
return NULL;
}
/* 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 <oec@codeblau.de>
*/
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<basic_data *>(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<basic_data *>(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;
}
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);
}
}
assert(auth_user_request->auth_user->scheme_data != NULL);
basic_auth = static_cast<basic_data *>(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<BasicAuthQueueNode *>(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<BasicAuthQueueNode *>(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);
}
}
#define DefaultAuthenticateChildrenMax 32 /* 32 processes */
/* Generic */
-class AuthenticateStateData {
+
+class AuthenticateStateData
+{
+
public:
void *data;
auth_user_request_t *auth_user_request;
};
/* queue of auth requests waiting for verification to occur */
-class BasicAuthQueueNode {
+
+class BasicAuthQueueNode
+{
+
public:
BasicAuthQueueNode *next;
AuthUserRequest *auth_user_request;
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;
/*
- * $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
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)));
}
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;
* 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);
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);
}
}
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)
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
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;
}
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;
}
{
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;
}
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;
}
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
{
return strcmp(u1->username, u2->username);
}
+
#endif
static auth_user_t *
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;
}
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
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
}
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);
}
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 *
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
{
/* 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
}
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();
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
authscheme->FreeUser = authenticateDigestUserFree;
authscheme->AddHeader = authDigestAddHeader;
#if WAITING_FOR_TE
+
authscheme->AddTrailer = authDigestAddTrailer;
#endif
+
authscheme->authStart = authenticateDigestStart;
authscheme->authStats = authenticateDigestStats;
authscheme->authUserUsername = authenticateDigestUsername;
{
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;
}
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
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 */
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;
}
{
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));
}
}
{
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 */
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");
}
}
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);
char *t = NULL;
void *cbdata;
debug(29, 9) ("authenticateDigestHandleReply: {%s}\n", reply ? reply : "<NULL>");
+
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);
}
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);
}
}
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;
}
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);
}
}
{
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.
*/
{
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;
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;
}
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();
*/
/* 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 */
/* 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;
}
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);
#include "rfc2617.h"
/* Generic */
-class DigestAuthenticateStateData {
+
+class DigestAuthenticateStateData
+{
+
public:
void *data;
auth_user_request_t *auth_user_request;
};
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" */
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;
};
/* 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;
/* 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;
/*
- * $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
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");
}
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;
}
auth_ntlm_config *config = static_cast<auth_ntlm_config *>(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);
}
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<auth_ntlm_config *>(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<auth_ntlm_config *>(scheme->scheme_data);
+ ntlmConfig->authenticateChildren = 5;
+ ntlmConfig->challengeuses = 0;
+ ntlmConfig->challengelifetime = 60;
}
+
ntlmConfig = static_cast<auth_ntlm_config *>(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
* 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;
}
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);
}
}
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;
}
{
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;
}
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");
+ }
+ }
}
}
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);
}
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;
}
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<ProxyAuthCachePointer *>(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<ProxyAuthCachePointer *>(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;
}
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;
}
ntlm_user_t *ntlm_user;
ntlm_request_t *ntlm_request;
debug(29, 9) ("authenticateNTLMHandleReply: Helper: '%p' {%s}\n", lastserver, reply ? reply : "<NULL>");
+
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<ntlm_helper_state_t *>(helperStatefulServerGetData(static_cast<helper_stateful_server *>(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<helper_stateful_server *>(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<ntlm_helper_state_t *>(helperStatefulServerGetData(static_cast<helper_stateful_server *>(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<helper_stateful_server *>(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<ntlm_user_t *>(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<ntlm_user_t *>(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<ntlm_user_t *>(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<ntlm_user_t *>(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<ntlm_user_t *>(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<ntlm_user_t *>(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<ntlm_user_t *>(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<ntlm_helper_state_t *>(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<ntlm_user_t *>(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<ntlm_helper_state_t *>(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<ntlm_user_t *>(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<ntlm_user_t *>(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);
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;
}
/* 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;
}
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<ntlm_helper_state_t *>(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<ntlm_helper_state_t *>(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<ntlm_helper_state_t *>(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<ntlm_helper_state_t *>(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");
}
}
authenticateNTLMHelperServerAvailable(void *data)
{
ntlm_helper_state_t *statedata = static_cast<ntlm_helper_state_t *>(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;
}
authenticateNTLMHelperServerOnEmpty(void *data)
{
ntlm_helper_state_t *statedata = static_cast<ntlm_helper_state_t *>(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;
}
}
{
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;
}
}
authenticateNTLMUsername(auth_user_t const * auth_user)
{
ntlm_user_t *ntlm_user = static_cast<ntlm_user_t *>(auth_user->scheme_data);
+
if (ntlm_user)
- return ntlm_user->username;
+ return ntlm_user->username;
+
return NULL;
}
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<ntlm_user_t *>(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<ProxyAuthCachePointer *>(memPoolAlloc(ntlm_user_hash_pool));
proxy_auth_hash->key = xstrdup(key);
proxy_auth_hash->auth_user = auth_user;
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;
}
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;
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<ProxyAuthCachePointer *>(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<ntlm_user_t *>(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<ProxyAuthCachePointer *>(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<ntlm_user_t *>(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<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, ntlm_user->username)))) {
- while ((authUserHashPointerUser(usernamehash)->auth_type != auth_user->auth_type) && (usernamehash->next) && !authenticateNTLMcmpUsername(static_cast<ntlm_user_t *>(authUserHashPointerUser(usernamehash)->scheme_data), ntlm_user))
- usernamehash = static_cast<AuthUserHashPointer*>(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<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, ntlm_user->username)))
+ ) {
+ while ((authUserHashPointerUser(usernamehash)->auth_type != auth_user->auth_type) && (usernamehash->next) && !authenticateNTLMcmpUsername(static_cast<ntlm_user_t *>(authUserHashPointerUser(usernamehash)->scheme_data), ntlm_user)
+ )
+ usernamehash = static_cast<AuthUserHashPointer*>(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;
}
} 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? */
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 */
};
/* 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
/*
- * $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
{
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;
}
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;
}
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;
AuthUserRequest::username() const
{
if (auth_user)
- return auth_user->username();
+ return auth_user->username();
else
- return NULL;
+ return NULL;
}
size_t
{
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);
+ }
}
}
{
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
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;
}
{
/* 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;
AuthUser::username () const
{
if (auth_module <= 0)
- return NULL;
+ return NULL;
+
return authscheme_list[auth_module - 1].authUserUsername(this);
}
{
/* 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<auth_user_request_t *>(memPoolAlloc(pool));
}
}
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);
}
authenticateAuthUserRequestMessage(auth_user_request_t * auth_user_request)
{
if (auth_user_request)
- return auth_user_request->getDenyMessage();
+ return auth_user_request->getDenyMessage();
+
return NULL;
}
}
static void
+
authenticateAuthUserRequestSetIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr)
{
auth_user_ip_t *ipdata, *tempnode;
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;
}
}
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);
}
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
{
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;
}
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;
}
/*
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,
* 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;
* 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);
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;
}
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;
}
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;
}
{
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
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;
}
}
/* 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
{
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
{
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);
{
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
{
auth_user_request->unlock();
}
-
+
int
authenticateAuthUserInuse(auth_user_t * auth_user)
*/
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<auth_user_request_t *>(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<auth_user_request_t *>(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;
void
authenticateAuthUserMerge(auth_user_t * from, auth_user_t * to)
-{
+{
to->absorb (from);
}
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<auth_user_request_t *>(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<auth_user_request_t *>(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;
}
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);
}
}
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");
}
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);
}
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());
}
}
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<authscheme_entry_t *>(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]);
}
{
AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(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.
*/
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<AuthUserHashPointer *>(memPoolAlloc(pool));
}
}
AuthUserHashPointer::AuthUserHashPointer (auth_user_t * anAuth_user):
-auth_user (anAuth_user)
+ auth_user (anAuth_user)
{
key = (void *)anAuth_user->username();
next = NULL;
/*
- * $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/
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;
/* 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);
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 */
/* 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
*/
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 *);
}
* This defines an auth scheme module
*/
-struct _authscheme_entry {
+struct _authscheme_entry
+{
const char *typestr;
AUTHSACTIVE *Active;
AUTHSADDHEADER *AddHeader;
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 */
/*
- * $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
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);
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;
}
wordlistAdd(wordlist ** list, const char *key)
{
while (*list)
- list = &(*list)->next;
+ list = &(*list)->next;
+
*list = static_cast<wordlist *>(memAllocate(MEM_WORDLIST));
+
(*list)->key = xstrdup(key);
+
(*list)->next = NULL;
+
return (*list)->key;
}
wordlistJoin(wordlist ** list, wordlist ** wl)
{
while (*list)
- list = &(*list)->next;
+ list = &(*list)->next;
+
*list = *wl;
+
*wl = NULL;
}
wordlistAddWl(wordlist ** list, wordlist * wl)
{
while (*list)
- list = &(*list)->next;
+ list = &(*list)->next;
+
for (; wl; wl = wl->next, list = &(*list)->next) {
- *list = static_cast<wordlist *>(memAllocate(MEM_WORDLIST));
- (*list)->key = xstrdup(wl->key);
- (*list)->next = NULL;
+ *list = static_cast<wordlist *>(memAllocate(MEM_WORDLIST));
+ (*list)->key = xstrdup(wl->key);
+ (*list)->next = NULL;
}
}
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;
}
}
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;
}
{
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;
}
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;
}
{
char *end;
long ret = strtol(token, &end, 10);
+
if (ret == 0 && end == token)
- self_destruct();
+ self_destruct();
+
return ret;
}
{
char *end;
double ret = strtod(token, &end);
+
if (ret == 0 && end == token)
- self_destruct();
+ self_destruct();
+
return ret;
}
{
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;
}
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;
}
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;
}
/* 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 <andre@online.ee>:
- * 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 <andre@online.ee>:
+ * 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
}
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<time_t> (m * d / u);
}
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<int>(86400 * 365.2522);
+ return static_cast<int>(86400 * 365.2522);
+
if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR)))
- return static_cast<int>(86400 * 365.2522 * 10);
+ return static_cast<int>(86400 * 365.2522 * 10);
+
debug(3, 1) ("parseTimeUnits: unknown time unit '%s'\n", unit);
+
return 0;
}
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<size_t>(m * d / u);
}
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;
}
{
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;
}
}
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);
}
}
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");
}
}
}
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));
}
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");
}
}
l = cbdataAlloc(acl_address);
parse_address(&l->addr);
aclParseAclList(&l->aclList);
+
while (*tail)
- tail = &(*tail)->next;
+ tail = &(*tail)->next;
+
*tail = l;
}
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);
}
}
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");
}
}
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;
}
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);
}
}
{
cfg->parsePoolAccess();
}
+
#endif
#ifdef HTTP_VIOLATIONS
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);
+ }
}
}
{
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);
+ }
}
}
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);
}
}
{
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);
+ }
}
}
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
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");
}
}
allocate_new_authScheme(authConfig * cfg)
{
if (cfg->schemes == NULL) {
- cfg->n_allocated = 4;
- cfg->schemes = static_cast<authScheme *>(xcalloc(cfg->n_allocated, sizeof(authScheme)));
+ cfg->n_allocated = 4;
+ cfg->schemes = static_cast<authScheme *>(xcalloc(cfg->n_allocated, sizeof(authScheme)));
}
+
if (cfg->n_allocated == cfg->n_configured) {
- authScheme *tmp;
- cfg->n_allocated <<= 1;
- tmp = static_cast<authScheme *>(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<authScheme *>(xcalloc(cfg->n_allocated, sizeof(authScheme)));
+ xmemcpy(tmp, cfg->schemes, cfg->n_configured * sizeof(authScheme));
+ xfree(cfg->schemes);
+ cfg->schemes = tmp;
}
}
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);
}
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;
{
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);
}
}
allocate_new_swapdir(_SquidConfig::_cacheSwap * swap)
{
if (swap->swapDirs == NULL) {
- swap->n_allocated = 4;
- swap->swapDirs = static_cast<SwapDir **>(xcalloc(swap->n_allocated, sizeof(SwapDir *)));
+ swap->n_allocated = 4;
+ swap->swapDirs = static_cast<SwapDir **>(xcalloc(swap->n_allocated, sizeof(SwapDir *)));
}
+
if (swap->n_allocated == swap->n_configured) {
- SwapDir **tmp;
- swap->n_allocated <<= 1;
- tmp = static_cast<SwapDir **>(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<SwapDir **>(xcalloc(swap->n_allocated, sizeof(SwapDir *)));
+ xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *));
+ xfree(swap->swapDirs);
+ swap->swapDirs = tmp;
}
}
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);
}
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.
*/
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];
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;
}
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
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;
}
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");
+ }
}
}
{
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;
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;
}
}
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;
}
}
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);
}
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;
}
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;
}
}
p = static_cast<cachemgr_passwd *>(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;
}
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);
}
}
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;
}
}
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;
}
{
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);
}
{
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<domain_ping *>(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<domain_ping *>(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;
}
}
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<domain_type *>(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<domain_type *>(xcalloc(1, sizeof(domain_type)));
+ l->type = parseNeighborType(type);
+ l->domain = xstrdup(domain);
+
+ for (L = &(p->typelist); *L; L = &((*L)->next))
+
+ ;
+ *L = l;
}
}
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;
}
}
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;
}
}
free_ushortlist(ushortlist ** P)
{
ushortlist *u;
+
while ((u = *P) != NULL) {
- *P = u->next;
- xfree(u);
+ *P = u->next;
+ xfree(u);
}
}
+
#endif
static void
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
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;
}
}
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<refresh_t *>(xcalloc(1, sizeof(refresh_t)));
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);
}
{
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);
}
}
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
{
char *token = strtok(NULL, w_space);
safe_free(*var);
+
if (token == NULL)
- self_destruct();
+ self_destruct();
+
*var = xstrdup(token);
}
{
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);
}
{
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;
}
}
{
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;
}
}
int i;
i = GetInteger();
+
if (i < 0)
- i = 0;
+ i = 0;
+
*var = (u_short) i;
}
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;
}
}
{
char *token;
char *t = strtok(NULL, "");
+
while ((token = strwordtok(NULL, &t)))
- wordlistAdd(list, token);
+ wordlistAdd(list, token);
}
static int
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();
}
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);
}
free_removalpolicy(RemovalPolicySettings ** settings)
{
if (!*settings)
- return;
+ return;
+
free_string(&(*settings)->type);
+
free_wordlist(&(*settings)->args);
+
xfree(*settings);
+
*settings = NULL;
}
parse_removalpolicy(RemovalPolicySettings ** settings)
{
if (*settings)
- free_removalpolicy(settings);
+ free_removalpolicy(settings);
+
*settings = static_cast<RemovalPolicySettings *>(xcalloc(1, sizeof(**settings)));
+
parse_string(&(*settings)->type);
+
parse_wordlist(&(*settings)->args);
}
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");
}
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;
}
{
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<sockaddr_in_list *>(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;
}
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);
}
}
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;
}
}
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);
}
}
{
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();
}
}
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;
}
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;
}
}
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);
}
}
{
return NULL == s;
}
+
#endif
#if USE_SSL
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;
}
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;
}
}
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);
}
}
{
return NULL == s;
}
+
#endif
#endif /* USE_SSL */
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 *
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;
}
}
/*
- * $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
*
#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);
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;
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);
}
}
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;
}
{
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
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;
}
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
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);
usage(const char *prg_name)
{
fprintf(stderr, "usage: %s <label1>: <swap_state>... <label2>: <swap_state>...\n",
- prg_name);
+ prg_name);
return -1;
}
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;
/*
- * $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
#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);
{
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);
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);
}
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;
}
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;
}
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);
}
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);
}
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 : "<unknown>",
- fd_table[fd].ipaddr, mgr->action);
- else
- debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n",
- mgr->user_name ? mgr->user_name : "<unknown>",
- 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 : "<unknown>",
+ fd_table[fd].ipaddr, mgr->action);
+ else
+ debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n",
+ mgr->user_name ? mgr->user_name : "<unknown>",
+ 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 : "<unknown>",
- fd_table[fd].ipaddr, mgr->action);
+ mgr->user_name ? mgr->user_name : "<unknown>",
+ 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);
}
{
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 *
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";
}
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));
}
}
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;
}
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);
}
/*
- * $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
#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)
static const char *script_name = "/cgi-bin/cachemgr.cgi";
static const char *progname = NULL;
static time_t now;
+
static struct in_addr no_addr;
/*
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);
}
void Win32SockCleanup(void)
{
if (--s_iInitCount == 0)
- WSACleanup();
+ WSACleanup();
+
return;
}
+
#endif /* ifdef _SQUID_MSWIN_ */
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
printf("<HR noshade size=\"1px\">\n");
printf("<ADDRESS>\n");
printf("Generated %s, by %s/%s@%s\n",
- mkrfc1123(now), progname, VERSION, getfullhostname());
+ mkrfc1123(now), progname, VERSION, getfullhostname());
printf("</ADDRESS></BODY></HTML>\n");
}
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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
+
printf("<HTML><HEAD><TITLE>Cache Manager Interface</TITLE>\n");
+
printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE></HEAD>\n");
+
printf("<BODY><H1>Cache Manager Interface</H1>\n");
+
printf("<P>This is a WWW interface to the instrumentation interface\n");
+
printf("for the Squid object cache.</P>\n");
+
printf("<HR noshade size=\"1px\">\n");
+
printf("<FORM METHOD=\"POST\" ACTION=\"%s\">\n", script_name);
+
printf("<TABLE BORDER=\"0\" CELLPADDING=\"10\" CELLSPACING=\"1\">\n");
+
printf("<TR><TH ALIGN=\"left\">Cache Host:</TH><TD><INPUT NAME=\"host\" ");
+
printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", host);
+
printf("<TR><TH ALIGN=\"left\">Cache Port:</TH><TD><INPUT NAME=\"port\" ");
+
printf("size=\"30\" VALUE=\"%d\"></TD></TR>\n", port);
+
printf("<TR><TH ALIGN=\"left\">Manager name:</TH><TD><INPUT NAME=\"user_name\" ");
+
printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", user_name);
+
printf("<TR><TH ALIGN=\"left\">Password:</TH><TD><INPUT TYPE=\"password\" NAME=\"passwd\" ");
+
printf("size=\"30\" VALUE=\"\"></TD></TR>\n");
+
printf("</TABLE><BR CLEAR=\"all\">\n");
+
printf("<INPUT TYPE=\"submit\" VALUE=\"Continue...\">\n");
+
printf("</FORM>\n");
+
print_trailer();
}
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);
}
{
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;
}
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), "<LI type=\"circle\">%s (disabled)<A HREF=\"%s\">.</A>\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), "<LI type=\"circle\">%s (hidden)<A HREF=\"%s\">.</A>\n", d, a_url);
+ snprintf(html, sizeof(html), "<LI type=\"circle\">%s (disabled)<A HREF=\"%s\">.</A>\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), "<LI type=\"circle\">%s (requires <a href=\"%s\">authentication</a>)<A HREF=\"%s\">.</A>\n",
- d, menu_url(req, "authenticate"), a_url);
- else
- /* highlight protected but probably available entries */
- if (!strcmp(p, "protected"))
- snprintf(html, sizeof(html), "<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\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), "<LI type=\"circle\">%s (hidden)<A HREF=\"%s\">.</A>\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), "<LI type=\"circle\">%s (requires <a href=\"%s\">authentication</a>)<A HREF=\"%s\">.</A>\n",
+ d, menu_url(req, "authenticate"), a_url);
+ else
+ /* highlight protected but probably available entries */
+ if (!strcmp(p, "protected"))
+ snprintf(html, sizeof(html), "<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\n",
+ a_url, d);
+
/* public entry or unknown type of protection */
- else
- snprintf(html, sizeof(html), "<LI type=\"disk\"><A HREF=\"%s\">%s</A>\n", a_url, d);
+ else
+ snprintf(html, sizeof(html), "<LI type=\"disk\"><A HREF=\"%s\">%s</A>\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;
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 ? "</table>\n<pre>" : "", buf);
- table_line_num = 0;
- return html;
+ /* nope, just text */
+ snprintf(html, sizeof(html), "%s%s",
+ table_line_num ? "</table>\n<pre>" : "", buf);
+ table_line_num = 0;
+ return html;
}
+
/* start html table */
if (!table_line_num) {
- l += snprintf(html + l, sizeof(html) - l, "</pre><table cellpadding=\"2\" cellspacing=\"1\">\n");
- next_is_header = 0;
+ l += snprintf(html + l, sizeof(html) - l, "</pre><table cellpadding=\"2\" cellspacing=\"1\">\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, "<tr>");
+
/* 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</%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</%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, "</tr>\n");
{
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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
- printf("<HTML><HEAD><TITLE>CacheMgr@%s: %s</TITLE>\n",
- req->hostname, action);
- printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}TABLE{background-color:#333333;border:0pt;padding:0pt}TH,TD{background-color:#ffffff}--></STYLE>\n");
- printf("</HEAD><BODY>\n");
- if (parse_menu) {
- printf("<H2><a href=\"%s\">Cache Manager</a> menu for %s:</H2>",
- menu_url(req, "authenticate"), req->hostname);
- printf("<UL>\n");
- } else {
- printf("<P><A HREF=\"%s\">%s</A>\n<HR noshade size=\"1px\">\n",
- menu_url(req, "menu"), "Cache Manager menu");
- printf("<PRE>\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("</UL>\n");
- else
- printf("</table></PRE>\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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
+
+ printf("<HTML><HEAD><TITLE>CacheMgr@%s: %s</TITLE>\n",
+ req->hostname, action);
+
+ printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}TABLE{background-color:#333333;border:0pt;padding:0pt}TH,TD{background-color:#ffffff}--></STYLE>\n");
+
+ printf("</HEAD><BODY>\n");
+
+ if (parse_menu) {
+ printf("<H2><a href=\"%s\">Cache Manager</a> menu for %s:</H2>",
+ menu_url(req, "authenticate"), req->hostname);
+ printf("<UL>\n");
+ } else {
+ printf("<P><A HREF=\"%s\">%s</A>\n<HR noshade size=\"1px\">\n",
+ menu_url(req, "menu"), "Cache Manager menu");
+ printf("<PRE>\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("</UL>\n");
+ else
+ printf("</table></PRE>\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;
}
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
}
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
}
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;
}
read_get_request(void)
{
char *s;
+
if ((s = getenv("QUERY_STRING")) == NULL)
- return NULL;
+ return NULL;
+
return xstrdup(s);
}
{
#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;
}
* 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;
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;
}
/*
- * $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
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))
* 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);
}
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;
}
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);
}
}
/*
- * $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
#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)
{
#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);
}
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;
}
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;
}
{
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)
p->y = (long) p ^ CBDATA_COOKIE;
cbdataCount++;
#if CBDATA_DEBUG
+
p->file = file;
p->line = line;
p->calls = stackCreate();
dlinkAdd(p, &p->link, &cbdataEntries);
debug(45, 3) ("cbdataAlloc: %p %s:%d\n", &p->data, file, line);
#endif
+
return (void *) &p->data;
}
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;
}
#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++;
}
#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();
}
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;
}
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;
}
}
_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
{
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");
}
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<CBDataCall, void>
{
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;
};
CBDataHistoryDumper dumper(sentry);
for_each (cbdataEntries, dumper);
}
+
#endif
/*
- * $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
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;
Line *doc;
Line *nocomment;
int array_flag;
+
struct Entry *next;
-} Entry;
+}
+
+Entry;
static const char WS[] = " \t";
lineAdd(Line ** L, const char *str)
{
while (*L)
- L = &(*L)->next;
+ L = &(*L)->next;
+
*L = (Line *)xcalloc(1, sizeof(Line));
+
(*L)->data = xstrdup(str);
}
int rc = 0;
char *ptr = NULL;
#ifdef _SQUID_OS2_
+
const char *rmode = "rt";
#else
+
const char *rmode = "r";
#endif
*-------------------------------------------------------------------*/
/* 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);
/*-------------------------------------------------------------------*
*-------------------------------------------------------------------*/
/* 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);
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;
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
{
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");
}
{
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");
}
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;
}
{
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;
}
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");
+ }
}
}
/*
- * $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
/* 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;
#endif
static int put_fd;
static char *put_file = NULL;
+
static struct stat sb;
int total_bytes = 0;
int io_timeout = 120;
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);
}
extern char *optarg;
time_t ims = 0;
int max_forwards = -1;
+
struct timeval tv1, tv2;
int i = 0, loops;
long ping_int;
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
/*
- * $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
clientStreamNode *
clientStreamNew(CSR * readfunc, CSCB * callback, CSD * detach, CSS * status,
- void *data)
+ void *data)
{
clientStreamNode *temp;
CBDATA_INIT_TYPE_FREECB(clientStreamNode, clientStreamFree);
*/
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;
*/
void
clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback,
- CSD * detach, CSS * status, void *data)
+ CSD * detach, CSS * status, void *data)
{
clientStreamNode *temp;
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);
}
*/
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);
}
*/
void
clientStreamRead(clientStreamNode * thisObject, clientHttpRequest * http,
- StoreIOBuffer readBuffer)
+ StoreIOBuffer readBuffer)
{
/* place the parameters on the 'stack' */
clientStreamNode *prev;
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);
}
* 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);
}
}
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);
}
}
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);
}
}
_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;
}
/*
- * $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/
#include "StoreIOBuffer.h"
typedef struct _clientStreamNode clientStreamNode;
+
class ClientHttpRequest;
/* client stream read callback */
typedef void CSCB(clientStreamNode *, ClientHttpRequest *, HttpReply *, StoreIOBuffer);
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;
/*
- * $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
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;
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);
}
}
* -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;
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;
}
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
}
#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);
}
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;
}
/*
- * $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
*
*/
-/* 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
*/
/* 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;
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);
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
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);
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)
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;
httpRequestFree(context->http);
/* clean up connection links to us */
assert(context != context->next);
+
if (conn)
- context->removeFromConnectionList(conn);
+ context->removeFromConnectionList(conn);
}
ClientSocketContext *
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
* 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;
}
}
clientPingHasFinished(ping_data const *aPing)
{
if (0 != aPing->stop.tv_sec && 0 != aPing->start.tv_sec)
- return true;
+ return true;
+
return false;
}
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;
}
}
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);
}
ClientHttpRequest::memObject() const
{
if (entry)
- return entry->mem_obj;
+ return entry->mem_obj;
+
return NULL;
}
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);
}
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);
}
}
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
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;
}
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);
}
}
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);
}
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;
}
}
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 */
}
clientIsRequestBodyValid(int bodyLength)
{
if (bodyLength >= 0)
- return 1;
+ return 1;
+
return 0;
}
clientIsRequestBodyTooLargeForPolicy(size_t bodyLength)
{
if (Config.maxRequestBodySize &&
- bodyLength > Config.maxRequestBodySize)
- return 1; /* too large */
+ bodyLength > Config.maxRequestBodySize)
+ return 1; /* too large */
+
return 0;
}
connIsUsable(ConnStateData * conn)
{
if (!conn || conn->fd == -1)
- return 0;
+ return 0;
+
return 1;
}
responseFinishedOrFailed(HttpReply * rep, StoreIOBuffer const & recievedData)
{
if (rep == NULL && recievedData.data == NULL && recievedData.length == 0)
- return 1;
+ return 1;
+
return 0;
}
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);
}
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
{
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;
/* 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 <crlf> (we packed a header, not a reply) */
*/
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;
}
}
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;
}
{
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 : "<none>");
- 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 : "<none>");
+
+ 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;
}
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();
}
}
ClientSocketContext::prepareReply(HttpReply * rep)
{
if (http->request->range)
- buildRangeHeader(rep);
+ buildRangeHeader(rep);
}
void
/* 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? */
}
*/
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.
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
*/
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.
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! */
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
*/
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
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 */
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;
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;
}
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");
}
}
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;
}
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;
}
skipLeadingSpace(char *aString)
{
char *result = aString;
+
while (xisspace(*aString))
- ++aString;
+ ++aString;
+
return result;
}
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;
}
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;
}
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;
/* 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);
}
}
*/
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;
*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);
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);
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
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);
}
}
connAddContextToQueue(ConnStateData * conn, ClientSocketContext * context)
{
ClientSocketContext **S;
+
for (S = (ClientSocketContext **) & conn->currentobject; *S;
- S = &(*S)->next);
+ S = &(*S)->next)
+
+ ;
*S = context;
+
++conn->nrequests;
}
{
int result = 0;
ClientSocketContext **T;
+
for (T = (ClientSocketContext **) & conn->currentobject;
- *T; T = &(*T)->next, ++result);
+ *T; T = &(*T)->next, ++result)
+
+ ;
return result;
}
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;
}
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;
}
* 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
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();
}
clientMaybeReadData(ConnStateData *conn, int do_next_read)
{
if (do_next_read) {
- conn->flags.readMoreRequests = 1;
- clientReadSomeData(conn);
+ conn->flags.readMoreRequests = 1;
+ clientReadSomeData(conn);
}
}
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);
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;
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);
}
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;
}
}
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;
}
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);
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
* 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;
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);
}
}
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;
}
}
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 */
#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
}
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);
}
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);
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;
}
/* 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;
/* 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
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);
/* 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;
}
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);
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++;
}
{
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;
}
}
{
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;
}
}
{
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;
}
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;
+ }
}
}
* 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;
}
/*
- * $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)
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 ();
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 */
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);
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);
/* 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 */
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);
}
}
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
* @?@: 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
/* 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);
}
}
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
* 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;
}
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.
+ */
+ }
}
}
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);
}
}
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);
}
}
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);
}
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
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);
}
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.
* 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();
}
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();
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.
* RC: Yes.
*/
if (entry->store_status == STORE_OK) {
- return context->storeOKTransferDone();
+ return context->storeOKTransferDone();
} else {
- return context->storeNotOKTransferDone();
+ return context->storeNotOKTransferDone();
}
}
clientReplyContext::storeOKTransferDone() const
{
if (http->out.offset >= objectLen(http->entry) - headers_sz)
- return 1;
+ return 1;
+
return 0;
}
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;
}
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;
}
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.
*
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
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;
}
}
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();
}
}
/* 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
* 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);
}
{
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;
}
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
{
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();
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);
}
}
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
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 *
tempBuffer.length = next()->readBuffer.length - reqofs;
tempBuffer.data = next()->readBuffer.data + reqofs;
storeClientCopy(sc, http->entry,
- tempBuffer, clientSendMoreData, this);
+ tempBuffer, clientSendMoreData, this);
}
void
{
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
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
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");
}
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;
}
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;
* 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;
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;
}
/*
- * $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)
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;
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);
cbdataReference(result);
return result;
}
-
+
void
ClientRequestContext::operator delete (void *address)
{
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))
{
return result;
}
-void
+void
ClientHttpRequest::operator delete (void *address)
{
ClientHttpRequest *temp = static_cast<ClientHttpRequest *>(address);
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 */
}
/* 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
*/
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;
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 ?
/* 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;
}
{
ClientRequestContext *context = new ClientRequestContext(http);
context->acl_checklist =
- clientAclChecklistCreate(Config.accessList.http, http);
+ clientAclChecklistCreate(Config.accessList.http, http);
context->acl_checklist->nonBlockingCheck(clientAccessCheckDone, context);
}
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 : "<null>");
- debug(85, 5) ("Proxy Auth Message = %s\n",
- proxy_auth_msg ? proxy_auth_msg : "<null>");
- /*
- * 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
- * <pribeiro@isel.pt>
- */
- 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 : "<null>");
+ debug(85, 5) ("Proxy Auth Message = %s\n",
+ proxy_auth_msg ? proxy_auth_msg : "<null>");
+ /*
+ * 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
+ * <pribeiro@isel.pt>
+ */
+ 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);
}
}
{
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;
}
* 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;
}
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
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();
}
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));
}
}
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();
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();
}
{
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 */
/*
- * $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/
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 *);
/* Not implemented - present to prevent synthetic operations */
ClientHttpRequest(ClientHttpRequest const &);
ClientHttpRequest& operator=(ClientHttpRequest const &);
-
+
String rangeBoundaryStr() const;
void freeResources();
void updateCounters();
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);
};
/*
- * $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
*/
#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);
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;
int
comm_existsiocallback(void)
{
- return CommCallbackList.head == NULL;
+ return CommCallbackList.head == NULL;
}
/*
*/
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));
}
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));
}
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;
+ };
}
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);
+ }
}
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;
}
/*
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);
}
/*
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
}
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);
}
#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
}
* - 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 */
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);
}
/*
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);
}
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);
}
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);
}
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);
}
/*
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
}
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;
}
/*
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);
}
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);
}
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));
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;
}
* 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);
}
* 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;
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;
}
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);
cs->data = NULL;
commSetTimeout(fd, -1, NULL, NULL);
commConnectFree(fd, cs);
+
if (cbdataReferenceValid(cbdata))
- callback(fd, status, cbdata);
+ callback(fd, status, cbdata);
+
cbdataReferenceDone(cbdata);
}
{
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;
* 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;
}
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);
}
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;
}
}
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;
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 <matusita@ics.es.osaka-u.ac.jp> */
- 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 <matusita@ics.es.osaka-u.ac.jp> */
+
+ 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;
}
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 */
{
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);
}
}
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);
}
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
/*
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);
}
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 */
/* 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;
}
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;
}
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;
}
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
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;
}
{
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;
}
#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
}
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
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);
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);
}
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;
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 */
}
{
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);
+ }
}
}
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);
+ }
}
}
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);
}
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;
}
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;
+ }
}
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
}
}
void
-CommIO::ResetNotifications()
+CommIO::ResetNotifications()
{
if (DoneSignalled) {
- FlushPipe();
- DoneSignalled = false;
+ FlushPipe();
+ DoneSignalled = false;
}
}
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);
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);
}
};
/*
- * $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
*
static void kq_update_events(int, short, PF *);
static int kq;
+
static struct timespec zero_timespec;
static struct kevent *kqlst; /* kevent buffer */
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;
}
if ((cur_handler == NULL && handler != NULL)
- || (cur_handler != NULL && handler == NULL)) {
+ || (cur_handler != NULL && handler == NULL)) {
+
struct kevent *kep;
kep = kqlst + kqoff;
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
+
}
}
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;
*/
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);
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;
comm_select(int msec)
{
int num, i;
+
static struct kevent ke[KE_LENGTH];
+
struct timespec poll_time;
/*
* 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.. */
/* 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;
}
/*
- * $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
*
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;
}
fdIsDns(int fd)
{
if (fd == DnsSocket)
- return 1;
+ return 1;
+
return 0;
}
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;
}
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
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;
}
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);
}
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);
}
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;
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;
}
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);
}
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;
{
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");
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--;
}
}
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--;
}
}
/*
- * $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
*
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;
}
fdIsIcp(int fd)
{
if (fd == theInIcpConnection)
- return 1;
+ return 1;
+
if (fd == theOutIcpConnection)
- return 1;
+ return 1;
+
return 0;
}
fdIsDns(int fd)
{
if (fd == DnsSocket)
- return 1;
+ return 1;
+
return 0;
}
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;
}
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
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;
}
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);
}
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);
}
fd_set pendingfds;
fd_set writefds;
#if DELAY_POOLS
+
fd_set slowfds;
#endif
+
PF *hdl = NULL;
int fd;
int maxfd;
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;
* 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");
}
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;
}
/*
- * $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
{
#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
#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
/*
*/
/* 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();
}
/*
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;
}
/*
* 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 "<lost>";
+ return "<lost>";
+
return Ctx_Descrs[ctx] ? Ctx_Descrs[ctx] : "<null>";
}
/*
- * $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 <robertc@squid-cache.org>
long DelayPools::MemoryUsed = 0;
-class Aggregate : public CompositePoolNode {
- public:
+class Aggregate : public CompositePoolNode
+{
+
+public:
typedef RefCount<Aggregate> Pointer;
void *operator new(size_t);
void operator delete (void *);
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 Key, class Value>
-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<VectorPool> 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<unsigned char, DelayBucket> 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;
void initHostIndex (DelaySpec &rate, unsigned char index, unsigned char host);
void update (DelaySpec const &, int incr);
void stats(StoreEntry *)const;
-
+
DelayBucket net;
VectorMap<unsigned char, DelayBucket> individuals;
};
-class ClassCHostPool : public CompositePoolNode {
- public:
+class ClassCHostPool : public CompositePoolNode
+{
+
+public:
typedef RefCount<ClassCHostPool> 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<unsigned char, ClassCBucket> 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;
};
};
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)
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);
}
}
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;
}
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 */
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");
}
}
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 *
}
Aggregate::AggregateId::AggregateId(Aggregate::Pointer anAggregate) : theAggregate(anAggregate)
-{
-}
+{}
int
Aggregate::AggregateId::bytesWanted (int min, int max) const
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);
}
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<Updateable *>::iterator pos = toUpdate.begin();
+
while (pos != toUpdate.end()) {
- (*pos)->update(incr);
- ++pos;
+ (*pos)->update(incr);
+ ++pos;
}
}
DelayPools::deregisterForUpdates (Updateable *anObject)
{
Vector<Updateable *>::iterator pos = toUpdate.begin();
+
while (pos != toUpdate.end() && *pos != anObject) {
- ++pos;
+ ++pos;
}
+
if (pos != toUpdate.end()) {
- /* move all objects down one */
- Vector<Updateable *>::iterator temp = pos;
- ++pos;
- while (pos != toUpdate.end()) {
- *temp = *pos;
- ++temp;
- ++pos;
- }
- toUpdate.pop_back();
+ /* move all objects down one */
+ Vector<Updateable *>::iterator temp = pos;
+ ++pos;
+
+ while (pos != toUpdate.end()) {
+ *temp = *pos;
+ ++temp;
+ ++pos;
+ }
+
+ toUpdate.pop_back();
}
}
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);
}
DelayPools::FreePools()
{
if (!DelayPools::pools())
- return;
+ return;
+
FreeDelayData();
}
unsigned short
-DelayPools::pools()
+DelayPools::pools()
{
return pools_;
}
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 <class Key, class Value>
VectorMap<Key,Value>::VectorMap() : nextMapPosition(0)
-{
-}
+{}
template <class Key, class Value>
-unsigned int
+unsigned int
VectorMap<Key,Value>::size() const
{
return nextMapPosition;
}
-
+
template <class Key, class Value>
unsigned int
VectorMap<Key,Value>::insert (Key const key)
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");
}
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
VectorMap<Key,Value>::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);
}
}
VectorPool::Id::Id (VectorPool::Pointer aPool, int anIndex) : theVector (aPool), theIndex (anIndex)
-{
-}
+{}
int
VectorPool::Id::bytesWanted (int min, int max) const
}
unsigned int const
+
IndividualPool::makeKey (struct in_addr &src_addr) const
{
unsigned int host;
}
unsigned int const
+
ClassCNetPool::makeKey (struct in_addr &src_addr) const
{
unsigned int net;
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");
}
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
}
unsigned char const
+
ClassCHostPool::makeHostKey (struct in_addr &src_addr) const
{
unsigned int host;
}
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);
}
}
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
/*
- * $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
{
return fd_table[fd].disk.write_q ? 0 : 1;
}
+
#endif
void
{
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;
}
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);
}
* select() loop. --SLF
*/
static void
+
diskCombineWrites(struct _fde_disk *fdd)
{
int len = 0;
* 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;
}
}
{
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);
}
/* 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];
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);
}
* 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
/*
- * $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
{
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;
}
}
dnsShutdown(void)
{
if (!dnsservers)
- return;
+ return;
+
helperShutdown(dnsservers);
+
wordlistDestroy(&dnsservers->cmdline);
+
if (!shutting_down)
- return;
+ return;
+
helperFree(dnsservers);
+
dnsservers = NULL;
}
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);
}
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 */
/*
- * $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
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;
int attempt;
};
-struct _ns {
+struct _ns
+{
+
struct sockaddr_in S;
int nqueries;
int nreplies;
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);
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++;
}
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);
}
}
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);
}
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
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");
}
}
idnsTickleQueue(void)
{
if (event_queued)
- return;
+ return;
+
if (NULL == lru_list.tail)
- return;
+ return;
+
eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, 1.0, 1);
+
event_queued = 1;
}
{
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;
}
{
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;
}
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);
}
{
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
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();
}
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]++;
}
/* ====================================================================== */
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++;
}
}
idnsShutdown(void)
{
if (DnsSocket < 0)
- return;
+ return;
+
comm_close(DnsSocket);
+
DnsSocket = -1;
+
idnsFreeNameservers();
}
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;
}
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;
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 */
/*
- * $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
* 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_ */
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() */
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
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");
}
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
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
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;
}
/*
- * $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/
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 {
/*
- * $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
/* local types */
-typedef struct {
+typedef struct
+{
int id;
char *page_name;
-} ErrorDynamicPageInfo;
+}
+
+ErrorDynamicPageInfo;
/* local constant and vars */
* 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<BR clear=\"all\">\n"
- "<HR noshade size=\"1px\">\n"
- "<ADDRESS>\n"
- "Generated %T by %h (%s)\n"
- "</ADDRESS>\n"
- "</BODY></HTML>\n"
- },
- {
- TCP_RESET,
- "reset"
- }
-};
+}
+
+error_hard_text[] = {
+
+ {
+ ERR_SQUID_SIGNATURE,
+ "\n<BR clear=\"all\">\n"
+ "<HR noshade size=\"1px\">\n"
+ "<ADDRESS>\n"
+ "Generated %T by %h (%s)\n"
+ "</ADDRESS>\n"
+ "</BODY></HTML>\n"
+ },
+ {
+ TCP_RESET,
+ "reset"
+ }
+ };
static Vector<ErrorDynamicPageInfo *> ErrorDynamicPages;
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;
}
const char *text;
error_page_count = ERR_MAX + ErrorDynamicPages.size();
error_text = static_cast<char **>(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);
+ }
+ }
}
}
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;
}
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;
}
/* 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;
}
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;
}
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;
}
{
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;
}
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 */
}
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);
* 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);
}
{
ErrorState *err = static_cast<ErrorState *>(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);
}
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);
}
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);
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;
}
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;
}
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;
}
/*
- * $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
#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;
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);
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;
}
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);
}
}
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;
}
/*
- * $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
#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);
* 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;
/******************************************************************
* external_acl directive
*/
-struct _external_acl {
+
+struct _external_acl
+{
external_acl *next;
int ttl;
int negative_ttl;
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;
{
external_acl *p = static_cast<external_acl *>(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<external_acl_entry *>(p->lru_list.tail->data));
+ external_acl_cache_delete(p, static_cast<external_acl_entry *>(p->lru_list.tail->data));
if (p->cache)
- hashFreeMemory(p->cache);
+ hashFreeMemory(p->cache);
}
void
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;
}
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");
}
}
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);
}
}
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;
}
* external acl type
*/
-struct _external_acl_data {
+struct _external_acl_data
+{
external_acl *def;
wordlist *arguments;
};
external_acl_data **datap = static_cast<external_acl_data **>(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;
}
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<external_acl_entry *>(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<external_acl_entry *>(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);
* 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;
}
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;
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;
}
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)
{
{
external_acl_entry *entry = static_cast<external_acl_entry *>(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<external_acl_entry *>(def->lru_list.tail->data));
+ external_acl_cache_delete(def, static_cast<external_acl_entry *>(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);
*/
typedef struct _externalAclState externalAclState;
-struct _externalAclState {
+
+struct _externalAclState
+{
EAH *callback;
void *callback_data;
char *key;
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);
}
external_acl_entry *entry = static_cast<external_acl_entry *>(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<externalAclState *>(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<externalAclState *>(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<external_acl_entry *>(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<external_acl_entry *>(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);
}
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");
}
}
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);
}
}
externalAclShutdown(void)
{
external_acl *p;
+
for (p = Config.externalAclHelperList; p; p = p->next) {
- helperShutdown(p->theHelper);
+ helperShutdown(p->theHelper);
}
}
/*
- * $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
#endif
const char *fdTypeStr[] =
-{
- "None",
- "Log",
- "File",
- "Socket",
- "Pipe",
- "Unknown"
-};
+ {
+ "None",
+ "Log",
+ "File",
+ "Socket",
+ "Pipe",
+ "Unknown"
+ };
static void fdUpdateBiggest(int fd, int);
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);
{
return (_write(fd, buf, len));
}
+
#else
int
default_read_method(int fd, char *buf, int len)
{
return (write(fd, buf, len));
}
+
#endif
void
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++;
}
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
{
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);
}
}
/*
* 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;
}
/*
- * $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
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 ;
}
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
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);
}
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;
}
/*
- * $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/
#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);
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;
READ_HANDLER *read_method;
WRITE_HANDLER *write_method;
#if USE_SSL
+
SSL *ssl;
- int ssl_shutdown:1;
+
+int ssl_shutdown:
+ 1;
#endif
};
/*
- * $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
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;
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;
}
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);
}
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);
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
/*
- * $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
fwdStateServerPeer(FwdState * fwdState)
{
if (NULL == fwdState)
- return NULL;
+ return NULL;
+
if (NULL == fwdState->servers)
- return NULL;
+ return NULL;
+
return fwdState->servers->_peer;
}
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);
}
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;
}
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);
}
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);
}
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
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);
}
}
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;
}
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);
}
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);
}
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++;
/*
* 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);
}
{
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);
}
}
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;
+ }
}
}
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);
fwdServersFree(FwdServer ** FS)
{
FwdServer *fs;
+
while ((fs = *FS)) {
- *FS = fs->next;
- fwdServerFree(fs);
+ *FS = fs->next;
+ fwdServerFree(fs);
}
}
* 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;
{
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;
}
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);
}
}
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
}
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]++;
}
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");
}
}
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 */
}
fwdUninit(void)
{
if (NULL == logfile)
- return;
+ return;
+
logfileClose(logfile);
+
logfile = NULL;
}
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
/*
- * $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
typedef struct _fqdncache_entry fqdncache_entry;
-struct _fqdncache_entry {
+struct _fqdncache_entry
+{
hash_link hash; /* must be first */
time_t lastref;
time_t expires;
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;
{
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);
}
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;
}
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;
}
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);
}
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 */
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;
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);
}
memset(&f, '\0', sizeof(f));
f.expires = squid_curtime;
f.flags.negcached = 1;
+
if (inbuf == NULL) {
- debug(35, 1) ("fqdncacheParse: Got <NULL> reply\n");
- return &f;
+ debug(35, 1) ("fqdncacheParse: Got <NULL> 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 <NULL>, expecting '$name'\n");
- return &f;
+ debug(35, 1) ("fqdncacheParse: Got <NULL>, 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 <NULL>, expecting TTL\n");
- return &f;
+ debug(35, 1) ("fqdncacheParse: Got <NULL>, 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)
{
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
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;
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);
c = cbdataAlloc(generic_cbdata);
c->data = f;
#if USE_DNSSERVERS
+
dnsSubmit(hashKeyStr(&f->hash), fqdncacheHandleReply, c);
#else
+
idnsPTRLookup(addr, fqdncacheHandleReply, c);
#endif
}
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;
}
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");
}
}
}
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;
}
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);
}
}
{
assert(f->locks > 0);
f->locks--;
+
if (fqdncacheExpiredEntry(f))
- fqdncacheRelease(f);
+ fqdncacheRelease(f);
}
static void
{
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);
}
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();
}
{
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;
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;
}
/*
- * $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 <slf@connect.com.au>
};
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;
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;
};
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;
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;
}
MemPool *pool;
if ((pool = squidaio_get_pool(size)) != NULL) {
- p = memPoolAlloc(pool);
+ p = memPoolAlloc(pool);
} else
- p = xmalloc(size);
+ p = xmalloc(size);
return p;
}
MemPool *pool;
if ((pool = squidaio_get_pool(size)) != NULL) {
- memPoolFree(pool, p);
+ memPoolFree(pool, p);
} else
- xfree(p);
+ xfree(p);
}
static void
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
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;
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);
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 */
{
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;
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 */
/* 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 */
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 */
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
int len;
if (!squidaio_initialised)
- squidaio_init();
+ squidaio_init();
+
requestp = memPoolAlloc(squidaio_request_pool);
+
resultp->result_type = _AIO_OP_OPENDIR;
+
return -1;
}
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;
}
}
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 */
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();
}
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;
}
}
/*
- * $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 <pete@demon.net>
#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;
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;
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;
aioFDWasClosed(int fd)
{
if (fd_table[fd].flags.closing)
- fd_close(fd);
+ fd_close(fd);
}
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;
}
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);
}
}
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);
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);
} /* aioRead */
void
+
aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data)
{
squidaio_ctrl_t *ctrlp;
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;
}
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");
}
};
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;
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 *);
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 *);
#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 *);
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_;
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 *);
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();
};
* 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
/*
- * $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
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;
}
#if USE_TRUNCATE_NOT_UNLINK
aioTruncate(path, NULL, NULL);
#else
+
aioUnlink(path, NULL, NULL);
#endif
}
/* ========== 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
cbdataReference(result);
return result;
}
-
+
void
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;
* NULL here.
*/
#ifdef MAGIC2
+
if (aioQueueSize() > MAGIC2)
- return true;
+ return true;
+
#endif
+
return false;
}
+
void
AufsIO::deleteSelf() const
{
cbdataReference(result);
return result;
}
-
+
void
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);
{
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
}
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
}
{
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
}
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;
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 <UFSStrategy *>(((AUFSSwapDir *)SD)->IO);
assert (IO);
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);
}
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;
}
{
AUFSFile *myFile = static_cast<AUFSFile *>(my_data);
assert (myFile);
- myFile->readDone (fd, buf, len, errflag);
+ myFile->readDone (fd, buf, len, errflag);
}
void
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);
}
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
}
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;
}
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__);
}
squidaiostate_t *aiostate = dynamic_cast<squidaiostate_t *>(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);
}
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");
}
* 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"
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;
}
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;
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 */
/* 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;
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 */
/* 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);
}
}
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;
}
* 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);
}
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;
};
/* 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 */
/* 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);
#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 *.
*/
/* 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 *);
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 */
extern MemPool *coss_membuf_pool;
extern MemPool *coss_index_pool;
-class CossSwapDir : public SwapDir
+class CossSwapDir : public SwapDir
{
+
public:
CossSwapDir();
virtual void init();
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;
/*
- * $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
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 *);
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;
}
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);
}
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;
}
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);
}
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);
}
* 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;
*/
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);
}
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;
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 &);
#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
{
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);
::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;
CossCleanLog::nextEntry()
{
const StoreEntry *entry;
+
if (!current)
- return NULL;
+ return NULL;
+
entry = (const StoreEntry *) current->data;
+
current = current->prev;
+
return entry;
}
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;
}
}
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"
/* 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;
}
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
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;
}
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");
}
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");
}
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);
}
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
/*
static void
storeCossDirDone(void)
{
-/* memPoolDestroy(&coss_index_pool); XXX Should be here? */
+ /* memPoolDestroy(&coss_index_pool); XXX Should be here? */
coss_initialised = 0;
}
/*
- * $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
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)
-{
-}
+{}
/*
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;
}
}
StoreIOState::Pointer
CossSwapDir::openStoreIO(StoreEntry & e, STFNCB * file_callback,
- STIOCB * callback, void *callback_data)
+ STIOCB * callback, void *callback_data)
{
char *p;
CossState *cstate;
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;
}
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);
}
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);
}
}
assert(dest != NULL);
xmemcpy(dest, buf, size);
offset_ += size;
+
if (free_func)
- (free_func) ((char *)buf);
+ (free_func) ((char *)buf);
}
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
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);
}
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;
}
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);
}
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);
}
}
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);
}
}
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);
}
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;
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;
}
* Clean up any references from the SIO before it get's released.
*/
CossState::~CossState()
-{
-}
+{}
_MQD_UNLINK
};
-struct _diomsg {
+struct _diomsg
+{
mtyp_t mtype;
int id;
int seq_no;
/*
- * $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
typedef struct _file_state file_state;
-struct _file_state {
+struct _file_state
+{
void *key;
file_state *next;
int id;
* 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;
}
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);
}
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;
}
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;
}
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;
}
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;
}
}
diomsg smsg;
int rlen;
char rbuf[512];
+
struct sigaction sa;
setbuf(stdout, NULL);
setbuf(stderr, NULL);
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);
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;
}
/*
- * $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
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);
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();
}
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);
}
/*
{
static time_t lastmsg = 0;
DiskdIO *DIO = dynamic_cast<DiskdIO *>(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();
}
}
int retval = 0;
DiskdIO *DIO = dynamic_cast<DiskdIO *>(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;
}
DiskdSwapDir::canStore(StoreEntry const &e)const
{
if (IO->shedLoad())
- return -1;
+ return -1;
+
return IO->load();
}
#if USE_UNLINKD
unlinkdUnlink(path);
#elif USE_TRUNCATE
+
truncate(path, 0);
#else
+
unlink(path);
#endif
-
+
}
/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */
DiskdIO *IO = dynamic_cast<DiskdIO *>(((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
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
}
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
* 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 *);
/* 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 *);
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;
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;
extern void storeDiskdHandle(diomsg * M);
#include "SwapDir.h"
+
class DiskdSwapDir : public UFSSwapDir
{
+
public:
virtual void init();
virtual void dump(StoreEntry &)const;
#define SHMBUF_BLKSZ SM_PAGE_SIZE
extern diskd_stats_t diskd_stats;
+
class DiskdIO : public UFSStrategy
{
+
public:
DiskdIO();
virtual bool shedLoad();
/*
- * $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
/* === PUBLIC =========================================================== */
DiskdIO::DiskdIO() : away (0), magic1(64), magic2(72)
-{
-}
+{}
bool
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;
}
}
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;
}
{
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);
}
}
debug (79,3)("diskdFile with base %p allocating\n", result);
return result;
}
-
+
void
DiskdFile::operator delete (void *address)
{
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;
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++;
}
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++;
}
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++;
}
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;
}
DiskdFile::notifyClient()
{
if (!canNotifyClient()) {
- return;
+ return;
}
+
ioRequestor->ioCompletedNotification();
}
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();
}
* 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 */
{
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();
}
off_t shm_offset;
char *sbuf = (char *)IO->shm.get(&shm_offset);
xmemcpy(sbuf, buf, size);
+
if (free_func)
- free_func(const_cast<char *>(buf));
+ free_func(const_cast<char *>(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)
{
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++;
}
{
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;
}
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);
{
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);
}
}
{
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
{
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);
}
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);
}
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
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
* 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;
}
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
* 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;
}
/*
- * $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
#include "SwapDir.h"
#include "Store.h"
-class NullSwapDir : public SwapDir
+class NullSwapDir : public SwapDir
{
+
public:
virtual void init();
virtual int canStore(StoreEntry const &)const;
{
store_dirs_rebuilding++;
eventAdd("storeNullDirRebuildComplete", storeNullDirRebuildComplete,
- NULL, 0.0, 1);
+ NULL, 0.0, 1);
}
StoreIOState::Pointer
static void
storeNullDirRebuildComplete(void *unused)
{
+
struct _store_rebuild_data counts;
memset(&counts, '\0', sizeof(counts));
store_dirs_rebuilding--;
/*
- * $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
#if USE_UNLINKD
unlinkdUnlink(path);
#elif USE_TRUNCATE
+
truncate(path, 0);
#else
+
::unlink(path);
#endif
}
/* ========== 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
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;
}
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 */
{
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);
}
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;
}
{
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);
}
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;
}
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");
}
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);
}
/*
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
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
* 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
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 */
}
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;
}
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;
}
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);
+ }
}
}
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;
}
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);
}
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
* 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;
* 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);
}
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;
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 &);
*/
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);
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;
}
UFSCleanLog::nextEntry()
{
const StoreEntry *entry = NULL;
+
if (walker)
- entry = walker->Next(walker);
+ entry = walker->Next(walker);
+
return entry;
}
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;
}
}
{
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"
/* 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;
}
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;
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 */
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;
}
* 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<UFSSwapDir *>(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<UFSSwapDir *>(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
assert(F0 < Config.cacheSwap.n_configured);
assert (UFSSwapDir::IsUFSDir (INDEXSD(F0)));
UFSSwapDir *sd = dynamic_cast<UFSSwapDir *>(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;
}
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;
}
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);
}
UFSSwapDir::replacementRemove(StoreEntry * e)
{
SwapDir *SD;
+
if (e->swap_dirn < 0)
- return;
+ return;
+
SD = INDEXSD(e->swap_dirn);
+
assert (dynamic_cast<UFSSwapDir *>(SD) == this);
+
debug(47, 4) ("UFSSwapDir::replacementRemove: remove node %p from dir %d\n", e,
- index);
+ index);
+
repl->Remove(repl, e, &e->repl);
}
UFSSwapDir::dump(StoreEntry & entry) const
{
storeAppendPrintf(&entry, " %d %d %d",
- max_size >> 10,
- l1,
- l2);
+ max_size >> 10,
+ l1,
+ l2);
}
char *
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;
}
/*
- * $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
{
return false;
}
+
void
UfsIO::deleteSelf() const
{
return new ufsstate_t (SD, e, callback, callback_data);
}
-DiskFile::Pointer
+DiskFile::Pointer
UfsIO::newFile (char const *path)
{
return new UFSFile (path);
cbdataReference(result);
return result;
}
-
+
void
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;
cbdataReference(result);
return result;
}
-
+
void
UFSFile::operator delete (void *address)
{
/* 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();
}
void UFSFile::doClose()
{
if (fd > -1) {
- file_close(fd);
- store_open_disk_fd--;
- fd = -1;
+ file_close(fd);
+ store_open_disk_fd--;
+ fd = -1;
}
}
UFSFile::error() const
{
if (fd < 0)
- return true;
+ return true;
+
return false;
}
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);
}
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();
}
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;
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)
{
{
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);
}
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);
}
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
{
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);
}
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();
}
/* 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;
}
/* ============= 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<char *>(qw->buf));
- delete qw;
+ if (qw->free_func)
+ qw->free_func(const_cast<char *>(qw->buf));
+ delete qw;
}
}
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;
}
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);
}
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);
}
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<char *>(q->buf), q->size, q->offset, q->free_func);
delete q;
return true;
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;
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 <UFSStoreState *>(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 <UFSStoreState *>(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;
}
#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;
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);
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);
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);
};
* 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;
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
/*
- * $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
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];
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 *);
************************************************/
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)
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;
}
}
{
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);
}
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 */
}
char *title;
storeBuffer(e);
storeAppendPrintf(e, "<!-- HTML listing generated by Squid %s -->\n",
- version_string);
+ version_string);
storeAppendPrintf(e, "<!-- %s -->\n", mkrfc1123(squid_curtime));
storeAppendPrintf(e, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
storeAppendPrintf(e, "<HTML><HEAD><TITLE>\n");
storeAppendPrintf(e, "FTP Directory: %s\n",
- html_quote(ftpState->title_url.buf()));
+ html_quote(ftpState->title_url.buf()));
storeAppendPrintf(e, "</TITLE>\n");
storeAppendPrintf(e, "<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n");
+
if (ftpState->flags.need_base_href)
- storeAppendPrintf(e, "<BASE HREF=\"%s\">\n",
- html_quote(ftpState->base_href.buf()));
+ storeAppendPrintf(e, "<BASE HREF=\"%s\">\n",
+ html_quote(ftpState->base_href.buf()));
+
storeAppendPrintf(e, "</HEAD><BODY>\n");
+
if (ftpState->cwd_message) {
- storeAppendPrintf(e, "<PRE>\n");
- for (w = ftpState->cwd_message; w; w = w->next)
- storeAppendPrintf(e, "%s\n", html_quote(w->key));
- storeAppendPrintf(e, "</PRE>\n");
- storeAppendPrintf(e, "<HR noshade size=\"1px\">\n");
- wordlistDestroy(&ftpState->cwd_message);
+ storeAppendPrintf(e, "<PRE>\n");
+
+ for (w = ftpState->cwd_message; w; w = w->next)
+ storeAppendPrintf(e, "%s\n", html_quote(w->key));
+
+ storeAppendPrintf(e, "</PRE>\n");
+
+ storeAppendPrintf(e, "<HR noshade size=\"1px\">\n");
+
+ wordlistDestroy(&ftpState->cwd_message);
}
+
storeAppendPrintf(e, "<H2>\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, "<A HREF=\"");
- i += strcspn(&title[i], "/");
- if (title[i] == '/')
- i++;
- for (k = 0; k < i; k++)
- storeAppendPrintf(e, "%c", title[k]);
- 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, "</A>");
- 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, "<A HREF=\"");
+ i += strcspn(&title[i], "/");
+
+ if (title[i] == '/')
+ i++;
+
+ for (k = 0; k < i; k++)
+ storeAppendPrintf(e, "%c", title[k]);
+
+ 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, "</A>");
+
+ 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, "</H2>\n");
storeAppendPrintf(e, "<PRE>\n");
dirup = ftpHtmlifyListEntry("<internal-dirup>", ftpState);
StoreEntry *e = ftpState->entry;
storeBuffer(e);
storeAppendPrintf(e, "</PRE>\n");
+
if (ftpState->flags.listformat_unknown && !ftpState->flags.tried_nlst) {
- storeAppendPrintf(e, "<A HREF=\"./;type=d\">[As plain directory]</A>\n");
+ storeAppendPrintf(e, "<A HREF=\"./;type=d\">[As plain directory]</A>\n");
} else if (ftpState->typecode == 'D') {
- storeAppendPrintf(e, "<A HREF=\"./\">[As extended directory]</A>\n");
+ storeAppendPrintf(e, "<A HREF=\"./\">[As extended directory]</A>\n");
}
+
storeAppendPrintf(e, "<HR noshade size=\"1px\">\n");
storeAppendPrintf(e, "<ADDRESS>\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, "</ADDRESS></BODY></HTML>\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;
}
#define MAX_TOKENS 64
static ftpListParts *
+
ftpListParseParts(const char *buf, struct _ftp_flags flags)
{
ftpListParts *p = NULL;
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 <mike@starbug.bofh.asn.au> */
- 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 <mike@starbug.bofh.asn.au> */
+ 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], "<dir>")) {
- 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 <dir> */
- 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], "<dir>")) {
+ 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 <dir> */
+ 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;
}
{
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;
}
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 <dirup> */
if (strcmp(line, "<internal-dirup>") == 0) {
- /* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> {link} */
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-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, "(<A HREF=\"%s\">%s</A>)",
- "%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, "(<A HREF=\"%s\">%s</A>)",
- "../",
- "Back");
- } else { /* NO_DOTDOT && ROOT_DIR */
- /* "UNIX Root" directory */
- strcpy(href, "../");
- strcpy(text, "Home Directory");
- }
- snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A> %s\n",
- href, icon, href, text, link);
- return html;
+ /* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> {link} */
+ snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-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, "(<A HREF=\"%s\">%s</A>)",
+ "%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, "(<A HREF=\"%s\">%s</A>)",
+ "../",
+ "Back");
+ } else { /* NO_DOTDOT && ROOT_DIR */
+ /* "UNIX Root" directory */
+ strcpy(href, "../");
+ strcpy(text, "Home Directory");
+ }
+
+ snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A> %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, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
- mimeGetIconURL("internal-dir"),
- "[DIR]");
- strcat(href, "/"); /* margin is allocated above */
- break;
+ snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
+ mimeGetIconURL("internal-dir"),
+ "[DIR]");
+ strcat(href, "/"); /* margin is allocated above */
+ break;
+
case 'l':
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-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, " -> <A HREF=\"%s\">%s</A>",
- link2,
- html_quote(parts->link));
- safe_free(link2);
- }
- break;
+ snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-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, " -> <A HREF=\"%s\">%s</A>",
+ link2,
+ html_quote(parts->link));
+ safe_free(link2);
+ }
+
+ break;
+
case '\0':
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
- mimeGetIconURL(parts->name),
- "[UNKNOWN]");
- snprintf(chdir, 2048, " <A HREF=\"%s/;type=d\"><IMG border=\"0\" SRC=\"%s\" "
- "ALT=\"[DIR]\"></A>",
- rfc1738_escape_part(parts->name),
- mimeGetIconURL("internal-dir"));
- break;
+ snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
+ mimeGetIconURL(parts->name),
+ "[UNKNOWN]");
+ snprintf(chdir, 2048, " <A HREF=\"%s/;type=d\"><IMG border=\"0\" SRC=\"%s\" "
+ "ALT=\"[DIR]\"></A>",
+ rfc1738_escape_part(parts->name),
+ mimeGetIconURL("internal-dir"));
+ break;
+
case '-':
+
default:
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
- mimeGetIconURL(parts->name),
- "[FILE]");
- snprintf(size, 2048, " %6dk", parts->size);
- break;
+ snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
+ mimeGetIconURL(parts->name),
+ "[FILE]");
+ snprintf(size, 2048, " %6dk", parts->size);
+ break;
}
+
if (parts->type != 'd') {
- if (mimeGetViewOption(parts->name)) {
- snprintf(view, 2048, " <A HREF=\"%s;type=a\"><IMG border=\"0\" SRC=\"%s\" "
- "ALT=\"[VIEW]\"></A>",
- href, mimeGetIconURL("internal-view"));
- }
- if (mimeGetDownloadOption(parts->name)) {
- snprintf(download, 2048, " <A HREF=\"%s;type=i\"><IMG border=\"0\" SRC=\"%s\" "
- "ALT=\"[DOWNLOAD]\"></A>",
- href, mimeGetIconURL("internal-download"));
- }
+ if (mimeGetViewOption(parts->name)) {
+ snprintf(view, 2048, " <A HREF=\"%s;type=a\"><IMG border=\"0\" SRC=\"%s\" "
+ "ALT=\"[VIEW]\"></A>",
+ href, mimeGetIconURL("internal-view"));
+ }
+
+ if (mimeGetDownloadOption(parts->name)) {
+ snprintf(download, 2048, " <A HREF=\"%s;type=i\"><IMG border=\"0\" SRC=\"%s\" "
+ "ALT=\"[DOWNLOAD]\"></A>",
+ href, mimeGetIconURL("internal-download"));
+ }
}
+
/* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> . . . {date}{size}{chdir}{view}{download}{link}\n */
if (parts->type != '\0') {
- snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%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, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%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, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%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, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%s "
+ "%s%s%s%s\n",
+ href, icon, href, html_quote(text), dots_fill(strlen(text)),
+ chdir, view, download, link);
}
+
ftpListPartsFree(&parts);
return html;
}
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);
}
{
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);
}
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);
+ }
}
/*
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 */
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;
}
}
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("/");
}
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);
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);
}
{
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;
}
}
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;
}
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);
}
}
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);
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);
}
{
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);
}
}
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;
}
{
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);
}
}
{
int code = ftpState->ctrl.replycode;
debug(9, 3) ("ftpReadPass\n");
+
if (code == 230) {
- ftpSendType(ftpState);
+ ftpSendType(ftpState);
} else {
- ftpFail(ftpState);
+ ftpFail(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;
}
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);
}
}
{
wordlist *w;
debug(9, 4) ("ftpTraverseDirectory %s\n",
- ftpState->filepath ? ftpState->filepath : "<NULL>");
+ ftpState->filepath ? ftpState->filepath : "<NULL>");
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;
}
}
{
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;
}
{
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);
}
}
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
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);
}
{
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);
}
{
/* 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
{
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);
}
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
* 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.
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);
{
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);
}
ftpOpenListenSocket(FtpStateData * ftpState, int fallback)
{
int fd;
+
struct sockaddr_in addr;
socklen_t addr_len;
int on = 1;
* 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;
ftpSendPort(FtpStateData * ftpState)
{
int fd;
+
struct sockaddr_in addr;
socklen_t addr_len;
unsigned char *addrptr;
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;
}
{
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");
}
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
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);
}
}
{
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);
}
}
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;
}
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);
}
}
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;
}
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;
}
{
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;
}
}
{
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);
}
}
{
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;
}
}
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);
}
}
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);
}
}
{
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);
}
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);
}
{
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;
}
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);
}
}
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);
}
{
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 */
}
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);
}
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 <yourpassword>";
+ command = "PASS <yourpassword>";
+
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);
}
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);
}
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);
}
}
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;
}
/*
- * $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/
#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 */
/*
- * $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
#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;
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;
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);
{
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);
}
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);
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);
}
}
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;
}
storeAppendPrintf(e, "<HR noshade size=\"1px\">\n");
storeAppendPrintf(e, "<ADDRESS>\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, "</ADDRESS></BODY></HTML>\n");
}
gopherEndHTML(GopherStateData * gopherState)
{
StoreEntry *e = gopherState->entry;
+
if (!gopherState->data_in) {
- gopherHTMLHeader(e, "Server Return Nothing", NULL);
- storeAppendPrintf(e, "<P>The Gopher query resulted in a blank response</P>");
+ gopherHTMLHeader(e, "Server Return Nothing", NULL);
+ storeAppendPrintf(e, "<P>The Gopher query resulted in a blank response</P>");
} else {
- storeAppendPrintf(e, "</PRE>\n");
+ storeAppendPrintf(e, "</PRE>\n");
}
+
gopherHTMLFooter(e);
}
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,
- "<p>This is a searchable Gopher index. Use the search\n"
- "function of your browser to enter search terms.\n"
- "<ISINDEX>\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,
+ "<p>This is a searchable Gopher index. Use the search\n"
+ "function of your browser to enter search terms.\n"
+ "<ISINDEX>\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,
- "<P>A CSO database usually contains a phonebook or\n"
- "directory. Use the search function of your browser to enter\n"
- "search terms.</P><ISINDEX>\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,
+ "<P>A CSO database usually contains a phonebook or\n"
+ "directory. Use the search function of your browser to enter\n"
+ "search terms.</P><ISINDEX>\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 ("<PRE>");
- 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 ("<PRE>");
+
+ 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, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s@%s%s%s/\">%s</A>\n",
- icon_url, escaped_selector, rfc1738_escape_part(host),
- *port ? ":" : "", port, html_quote(name));
- else
- snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s%s%s/\">%s</A>\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, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"http://%s/%s\">%s</A>\n",
- icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name));
- } else {
- /* Standard link */
- snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"gopher://%s/%c%s\">%s</A>\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, "</PRE><HR noshade size=\"1px\"><H2>Record# %d<br><i>%s</i></H2>\n<PRE>", 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, "</PRE><HR noshade size=\"1px\"><H2>%s</H2>\n<PRE>", 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, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s@%s%s%s/\">%s</A>\n",
+ icon_url, escaped_selector, rfc1738_escape_part(host),
+ *port ? ":" : "", port, html_quote(name));
+ else
+ snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s%s%s/\">%s</A>\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, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"http://%s/%s\">%s</A>\n",
+ icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name));
+ } else {
+ /* Standard link */
+ snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"gopher://%s/%c%s\">%s</A>\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, "</PRE><HR noshade size=\"1px\"><H2>Record# %d<br><i>%s</i></H2>\n<PRE>", 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, "</PRE><HR noshade size=\"1px\"><H2>%s</H2>\n<PRE>", 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;
}
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);
}
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;
}
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. */
{
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);
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);
/*
- * $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?
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);
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);
{
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);
}
{
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);
}
{
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
* 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);
}
}
/*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);
}
}
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");
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");
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);
}
}
{
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);
}
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
}
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);
}
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);
}
{
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); */
}
{
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;
}
{
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;
}
{
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;
}
{
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;
}
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;
}
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! */
}
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++;
}
{
helper_request *r;
helper_server *srv;
+
while ((srv = GetFirstAvailable(hlp)) && (r = Dequeue(hlp)))
- helperDispatch(srv, r);
+ helperDispatch(srv, r);
}
static void
{
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
/*
- * $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
#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;
Countstr signature;
};
-class htcpSpecifier : public StoreClient {
+class htcpSpecifier : public StoreClient
+{
+
public:
void *operator new (unsigned int byteCount);
void operator delete (void *address);
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;
};
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
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
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
}
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 : "<NULL>");
+
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;
}
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;
}
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;
}
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;
}
{
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;
}
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;
}
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;
}
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());
}
/*
{
/* 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<htcpSpecifier *> (memPoolAlloc(pool));
}
-void
+void
htcpSpecifier::operator delete (void *address)
{
memPoolFree(pool, address);
}
void
+
htcpSpecifier::setFrom (struct sockaddr_in *aSocket)
{
from = aSocket;
{
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;
}
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);
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);
}
static void
+
htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from)
{
htcpStuff stuff;
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");
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);
}
{
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();
}
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);
{
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);
}
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));
}
}
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);
xfree(pkt);
}
-/*
+/*
* htcpSocketShutdown only closes the 'in' socket if it is
* different than the 'out' socket.
*/
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
* I think there should be a separate hander for reading replies..
*/
assert(htcpOutSocket > -1);
+
commSetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0);
}
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;
}
}
/*
- * $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
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);
{
HttpStateData *httpState = static_cast<HttpStateData *>(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;
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;
}
HttpStateData *httpState = static_cast<HttpStateData *>(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);
}
httpMakePublic(StoreEntry * entry)
{
if (EBIT_TEST(entry->flags, ENTRY_CACHABLE))
- storeSetPublicKey(entry);
+ storeSetPublicKey(entry);
}
/* This object should never be cached at all */
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;
}
}
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;
}
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 */
}
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();
}
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);
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);
}
}
{
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?
*/
*/
if (!reply->keep_alive)
return COMPLETE_NONPERSISTENT_MSG;
+
return COMPLETE_PERSISTENT_MSG;
}
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;
}
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);
}
}
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();
}
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;
}
HttpStateData::maybeReadData()
{
if (do_next_read) {
- do_next_read = 0;
+ do_next_read = 0;
comm_read(fd, buf, amountToRead(), httpReadReply, this);
}
}
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);
}
}
*/
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)
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();
}
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)
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);
}
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,
HttpStateData *httpState = static_cast<HttpStateData *>(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);
}
}
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);
}
}
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);
}
/*
- * $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/
#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;
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;
/*
- * $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
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);
}
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;
}
}
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;
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);
}
#if ALLOW_SOURCE_PING
void
+
icmpSourcePing(struct in_addr to, const icp_common_t * header, const char *url)
{
#if USE_ICMP
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
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
}
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
}
/*
- * $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
#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);
/* 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
_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;
};
ICP2State::~ICP2State ()
-{
-}
+{}
void
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;
}
/* 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);
}
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;
}
}
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;
}
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;
}
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;
}
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);
}
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;
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;
/* 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;
}
}
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));
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);
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));
}
}
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;
}
/*
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
* 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
* disable reading on the outgoing socket.
*/
assert(theOutIcpConnection > -1);
+
commSetSelect(theOutIcpConnection, COMM_SELECT_READ, NULL, NULL, 0);
}
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;
}
}
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++;
}
}
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;
}
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);
}
/*
- * $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
#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;
}
}
/*
- * $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
#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;
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);
}
}
{
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);
}
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);
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);
}
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;
}
* 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;
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);
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);
}
/*
- * $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
isPowTen(int count)
{
double x = log(count) / log(10.0);
+
if (0.0 != x - (double) (int) x)
- return 0;
+ return 0;
+
return 1;
}
/*
- * $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
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);
}
}
* 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;
}
internalLocalUri(const char *dir, const char *name)
{
return internalRemoteUri(getMyHostname(),
- getMyPort(), dir, name);
+ getMyPort(), dir, name);
}
const char *
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;
}
/*
- * $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
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);
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;
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;
}
/*
- * $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
typedef struct _ipcache_entry ipcache_entry;
-struct _ipcache_entry {
+struct _ipcache_entry
+{
hash_link hash; /* must be first */
time_t lastref;
time_t expires;
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;
{
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;
}
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;
}
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);
}
{
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 */
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;
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);
}
memset(&i, '\0', sizeof(i));
i.expires = squid_curtime;
i.flags.negcached = 1;
+
if (inbuf == NULL) {
- debug(14, 1) ("ipcacheParse: Got <NULL> reply\n");
- i.error_message = xstrdup("Internal Squid Error");
- return &i;
+ debug(14, 1) ("ipcacheParse: Got <NULL> 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 <NULL>, expecting '$addr'\n");
- return &i;
+ debug(14, 1) ("ipcacheParse: Got <NULL>, 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 <NULL>, expecting TTL\n");
- return &i;
+ debug(14, 1) ("ipcacheParse: Got <NULL>, 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)
{
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
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;
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);
c = cbdataAlloc(generic_cbdata);
c->data = i;
#if USE_DNSSERVERS
+
dnsSubmit(hashKeyStr(&i->hash), ipcacheHandleReply, c);
#else
+
idnsALookup(hashKeyStr(&i->hash), ipcacheHandleReply, c);
#endif
}
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);
}
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;
}
{
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");
}
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
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.
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;
}
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);
}
}
{
assert(i->locks > 0);
i->locks--;
+
if (ipcacheExpiredEntry(i))
- ipcacheRelease(i);
+ ipcacheRelease(i);
}
void
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]));
}
/*
* 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));
}
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();
}
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;
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;
}
/*
- * $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
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;
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 *
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);
}
}
/*
- * $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
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<Logfile *>(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;
}
{
logfileFlush(lf);
file_close(lf->fd);
+
if (lf->buf)
- xfree(lf->buf);
+ xfree(lf->buf);
+
xfree(lf);
}
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());
}
}
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);
}
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);
}
logfileFlush(Logfile * lf)
{
if (0 == lf->offset)
- return;
+ return;
+
logfileWriteWrapper(lf, lf->buf, (size_t) lf->offset);
+
lf->offset = 0;
}
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());
}
/*
- * $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
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);
}
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;
+ }
}
}
{
do_rotate = 1;
#if !HAVE_SIGACTION
+
signal(sig, rotate_logs);
#endif
}
{
do_reconfigure = 1;
#if !HAVE_SIGACTION
+
signal(sig, reconfigure);
#endif
}
{
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
}
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
}
clientHttpConnectionsClose();
icpConnectionShutdown();
#if USE_HTCP
+
htcpSocketShutdown();
#endif
+
icmpClose();
#ifdef SQUID_SNMP
+
snmpConnectionShutdown();
#endif
#if USE_WCCP
+
wccpConnectionShutdown();
#endif
+
asnFreeMemory();
}
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();
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();
{
icmpClose();
#if USE_DNSSERVERS
+
dnsShutdown();
#endif
+
redirectShutdown();
authenticateShutdown();
externalAclShutdown();
useragentRotateLog(); /* useragent.log */
refererRotateLog(); /* referer.log */
#if WIP_FWD_LOG
+
fwdLogRotate();
#endif
+
icmpOpen();
#if USE_DNSSERVERS
+
dnsInit();
#endif
+
redirectInit();
authenticateInit(&Config.authConfiguration);
externalAclInit();
{
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'!");
}
}
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());
}
}
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;
}
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 */
#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 */
* 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);
/* 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;
}
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);
}
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);
}
}
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;
}
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
*/
/* 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 */
}
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();
useragentLogClose();
refererCloseLog();
#if WIP_FWD_LOG
+
fwdUninit();
#endif
+
storeDirSync(); /* Flush log close */
#if PURIFY || XMALLOC_TRACE
+
storeFsDone();
configFreeMemory();
storeFreeMemory();
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);
}
/*
- * $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
/* 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;
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");
}
memBufStats(StoreEntry * sentry)
{
storeAppendPrintf(sentry, "Large buffers: %d (%d KB)\n",
- HugeBufCountMeter.level,
- HugeBufVolumeMeter.level / 1024);
+ HugeBufCountMeter.level,
+ HugeBufVolumeMeter.level / 1024);
}
void
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);
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);
{
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;
}
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);
}
}
/* 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;
}
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);
}
}
{
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;
}
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));
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);
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)
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]);
}
}
{
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
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
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;
}
}
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;
}
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;
/* 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;
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 */
/*
- * $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
{
/* 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);
}
}
mem_node::mem_node(off_t offset):nodeBuffer(0,offset,data), next (NULL)
-{
-}
+{}
mem_node::~mem_node()
{
mem_node::InUseCount()
{
if (!pool)
- return 0;
+ return 0;
+
MemPoolStats stats;
+
memPoolGetStats (&stats, pool);
+
return stats.items_inuse;
}
mem_node::contains (size_t const &location) const
{
if (start() <= location && end() > location)
- return true;
+ return true;
+
return false;
}
mem_node::canAccept (size_t const &location) const
{
if (location == end() && space() > 0)
- return true;
+ return true;
+
return false;
}
/*
- * $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/
#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 */
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;
mem_node *next;
/* Private */
char data[SM_PAGE_SIZE];
+
private:
static MemPool *pool;
};
/*
- * $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
#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;
};
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;
}
{
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;
}
{
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);
}
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)
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();
}
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);
}
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;
}
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;
}
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");
}
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;
}
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);
}
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);
}
/*
- * $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
{
#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;
}
{
#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
}
/*
- * $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
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;
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;
}
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
* 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);
}
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;
}
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;
}
{
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;
}
{
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;
}
{
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;
}
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;
}
{
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);
}
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;
}
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;
}
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;
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?
* 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;
}
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;
}
{
peer *best_p = NULL;
#if USE_CACHE_DIGESTS
+
const cache_key *key;
int best_rtt = 0;
int choice_count = 0;
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;
}
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 : "<none>", lookup_t_str[lookup]);
+ p ? p->host : "<none>", lookup_t_str[lookup]);
+
#endif
}
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;
}
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
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
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;
}
* 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;
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);
}
}
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;
}
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;
}
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;
}
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
}
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);
}
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;
}
}
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;
}
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);
}
{
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;
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;
}
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);
}
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);
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);
}
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");
}
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);
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
/*
- * $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
STATE_BODY
} netdb_conn_state_t;
-typedef struct {
+typedef struct
+{
peer *p;
StoreEntry *e;
store_client *sc;
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);
static wordlist *peer_names = NULL;
static void
+
netdbHashInsert(netdbEntry * n, struct in_addr addr)
{
xstrncpy(n->network, inet_ntoa(networkFromInaddr(addr)), 16);
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);
}
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);
{
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);
}
}
{
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);
}
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;
}
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;
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;
}
{
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 *
{
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;
}
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++;
{
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
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));
*/
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);
}
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));
/*
* 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);
}
netdbExchangeState *ex = (netdbExchangeState *)data;
int rec_sz = 0;
off_t o;
+
struct in_addr addr;
double rtt;
double hops;
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 */
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++;
}
/*
* much data over
*/
memmove(ex->buf, ex->buf + (ex->buf_ofs - size), size);
+
ex->buf_ofs = size;
/*
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);
}
}
{
#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
}
#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
}
}
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;
}
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
}
{
#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;
}
{
#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;
}
{
#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
}
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
}
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);
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();
}
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);
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
}
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;
}
/*
- * $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
#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 */
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;
}
static struct _pconn *
-pconnNew(const char *key)
+ pconnNew(const char *key)
{
pconn *p;
CBDATA_INIT_TYPE(pconn);
}
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);
}
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));
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);
}
{
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]);
}
}
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);
int
pconnPop(const char *host, u_short port)
{
+
struct _pconn *p;
hash_link *hptr;
int fd = -1;
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;
}
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);
}
/*
- * $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
peerDigestClean(PeerDigest * pd)
{
assert(pd);
+
if (pd->cd)
- cacheDigestDestroy(pd->cd);
+ cacheDigestDestroy(pd->cd);
+
pd->host.clean();
}
assert(pd);
/* inform peer (if any) that we are gone */
+
if (cbdataReferenceValidDone(pd->peer, (void **) &p))
- peerNoteDigestGone(p);
+ peerNoteDigestGone(p);
peerDigestClean(pd);
+
cbdataFree(pd);
}
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] */
{
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;
}
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);
}
/*
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);
}
}
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);
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);
}
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) */
/* 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);
/* 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);
}
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,
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");
}
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");
}
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");
}
* 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;
}
{
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);
}
{
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);
}
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);
}
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);
}
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));
}
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;
{
/* 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;
}
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
/*
- * $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
#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);
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);
}
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);
}
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);
}
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;
}
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);
}
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;
}
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);
}
}
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
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);
}
}
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);
}
}
{
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);
{
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;
}
}
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);
}
{
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);
}
{
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
{
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;
}
/*
- * $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
#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);
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");
}
}
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;
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;
/*
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);
}
{
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);
}
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;
}
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;
}
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;
}
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);
}
}
#if GETTIMEOFDAY_NO_TZP
gettimeofday(¤t_time);
#else
+
gettimeofday(¤t_time, NULL);
#endif
+
return squid_curtime = current_time.tv_sec;
}
{
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 */
}
fprintf(stderr, "%s: ICMP support not compiled in.\n", argv[0]);
return 1;
}
+
#endif /* USE_ICMP */
/*
- * $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/
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 *);
/* 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);
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 */
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 *);
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);
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);
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);
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);
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
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 *);
#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 *);
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);
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);
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);
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);
/* 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
* store_rebuild.c
*/
SQUIDCEXTERN void storeRebuildStart(void);
+
SQUIDCEXTERN void storeRebuildComplete(struct _store_rebuild_data *);
SQUIDCEXTERN void storeRebuildProgress(int sd_index, int total, int sofar);
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);
* 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);
*/
#ifdef _SQUID_SOLARIS_
+
SQUIDCEXTERN int getrusage(int, struct rusage *);
SQUIDCEXTERN int getpagesize(void);
SQUIDCEXTERN int gethostname(char *, int);
/*
- * $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
*
*/
-/*
+/*
* usage: recv-announce logfile
*/
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;
}
/*
- * $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
#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);
char *t;
void *cbdata;
debug(61, 5) ("redirectHandleRead: {%s}\n", reply ? reply : "<NULL>");
+
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);
}
{
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 ****/
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);
}
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);
}
}
redirectShutdown(void)
{
if (!redirectors)
- return;
+ return;
+
helperShutdown(redirectors);
+
if (!shutting_down)
- return;
+ return;
+
helperFree(redirectors);
+
redirectors = NULL;
}
/*
- * $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 <ramey@csc.ti.com> (useragent)
{
#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
}
refererRotateLog(void)
{
#if USE_REFERER_LOG
+
if (NULL == refererlog)
- return;
+ return;
+
logfileRotate(refererlog);
+
#endif
}
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
}
refererCloseLog(void)
{
#if USE_REFERER_LOG
+
if (NULL == refererlog)
- return;
+ return;
+
logfileClose(refererlog);
+
refererlog = NULL;
+
#endif
}
/*
- * $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
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
STALE_DEFAULT = 299
};
-static struct RefreshCounts {
+static struct RefreshCounts
+{
const char *proto;
int total;
int status[STALE_DEFAULT + 1];
-} refreshCounts[rcCount];
+}
+
+refreshCounts[rcCount];
/*
* Defaults:
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;
}
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;
}
/*
* 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<time_t>((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<time_t>((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);
}
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 : "<none>");
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;
}
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;
}
refreshCounts[rcHTCP].status[reason]++;
return (reason < 200) ? 0 : 1;
}
+
#endif
#if USE_CACHE_DIGESTS
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
{
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;
}
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
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
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 = "<none>";
DefaultRefresh.min = REFRESH_DEFAULT_MIN;
/*
- * $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
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;
}
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.
{
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;
}
/*
- * $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
static int nr_heap_policies = 0;
-struct HeapPolicyData {
+struct HeapPolicyData
+{
void setPolicyNode (StoreEntry *, void *) const;
RemovalPolicy *policy;
heap *theHeap;
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;
};
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;
}
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;
}
}
{
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;
};
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;
}
/** RemovalPurgeWalker **/
typedef struct _HeapPurgeData HeapPurgeData;
-struct _HeapPurgeData {
+
+struct _HeapPurgeData
+{
link_list *locked_entries;
heap_key min_age;
};
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;
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);
}
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;
}
/*
- * $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
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;
};
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;
}
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 *.
*/
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
{
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;
};
{
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;
}
/** RemovalPurgeWalker **/
typedef struct _LruPurgeData LruPurgeData;
-struct _LruPurgeData {
+
+struct _LruPurgeData
+{
LruNode *current;
LruNode *start;
};
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);
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));
}
}
/* 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;
}
/*
- * $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
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);
}
{
LOCAL_ARRAY(char, tbuf, 256);
LOCAL_ARRAY(char, sndbuf, BUFSIZ);
+
struct sockaddr_in S;
char *host = Config.Announce.host;
char *file = NULL;
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());
}
/*
- * $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
#include "mem_node.h"
/************************************************************************
-
+
SQUID MIB Implementation
-
+
************************************************************************/
variable_list *
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;
}
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;
}
snmp_meshPtblFn(variable_list * Var, snint * ErrP)
{
variable_list *Answer = NULL;
+
struct in_addr *laddr;
char *cp = NULL;
peer *p = NULL;
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;
}
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;
}
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;
}
/*
- * $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
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;
};
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);
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");
}
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;
}
}
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
* on the outgoing socket.
*/
assert(theOutSnmpConnection > -1);
+
commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
}
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);
}
}
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;
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());
}
}
static void
snmpDecodePacket(snmp_request_t * rq)
{
+
struct snmp_pdu *PDU;
+
struct snmp_session Session;
u_char *Community;
u_char *buf = rq->buf;
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);
}
/*
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);
}
}
* 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;
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);
}
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);
}
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 *
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);
}
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);
}
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);
}
{
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);
}
* Tree utility functions.
*/
-/*
+/*
* Returns a the sibling object in the tree
*/
static mib_tree_entry *
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 *
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);
}
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
mib_tree_entry *entry = NULL;
va_start(args, children);
#else
+
va_list args;
oid *name = NULL;
int len = 0, children = 0, loop;
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 *
snmpCreateOid(int length,...)
#else
snmpCreateOid(va_alist)
- va_dcl
+va_dcl
#endif
{
#if STDC_HEADERS
int loop;
va_start(args, length);
#else
+
va_list args;
int length = 0, loop;
oid *new_oid;
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);
}
xmemcpy(Ans, A, (sizeof(oid) * ALen));
return Ans;
}
+
#endif
/*
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);
}
void
+
addr2oid(struct in_addr addr, oid * Dest)
{
u_char *cp;
}
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];
/*
- * $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
*
* 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;
#ifdef USE_GNUREGEX
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
#include "GNUregex.h"
#ifdef __cplusplus
}
+
#endif
#elif HAVE_REGEX_H
#include <regex.h>
#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
/*
- * $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
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;
}
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)
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;
}
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;
}
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);
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;
}
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;
}
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;
}
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);
}
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;
}
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);
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);
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 *
/*
- * $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
#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 *);
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);
}
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));
}
}
{
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;
}
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;
}
{
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;
}
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");
}
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);
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;
}
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");
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));
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
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);
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));
}
}
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
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
}
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;
}
{
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 */
* 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
ConnStateData *conn;
StoreEntry *e;
int fd;
+
for (i = ClientActiveRequests.head; i; i = i->next) {
- http = static_cast<clientHttpRequest *>(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<clientHttpRequest *>(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");
}
}
/*
- * $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
mem_hdr::lowestOffset () const
{
if (head)
- return head->nodeBuffer.offset;
+ return head->nodeBuffer.offset;
+
return 0;
}
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;
}
mem_hdr::freeContent()
{
while (head)
- unlinkHead();
+ unlinkHead();
+
head = tail = NULL;
+
inmem_hi = 0;
}
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);
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);
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;
}
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;
+ }
}
}
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());
}
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;
}
}
{
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..
mem_hdr::getBlockContainingLocation (size_t location) const
{
mem_node *result = getHighestBlockBeforeLocation(location);
+
if (!result || !result->contains(location))
- return NULL;
+ return NULL;
+
return result;
}
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
{
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;
}
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;
}
{
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;
}
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;
}
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);
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;
/*
- * $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/
#define SQUID_STMEM_H
class mem_node;
+
class StoreIOBuffer;
-class mem_hdr {
+
+class mem_hdr
+{
+
public:
void freeContent();
int lowestOffset () const;
void internalAppend(const char *data, int len);
mem_node *head;
mem_node *tail;
+
private:
void unlinkHead();
void makeAppendSpace();
/*
- * $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
#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;
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);
}
StoreEntry::inUseCount()
{
if (!pool)
- return 0;
+ return 0;
+
MemPoolStats stats;
+
memPoolGetStats (&stats, pool);
+
return stats.items_inuse;
}
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;
}
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
* 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.
{
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;
}
StoreEntry *e = static_cast<StoreEntry *>(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;
}
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);
}
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);
}
}
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);
}
}
{
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);
}
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);
}
{
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;
}
{
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
{
assert (aClient);
StoreEntry *result = storeGetPublicByRequest (request);
+
if (!result)
- result = NullStoreEntry::getInstance();
+ result = NullStoreEntry::getInstance();
+
aClient->created (result);
}
{
assert (aClient);
StoreEntry *result = storeGetPublic (uri, method);
+
if (!result)
- result = NullStoreEntry::getInstance();
+ result = NullStoreEntry::getInstance();
+
aClient->created (result);
}
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;
}
getKeyCounter(void)
{
static int key_counter = 0;
+
if (++key_counter < 0)
- key_counter = 1;
+ key_counter = 1;
+
return key_counter;
}
{
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);
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
* 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 *
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;
storeWriteComplete (void *data, StoreIOBuffer wroteBuffer)
{
StoreEntry *e = (StoreEntry *)data;
+
if (EBIT_TEST(e->flags, DELAY_SENDING))
- return;
+ return;
+
InvokeHandlers(e);
}
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);
}
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;
e = va_arg(args, StoreEntry *);
fmt = va_arg(args, char *);
#endif
+
storeAppendVPrintf(e, fmt, args);
va_end(args);
}
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;
}
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<size_t>(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<size_t>(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;
}
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<size_t>(e->getReply()->content_length) > Config.Store.maxObjectSize) ||
- static_cast<size_t>(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<size_t>(e->getReply()->content_length)
+ > Config.Store.maxObjectSize) ||
+ static_cast<size_t>(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;
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,
*/
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 */
}
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);
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);
}
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);
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<StoreEntry*>(stackPop(&LateReleaseStack));
- if (e == NULL) {
- /* done! */
- debug(20, 1) ("storeLateRelease: released %d objects\n", n);
- return;
- }
- storeUnlockObject(e);
- n++;
+ e = static_cast<StoreEntry*>(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);
}
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;
}
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;
}
/* 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
storeKeyInit();
storeInitHashValues();
store_table = hash_create(storeKeyHashCmp,
- store_hash_buckets, storeKeyHashHash);
+ store_hash_buckets, storeKeyHashHash);
mem_policy = createRemovalPolicy(Config.memPolicy);
storeDigestInit();
storeLogOpen();
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;
}
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;
}
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;
}
hashFreeMemory(store_table);
store_table = NULL;
#if USE_CACHE_DIGESTS
+
if (store_digest)
- cacheDigestDestroy(store_digest);
+ cacheDigestDestroy(store_digest);
+
#endif
+
store_digest = NULL;
}
expiresMoreThan(time_t expires, time_t when)
{
if (expires < 0) /* No Expires given */
- return 1;
+ return 1;
+
return (expires > (squid_curtime + when));
}
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;
}
* 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
* 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;
}
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;
}
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);
}
StoreEntry::getReply () const
{
if (NULL == mem_obj)
- return NULL;
+ return NULL;
+
return mem_obj->getReply();
}
int i = 0;
while (storefs_list[i].typestr != NULL) {
- storefs_list[i].donefunc();
- i++;
+ storefs_list[i].donefunc();
+ i++;
}
}
{
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<storefs_entry_t *>(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]);
}
{
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<storerepl_entry_t *>(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;
}
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");
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
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);
/* 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()
/* 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;
}
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;
/*
- * $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
{
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;
}
{
return sc->owner == someClient;
}
+
#endif
/* add client with fd to client list */
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;
}
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;
void *cbdata = _callback.callback_data;
_callback = Callback(NULL, NULL);
copyInto.data = NULL;
+
if (cbdataReferenceValid(cbdata))
- temphandler(cbdata, result);
+ temphandler(cbdata, result);
+
cbdataReferenceDone(cbdata);
}
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);
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 */
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;
}
/* 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());
/*
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
*/
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;
}
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
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);
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;
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<size_t>(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.
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;
}
{
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;
}
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);
}
}
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;
}
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);
}
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");
}
{
delayId = delay_id;
}
+
#endif
/*
- * $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
* local types
*/
-typedef struct {
+typedef struct
+{
StoreDigestCBlock cblock;
int rebuild_lock; /* bucket number */
generic_cbdata *rewrite_lock; /* points to store entry with the digest */
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;
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
storeDigestNoteStoreReady(void)
{
#if USE_CACHE_DIGESTS
+
if (Config.onoff.digest_generation) {
- storeDigestRebuildStart(NULL);
- storeDigestRewriteStart(NULL);
+ storeDigestRebuildStart(NULL);
+ storeDigestRewriteStart(NULL);
}
+
#endif
}
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
}
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
}
/* 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
*/
#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;
}
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++;
}
}
{
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();
}
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);
}
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 */
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);
}
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);
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();
}
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);
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);
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 */
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
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));
}
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;
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;
}
}
/*
- * $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
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
}
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
}
/*
* 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;
}
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;
}
/* 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;
}
/*
* 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);
}
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
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);
+ }
}
}
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);
}
}
{
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();
}
/*
{
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;
}
storeDirSync(void)
{
for (int i = 0; i < Config.cacheSwap.n_configured; ++i)
- INDEXSD(i)->sync();
+ INDEXSD(i)->sync();
}
/*
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++;
}
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;
}
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;
}
#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;
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;
}
*/
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);
}
storeClose(StoreIOState::Pointer sio)
{
if (sio->flags.closing)
- return;
+ return;
+
sio->flags.closing = 1;
+
sio->close();
}
/*
- * $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
{
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;
}
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;
}
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;
}
/* 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));
}
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));
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;
}
storeKeyHashBuckets(int nbuckets)
{
int n = 0x2000;
+
while (n < nbuckets)
- n <<= 1;
+ n <<= 1;
+
return n;
}
storeKeyNull(const cache_key * key)
{
if (memcmp(key, null_key, MD5_DIGEST_CHARS) == 0)
- return 1;
+ return 1;
else
- return 0;
+ return 0;
}
void
/*
- * $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
#include "MemObject.h"
static const char *storeLogTags[] =
-{
- "CREATE",
- "SWAPIN",
- "SWAPOUT",
- "RELEASE",
- "SO_FAIL",
-};
+ {
+ "CREATE",
+ "SWAPIN",
+ "SWAPOUT",
+ "RELEASE",
+ "SO_FAIL",
+ };
static Logfile *storelog = NULL;
{
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());
}
}
storeLogRotate(void)
{
if (NULL == storelog)
- return;
+ return;
+
logfileRotate(storelog);
}
storeLogClose(void)
{
if (NULL == storelog)
- return;
+ return;
+
logfileClose(storelog);
+
storelog = NULL;
}
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);
}
/*
- * $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
#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;
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;
* 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;
}
* occurs in storeCleanup(), when it is finished.
*/
RebuildProgress = (store_rebuild_progress *)xcalloc(Config.cacheSwap.n_configured,
- sizeof(store_rebuild_progress));
+ sizeof(store_rebuild_progress));
}
/*
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;
}
/*
- * $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
{
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);
}
{
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++;
}
/*
- * $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
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();
}
}
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;
}
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;
/*
- * $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
* 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
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 */
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);
}
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);
}
}
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);
}
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);
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
* 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;
}
/*
- * $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/
#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;
#if USE_ARP_ACL
-struct _acl_arp_data {
+struct _acl_arp_data
+{
char eth[6];
};
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;
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;
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;
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;
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;
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;
void *client_data;
};
-struct _dnsserver_t {
+struct _dnsserver_t
+{
int id;
int inpipe;
int outpipe;
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;
* 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;
off_t offset;
};
-struct _fileMap {
+struct _fileMap
+{
int max_n_files;
int n_files_in_map;
int toggle;
};
/* see Packer.c for description */
-struct _Packer {
+
+struct _Packer
+{
/* protected, use interface functions instead */
append_f append;
vprintf_f vprintf;
};
/* 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 */
* 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;
};
/* 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 */
};
/* 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 */
};
class HttpHdrContRange;
-struct _HttpReply {
+
+struct _HttpReply
+{
/* unsupported, writable, may disappear/change in the future */
int hdr_sz; /* sums _stored_ status-line, headers, and <CRLF> */
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;
int p_rtt;
};
-struct _HierarchyLogEntry {
+struct _HierarchyLogEntry
+{
hier_code code;
char host[SQUIDHOSTNAMELEN];
ping_data ping;
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;
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;
int reserved[32 - 6];
};
-struct _DigestFetchState {
+struct _DigestFetchState
+{
PeerDigest *pd;
StoreEntry *entry;
StoreEntry *old_entry;
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;
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;
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;
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;
int n_peers;
};
-struct _ps_state {
+struct _ps_state
+{
request_t *request;
StoreEntry *entry;
int always_direct;
* 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
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;
#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);
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;
* 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;
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;
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;
FREE *free_func;
};
-struct _ErrorState {
+struct _ErrorState
+{
err_type type;
int page_id;
http_status httpStatus;
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;
};
* "very generic" histogram;
* see important comments on hbase_f restrictions in StatHist.c
*/
-struct _StatHist {
+
+struct _StatHist
+{
int *bins;
int capacity;
double min;
* 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;
* 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;
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 */
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;
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;
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;
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;
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;
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 */
};
* 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 */
* This defines an fs type
*/
-struct _storefs_entry {
+struct _storefs_entry
+{
const char *typestr;
STFSSHUTDOWN *donefunc;
STFSNEW *newfunc;
* This defines an repl type
*/
-struct _storerepl_entry {
+struct _storerepl_entry
+{
const char *typestr;
REMOVALPOLICYCREATE *create;
};
* 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);
/*
- * $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
*
#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;
};
-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 */
/* 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;
}
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;
}
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);
}
{
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);
}
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);
}
{
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
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++;
}
}
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);
}
{
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;
}
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;
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--;
}
}
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);
}
}
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);
}
}
usage(const char *prg_name)
{
fprintf(stderr, "usage: %s <access_log> <swap_state> ...\n",
- prg_name);
+ prg_name);
return -1;
}
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 */
/* 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);
/*
- * $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
{
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 *
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);
}
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 */
#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
}
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));
}
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();
}
{
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
}
#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();
}
/* 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 */
#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);
}
/* 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);
/* 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
}
{
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 */
}
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)
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
}
{
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
}
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
}
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);
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;
}
#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 */
}
#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;
}
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;
doubleAverage(double cur, double newD, int N, int max)
{
if (N > max)
- N = max;
+ N = max;
+
return (cur * (N - 1.0) + newD) / N;
}
intAverage(int cur, int newI, int n, int max)
{
if (n > max)
- n = max;
+ n = max;
+
return (cur * (n - 1) + newI) / n;
}
logsFlush(void)
{
if (debug_log)
- fflush(debug_log);
+ fflush(debug_log);
}
const char *
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);
}
dlinkNodeDelete(dlink_node * m)
{
if (m == NULL)
- return;
+ return;
+
memPoolFree(dlink_node_pool, m);
}
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
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;
}
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;
}
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;
}
{
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;
}
{
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;
}
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;
}
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);
}
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 */
}
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;
}
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);
}
/*
- * $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
#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";
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
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
{
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
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); /* ??? */
}
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); /* ??? */
}
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); /* ??? */
}
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); /* ??? */
}
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);
+ }
}
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
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
{
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);
}
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
+
}
}
* 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;
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.
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);
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
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);
}
/*
- * $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/
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
/* 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 */
typedef void (*ObjPackMethod) (void *obj, Packer * p);
#if USE_HTCP
+
typedef struct _htcpReplyData htcpReplyData;
#endif
typedef int STDIRSELECT(const StoreEntry *);
typedef struct _external_acl external_acl;
+
typedef struct _external_acl_entry external_acl_entry;
#endif /* SQUID_TYPEDEFS_H */
/*
- * $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
cbdataReference(result);
return result;
}
-
+
void
RebuildState::operator delete (void *address)
{
struct InitStoreEntry : public unary_function<StoreMeta, void>
{
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;
};
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);
}
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<UFSSwapDir *>(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<UFSSwapDir *>(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<UFSSwapDir *>(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<UFSSwapDir *>(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);
}
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;
}
/*
- * $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/
* ----------------------------------------------------------
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;
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<IORequestor> Pointer;
virtual void ioCompletedNotification() = 0;
virtual void closeCompleted() = 0;
virtual void writeCompleted(int errflag, size_t len) = 0;
};
-class DiskFile : public RefCountable {
- public:
+class DiskFile : public RefCountable
+{
+
+public:
typedef RefCount<DiskFile> Pointer;
virtual void deleteSelf() const = 0;
virtual void open (int, mode_t, IORequestor::Pointer) = 0;
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;
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 *);
char *read_buf;
};
-class RebuildState : public RefCountable {
+class RebuildState : public RefCountable
+{
+
public:
void *operator new(size_t);
void operator delete(void *);
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();
/*
- * $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
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;
+ }
}
};
memset(&anEntry, '\0', sizeof(StoreEntry));
- DumpStoreMeta dumper;
- for_each(*metadata, dumper);
+ DumpStoreMeta dumper;
+
+ for_each(*metadata, dumper);
return 0;
/*
- * $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
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);
}
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++;
}
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;
}
{
int x;
const char *args[2];
+
struct timeval slp;
args[0] = "(unlinkd)";
args[1] = NULL;
/* 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);
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);
}
/*
- * $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
#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 *
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;
}
* 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;
}
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;
}
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;
}
}
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);
{
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));
}
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;
}
{
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).
*/
* 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]));
}
{
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;
}
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;
}
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);
}
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;
}
}
/*
- * $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
#define URN_REQBUF_SZ 4096
-class UrnState : public StoreClient {
+class UrnState : public StoreClient
+{
+
public:
void created (StoreEntry *newEntry);
void *operator new (size_t byteCount);
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);
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
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;
}
{
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;
}
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
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");
}
request = requestLink(r);
storeLockObject(entry);
setUriResFromRequest(r);
+
if (urlres_r == NULL)
- return;
+ return;
+
StoreEntry::getPublic (this, urlres, METHOD_GET);
}
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
{
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 */
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,
- "<TITLE>Select URL for %s</TITLE>\n"
- "<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n"
- "<H2>Select URL for %s</H2>\n"
- "<TABLE BORDER=\"0\" WIDTH=\"100%%\">\n", storeUrl(e), storeUrl(e));
+ "<TITLE>Select URL for %s</TITLE>\n"
+ "<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n"
+ "<H2>Select URL for %s</H2>\n"
+ "<TABLE BORDER=\"0\" WIDTH=\"100%%\">\n", storeUrl(e), storeUrl(e));
+
for (i = 0; i < urlcnt; i++) {
- u = &urls[i];
- debug(52, 3) ("URL {%s}\n", u->url);
- memBufPrintf(&mb,
- "<TR><TD><A HREF=\"%s\">%s</A></TD>", u->url, u->url);
- if (urls[i].rtt > 0)
- memBufPrintf(&mb,
- "<TD align=\"right\">%4d <it>ms</it></TD>", u->rtt);
- else
- memBufPrintf(&mb, "<TD align=\"right\">Unknown</TD>");
- memBufPrintf(&mb,
- "<TD>%s</TD></TR>\n", u->flags.cached ? " [cached]" : " ");
+ u = &urls[i];
+ debug(52, 3) ("URL {%s}\n", u->url);
+ memBufPrintf(&mb,
+ "<TR><TD><A HREF=\"%s\">%s</A></TD>", u->url, u->url);
+
+ if (urls[i].rtt > 0)
+ memBufPrintf(&mb,
+ "<TD align=\"right\">%4d <it>ms</it></TD>", u->rtt);
+ else
+ memBufPrintf(&mb, "<TD align=\"right\">Unknown</TD>");
+
+ memBufPrintf(&mb,
+ "<TD>%s</TD></TR>\n", u->flags.cached ? " [cached]" : " ");
}
+
memBufPrintf(&mb,
- "</TABLE>"
- "<HR noshade size=\"1px\">\n"
- "<ADDRESS>\n"
- "Generated by %s@%s\n"
- "</ADDRESS>\n",
- full_appname_string, getMyHostname());
+ "</TABLE>"
+ "<HR noshade size=\"1px\">\n"
+ "<ADDRESS>\n"
+ "Generated by %s@%s\n"
+ "</ADDRESS>\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);
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;
}
/*
- * $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 <ramey@csc.ti.com>
{
#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
}
useragentRotateLog(void)
{
#if USE_USERAGENT_LOG
+
if (NULL == useragentlog)
- return;
+ return;
+
logfileRotate(useragentlog);
+
#endif
}
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
}
useragentLogClose(void)
{
#if USE_USERAGENT_LOG
+
if (NULL == useragentlog)
- return;
+ return;
+
logfileClose(useragentlog);
+
useragentlog = NULL;
+
#endif
}
/*
- * $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
#include "DelayPools.h"
#endif
-class WaisStateData {
+class WaisStateData
+{
+
public:
int fd;
StoreEntry *entry;
waisStateFree(int fdnotused, void *data)
{
WaisStateData *waisState = (WaisStateData *)data;
+
if (waisState == NULL)
- return;
+ return;
+
storeUnlockObject(waisState->entry);
+
requestUnlink(waisState->request);
+
cbdataFree(waisState);
}
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);
}
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);
}
}
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);
}
}
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);
}
/*
- * $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
#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;
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;
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;
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;
}
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);
}
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;
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();
+ }
}
}
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;
}
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;
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);
}
/*
- * $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
#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);
static void
whoisWriteComplete(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
{
- xfree(buf);
+ xfree(buf);
}
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
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;
}
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);
}
/*
- * $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 * * * * * * *
*
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;
}
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