1
0
mirror of https://github.com/PurpleI2P/i2pd.git synced 2025-01-18 04:19:58 +00:00

SSU2: check if socket is opened before sending data, handle network_reset error

Signed-off-by: r4sas <r4sas@i2pmail.org>
This commit is contained in:
R4SAS 2023-05-27 01:00:19 +03:00
parent dc6a42c26f
commit ae439b5385
Signed by: r4sas
GPG Key ID: 66F6C87B98EBCFE2
2 changed files with 34 additions and 13 deletions

View File

@ -30,7 +30,7 @@ namespace data
{ {
return boost::posix_time::second_clock::local_time(); return boost::posix_time::second_clock::local_time();
} }
RouterProfile::RouterProfile (): RouterProfile::RouterProfile ():
m_LastUpdateTime (GetTime ()), m_IsUpdated (false), m_LastUpdateTime (GetTime ()), m_IsUpdated (false),
m_LastDeclineTime (0), m_LastUnreachableTime (0), m_LastDeclineTime (0), m_LastUnreachableTime (0),
@ -175,8 +175,8 @@ namespace data
{ {
m_HasConnected = true; m_HasConnected = true;
UpdateTime (); UpdateTime ();
} }
bool RouterProfile::IsLowPartcipationRate () const bool RouterProfile::IsLowPartcipationRate () const
{ {
return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate
@ -223,7 +223,7 @@ namespace data
m_LastUnreachableTime = 0; m_LastUnreachableTime = 0;
return (bool)m_LastUnreachableTime; return (bool)m_LastUnreachableTime;
} }
bool RouterProfile::IsUseful() const { bool RouterProfile::IsUseful() const {
return return
m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD || m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD ||
@ -240,7 +240,7 @@ namespace data
auto it = g_Profiles.find (identHash); auto it = g_Profiles.find (identHash);
if (it != g_Profiles.end ()) if (it != g_Profiles.end ())
return it->second; return it->second;
} }
auto profile = std::make_shared<RouterProfile> (); auto profile = std::make_shared<RouterProfile> ();
profile->Load (identHash); // if possible profile->Load (identHash); // if possible
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::unique_lock<std::mutex> l(g_ProfilesMutex);
@ -261,7 +261,7 @@ namespace data
{ {
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::unique_lock<std::mutex> l(g_ProfilesMutex);
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
{ {
if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL) if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL)
{ {
if (it->second->IsUpdated ()) if (it->second->IsUpdated ())
@ -270,11 +270,11 @@ namespace data
} }
else else
it++; it++;
} }
} }
for (auto& it: tmp) for (auto& it: tmp)
if (it.second) it.second->Save (it.first); if (it.second) it.second->Save (it.first);
} }
void SaveProfiles () void SaveProfiles ()
{ {
@ -288,22 +288,22 @@ namespace data
for (auto& it: tmp) for (auto& it: tmp)
if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600)
it.second->Save (it.first); it.second->Save (it.first);
} }
void DeleteObsoleteProfiles () void DeleteObsoleteProfiles ()
{ {
{ {
auto ts = GetTime (); auto ts = GetTime ();
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::unique_lock<std::mutex> l(g_ProfilesMutex);
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
{ {
if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600) if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600)
it = g_Profiles.erase (it); it = g_Profiles.erase (it);
else else
it++; it++;
} }
} }
struct stat st; struct stat st;
std::time_t now = std::time(nullptr); std::time_t now = std::time(nullptr);

View File

@ -78,6 +78,7 @@ namespace transport
if (address->IsV4 ()) if (address->IsV4 ())
{ {
found = true; found = true;
LogPrint (eLogDebug, "SSU2: Opening IPv4 socket at Start");
OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV4, port)); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV4, port));
m_ReceiveService.GetService ().post( m_ReceiveService.GetService ().post(
[this]() [this]()
@ -89,6 +90,7 @@ namespace transport
if (address->IsV6 ()) if (address->IsV6 ())
{ {
found = true; found = true;
LogPrint (eLogDebug, "SSU2: Opening IPv6 socket at Start");
OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV6, port)); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV6, port));
m_ReceiveService.GetService ().post( m_ReceiveService.GetService ().post(
[this]() [this]()
@ -243,10 +245,12 @@ namespace transport
if (!ecode if (!ecode
|| ecode == boost::asio::error::connection_refused || ecode == boost::asio::error::connection_refused
|| ecode == boost::asio::error::connection_reset || ecode == boost::asio::error::connection_reset
|| ecode == boost::asio::error::network_reset
|| ecode == boost::asio::error::network_unreachable || ecode == boost::asio::error::network_unreachable
|| ecode == boost::asio::error::host_unreachable || ecode == boost::asio::error::host_unreachable
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO #ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_ || ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|| ecode.value() == boost::winapi::WSAENETRESET_ // 10052
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_ || ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_ || ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
#endif #endif
@ -303,7 +307,7 @@ namespace transport
else else
{ {
auto ep = socket.local_endpoint (); auto ep = socket.local_endpoint ();
socket.close (); LogPrint (eLogCritical, "SSU2: Reopening socket in HandleReceivedFrom: code ", ecode.value(), ": ", ecode.message ());
OpenSocket (ep); OpenSocket (ep);
Receive (socket); Receive (socket);
} }
@ -558,16 +562,25 @@ namespace transport
SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to); SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to);
return; return;
} }
std::vector<boost::asio::const_buffer> bufs std::vector<boost::asio::const_buffer> bufs
{ {
boost::asio::buffer (header, headerLen), boost::asio::buffer (header, headerLen),
boost::asio::buffer (payload, payloadLen) boost::asio::buffer (payload, payloadLen)
}; };
boost::system::error_code ec; boost::system::error_code ec;
if (to.address ().is_v6 ()) if (to.address ().is_v6 ())
{
if (!m_SocketV6.is_open ()) return;
m_SocketV6.send_to (bufs, to, 0, ec); m_SocketV6.send_to (bufs, to, 0, ec);
}
else else
{
if (!m_SocketV4.is_open ()) return;
m_SocketV4.send_to (bufs, to, 0, ec); m_SocketV4.send_to (bufs, to, 0, ec);
}
if (!ec) if (!ec)
i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen); i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen);
else else
@ -582,17 +595,25 @@ namespace transport
SendThroughProxy (header, headerLen, headerX, headerXLen, payload, payloadLen, to); SendThroughProxy (header, headerLen, headerX, headerXLen, payload, payloadLen, to);
return; return;
} }
std::vector<boost::asio::const_buffer> bufs std::vector<boost::asio::const_buffer> bufs
{ {
boost::asio::buffer (header, headerLen), boost::asio::buffer (header, headerLen),
boost::asio::buffer (headerX, headerXLen), boost::asio::buffer (headerX, headerXLen),
boost::asio::buffer (payload, payloadLen) boost::asio::buffer (payload, payloadLen)
}; };
boost::system::error_code ec; boost::system::error_code ec;
if (to.address ().is_v6 ()) if (to.address ().is_v6 ())
{
if (!m_SocketV6.is_open ()) return;
m_SocketV6.send_to (bufs, to, 0, ec); m_SocketV6.send_to (bufs, to, 0, ec);
}
else else
{
if (!m_SocketV4.is_open ()) return;
m_SocketV4.send_to (bufs, to, 0, ec); m_SocketV4.send_to (bufs, to, 0, ec);
}
if (!ec) if (!ec)
i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen); i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen);