*/
#include "squid.h"
-#include "clientStream.h"
-#include "client_side_request.h"
-#include "auth/UserRequest.h"
-#include "HttpRequest.h"
-#include "ProtoPort.h"
#include "acl/FilledChecklist.h"
#include "acl/Gadgets.h"
-#include "client_side.h"
-#include "client_side_reply.h"
-#include "Store.h"
-#include "HttpReply.h"
-#include "MemObject.h"
-#include "ClientRequestContext.h"
-#include "SquidTime.h"
-#include "wordlist.h"
-#include "inet_pton.h"
-#include "fde.h"
-
#if USE_ADAPTATION
#include "adaptation/AccessCheck.h"
#include "adaptation/Iterator.h"
#if ICAP_CLIENT
#include "adaptation/icap/History.h"
#endif
-//static void adaptationAclCheckDoneWrapper(Adaptation::ServicePointer service, void *data);
#endif
-
+#include "auth/UserRequest.h"
+#include "clientStream.h"
+#include "client_side.h"
+#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_);
request->my_addr.SetPort(0);
- /* RFC 2616 says 'upgrade' to our 1.0 regardless of what the client is */
- HttpVersion http_ver(1,0);
+ /* Our version is HTTP/1.1 */
+ HttpVersion http_ver(1,1);
request->http_ver = http_ver;
http->request = HTTPMSGLOCK(request);
const char *p;
const char *asciiaddr;
int l;
- IpAddress addr;
+ Ip::Address addr;
p = request->x_forwarded_for_iterator.termedBuf();
l = request->x_forwarded_for_iterator.size();
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);
}
}
clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data;
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- IpAddress tmpnoaddr;
+ Ip::Address tmpnoaddr;
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;
}
request->flags.loopdetect = 1;
}
-#if FORW_VIA_DB
+#if USE_FORW_VIA_DB
fvdbCountVia(s.termedBuf());
#endif
logReferer(fqdnFromAddr(http->getConn()->log_addr), str, http->log_uri);
#endif
-#if FORW_VIA_DB
+#if USE_FORW_VIA_DB
if (req_hdr->has(HDR_X_FORWARDED_FOR)) {
String s = req_hdr->getList(HDR_X_FORWARDED_FOR);
}
#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);
}
}
#endif
}
-#ifndef _USE_INLINE_
+#if !_USE_INLINE_
#include "client_side_request.cci"
#endif
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 << ")");
// The original author of the code also wanted to pass an errno to
// setReplyToError, but it seems unlikely that the errno reflects the
// true cause of the error at this point, so I did not pass it.
- IpAddress noAddr;
+ Ip::Address noAddr;
noAddr.SetNoAddr();
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);
}