-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Aleth should wait 2 seconds to close socket after sending disconnect to peer #5650
Description
According to the RLPX handshake spec, one should give clients 2 seconds to disconnect after sending a disconnect packet:
Inform the peer that a disconnection is imminent; if received, a peer should disconnect immediately. When sending, well-behaved hosts give their peers a fighting chance (read: wait 2 seconds) to disconnect to before disconnecting themselves.
However, Aleth closes the socket immediately (via Session::drop). This also means that the disconnect packet may not be sent - this is because Session::disconnect (and all of the functions it calls) is executed on the network thread, whereas the async_write may not execute immediately in which case I suspect it will execute after Session::disconnect / Session::drop:
Lines 299 to 310 in c630593
| void Session::disconnect(DisconnectReason _reason) | |
| { | |
| cnetdetails << "Disconnecting (our reason: " << reasonOf(_reason) << ") from " << m_logSuffix; | |
| if (m_socket->ref().is_open()) | |
| { | |
| RLPStream s; | |
| prep(s, DisconnectPacket, 1) << (int)_reason; | |
| sealAndSend(s); | |
| } | |
| drop(_reason); | |
| } |
Here's where the actual socket write takes place (in Session::write):
Lines 237 to 256 in c630593
| auto self(shared_from_this()); | |
| ba::async_write(m_socket->ref(), ba::buffer(*out), | |
| [this, self](boost::system::error_code ec, std::size_t /*length*/) { | |
| // must check queue, as write callback can occur following dropped() | |
| if (ec) | |
| { | |
| LOG(m_netLogger) << "Error sending: " << ec.message(); | |
| drop(TCPError); | |
| return; | |
| } | |
| DEV_GUARDED(x_framing) | |
| { | |
| m_writeQueue.pop_front(); | |
| if (m_writeQueue.empty()) | |
| return; | |
| } | |
| write(); | |
| }); | |
| } |