Socket for Chrome source code analysis (1)

Source: Internet
Author: User

 
As an analysis of HTTP connections, we first track the process of chrome processing a new URL request.
 
From the chrome implementation perspective, requests to a URL resource are implemented in the browser process, rather than by various render processes, it is said that the development documents mentioned three main advantages of doing so. One is to avoid network communication between sub-processes and increase security, and the other is to facilitate sharing of cookie and other persistent resources on different pages, otherwise, it is troublesome to pass cookies in different render processes. The third is that the browser can perform unified network communication to reduce the number of HTTP connections.
Generally, after you enter the URL address in the address bar and press enter to confirm, because autocompleteeditviewwin inherits from the cricheditctrl class of ATL, it also has the message ing capability. Under the Control of message ing, in the end, the onkeydownonlywritable function is called. The switch in onkeydownonlywritable processes various buttons separately. If it is a carriage return key, model _-> acceptinput is called, this function requires some simple judgment on the input URL address. Because the call process in the middle is long, we will not analyze each function here, but only list the call process:
SRC \ chrome \ browser \ AutoComplete \ autocomplete_edit.cc # 351view _-> Openurl
SRC \ chrome \ browser \ AutoComplete \ autocomplete_edit_view_win.cc #612 model _-> Openurl
SRC \ chrome \ browser \ AutoComplete \ autocomplete_edit.cc #612 model _-> Openurl,
SRC \ chrome \ browser \ AutoComplete \ autocomplete_edit.cc #412 controller _-> onautocompleteaccept.
SRC \ chrome \ browser \ views \ location_bar \ location_bar_view.cc #791 command_updater _-> executecommand (idc_open_current_url );
SRC \ chrome \ browser \ command_updater.cc #45 delegate _-> executecommand (ID );
SRC \ chrome \ browser. CC #2318 executecommandwithdisposition (ID, current_tab );
SRC \ chrome \ browser. CC #1245 Browser: navigate (& Params );
SRC \ chrome \ browser \ browser_navigator.cc #324 Params-> target_contents-> controller (). loadurl
SRC \ chrome \ browser \ tab_contents \ navigation_controller.cc #496 loadentry (entry );
SRC \ chrome \ browser \ tab_contents \ navigation_controller.cc #282 navigatetopendingentry (no_reload );
SRC \ chrome \ browser \ tab_contents \ navigation_controller.cc #1039 tab_contents _-> navigatetopendingentry (reload_type)
SRC \ chrome \ browser \ tab_contents \ tab_contents.cc #853 navigatetoentry (* controller _. pending_entry (), reload_type );
SRC \ chrome \ browser \ tab_contents \ tab_contents.cc #891 dest_render_view_host-> navigate (navigate_params );
SRC \ chrome \ browser \ renderer_host \ render_view_host.cc #250 send (nav_message );
Let's take a look at the last two rows: dest_render_view_host-> navigate (navigate_params); In the tabcontents: navigatetoentry function, dest_render_view_host is a pointer that calls render_manager _. in the chrome process model, the browser Process manages other processes and pages. A process is an renderprocesshost instance, and a page is a renderviewhost instance. The page is actually hosted on renderprocess, and a renderprocess can have multiple renderviews. Render_manager _ is the class responsible for managing renderviewhost in tabcontents. Here it returns an available renderviewhost instance. renderviewhost collects all information related to this URL request, generate a message and send it to the renderprocess through the IPC Mechanism. function calls before sending occur in the mainthread of the browser process, when a message needs to be sent to renderprocess, it enters the I/O
Thread field. As for the IPC Mechanism, we will leave it for later analysis.
After a message is sent, the renderthread and renderview of the renderprocess receive the message. The message is first classified and routed in the renderprocess, and then transmitted to the renderview
The onmessagereceived function continues to list the process below:
SRC \ chrome \ Renderer \ render_view.cc #764 ipc_message_handler (viewmsg_navigate, onnavigate)
SRC \ chrome \ Renderer \ render_view.cc #1226 main_frame-> loadrequest (request );
SRC \ third_party \ WebKit \ chromium \ SRC \ webframeimpl. cpp #883 m_frame-> loader ()-> load (resourcerequest, false );
SRC \ third_party \ WebKit \ WebCore \ loader \ frameloader. cpp #1362 load (request, substitutedata (), lockhistory );
SRC \ third_party \ WebKit \ WebCore \ loader \ frameloader. cpp #1375 load (loader. Get ());
SRC \ third_party \ WebKit \ WebCore \ loader \ frameloader. cpp #1433 loadwithdocumentloader (newdocumentloader, type, 0 );
SRC \ third_party \ WebKit \ WebCore \ loader \ frameloader. cpp #1477 continueloadafternavigationpolicy (loader-> request (), formstate, false );
SRC \ third_party \ WebKit \ WebCore \ loader \ frameloader. cpp #2975 continueloadafterwillsubmitform ();
SRC \ third_party \ WebKit \ WebCore \ loader \ frameloader. cpp #2463 m_provisionaldocumentloader-> startloadingmainresource (identifier)
SRC \ third_party \ WebKit \ WebCore \ loader \ documentloader. cpp #765 m_mainresourceloader-> load (m_request, m_substitutedata)
SRC \ third_party \ WebKit \ WebCore \ loader \ mainresourceloader. cpp #583 loadnow (request)
SRC \ third_party \ WebKit \ WebCore \ loader \ mainresourceloader. cpp #556 resourcehandle: Create
SRC \ third_party \ WebKit \ chromium \ SRC \ resourcehandle. cpp #223 newhandle-> Start (context)
SRC \ third_party \ WebKit \ chromium \ SRC \ resourcehandle. cpp #251 D-> Start ();
SRC \ third_party \ WebKit \ chromium \ SRC \ resourcehandle. cpp #111 m_loader-> loadasynchronously (wrappedrequest, this );
SRC \ WebKit \ glue \ weburlloader_impl.cc #717 context _-> Start (request, null );
SRC \ WebKit \ glue \ weburlloader_impl.cc #476 bridge _-> Start (this)
SRC \ chrome \ common \ resource_dispatcher.cc #186 dispatcher _-> message_sender ()-> send
Here, the page rendering request is encapsulated as a message through the IPC Mechanism and sent to the browser process. Of course, the code is still executed on renderthread before calling dispatcher _-> message_sender ()-> send, but the message is actually sent in mainthread, the cause is further analyzed in the IPC Mechanism.
As the browser process that receives the message, the message is first processed in I/O thrad and then forwarded to mainthread. mainthread then processes the message and maps it to the onmessagereceived function of resourcedispatcherhost.

SRC \ chrome \ browser \ renderer_host \ resource_dispatcher_host.cc #542 beginrequestinternal (request );
SRC \ chrome \ browser \ renderer_host \ resource_dispatcher_host.cc #1310 insertintoresourcequeue (request, * info );
SRC \ chrome \ browser \ renderer_host \ resource_dispatcher_host.cc #1316 resource_queue _. addrequest (request, request_info );
SRC \ chrome \ browser \ renderer_host \ resource_queue.cc #62 request-> Start ();
SRC \ net \ url_request \ url_request.cc #307 startjob (getjobmanager ()-> createjob (this ));
SRC \ net \ url_request \ url_request.cc #336 job _-> Start ();
SRC \ net \ url_request \ url_request_http_job.cc #159 addcookieheaderandstart ();
SRC \ net \ url_request \ url_request_http_job.cc #739 oncangetcookiescompleted (policy );
SRC \ net \ url_request \ url_request_http_job.cc #460 starttransaction ();
SRC \ net \ url_request \ url_request_http_job.cc #632 transaction _-> Start
SRC \ net \ HTTP \ http_network_transaction.cc #144 doloop (OK );
SRC \ net \ HTTP \ http_network_transaction.cc #446 docreatestream ();
SRC \ net \ HTTP \ http_network_transaction.cc #449 docreatestreamcomplete (RV );
SRC \ net \ HTTP \ http_network_transaction.cc #456 doinitstreamcomplete (RV );
SRC \ net \ HTTP \ http_network_transaction.cc #463 dogenerateproxyauthtokencomplete (RV );
SRC \ net \ HTTP \ http_network_transaction.cc #470 dogenerateserverauthtokencomplete (RV );
SRC \ net \ HTTP \ http_network_transaction.cc #475 dosendrequest ();
SRC \ net \ HTTP \ http_network_transaction.cc #646 stream _-> sendrequest
SRC \ net \ HTTP \ http_basic_stream.cc #48 parser _-> sendrequest
SRC \ net \ HTTP \ http_stream_parser.cc #63 doloop (OK)
SRC \ net \ HTTP \ http_stream_parser.cc #145 dosendheaders (result );
SRC \ net \ HTTP \ http_stream_parser.cc #228 connection _-> socket ()-> write
 
