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