/* Local functions */
/* ClientSocketContext */
-static ClientSocketContext *ClientSocketContextNew(ClientHttpRequest *);
+static ClientSocketContext *ClientSocketContextNew(const Comm::ConnectionPointer &clientConn, ClientHttpRequest *);
/* other */
static IOCB clientWriteComplete;
static IOCB clientWriteBodyComplete;
char *skipLeadingSpace(char *aString);
static void connNoteUseOfBuffer(ConnStateData* conn, size_t byteCount);
-static ConnStateData *connStateCreate(const Comm::ConnectionPointer &details, http_port_list *port);
+static ConnStateData *connStateCreate(const Comm::ConnectionPointer &client, http_port_list *port);
const Comm::ConnectionPointer &
ClientSocketContext::clientConn() const
{
- assert (http);
- assert (http->getConn() != NULL);
- assert (http->getConn()->clientConn != NULL);
- return http->getConn()->clientConn;
+ assert (clientConnection != NULL);
+ return clientConnection;
}
clientStreamNode *
}
ClientSocketContext *
-ClientSocketContextNew(ClientHttpRequest * http)
+ClientSocketContextNew(const Comm::ConnectionPointer &client, ClientHttpRequest * http)
{
ClientSocketContext *newContext;
assert(http != NULL);
newContext = new ClientSocketContext;
newContext->http = http;
+ newContext->clientConnection = client;
return newContext;
}
accessLogLog(&al, checklist);
updateCounters();
- if (getConn() != NULL)
- clientdbUpdate(getConn()->peer, logType, PROTO_HTTP, out.size);
+ if (getConn() != NULL && getConn()->clientConn != NULL)
+ clientdbUpdate(getConn()->clientConn->remote, logType, PROTO_HTTP, out.size);
}
delete checklist;
void
ConnStateData::swanSong()
{
- debugs(33, 2, "ConnStateData::swanSong: FD " << (clientConn!=NULL?clientConn->fd:-1));
+ debugs(33, 2, HERE << clientConn);
clientConn = NULL;
flags.readMoreRequests = false;
- clientdbEstablished(peer, -1); /* decrement */
+ clientdbEstablished(clientConn->remote, -1); /* decrement */
assert(areAllContextsForThisConnection());
freeAllContexts();
extern "C" CSD clientReplyDetach;
static ClientSocketContext *
-parseHttpRequestAbort(ConnStateData * conn, const char *uri)
+parseHttpRequestAbort(ConnStateData * csd, const char *uri)
{
ClientHttpRequest *http;
ClientSocketContext *context;
StoreIOBuffer tempBuffer;
- http = new ClientHttpRequest(conn);
- http->req_sz = conn->in.notYetUsed;
+ http = new ClientHttpRequest(csd);
+ http->req_sz = csd->in.notYetUsed;
http->uri = xstrdup(uri);
setLogUri (http, uri);
- context = ClientSocketContextNew(http);
+ context = ClientSocketContextNew(csd->clientConn, http);
tempBuffer.data = context->reqbuf;
tempBuffer.length = HTTP_REQBUF_SZ;
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
http->uri = (char *)xcalloc(url_sz, 1);
snprintf(http->uri, url_sz, "%s://%s:%d%s",
http->getConn()->port->protocol,
- http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN),
- http->getConn()->me.GetPort(), url);
+ http->getConn()->clientConn->local.NtoA(ntoabuf,MAX_IPSTRLEN),
+ http->getConn()->clientConn->local.GetPort(), url);
debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'");
} else if (vport > 0) {
/* Put the local socket IP address as the hostname, but static port */
http->uri = (char *)xcalloc(url_sz, 1);
snprintf(http->uri, url_sz, "%s://%s:%d%s",
http->getConn()->port->protocol,
- http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN),
+ http->getConn()->clientConn->local.NtoA(ntoabuf,MAX_IPSTRLEN),
vport, url);
debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'");
}
http->uri = (char *)xcalloc(url_sz, 1);
snprintf(http->uri, url_sz, "%s://%s:%d%s",
http->getConn()->port->protocol,
- http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN),
- http->getConn()->me.GetPort(), url);
+ http->getConn()->clientConn->local.NtoA(ntoabuf,MAX_IPSTRLEN),
+ http->getConn()->clientConn->local.GetPort(), url);
debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'");
}
}
* Sets result->flags.parsed_ok to 1 if we have a good request.
*/
static ClientSocketContext *
-parseHttpRequest(ConnStateData *conn, HttpParser *hp, HttpRequestMethod * method_p, HttpVersion *http_ver)
+parseHttpRequest(ConnStateData *csd, HttpParser *hp, HttpRequestMethod * method_p, HttpVersion *http_ver)
{
char *req_hdr = NULL;
char *end;
} else if ( (size_t)hp->bufsiz >= Config.maxRequestHeaderSize && headersEnd(hp->buf, Config.maxRequestHeaderSize) == 0) {
debugs(33, 5, "parseHttpRequest: Too large request");
hp->request_parse_status = HTTP_HEADER_TOO_LARGE;
- return parseHttpRequestAbort(conn, "error:request-too-large");
+ return parseHttpRequestAbort(csd, "error:request-too-large");
}
/* Attempt to parse the first line; this'll define the method, url, version and header begin */
}
if (r == -1) {
- return parseHttpRequestAbort(conn, "error:invalid-request");
+ return parseHttpRequestAbort(csd, "error:invalid-request");
}
/* Request line is valid here .. */
if (req_sz >= Config.maxRequestHeaderSize) {
debugs(33, 5, "parseHttpRequest: Too large request");
hp->request_parse_status = HTTP_HEADER_TOO_LARGE;
- return parseHttpRequestAbort(conn, "error:request-too-large");
+ return parseHttpRequestAbort(csd, "error:request-too-large");
}
/* Set method_p */
*method_p = HttpRequestMethod(&hp->buf[hp->m_start], &hp->buf[hp->m_end]+1);
/* deny CONNECT via accelerated ports */
- if (*method_p == METHOD_CONNECT && conn && conn->port && conn->port->accel) {
- debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << conn->port->protocol << " Accelerator port " << conn->port->s.GetPort() );
+ if (*method_p == METHOD_CONNECT && csd && csd->port && csd->port->accel) {
+ debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << csd->port->protocol << " Accelerator port " << csd->port->s.GetPort() );
/* XXX need a way to say "this many character length string" */
debugs(33, DBG_IMPORTANT, "WARNING: for request: " << hp->buf);
hp->request_parse_status = HTTP_METHOD_NOT_ALLOWED;
- return parseHttpRequestAbort(conn, "error:method-not-allowed");
+ return parseHttpRequestAbort(csd, "error:method-not-allowed");
}
if (*method_p == METHOD_NONE) {
/* XXX need a way to say "this many character length string" */
debugs(33, 1, "clientParseRequestMethod: Unsupported method in request '" << hp->buf << "'");
hp->request_parse_status = HTTP_METHOD_NOT_ALLOWED;
- return parseHttpRequestAbort(conn, "error:unsupported-request-method");
+ return parseHttpRequestAbort(csd, "error:unsupported-request-method");
}
/*
HttpParserReqSz(hp));
/* Ok, all headers are received */
- http = new ClientHttpRequest(conn);
+ http = new ClientHttpRequest(csd);
http->req_sz = HttpParserRequestLen(hp);
- result = ClientSocketContextNew(http);
+ result = ClientSocketContextNew(csd->clientConn, http);
tempBuffer.data = result->reqbuf;
tempBuffer.length = HTTP_REQBUF_SZ;
* - internal URL
* - mixed combos of the above with internal URL
*/
- if (conn->transparent()) {
+ if (csd->transparent()) {
/* intercept or transparent mode, properly working with no failures */
- http->flags.intercepted = conn->port->intercepted;
- http->flags.spoof_client_ip = conn->port->spoof_client_ip;
- prepareTransparentURL(conn, http, url, req_hdr);
+ http->flags.intercepted = csd->port->intercepted;
+ http->flags.spoof_client_ip = csd->port->spoof_client_ip;
+ prepareTransparentURL(csd, http, url, req_hdr);
- } else if (conn->port->intercepted || conn->port->spoof_client_ip) {
+ } else if (csd->port->intercepted || csd->port->spoof_client_ip) {
/* transparent or intercept mode with failures */
- prepareTransparentURL(conn, http, url, req_hdr);
+ prepareTransparentURL(csd, http, url, req_hdr);
- } else if (conn->port->accel || conn->switchedToHttps()) {
+ } else if (csd->port->accel || csd->switchedToHttps()) {
/* accelerator mode */
- prepareAcceleratedURL(conn, http, url, req_hdr);
+ prepareAcceleratedURL(csd, http, url, req_hdr);
} else if (internalCheck(url)) {
/* internal URL mode */
assert (repContext);
repContext->setReplyToError(ERR_TOO_BIG,
HTTP_BAD_REQUEST, METHOD_NONE, NULL,
- peer, NULL, NULL, NULL);
+ clientConn->remote, NULL, NULL, NULL);
context->registerWithConn();
context->pullData();
}
assert (repContext);
switch (hp->request_parse_status) {
case HTTP_HEADER_TOO_LARGE:
- repContext->setReplyToError(ERR_TOO_BIG, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, conn->in.buf, NULL);
+ repContext->setReplyToError(ERR_TOO_BIG, HTTP_BAD_REQUEST, method, http->uri, conn->clientConn->remote, NULL, conn->in.buf, NULL);
break;
case HTTP_METHOD_NOT_ALLOWED:
- repContext->setReplyToError(ERR_UNSUP_REQ, HTTP_METHOD_NOT_ALLOWED, method, http->uri, conn->peer, NULL, conn->in.buf, NULL);
+ repContext->setReplyToError(ERR_UNSUP_REQ, HTTP_METHOD_NOT_ALLOWED, method, http->uri,
+ conn->clientConn->remote, NULL, conn->in.buf, NULL);
break;
default:
- repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, conn->in.buf, NULL);
+ repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri,
+ conn->clientConn->remote, NULL, conn->in.buf, NULL);
}
assert(context->http->out.offset == 0);
context->pullData();
debugs(33, 5, "Invalid URL: " << http->uri);
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL);
+ repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->clientConn->remote, NULL, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = false;
debugs(33, 5, "Unsupported HTTP version discovered. :\n" << HttpParserHdrBuf(hp));
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, HTTP_HTTP_VERSION_NOT_SUPPORTED, method, http->uri, conn->peer, NULL, HttpParserHdrBuf(hp), NULL);
+ repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, HTTP_HTTP_VERSION_NOT_SUPPORTED, method, http->uri,
+ conn->clientConn->remote, NULL, HttpParserHdrBuf(hp), NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = false;
debugs(33, 5, "Failed to parse request headers:\n" << HttpParserHdrBuf(hp));
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL);
+ repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->clientConn->remote, NULL, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = false;
request->flags.internal = http->flags.internal;
setLogUri (http, urlCanonicalClean(request));
- request->client_addr = conn->peer;
+ request->client_addr = conn->clientConn->remote; // XXX: remove reuest->client_addr member.
#if USE_SQUID_EUI
request->client_eui48 = conn->peer_eui48;
request->client_eui64 = conn->peer_eui64;
#endif
#if FOLLOW_X_FORWARDED_FOR
- request->indirect_client_addr = conn->peer;
+ request->indirect_client_addr = conn->clientConn->remote;
#endif /* FOLLOW_X_FORWARDED_FOR */
- request->my_addr = conn->me;
+ request->my_addr = conn->clientConn->local;
request->http_ver = http_ver;
if (request->header.chunked()) {
clientStreamNode *node = context->getClientReplyContext();
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_UNSUP_REQ,
- HTTP_NOT_IMPLEMENTED, request->method, NULL,
- conn->peer, request, NULL, NULL);
+ repContext->setReplyToError(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED, request->method, NULL,
+ conn->clientConn->remote, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = false;
assert (repContext);
repContext->setReplyToError(ERR_INVALID_REQ,
HTTP_LENGTH_REQUIRED, request->method, NULL,
- conn->peer, request, NULL, NULL);
+ conn->clientConn->remote, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = false;
clientStreamNode *node = context->getClientReplyContext();
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_INVALID_REQ, HTTP_EXPECTATION_FAILED, request->method, http->uri, conn->peer, request, NULL, NULL);
+ repContext->setReplyToError(ERR_INVALID_REQ, HTTP_EXPECTATION_FAILED, request->method, http->uri,
+ conn->clientConn->remote, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
goto finish;
assert (repContext);
repContext->setReplyToError(ERR_TOO_BIG,
HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL,
- conn->peer, http->request, NULL, NULL);
+ conn->clientConn->remote, http->request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
goto finish;
void
ConnStateData::clientReadRequest(const CommIoCbParams &io)
{
- debugs(33,5,HERE << "clientReadRequest FD " << io.fd << " size " << io.size);
+ debugs(33,5,HERE << io.conn << " size " << io.size);
Must(reading());
reader = NULL;
bool do_next_read = 1; /* the default _is_ to read data! - adrian */
/* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */
if (io.flag == COMM_ERR_CLOSING) {
- debugs(33,5, HERE << " FD " << io.fd << " closing Bailout.");
+ debugs(33,5, HERE << io.conn << " closing Bailout.");
return;
}
assert(Comm::IsConnOpen(clientConn));
- assert(io.fd == clientConn->fd);
+ assert(io.conn == clientConn);
/*
* Don't reset the timeout value here. The timeout value will be
*/
if (connReadWasError(io.flag, io.size, io.xerrno)) {
notifyAllContexts(io.xerrno);
- clientConn->close();
+ io.conn->close();
return;
}
return;
} else if (io.size == 0) {
- debugs(33, 5, "clientReadRequest: FD " << io.fd << " closed?");
+ debugs(33, 5, HERE << io.conn << " closed?");
if (connFinishedWithConn(io.size)) {
clientConn->close();
}
/* It might be half-closed, we can't tell */
- fd_table[io.fd].flags.socket_eof = 1;
+ fd_table[io.conn->fd].flags.socket_eof = 1;
- commMarkHalfClosed(io.fd);
+ commMarkHalfClosed(io.conn->fd);
do_next_read = 0;
- fd_note(io.fd, "half-closed");
+ fd_note(io.conn->fd, "half-closed");
/* There is one more close check at the end, to detect aborted
* (partial) requests. At this point we can't tell if the request
* XXX: This duplicates ClientSocketContext::keepaliveNextRequest
*/
if (getConcurrentRequestCount() == 0 && commIsHalfClosed(io.fd)) {
- debugs(33, 5, "clientReadRequest: FD " << io.fd << ": half-closed connection, no completed request parsed, connection closing.");
+ debugs(33, 5, HERE << io.conn << ": half-closed connection, no completed request parsed, connection closing.");
clientConn->close();
return;
}
}
ConnStateData *
-connStateCreate(const Comm::ConnectionPointer &conn, http_port_list *port)
+connStateCreate(const Comm::ConnectionPointer &client, http_port_list *port)
{
ConnStateData *result = new ConnStateData;
- result->peer = conn->remote;
- result->log_addr = conn->remote;
+ result->clientConn = client;
+ result->log_addr = client->remote;
result->log_addr.ApplyMask(Config.Addrs.client_netmask);
- result->me = conn->local;
- result->clientConn = conn;
result->in.buf = (char *)memAllocBuf(CLIENT_REQ_BUF_SZ, &result->in.allocatedSize);
result->port = cbdataReference(port);
+ // XXX: move the NAT and TPROXY stuff into ConnAcceptor
if (port->intercepted || port->spoof_client_ip) {
- Ip::Address client, dst;
+ Ip::Address cl, dst;
- if (Ip::Interceptor.NatLookup(conn->fd, conn->local, conn->remote, client, dst) == 0) {
- result->me = client;
- result->peer = dst;
+ if (Ip::Interceptor.NatLookup(client->fd, client->local, client->remote, cl, dst) == 0) {
+ result->clientConn->local = cl;
+ result->clientConn->remote = dst;
result->transparent(true);
}
}
(result->transparent() || port->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)) {
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
int i = IP_PMTUDISC_DONT;
- setsockopt(conn->fd, SOL_IP, IP_MTU_DISCOVER, &i, sizeof i);
+ setsockopt(client->fd, SOL_IP, IP_MTU_DISCOVER, &i, sizeof i);
#else
http_port_list *s = (http_port_list *)data;
ConnStateData *connState = NULL;
- if (flag != COMM_OK) {
- debugs(33, 1, "httpAccept: FD " << sock << ": accept failure: " << xstrerr(xerrno));
- return;
- }
+ assert(flag == COMM_OK); // acceptor does not call us for anything bad.
debugs(33, 4, HERE << details << ": accepted");
fd_note(details->fd, "client http connect");
https_port_list *s = (https_port_list *)data;
SSL_CTX *sslContext = s->sslContext;
- if (flag != COMM_OK) {
- errno = xerrno;
- debugs(33, 1, "httpsAccept: FD " << sock << ": accept failure: " << xstrerr(xerrno));
- return;
- }
+ assert(flag != COMM_OK); // Acceptor does not call un unless successful.
SSL *ssl = NULL;
if (!(ssl = httpsCreate(details, sslContext)))