The request-> Start () function goes to the network communication section and starts detailed analysis from connection _-> socket ()-> write.
Here, the write call is actually a member function of the tcpclientsocketwin class. The three parameters passed in by the function are sending the cache Buf, the cache length buf_len, And the callback function pointer callback.
 
Use the following code to save the sent data.
 
Core _-> write_buffer _. Len = buf_len;
Core _-> write_buffer _. Buf = Buf-> data ();
Core _-> write_buffer_length _ = buf_len;
Core _ is a member variable of tcpclientsocketwin. It is actually a class that plays this core role in the process of reading and writing network data in tcpclientsocketwin. Let's first look at the definition of core:
Class tcpclientsocketwin: CORE: public base: refcounted <core> {
Public:
Explicit core (tcpclientsocketwin * socket );
Void watchforread ();
Void watchforwrite ();
Void detach () {socket _ = NULL ;}
Overlapped read_overlapped _;
Overlapped write_overlapped _;
Wsabuf read_buffer _;
Wsabuf write_buffer _;
Scoped_refptr <iobuffer> read_iobuffer _;
Scoped_refptr <iobuffer> write_iobuffer _;
Int write_buffer_length _;
Int throttlereadsize (INT size ){
If (slow_start_throttle _ <kmaxslowstartthrottle ){
Size = STD: min (size, slow_start_throttle _);
Slow_start_throttle _ * = 2;
}
Return size;
}
PRIVATE:
Friend class base: refcounted <core>;
Class readdelegate: public base: objectwatcher: Delegate {
Public:
Explicit readdelegate (core * CORE): core _ (CORE ){}
Virtual ~ Readdelegate (){}
Virtual void onobjectsignaled (handle object );
PRIVATE:
Core * const core _;
};
Class writedelegate: public base: objectwatcher: Delegate {
Public:
Explicit writedelegate (core * CORE): core _ (CORE ){}
Virtual ~ Writedelegate (){}
Virtual void onobjectsignaled (handle object );
PRIVATE:
Core * const core _;
};
~ Core ();
Tcpclientsocketwin * socket _;
Readdelegate reader _;
Writedelegate writer _;
Base: objectwatcher read_watcher _;
Base: objectwatcher write_watcher _;
Static const int kinitialslowstartthrottle = 1*1024;
Static const int kmaxslowstartthrottle = 32 * kinitialslowstartthrottle;
Int slow_start_throttle _;
Disallow_copy_and_assign (CORE );
};
In general, the function of core-like is to provide and coordinate all relevant event objects for the TCP Connection Based on Event Notification asynchronous I/O, and send and receive caches, thread Pool control and callback processing. Overlapped read_overlapped _ and overlapped write_overlapped _ are the overlapping I/O control variables for read and write respectively, and wsabuf read_buffer _ and wsabuf write_buffer _ maintain the Read and Write cache.

