/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
#include "squid.h"
#include "client_side.h"
-#include "client_side_request.h"
#include "client_side_reply.h"
+#include "client_side_request.h"
#include "ClientRequestContext.h"
#include "Downloader.h"
+#include "fatal.h"
#include "http/one/RequestParser.h"
#include "http/Stream.h"
http = nullptr;
}
-Downloader::Downloader(SBuf &url, AsyncCall::Pointer &aCallback, unsigned int level):
+void
+Downloader::CbDialer::print(std::ostream &os) const
+{
+ os << " Http Status:" << status << Raw("body data", object.rawContent(), 64).hex();
+}
+
+Downloader::Downloader(SBuf &url, AsyncCall::Pointer &aCallback, const XactionInitiator initiator, unsigned int level):
AsyncJob("Downloader"),
url_(url),
callback_(aCallback),
- level_(level)
+ level_(level),
+ initiator_(initiator)
{
}
Downloader::~Downloader()
{
+ debugs(33, 6, this);
+}
+
+void
+Downloader::swanSong()
+{
+ debugs(33, 6, this);
+ if (context_) {
+ context_->finished();
+ context_ = nullptr;
+ }
}
bool
HttpReply * rep, StoreIOBuffer receivedData)
{
debugs(33, 6, MYNAME);
- /* Test preconditions */
+ /* Test preconditions */
assert(node);
/* TODO: handle this rather than asserting
/// Initializes and starts the HTTP GET request to the remote server
bool
Downloader::buildRequest()
-{
+{
const HttpRequestMethod method = Http::METHOD_GET;
- char *uri = xstrdup(url_.c_str());
- HttpRequest *const request = HttpRequest::CreateFromUrl(uri, method);
+ const MasterXaction::Pointer mx = new MasterXaction(initiator_);
+ auto * const request = HttpRequest::FromUrl(url_, mx, method);
if (!request) {
debugs(33, 5, "Invalid URI: " << url_);
- xfree(uri);
return false; //earlyError(...)
}
request->http_ver = Http::ProtocolVersion();
request->header.putStr(Http::HdrType::HOST, request->url.host());
request->header.putTime(Http::HdrType::DATE, squid_curtime);
- request->flags.internalClient = true;
request->client_addr.setNoAddr();
#if FOLLOW_X_FORWARDED_FOR
request->indirect_client_addr.setNoAddr();
"\n----------");
ClientHttpRequest *const http = new ClientHttpRequest(nullptr);
- http->request = request;
- HTTPMSGLOCK(http->request);
+ http->initRequest(request);
http->req_sz = 0;
- http->uri = uri;
- setLogUri (http, urlCanonicalClean(request));
+ // XXX: performance regression. c_str() reallocates
+ http->uri = xstrdup(url_.c_str());
context_ = new DownloaderContext(this, http);
StoreIOBuffer tempBuffer;
return;
}
- if (receivedData.length) {
- object_.append(receivedData.data, receivedData.length);
- http->out.size += receivedData.length;
- http->out.offset += receivedData.length;
- }
+ object_.append(receivedData.data, receivedData.length);
+ http->out.size += receivedData.length;
+ http->out.offset += receivedData.length;
switch (clientStreamStatus(node, http)) {
case STREAM_NONE: {
tempBuffer.length = HTTP_REQBUF_SZ;
clientStreamRead(node, http, tempBuffer);
}
- break;
+ break;
case STREAM_COMPLETE:
debugs(33, 3, "Object data transfer successfully complete");
callBack(Http::scOkay);
Downloader::downloadFinished()
{
debugs(33, 7, this);
- // We cannot delay http destruction until refcounting deletes
- // DownloaderContext. The http object destruction will cause
- // clientStream cleanup and will release the refcount to context_
- // object hold by clientStream structures.
- context_->finished();
- context_ = nullptr;
Must(done());
}
void
Downloader::callBack(Http::StatusCode const statusCode)
{
- CbDialer *dialer = dynamic_cast<CbDialer*>(callback_->getDialer());
- Must(dialer);
- dialer->status = statusCode;
- if (statusCode == Http::scOkay)
- dialer->object = object_;
- ScheduleCallHere(callback_);
- callback_ = nullptr;
-
- // Calling deleteThis method here to finish Downloader
- // may result to squid crash.
- // This method called by handleReply method which maybe called
- // by ClientHttpRequest::doCallouts. The doCallouts after this object
- // deleted, may operate on non valid objects.
- // Schedule an async call here just to force squid to delete this object.
- CallJobHere(33, 7, CbcPointer<Downloader>(this), Downloader, downloadFinished);
+ CbDialer *dialer = dynamic_cast<CbDialer*>(callback_->getDialer());
+ Must(dialer);
+ dialer->status = statusCode;
+ if (statusCode == Http::scOkay)
+ dialer->object = object_;
+ ScheduleCallHere(callback_);
+ callback_ = nullptr;
+
+ // We cannot deleteThis() because we may be called synchronously from
+ // doCallouts() via handleReply() (XXX), and doCallouts() may crash if we
+ // disappear. Instead, schedule an async call now so that later, when the
+ // call firing code discovers a done() job, it deletes us.
+ CallJobHere(33, 7, CbcPointer<Downloader>(this), Downloader, downloadFinished);
}