#include "CommCalls.h"
#include "HttpControlMsg.h"
+void
+HttpControlMsgSink::wroteControlMsgOK()
+{
+ if (cbControlMsgSent) {
+ ScheduleCallHere(cbControlMsgSent);
+ cbControlMsgSent = nullptr;
+ }
+}
+
/// called when we wrote the 1xx response
void
HttpControlMsgSink::wroteControlMsg(const CommIoCbParams ¶ms)
return;
if (params.flag == Comm::OK) {
- if (cbControlMsgSent)
- ScheduleCallHere(cbControlMsgSent);
+ wroteControlMsgOK();
return;
}
/// called to send the 1xx message and notify the Source
virtual void sendControlMsg(HttpControlMsg msg) = 0;
+ virtual void wroteControlMsgOK();
+
/// callback to handle Comm::Write completion
void wroteControlMsg(const CommIoCbParams &);
// TODO: enforces HTTP/1 MUST on pipeline order, but is irrelevant to HTTP/2
if (context != http->getConn()->pipeline.front())
context->deferRecipientForLater(node, rep, receivedData);
+ else if (http->getConn()->cbControlMsgSent) // 1xx to the user is pending
+ context->deferRecipientForLater(node, rep, receivedData);
else
http->getConn()->handleReply(rep, receivedData);
clientConnection->close();
}
+void
+ConnStateData::wroteControlMsgOK()
+{
+ HttpControlMsgSink::wroteControlMsgOK();
+
+ if (Http::StreamPointer deferredRequest = pipeline.front()) {
+ debugs(33, 3, clientConnection << ": calling PushDeferredIfNeeded after control msg wrote");
+ ClientSocketContextPushDeferredIfNeeded(deferredRequest, this);
+ }
+}
+
/// Our close handler called by Comm when the pinned connection is closed
void
ConnStateData::clientPinnedConnectionClosed(const CommCloseCbParams &io)
/* HttpControlMsgSink API */
virtual void sendControlMsg(HttpControlMsg);
+ virtual void wroteControlMsgOK();
/// Traffic parsing
bool clientParseRequests();
void
Http::One::Server::writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call)
{
- const ClientHttpRequest *http = pipeline.front()->http;
+ Http::StreamPointer context = pipeline.front();
+ Must(context != nullptr);
+
+ // Ignore this late control message if we have started sending a
+ // reply to the user already (e.g., after an error).
+ if (context->reply) {
+ debugs(11, 2, "drop 1xx made late by " << context->reply);
+ // but still inform the caller (so it may resume its operation)
+ ScheduleCallHere(call);
+ return;
+ }
+
+ const ClientHttpRequest *http = context->http;
// apply selected clientReplyContext::buildReplyHeader() mods
// it is not clear what headers are required for control messages