]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2025 The Squid Software Foundation and contributors | |
3 | * | |
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. | |
7 | */ | |
8 | ||
9 | #ifndef SQUID_SRC_CLIENT_SIDE_REPLY_H | |
10 | #define SQUID_SRC_CLIENT_SIDE_REPLY_H | |
11 | ||
12 | #include "acl/forward.h" | |
13 | #include "client_side_request.h" | |
14 | #include "ip/forward.h" | |
15 | #include "RequestFlags.h" | |
16 | #include "StoreClient.h" | |
17 | ||
18 | class ErrorState; | |
19 | ||
20 | /* XXX make static method */ | |
21 | ||
22 | class clientReplyContext : public RefCountable, public StoreClient | |
23 | { | |
24 | CBDATA_CLASS(clientReplyContext); | |
25 | ||
26 | public: | |
27 | static STCB CacheHit; | |
28 | static STCB HandleIMSReply; | |
29 | static STCB SendMoreData; | |
30 | ||
31 | clientReplyContext(ClientHttpRequest *); | |
32 | ~clientReplyContext() override; | |
33 | ||
34 | void saveState(); | |
35 | void restoreState(); | |
36 | void purgeRequest (); | |
37 | void doGetMoreData(); | |
38 | void identifyStoreObject(); | |
39 | void identifyFoundObject(StoreEntry *entry, const char *detail); | |
40 | int storeOKTransferDone() const; | |
41 | int storeNotOKTransferDone() const; | |
42 | /// replaces current response store entry with the given one | |
43 | void setReplyToStoreEntry(StoreEntry *e, const char *reason); | |
44 | /// builds error using clientBuildError() and calls setReplyToError() below | |
45 | void setReplyToError(err_type, Http::StatusCode, char const *, const ConnStateData *, HttpRequest *, const char *, | |
46 | #if USE_AUTH | |
47 | Auth::UserRequest::Pointer); | |
48 | #else | |
49 | void * unused); | |
50 | #endif | |
51 | /// creates a store entry for the reply and appends err to it | |
52 | void setReplyToError(const HttpRequestMethod& method, ErrorState *err); | |
53 | /// creates a store entry for the reply and appends error reply to it | |
54 | void setReplyToReply(HttpReply *reply); | |
55 | void createStoreEntry(const HttpRequestMethod& m, RequestFlags flags); | |
56 | void removeStoreReference(store_client ** scp, StoreEntry ** ep); | |
57 | void removeClientStoreReference(store_client **scp, ClientHttpRequest *http); | |
58 | void startError(ErrorState * err); | |
59 | void processExpired(); | |
60 | clientStream_status_t replyStatus(); | |
61 | void processMiss(); | |
62 | void traceReply(); | |
63 | const char *storeId() const { return (http->store_id.size() > 0 ? http->store_id.termedBuf() : http->uri); } | |
64 | ||
65 | Http::StatusCode purgeStatus; | |
66 | ||
67 | /* StoreClient API */ | |
68 | LogTags *loggingTags() const override; | |
69 | ||
70 | ClientHttpRequest *http; | |
71 | store_client *sc; /* The store_client we're using */ | |
72 | ||
73 | /// Buffer dedicated to receiving storeClientCopy() responses to generated | |
74 | /// revalidation requests. These requests cannot use next()->readBuffer | |
75 | /// because the latter keeps the contents of the stale HTTP response during | |
76 | /// revalidation. sendClientOldEntry() uses that contents. | |
77 | char tempbuf[HTTP_REQBUF_SZ]; | |
78 | ||
79 | struct Flags { | |
80 | Flags() : storelogiccomplete(0), complete(0), headersSent(false) {} | |
81 | ||
82 | unsigned storelogiccomplete:1; | |
83 | unsigned complete:1; ///< we have read all we can from upstream | |
84 | bool headersSent; | |
85 | } flags; | |
86 | clientStreamNode *ourNode; /* This will go away if/when this file gets refactored some more */ | |
87 | ||
88 | private: | |
89 | /* StoreClient API */ | |
90 | void fillChecklist(ACLFilledChecklist &) const override; | |
91 | ||
92 | clientStreamNode *getNextNode() const; | |
93 | void makeThisHead(); | |
94 | bool errorInStream(const StoreIOBuffer &result) const; | |
95 | bool matchesStreamBodyBuffer(const StoreIOBuffer &) const; | |
96 | void sendStreamError(StoreIOBuffer const &result); | |
97 | void pushStreamData(const StoreIOBuffer &); | |
98 | clientStreamNode * next() const; | |
99 | HttpReply *reply; | |
100 | void processReplyAccess(); | |
101 | static ACLCB ProcessReplyAccessResult; | |
102 | void processReplyAccessResult(const Acl::Answer &accessAllowed); | |
103 | void cloneReply(); | |
104 | void buildReplyHeader (); | |
105 | bool alwaysAllowResponse(Http::StatusCode sline) const; | |
106 | int checkTransferDone(); | |
107 | void processOnlyIfCachedMiss(); | |
108 | bool processConditional(); | |
109 | void noteStreamBufferredBytes(const StoreIOBuffer &); | |
110 | void cacheHit(StoreIOBuffer result); | |
111 | void handleIMSReply(StoreIOBuffer result); | |
112 | void sendMoreData(StoreIOBuffer result); | |
113 | void triggerInitialStoreRead(STCB = SendMoreData); | |
114 | void requestMoreBodyFromStore(); | |
115 | void sendClientOldEntry(); | |
116 | void purgeAllCached(); | |
117 | /// attempts to release the cached entry | |
118 | /// \returns whether the entry was released | |
119 | bool purgeEntry(StoreEntry &, const Http::MethodType, const char *descriptionPrefix = ""); | |
120 | /// releases both cached GET and HEAD entries | |
121 | void purgeDoPurge(); | |
122 | void forgetHit(); | |
123 | bool blockedHit() const; | |
124 | const char *storeLookupString(bool found) const { return found ? "match" : "mismatch"; } | |
125 | void detailStoreLookup(const char *detail); | |
126 | ||
127 | void sendBodyTooLargeError(); | |
128 | void sendPreconditionFailedError(); | |
129 | void sendNotModified(); | |
130 | void sendNotModifiedOrPreconditionFailedError(); | |
131 | void sendClientUpstreamResponse(const StoreIOBuffer &upstreamResponse); | |
132 | ||
133 | /// Reduces a chance of an accidental direct storeClientCopy() call that | |
134 | /// (should but) forgets to invalidate our lastStreamBufferedBytes. This | |
135 | /// function is not defined; decltype() syntax prohibits "= delete", but | |
136 | /// function usage will trigger deprecation warnings and linking errors. | |
137 | static decltype(::storeClientCopy) storeClientCopy [[deprecated]]; | |
138 | ||
139 | /// Classification of the initial Store lookup. | |
140 | /// This very first lookup happens without the Vary-driven key augmentation. | |
141 | /// TODO: Exclude internal Store match bans from the "mismatch" category. | |
142 | const char *firstStoreLookup_ = nullptr; | |
143 | ||
144 | /* (stale) cache hit information preserved during IMS revalidation */ | |
145 | StoreEntry *old_entry; | |
146 | store_client *old_sc; | |
147 | time_t old_lastmod; | |
148 | String old_etag; | |
149 | ||
150 | bool deleting; | |
151 | ||
152 | typedef enum { | |
153 | crNone = 0, ///< collapsed revalidation is not allowed for this context | |
154 | crInitiator, ///< we initiated collapsed revalidation request | |
155 | crSlave ///< we collapsed on the existing revalidation request | |
156 | } CollapsedRevalidation; | |
157 | ||
158 | CollapsedRevalidation collapsedRevalidation; | |
159 | ||
160 | /// HTTP response body bytes stored in our Client Stream buffer (if any) | |
161 | StoreIOBuffer lastStreamBufferedBytes; | |
162 | ||
163 | // TODO: Remove after moving the meat of this function into a method. | |
164 | friend CSR clientGetMoreData; | |
165 | }; | |
166 | ||
167 | // TODO: move to SideAgent parent, when we have one | |
168 | void purgeEntriesByUrl(HttpRequest *, const char *); | |
169 | ||
170 | #endif /* SQUID_SRC_CLIENT_SIDE_REPLY_H */ | |
171 |