Bug 1814798 - pt 2. Add a PHCManager component to control PHC r=glandium,emilio
[gecko.git] / netwerk / protocol / http / nsHttp.h
blob6414f7c63966140ec1b6124e70645387a457fb50
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=4 sw=2 sts=2 et cin: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef nsHttp_h__
8 #define nsHttp_h__
10 #include <stdint.h>
11 #include "prtime.h"
12 #include "nsString.h"
13 #include "nsError.h"
14 #include "nsTArray.h"
15 #include "mozilla/OriginAttributes.h"
16 #include "mozilla/TimeStamp.h"
18 #include "mozilla/UniquePtr.h"
19 #include "NSSErrorsService.h"
21 class nsICacheEntry;
23 namespace mozilla {
25 namespace net {
26 class nsHttpResponseHead;
27 class nsHttpRequestHead;
28 class CacheControlParser;
30 enum class HttpVersion {
31 UNKNOWN = 0,
32 v0_9 = 9,
33 v1_0 = 10,
34 v1_1 = 11,
35 v2_0 = 20,
36 v3_0 = 30
39 enum class SpdyVersion { NONE = 0, HTTP_2 = 5 };
41 enum class SupportedAlpnRank : uint8_t {
42 NOT_SUPPORTED = 0,
43 HTTP_1_1 = 1,
44 HTTP_2 = 2,
45 // Note that the order here MUST be the same as the order in kHttp3Versions.
46 HTTP_3_DRAFT_29 = 3,
47 HTTP_3_DRAFT_30 = 4,
48 HTTP_3_DRAFT_31 = 5,
49 HTTP_3_DRAFT_32 = 6,
50 HTTP_3_VER_1 = 7,
53 inline bool IsHttp3(SupportedAlpnRank aRank) {
54 return aRank >= SupportedAlpnRank::HTTP_3_DRAFT_29;
57 extern const uint32_t kHttp3VersionCount;
58 extern const nsCString kHttp3Versions[];
60 //-----------------------------------------------------------------------------
61 // http connection capabilities
62 //-----------------------------------------------------------------------------
64 #define NS_HTTP_ALLOW_KEEPALIVE (1 << 0)
65 #define NS_HTTP_LARGE_KEEPALIVE (1 << 1)
67 // a transaction with this caps flag will continue to own the connection,
68 // preventing it from being reclaimed, even after the transaction completes.
69 #define NS_HTTP_STICKY_CONNECTION (1 << 2)
71 // a transaction with this caps flag will, upon opening a new connection,
72 // bypass the local DNS cache
73 #define NS_HTTP_REFRESH_DNS (1 << 3)
75 // a transaction with this caps flag will not pass SSL client-certificates
76 // to the server (see bug #466080), but is may also be used for other things
77 #define NS_HTTP_LOAD_ANONYMOUS (1 << 4)
79 // a transaction with this caps flag keeps timing information
80 #define NS_HTTP_TIMING_ENABLED (1 << 5)
82 // a transaction with this flag blocks the initiation of other transactons
83 // in the same load group until it is complete
84 #define NS_HTTP_LOAD_AS_BLOCKING (1 << 6)
86 // Disallow the use of the SPDY protocol. This is meant for the contexts
87 // such as HTTP upgrade which are nonsensical for SPDY, it is not the
88 // SPDY configuration variable.
89 #define NS_HTTP_DISALLOW_SPDY (1 << 7)
91 // a transaction with this flag loads without respect to whether the load
92 // group is currently blocking on some resources
93 #define NS_HTTP_LOAD_UNBLOCKED (1 << 8)
95 // This flag indicates the transaction should accept associated pushes
96 #define NS_HTTP_ONPUSH_LISTENER (1 << 9)
98 // Transactions with this flag should react to errors without side effects
99 // First user is to prevent clearing of alt-svc cache on failed probe
100 #define NS_HTTP_ERROR_SOFTLY (1 << 10)
102 // This corresponds to nsIHttpChannelInternal.beConservative
103 // it disables any cutting edge features that we are worried might result in
104 // interop problems with critical infrastructure
105 #define NS_HTTP_BE_CONSERVATIVE (1 << 11)
107 // Transactions with this flag should be processed first.
108 #define NS_HTTP_URGENT_START (1 << 12)
110 // A sticky connection of the transaction is explicitly allowed to be restarted
111 // on ERROR_NET_RESET.
112 #define NS_HTTP_CONNECTION_RESTARTABLE (1 << 13)
114 // Allow re-using a spdy/http2 connection with NS_HTTP_ALLOW_KEEPALIVE not set.
115 // This is primarily used to allow connection sharing for websockets over http/2
116 // without accidentally allowing it for websockets not over http/2
117 #define NS_HTTP_ALLOW_SPDY_WITHOUT_KEEPALIVE (1 << 15)
119 // Only permit CONNECTing to a proxy. A channel with this flag will not send an
120 // http request after CONNECT or setup tls. An http upgrade handler MUST be
121 // set. An ALPN header is set using the upgrade protocol.
122 #define NS_HTTP_CONNECT_ONLY (1 << 16)
124 // The connection should not use IPv4.
125 #define NS_HTTP_DISABLE_IPV4 (1 << 17)
127 // The connection should not use IPv6
128 #define NS_HTTP_DISABLE_IPV6 (1 << 18)
130 // Encodes the TRR mode.
131 #define NS_HTTP_TRR_MODE_MASK ((1 << 19) | (1 << 20))
133 // Disallow the use of the HTTP3 protocol. This is meant for the contexts
134 // such as HTTP upgrade which are not supported by HTTP3.
135 #define NS_HTTP_DISALLOW_HTTP3 (1 << 21)
137 // Force a transaction to stay in pending queue until the HTTPS RR is
138 // available.
139 #define NS_HTTP_FORCE_WAIT_HTTP_RR (1 << 22)
141 // This is used for a temporary workaround for a web-compat issue. The flag is
142 // only set on CORS preflight request to allowed sending client certificates
143 // on a connection for an anonymous request.
144 #define NS_HTTP_LOAD_ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT (1 << 23)
146 #define NS_HTTP_DISALLOW_HTTPS_RR (1 << 24)
148 #define NS_HTTP_DISALLOW_ECH (1 << 25)
150 // Used to indicate that an HTTP Connection should obey Resist Fingerprinting
151 // and set the User-Agent accordingly.
152 #define NS_HTTP_USE_RFP (1 << 26)
154 // If set, then the initial TLS handshake failed.
155 #define NS_HTTP_IS_RETRY (1 << 27)
157 // When set, disallow to connect to a HTTP/2 proxy.
158 #define NS_HTTP_DISALLOW_HTTP2_PROXY (1 << 28)
160 #define NS_HTTP_TRR_FLAGS_FROM_MODE(x) ((static_cast<uint32_t>(x) & 3) << 19)
162 #define NS_HTTP_TRR_MODE_FROM_FLAGS(x) \
163 (static_cast<nsIRequest::TRRMode>((((x)&NS_HTTP_TRR_MODE_MASK) >> 19) & 3))
165 //-----------------------------------------------------------------------------
166 // some default values
167 //-----------------------------------------------------------------------------
169 #define NS_HTTP_DEFAULT_PORT 80
170 #define NS_HTTPS_DEFAULT_PORT 443
172 #define NS_HTTP_HEADER_SEP ','
174 //-----------------------------------------------------------------------------
175 // http atoms...
176 //-----------------------------------------------------------------------------
178 struct nsHttpAtom;
179 struct nsHttpAtomLiteral;
181 namespace nsHttp {
182 [[nodiscard]] nsresult CreateAtomTable();
183 void DestroyAtomTable();
185 // will dynamically add atoms to the table if they don't already exist
186 nsHttpAtom ResolveAtom(const nsACString& s);
188 // returns true if the specified token [start,end) is valid per RFC 2616
189 // section 2.2
190 bool IsValidToken(const char* start, const char* end);
192 inline bool IsValidToken(const nsACString& s) {
193 return IsValidToken(s.BeginReading(), s.EndReading());
196 // Strip the leading or trailing HTTP whitespace per fetch spec section 2.2.
197 void TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest);
199 // Returns true if the specified value is reasonable given the defintion
200 // in RFC 2616 section 4.2. Full strict validation is not performed
201 // currently as it would require full parsing of the value.
202 bool IsReasonableHeaderValue(const nsACString& s);
204 // find the first instance (case-insensitive comparison) of the given
205 // |token| in the |input| string. the |token| is bounded by elements of
206 // |separators| and may appear at the beginning or end of the |input|
207 // string. null is returned if the |token| is not found. |input| may be
208 // null, in which case null is returned.
209 const char* FindToken(const char* input, const char* token, const char* seps);
211 // This function parses a string containing a decimal-valued, non-negative
212 // 64-bit integer. If the value would exceed INT64_MAX, then false is
213 // returned. Otherwise, this function returns true and stores the
214 // parsed value in |result|. The next unparsed character in |input| is
215 // optionally returned via |next| if |next| is non-null.
217 // TODO(darin): Replace this with something generic.
219 [[nodiscard]] bool ParseInt64(const char* input, const char** next,
220 int64_t* result);
222 // Variant on ParseInt64 that expects the input string to contain nothing
223 // more than the value being parsed.
224 [[nodiscard]] inline bool ParseInt64(const char* input, int64_t* result) {
225 const char* next;
226 return ParseInt64(input, &next, result) && *next == '\0';
229 // Return whether the HTTP status code represents a permanent redirect
230 bool IsPermanentRedirect(uint32_t httpStatus);
232 // Returns the APLN token which represents the used protocol version.
233 const char* GetProtocolVersion(HttpVersion pv);
235 bool ValidationRequired(bool isForcedValid,
236 nsHttpResponseHead* cachedResponseHead,
237 uint32_t loadFlags, bool allowStaleCacheContent,
238 bool forceValidateCacheContent, bool isImmutable,
239 bool customConditionalRequest,
240 nsHttpRequestHead& requestHead, nsICacheEntry* entry,
241 CacheControlParser& cacheControlRequest,
242 bool fromPreviousSession,
243 bool* performBackgroundRevalidation = nullptr);
245 nsresult GetHttpResponseHeadFromCacheEntry(
246 nsICacheEntry* entry, nsHttpResponseHead* cachedResponseHead);
248 nsresult CheckPartial(nsICacheEntry* aEntry, int64_t* aSize,
249 int64_t* aContentLength,
250 nsHttpResponseHead* responseHead);
252 void DetermineFramingAndImmutability(nsICacheEntry* entry,
253 nsHttpResponseHead* cachedResponseHead,
254 bool isHttps, bool* weaklyFramed,
255 bool* isImmutable);
257 // Called when an optimization feature affecting active vs background tab load
258 // took place. Called only on the parent process and only updates
259 // mLastActiveTabLoadOptimizationHit timestamp to now.
260 void NotifyActiveTabLoadOptimization();
261 TimeStamp GetLastActiveTabLoadOptimizationHit();
262 void SetLastActiveTabLoadOptimizationHit(TimeStamp const& when);
263 bool IsBeforeLastActiveTabLoadOptimization(TimeStamp const& when);
265 nsCString ConvertRequestHeadToString(nsHttpRequestHead& aRequestHead,
266 bool aHasRequestBody,
267 bool aRequestBodyHasHeaders,
268 bool aUsingConnect);
270 template <typename T>
271 using SendFunc = std::function<bool(const T&, uint64_t, uint32_t)>;
273 template <typename T>
274 bool SendDataInChunks(const nsCString& aData, uint64_t aOffset, uint32_t aCount,
275 const SendFunc<T>& aSendFunc) {
276 static uint32_t const kCopyChunkSize = 128 * 1024;
277 uint32_t toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
279 uint32_t start = 0;
280 while (aCount) {
281 T data(Substring(aData, start, toRead));
283 if (!aSendFunc(data, aOffset, toRead)) {
284 return false;
287 aOffset += toRead;
288 start += toRead;
289 aCount -= toRead;
290 toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
293 return true;
296 } // namespace nsHttp
298 struct nsHttpAtomLiteral;
299 struct nsHttpAtom {
300 nsHttpAtom() = default;
301 nsHttpAtom(const nsHttpAtom& other) = default;
303 explicit operator bool() const { return !_val.IsEmpty(); }
305 const char* get() const {
306 if (_val.IsEmpty()) {
307 return nullptr;
309 return _val.BeginReading();
312 const nsCString& val() const { return _val; }
314 void operator=(const nsHttpAtom& a) { _val = a._val; }
316 // This constructor is mainly used to build the static atom list
317 // Avoid using it for anything else.
318 explicit nsHttpAtom(const nsACString& val) : _val(val) {}
320 private:
321 nsCString _val;
322 friend nsHttpAtom nsHttp::ResolveAtom(const nsACString& s);
325 struct nsHttpAtomLiteral {
326 const char* get() const { return _data.get(); }
327 nsLiteralCString const& val() const { return _data; }
329 template <size_t N>
330 constexpr explicit nsHttpAtomLiteral(const char (&val)[N]) : _data(val) {}
332 operator nsHttpAtom() const { return nsHttpAtom(_data); }
334 private:
335 nsLiteralCString _data;
338 inline bool operator==(nsHttpAtomLiteral const& self,
339 nsHttpAtomLiteral const& other) {
340 return self.get() == other.get();
342 inline bool operator!=(nsHttpAtomLiteral const& self,
343 nsHttpAtomLiteral const& other) {
344 return self.get() != other.get();
347 inline bool operator==(nsHttpAtom const& self, nsHttpAtomLiteral const& other) {
348 return self.val() == other.val();
350 inline bool operator!=(nsHttpAtom const& self, nsHttpAtomLiteral const& other) {
351 return self.val() != other.val();
354 inline bool operator==(nsHttpAtomLiteral const& self, nsHttpAtom const& other) {
355 return self.val() == other.val();
357 inline bool operator!=(nsHttpAtomLiteral const& self, nsHttpAtom const& other) {
358 return self.val() != other.val();
361 inline bool operator==(nsHttpAtom const& self, nsHttpAtom const& other) {
362 return self.val() == other.val();
364 inline bool operator!=(nsHttpAtom const& self, nsHttpAtom const& other) {
365 return self.val() != other.val();
368 namespace nsHttp {
370 // Declare all atoms
372 // The atom names and values are stored in nsHttpAtomList.h and are brought
373 // to you by the magic of C preprocessing. Add new atoms to nsHttpAtomList
374 // and all support logic will be auto-generated.
376 #define HTTP_ATOM(_name, _value) \
377 inline constexpr nsHttpAtomLiteral _name(_value);
378 #include "nsHttpAtomList.h"
379 #undef HTTP_ATOM
380 } // namespace nsHttp
382 //-----------------------------------------------------------------------------
383 // utilities...
384 //-----------------------------------------------------------------------------
386 static inline uint32_t PRTimeToSeconds(PRTime t_usec) {
387 return uint32_t(t_usec / PR_USEC_PER_SEC);
390 #define NowInSeconds() PRTimeToSeconds(PR_Now())
392 // Round q-value to 2 decimal places; return 2 most significant digits as uint.
393 #define QVAL_TO_UINT(q) ((unsigned int)(((q) + 0.005) * 100.0))
395 #define HTTP_LWS " \t"
396 #define HTTP_HEADER_VALUE_SEPS HTTP_LWS ","
398 void EnsureBuffer(UniquePtr<char[]>& buf, uint32_t newSize, uint32_t preserve,
399 uint32_t& objSize);
400 void EnsureBuffer(UniquePtr<uint8_t[]>& buf, uint32_t newSize,
401 uint32_t preserve, uint32_t& objSize);
403 // h2=":443"; ma=60; single
404 // results in 3 mValues = {{h2, :443}, {ma, 60}, {single}}
406 class ParsedHeaderPair {
407 public:
408 ParsedHeaderPair(const char* name, int32_t nameLen, const char* val,
409 int32_t valLen, bool isQuotedValue);
411 ParsedHeaderPair(ParsedHeaderPair const& copy)
412 : mName(copy.mName),
413 mValue(copy.mValue),
414 mUnquotedValue(copy.mUnquotedValue),
415 mIsQuotedValue(copy.mIsQuotedValue) {
416 if (mIsQuotedValue) {
417 mValue.Rebind(mUnquotedValue.BeginReading(), mUnquotedValue.Length());
421 nsDependentCSubstring mName;
422 nsDependentCSubstring mValue;
424 private:
425 nsCString mUnquotedValue;
426 bool mIsQuotedValue;
428 void RemoveQuotedStringEscapes(const char* val, int32_t valLen);
431 class ParsedHeaderValueList {
432 public:
433 ParsedHeaderValueList(const char* t, uint32_t len, bool allowInvalidValue);
434 nsTArray<ParsedHeaderPair> mValues;
436 private:
437 void ParseNameAndValue(const char* input, bool allowInvalidValue);
440 class ParsedHeaderValueListList {
441 public:
442 // RFC 7231 section 3.2.6 defines the syntax of the header field values.
443 // |allowInvalidValue| indicates whether the rule will be used to check
444 // the input text.
445 // Note that ParsedHeaderValueListList is currently used to parse
446 // Alt-Svc and Server-Timing header. |allowInvalidValue| is set to true
447 // when parsing Alt-Svc for historical reasons.
448 explicit ParsedHeaderValueListList(const nsCString& fullHeader,
449 bool allowInvalidValue = true);
450 nsTArray<ParsedHeaderValueList> mValues;
452 private:
453 nsCString mFull;
456 void LogHeaders(const char* lineStart);
458 // Convert HTTP response codes returned by a proxy to nsresult.
459 // This function should be only used when we get a failed response to the
460 // CONNECT method.
461 nsresult HttpProxyResponseToErrorCode(uint32_t aStatusCode);
463 // Convert an alpn string to SupportedAlpnType.
464 SupportedAlpnRank IsAlpnSupported(const nsACString& aAlpn);
466 static inline bool AllowedErrorForHTTPSRRFallback(nsresult aError) {
467 return psm::IsNSSErrorCode(-1 * NS_ERROR_GET_CODE(aError)) ||
468 aError == NS_ERROR_NET_RESET ||
469 aError == NS_ERROR_CONNECTION_REFUSED ||
470 aError == NS_ERROR_UNKNOWN_HOST || aError == NS_ERROR_NET_TIMEOUT;
473 bool SecurityErrorThatMayNeedRestart(nsresult aReason);
475 [[nodiscard]] nsresult MakeOriginURL(const nsACString& origin,
476 nsCOMPtr<nsIURI>& url);
478 [[nodiscard]] nsresult MakeOriginURL(const nsACString& scheme,
479 const nsACString& origin,
480 nsCOMPtr<nsIURI>& url);
482 void CreatePushHashKey(const nsCString& scheme, const nsCString& hostHeader,
483 const mozilla::OriginAttributes& originAttributes,
484 uint64_t serial, const nsACString& pathInfo,
485 nsCString& outOrigin, nsCString& outKey);
487 nsresult GetNSResultFromWebTransportError(uint8_t aErrorCode);
489 uint8_t GetWebTransportErrorFromNSResult(nsresult aResult);
491 uint64_t WebTransportErrorToHttp3Error(uint8_t aErrorCode);
493 uint8_t Http3ErrorToWebTransportError(uint64_t aErrorCode);
495 } // namespace net
496 } // namespace mozilla
498 #endif // nsHttp_h__