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