/*
- * DEBUG: section 93 ICAP (RFC 3507) Client
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
*/
+/* DEBUG: section 93 ICAP (RFC 3507) Client */
+
#include "squid.h"
-#include "HttpMsg.h"
-#include "adaptation/Initiator.h"
+#include "adaptation/Answer.h"
#include "adaptation/Initiate.h"
+#include "adaptation/Initiator.h"
#include "base/AsyncJobCalls.h"
+#include "http/Message.h"
namespace Adaptation
{
-
-// AdaptInitiator::noteAdaptionAnswer Dialer locks/unlocks the message in transit
-// TODO: replace HTTPMSGLOCK with general RefCounting and delete this class
-class AnswerDialer: public UnaryMemFunT<Initiator, HttpMsg*>
+typedef UnaryMemFunT<Initiator, Answer, const Answer &> AnswerDialer;
+/// Calls expectNoConsumption() if noteAdaptationAnswer async call is
+/// scheduled but never fired (e.g., because the HTTP transaction aborts).
+class AnswerCall: public AsyncCallT<AnswerDialer>
{
public:
- typedef UnaryMemFunT<Initiator, HttpMsg*> Parent;
-
- AnswerDialer(const Parent::JobPointer &job, Parent::Method meth,
- HttpMsg *msg): Parent(job, meth, msg) { HTTPMSGLOCK(arg1); }
- AnswerDialer(const AnswerDialer &d): Parent(d) { HTTPMSGLOCK(arg1); }
- virtual ~AnswerDialer() { HTTPMSGUNLOCK(arg1); }
+ AnswerCall(const char *aName, const AnswerDialer &aDialer) :
+ AsyncCallT<AnswerDialer>(93, 5, aName, aDialer), fired(false) {}
+ virtual void fire() {
+ fired = true;
+ AsyncCallT<AnswerDialer>::fire();
+ }
+ virtual ~AnswerCall() {
+ if (!fired && dialer.arg1.message != NULL && dialer.arg1.message->body_pipe != NULL)
+ dialer.arg1.message->body_pipe->expectNoConsumption();
+ }
private:
- AnswerDialer &operator =(const AnswerDialer &); // not implemented
+ bool fired; ///< whether we fired the call
};
-
-} // namespace Adaptation
-
-
-/* Initiate */
+}
Adaptation::Initiate::Initiate(const char *aTypeName): AsyncJob(aTypeName)
{
theInitiator = i;
}
-
// internal cleanup
void Adaptation::Initiate::swanSong()
{
theInitiator.clear();
}
-void Adaptation::Initiate::sendAnswer(HttpMsg *msg)
+void Adaptation::Initiate::sendAnswer(const Answer &answer)
{
- assert(msg);
- CallJob(93, 5, __FILE__, __LINE__, "Initiator::noteAdaptationAnswer",
- AnswerDialer(theInitiator, &Initiator::noteAdaptationAnswer, msg));
+ AsyncCall::Pointer call = new AnswerCall("Initiator::noteAdaptationAnswer",
+ AnswerDialer(theInitiator, &Initiator::noteAdaptationAnswer, answer));
+ ScheduleCallHere(call);
clearInitiator();
}
-
void Adaptation::Initiate::tellQueryAborted(bool final)
{
- CallJobHere1(93, 5, theInitiator,
- Initiator, noteAdaptationQueryAbort, final);
- clearInitiator();
+ sendAnswer(Answer::Error(final));
}
const char *Adaptation::Initiate::status() const
{
return AsyncJob::status(); // for now
}
+