summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-02-21 15:26:59 +0100
committerGitHub <noreply@github.com>2021-02-21 15:26:59 +0100
commitc040b0151d2dfc5d98ca380911d8cc2d0a3fccd8 (patch)
tree9092cb0b37fe8711a04600f3c2c07bb1ebb351d7 /Source
parent6f71a1ec5054d74890974b64ed65bdf5e9d4b16c (diff)
parentbf246c36f534c0772f26384be3c0a6700274d887 (diff)
Merge pull request #8759 from sepalani/so-connect
IOS/NET: Add timeout on blocking connect
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/Config/MainSettings.cpp4
-rw-r--r--Source/Core/Core/Config/MainSettings.h1
-rw-r--r--Source/Core/Core/IOS/Network/Socket.cpp32
-rw-r--r--Source/Core/Core/IOS/Network/Socket.h9
4 files changed, 44 insertions, 2 deletions
diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp
index bcd8887def..d0fbd6c1f2 100644
--- a/Source/Core/Core/Config/MainSettings.cpp
+++ b/Source/Core/Core/Config/MainSettings.cpp
@@ -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
diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h
index 1d9a687153..c0a063c624 100644
--- a/Source/Core/Core/Config/MainSettings.h
+++ b/Source/Core/Core/Config/MainSettings.h
@@ -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
diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp
index 53a34fef05..663b3f05dd 100644
--- a/Source/Core/Core/IOS/Network/Socket.cpp
+++ b/Source/Core/Core/IOS/Network/Socket.cpp
@@ -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};
diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h
index c72ffd6998..6bacd6f482 100644
--- a/Source/Core/Core/IOS/Network/Socket.h
+++ b/Source/Core/Core/IOS/Network/Socket.h
@@ -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