#include "squid.h"
#include "acl/FilledChecklist.h"
+#include "base/CbcPointer.h"
#include "base/Vector.h"
#include "CachePeer.h"
#include "client_side_request.h"
bool noConnections() const;
char *url;
+ CbcPointer<ClientHttpRequest> http;
HttpRequest::Pointer request;
AccessLogEntryPointer al;
Comm::ConnectionList serverDestinations;
TunnelStateData::TunnelStateData() :
url(NULL),
+ http(),
request(NULL),
status_ptr(NULL),
connectRespBuf(NULL),
assert(!tunnelState->waitingForConnectExchange());
*tunnelState->status_ptr = Http::scOkay;
if (cbdataReferenceValid(tunnelState)) {
+
+ // Shovel any payload already pushed into reply buffer by the server response
if (!tunnelState->server.len)
tunnelState->copyRead(tunnelState->server, TunnelStateData::ReadServer);
- else
+ else {
+ debugs(26, DBG_DATA, "Tunnel server PUSH Payload: \n" << Raw("", tunnelState->server.buf, tunnelState->server.len) << "\n----------");
tunnelState->copy(tunnelState->server.len, tunnelState->server, tunnelState->client, TunnelStateData::WriteClientDone);
- tunnelState->copyRead(tunnelState->client, TunnelStateData::ReadClient);
+ }
+
+ // Bug 3371: shovel any payload already pushed into ConnStateData by the client request
+ if (tunnelState->http.valid() && tunnelState->http->getConn() && !tunnelState->http->getConn()->in.notYetUsed) {
+ struct ConnStateData::In *in = &tunnelState->http->getConn()->in;
+ debugs(26, DBG_DATA, "Tunnel client PUSH Payload: \n" << Raw("", in->buf, in->notYetUsed) << "\n----------");
+
+ // We just need to ensure the bytes from ConnStateData are in client.buf already to deliver
+ memcpy(tunnelState->client.buf, in->buf, in->notYetUsed);
+ // NP: readClient() takes care of buffer length accounting.
+ tunnelState->readClient(tunnelState->client.buf, in->notYetUsed, COMM_OK, 0);
+ in->notYetUsed = 0; // ConnStateData buffer accounting after the shuffle.
+ } else
+ tunnelState->copyRead(tunnelState->client, TunnelStateData::ReadClient);
}
}
tunnelState->server.size_ptr = size_ptr;
tunnelState->status_ptr = status_ptr;
tunnelState->client.conn = http->getConn()->clientConnection;
+ tunnelState->http = http;
tunnelState->al = al;
comm_add_close_handler(tunnelState->client.conn->fd,
packerClean(&p);
mb.append("\r\n", 2);
+ debugs(11, 2, "Tunnel Server REQUEST: " << tunnelState->server.conn << ":\n----------\n" <<
+ Raw("tunnelRelayConnectRequest", mb.content(), mb.contentSize()) << "\n----------");
+
if (tunnelState->clientExpectsConnectResponse()) {
// hack: blindly tunnel peer response (to our CONNECT request) to the client as ours.
AsyncCall::Pointer writeCall = commCbCall(5,5, "tunnelConnectedWriteDone",