Merge pull request #8759 from sepalani/so-connect

IOS/NET: Add timeout on blocking connect
This commit is contained in:
Léo Lam 2021-02-21 15:26:59 +01:00 committed by GitHub
commit c040b0151d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 2 deletions

View File

@ -157,6 +157,10 @@ const Info<bool> MAIN_NETWORK_SSL_DUMP_ROOT_CA{{System::Main, "Network", "SSLDum
const Info<bool> MAIN_NETWORK_SSL_DUMP_PEER_CERT{{System::Main, "Network", "SSLDumpPeerCert"},
false};
const Info<bool> MAIN_NETWORK_DUMP_AS_PCAP{{System::Main, "Network", "DumpAsPCAP"}, false};
// Default value based on:
// - [RFC 1122] 4.2.3.5 TCP Connection Failures (at least 3 minutes)
// - https://dolp.in/pr8759 hwtest (3 minutes and 10 seconds)
const Info<int> MAIN_NETWORK_TIMEOUT{{System::Main, "Network", "NetworkTimeout"}, 190};
// Main.Interface

View File

@ -130,6 +130,7 @@ extern const Info<bool> MAIN_NETWORK_SSL_VERIFY_CERTIFICATES;
extern const Info<bool> MAIN_NETWORK_SSL_DUMP_ROOT_CA;
extern const Info<bool> MAIN_NETWORK_SSL_DUMP_PEER_CERT;
extern const Info<bool> MAIN_NETWORK_DUMP_AS_PCAP;
extern const Info<int> MAIN_NETWORK_TIMEOUT;
// Main.Interface

View File

@ -331,11 +331,24 @@ void WiiSocket::Update(bool read, bool write, bool except)
}
// Fix blocking error codes
if (!nonBlock)
if (!nonBlock && it->net_type == IOCTL_SO_CONNECT)
{
if (it->net_type == IOCTL_SO_CONNECT && ReturnValue == -SO_EISCONN)
switch (ReturnValue)
{
case -SO_EAGAIN:
case -SO_EALREADY:
case -SO_EINPROGRESS:
if (std::chrono::steady_clock::now() > GetTimeout())
{
ReturnValue = -SO_ENETUNREACH;
ResetTimeout();
}
break;
case -SO_EISCONN:
ReturnValue = SO_SUCCESS;
[[fallthrough]];
default:
ResetTimeout();
}
}
}
@ -660,6 +673,21 @@ void WiiSocket::Update(bool read, bool write, bool except)
}
}
const WiiSocket::Timeout& WiiSocket::GetTimeout()
{
if (!timeout.has_value())
{
timeout = std::chrono::steady_clock::now() +
std::chrono::seconds(Config::Get(Config::MAIN_NETWORK_TIMEOUT));
}
return *timeout;
}
void WiiSocket::ResetTimeout()
{
timeout.reset();
}
void WiiSocket::DoSock(Request request, NET_IOCTL type)
{
sockop so = {request, false};

View File

@ -43,8 +43,10 @@ typedef struct pollfd pollfd_t;
#endif
#include <algorithm>
#include <chrono>
#include <cstdio>
#include <list>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
@ -184,6 +186,7 @@ public:
WiiSocket& operator=(WiiSocket&&) = default;
private:
using Timeout = std::chrono::time_point<std::chrono::steady_clock>;
struct sockop
{
Request request;
@ -204,14 +207,20 @@ private:
s32 CloseFd();
s32 FCntl(u32 cmd, u32 arg);
const Timeout& GetTimeout();
void ResetTimeout();
void DoSock(Request request, NET_IOCTL type);
void DoSock(Request request, SSL_IOCTL type);
void Update(bool read, bool write, bool except);
bool IsValid() const { return fd >= 0; }
s32 fd = -1;
s32 wii_fd = -1;
bool nonBlock = false;
std::list<sockop> pending_sockops;
std::optional<Timeout> timeout;
};
class WiiSockMan