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