1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set ts=4 sw=4 sts=4 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/. */
6
7 #ifndef nsHttp_h__
8 #define nsHttp_h__
9
10 #include <stdint.h>
11 #include "prtime.h"
12 #include "nsAutoPtr.h"
13 #include "nsString.h"
14 #include "nsError.h"
15 #include "nsTArray.h"
16 #include "mozilla/TimeStamp.h"
17 #include "mozilla/UniquePtr.h"
18
19 // http version codes
20 #define NS_HTTP_VERSION_UNKNOWN 0
21 #define NS_HTTP_VERSION_0_9 9
22 #define NS_HTTP_VERSION_1_0 10
23 #define NS_HTTP_VERSION_1_1 11
24 #define NS_HTTP_VERSION_2_0 20
25
26 class nsICacheEntry;
27
28 namespace mozilla {
29
30 class Mutex;
31
32 namespace net {
33 class nsHttpResponseHead;
34 class nsHttpRequestHead;
35 class CacheControlParser;
36
37 enum {
38 // SPDY_VERSION_2 = 2, REMOVED
39 // SPDY_VERSION_3 = 3, REMOVED
40 // SPDY_VERSION_31 = 4, REMOVED
41 HTTP_VERSION_2 = 5
42
43 // leave room for official versions. telem goes to 48
44 // 24 was a internal spdy/3.1
45 // 25 was spdy/4a2
46 // 26 was http/2-draft08 and http/2-draft07 (they were the same)
47 // 27 was http/2-draft09, h2-10, and h2-11
48 // 28 was http/2-draft12
49 // 29 was http/2-draft13
50 // 30 was h2-14 and h2-15
51 // 31 was h2-16
52 };
53
54 typedef uint8_t nsHttpVersion;
55
56 //-----------------------------------------------------------------------------
57 // http connection capabilities
58 //-----------------------------------------------------------------------------
59
60 #define NS_HTTP_ALLOW_KEEPALIVE (1 << 0)
61 #define NS_HTTP_LARGE_KEEPALIVE (1 << 1)
62
63 // a transaction with this caps flag will continue to own the connection,
64 // preventing it from being reclaimed, even after the transaction completes.
65 #define NS_HTTP_STICKY_CONNECTION (1 << 2)
66
67 // a transaction with this caps flag will, upon opening a new connection,
68 // bypass the local DNS cache
69 #define NS_HTTP_REFRESH_DNS (1 << 3)
70
71 // a transaction with this caps flag will not pass SSL client-certificates
72 // to the server (see bug #466080), but is may also be used for other things
73 #define NS_HTTP_LOAD_ANONYMOUS (1 << 4)
74
75 // a transaction with this caps flag keeps timing information
76 #define NS_HTTP_TIMING_ENABLED (1 << 5)
77
78 // a transaction with this flag blocks the initiation of other transactons
79 // in the same load group until it is complete
80 #define NS_HTTP_LOAD_AS_BLOCKING (1 << 6)
81
82 // Disallow the use of the SPDY protocol. This is meant for the contexts
83 // such as HTTP upgrade which are nonsensical for SPDY, it is not the
84 // SPDY configuration variable.
85 #define NS_HTTP_DISALLOW_SPDY (1 << 7)
86
87 // a transaction with this flag loads without respect to whether the load
88 // group is currently blocking on some resources
89 #define NS_HTTP_LOAD_UNBLOCKED (1 << 8)
90
91 // This flag indicates the transaction should accept associated pushes
92 #define NS_HTTP_ONPUSH_LISTENER (1 << 9)
93
94 // Transactions with this flag should react to errors without side effects
95 // First user is to prevent clearing of alt-svc cache on failed probe
96 #define NS_HTTP_ERROR_SOFTLY (1 << 10)
97
98 // This corresponds to nsIHttpChannelInternal.beConservative
99 // it disables any cutting edge features that we are worried might result in
100 // interop problems with critical infrastructure
101 #define NS_HTTP_BE_CONSERVATIVE (1 << 11)
102
103 // Transactions with this flag should be processed first.
104 #define NS_HTTP_URGENT_START (1 << 12)
105
106 // A sticky connection of the transaction is explicitly allowed to be restarted
107 // on ERROR_NET_RESET.
108 #define NS_HTTP_CONNECTION_RESTARTABLE (1 << 13)
109
110 //-----------------------------------------------------------------------------
111 // some default values
112 //-----------------------------------------------------------------------------
113
114 #define NS_HTTP_DEFAULT_PORT 80
115 #define NS_HTTPS_DEFAULT_PORT 443
116
117 #define NS_HTTP_HEADER_SEPS ", \t"
118
119 //-----------------------------------------------------------------------------
120 // http atoms...
121 //-----------------------------------------------------------------------------
122
123 struct nsHttpAtom {
124 operator const char *() const { return _val; }
getnsHttpAtom125 const char *get() const { return _val; }
126
127 void operator=(const char *v) { _val = v; }
128 void operator=(const nsHttpAtom &a) { _val = a._val; }
129
130 // private
131 const char *_val;
132 };
133
134 namespace nsHttp {
135 MOZ_MUST_USE nsresult CreateAtomTable();
136 void DestroyAtomTable();
137
138 // The mutex is valid any time the Atom Table is valid
139 // This mutex is used in the unusual case that the network thread and
140 // main thread might access the same data
141 Mutex *GetLock();
142
143 // will dynamically add atoms to the table if they don't already exist
144 nsHttpAtom ResolveAtom(const char *);
ResolveAtom(const nsACString & s)145 inline nsHttpAtom ResolveAtom(const nsACString &s) {
146 return ResolveAtom(PromiseFlatCString(s).get());
147 }
148
149 // returns true if the specified token [start,end) is valid per RFC 2616
150 // section 2.2
151 bool IsValidToken(const char *start, const char *end);
152
IsValidToken(const nsACString & s)153 inline bool IsValidToken(const nsACString &s) {
154 return IsValidToken(s.BeginReading(), s.EndReading());
155 }
156
157 // Strip the leading or trailing HTTP whitespace per fetch spec section 2.2.
158 void TrimHTTPWhitespace(const nsACString &aSource, nsACString &aDest);
159
160 // Returns true if the specified value is reasonable given the defintion
161 // in RFC 2616 section 4.2. Full strict validation is not performed
162 // currently as it would require full parsing of the value.
163 bool IsReasonableHeaderValue(const nsACString &s);
164
165 // find the first instance (case-insensitive comparison) of the given
166 // |token| in the |input| string. the |token| is bounded by elements of
167 // |separators| and may appear at the beginning or end of the |input|
168 // string. null is returned if the |token| is not found. |input| may be
169 // null, in which case null is returned.
170 const char *FindToken(const char *input, const char *token,
171 const char *separators);
172
173 // This function parses a string containing a decimal-valued, non-negative
174 // 64-bit integer. If the value would exceed INT64_MAX, then false is
175 // returned. Otherwise, this function returns true and stores the
176 // parsed value in |result|. The next unparsed character in |input| is
177 // optionally returned via |next| if |next| is non-null.
178 //
179 // TODO(darin): Replace this with something generic.
180 //
181 MOZ_MUST_USE bool ParseInt64(const char *input, const char **next,
182 int64_t *result);
183
184 // Variant on ParseInt64 that expects the input string to contain nothing
185 // more than the value being parsed.
ParseInt64(const char * input,int64_t * result)186 inline MOZ_MUST_USE bool ParseInt64(const char *input, int64_t *result) {
187 const char *next;
188 return ParseInt64(input, &next, result) && *next == '\0';
189 }
190
191 // Return whether the HTTP status code represents a permanent redirect
192 bool IsPermanentRedirect(uint32_t httpStatus);
193
194 // Returns the APLN token which represents the used protocol version.
195 const char *GetProtocolVersion(uint32_t pv);
196
197 bool ValidationRequired(bool isForcedValid,
198 nsHttpResponseHead *cachedResponseHead,
199 uint32_t loadFlags, bool allowStaleCacheContent,
200 bool isImmutable, bool customConditionalRequest,
201 nsHttpRequestHead &requestHead, nsICacheEntry *entry,
202 CacheControlParser &cacheControlRequest,
203 bool fromPreviousSession);
204
205 nsresult GetHttpResponseHeadFromCacheEntry(
206 nsICacheEntry *entry, nsHttpResponseHead *cachedResponseHead);
207
208 nsresult CheckPartial(nsICacheEntry *aEntry, int64_t *aSize,
209 int64_t *aContentLength,
210 nsHttpResponseHead *responseHead);
211
212 void DetermineFramingAndImmutability(nsICacheEntry *entry,
213 nsHttpResponseHead *cachedResponseHead,
214 bool isHttps, bool *weaklyFramed,
215 bool *isImmutable);
216
217 // Called when an optimization feature affecting active vs background tab load
218 // took place. Called only on the parent process and only updates
219 // mLastActiveTabLoadOptimizationHit timestamp to now.
220 void NotifyActiveTabLoadOptimization();
221 TimeStamp const GetLastActiveTabLoadOptimizationHit();
222 void SetLastActiveTabLoadOptimizationHit(TimeStamp const &when);
223 bool IsBeforeLastActiveTabLoadOptimization(TimeStamp const &when);
224
225 // Declare all atoms
226 //
227 // The atom names and values are stored in nsHttpAtomList.h and are brought
228 // to you by the magic of C preprocessing. Add new atoms to nsHttpAtomList
229 // and all support logic will be auto-generated.
230 //
231 #define HTTP_ATOM(_name, _value) extern nsHttpAtom _name;
232 #include "nsHttpAtomList.h"
233 #undef HTTP_ATOM
234 } // namespace nsHttp
235
236 //-----------------------------------------------------------------------------
237 // utilities...
238 //-----------------------------------------------------------------------------
239
PRTimeToSeconds(PRTime t_usec)240 static inline uint32_t PRTimeToSeconds(PRTime t_usec) {
241 return uint32_t(t_usec / PR_USEC_PER_SEC);
242 }
243
244 #define NowInSeconds() PRTimeToSeconds(PR_Now())
245
246 // Round q-value to 2 decimal places; return 2 most significant digits as uint.
247 #define QVAL_TO_UINT(q) ((unsigned int)((q + 0.005) * 100.0))
248
249 #define HTTP_LWS " \t"
250 #define HTTP_HEADER_VALUE_SEPS HTTP_LWS ","
251
252 void EnsureBuffer(UniquePtr<char[]> &buf, uint32_t newSize, uint32_t preserve,
253 uint32_t &objSize);
254 void EnsureBuffer(UniquePtr<uint8_t[]> &buf, uint32_t newSize,
255 uint32_t preserve, uint32_t &objSize);
256
257 // h2=":443"; ma=60; single
258 // results in 3 mValues = {{h2, :443}, {ma, 60}, {single}}
259
260 class ParsedHeaderPair {
261 public:
262 ParsedHeaderPair(const char *name, int32_t nameLen, const char *val,
263 int32_t valLen, bool isQuotedValue);
264
ParsedHeaderPair(ParsedHeaderPair const & copy)265 ParsedHeaderPair(ParsedHeaderPair const ©)
266 : mName(copy.mName),
267 mValue(copy.mValue),
268 mUnquotedValue(copy.mUnquotedValue),
269 mIsQuotedValue(copy.mIsQuotedValue) {
270 if (mIsQuotedValue) {
271 mValue.Rebind(mUnquotedValue.BeginReading(), mUnquotedValue.Length());
272 }
273 }
274
275 nsDependentCSubstring mName;
276 nsDependentCSubstring mValue;
277
278 private:
279 nsCString mUnquotedValue;
280 bool mIsQuotedValue;
281
282 void RemoveQuotedStringEscapes(const char *val, int32_t valLen);
283 };
284
285 class ParsedHeaderValueList {
286 public:
287 ParsedHeaderValueList(const char *t, uint32_t len, bool allowInvalidValue);
288 nsTArray<ParsedHeaderPair> mValues;
289
290 private:
291 void ParseNameAndValue(const char *input, bool allowInvalidValue);
292 };
293
294 class ParsedHeaderValueListList {
295 public:
296 // RFC 7231 section 3.2.6 defines the syntax of the header field values.
297 // |allowInvalidValue| indicates whether the rule will be used to check
298 // the input text.
299 // Note that ParsedHeaderValueListList is currently used to parse
300 // Alt-Svc and Server-Timing header. |allowInvalidValue| is set to true
301 // when parsing Alt-Svc for historical reasons.
302 explicit ParsedHeaderValueListList(const nsCString &txt,
303 bool allowInvalidValue = true);
304 nsTArray<ParsedHeaderValueList> mValues;
305
306 private:
307 nsCString mFull;
308 };
309
310 } // namespace net
311 } // namespace mozilla
312
313 #endif // nsHttp_h__
314