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 &copy)
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