/*
- * $Id: HttpStatusLine.cc,v 1.12 1998/06/03 15:52:16 rousskov Exp $
+ * $Id: HttpStatusLine.cc,v 1.13 1998/06/09 05:22:03 wessels Exp $
*
* DEBUG: section 57 HTTP Status-line
* AUTHOR: Alex Rousskov
/* local constants */
const char *HttpStatusLineFormat = "HTTP/%3.1f %3d %s\r\n";
-/* local routines */
-static const char *httpStatusString(http_status status);
-
-
-
void
httpStatusLineInit(HttpStatusLine * sline)
{
return sline->reason ? sline->reason : httpStatusString(sline->status);
}
-static const char *
+const char *
httpStatusString(http_status status)
{
/* why not to return matching string instead of using "p" ? @?@ */
/*
- * $Id: forward.cc,v 1.2 1998/06/05 21:24:57 rousskov Exp $
+ * $Id: forward.cc,v 1.3 1998/06/09 05:22:04 wessels Exp $
*
* DEBUG: section 17 Request Forwarding
* AUTHOR: Duane Wessels
#include "squid.h"
-struct _server {
- char *host;
- u_short port;
- peer *peer;
- struct _server *next;
-};
-
-typedef struct {
- int fd;
- StoreEntry *entry;
- request_t *request;
- struct _server *servers;
-} FwdState;
-
static void fwdStartComplete(peer * p, void *data);
static void fwdStartFail(peer * p, void *data);
static void fwdDispatch(FwdState *, int server_fd);
+static void fwdConnectStart(FwdState * fwdState);
+static void fwdStateFree(FwdState * fwdState);
+static PF fwdConnectTimeout;
+static PF fwdServerClosed;
+static CNCB fwdConnectDone;
static void
-fwdStateFree(void *data)
+fwdStateFree(FwdState *fwdState)
{
- FwdState *fwdState = data;
- struct _server *s;
- struct _server *n = fwdState->servers;
+ FwdServer *s;
+ FwdServer *n = fwdState->servers;
while ((s = n)) {
n = s->next;
xfree(s->host);
cbdataFree(fwdState);
}
+static void
+fwdServerClosed(int fd, void *data)
+{
+ FwdState *fwdState = data;
+ debug(17,3)("fwdServerClosed: FD %d %s\n", fd,
+ storeUrl(fwdState->entry));
+ fwdStateFree(fwdState);
+}
+
static void
fwdConnectDone(int server_fd, int status, void *data)
{
fd_table[server_fd].uses++;
fwdDispatch(fwdState, server_fd);
}
- fwdStateFree(fwdState);
}
static void
const char *url = storeUrl(fwdState->entry);
int fd;
ErrorState *err;
- struct _server *srv = fwdState->servers;
+ FwdServer *srv = fwdState->servers;
assert(srv);
debug(17, 3) ("fwdConnectStart: %s\n", url);
if ((fd = pconnPop(srv->host, srv->port)) >= 0) {
debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd);
+ comm_add_close_handler(fd, fwdServerClosed, fwdState);
fwdConnectDone(fd, COMM_OK, fwdState);
return;
}
err->xerrno = errno;
err->request = requestLink(fwdState->request);
errorAppendEntry(fwdState->entry, err);
+ fwdStateFree(fwdState);
return;
}
+ comm_add_close_handler(fd, fwdServerClosed, fwdState);
commSetTimeout(fd,
Config.Timeout.connect,
fwdConnectTimeout,
fwdStartComplete(peer * p, void *data)
{
FwdState *fwdState = data;
- struct _server *s;
- if (!storeUnlockObject(fwdState->entry))
+ FwdServer *s;
+ if (!storeUnlockObject(fwdState->entry)) {
+ fwdStateFree(fwdState);
return;
+ }
s = xcalloc(1, sizeof(*s));
if (NULL != p) {
s->host = xstrdup(p->host);
{
FwdState *fwdState = data;
ErrorState *err;
- if (!storeUnlockObject(fwdState->entry))
+ if (!storeUnlockObject(fwdState->entry)) {
+ fwdStateFree(fwdState);
return;
+ }
err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
err->request = requestLink(fwdState->request);
errorAppendEntry(fwdState->entry, err);
requestUnlink(fwdState->request);
- cbdataFree(fwdState);
+ fwdStateFree(fwdState);
}
+
static void
fwdDispatch(FwdState * fwdState, int server_fd)
{
request_t *request = fwdState->request;
StoreEntry *entry = fwdState->entry;
debug(17, 5) ("fwdDispatch: FD %d: Fetching '%s %s'\n",
- fwdState->fd,
+ fwdState->client_fd,
RequestMethodStr[request->method],
storeUrl(entry));
assert(!EBIT_TEST(entry->flag, ENTRY_DISPATCHED));
netdbPingSite(request->host);
if (fwdState->servers && (p = fwdState->servers->peer)) {
p->stats.fetches++;
- httpStart(request, entry, p, server_fd);
+ httpStart(fwdState, server_fd);
} else {
switch (request->protocol) {
case PROTO_HTTP:
- httpStart(request, entry, NULL, server_fd);
+ httpStart(fwdState, server_fd);
break;
case PROTO_GOPHER:
gopherStart(entry, server_fd);
waisStart(request, entry, server_fd);
break;
case PROTO_CACHEOBJ:
- cachemgrStart(fwdState->fd, request, entry);
+ cachemgrStart(fwdState->client_fd, request, entry);
break;
case PROTO_URN:
urnStart(request, entry);
fwdState = xcalloc(1, sizeof(FwdState));
cbdataAdd(fwdState, MEM_NONE);
fwdState->entry = entry;
- fwdState->fd = fd;
+ fwdState->client_fd = fd;
fwdState->request = requestLink(request);
switch (request->protocol) {
case PROTO_CACHEOBJ:
return 0;
return 1;
}
+
+void
+fwdFail(FwdState *fwdState, int err_code, http_status http_code, int xerrno)
+{
+ debug(17, 1)("fwdFail: %s \"%s\"\n\t%s\n",
+ err_type_str[err_code],
+ httpStatusString(http_code),
+ storeUrl(fwdState->entry));
+ fwdState->fail.err_code = err_code;
+ fwdState->fail.http_code = http_code;
+ fwdState->fail.xerrno = xerrno;
+}
/*
- * $Id: http.cc,v 1.283 1998/06/04 20:03:07 wessels Exp $
+ * $Id: http.cc,v 1.284 1998/06/09 05:22:05 wessels Exp $
*
* DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
* AUTHOR: Harvest Derived
static void httpMakePrivate(StoreEntry *);
static void httpMakePublic(StoreEntry *);
static STABH httpAbort;
-static HttpStateData *httpBuildState(int, StoreEntry *, request_t *, peer *);
static int httpSocketOpen(StoreEntry *, request_t *);
static void httpRestart(HttpStateData *);
static int httpTryRestart(HttpStateData *);
if (httpState == NULL)
return;
storeUnregisterAbort(httpState->entry);
- assert(httpState->entry->store_status != STORE_PENDING);
storeUnlockObject(httpState->entry);
if (httpState->reply_hdr) {
memFree(MEM_8K_BUF, httpState->reply_hdr);
int len;
int bin;
int clen;
- ErrorState *err;
if (fwdAbortFetch(entry)) {
storeAbort(entry, 0);
comm_close(fd);
fd, xstrerror());
if (ignoreErrno(errno)) {
commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
- } else if (entry->mem_obj->inmem_hi == 0 && httpTryRestart(httpState)) {
- httpRestart(httpState);
- } else if (clen == 0) {
- err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
- err->xerrno = errno;
- err->request = requestLink(httpState->orig_request);
- errorAppendEntry(entry, err);
+ } else if (entry->mem_obj->inmem_hi == 0) {
+ fwdFail(httpState->fwdState, ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, errno);
comm_close(fd);
} else {
storeAbort(entry, 0);
comm_close(fd);
}
} else if (len == 0 && entry->mem_obj->inmem_hi == 0) {
- if (httpTryRestart(httpState)) {
- httpRestart(httpState);
- } else {
- httpState->eof = 1;
- err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
- err->xerrno = errno;
- err->request = requestLink(httpState->orig_request);
- errorAppendEntry(entry, err);
- comm_close(fd);
- }
+ fwdFail(httpState->fwdState, ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE, errno);
+ httpState->eof = 1;
+ comm_close(fd);
} else if (len == 0) {
/* Connection closed; retrieval done. */
httpState->eof = 1;
return fd;
}
-static HttpStateData *
-httpBuildState(int fd, StoreEntry * entry, request_t * orig_request, peer * e)
+void
+httpStart(FwdState * fwdState, int fd)
{
HttpStateData *httpState = memAllocate(MEM_HTTP_STATE_DATA);
- request_t *request;
- storeLockObject(entry);
+ request_t *proxy_req;
+ request_t *orig_req = fwdState->request;
+ debug(11, 3) ("httpStart: \"%s %s\"\n",
+ RequestMethodStr[orig_req->method],
+ storeUrl(fwdState->entry));
cbdataAdd(httpState, MEM_HTTP_STATE_DATA);
- httpState->entry = entry;
+ storeLockObject(fwdState->entry);
+ httpState->fwdState = fwdState;
+ httpState->entry = fwdState->entry;
httpState->fd = fd;
- if (e) {
- request = requestCreate(
- orig_request->method, PROTO_NONE, storeUrl(entry));
- xstrncpy(request->host, e->host, SQUIDHOSTNAMELEN);
- request->port = e->http_port;
- httpState->request = requestLink(request);
- httpState->peer = e;
- httpState->orig_request = requestLink(orig_request);
- EBIT_SET(request->flags, REQ_PROXYING);
+ if (fwdState->servers)
+ httpState->peer = fwdState->servers->peer; /* might be NULL */
+ if (httpState->peer) {
+ proxy_req = requestCreate(orig_req->method,
+ PROTO_NONE, storeUrl(httpState->entry));
+ xstrncpy(proxy_req->host, httpState->peer->host, SQUIDHOSTNAMELEN);
+ proxy_req->port = httpState->peer->http_port;
+ httpState->request = requestLink(proxy_req);
+ httpState->peer = httpState->peer;
+ httpState->orig_request = requestLink(orig_req);
+ EBIT_SET(proxy_req->flags, REQ_PROXYING);
+ /*
+ * 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 (EBIT_TEST(httpState->peer->options, NEIGHBOR_PROXY_ONLY))
+ storeReleaseRequest(httpState->entry);
} else {
- httpState->request = requestLink(orig_request);
- httpState->orig_request = requestLink(orig_request);
+ 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(httpState->fd, httpStateFree, httpState);
- storeRegisterAbort(entry, httpAbort, httpState);
- return httpState;
-}
-
-void
-httpStart(request_t * request, StoreEntry * entry, peer * e, int fd)
-{
- HttpStateData *httpState;
- debug(11, 3) ("httpStart: \"%s %s\"\n",
- RequestMethodStr[request->method], storeUrl(entry));
+ /*
+ * register the handler to free HTTP state data when the FD closes
+ */
+ comm_add_close_handler(fd, httpStateFree, httpState);
+ storeRegisterAbort(httpState->entry, httpAbort, httpState);
Counter.server.all.requests++;
Counter.server.http.requests++;
- if (e)
- if (EBIT_TEST(e->options, NEIGHBOR_PROXY_ONLY))
- storeReleaseRequest(entry);
- httpState = httpBuildState(fd, entry, request, e);
httpConnectDone(fd, COMM_OK, httpState);
}
extern HASHHASH hash4;
extern int httpCachable(method_t);
-extern void httpStart(request_t *, StoreEntry *, peer *, int);
+extern void httpStart(FwdState *, int fd);
extern void httpParseReplyHeaders(const char *, http_reply *);
extern void httpProcessReplyHeader(HttpStateData *, const char *, int);
extern size_t httpBuildRequestPrefix(request_t * request,
const char *end);
/* pack fields using Packer */
extern void httpStatusLinePackInto(const HttpStatusLine * sline, Packer * p);
+extern const char *httpStatusString(http_status status);
/* Http Body */
/* init/clean */
extern int fwdUnregister(StoreEntry *, request_t *);
extern int fwdAbortFetch(StoreEntry * entry);
extern DEFER fwdCheckDeferRead;
+extern void fwdFail(FwdState *, int, http_status, int);
extern void urnStart(request_t *, StoreEntry *);
request_t *orig_request;
int fd;
int flags;
+ FwdState *fwdState;
};
struct _icpUdpData {
int count; /* number of digested entries */
int del_count; /* number of deletions performed so far */
};
+
+struct _FwdState {
+ int client_fd;
+ StoreEntry *entry;
+ request_t *request;
+ FwdServer *servers;
+ struct {
+ int err_code;
+ http_status http_code;
+ int xerrno;
+ } fail;
+};
+
+struct _FwdServer {
+ char *host;
+ u_short port;
+ peer *peer;
+ struct _FwdServer *next;
+};
typedef struct _cd_guess_stats cd_guess_stats;
typedef struct _CacheDigest CacheDigest;
typedef struct _Version Version;
+typedef struct _FwdState FwdState;
+typedef struct _FwdServer FwdServer;
#if SQUID_SNMP
typedef struct _snmp_request_t snmp_request_t;