Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>So I did some testing. Based on my results, it's clear that they depend on the underlying OS implementation. For reference, I tested this with a stock Fedora kernel: <code>2.6.35.10-74.fc14.x86_64</code>.</p> <p>The bottom line is that <code>async_resolve()</code> looks to be the only case where you <em>might</em> be able to get away without setting a <code>deadline_timer</code>. It's practically required in every other case for reasonable behavior.</p> <hr> <p><strong><code>async_resolve()</code></strong></p> <p>A call to <code>async_resolve()</code> resulted in 4 queries 5 seconds apart. The handler was called 20 seconds after the request with the error <code>boost::asio::error::host_not_found</code>.</p> <p>My resolver defaults to a timeout of 5 seconds with 2 attempts (<code>resolv.h</code>), so it appears to send twice the number of queries configured. The behavior is modifiable by setting <code>options timeout</code> and <code>options attempts</code> in <code>/etc/resolv.conf</code>. In every case the number of queries sent was double whatever <code>attempts</code> was set to and the handler was called with the <code>host_not_found</code> error afterwards.</p> <p>For the test, the single configured nameserver was black-hole routed.</p> <hr> <p><strong><code>async_connect()</code></strong></p> <p>Calling <code>async_connect()</code> with a black-hole-routed destination resulted in the handler being called with the error <code>boost::asio::error::timed_out</code> after ~189 seconds.</p> <p>The stack sent the initial SYN and 5 retries. The first retry was sent after 3 seconds, with the retry timeout doubling each time (3+6+12+24+48+96=189). The number of retries can be changed:</p> <pre><code>% sysctl net.ipv4.tcp_syn_retries net.ipv4.tcp_syn_retries = 5 </code></pre> <p>The default of 5 is chosen to comply with RFC 1122 (4.2.3.5):</p> <blockquote> <p>[The retransmission timers] for a SYN segment MUST be set large enough to provide retransmission of the segment for at least 3 minutes. The application can close the connection (i.e., give up on the open attempt) sooner, of course.</p> </blockquote> <p>3 minutes = 180 seconds, though the RFC doesn't appear to specify an upper bound. There's nothing stopping an implementation from retrying forever.</p> <hr> <p><strong><code>async_write()</code></strong></p> <p>As long as the socket's send buffer wasn't full, this handler was always called right away.</p> <p>My test established a TCP connection and set a timer to call <code>async_write()</code> a minute later. During the minute where the connection was established but prior to the <code>async_write()</code> call, I tried all sorts of mayhem:</p> <ul> <li>Setting a downstream router to black-hole subsequent traffic to the destination.</li> <li>Clearing the session in a downstream firewall so it would reply with spoofed RSTs from the destination.</li> <li>Unplugging my Ethernet</li> <li>Running <code>/etc/init.d/network stop</code></li> </ul> <p>No matter what I did, the next <code>async_write()</code> would immediately call its handler to report success.</p> <p>In the case where the firewall spoofed the RST, the connection was closed immediately, but I had no way of knowing that until I attempted the <em>next</em> operation (which would immediately report <code>boost::asio::error::connection_reset</code>). In the other cases, the connection would remain open and not report errors to me until it eventually timed out 17-18 minutes later.</p> <p>The worst case for <code>async_write()</code> is if the host is retransmitting and the send buffer is full. If the buffer is full, <code>async_write()</code> won't call its handler until the retransmissions time out. Linux defaults to 15 retransmissions:</p> <pre><code>% sysctl net.ipv4.tcp_retries2 net.ipv4.tcp_retries2 = 15 </code></pre> <p>The time between the retransmissions increases after each (and is based on many factors such as the estimated round-trip time of the specific connection) but is clamped at 2 minutes. So with the default 15 retransmissions and worst-case 2-minute timeout, the upper bound is 30 minutes for the <code>async_write()</code> handler to be called. When it is called, error is set to <code>boost::asio::error::timed_out</code>.</p> <hr> <p><strong><code>async_read()</code></strong></p> <p>This should never call its handler as long as the connection is established and no data is received. I haven't had time to test it.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload