summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar comex2023-07-01 17:28:43 -0700
committerGravatar Liam2023-08-15 20:59:57 -0400
commit755bcc459bb9a5c7d521ea9046a8ac58c5256e73 (patch)
tree63a837fd55b77a8bb3c0b766c31a0d8ab0642d67
parentMerge pull request #11287 from liamwhite/replaced-bytes (diff)
downloadyuzu-755bcc459bb9a5c7d521ea9046a8ac58c5256e73.tar.gz
yuzu-755bcc459bb9a5c7d521ea9046a8ac58c5256e73.tar.xz
yuzu-755bcc459bb9a5c7d521ea9046a8ac58c5256e73.zip
Improve behavior when sending to closed connection
- On Unix, this would previously kill the Yuzu process with SIGPIPE. Send MSG_NOSIGNAL to opt out of this. - Add support for the proper error code in this situation, EPIPE. - Windows has nonstandard behavior in this situation; translate it to the standard behavior. Kind of pointless, but isn't it nice to be correct?
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/sockets/sockets.h2
-rw-r--r--src/core/hle/service/sockets/sockets_translate.cpp4
-rw-r--r--src/core/internal_network/network.cpp35
-rw-r--r--src/core/internal_network/network.h2
4 files changed, 36 insertions, 7 deletions
diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h
index 77426c46e..f86af01a4 100644
--- a/src/core/hle/service/sockets/sockets.h
+++ b/src/core/hle/service/sockets/sockets.h
@@ -18,7 +18,9 @@ enum class Errno : u32 {
18 AGAIN = 11, 18 AGAIN = 11,
19 INVAL = 22, 19 INVAL = 22,
20 MFILE = 24, 20 MFILE = 24,
21 PIPE = 32,
21 MSGSIZE = 90, 22 MSGSIZE = 90,
23 CONNABORTED = 103,
22 CONNRESET = 104, 24 CONNRESET = 104,
23 NOTCONN = 107, 25 NOTCONN = 107,
24 TIMEDOUT = 110, 26 TIMEDOUT = 110,
diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp
index c1187209f..aed05250c 100644
--- a/src/core/hle/service/sockets/sockets_translate.cpp
+++ b/src/core/hle/service/sockets/sockets_translate.cpp
@@ -23,10 +23,14 @@ Errno Translate(Network::Errno value) {
23 return Errno::INVAL; 23 return Errno::INVAL;
24 case Network::Errno::MFILE: 24 case Network::Errno::MFILE:
25 return Errno::MFILE; 25 return Errno::MFILE;
26 case Network::Errno::PIPE:
27 return Errno::PIPE;
26 case Network::Errno::NOTCONN: 28 case Network::Errno::NOTCONN:
27 return Errno::NOTCONN; 29 return Errno::NOTCONN;
28 case Network::Errno::TIMEDOUT: 30 case Network::Errno::TIMEDOUT:
29 return Errno::TIMEDOUT; 31 return Errno::TIMEDOUT;
32 case Network::Errno::CONNABORTED:
33 return Errno::CONNABORTED;
30 case Network::Errno::CONNRESET: 34 case Network::Errno::CONNRESET:
31 return Errno::CONNRESET; 35 return Errno::CONNRESET;
32 case Network::Errno::INPROGRESS: 36 case Network::Errno::INPROGRESS:
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp
index bda9fa2e0..5d28300e6 100644
--- a/src/core/internal_network/network.cpp
+++ b/src/core/internal_network/network.cpp
@@ -39,6 +39,11 @@ namespace Network {
39 39
40namespace { 40namespace {
41 41
42enum class CallType {
43 Send,
44 Other,
45};
46
42#ifdef _WIN32 47#ifdef _WIN32
43 48
44using socklen_t = int; 49using socklen_t = int;
@@ -96,7 +101,7 @@ bool EnableNonBlock(SOCKET fd, bool enable) {
96 return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR; 101 return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
97} 102}
98 103
99Errno TranslateNativeError(int e) { 104Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
100 switch (e) { 105 switch (e) {
101 case 0: 106 case 0:
102 return Errno::SUCCESS; 107 return Errno::SUCCESS;
@@ -112,6 +117,14 @@ Errno TranslateNativeError(int e) {
112 return Errno::AGAIN; 117 return Errno::AGAIN;
113 case WSAECONNREFUSED: 118 case WSAECONNREFUSED:
114 return Errno::CONNREFUSED; 119 return Errno::CONNREFUSED;
120 case WSAECONNABORTED:
121 if (call_type == CallType::Send) {
122 // Winsock yields WSAECONNABORTED from `send` in situations where Unix
123 // systems, and actual Switches, yield EPIPE.
124 return Errno::PIPE;
125 } else {
126 return Errno::CONNABORTED;
127 }
115 case WSAECONNRESET: 128 case WSAECONNRESET:
116 return Errno::CONNRESET; 129 return Errno::CONNRESET;
117 case WSAEHOSTUNREACH: 130 case WSAEHOSTUNREACH:
@@ -198,7 +211,7 @@ bool EnableNonBlock(int fd, bool enable) {
198 return fcntl(fd, F_SETFL, flags) == 0; 211 return fcntl(fd, F_SETFL, flags) == 0;
199} 212}
200 213
201Errno TranslateNativeError(int e) { 214Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
202 switch (e) { 215 switch (e) {
203 case 0: 216 case 0:
204 return Errno::SUCCESS; 217 return Errno::SUCCESS;
@@ -208,6 +221,10 @@ Errno TranslateNativeError(int e) {
208 return Errno::INVAL; 221 return Errno::INVAL;
209 case EMFILE: 222 case EMFILE:
210 return Errno::MFILE; 223 return Errno::MFILE;
224 case EPIPE:
225 return Errno::PIPE;
226 case ECONNABORTED:
227 return Errno::CONNABORTED;
211 case ENOTCONN: 228 case ENOTCONN:
212 return Errno::NOTCONN; 229 return Errno::NOTCONN;
213 case EAGAIN: 230 case EAGAIN:
@@ -236,13 +253,13 @@ Errno TranslateNativeError(int e) {
236 253
237#endif 254#endif
238 255
239Errno GetAndLogLastError() { 256Errno GetAndLogLastError(CallType call_type = CallType::Other) {
240#ifdef _WIN32 257#ifdef _WIN32
241 int e = WSAGetLastError(); 258 int e = WSAGetLastError();
242#else 259#else
243 int e = errno; 260 int e = errno;
244#endif 261#endif
245 const Errno err = TranslateNativeError(e); 262 const Errno err = TranslateNativeError(e, call_type);
246 if (err == Errno::AGAIN || err == Errno::TIMEDOUT || err == Errno::INPROGRESS) { 263 if (err == Errno::AGAIN || err == Errno::TIMEDOUT || err == Errno::INPROGRESS) {
247 // These happen during normal operation, so only log them at debug level. 264 // These happen during normal operation, so only log them at debug level.
248 LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); 265 LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e));
@@ -731,13 +748,17 @@ std::pair<s32, Errno> Socket::Send(std::span<const u8> message, int flags) {
731 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); 748 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
732 ASSERT(flags == 0); 749 ASSERT(flags == 0);
733 750
751 int native_flags = 0;
752#if YUZU_UNIX
753 native_flags |= MSG_NOSIGNAL; // do not send us SIGPIPE
754#endif
734 const auto result = send(fd, reinterpret_cast<const char*>(message.data()), 755 const auto result = send(fd, reinterpret_cast<const char*>(message.data()),
735 static_cast<int>(message.size()), 0); 756 static_cast<int>(message.size()), native_flags);
736 if (result != SOCKET_ERROR) { 757 if (result != SOCKET_ERROR) {
737 return {static_cast<s32>(result), Errno::SUCCESS}; 758 return {static_cast<s32>(result), Errno::SUCCESS};
738 } 759 }
739 760
740 return {-1, GetAndLogLastError()}; 761 return {-1, GetAndLogLastError(CallType::Send)};
741} 762}
742 763
743std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message, 764std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
@@ -759,7 +780,7 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
759 return {static_cast<s32>(result), Errno::SUCCESS}; 780 return {static_cast<s32>(result), Errno::SUCCESS};
760 } 781 }
761 782
762 return {-1, GetAndLogLastError()}; 783 return {-1, GetAndLogLastError(CallType::Send)};
763} 784}
764 785
765Errno Socket::Close() { 786Errno Socket::Close() {
diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h
index badcb8369..c7e20ae34 100644
--- a/src/core/internal_network/network.h
+++ b/src/core/internal_network/network.h
@@ -33,10 +33,12 @@ enum class Errno {
33 BADF, 33 BADF,
34 INVAL, 34 INVAL,
35 MFILE, 35 MFILE,
36 PIPE,
36 NOTCONN, 37 NOTCONN,
37 AGAIN, 38 AGAIN,
38 CONNREFUSED, 39 CONNREFUSED,
39 CONNRESET, 40 CONNRESET,
41 CONNABORTED,
40 HOSTUNREACH, 42 HOSTUNREACH,
41 NETDOWN, 43 NETDOWN,
42 NETUNREACH, 44 NETUNREACH,