]> git.ipfire.org Git - thirdparty/squid.git/blob - src/http/Stream.h
Remove Edge Side Include (ESI) protocol (#1905)
[thirdparty/squid.git] / src / http / Stream.h
1 /*
2 * Copyright (C) 1996-2023 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_HTTP_STREAM_H
10 #define SQUID_SRC_HTTP_STREAM_H
11
12 #include "clientStreamForward.h"
13 #include "comm/forward.h"
14 #include "debug/Stream.h"
15 #include "error/Error.h"
16 #include "http/forward.h"
17 #include "log/forward.h"
18 #include "mem/forward.h"
19 #include "servers/forward.h"
20 #include "StoreIOBuffer.h"
21 #if USE_DELAY_POOLS
22 #include "MessageBucket.h"
23 #endif
24
25 namespace Http
26 {
27
28 /**
29 * The processing context for a single HTTP transaction (stream).
30 *
31 * A stream lifetime extends from directly after a request has been parsed
32 * off the client connection buffer, until the last byte of both request
33 * and reply payload (if any) have been written, or it is otherwise
34 * explicitly terminated.
35 *
36 * Streams self-register with the Http::Server Pipeline being managed by the
37 * Server for the connection on which the request was received.
38 *
39 * The socket level management and I/O is done by a Server which owns us.
40 * The scope of this objects control over a socket consists of the data
41 * buffer received from the Server with an initially unknown length.
42 * When that length is known it sets the end boundary of our access to the
43 * buffer.
44 *
45 * The individual processing actions are done by other Jobs which we start.
46 *
47 * When a stream is completed the finished() method needs to be called which
48 * will perform all cleanup and deregistration operations. If the reason for
49 * finishing is an error, then notifyIoError() needs to be called prior to
50 * the finished() method.
51 * The caller should follow finished() with a call to ConnStateData::kick()
52 * to resume processing of other transactions or I/O on the connection.
53 *
54 * Alternatively the initiateClose() method can be called to terminate the
55 * whole client connection and all other pending streams.
56 *
57 * HTTP/1.x:
58 *
59 * When HTTP/1 pipeline is operating there may be multiple transactions using
60 * the client connection. Only the back() stream may read from the connection,
61 * and only the front() stream may write to it. A stream which needs to read
62 * or write to the connection but does not meet those criteria must be shifted
63 * to the deferred state.
64 *
65 *
66 * XXX: If an async call ends the ClientHttpRequest job, Http::Stream
67 * (and ConnStateData) may not know about it, leading to segfaults and
68 * assertions. This is difficult to fix
69 * because ClientHttpRequest lacks a good way to communicate its ongoing
70 * destruction back to the Http::Stream which pretends to "own" *http.
71 */
72 class Stream : public RefCountable
73 {
74 MEMPROXY_CLASS(Stream);
75
76 public:
77 /// construct with HTTP/1.x details
78 Stream(const Comm::ConnectionPointer &aConn, ClientHttpRequest *aReq);
79 ~Stream() override;
80
81 /// register this stream with the Server
82 void registerWithConn();
83
84 /// whether it is registered with a Server
85 bool connRegistered() const {return connRegistered_;};
86
87 /// whether the reply has started being sent
88 bool startOfOutput() const;
89
90 /// update stream state after a write, may initiate more I/O
91 void writeComplete(size_t size);
92
93 /// get more data to send
94 void pullData();
95
96 /// \return true if the HTTP request is for multiple ranges
97 bool multipartRangeRequest() const;
98
99 int64_t getNextRangeOffset() const;
100 bool canPackMoreRanges() const;
101 size_t lengthToSend(Range<int64_t> const &available) const;
102
103 clientStream_status_t socketState();
104
105 /// send an HTTP reply message headers and maybe some initial payload
106 void sendStartOfMessage(HttpReply *, StoreIOBuffer bodyData);
107 /// send some HTTP reply message payload
108 void sendBody(StoreIOBuffer bodyData);
109 /// update stream state when N bytes are being sent.
110 /// NP: Http1Server bytes actually not sent yet, just packed into a MemBuf ready
111 void noteSentBodyBytes(size_t);
112
113 /// add Range headers (if any) to the given HTTP reply message
114 void buildRangeHeader(HttpReply *);
115
116 clientStreamNode * getTail() const;
117 clientStreamNode * getClientReplyContext() const;
118
119 ConnStateData *getConn() const;
120
121 /// update state to reflect I/O error
122 void noteIoError(const Error &, const LogTagsErrors &);
123
124 /// cleanup when the transaction has finished. may destroy 'this'
125 void finished();
126
127 /// terminate due to a send/write error (may continue reading)
128 void initiateClose(const char *reason);
129
130 void deferRecipientForLater(clientStreamNode *, HttpReply *, StoreIOBuffer receivedData);
131
132 public: // HTTP/1.x state data
133
134 Comm::ConnectionPointer clientConnection; ///< details about the client connection socket
135 ClientHttpRequest *http; /* we pretend to own that Job */
136 HttpReply *reply;
137 char reqbuf[HTTP_REQBUF_SZ];
138 struct {
139 unsigned deferred:1; ///< This is a pipelined request waiting for the current object to complete
140 unsigned parsed_ok:1; ///< Was this parsed correctly?
141 } flags;
142
143 bool mayUseConnection() const {return mayUseConnection_;}
144
145 void mayUseConnection(bool aBool) {
146 mayUseConnection_ = aBool;
147 debugs(33, 3, "This " << this << " marked " << aBool);
148 }
149
150 class DeferredParams
151 {
152
153 public:
154 clientStreamNode *node;
155 HttpReply *rep;
156 StoreIOBuffer queuedBuffer;
157 };
158
159 DeferredParams deferredparams;
160 int64_t writtenToSocket;
161
162 private:
163 void prepareReply(HttpReply *);
164 void packChunk(const StoreIOBuffer &bodyData, MemBuf &);
165 void packRange(StoreIOBuffer const &, MemBuf *);
166 void doClose();
167
168 bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */
169 bool connRegistered_;
170 #if USE_DELAY_POOLS
171 MessageBucket::Pointer writeQuotaHandler; ///< response write limiter, if configured
172 #endif
173 };
174
175 } // namespace Http
176
177 #endif /* SQUID_SRC_HTTP_STREAM_H */
178