diff options
author | Vasil Dimov <vd@FreeBSD.org> | 2023-07-10 12:13:54 +0200 |
---|---|---|
committer | Vasil Dimov <vd@FreeBSD.org> | 2023-10-05 14:10:43 +0200 |
commit | 762404a68c114e8831cdfae937627174544b55a7 (patch) | |
tree | 731ccea100f11845cfd2ceca5a1ad10d40b749f2 /src/net.cpp | |
parent | 78fd3c2672400fb958f2d25ddd40955c7deed4cd (diff) |
i2p: also sleep after errors in Accept()
Background:
`Listen()` does:
* if the session is not created yet
* create the control socket and on it:
* `HELLO`
* `SESSION CREATE ID=sessid`
* leave the control socked opened
* create a new socket and on it:
* `HELLO`
* `STREAM ACCEPT ID=sessid`
* read reply (`STREAM STATUS`)
Then a wait starts, for a peer to connect. When connected,
`Accept()` does:
* on the socket from `STREAM ACCEPT` from `Listen()`: read the
Base64 identification of the connecting peer
Problem:
The I2P router may be in such a state that this happens in a quick
succession (many times per second, see https://github.com/bitcoin/bitcoin/issues/22759#issuecomment-1609907115):
`Listen()`-succeeds, `Accept()`-fails.
`Accept()` fails because the I2P router sends something that is
not Base64 on the socket:
STREAM STATUS RESULT=I2P_ERROR MESSAGE="Session was closed"
We only sleep after failed `Listen()` because the assumption was that
if `Accept()` fails then the next `Listen()` will also fail.
Solution:
Avoid filling the log with "Error accepting:" messages and sleep also
after a failed `Accept()`.
Extra changes:
* Reset the error waiting time after one successful connection.
Otherwise the timer will remain high due to problems that have
vanished long time ago.
* Increment the wait time less aggressively.
Diffstat (limited to 'src/net.cpp')
-rw-r--r-- | src/net.cpp | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/src/net.cpp b/src/net.cpp index 994abd986d..9048dd438e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2974,6 +2974,13 @@ void CConnman::ThreadI2PAcceptIncoming() bool advertising_listen_addr = false; i2p::Connection conn; + auto SleepOnFailure = [&]() { + interruptNet.sleep_for(err_wait); + if (err_wait < err_wait_cap) { + err_wait += 1s; + } + }; + while (!interruptNet) { if (!m_i2p_sam_session->Listen(conn)) { @@ -2981,12 +2988,7 @@ void CConnman::ThreadI2PAcceptIncoming() RemoveLocal(conn.me); advertising_listen_addr = false; } - - interruptNet.sleep_for(err_wait); - if (err_wait < err_wait_cap) { - err_wait *= 2; - } - + SleepOnFailure(); continue; } @@ -2996,11 +2998,14 @@ void CConnman::ThreadI2PAcceptIncoming() } if (!m_i2p_sam_session->Accept(conn)) { + SleepOnFailure(); continue; } CreateNodeFromAcceptedSocket(std::move(conn.sock), NetPermissionFlags::None, CAddress{conn.me, NODE_NONE}, CAddress{conn.peer, NODE_NONE}); + + err_wait = err_wait_begin; } } |