]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ipc/Forwarder.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / ipc / Forwarder.cc
CommitLineData
51ea0904 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
51ea0904 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
51ea0904
CT
7 */
8
bbc27441
AJ
9/* DEBUG: section 54 Interprocess Communication */
10
f7f3304a 11#include "squid.h"
51ea0904
CT
12#include "base/AsyncJobCalls.h"
13#include "base/TextException.h"
1b76e6c1
AJ
14#include "errorpage.h"
15#include "HttpReply.h"
16#include "HttpRequest.h"
51ea0904
CT
17#include "ipc/Forwarder.h"
18#include "ipc/Port.h"
4c218615 19#include "ipc/RequestId.h"
51ea0904
CT
20#include "ipc/TypedMsgHdr.h"
21
51ea0904
CT
22CBDATA_NAMESPACED_CLASS_INIT(Ipc, Forwarder);
23
24Ipc::Forwarder::RequestsMap Ipc::Forwarder::TheRequestsMap;
4c218615 25Ipc::RequestId::Index Ipc::Forwarder::LastRequestId = 0;
51ea0904
CT
26
27Ipc::Forwarder::Forwarder(Request::Pointer aRequest, double aTimeout):
f53969cc 28 AsyncJob("Ipc::Forwarder"),
87388f15 29 codeContext(CodeContext::Current()),
f53969cc 30 request(aRequest), timeout(aTimeout)
51ea0904 31{
51ea0904
CT
32}
33
34Ipc::Forwarder::~Forwarder()
35{
ebaabe74
AR
36 SWALLOW_EXCEPTIONS({
37 Must(request->requestId == 0);
38 });
51ea0904
CT
39}
40
41void
42Ipc::Forwarder::start()
43{
44 debugs(54, 3, HERE);
45
46 typedef NullaryMemFunT<Forwarder> Dialer;
933a6aed 47 AsyncCall::Pointer callback = JobCallback(54, 5, Dialer, this, Forwarder::handleRemoteAck);
51ea0904
CT
48 if (++LastRequestId == 0) // don't use zero value as request->requestId
49 ++LastRequestId;
50 request->requestId = LastRequestId;
51 TheRequestsMap[request->requestId] = callback;
52 TypedMsgHdr message;
53
54 try {
55 request->pack(message);
56 } catch (...) {
57 // assume the pack() call failed because the message did not fit
58 // TODO: add a more specific exception?
59 handleError();
a7ba2ec1 60 return;
51ea0904
CT
61 }
62
1ee292b7 63 SendMessage(Ipc::Port::CoordinatorAddr(), message);
51ea0904
CT
64 eventAdd("Ipc::Forwarder::requestTimedOut", &Forwarder::RequestTimedOut,
65 this, timeout, 0, false);
66}
67
68void
69Ipc::Forwarder::swanSong()
70{
71 debugs(54, 5, HERE);
72 removeTimeoutEvent();
73 if (request->requestId > 0) {
74 DequeueRequest(request->requestId);
75 request->requestId = 0;
76 }
51ea0904
CT
77}
78
79bool
80Ipc::Forwarder::doneAll() const
81{
82 debugs(54, 5, HERE);
83 return request->requestId == 0;
84}
85
86/// called when Coordinator starts processing the request
87void
88Ipc::Forwarder::handleRemoteAck()
89{
90 debugs(54, 3, HERE);
91 request->requestId = 0;
70eb3fde
EB
92 // Do not do entry->complete() because it will trigger our client side
93 // processing when we no longer own the client-Squid connection.
94 // Let job cleanup close the client-Squid connection that Coordinator
95 // now owns.
51ea0904
CT
96}
97
98/// Ipc::Forwarder::requestTimedOut wrapper
99void
100Ipc::Forwarder::RequestTimedOut(void* param)
101{
102 debugs(54, 3, HERE);
103 Must(param != NULL);
104 Forwarder* fwdr = static_cast<Forwarder*>(param);
105 // use async call to enable job call protection that time events lack
87388f15
EB
106
107 CallBack(fwdr->codeContext, [&fwdr] {
108 CallJobHere(54, 5, fwdr, Forwarder, requestTimedOut);
109 });
51ea0904
CT
110}
111
112/// called when Coordinator fails to start processing the request [in time]
113void
114Ipc::Forwarder::requestTimedOut()
115{
116 debugs(54, 3, HERE);
117 handleTimeout();
118}
119
120void
121Ipc::Forwarder::handleError()
122{
123 mustStop("error");
124}
125
126void
127Ipc::Forwarder::handleTimeout()
128{
129 mustStop("timeout");
130}
131
132/// terminate with an error
133void
134Ipc::Forwarder::handleException(const std::exception& e)
135{
933a6aed 136 debugs(54, 3, HERE << e.what());
51ea0904
CT
137 mustStop("exception");
138}
139
140void
141Ipc::Forwarder::callException(const std::exception& e)
142{
143 try {
144 handleException(e);
145 } catch (const std::exception& ex) {
146 debugs(54, DBG_CRITICAL, HERE << ex.what());
147 }
148 AsyncJob::callException(e);
149}
150
151/// returns and forgets the right Forwarder callback for the request
152AsyncCall::Pointer
4c218615 153Ipc::Forwarder::DequeueRequest(const RequestId::Index requestId)
51ea0904
CT
154{
155 debugs(54, 3, HERE);
156 Must(requestId != 0);
157 AsyncCall::Pointer call;
158 RequestsMap::iterator request = TheRequestsMap.find(requestId);
159 if (request != TheRequestsMap.end()) {
160 call = request->second;
161 Must(call != NULL);
162 TheRequestsMap.erase(request);
163 }
164 return call;
165}
166
167/// called when we are no longer waiting for Coordinator to respond
168void
169Ipc::Forwarder::removeTimeoutEvent()
170{
171 if (eventFind(&Forwarder::RequestTimedOut, this))
172 eventDelete(&Forwarder::RequestTimedOut, this);
173}
174
175void
4c218615 176Ipc::Forwarder::HandleRemoteAck(const RequestId requestId)
51ea0904
CT
177{
178 debugs(54, 3, HERE);
179 Must(requestId != 0);
180
181 AsyncCall::Pointer call = DequeueRequest(requestId);
182 if (call != NULL)
183 ScheduleCallHere(call);
184}
f53969cc 185