Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #ifndef nsAHttpTransaction_h__
6 : #define nsAHttpTransaction_h__
7 :
8 : #include "nsISupports.h"
9 : #include "nsTArray.h"
10 : #include "nsWeakReference.h"
11 :
12 : class nsIInterfaceRequestor;
13 : class nsITransport;
14 : class nsIRequestContext;
15 :
16 : namespace mozilla { namespace net {
17 :
18 : class nsAHttpConnection;
19 : class nsAHttpSegmentReader;
20 : class nsAHttpSegmentWriter;
21 : class nsHttpTransaction;
22 : class nsHttpRequestHead;
23 : class nsHttpConnectionInfo;
24 : class NullHttpTransaction;
25 : class SpdyConnectTransaction;
26 :
27 : //----------------------------------------------------------------------------
28 : // Abstract base class for a HTTP transaction:
29 : //
30 : // A transaction is a "sink" for the response data. The connection pushes
31 : // data to the transaction by writing to it. The transaction supports
32 : // WriteSegments and may refuse to accept data if its buffers are full (its
33 : // write function returns NS_BASE_STREAM_WOULD_BLOCK in this case).
34 : //----------------------------------------------------------------------------
35 :
36 : // 2af6d634-13e3-494c-8903-c9dce5c22fc0
37 : #define NS_AHTTPTRANSACTION_IID \
38 : { 0x2af6d634, 0x13e3, 0x494c, {0x89, 0x03, 0xc9, 0xdc, 0xe5, 0xc2, 0x2f, 0xc0 }}
39 :
40 16 : class nsAHttpTransaction : public nsSupportsWeakReference
41 : {
42 : public:
43 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_AHTTPTRANSACTION_IID)
44 :
45 : // called by the connection when it takes ownership of the transaction.
46 : virtual void SetConnection(nsAHttpConnection *) = 0;
47 :
48 : // called by the connection after a successfull activation of this transaction
49 : // in other words, tells the transaction it transitioned to the "active" state.
50 0 : virtual void OnActivated(bool h2) {}
51 :
52 : // used to obtain the connection associated with this transaction
53 : virtual nsAHttpConnection *Connection() = 0;
54 :
55 : // called by the connection to get security callbacks to set on the
56 : // socket transport.
57 : virtual void GetSecurityCallbacks(nsIInterfaceRequestor **) = 0;
58 :
59 : // called to report socket status (see nsITransportEventSink)
60 : virtual void OnTransportStatus(nsITransport* transport,
61 : nsresult status, int64_t progress) = 0;
62 :
63 : // called to check the transaction status.
64 : virtual bool IsDone() = 0;
65 : virtual nsresult Status() = 0;
66 : virtual uint32_t Caps() = 0;
67 :
68 : // called to notify that a requested DNS cache entry was refreshed.
69 : virtual void SetDNSWasRefreshed() = 0;
70 :
71 : // called to read request data from the transaction.
72 : virtual MOZ_MUST_USE nsresult ReadSegments(nsAHttpSegmentReader *reader,
73 : uint32_t count,
74 : uint32_t *countRead) = 0;
75 :
76 : // called to write response data to the transaction.
77 : virtual MOZ_MUST_USE nsresult WriteSegments(nsAHttpSegmentWriter *writer,
78 : uint32_t count,
79 : uint32_t *countWritten) = 0;
80 :
81 : // These versions of the functions allow the overloader to specify whether or
82 : // not it is safe to call *Segments() in a loop while they return OK.
83 : // The callee should turn again to false if it is not, otherwise leave untouched
84 : virtual MOZ_MUST_USE nsresult
85 8 : ReadSegmentsAgain(nsAHttpSegmentReader *reader, uint32_t count,
86 : uint32_t *countRead, bool *again)
87 : {
88 8 : return ReadSegments(reader, count, countRead);
89 : }
90 : virtual MOZ_MUST_USE nsresult
91 14 : WriteSegmentsAgain(nsAHttpSegmentWriter *writer, uint32_t count,
92 : uint32_t *countWritten, bool *again)
93 : {
94 14 : return WriteSegments(writer, count, countWritten);
95 : }
96 :
97 : // called to close the transaction
98 : virtual void Close(nsresult reason) = 0;
99 :
100 : // called to indicate a failure with proxy CONNECT
101 : virtual void SetProxyConnectFailed() = 0;
102 :
103 : // called to retrieve the request headers of the transaction
104 : virtual nsHttpRequestHead *RequestHead() = 0;
105 :
106 : // determine the number of real http/1.x transactions on this
107 : // abstract object. Pipelines had multiple, SPDY has 0,
108 : // normal http transactions have 1.
109 : virtual uint32_t Http1xTransactionCount() = 0;
110 :
111 : // called to remove the unused sub transactions from an object that can
112 : // handle multiple transactions simultaneously (i.e. h2).
113 : //
114 : // Returns NS_ERROR_NOT_IMPLEMENTED if the object does not implement
115 : // sub-transactions.
116 : //
117 : // Returns NS_ERROR_ALREADY_OPENED if the subtransactions have been
118 : // at least partially written and cannot be moved.
119 : //
120 : virtual MOZ_MUST_USE nsresult TakeSubTransactions(
121 : nsTArray<RefPtr<nsAHttpTransaction> > &outTransactions) = 0;
122 :
123 : // Occasionally the abstract interface has to give way to base implementations
124 : // to respect differences between spdy, h2, etc..
125 : // These Query* (and IsNullTransaction()) functions provide a way to do
126 : // that without using xpcom or rtti. Any calling code that can't deal with
127 : // a null response from one of them probably shouldn't be using nsAHttpTransaction
128 :
129 : // equivalent to !!dynamic_cast<NullHttpTransaction *>(this)
130 : // A null transaction is expected to return BASE_STREAM_CLOSED on all of
131 : // its IO functions all the time.
132 8 : virtual bool IsNullTransaction() { return false; }
133 0 : virtual NullHttpTransaction *QueryNullTransaction() { return nullptr; }
134 :
135 : // If we used rtti this would be the result of doing
136 : // dynamic_cast<nsHttpTransaction *>(this).. i.e. it can be nullptr for
137 : // non nsHttpTransaction implementations of nsAHttpTransaction
138 0 : virtual nsHttpTransaction *QueryHttpTransaction() { return nullptr; }
139 :
140 : // If we used rtti this would be the result of doing
141 : // dynamic_cast<SpdyConnectTransaction *>(this).. i.e. it can be nullptr for
142 : // other types
143 0 : virtual SpdyConnectTransaction *QuerySpdyConnectTransaction() { return nullptr; }
144 :
145 : // return the request context associated with the transaction
146 0 : virtual nsIRequestContext *RequestContext() { return nullptr; }
147 :
148 : // return the connection information associated with the transaction
149 : virtual nsHttpConnectionInfo *ConnectionInfo() = 0;
150 :
151 : // The base definition of these is done in nsHttpTransaction.cpp
152 : virtual bool ResponseTimeoutEnabled() const;
153 : virtual PRIntervalTime ResponseTimeout();
154 :
155 : // conceptually the security info is part of the connection, but sometimes
156 : // in the case of TLS tunneled within TLS the transaction might present
157 : // a more specific security info that cannot be represented as a layer in
158 : // the connection due to multiplexing. This interface represents such an
159 : // overload. If it returns NS_FAILURE the connection should be considered
160 : // authoritative.
161 3 : virtual MOZ_MUST_USE nsresult GetTransactionSecurityInfo(nsISupports **)
162 : {
163 3 : return NS_ERROR_NOT_IMPLEMENTED;
164 : }
165 :
166 0 : virtual void DisableSpdy() { }
167 0 : virtual void ReuseConnectionOnRestartOK(bool) { }
168 :
169 : // Returns true if early-data or fast open is possible.
170 0 : virtual MOZ_MUST_USE bool CanDo0RTT() {
171 0 : return false;
172 : }
173 : // Returns true if early-data is possible and transaction will remember
174 : // that it is in 0RTT mode (to know should it rewide transaction or not
175 : // in the case of an error).
176 0 : virtual MOZ_MUST_USE bool Do0RTT() {
177 0 : return false;
178 : }
179 : // This function will be called when a tls handshake has been finished and
180 : // we know whether early-data that was sent has been accepted or not, e.g.
181 : // do we need to restart a transaction. This will be called only if Do0RTT
182 : // returns true.
183 : // If aRestart parameter is true we need to restart the transaction,
184 : // otherwise the erly-data has been accepted and we can continue the
185 : // transaction.
186 : // If aAlpnChanged is true (and we were assuming http/2), we'll need to take
187 : // the transactions out of the session, rewind them all, and start them back
188 : // over as http/1 transactions
189 : // The function will return success or failure of the transaction restart.
190 0 : virtual MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged) {
191 0 : return NS_ERROR_NOT_IMPLEMENTED;
192 : }
193 :
194 0 : virtual MOZ_MUST_USE nsresult RestartOnFastOpenError() {
195 0 : return NS_ERROR_NOT_IMPLEMENTED;
196 : }
197 :
198 0 : virtual uint64_t TopLevelOuterContentWindowId() {
199 0 : MOZ_ASSERT(false);
200 : return 0;
201 : }
202 :
203 0 : virtual void SetFastOpenStatus(uint8_t aStatus) {}
204 : };
205 :
206 : NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpTransaction, NS_AHTTPTRANSACTION_IID)
207 :
208 : #define NS_DECL_NSAHTTPTRANSACTION \
209 : void SetConnection(nsAHttpConnection *) override; \
210 : nsAHttpConnection *Connection() override; \
211 : void GetSecurityCallbacks(nsIInterfaceRequestor **) override; \
212 : void OnTransportStatus(nsITransport* transport, \
213 : nsresult status, int64_t progress) override; \
214 : bool IsDone() override; \
215 : nsresult Status() override; \
216 : uint32_t Caps() override; \
217 : void SetDNSWasRefreshed() override; \
218 : virtual MOZ_MUST_USE nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *) override; \
219 : virtual MOZ_MUST_USE nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *) override; \
220 : virtual void Close(nsresult reason) override; \
221 : nsHttpConnectionInfo *ConnectionInfo() override; \
222 : void SetProxyConnectFailed() override; \
223 : virtual nsHttpRequestHead *RequestHead() override; \
224 : uint32_t Http1xTransactionCount() override; \
225 : MOZ_MUST_USE nsresult TakeSubTransactions(nsTArray<RefPtr<nsAHttpTransaction> > &outTransactions) override;
226 :
227 : //-----------------------------------------------------------------------------
228 : // nsAHttpSegmentReader
229 : //-----------------------------------------------------------------------------
230 :
231 3 : class nsAHttpSegmentReader
232 : {
233 : public:
234 : // any returned failure code stops segment iteration
235 : virtual MOZ_MUST_USE nsresult OnReadSegment(const char *segment,
236 : uint32_t count,
237 : uint32_t *countRead) = 0;
238 :
239 : // Ask the segment reader to commit to accepting size bytes of
240 : // data from subsequent OnReadSegment() calls or throw hard
241 : // (i.e. not wouldblock) exceptions. Implementations
242 : // can return NS_ERROR_FAILURE if they never make commitments of that size
243 : // (the default), NS_OK if they make the commitment, or
244 : // NS_BASE_STREAM_WOULD_BLOCK if they cannot make the
245 : // commitment now but might in the future and forceCommitment is not true .
246 : // (forceCommitment requires a hard failure or OK at this moment.)
247 : //
248 : // SpdySession uses this to make sure frames are atomic.
249 0 : virtual MOZ_MUST_USE nsresult CommitToSegmentSize(uint32_t size,
250 : bool forceCommitment)
251 : {
252 0 : return NS_ERROR_FAILURE;
253 : }
254 : };
255 :
256 : #define NS_DECL_NSAHTTPSEGMENTREADER \
257 : MOZ_MUST_USE nsresult OnReadSegment(const char *, uint32_t, uint32_t *) override;
258 :
259 : //-----------------------------------------------------------------------------
260 : // nsAHttpSegmentWriter
261 : //-----------------------------------------------------------------------------
262 :
263 3 : class nsAHttpSegmentWriter
264 : {
265 : public:
266 : // any returned failure code stops segment iteration
267 : virtual MOZ_MUST_USE nsresult OnWriteSegment(char *segment,
268 : uint32_t count,
269 : uint32_t *countWritten) = 0;
270 : };
271 :
272 : #define NS_DECL_NSAHTTPSEGMENTWRITER \
273 : MOZ_MUST_USE nsresult OnWriteSegment(char *, uint32_t, uint32_t *) override;
274 :
275 : } // namespace net
276 : } // namespace mozilla
277 :
278 : #endif // nsAHttpTransaction_h__
|