OLD | NEW |
---|---|
(Empty) | |
1 # Life of a URLRequest | |
2 | |
3 This document is intended as an overview of the core layers of the network | |
4 stack, their basic responsibilities, how they fit together, and where some of | |
5 the pain points are, without going into too much detail. Though it touches a | |
6 bit on the renderer process and the content/loader stack, the focus is on net/ | |
7 itself. | |
8 | |
9 It's particularly targeted at people new to the Chrome network stack, but | |
10 should also be useful for team members who may be experts at some parts of the | |
11 stack, but are largely unfamiliar with other components. It starts by walking | |
12 through how a basic request issued by Blink works its way through the network | |
13 stack, and then moves on to discuss how various components plug in. | |
14 | |
15 | |
16 # Anatomy of the Network Stack | |
17 | |
18 The main top-level network stack object is the URLRequextContext. The context | |
19 has non-owning pointers to everything needed to create and issue a URLRequest. | |
20 The context must outlive all requests that use it. Creating a context is a | |
21 rather complicated process, and it's recommended that most embedders use | |
22 URLRequestContextBuilder to do this. Chrome itself has several request | |
23 contexts that the network stack team owns: | |
24 | |
25 * The proxy URLRequestContext, owned by the IOThread and used to get PAC | |
26 scripts while avoiding re-entrancy. | |
27 * The system URLRequestContext, also owned by the IOThread, used for requests | |
28 that aren't associated with a profile. | |
29 * Each profile, including incognito profiles, has a number of URLRequestContexts | |
30 that are created as needed: | |
31 * The main URLRequestContext is mostly created in ProfileIOData, though it | |
32 has a couple components that are passed in from content's StoragePartition | |
33 code. Several other components are shared with the system URLRequestContext, | |
34 like the HostResolver. | |
35 * Each non-incognito profile also has a media request context, which uses a | |
36 different on-disk cache than the main request context. This prevents a | |
37 single huge media file from evicting everything else in the cache. | |
38 * On desktop platforms, each profile has a request context for extensions. | |
39 * Each profile has two contexts for each isolated app (One for media, one | |
40 for everything else). | |
41 | |
42 The "HttpNetworkSession" is another major network stack object. It has | |
xunjieli
2015/07/10 20:32:26
nit: I think the quotes can be removed, since quot
mmenke
2015/07/10 21:37:32
Done.
| |
43 pointers to the network stack objects that more directly deal with sockets, and | |
44 their dependendencies. Its main objects are the HttpStreamFactory, the socket | |
45 pools, and the SPDY/QUIC session pools. | |
46 | |
47 This document does not mention either of these objects much, but at layers | |
48 above the HttpStreamFactory, objects often grab their dependencies from the | |
49 URLRequestContext, while the HttpStreamFactory and layers below it generally | |
50 get their dependencies from the HttpNetworkSession. | |
51 | |
52 | |
53 # How many "Delegates"? | |
54 | |
55 The network stack informs the embedder of important events for a request using | |
56 two main interfaces: The URLRequest::Delegate interface and the NetworkDelegate | |
xunjieli
2015/07/10 20:32:26
nit: lowercase "The" after the colon.
mmenke
2015/07/10 21:37:32
Done.
| |
57 interface. | |
58 | |
59 The URLRequest::Delegate interface consists of small set callbacks needed to let | |
xunjieli
2015/07/10 20:32:26
[a] small set [of] callbacks?
mmenke
2015/07/10 21:37:32
Done.
| |
60 the embedder drive a request forward. URLRequest::Delegates generally own the | |
61 URLRequest. | |
62 | |
63 The NetworkDelegate is a single object shared by all requests, and includes | |
64 callbacks corresponding to most of the URLRequest::Delegate's callbacks, as well | |
65 as an assortment of other methods. The NetworkDelegate is optional, the | |
xunjieli
2015/07/10 20:32:26
nit: Add a conjunction in "The NetworkDelegate is
mmenke
2015/07/10 21:37:31
Done.
| |
66 URLRequest::Delegate is not. | |
67 | |
68 | |
69 # Overview | |
70 | |
71 A request for data is normally dispatched from the renderer to the browser | |
72 process. There a URLRequest is created to drive the request. A | |
73 protocol-specific job (e.g. HTTP, data, file) is attached to the request. That | |
74 job first checks the cache, and then creates a network connection, if necessary, | |
75 to actually fetch the data. That connection object interacts with network socket | |
76 pools to potentially re-use sockets; the socket pools create and connect a | |
77 socket if there is no appropriate existing socket. Once that socket exists, the | |
78 HTTP request is dispatched, the response read and parsed, and the result | |
79 returned back up the stack and sent over to the renderer. | |
80 | |
81 Of course, it's not quite that simple :-}. | |
82 | |
83 Consider a simple request issued by the renderer process. Suppose it's an HTTP | |
84 request, the response is uncompressed, and no matching entry in the cache. | |
85 | |
86 ### Request Starts in a Child Process | |
xunjieli
2015/07/10 20:32:26
I find it a bit confusing that this doc mentioned
mmenke
2015/07/10 21:37:32
That's right.
| |
87 | |
88 * ResourceDispatcher to creates an IPCResourceLoaderBridge. | |
xunjieli
2015/07/10 20:32:26
nit: remove "to".
mmenke
2015/07/10 21:37:32
Done.
| |
89 * The IPCResourceLoaderBridge asks ResourceDispatcher to start the request. | |
90 * ResourceDispatcher sends an IPC to the ResourceDispatcherHost in the | |
91 browser process. | |
92 | |
93 ### ResourceDispatcherHost set up the request in the Browser Process | |
94 | |
95 * ResourceDispatcherHost uses the URLRequestContext to create the URLRequest. | |
96 * ResourceDispatcherHost creates a ResourceLoader and ResourceHandler chain to | |
xunjieli
2015/07/10 20:32:26
nit: and [a] ResourceHandler chain.
(It reads as i
mmenke
2015/07/10 21:37:31
Done, and rephrased to hopefully be clearer.
| |
97 manage the URLRequest. | |
98 * ResourceLoader starts the URLRequest. | |
99 | |
100 ### Check the Cache, Request an HttpStream | |
101 | |
102 * The URLRequest asks the URLRequestJobFactory to create a URLRequestJob, | |
103 usually a URLRequestHttpJob for HTTP/HTTPS requests. | |
104 * The URLRequestHttpJob asks the HttpCache to create an HttpTransaction | |
105 (always an HttpCache::Transaction). | |
106 * The HttpCache::Transaction sees there's no cache entry for the request, | |
107 and creates an HttpNetworkTransaction. | |
108 * The HttpNetworkTransaction calls into the HttpStreamFactory to request an | |
109 HttpStream. | |
110 | |
111 ### Create an HttpStream | |
112 * HttpStreamFactory creates an HttpStreamFactoryImpl::Job. | |
113 * HttpStreamFactoryImpl::Job calls into the TransportClientSocketPool to | |
114 populate an ClientSocketHandle. | |
115 * TransportClientSocketPool has no idle sockets, so it creates a | |
116 TransportConnectJob and starts it. | |
117 * TransportConnectJob creates a StreamSocket and establishes a connection. | |
118 * TransportClientSocketPool puts the StreamSocket in the ClientSocketHandle, | |
119 and calls into HttpStreamFactoryImpl::Job. | |
120 * HttpStreamFactoryImpl::Job creates an HttpBasicStream, which takes | |
121 ownership of the ClientSocketHandle. | |
122 * It returns the HttpBasicStream to the HttpNetworkTransaction. | |
123 | |
124 ### Send request and read the response headers | |
125 | |
126 * HttpNetworkTransaction gives the request headers to the HttpBasicStream, | |
127 and tells it to start the request. | |
128 * HttpBasicStream sends the request, and waits for the response. | |
129 * The HttpBasicStream sends the response headers back to the | |
130 HttpNetworkTransaction. | |
131 * The response headers are sent up to the URLRequest, to the ResourceLoader, | |
132 through the ResourceHandler stack. | |
xunjieli
2015/07/10 20:32:26
nit: I would replace "stack" with "chain" so there
mmenke
2015/07/10 21:37:32
Done.
| |
133 * They're then sent by the AsyncResourceHandler to the ResourceDispatcher. | |
xunjieli
2015/07/10 20:32:26
I got confused by the sudden mention of AsyncResou
mmenke
2015/07/10 21:37:32
Clarified that the AsyncResourceHandler is the las
| |
134 | |
135 ### Response body is read | |
136 | |
137 * AsyncResourceHandler allocates a 512k ring buffer of shared memory to read | |
138 the body of the request. | |
139 * AsyncResourceHandler tells the ResourceLoader to read the response body to | |
140 the buffer, 32kB at a time. | |
141 * AsyncResourceHandler informs the ResourceDispatcher of each read. | |
xunjieli
2015/07/10 20:32:26
How does AsyncResourceHandler inform the ResourceD
mmenke
2015/07/10 21:37:32
Done.
| |
142 * ResourceDispatcher tells the AsyncResourceHandler when it's done with the | |
143 data with each read, so it knows when parts of the buffer can be reused. | |
144 | |
145 ### URLRequest is Destroyed | |
xunjieli
2015/07/10 20:32:26
nit: s/Destroyed/destroyed.
I think we should sti
mmenke
2015/07/10 21:37:32
Done to all the "###" titles (Hrm, I was really in
| |
146 | |
147 * When complete, the RDH deletes the ResourceLoader, which deletes the | |
xunjieli
2015/07/10 20:32:26
Does the chain of ResourceHandlers also get delete
mmenke
2015/07/10 21:37:32
Done.
| |
148 URLRequest. | |
149 * During destruction, the HttpNetworkTransaction determines if the socket is | |
150 reusable, and if so, tells the HttpBasicStream to return it to the socket pool. | |
151 | |
152 # Details | |
xunjieli
2015/07/10 20:32:26
I thought the life of a url is ended, because I di
| |
153 | |
154 Continuing with a "simple" URLRequest, here's a bit more detail on how things | |
155 work. | |
156 | |
157 ### Request Starts in a Child Process | |
158 | |
159 Each child process has at most one ResourceDispatcher, which is responsible for | |
160 all URL request-related communication with the browser process. When something | |
161 in the renderer needs to issue a resource request, it calls into the | |
162 ResourceDispatcher, which returns an IPCResourceLoaderBridge to the caller. | |
163 The caller uses the bridge to start a request. When started, the | |
164 ResourceDispatcher assigns the request a per-renderer ID, and then sends the | |
165 ID, along with all information needed to issue the request, to the | |
166 ResourceDispatcherHost in the browser process. | |
167 | |
168 ### ResourceDispatcherHost set up the request in the Browser Process | |
169 | |
170 The ResourceDispatcherHost (RDH), along with most of the network stack, lives | |
171 on the browser process's IO thread. The browser process only has one RDH, | |
172 which is responsible for handling all network requests initiated by | |
173 ResourceDispatchers in all child processes, not just renderer process. | |
174 Browser-initiated don't go through the RDH, with some exceptions. | |
xunjieli
2015/07/10 20:32:26
nit: s/"Browser-initiated"/"requests initiated by
mmenke
2015/07/10 21:37:32
Done.
| |
175 | |
176 When the RDH sees the request, it calls into a URLRequestContext to create the | |
177 URLRequest. The URLRequestContext has pointers to all the network stack | |
178 objects needed to issue the request over the network, such as the cache, cookie | |
179 store, and host resolver. The RDH then creates a chain of ResourceHandlers | |
180 each of which can monitor/modify/delay/cancel the URLRequest and the | |
181 information it returns. The only one of these I'll talk about here is the | |
182 AsyncResourceHandler, which is the last ResourceHandler in the chain. The RDH | |
183 then creates a ResourceLoader (Which is the URLRequest::Delegate), passes | |
184 ownership of the URLRequest and the ResourceHandler chain to it, and then starts | |
185 the ResourceLoader. | |
186 | |
187 The ResourceLoader checks that none of the ResourceHandlers want to cancel, | |
188 modify, or delay the request, and then finally starts the URLRequest. | |
189 | |
190 ### Check the Cache, Request an HttpStream | |
191 | |
192 The URLRequest then calls into the URLRequestJobFactory to create a | |
193 URLRequestJob and then starts it. In the case of an HTTP or HTTPS request, this | |
194 will be a URLRequestHttpJob. The URLRequestHttpJob attaches cookies to the | |
195 request, if needed. | |
196 | |
197 The URLRequestHttpJob calls into the HttpCache to create an | |
198 HttpCache::Transaction. If there's no matching entry in the cache, the | |
199 HttpCache::Transaction will just call into the HttpNetworkLayer to create an | |
200 HttpNetworkTransaction, and transparently wrap it. The HttpNetworkTransaction | |
201 then calls into the HttpStreamFactory to request an HttpStream to the server. | |
202 | |
203 ### Create an HttpStream | |
204 | |
205 The HttpStreamFactoryImpl::Job creates a ClientSocketHandle to hold a socket, | |
206 once connected, and passes it into the ClientSocketPoolManager. The | |
207 ClientSocketPoolManager assembles the TransportSocketParams needed to | |
208 establish the connection and creates a group name ("host:port") used to | |
209 identify sockets that can be used interchangeably. | |
210 | |
211 The ClientSocketPoolManager directs the request to the | |
212 TransportClientSocketPool, since there's no proxy and it will be using | |
213 HTTP/1.x. The pool sends it on to the | |
214 ClientSocketPoolBase<TransportSocketParams> it wraps, which sends it on to its | |
xunjieli
2015/07/10 20:32:26
I am not 100% sure on what the three "it" refer to
mmenke
2015/07/10 21:37:32
Good point. Removed almost all the its.
| |
215 ClientSocketPoolBaseHelper. If there isn't already an idle connection, and there | |
216 are available socket slots, the ClientSocketPoolBaseHelper will create a new | |
217 TransportConnectJob using the aforementioned params object. This Job will do the | |
218 actual DNS lookup by calling into the HostResolverImpl, if needed, and then | |
219 finally establish a connection. | |
220 | |
221 Once the socket is connected, ownership of the socket is passed to the | |
222 ClientSocketHandle. The HttpStreamFactoryImpl::Job is then informed the | |
223 connection attempt succeeded, and it then creates an HttpBasicStream, which | |
224 takes ownership of the ClientSocketHandle. It then passes ownership of the | |
225 HttpBasicStream back to the HttpNetworkTransaction. | |
226 | |
227 ### Send request and read the response headers | |
228 | |
229 The Transaction passes the request headers to the HttpBasicStream, which uses an | |
230 HttpStreamParser to (finally) format the request headers and body (if present) | |
231 and send them to the server. | |
232 | |
233 The HttpStreamParser waits to receive the response and then parses the HTTP/1.x | |
234 response headers, and then passes them up through both Transaction classes | |
xunjieli
2015/07/10 20:32:26
nit: I'd spell out what these two Transaction clas
mmenke
2015/07/10 21:37:32
Done.
| |
235 to the URLRequestHttpJob. The URLRequestHttpJob saves any cookies, if needed, | |
236 and then passes the headers up to the URLRequest and on to the ResourceLoader. | |
237 | |
238 The ResourceLoader passes them through the chain of ResourceHandlers, and then | |
239 they make their way to the AsyncResourceHandler. The AsyncResourceHandler uses | |
240 the renderer process ID ("child ID") to figure out which process the request | |
241 was associated with, and then sends the headers along with the request ID to | |
242 that process's ResourceDispatcher. The ResourceDispatcher uses the ID to | |
243 figure out which IPCResourceLoaderBridge the headers should be sent to, which | |
244 sends them on to whatever created the IPCResourceLoaderBridge in the first | |
245 place. | |
246 | |
247 ### Response body is read | |
248 | |
249 Without waiting to hear back from the ResourceDispatcher, the ResourceLoader | |
250 tells its ResourceHandler chain to allocate memory to receive the response | |
251 body. The AsyncResourceHandler creates a 512KB ring buffer of shared memory, | |
252 and then passes the first 32KB of it to the ResourceLoader for the first read. | |
253 The ResourceLoader then passes a 32KB body read request down through the | |
254 URLRequest all the way down to the HttpResponseParser. Once some data is read, | |
255 possibly less than 32KB, the number of bytes read makes its way back to the | |
256 AsyncResourceHandler, which passes the shared memory buffer and the offset and | |
257 amount of data read to the renderer process. | |
258 | |
259 The AsyncResourceHandler relies on ACKs from the renderer to prevent it from | |
260 overwriting data that the renderer has yet to consume. This process repeats | |
261 until the response body is completely read. | |
262 | |
263 ### URLRequest is destroyed | |
264 | |
265 When the URLRequest informs the ResourceLoader it's complete, the | |
266 ResourceLoader tells the ResourceHandlers, and the AsyncResourceHandler tells | |
267 the ResourceDispatcher the request is complete. The RDH then deletes | |
268 ResourceLoader, which deletes the URLRequest. | |
xunjieli
2015/07/10 20:32:27
nit: I'd mention what happens to the chain of Reso
mmenke
2015/07/10 21:37:32
Done.
| |
269 | |
270 When the HttpNetworkTransaction is being torn down, it figures out if the | |
271 socket is reusable. If not, it tells the HttpBasicStream to close the socket. | |
272 Either way, the ClientSocketHandle returns the socket is then returned to the | |
273 socket pool, either for reuse or so the socket pool knows it has another free | |
274 socket slot. | |
275 | |
276 | |
277 # Additional Topics | |
278 | |
279 ## HTTP Cache | |
280 | |
281 The HttpCache::Transaction sits between the URLRequestHttpJob and the | |
282 HttpNetworkTransaction, and implements the HttpTransaction interface, just like | |
283 the HttpNetworkTransaction. The HttpCache::Transaction checks if a request can | |
284 be served out of the cache. If a request needs to be revalidated, it handles | |
285 sending a 204 revalidation request over the network. It may also break a range | |
286 request into multiple cached and non-cached contiguous chunks, and may issue | |
287 multiple network requests for a single range URLRequest. | |
288 | |
289 One important detail is that it has a read/write lock for each URL. The lock | |
290 technically allows multiple reads at once, but since an HttpCache::Transaction | |
291 always grabs the lock for writing and reading before downgrading it to a read | |
292 only lock, all requests for the same URL are effectively done serially. Blink | |
293 merges requests for the same URL in many cases, which mitigates this problem to | |
294 some extent. | |
295 | |
296 The HttpCache::Transaction uses one of three disk_cache::Backends to actually | |
297 store the cache's index and files: The in memory backend, the blockfile cache | |
298 backend, and the simple cache backend. The first is used in incognito. The | |
299 latter two are both stored on disk, and are used on different platforms. | |
300 | |
301 ## Cancellation | |
302 | |
303 A request can be cancelled by the renderer process Blink or by any of the | |
xunjieli
2015/07/10 20:32:26
Why is the "renderer process" called Blink? I thou
mmenke
2015/07/10 21:37:32
Removed the Blink (Was supposed to be "Blink in th
| |
304 ResourceHandlers through the ResourceLoader. When the cancellation message | |
xunjieli
2015/07/10 20:32:26
nit: maybe add the word "chain" here?
e.g. any Re
mmenke
2015/07/10 21:37:32
Done.
| |
305 reaches the URLRequest, it passes on the fact it's been cancelled back to the | |
306 ResourceLoader, which then sends the message down the ResourceHandler chain. | |
307 | |
308 When an HttpNetworkTransaction for a cancelled request is being torn down, it | |
309 figures out if the socket the HttpStream owns can potentially be reused, based | |
310 on the protocol (HTTP / SPDY / QUIC) and any received headers. If the socket | |
311 potentially can be reused, an HttpResponseBodyDrainer is created to try and | |
312 read any remaining body bytes of the HttpStream, if any, before returning the | |
313 socket to the SocketPool. If this takes too long, or there's an error, the | |
314 socket is closed instead. Since this all happens at the layer below the cache, | |
315 any drained bytes are not written to the cache, and as far as the cache layer is | |
316 concerned, it only has a partial response. | |
317 | |
318 ## Redirects | |
319 | |
320 The URLRequestHttpJob checks if headers indicate a redirect when it receives | |
321 them from the next layer down (Typically the HttpCache::Transaction). If they | |
322 indicate a redirect, it tells the cache the response is complete, ignoring the | |
323 body, so the cache only has the headers. The cache then treats it as a complete | |
324 entry, even if the headers indicated there will be a body. | |
325 | |
326 The URLRequestHttpJob then checks if the URLRequest if the request should be | |
327 followed. First it checks the scheme. Then it informs the ResourceLoader | |
328 about the redirect, to give it a chance to cancel the request. The information | |
329 makes its way down through the AsyncResourceHandler to the ResourceDispatcher | |
330 and on into Blink, which checks if the redirect should be followed. | |
331 | |
332 The ResourceDispatcher then asynchronously sends a message back to either | |
333 follow the redirect or cancel the request. In either case, the old | |
334 HttpTransaction is destroyed, and the HttpNetworkTransaction attempts to drain | |
335 the socket for reuse, just as in the cancellation case. If the redirect is | |
336 followed, the URLRequest calls into the URLRequestJobFactory to create a new | |
337 URLRequestJob, and then starts it. | |
338 | |
339 ## Filters (gzip, SDCH, etc) | |
340 | |
341 When the URLRequestHttpJob receives headers, it sends a list of all Content- | |
342 Encoding values to Filter::Factory, which creates a (possibly empty) chain of | |
xunjieli
2015/07/10 20:32:26
nit: I think there is a space between the dash and
mmenke
2015/07/10 21:37:32
Done.
| |
343 filters. As body bytes are received, they're passed through the filters at the | |
344 URLRequestJob layer and the decoded bytes are passed back to the embedder. | |
345 | |
346 Since this is done above the cache layer, the cache stores the responses prior | |
347 to decompression. As a result, if files aren't compressed over the wire, they | |
348 aren't compressed in the cache, either. This behavior can also create problems | |
349 when responses are SDCH compressed, as a dictionary and a cached file encoded | |
350 using it may have different lifetimes. | |
351 | |
352 ## Socket Pools | |
353 | |
354 The ClientSocketPoolManager is responsible for assembling the parameters needed | |
355 to connect a socket, and then sending the request to the right socket pool. | |
356 Each socket request sent to a socket pool comes with a socket params object, a | |
357 ClientSocketHandle, and a "group name". The params object contains all the | |
358 information a ConnectJob needs to create a connection of a given type, and | |
359 different types of socket pools take different params types. The | |
360 ClientSocketHandle will take temporary ownership of the socket, once connected | |
361 socket, and return it to the socket pool when done. All connections with the | |
362 same group name in the same pool can be used to service the same connection | |
363 request, so it consists of host, port, protocol, and whether "privacy mode" is | |
364 used for requests using the socket or not. | |
365 | |
366 All socket pool classes derive from the ClientSocketPoolBase<SocketParamType>. | |
367 The ClientSocketPoolBase handles managing sockets - which requests to create | |
368 sockets for, which requests get connected sockets first, which sockets belong | |
369 to which groups, connection limits per group, keeping track of and closing idle | |
370 sockets, etc. Each ClientSocketPoolBase subclass has its own ConnectJob type, | |
371 which establishes a connection using the socket params, before the pool hands | |
372 out the connected socket. | |
373 | |
374 ## Socket Pool Layering | |
375 | |
376 Some socket pools are layered on top other socket pools. This is done when a | |
377 "socket" in a higher layer needs to establish a connection in a lower level | |
378 pool and then take ownership of it as part of its connection process. See later | |
379 sections for examples. There are a couple additional complexities here. | |
380 | |
381 From the perspective of the lower layer pool, all of its sockets that a higher | |
382 layer pools owns are actively in use, even when the higher layer pool considers | |
383 them idle. As a result, when a lower layer pool is at its connection limit and | |
384 needs to make a new connection, it will ask any higher layer pools pools to | |
385 close an idle connection if they have one, so it can make a new connection. | |
386 | |
387 Sockets in the higher layer pool must have their own distinct group name in the | |
xunjieli
2015/07/10 20:32:26
This sentence is a bit hard to understand. Conside
mmenke
2015/07/10 21:37:32
Tried to make it a bit clearer.
| |
388 lower layer pool as well. This is needed so the lower layer pool won't, for | |
389 example, group SSL and HTTP connections to the same port together. | |
390 | |
391 ## SSL | |
392 | |
393 When an SSL connection is needed, the ClientSocketPoolManager assembles the | |
394 parameters needed both to connect the TCP socket and establish an SSL | |
395 connection. It then passes them to the SSLClientSocketPool, which creates | |
396 an SSLConnectJob using them. The SSLConnectJob's first step is to call into the | |
397 TransportSocketPool to establish a TCP connection. | |
398 | |
399 Once a connection is established by the lower layered pool, the SSLConnectJob | |
400 then starts SSL negotiation. Once that's done, the SSL socket is passed back to | |
401 the HttpStreamFactoryImpl::Job that initiated the request, and things proceed | |
402 just as with HTTP. When complete, the socket is returned to the | |
403 SSLClientSocketPool. | |
404 | |
405 ## Proxies | |
406 | |
407 The first step the HttpStreamFactoryImpl::Job performs, just before calling | |
408 into the ClientSocketPoolManager to create a socket, is to check with the | |
409 ProxyService to see if a proxy is needed for the URL it's been given. The | |
410 ClientSocketPoolManager then uses this information to find the correct proxy | |
411 socket pool to send the request to. | |
412 | |
413 TODO(mmenke): Discuss proxy configurations, WPAD, tracing proxy resolver. | |
414 | |
415 ## Proxy Socket Pools | |
416 | |
417 Each SOCKS or HTTP proxy has its own completely independent set of socket | |
418 pools. They have their own exclusive TransportSocketPool, their own protocol- | |
419 specific pool above it, and their own SSLSocketPool above that. HTTPS proxies | |
420 also have a second SSLSocketPool between the the HttpProxyClientSocketPool and | |
421 the TransportSocketPool, since they can talk SSL to both the proxy and the | |
422 destination server, layered on top of each other. | |
423 | |
424 ## SPDY | |
425 | |
426 Once an SSL connection is established, the HttpStreamFactoryImpl::Job checks if | |
427 SPDY was negotiated over the socket. If so, it creates a SpdySession using the | |
428 socket, and a SpdyHttpStream. The SpdyHttpStream will be passed to the | |
429 HttpNetworkTransaction, which drives the stream as usual. | |
430 | |
431 The SpdySession will be shared with other Jobs connecting to the same server, | |
432 and future Jobs will find the SpdySession before they try to create a | |
433 connection. HttpServerProperties also tracks which servers supported SPDY when | |
434 we last talked to them. We only try to establish a single connection to servers | |
435 we think speak SPDY when multiple HttpStreamFactoryImpl::Jobs are trying to | |
436 connect to them, to avoid wasting resources. | |
437 | |
438 ## QUIC | |
439 | |
440 HttpServerProperties also tracks which servers have advertised QUIC support in | |
441 the past. If a server has advertised QUIC support, a second | |
442 HttpStreamFactoryImpl::Job will be created for SPDY, and will be raced against | |
443 the one for HTTP/HTTPS connection. Whichever connects first will be used. | |
444 Existing QUIC sessions will be reused if available. | |
445 | |
446 TODO(mmenke): Discuss SPDY/QUIC proxies? | |
447 | |
448 ## Prioritization | |
449 | |
450 URLRequests are assigned a priority on creation. It only comes into play in | |
451 a couple places: | |
452 | |
453 * The ResourceScheduler lives outside net/, and in some cases, delays starting | |
454 low priority requests on a per-tab basis. | |
455 * DNS lookups are initiated based on the highest priority request for a lookup. | |
456 * Socket pools hand out and create sockets on prioritization. However, idle | |
457 sockets will be assigned to low priority requests in preference to creating new | |
458 sockets for higher priority requests. | |
xunjieli
2015/07/10 20:32:26
I don't understand this sentence.
Do you instead
mmenke
2015/07/10 21:37:31
No...If we have no free socket slots, and a high p
| |
459 * SPDY and QUIC both support sending priorities over-the-wire. | |
460 | |
461 At the socket pool layer, sockets are only assigned to socket requests once the | |
462 socket is connected and SSL is negotiated, if needed. This is done so that if | |
463 a higher priority request for a group reaches the socket pool before a | |
464 connection is established, the first usable connection goes to the highest | |
465 priority socket request. | |
466 | |
467 ## Non-HTTP schemes | |
468 | |
469 The URLRequestJobFactory has a ProtocolHander for each supported scheme. | |
470 Non-HTTP URLRequests have their own ProtocolHandlers. Some are implemented in | |
471 net/, (like FTP, file, and data, though blink handles some data URLs | |
472 internally), and others are implemented in content/ or chrome (like blob, | |
473 chrome, and chrome-extension). | |
OLD | NEW |