The core also defines two private classes in the class body: Class readdelegate: public base: objectwatcher: Delegate and class writedelegate: public base: objectwatcher: Delegate. Both classes have only one member function onobjectsignaled, which will be called in the message loop of chrome self-built threads. As for why onobjectsignaled is called, this is followed by the other two member variables base: objectwatcher read_watcher _ and base: objectwatcher
Write_watcher _ is directly related and will be analyzed in detail later.

Next, we will analyze the tcpclientsocketwin class comprehensively. First, we will see how it establishes a TCP connection. tcpclientsocketwin first calls the member function connect, which is just a simple setting of the next_connect_state _ status, assign a value to current_ai _. current_ai _ is an addrinfo struct. addrinfo is compatible with IPv4 and IPv6 address information. Therefore, we can transparently process the addresses of these two protocol families. Next, call the doconnectloop function and check the implementation of doconnectloop. There is only one simple loop. First, call doconnect. If the connection succeeds immediately, then call doconnectcomplete, otherwise, an err_io_pending error code is returned, indicating that the connection request is in the asynchronous outbound flow or the call fails.

Let's take a look at the implementation of the doconnect () function, not only because you need to call connect to a new connection before writing data, but also initialize the asynchronous I/O model of the set of interfaces in this function, let's take a look at the main code of this function:

#1 int tcpclientsocketwin: doconnect (){
#2 const struct addrinfo * Ai = current_ai _;
#3 dcheck (AI );
#4 dcheck_eq (0, connect_ OS _error _);
#5 If (previusly_disconnected _){
#6 use_history _. Reset ();
#7 previusly_disconnected _ = false;
#8}
#9 net_log _. beginevent (netlog: type_tcp_connect_attempt,
#10 new netlogstringparameter (
#11 "Address", netaddresstostringwithport (current_ai _); // The Writing Date for debugging
#12 next_connect_state _ = connect_state_connect_complete;
#13 connect_ OS _error _ = createsocket (AI); // create a new socket
#14 if (connect_ OS _error _! = 0)
#15 return mapwinsockerror (connect_ OS _error _);
#16 dcheck (! Core _);
#17 core _ = new core (this); // create a core _
#18 core _-> read_overlapped _. hevent = wsacreateevent (); // create an overlapping I/O structure
#19 wsaeventselect (socket _, core _-> read_overlapped _. hevent, fd_connect); // initialize the I/O model. wsaeventselect is an asynchronous I/O model. For details, refer to the description of msdn and other materials.
#20 core _-> write_overlapped _. hevent = wsacreateevent ();
#21 if (! Connect (socket _, AI-> ai_addr, static_cast <int> (AI-> ai_addrlen) {// return immediately after connect is called in asynchronous mode
#22 notreached ();
#23 if (reseteventifsignaled (core _-> read_overlapped _. hevent ))
#24 Return OK;
#25} else {
#26 int OS _error = wsagetlasterror ();
#27 if (OS _error! = Wsaewouldblock ){
#28 log (error) <"Connect failed:" <OS _error;
#29 connect_ OS _error _ = OS _error;
#30 return mapconnecterror (OS _error );
#31}
#32}
#34 core _-> watchforread (); // install the callback function here
#35 return err_io_pending;

#36}

Call createsocket in Row 3 to create a new set of interfaces, create a core object core _, and create event objects for asynchronous I/O for read_overlapped _ and write_overlapped _ respectively, initialize the wsaeventselect model in lines 19 to Implement Asynchronous calls to connect. According to Microsoft documents, once wsaeventselect is called, the target set of interfaces will be switched to non-blocking mode, connect does not wait for the server's response but returns immediately. The returned value is socket_errore. It should be said that connect will never return 0, but here they still process the returned 0, call reseteventifsignaled to determine whether the event object is in the sent message state. You can also see that connect and read share read_overlapped _. Therefore, in the core: readdelegate: onobjectsignaled function, will distinguish connect and read parallel Do not call corresponding processing functions. The last 34 lines call core _-> watchforread () to submit the connection to the thread model. If the connection is successful, didcompleteconnect will be called, and the last call to doreadcallback will notify the upper-layer callers.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.