[squid-dev] [PATCH] Fetch missing certificates
Christos Tsantilas
christos at chtsanti.net
Wed Jul 13 16:48:27 UTC 2016
On 07/11/2016 10:13 PM, Alex Rousskov wrote:
> On 07/11/2016 10:18 AM, Christos Tsantilas wrote:
>
>> + /// The maximum allowed object size.
>> + static const size_t MaxObjectSize = 1*1024*1024;
>
>
>> + bool existingContent = reply ? reply->content_length : 0;
>> + bool exceedSize = (existingContent > -1 && (size_t)existingContent > MaxObjectSize) ||
>> + ((object.length() + receivedData.length) > MaxObjectSize);
>
> Wrong type for existingContent. Please use appropriate C++ type casts.
>
> Please refactor to also account for SBuf::maxSize, even if the current
> MaxObjectSize is much smaller.
Stupid bug. I am expecting c++ error in such cases but...
>
> If you can make them const, make them const.
>
> Also, please s/exceedSize/tooLarge/ or s/excessiveSize/.
OK on these. I hope they are ok now.
>
>
>> + status = Http::scInternalServerError;
>> + callBack();
>
>> + status = Http::scOkay;
>> + callBack();
>
>> + status = Http::scInternalServerError;
>> + callBack();
>
>> + status = Http::scInternalServerError;
>> + callBack();
>
> Please make status a callBack() parameter instead of a Downloader data
> member.
ok.
>
>
>> + /// Callback data to use with Downloader callbacks.
>> + class CbDialer {
>> + public:
>> + CbDialer(): status(Http::scNone) {}
>> + virtual ~CbDialer() {}
>> + SBuf object;
>> + Http::StatusCode status;
>> + };
>
> If you can make Downloader::CbDialer print the status parameter and
> perhaps, for successful downloads, the beginning of object parameter
> (via Raw), please do so. See CallDialer::print().
I did not change anything here.
The PeerConnectorCertDownloaderDialer which is Downloader::CbDialer and
CallDialer kid implements the print method.
If you prefer we can make the Downloader::CbDialer a CallDialer kid and
implement the print method.
>
>
>> + debugs(33, 5, HERE);
>
>> + debugs(33 , 2, HERE);
>
>> + debugs(33, 6, HERE);
>
> s/HERE/this/
Well, I use your suggestion for destructors and Amos for functions.
For Downloader probably the AsyncJob::id should used, or print nothing,
the AsyncJob destructor prints a message in destructor.
Anyway.
>
>
>> + ClientHttpRequest *const http = new ClientHttpRequest(NULL);
>
> s/NULL/nullptr/ in new code
ok
>
>
> The scope of the following few comments overlap. They should be
> considered together.
>
>> +/// Used to hold and pass the required info and buffers to the
>> +/// clientStream callbacks
>> +class DownloaderContext: public RefCountable
>
> Why do we need a dedicated class with complex lifetime controls [instead
> of using Downloader itself] for this? I am not saying this is wrong yet,
> just asking why it is needed...
Two reasons:
1) The existing related code for client_side and esi uses a context
class, and I just follow the same scheme.
2) The clientStream code requires a RefCountable class.
Because Downloader is an AsyncJob cbdata class and used as cbdata class
I did not feel safe to use it with clientStream code.
The DownloaderContext class is build for clientStream and destroyed by
clientStream code after finished. I think it is better to keep this class.
>
>
>> +class DownloaderContext: public RefCountable
>> +{
>> + CBDATA_CLASS(DownloaderContext);
>
> The combination of cbdata and RefCountable can be deadly as both
> interfaces compete for object lifetime control without knowing about
> each other. IIRC, a few of these ticking time bombs remain in Squid code
> today, but here we are adding new code so, unless existing API require
> this, we should avoid this combination.
>
> I assume that ClientStreams require cbdata; is RefCountable required by
> some other existing API?
No requires RefCoutanble. I added cbdata definitions just for memory
pools and because I was influenced by the similar code in client_side
and esi code.
There is not any need for cbdata for this class. I replaced with
MEMPROXY_CLASS
>
>
>> +DownloaderContext::~DownloaderContext()
>> +{
> ...
>> + if (http)
>> + finished();
>> +}
>> +
>> +void
>> +DownloaderContext::finished()
>> +{
>> + delete http;
>> + http = NULL;
>> +}
>
>> +void
>> +Downloader::downloadFinished()
>> +{
>> + debugs(33, 7, this);
>> + context_->finished();
>
> If we do not need to delete "http" right when downloadFinished() is
> called, then please merge finished() into the DownloaderContext
We need to delete http here.
Unfortunately holds (inderectly) depedencies to context_ object.
The ClientHttpRequest destructor will cause the clientStream objects to
be released, and also release clientStream refcount to context_ object.
(Yes confusing and difficult to follow. Maybe a subject for a "routing
parent for ConnStateData/Esi/Downloader classes" project?)
> destructor. Otherwise, perhaps add a source comment to document that we
> cannot delay http destruction until refcounting deletes DownloaderContext.
I add a comment which try to describe the problem.
>
>
>> + // 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 a fake call here just to force squid to delete this object.
>> + CallJobHere(33, 7, CbcPointer<Downloader>(this), Downloader, downloadFinished);
>
> Does a single async call guarantee that doCallouts() will be able to
> handle our destruction? What if doCallouts() schedules an async call as
> well and comes back after our destruction? Is this a problem our patch
> introduces or an existing/old doCallouts() flaw that we simply need to
> work around, just like some other doCallouts() users?
It is not a problem added by this patch.
It is the doCallouts design. For a reason does not affect other
subsystems. Probably it is hiden because of tricks like this I did.
This asyncCall will delay ClientHttpRequest destruction after the
doCallouts will be finished. Else the ClientHttpRequest object will be
destroyed while the doCallouts runs.
If doCallouts schedule a new callback this is normally checks if the
ClientHttpRequest object is still not NULL.
>
>
>> + Downloader* downloader;
>
>> + if (!cbdataReferenceValid(context->downloader))
>> + return;
>
> The check only makes sense if context->downloader is a CbcPointer or
> equivalent, not a raw pointer. Otherwise, to reliably test downloader
> validity you need the downloader pointer to be valid (i.e., either it
> always works and the check is not needed or it may crash and the check
> is broken).
I can not see the mistake here.
The cotnext->downloader is set as cbdataReference of cbdata. The pointer
is always valid but the object maybe is not valid.
I replaced with CbcPointer<Downloader>
>
>
>> + /// Fake call used internally by Downloader.
>> + void downloadFinished();
>
> This method/call is as real as any other call. We are forced to call it
> asynchronously because of doCallouts() limitations, but it is not fake.
> I suggest documenting it as "delays destruction to protect doCallouts()"
> or something like that.
ok
>
>
>> + // Schedule a fake call here just to force squid to delete this object.
>
> Similarly, s/a fake/an async/
ok
>
>
>> + debugs(33, 4, "Received " << receivedData.length <<
>> + " object data, offset: " << receivedData.offset <<
>> + " error flag:" << receivedData.flags.error);
>
> Please move this debugging up, before we may exit the method.
ok
>
> Also, should not we check receivedData.flags.error _before_ we interpret
> any receivedData.length and such?
Well. My sense is that for a reason nobody checks for this flag.
I add a check for failed reply, we may add some other related checks
here in the future.
For now looks enough.
>
>
>> + bool exceedSize = (existingContent > -1 && (size_t)existingContent > MaxObjectSize) ||
>> + ((object.length() + receivedData.length) > MaxObjectSize);
>
> ...
>
>> + if (receivedData.length > 0) {
>> + object.append(receivedData.data, receivedData.length);
>> + http->out.size += receivedData.length;
>> + http->out.offset += receivedData.length;
>> + }
>
> The combination does not make sense as far as non-positive
> receivedData.length is concerned:
>
> * If receivedData.length cannot be negative, then the if-statement is
> not needed.
> * If receivedData.length can be negative, then it cannot be used in
> exceedSize calculations without protection.
It can be zero.
I replaced "if (recevedData.length >0)" with a "if (receivedData.length)"
>
>
> Thank you,
>
> Alex.
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SQUID-112-fetch-certificates-t3.patch
Type: text/x-patch
Size: 74954 bytes
Desc: not available
URL: <http://lists.squid-cache.org/pipermail/squid-dev/attachments/20160713/f611aeda/attachment-0001.bin>
More information about the squid-dev
mailing list