]> git.ipfire.org Git - thirdparty/squid.git/blob - src/mgr/Forwarder.cc
5ede4f7cdca17a966e37f57df70bfe898343b60d
[thirdparty/squid.git] / src / mgr / Forwarder.cc
1 /*
2 * $Id$
3 *
4 * DEBUG: section 16 Cache Manager API
5 *
6 */
7
8 #include "squid.h"
9 #include "base/AsyncJobCalls.h"
10 #include "base/TextException.h"
11 #include "CommCalls.h"
12 #include "comm/Connection.h"
13 #include "errorpage.h"
14 #include "globals.h"
15 #include "HttpReply.h"
16 #include "HttpRequest.h"
17 #include "ipc/Port.h"
18 #include "mgr/Forwarder.h"
19 #include "mgr/Request.h"
20 #include "SquidTime.h"
21 #include "Store.h"
22
23 CBDATA_NAMESPACED_CLASS_INIT(Mgr, Forwarder);
24
25 Mgr::Forwarder::Forwarder(const Comm::ConnectionPointer &aConn, const ActionParams &aParams,
26 HttpRequest* aRequest, StoreEntry* anEntry):
27 Ipc::Forwarder(new Request(KidIdentifier, 0, aConn, aParams), 10),
28 httpRequest(aRequest), entry(anEntry), conn(aConn)
29 {
30 debugs(16, 5, HERE << conn);
31 Must(Comm::IsConnOpen(conn));
32 Must(httpRequest != NULL);
33 Must(entry != NULL);
34
35 HTTPMSGLOCK(httpRequest);
36 entry->lock();
37 EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT);
38
39 closer = asyncCall(16, 5, "Mgr::Forwarder::noteCommClosed",
40 CommCbMemFunT<Forwarder, CommCloseCbParams>(this, &Forwarder::noteCommClosed));
41 comm_add_close_handler(conn->fd, closer);
42 }
43
44 Mgr::Forwarder::~Forwarder()
45 {
46 debugs(16, 5, HERE);
47 Must(httpRequest != NULL);
48 Must(entry != NULL);
49
50 HTTPMSGUNLOCK(httpRequest);
51 entry->unregisterAbort();
52 entry->unlock();
53 cleanup();
54 }
55
56 /// closes our copy of the client HTTP connection socket
57 void
58 Mgr::Forwarder::cleanup()
59 {
60 if (Comm::IsConnOpen(conn)) {
61 if (closer != NULL) {
62 comm_remove_close_handler(conn->fd, closer);
63 closer = NULL;
64 }
65 conn->close();
66 }
67 conn = NULL;
68 }
69
70 void
71 Mgr::Forwarder::handleError()
72 {
73 debugs(16, DBG_CRITICAL, "ERROR: uri " << entry->url() << " exceeds buffer size");
74 sendError(new ErrorState(ERR_INVALID_URL, HTTP_REQUEST_URI_TOO_LARGE, httpRequest));
75 mustStop("long URI");
76 }
77
78 void
79 Mgr::Forwarder::handleTimeout()
80 {
81 sendError(new ErrorState(ERR_LIFETIME_EXP, HTTP_REQUEST_TIMEOUT, httpRequest));
82 Ipc::Forwarder::handleTimeout();
83 }
84
85 void
86 Mgr::Forwarder::handleException(const std::exception& e)
87 {
88 if (entry != NULL && httpRequest != NULL && Comm::IsConnOpen(conn))
89 sendError(new ErrorState(ERR_INVALID_RESP, HTTP_INTERNAL_SERVER_ERROR, httpRequest));
90 Ipc::Forwarder::handleException(e);
91 }
92
93 /// called when the client socket gets closed by some external force
94 void
95 Mgr::Forwarder::noteCommClosed(const CommCloseCbParams& params)
96 {
97 debugs(16, 5, HERE);
98 conn = NULL; // needed?
99 mustStop("commClosed");
100 }
101
102 /// called when Coordinator starts processing the request
103 void
104 Mgr::Forwarder::handleRemoteAck()
105 {
106 Ipc::Forwarder::handleRemoteAck();
107
108 Must(entry != NULL);
109 EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
110 entry->complete();
111 }
112
113 /// send error page
114 void
115 Mgr::Forwarder::sendError(ErrorState *error)
116 {
117 debugs(16, 3, HERE);
118 Must(error != NULL);
119 Must(entry != NULL);
120 Must(httpRequest != NULL);
121
122 EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
123 entry->buffer();
124 entry->replaceHttpReply(error->BuildHttpReply());
125 entry->expires = squid_curtime;
126 delete error;
127 entry->flush();
128 entry->complete();
129 }