++ s/sprintf/snprintf/g
+
+ Write the text for all the error message files
+ we don't properly handle the HTTP/1.1 'Connection' header
+ make USE_PROXY_AUTH standard
+ Incorporate Pelletier's latest retry patch for 1.1
+ FTP PUT
-+ s/sprintf/snprintf/g
+ be more persistent in forwarding requests; return fewer error pages
+ AS # routing
+ Send full HTTP requests in ICP messages
<!-- %%%% Chapter : IP CACHE %%%% -->
<sect>IP Cache
+<P>
+The IP cache is a built-in component of squid providing
+Hostname to IP-Number translation functionality and managing
+the involved data-structures . It usually
+doesn't block on a request except for special cases where this
+is desired (explained below).
+The data structure used for storing name-address mappings
+is a small hashtable (<em>static hash_table *ip_table</em>),
+where structures of type <em>ipcache_entry</em> whose most
+interesting members are:
+<verb>
+struct _ipcache_entry {
+char *name;
+time_t lastref;
+ipcache_addrs addrs;
+struct _ip_pending *pending_head;
+char *error_message;
+unsigned char locks;
+ipcache_status_t status:3;
+}
+</verb>
+
+Main functionality
+is provided through calls to:
+<descrip>
+<tag>ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerdata)
+</tag>
+where <em/name/ is the name of the host to resolve, <em/handler/ is a
+pointer to the function to be called when the reply from the IP cache (or
+the DNS if the IP cache misses) and <em/handlerdata/ is information that
+is passed to the handler and does not affect the IP cache.
+<tag>ipcache_gethostbyname(const char *name,int flags)</tag>
+is different in that
+it only checks if an entry exists in it's data-structures and does not by
+default contact the DNS, unless this is requested, by setting the <em/flags/ to
+<em/IP_BLOCKING_LOOKUP/ or <em/IP_LOOKUP_IF_MISS/.
+<tag>ipcache_init()</tag> is called from <em/mainInitialize()/ after disk
+initialization and prior to the reverse fqdn cache initialization
+<tag>ipcache_restart()</tag> is called to clear the IP cache's data structures,
+cancel all pending requests. Currently, it is only called from
+<em/mainReconfigure/.
+</descrip>
+
+
<!-- %%%% Chapter : SERVER PROTOCOLS %%%% -->
<sect>Server Protocols
<sect1>HTTP
<P>
This means that:
<PRE>
- @LONG_DESCRIPTION@
+ The cache was not able to resolve the hostname presented in the URL.
+ Check if the address is correct.
</PRE>
/*
- * $Id: util.h,v 1.31 1997/07/16 20:31:53 wessels Exp $
+ * $Id: util.h,v 1.32 1997/10/16 19:22:36 kostas Exp $
*
* AUTHOR: Harvest Derived
*
extern char *uudecode _PARAMS((const char *));
extern char *xstrdup _PARAMS((const char *));
extern const char *xstrerror _PARAMS((void));
+extern const char *xbstrerror _PARAMS((int));
extern int tvSubMsec _PARAMS((struct timeval, struct timeval));
extern int tvSubUsec _PARAMS((struct timeval, struct timeval));
extern char *xstrncpy _PARAMS((char *, const char *, size_t));
#define AUTH_MSG_SZ 4096
#define HTTP_REPLY_BUF_SZ 4096
+#if !defined(ERROR_BUF_SZ) && defined(MAX_URL)
+#define ERROR_BUF_SZ (MAX_URL << 2)
+#endif
+
#define HTTP_PROXYING (1<<0)
#define HTTP_KEEPALIVE (1<<1)
typedef enum {
ERR_NONE,
+ ERR_NO_CLIENTS,
ERR_READ_TIMEOUT,
ERR_LIFETIME_EXP,
ERR_READ_ERROR,
/*
- * $Id: errorpage.cc,v 1.71 1997/10/14 18:24:32 wessels Exp $
+ * $Id: errorpage.cc,v 1.72 1997/10/16 19:22:38 kostas Exp $
*
* DEBUG: section 4 Error Generation
* AUTHOR: Duane Wessels
p=buf;
break;
case 'E':
- snprintf(buf, CVT_BUF_SZ, "(%d) %s", err->errno, xstrerror());
+ snprintf(buf, CVT_BUF_SZ, "(%d) %s", err->errno,xbstrerror(err->errno));
+ break;
+ case 'w':
+ snprintf(buf, CVT_BUF_SZ, "%s",Config.adminEmail);
+ break;
+ case 'h':
+ snprintf(buf, CVT_BUF_SZ, "%s", getMyHostname());
break;
/*
* e - errno x
* I - server IP address
* i - client IP address
* L - HREF link for more info/contact
- * w - cachemgr email address
- * h - cache hostname
+ * w - cachemgr email address x
+ * h - cache hostname x
* d - seconds elapsed since request received
- * p - URL port #
+ * p - URL port # x
*/
default:
p = "%UNKNOWN%";
return p;
}
-#define ERROR_BUF_SZ (MAX_URL<<2)
-
static char *
errorBuildBuf(ErrorState * err, int *len)
{
/*
- * $Id: gopher.cc,v 1.94 1997/10/14 16:56:04 wessels Exp $
+ * $Id: gopher.cc,v 1.95 1997/10/16 19:22:38 kostas Exp $
*
* DEBUG: section 10 Gopher
* AUTHOR: Harvest Derived
{
GopherStateData *gopherState = data;
StoreEntry *entry = gopherState->entry;
+ ErrorState *err;
+
debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, entry->url);
- assert(!ERR_READ_TIMEOUT);
+ /* was assert */
+ if (entry->object_len == 0) {
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_READ_TIMEOUT;
+ err->http_status=HTTP_GATEWAY_TIMEOUT;
+ err->url=gopherState->request;
+ errorAppendEntry(entry, err);
+ }
storeAbort(entry, 0);
comm_close(fd);
}
gopherReadReply,
data, 0);
} else {
- assert(!ERR_READ_ERROR);
- storeAbort(entry, 0);
- comm_close(fd);
+ /* was assert */
+ ErrorState *err;
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_READ_ERROR;
+ err->errno=errno;
+ err->http_status=HTTP_INTERNAL_SERVER_ERROR;
+ err->url = entry->url;
+ errorAppendEntry(entry, err);
+ storeAbort(entry, 0);
+ comm_close(fd);
}
} else if (len == 0 && entry->mem_obj->e_current_len == 0) {
- assert(!ERR_ZERO_SIZE_OBJECT);
+ /* was assert */
+ ErrorState *err;
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_ZERO_SIZE_OBJECT;
+ err->errno = errno;
+ err->http_status=HTTP_SERVICE_UNAVAILABLE;
+ err->url=gopherState->request;
+ errorAppendEntry(entry, err);
storeAbort(entry, 0);
comm_close(fd);
} else if (len == 0) {
debug(10, 5) ("gopherSendComplete: FD %d size: %d errflag: %d\n",
fd, size, errflag);
if (errflag) {
- assert(!ERR_CONNECT_FAIL);
+ /* was assert */
+ ErrorState *err;
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_CONNECT_FAIL;
+ err->errno=errno;
+ err->host = xstrdup(gopherState->host);
+ err->port = gopherState->port;
+ err->http_status=HTTP_SERVICE_UNAVAILABLE;
+ err->url=entry->url;
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
comm_close(fd);
if (buf)
{
char *url = entry->url;
GopherStateData *gopherState = CreateGopherStateData();
+ ErrorState *err;
int fd;
storeLockObject(entry);
gopherState->entry = entry;
/* Parse url. */
if (gopher_url_parser(url, gopherState->host, &gopherState->port,
&gopherState->type_id, gopherState->request)) {
- assert(!ERR_INVALID_URL);
+ /* was assert */
+ ErrorState *err;
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_INVALID_URL;
+ err->http_status=HTTP_BAD_REQUEST;
+ err->url=url;
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
gopherStateFree(-1, gopherState);
return;
url);
if (fd == COMM_ERROR) {
debug(10, 4) ("gopherStart: Failed because we're out of sockets.\n");
- assert(!ERR_SOCKET_FAILURE);
+ /* was assert */
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_SOCKET_FAILURE;
+ err->errno=errno;
+ err->http_status=HTTP_INTERNAL_SERVER_ERROR;
+ if (entry && entry->url)
+ err->url=entry->url;
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
gopherStateFree(-1, gopherState);
return;
}
comm_add_close_handler(fd, gopherStateFree, gopherState);
storeRegisterAbort(entry, gopherAbort, gopherState);
+
+ /* check if IP is already in cache. It must be.
+ * It should be done before this route is called.
+ * Otherwise, we cannot check return code for connect. */
+ if (!ipcache_gethostbyname(gopherState->host, 0)) {
+ debug(10, 4) ("gopherStart: Called without IP entry in ipcache. OR lookup failed.\n");
+ /* was assert */
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_DNS_FAIL;
+ err->http_status = HTTP_SERVICE_UNAVAILABLE;
+ err->dnsserver_msg = xstrdup(dns_error_message);
+ err->url=entry->url;
+ errorAppendEntry(entry, err);
+ storeAbort(entry, 0);
+ comm_close(fd);
+ return;
+ }
+
if (((gopherState->type_id == GOPHER_INDEX) || (gopherState->type_id == GOPHER_CSO))
&& (strchr(gopherState->request, '?') == NULL)) {
/* Index URL without query word */
gopherConnectDone(int fd, int status, void *data)
{
GopherStateData *gopherState = data;
+ StoreEntry *entry = gopherState->entry;
+
+ ErrorState *err;
if (status == COMM_ERR_DNS) {
debug(10, 4) ("gopherConnectDone: Unknown host: %s\n", gopherState->host);
- assert(!ERR_DNS_FAIL);
+ /* was assert */
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_DNS_FAIL;
+ err->dnsserver_msg = xstrdup(dns_error_message);
+ err->http_status=HTTP_SERVICE_UNAVAILABLE;
+ err->url=entry->url;
+ errorAppendEntry(entry, err);
storeAbort(gopherState->entry, 0);
comm_close(fd);
} else if (status != COMM_OK) {
- assert(!ERR_CONNECT_FAIL);
+ /* was assert */
+ ErrorState *err;
+ err=xcalloc(1,sizeof(ErrorState));
+ err->type=ERR_CONNECT_FAIL;
+ err->http_status=HTTP_SERVICE_UNAVAILABLE;
+ err->errno= errno;
+ err->host = xstrdup(gopherState->host);
+ err->port = gopherState->port;
+ err->url=entry->url;
+ errorAppendEntry(entry, err);
storeAbort(gopherState->entry, 0);
comm_close(fd);
} else {
/*
- * $Id: mime.cc,v 1.38 1997/10/13 22:09:16 kostas Exp $
+ * $Id: mime.cc,v 1.39 1997/10/16 19:22:39 kostas Exp $
*
* DEBUG: section 25 MIME Parsing
* AUTHOR: Harvest Derived
/* NOTE: don't know size of result thus didn't change
to snprintf(). Should be done sometime! */
- sprintf(result, "Server: %s/%s\r\n%s%s%sContent-Type: %s\r\n%s",
+ snprintf(result, MAX_MIME, "Server: %s/%s\r\n%s%s%sContent-Type: %s\r\n%s",
appname,
version_string,
date,
/*
- * $Id: squid.h,v 1.129 1997/07/16 20:32:16 wessels Exp $
+ * $Id: squid.h,v 1.130 1997/10/16 19:22:40 kostas Exp $
*
* AUTHOR: Duane Wessels
*
#define BUFSIZ 4096 /* make reasonable guess */
#endif
+
#ifndef SA_RESTART
#define SA_RESTART 0
#endif
/*
- * $Id: store_dir.cc,v 1.28 1997/10/13 22:09:23 kostas Exp $
+ * $Id: store_dir.cc,v 1.29 1997/10/16 19:22:41 kostas Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
safeunlink(path, 1);
if (mkdir(path, 0777) < 0) {
if (errno != EEXIST) {
- /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
- change to snprintf() ... yet */
- sprintf(tmp_error_buf, "Failed to create swap directory %s: %s",
+ /* NOTE: couldn't figure size of tmp_error_buf, assumed
+ ERROR_BUF_SZ */
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
+ "Failed to create swap directory %s: %s",
path,
xstrerror());
fatal(tmp_error_buf);
}
debug(47, 1) ("Created directory %s\n", path);
if (stat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) {
- /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
- change to snprintf() ... yet */
- sprintf(tmp_error_buf,
+ /* NOTE: couldn't figure size of tmp_error_buf, assumed
+ ERROR_BUF_SZ */
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
"Failed to create directory %s: %s", path, xstrerror());
fatal(tmp_error_buf);
}
/*
- * $Id: tools.cc,v 1.121 1997/10/13 22:09:24 kostas Exp $
+ * $Id: tools.cc,v 1.122 1997/10/16 19:22:41 kostas Exp $
*
* DEBUG: section 21 Misc Functions
* AUTHOR: Harvest Derived
#endif /* HAVE_GETRUSAGE */
}
+
void
death(int sig)
{
if (rl.rlim_cur > rl.rlim_max)
Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
- /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
- change to snprintf() ... yet */
- sprintf(tmp_error_buf, "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
+ /* NOTE: couldn't figure size of tmp_error_buf, thus
+ assuming ERROR_BUF_SZ */
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
+ "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
fatal_dump(tmp_error_buf);
}
}
if (rl.rlim_cur > rl.rlim_max)
Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
- /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
- change to snprintf() ... yet */
- sprintf(tmp_error_buf, "setrlimit: RLIMIT_OFILE: %s", xstrerror());
+ /* NOTE: couldn't figure size of tmp_error_buf, thus
+ assuming ERROR_BUF_SZ */
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
+ "setrlimit: RLIMIT_OFILE: %s", xstrerror());
fatal_dump(tmp_error_buf);
}
}
} 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) {
- /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
- change to snprintf() ... yet */
- sprintf(tmp_error_buf, "setrlimit: RLIMIT_DATA: %s", xstrerror());
+ /* NOTE: couldn't figure size of tmp_error_buf, thus d
+ assuming ERROR_BUF_SZ */
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
+ "setrlimit: RLIMIT_DATA: %s", xstrerror());
fatal_dump(tmp_error_buf);
}
}
} 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) {
- /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
- change to snprintf() ... yet */
- sprintf(tmp_error_buf, "setrlimit: RLIMIT_VMEM: %s", xstrerror());
+ /* NOTE: couldn't figure size of tmp_error_buf, thus
+ assuming ERROR_BUF_SZ */
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
+ "setrlimit: RLIMIT_VMEM: %s", xstrerror());
fatal_dump(tmp_error_buf);
}
}
/*
- * $Id: wais.cc,v 1.82 1997/10/14 18:31:28 wessels Exp $
+ * $Id: wais.cc,v 1.83 1997/10/16 19:22:42 kostas Exp $
*
* DEBUG: section 24 WAIS Relay
* AUTHOR: Harvest Derived
waisTimeout(int fd, void *data)
{
WaisStateData *waisState = data;
+ ErrorState *err;
StoreEntry *entry = waisState->entry;
debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, entry->url);
- assert(!ERR_READ_TIMEOUT);
+ /* was assert */
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_READ_TIMEOUT;
+ err->http_status = HTTP_GATEWAY_TIMEOUT;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
comm_close(fd);
}
int off;
int bin;
if (protoAbortFetch(entry)) {
- assert(!ERR_CLIENT_ABORT);
+ /* was assert */
+ ErrorState *err;
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_CLIENT_ABORT;
+ err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
storeAbort(entry, 0);
comm_close(fd);
return;
}
if (entry->flag & DELETE_BEHIND && !storeClientWaiting(entry)) {
/* we can terminate connection right now */
+ /* was assert */
+ ErrorState *err;
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_NO_CLIENTS;
+ err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
storeAbort(entry, 0);
comm_close(fd);
return;
commSetSelect(fd, COMM_SELECT_READ,
waisReadReply, waisState, 0);
} else {
+ ErrorState *err;
BIT_RESET(entry->flag, ENTRY_CACHABLE);
storeReleaseRequest(entry);
- assert(!ERR_READ_ERROR);
+ /* was assert */
+
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_READ_ERROR;
+ err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
comm_close(fd);
}
} else if (len == 0 && entry->mem_obj->e_current_len == 0) {
- assert(!ERR_ZERO_SIZE_OBJECT);
+ /* was assert */
+ ErrorState *err;
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_ZERO_SIZE_OBJECT;
+ err->errno = errno;
+ err->http_status = HTTP_SERVICE_UNAVAILABLE;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
comm_close(fd);
} else if (len == 0) {
debug(24, 5) ("waisSendComplete: FD %d size: %d errflag: %d\n",
fd, size, errflag);
if (errflag) {
- assert(!ERR_CONNECT_FAIL);
+ /* was assert */
+ ErrorState *err;
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_CONNECT_FAIL;
+ err->errno=errno;
+ err->host =xstrdup(waisState->relayhost);
+ err->port = waisState->relayport;
+ err->http_status = HTTP_SERVICE_UNAVAILABLE;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
comm_close(fd);
} else {
method_t method = request->method;
debug(24, 3) ("waisStart: \"%s %s\"\n", RequestMethodStr[method], url);
if (!Config.Wais.relayHost) {
+ ErrorState *err;
debug(24, 0) ("waisStart: Failed because no relay host defined!\n");
- assert(!ERR_NO_RELAY);
+ /* was assert */
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_NO_RELAY;
+ err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
+
storeAbort(entry, 0);
return;
}
COMM_NONBLOCKING,
url);
if (fd == COMM_ERROR) {
+ ErrorState *err;
debug(24, 4) ("waisStart: Failed because we're out of sockets.\n");
- assert(!ERR_SOCKET_FAILURE);
+ /* was assert */
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_SOCKET_FAILURE;
+ err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+ err->request = urlParse(METHOD_CONNECT, waisState->request);
+ errorAppendEntry(entry, err);
storeAbort(entry, 0);
return;
}
waisConnectDone(int fd, int status, void *data)
{
WaisStateData *waisState = data;
+ char *request = waisState->request;
+ ErrorState *err;
+
if (status == COMM_ERR_DNS) {
- assert(!ERR_DNS_FAIL);
+ /* was assert */
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_DNS_FAIL;
+ err->http_status = HTTP_SERVICE_UNAVAILABLE;
+ err->dnsserver_msg = xstrdup(dns_error_message);
+ err->request = urlParse(METHOD_CONNECT, request);
+ errorAppendEntry(waisState->entry, err);
storeAbort(waisState->entry, 0);
comm_close(fd);
} else if (status != COMM_OK) {
- assert(!ERR_CONNECT_FAIL);
+ /* was assert */
+ err = xcalloc(1, sizeof(ErrorState));
+ err->type = ERR_CONNECT_FAIL;
+ err->http_status = HTTP_SERVICE_UNAVAILABLE;
+ err->errno = errno;
+ err->host = xstrdup(waisState->relayhost);
+ err->port = waisState->relayport;
+ err->request = urlParse(METHOD_CONNECT, request);
+ errorAppendEntry(waisState->entry, err);
storeAbort(waisState->entry, 0);
comm_close(fd);
} else {