#include "client_side_reply.h"
#include "client_side_request.h"
#include "ClientRequestContext.h"
+#include "comm/Connection.h"
#include "compat/inet_pton.h"
#include "fde.h"
#include "HttpReply.h"
#include "HttpRequest.h"
+#include "ip/QosConfig.h"
#include "MemObject.h"
#include "ProtoPort.h"
#include "Store.h"
#include "SquidTime.h"
#include "wordlist.h"
+#include "err_detail_type.h"
#if LINGERING_CLOSE
{
start_time = current_time;
setConn(aConn);
+ clientConnection = aConn->clientConn;
dlinkAdd(this, &active, &ClientActiveRequests);
#if USE_ADAPTATION
request_satisfaction_mode = false;
if (calloutContext)
delete calloutContext;
+ clientConnection = NULL;
+
if (conn_)
cbdataReferenceDone(conn_);
acl_checklist = clientAclChecklistCreate(Config.accessList.adapted_http, http);
acl_checklist->nonBlockingCheck(clientAccessCheckDoneWrapper, this);
} else {
- debugs(85, 2, HERE << "No adapted_http_access configuration.");
+ debugs(85, 2, HERE << "No adapted_http_access configuration. default: ALLOW");
clientAccessCheckDone(ACCESS_ALLOWED);
}
}
tmpnoaddr.SetNoAddr();
repContext->setReplyToError(page_id, status,
http->request->method, NULL,
- http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
+ http->getConn() != NULL ? http->getConn()->clientConn->remote : tmpnoaddr,
http->request,
NULL,
http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
if (http->getConn() != NULL) {
ih->rfc931 = http->getConn()->rfc931;
#if USE_SSL
- ih->ssluser = sslGetUserEmail(fd_table[http->getConn()->fd].ssl);
+ assert(http->getConn()->clientConn != NULL);
+ ih->ssluser = sslGetUserEmail(fd_table[http->getConn()->clientConn->fd].ssl);
#endif
}
ih->log_uri = http->log_uri;
}
if (no_cache) {
-#if HTTP_VIOLATIONS
+#if USE_HTTP_VIOLATIONS
if (Config.onoff.reload_into_ims)
request->flags.nocache_hack = 1;
/* ignore range header in non-GETs or non-HEADs */
if (request->method == METHOD_GET || request->method == METHOD_HEAD) {
- request->range = req_hdr->getRange();
+ // XXX: initialize if we got here without HttpRequest::parseHeader()
+ if (!request->range)
+ request->range = req_hdr->getRange();
if (request->range) {
request->flags.range = 1;
else {
req_hdr->delById(HDR_RANGE);
req_hdr->delById(HDR_REQUEST_RANGE);
+ delete request->range;
request->range = NULL;
}
}
#endif
- if (request->method == METHOD_TRACE || request->method == METHOD_OPTIONS) {
- request->max_forwards = req_hdr->getInt64(HDR_MAX_FORWARDS);
- }
request->flags.cachable = http->request->cacheable();
if ((t = strchr(result, ':')) != NULL) {
http->redirect.status = status;
http->redirect.location = xstrdup(t + 1);
+ // TODO: validate the URL produced here is RFC 2616 compliant absolute URI
} else {
- debugs(85, 1, "clientRedirectDone: bad input: " << result);
+ if (old_request->http_ver < HttpVersion(1,1))
+ debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid 302 redirect Location: " << result);
+ else
+ debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid 303 redirect Location: " << result);
}
- } else if (strcmp(result, http->uri))
- new_request = HttpRequest::CreateFromUrlAndMethod(result, old_request->method);
+ } else if (strcmp(result, http->uri)) {
+ if (!(new_request = HttpRequest::CreateFromUrlAndMethod(result, old_request->method)))
+ debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid request: " <<
+ old_request->method << " " << result << " HTTP/1.1");
+ }
}
if (new_request) {
/* FIXME PIPELINE: This is innacurate during pipelining */
- if (http->getConn() != NULL)
- fd_note(http->getConn()->fd, http->uri);
+ if (http->getConn() != NULL && Comm::IsConnOpen(http->getConn()->clientConn))
+ fd_note(http->getConn()->clientConn->fd, http->uri);
assert(http->uri);
if (request->method == METHOD_CONNECT && !redirect.status) {
logType = LOG_TCP_MISS;
+ getConn()->stopReading(); // tunnels read for themselves
tunnelStart(this, &out.size, &al.http.code);
return;
}
// called when comm_write has completed
static void
-SslBumpEstablish(int, char *, size_t, comm_err_t errflag, int, void *data)
+SslBumpEstablish(const Comm::ConnectionPointer &, char *, size_t, comm_err_t errflag, int, void *data)
{
ClientHttpRequest *r = static_cast<ClientHttpRequest*>(data);
debugs(85, 5, HERE << "responded to CONNECT: " << r << " ? " << errflag);
void
ClientHttpRequest::sslBumpStart()
{
- debugs(85, 5, HERE << "ClientHttpRequest::sslBumpStart");
-
+ debugs(85, 5, HERE << "Confirming CONNECT tunnel on FD " << getConn()->clientConn);
// send an HTTP 200 response to kick client SSL negotiation
- const int fd = getConn()->fd;
- debugs(33, 7, HERE << "Confirming CONNECT tunnel on FD " << fd);
+ debugs(33, 7, HERE << "Confirming CONNECT tunnel on FD " << getConn()->clientConn);
// TODO: Unify with tunnel.cc and add a Server(?) header
- static const char *const conn_established =
- "HTTP/1.0 200 Connection established\r\n\r\n";
- comm_write(fd, conn_established, strlen(conn_established),
- &SslBumpEstablish, this, NULL);
+ static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
+ comm_write(getConn()->clientConn, conn_established, strlen(conn_established), &SslBumpEstablish, this, NULL);
}
#endif
* the callout. This is strictly for convenience.
*/
-extern int aclMapTOS (acl_tos * head, ACLChecklist * ch);
+extern tos_t aclMapTOS (acl_tos * head, ACLChecklist * ch);
+extern nfmark_t aclMapNfmark (acl_nfmark * head, ACLChecklist * ch);
void
ClientHttpRequest::doCallouts()
}
}
- if (!calloutContext->clientside_tos_done) {
- calloutContext->clientside_tos_done = true;
- if (getConn() != NULL) {
+ if (!calloutContext->tosToClientDone) {
+ calloutContext->tosToClientDone = true;
+ if (getConn() != NULL && Comm::IsConnOpen(getConn()->clientConn)) {
ACLFilledChecklist ch(NULL, request, NULL);
ch.src_addr = request->client_addr;
ch.my_addr = request->my_addr;
- int tos = aclMapTOS(Config.accessList.clientside_tos, &ch);
+ tos_t tos = aclMapTOS(Ip::Qos::TheConfig.tosToClient, &ch);
if (tos)
- comm_set_tos(getConn()->fd, tos);
+ Ip::Qos::setSockTos(getConn()->clientConn, tos);
+ }
+ }
+
+ if (!calloutContext->nfmarkToClientDone) {
+ calloutContext->nfmarkToClientDone = true;
+ if (getConn() != NULL && Comm::IsConnOpen(getConn()->clientConn)) {
+ ACLFilledChecklist ch(NULL, request, NULL);
+ ch.src_addr = request->client_addr;
+ ch.my_addr = request->my_addr;
+ nfmark_t mark = aclMapNfmark(Ip::Qos::TheConfig.nfmarkToClient, &ch);
+ if (mark)
+ Ip::Qos::setSockNfmark(getConn()->clientConn, mark);
}
}
assert(!virginHeadSource);
assert(!adaptedBodySource);
virginHeadSource = initiateAdaptation(
- new Adaptation::Iterator(this, request, NULL, g));
+ new Adaptation::Iterator(request, NULL, g));
// we could try to guess whether we can bypass this adaptation
// initiation failure, but it should not really happen
- assert(virginHeadSource != NULL); // Must, really
+ Must(initiated(virginHeadSource));
}
void
{
clearAdaptation(virginHeadSource);
assert(!adaptedBodySource);
- handleAdaptationFailure(!final);
+ handleAdaptationFailure(ERR_DETAIL_ICAP_REQMOD_ABORT, !final);
}
void
{
assert(!virginHeadSource);
stopConsumingFrom(adaptedBodySource);
- handleAdaptationFailure();
+ handleAdaptationFailure(ERR_DETAIL_ICAP_RESPMOD_CLT_SIDE_BODY);
}
void
-ClientHttpRequest::handleAdaptationFailure(bool bypassable)
+ClientHttpRequest::handleAdaptationFailure(int errDetail, bool bypassable)
{
debugs(85,3, HERE << "handleAdaptationFailure(" << bypassable << ")");
ConnStateData * c = getConn();
repContext->setReplyToError(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
request->method, NULL,
- (c != NULL ? c->peer : noAddr), request, NULL,
+ (c != NULL ? c->clientConn->remote : noAddr), request, NULL,
(c != NULL && c->auth_user_request != NULL ?
c->auth_user_request : request->auth_user_request));
+ request->detailError(ERR_ICAP_FAILURE, errDetail);
+
node = (clientStreamNode *)client_stream.tail->data;
clientStreamRead(node, this, node->readBuffer);
}