Tor source code analysis 11-client Execution Process (Network Information download continued)

Source: Internet
Author: User

Through the re-Description of the connection and link in the previous section, we can continue to analyze the source code. In this section, we will begin to focus on the establishment of the link, the establishment of the or connection based on the link, and the re-analysis of some libevent scheduling. You will understand that by now, we have begun to access the underlying, deepest hidden connection and Scheduling Mechanisms of Tor systems. This part is the essence of the entire system. Later, almost all application request connection processing and so on will repeatedly use this part of code.

1. Start of link establishment and or connection, circuit_establish_circuit

Here we re-analyze the functions created by the link:

/** Build a new circuit for <B> purpose </B>. if <B> exit </B> * is defined, then use that as your exit router, else choose a suitable * exit node. ** also launch a connection to the first or in the chosen path, if * it's not open already. */optional * values (uint8_t purpose, extend_info_t * exit, int flags) {optional * CIRC; int err_reason = 0; circ = origin_circuit_init (purpose, flags); // link initialization; if (onion_pick_cpath_exit (CIRC, exit) <0 | // select the link egress node; onion_populate_cpath (CIRC) <0) {// select the link entry node and intermediate node ;......} if (err_reason = circuit_handle_first_hop (CIRC) <0) {// start to send a request for establishing or connection to the first node of the link; (or the connection is established on top of the TLS connection )......} return CIRC ;}

As we described earlier, the main function's internal work includes three points: Initialize the link structure, select the link node, and establish a connection to the first node in the link. It should be noted that the initialization of the Link Structure and the selection of link nodes are simple. Therefore, in the following analysis, we will not detail the detailed rules for these two operations, but will focus our attention on the actual operation part of link establishment. If you have any questions about the node selection, you can analyze the above two node selection functions. We believe that you can find the node selection policy and related mechanisms. However, the selection of nodes is not the focus of the program execution process, so we should focus on the analysis function: circuit_handle_first_hop.

2. Or connection establishment and link expansion, circuit_handle_first_hop

After the client completes the link initialization and node selection in the Link, an or connection to the first link node will be established. However, there is still a reuse problem, that is, the multiple links we mentioned earlier can share one or connection. Imagine that when a link Selects all nodes in the Link, it will send or connection requests to the first node. If there is an or connection between the client host and the selected node host, do you need to re-connect? Obviously, it is unnecessary. So we can reuse multiple links on one or connection. So we will see some operations in the code to determine whether there is an available or connection. Next, let's look at the Code:

/** Start establishing the first hop of our circuit. figure out what * Or we shoshould connect to, and if necessary start the connection to * It. if we're already connected, then sends the 'create' cell. * return 0 for OK,-reason If CIRC shoshould be marked-for-close. */intcircuit_handle_first_hop (origin_circuit_t * CIRC ){...... firsthop = onion_next_hop_in_cpath (Circ-> cpath); // select the first unmarked open node in the link in sequence; in this function In fact, each selected link entry node is actually; n_conn = connection_or_get_for_extend (firsthop-> extend_info-> identity_digest, // obtain reusable or connections; & firsthop-> extend_info-> ADDR, & MSG, & should_launch); If (! N_conn) {/* not currently connected in a useful way. * /// if there is no or connection that can be reused, the or connection to the first node is reestablished; circ-> _ base. n_hop = extend_info_dup (firsthop-> extend_info); If (should_launch) {// create an or connection to the first node to execute the function: connection_or_connect n_conn = connection_or_connect (& firsthop-> extend_info-> ADDR, firsthop-> extend_info-> port, firsthop-> extend_info-> identity_digest);} return 0 ;} else {/* It's already open. use it. * /// if there is a reusable or connection, send the create package to inform the remote node to start a new link; circ-> _ base. n_conn = n_conn; If (err_reason = circuit_send_next_onion_skin (CIRC) <0 ){......}} return 0 ;}

We can understand that the reuse or reuse is for the or connection of the first node of the link. For other nodes, the local client does not directly communicate with them at the or level, but communicates with them through link expansion. Therefore, for the first node, the local client needs to achieve or-Level Interconnection and link-level communication, that is, to send a create package to inform the link to be enabled. For other nodes, the local client only sends the link layer command package to the first node to implement communication at the link layer.

From the above functions, we can see two key branches: the branches that initiate or connection requests to the first node, reuse or connections, and directly initiate a new link to the first node to open the command branch. According to the general process of the system, we will first analyze the situations where no or connection is available in the system. That is to say, by default, there is no or connection that meets the link requirements in the system. Then, the program needs to establish an or connection from the local to the first node of the link.

3. or connection creation details

The or connection is established based on the TLS connection. To establish an available or connection, you need to complete the TLS handshake. However, the handshake process requires several rounds of exchanges between the two parties. Obviously, it is very inefficient to wait for the handshake to end in a function. Or connection details, we need to focus on how the system designs a non-blocking TLS handshake process to achieve efficient operation. The code analysis is as follows:

/** Launch a new or connection to <B> ADDR </B>: <B> port </B> and login CT to * handshake with an OR with identity digest <B> id_digest </B>. ** If <B> id_digest </B> is me, do nothing. if we're already connected to it, * return that connection. if the connect () is in progress, set the * New Conn's state to 'connection' and return it. if connect () succeeds, * Call connection_tls_start_handshake () on it. ** this function is called from router_retry_connections (), for * ors connecting to ors, and circuit_establish_circuit (), for * ops connecting to ORS. // The comment here can indicate the importance of this function; ** return the launched Conn, or null if it failed. */or_connection_t * connection_or_connect (const tor_addr_t * _ ADDR, uint16_t port, const char * id_digest ){...... conn = or_connection_new (tor_addr_family (& ADDR);/* set up conn so it's got all the data we need to remember */connection_or_init_conn_from_address (Conn, & ADDR, port, id_digest, 1); Conn-> _ base. state = or_conn_state_connecting; Conn-> is_outgoing = 1;/* If we are using a proxy server, find it and use it. */r = get_proxy_addrport (& proxy_addr, & proxy_port, & proxy_type, to_conn (conn); If (r = 0) {// do not use a proxy ;......} else {// use proxy ...... // This part involves proxy operations, which are skipped for the moment. Later, there will be proxy and bridge topics;} switch (connection_connect (to_conn (conn), Conn-> _ base. address, // or establish the socket layer; & ADDR, port, & socket_error) {Case-1: // creation failed/* If the connection failed immediately, and we're using * a proxy, our proxy is down. don't blame the TOR server. */...... return NULL; Case 0: // creation in progress. This is normal; connection_watch_events (to_conn (conn), read_event | write_event ); // Add the read/write events connected by or to the libevent event listening queue; return conn;/* Case 1: fall through * // The connection is established. If the socket connection can be established very quickly, then directly enters the TLS handshake phase;} // start the TLS handshake phase here. In this function, only the above socket connection completes the connection very quickly and will be executed here; if (connection_or_finished_connecting (conn) <0) {/* already marked for close */return NULL;} return conn ;}

The most important part of the above functions is the function connetion_connect. This function is used to establish a socket, but the result of the establishment is non-blocking, so there are three results: the establishment fails-1, the creation is in progress 0, build 1. Because the socket connection is non-blocking, both being established and established are possible. If the establishment is complete, you can directly start the TLS handshake connection. If the establishment is in progress, you need to add the connection to the libevent event listening list for monitoring and subsequent operations. In fact, the focus of this part is the operation when the connection cannot be completed immediately: add the established connection to the libevent event listening queue. Here, we have a vague sense of how the TOR system handles the connection establishment operation that takes some time to complete. In fact, the TOR system even uses the libevent event scheduling system to schedule the connection establishment process. If the connection creation operation is not completed when the non-blocking connection establishment process is returned, the system adds the connection to the libevent event pool. The connection can be operated at the beginning of the main cycle of the next event, then, the connection is established and the handshake operation is continued.

Here, we will introduce the process of establishing or connections. In this process, the most important part is to process the returned values of socket connections. At this time, you may not see how to process the activated events in the libevent event queue. In the subsequent articles, we will go into the main loop event processing analysis. In fact, it is the analysis of read/write functions:

1, conn_write_callback;

2, conn_read_callback;

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.