* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
-#include "config.h"
-
-/* for ClientActiveRequests global */
-#include "dlink.h"
-
-/* old includes without reasons given. */
#include "squid.h"
#include "acl/FilledChecklist.h"
#include "acl/Gadgets.h"
-#include "auth/UserRequest.h"
-#include "client_side.h"
+#include "anyp/PortCfg.h"
#include "client_side_reply.h"
+#include "client_side.h"
#include "clientStream.h"
-#if USE_DELAY_POOLS
-#include "DelayPools.h"
-#endif
+#include "dlink.h"
#include "errorpage.h"
-#if USE_SQUID_ESI
-#include "esi/Esi.h"
-#endif
#include "fde.h"
+#include "format/Token.h"
#include "forward.h"
+#include "globals.h"
+#include "globals.h"
#include "HttpReply.h"
#include "HttpRequest.h"
#include "ip/QosConfig.h"
-#include "log/Tokens.h"
+#include "ipcache.h"
#include "MemObject.h"
+#include "protos.h"
#include "SquidTime.h"
-#include "StoreClient.h"
#include "Store.h"
+#include "StoreClient.h"
+#if USE_AUTH
+#include "auth/UserRequest.h"
+#endif
+#if USE_DELAY_POOLS
+#include "DelayPools.h"
+#endif
+#if USE_SQUID_ESI
+#include "esi/Esi.h"
+#endif
CBDATA_CLASS_INIT(clientReplyContext);
clientReplyContext::setReplyToError(
err_type err, http_status status, const HttpRequestMethod& method, char const *uri,
Ip::Address &addr, HttpRequest * failedrequest, const char *unparsedrequest,
- AuthUserRequest::Pointer auth_user_request)
+#if USE_AUTH
+ Auth::UserRequest::Pointer auth_user_request
+#else
+ void*
+#endif
+)
{
ErrorState *errstate = clientBuildError(err, status, uri, addr, failedrequest);
if (unparsedrequest)
errstate->request_hdrs = xstrdup(unparsedrequest);
- if (status == HTTP_NOT_IMPLEMENTED && http->request)
+#if USE_AUTH
+ errstate->auth_user_request = auth_user_request;
+#endif
+ setReplyToError(method, errstate);
+}
+
+void clientReplyContext::setReplyToError(const HttpRequestMethod& method, ErrorState *errstate)
+{
+ if (errstate->httpStatus == HTTP_NOT_IMPLEMENTED && http->request)
/* prevent confusion over whether we default to persistent or not */
http->request->flags.proxy_keepalive = 0;
- http->al.http.code = errstate->httpStatus;
+ http->al->http.code = errstate->httpStatus;
createStoreEntry(method, request_flags());
-
- errstate->auth_user_request = auth_user_request;
-
assert(errstate->callback_data == NULL);
errorAppendEntry(http->storeEntry(), errstate);
/* Now the caller reads to get this */
}
+void clientReplyContext::setReplyToStoreEntry(StoreEntry *entry)
+{
+ entry->lock(); // removeClientStoreReference() unlocks
+ sc = storeClientListAdd(entry, this);
+#if USE_DELAY_POOLS
+ sc->setDelayId(DelayId::DelayClient(http));
+#endif
+ reqofs = 0;
+ reqsize = 0;
+ flags.storelogiccomplete = 1;
+ http->storeEntry(entry);
+}
+
void
clientReplyContext::removeStoreReference(store_client ** scp,
StoreEntry ** ep)
debugs(88, 5, "clientReplyContext::processExpired : lastmod " << entry->lastmod );
http->storeEntry(entry);
assert(http->out.offset == 0);
-
- http->request->clientConnection = http->getConn();
+ assert(http->request->clientConnectionManager == http->getConn());
/*
* A refcounted pointer so that FwdState stays around as long as
* this clientReplyContext does
*/
- FwdState::fwdStart(http->getConn() != NULL ? http->getConn()->fd : -1,
- http->storeEntry(),
- http->request);
+ Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL;
+ FwdState::Start(conn, http->storeEntry(), http->request, http->al);
+
/* Register with storage manager to receive updates when data comes in. */
if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
- debugs(88, 0, "clientReplyContext::processExpired: Found ENTRY_ABORTED object");
+ debugs(88, DBG_CRITICAL, "clientReplyContext::processExpired: Found ENTRY_ABORTED object");
{
/* start counting the length from 0 */
}
}
-
void
clientReplyContext::sendClientUpstreamResponse()
{
// origin replied 304
if (status == HTTP_NOT_MODIFIED) {
http->logType = LOG_TCP_REFRESH_UNMODIFIED;
+ http->request->flags.stale_if_hit = 0; // old_entry is no longer stale
// update headers on existing entry
old_rep->updateOnNotModified(http->storeEntry()->getReply());
assert(http->logType == LOG_TCP_HIT);
if (strcmp(e->mem_obj->url, urlCanonical(r)) != 0) {
- debugs(33, 1, "clientProcessHit: URL mismatch, '" << e->mem_obj->url << "' != '" << urlCanonical(r) << "'");
+ debugs(33, DBG_IMPORTANT, "clientProcessHit: URL mismatch, '" << e->mem_obj->url << "' != '" << urlCanonical(r) << "'");
processMiss();
return;
}
case VARY_CANCEL:
/* varyEvaluateMatch found a object loop. Process as miss */
- debugs(88, 1, "clientProcessHit: Vary object loop!");
+ debugs(88, DBG_IMPORTANT, "clientProcessHit: Vary object loop!");
processMiss();
return;
}
*/
http->logType = LOG_TCP_CLIENT_REFRESH_MISS;
processMiss();
- } else if (r->protocol == PROTO_HTTP) {
+ } else if (r->protocol == AnyP::PROTO_HTTP) {
/*
* Object needs to be revalidated
* XXX This could apply to FTP as well, if Last-Modified is known.
*/
if (http->storeEntry()) {
if (EBIT_TEST(http->storeEntry()->flags, ENTRY_SPECIAL)) {
- debugs(88, 0, "clientProcessMiss: miss on a special object (" << url << ").");
- debugs(88, 0, "\tlog_type = " << log_tags[http->logType]);
+ debugs(88, DBG_CRITICAL, "clientProcessMiss: miss on a special object (" << url << ").");
+ debugs(88, DBG_CRITICAL, "\tlog_type = " << Format::log_tags[http->logType]);
http->storeEntry()->dump(1);
}
/// Deny loops for accelerator and interceptor. TODO: deny in all modes?
if (r->flags.loopdetect &&
(http->flags.accel || http->flags.intercepted)) {
- http->al.http.code = HTTP_FORBIDDEN;
- err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->peer, http->request);
+ http->al->http.code = HTTP_FORBIDDEN;
+ err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->clientConnection->remote, http->request);
createStoreEntry(r->method, request_flags());
errorAppendEntry(http->storeEntry(), err);
triggerInitialStoreRead();
if (http->redirect.status) {
HttpReply *rep = new HttpReply;
-#if LOG_TCP_REDIRECTS
-
http->logType = LOG_TCP_REDIRECT;
-#endif
-
http->storeEntry()->releaseRequest();
rep->redirect(http->redirect.status, http->redirect.location);
http->storeEntry()->replaceHttpReply(rep);
/** Check for internal requests. Update Protocol info if so. */
if (http->flags.internal)
- r->protocol = PROTO_INTERNAL;
+ r->protocol = AnyP::PROTO_INTERNAL;
- r->clientConnection = http->getConn();
+ assert(r->clientConnectionManager == http->getConn());
/** Start forwarding to get the new object from network */
- FwdState::fwdStart(http->getConn() != NULL ? http->getConn()->fd : -1,
- http->storeEntry(),
- r);
+ Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL;
+ FwdState::Start(conn, http->storeEntry(), r, http->al);
}
}
void
clientReplyContext::processOnlyIfCachedMiss()
{
- ErrorState *err = NULL;
debugs(88, 4, "clientProcessOnlyIfCachedMiss: '" <<
RequestMethodStr(http->request->method) << " " << http->uri << "'");
- http->al.http.code = HTTP_GATEWAY_TIMEOUT;
- err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, NULL, http->getConn()->peer, http->request);
+ http->al->http.code = HTTP_GATEWAY_TIMEOUT;
+ ErrorState *err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, NULL,
+ http->getConn()->clientConnection->remote, http->request);
removeClientStoreReference(&sc, http);
startError(err);
}
if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) {
http->logType = LOG_TCP_DENIED;
- ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->peer, http->request);
+ ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL,
+ http->getConn()->clientConnection->remote, http->request);
startError(err);
return;
}
if (!Config2.onoff.enable_purge) {
http->logType = LOG_TCP_DENIED;
- ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->peer, http->request);
+ ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->clientConnection->remote, http->request);
startError(err);
return;
}
int
clientReplyContext::storeOKTransferDone() const
{
+ assert(http->storeEntry()->objectLen() >= 0);
+ assert(http->storeEntry()->objectLen() >= headers_sz);
if (http->out.offset >= http->storeEntry()->objectLen() - headers_sz) {
debugs(88,3,HERE << "storeOKTransferDone " <<
" out.offset=" << http->out.offset <<
/* haven't found end of headers yet */
return 0;
- int sending = SENDING_BODY;
-
- if (curReply->sline.status == HTTP_NO_CONTENT ||
- curReply->sline.status == HTTP_NOT_MODIFIED ||
- curReply->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,
}
}
-
/* A write has completed, what is the next status based on the
* canonical request data?
* 1 something is wrong
{
#if SIZEOF_INT64_T == 4
if (http->out.size > 0x7FFF0000) {
- debugs(88, 1, "WARNING: closing FD " << fd << " to prevent out.size counter overflow");
- debugs(88, 1, "\tclient " << http->getConn()->peer);
- debugs(88, 1, "\treceived " << http->out.size << " bytes");
- debugs(88, 1, "\tURI " << http->log_uri);
+ debugs(88, DBG_IMPORTANT, "WARNING: closing FD " << fd << " to prevent out.size counter overflow");
+ debugs(88, DBG_IMPORTANT, "\tclient " << http->getConn()->peer);
+ debugs(88, DBG_IMPORTANT, "\treceived " << http->out.size << " bytes");
+ debugs(88, DBG_IMPORTANT, "\tURI " << http->log_uri);
return 1;
}
if (http->out.offset > 0x7FFF0000) {
- debugs(88, 1, "WARNING: closing FD " << fd < " to prevent out.offset counter overflow");
- debugs(88, 1, "\tclient " << http->getConn()->peer);
- debugs(88, 1, "\treceived " << http->out.size << " bytes, offset " << http->out.offset);
- debugs(88, 1, "\tURI " << http->log_uri);
+ debugs(88, DBG_IMPORTANT, "WARNING: closing FD " << fd < " to prevent out.offset counter overflow");
+ debugs(88, DBG_IMPORTANT, "\tclient " << http->getConn()->peer);
+ debugs(88, DBG_IMPORTANT, "\treceived " << http->out.size << " bytes, offset " << http->out.offset);
+ debugs(88, DBG_IMPORTANT, "\tURI " << http->log_uri);
return 1;
}
hdr->delById(HDR_SET_COOKIE);
// TODO: RFC 2965 : Must honour Cache-Control: no-cache="set-cookie2" and remove header.
- // if there is not configured a peer proxy with login=PASS option enabled
+ // if there is not configured a peer proxy with login=PASS or login=PASSTHRU option enabled
// remove the Proxy-Authenticate header
- if ( !(request->peer_login && strcmp(request->peer_login,"PASS") ==0))
+ if ( !request->peer_login || (strcmp(request->peer_login,"PASS") != 0 && strcmp(request->peer_login,"PASSTHRU") != 0))
reply->header.delById(HDR_PROXY_AUTHENTICATE);
reply->header.removeHopByHopEntries();
if (EBIT_TEST(http->storeEntry()->flags, ENTRY_SPECIAL)) {
hdr->delById(HDR_DATE);
hdr->insertTime(HDR_DATE, squid_curtime);
+ } else if (http->getConn() && http->getConn()->port->actAsOrigin) {
+ // Swap the Date: header to current time if we are simulating an origin
+ HttpHeaderEntry *h = hdr->findEntry(HDR_DATE);
+ if (h)
+ hdr->putExt("X-Origin-Date", h->value.termedBuf());
+ hdr->delById(HDR_DATE);
+ hdr->insertTime(HDR_DATE, squid_curtime);
+ h = hdr->findEntry(HDR_EXPIRES);
+ if (h && http->storeEntry()->expires >= 0) {
+ hdr->putExt("X-Origin-Expires", h->value.termedBuf());
+ hdr->delById(HDR_EXPIRES);
+ hdr->insertTime(HDR_EXPIRES, squid_curtime + http->storeEntry()->expires - http->storeEntry()->timestamp);
+ }
+ if (http->storeEntry()->timestamp <= squid_curtime) {
+ // put X-Cache-Age: instead of Age:
+ char age[64];
+ snprintf(age, sizeof(age), "%ld", (long int) squid_curtime - http->storeEntry()->timestamp);
+ hdr->putExt("X-Cache-Age", age);
+ }
} else if (http->storeEntry()->timestamp <= squid_curtime) {
hdr->putInt(HDR_AGE,
squid_curtime - http->storeEntry()->timestamp);
else if (http->storeEntry()->timestamp > 0)
hdr->insertTime(HDR_DATE, http->storeEntry()->timestamp);
else {
- debugs(88,1,"WARNING: An error inside Squid has caused an HTTP reply without Date:. Please report this");
- /* TODO: dump something useful about the problem */
+ debugs(88,DBG_IMPORTANT,"WARNING: An error inside Squid has caused an HTTP reply without Date:. Please report this:");
+ /* dump something useful about the problem */
+ http->storeEntry()->dump(DBG_IMPORTANT);
}
}
}
/* Filter unproxyable authentication types */
-
if (http->logType != LOG_TCP_DENIED &&
hdr->has(HDR_WWW_AUTHENTICATE)) {
HttpHeaderPos pos = HttpHeaderInitPos;
hdr->refreshMask();
}
+#if USE_AUTH
/* Handle authentication headers */
if (http->logType == LOG_TCP_DENIED &&
( reply->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED ||
authenticateFixHeader(reply, request->auth_user_request, request, 0, 1);
} else if (request->auth_user_request != NULL)
authenticateFixHeader(reply, request->auth_user_request, request, http->flags.accel, 0);
+#endif
/* Append X-Cache */
httpHeaderPutStrf(hdr, HDR_X_CACHE, "%s from %s",
#endif
const bool maySendChunkedReply = !request->multipartRangeRequest() &&
+ reply->sline.protocol == AnyP::PROTO_HTTP && // response is HTTP
(request->http_ver >= HttpVersion(1, 1));
/* Check whether we should send keep-alive */
} else if (fdUsageHigh()&& !request->flags.must_keepalive) {
debugs(88, 3, "clientBuildReplyHeader: Not many unused FDs, can't keep-alive");
request->flags.proxy_keepalive = 0;
+ } else if (request->flags.sslBumped && !reply->persistent()) {
+ // We do not really have to close, but we pretend we are a tunnel.
+ debugs(88, 3, "clientBuildReplyHeader: bumped reply forces close");
+ request->flags.proxy_keepalive = 0;
}
// Decide if we send chunked reply
httpHdrMangleList(hdr, request, ROR_REPLY);
}
-
void
clientReplyContext::cloneReply()
{
reply = HTTPMSGLOCK(rep);
- if (reply->sline.protocol == PROTO_HTTP) {
+ if (reply->sline.protocol == AnyP::PROTO_HTTP) {
/* RFC 2616 requires us to advertise our 1.1 version (but only on real HTTP traffic) */
reply->sline.version = HttpVersion(1,1);
}
*/
if (r->flags.nocache) {
-#if USE_DNSSERVERS
-
+#if USE_DNSHELPER
ipcacheInvalidate(r->GetHost());
-
#else
-
ipcacheInvalidateNegative(r->GetHost());
-
-#endif /* USE_DNSSERVERS */
+#endif /* USE_DNSHELPER */
}
else if (r->flags.nocache_hack) {
-#if USE_DNSSERVERS
-
+#if USE_DNSHELPER
ipcacheInvalidate(r->GetHost());
-
#else
-
ipcacheInvalidateNegative(r->GetHost());
-
-#endif /* USE_DNSSERVERS */
+#endif /* USE_DNSHELPER */
}
if (http->redirect.status) {
/** \li If redirection status is True force this to be a MISS */
- debugs(85, 3, "clientProcessRequest2: redirectStatus forced StoreEntry to NULL - MISS");
+ debugs(85, 3, HERE << "REDIRECT status forced StoreEntry to NULL (no body on 3XX responses)");
http->storeEntry(NULL);
- http->logType = LOG_TCP_MISS;
+ http->logType = LOG_TCP_REDIRECT;
doGetMoreData();
return;
}
assert (context);
assert(context->http == http);
-
clientStreamNode *next = ( clientStreamNode *)aNode->node.next->data;
if (!context->ourNode)
assert(http->out.offset == 0);
if (Ip::Qos::TheConfig.isHitTosActive()) {
- Ip::Qos::doTosLocalHit(http->getConn()->fd);
+ Ip::Qos::doTosLocalHit(http->getConn()->clientConnection);
}
if (Ip::Qos::TheConfig.isHitNfmarkActive()) {
- Ip::Qos::doNfmarkLocalHit(http->getConn()->fd);
+ Ip::Qos::doNfmarkLocalHit(http->getConn()->clientConnection);
}
localTempBuffer.offset = reqofs;
tmp_noaddr.SetNoAddr(); // TODO: make a global const
http->logType = LOG_TCP_DENIED_REPLY;
ErrorState *err = clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL,
- http->getConn() != NULL ? http->getConn()->peer : tmp_noaddr,
+ http->getConn() != NULL ? http->getConn()->clientConnection->remote : tmp_noaddr,
http->request);
removeClientStoreReference(&(sc), http);
HTTPMSGUNLOCK(reply);
http->logType = LOG_TCP_HIT;
ErrorState *const err =
clientBuildError(ERR_PRECONDITION_FAILED, HTTP_PRECONDITION_FAILED,
- NULL, http->getConn()->peer, http->request);
+ NULL, http->getConn()->clientConnection->remote, http->request);
removeClientStoreReference(&sc, http);
HTTPMSGUNLOCK(reply);
startError(err);
e = http->storeEntry();
// Copy timestamp from the original entry so the 304
// reply has a meaningful Age: header.
+ e->timestampsSet();
e->timestamp = timestamp;
e->replaceHttpReply(temprep);
e->complete();
http->logType == LOG_TCP_DENIED_REPLY ||
alwaysAllowResponse(reply->sline.status)) {
headers_sz = reply->hdr_sz;
- processReplyAccessResult(1);
+ processReplyAccessResult(ACCESS_ALLOWED);
return;
}
/** check for absent access controls (permit by default) */
if (!Config.accessList.reply) {
- processReplyAccessResult(1);
+ processReplyAccessResult(ACCESS_ALLOWED);
return;
}
}
void
-clientReplyContext::ProcessReplyAccessResult (int rv, void *voidMe)
+clientReplyContext::ProcessReplyAccessResult(allow_t rv, void *voidMe)
{
clientReplyContext *me = static_cast<clientReplyContext *>(voidMe);
me->processReplyAccessResult(rv);
}
void
-clientReplyContext::processReplyAccessResult(bool accessAllowed)
+clientReplyContext::processReplyAccessResult(const allow_t &accessAllowed)
{
debugs(88, 2, "The reply for " << RequestMethodStr(http->request->method)
- << " " << http->uri << " is "
- << ( accessAllowed ? "ALLOWED" : "DENIED")
- << ", because it matched '"
+ << " " << http->uri << " is " << accessAllowed << ", because it matched '"
<< (AclMatchedName ? AclMatchedName : "NO ACL's") << "'" );
- if (!accessAllowed) {
+ if (accessAllowed != ACCESS_ALLOWED) {
ErrorState *err;
err_type page_id;
page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName, 1);
Ip::Address tmp_noaddr;
tmp_noaddr.SetNoAddr();
err = clientBuildError(page_id, HTTP_FORBIDDEN, NULL,
- http->getConn() != NULL ? http->getConn()->peer : tmp_noaddr,
+ http->getConn() != NULL ? http->getConn()->clientConnection->remote : tmp_noaddr,
http->request);
removeClientStoreReference(&sc, http);
startError(err);
-
return;
}
ConnStateData * conn = http->getConn();
- int fd = conn != NULL ? conn->fd : -1;
- if (fd >= 0 && fd_table[fd].closing()) { // too late, our conn is closing
- // TODO: should we also quit when fd is negative?
- debugs(33,3, HERE << "not sending more data to a closing FD " << fd);
+ if (conn == NULL || !conn->isOpen()) {
+ // too late, our conn is closing
+ // TODO: should we also quit?
+ debugs(33,3, HERE << "not sending more data to a closing " << conn->clientConnection);
return;
}
char *buf = next()->readBuffer.data;
- char *body_buf = buf;
-
if (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;
+ memcpy(buf, result.data, result.length);
}
- if (reqofs==0 && !logTypeIsATcpHit(http->logType)) {
- assert(fd >= 0); // the beginning of this method implies fd may be -1
+ if (reqofs==0 && !logTypeIsATcpHit(http->logType) && Comm::IsConnOpen(conn->clientConnection)) {
if (Ip::Qos::TheConfig.isHitTosActive()) {
- Ip::Qos::doTosLocalMiss(fd, http->request->hier.code);
+ Ip::Qos::doTosLocalMiss(conn->clientConnection, http->request->hier.code);
}
if (Ip::Qos::TheConfig.isHitNfmarkActive()) {
- Ip::Qos::doNfmarkLocalMiss(fd, http->request->hier.code);
+ Ip::Qos::doNfmarkLocalMiss(conn->clientConnection, http->request->hier.code);
}
}
reqofs << " bytes (" << result.length <<
" new bytes)");
debugs(88, 5, "clientReplyContext::sendMoreData:"
- " FD " << fd <<
+ << conn->clientConnection <<
" '" << entry->url() << "'" <<
" out.offset=" << http->out.offset);
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);
+ safe_free(http->al->headers.reply);
+ http->al->headers.reply = (char *)xcalloc(k + 1, 1);
+ xstrncpy(http->al->headers.reply, buf, k);
}
}
return;
}
-
-
/* Using this breaks the client layering just a little!
*/
void
*/
if (http->request == NULL)
- http->request = HTTPMSGLOCK(new HttpRequest(m, PROTO_NONE, null_string));
+ http->request = HTTPMSGLOCK(new HttpRequest(m, AnyP::PROTO_NONE, null_string));
StoreEntry *e = storeCreateEntry(http->uri, http->log_uri, reqFlags, m);
clientBuildError(err_type page_id, http_status status, char const *url,
Ip::Address &src_addr, HttpRequest * request)
{
- ErrorState *err = errorCon(page_id, status, request);
+ ErrorState *err = new ErrorState(page_id, status, request);
err->src_addr = src_addr;
if (url)