Socket: Abort pending operations on shutdown
This commit is contained in:
parent
fb32f1ab88
commit
c63ac38c83
|
@ -402,13 +402,19 @@ IPCCommandResult NetIPTop::HandleDoSockRequest(const IOCtlRequest& request)
|
||||||
|
|
||||||
IPCCommandResult NetIPTop::HandleShutdownRequest(const IOCtlRequest& request)
|
IPCCommandResult NetIPTop::HandleShutdownRequest(const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
request.Log(GetDeviceName(), Common::Log::IOS_WC24);
|
if (request.buffer_in == 0 || request.buffer_in_size < 8)
|
||||||
|
{
|
||||||
|
ERROR_LOG(IOS_NET, "IOCTL_SO_SHUTDOWN = EINVAL, BufferIn: (%08x, %i)", request.buffer_in,
|
||||||
|
request.buffer_in_size);
|
||||||
|
return GetDefaultReply(-SO_EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
u32 fd = Memory::Read_U32(request.buffer_in);
|
const u32 fd = Memory::Read_U32(request.buffer_in);
|
||||||
u32 how = Memory::Read_U32(request.buffer_in + 4);
|
const u32 how = Memory::Read_U32(request.buffer_in + 4);
|
||||||
int ret = shutdown(WiiSockMan::GetInstance().GetHostSocket(fd), how);
|
WiiSockMan& sm = WiiSockMan::GetInstance();
|
||||||
|
const s32 return_value = sm.ShutdownSocket(fd, how);
|
||||||
return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_SHUTDOWN", false));
|
INFO_LOG(IOS_NET, "IOCTL_SO_SHUTDOWN(fd=%d, how=%d) = %d", fd, how, return_value);
|
||||||
|
return GetDefaultReply(return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult NetIPTop::HandleListenRequest(const IOCtlRequest& request)
|
IPCCommandResult NetIPTop::HandleListenRequest(const IOCtlRequest& request)
|
||||||
|
|
|
@ -156,6 +156,54 @@ void WiiSocket::SetWiiFd(s32 s)
|
||||||
wii_fd = s;
|
wii_fd = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 WiiSocket::Shutdown(u32 how)
|
||||||
|
{
|
||||||
|
if (how > 2)
|
||||||
|
return -SO_EINVAL;
|
||||||
|
|
||||||
|
// The Wii does nothing and returns 0 for IP_PROTO_UDP
|
||||||
|
int so_type;
|
||||||
|
socklen_t opt_len = sizeof(so_type);
|
||||||
|
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, reinterpret_cast<char*>(&so_type), &opt_len) != 0 ||
|
||||||
|
(so_type != SOCK_STREAM && so_type != SOCK_DGRAM))
|
||||||
|
return -SO_EBADF;
|
||||||
|
if (so_type == SOCK_DGRAM)
|
||||||
|
return SO_SUCCESS;
|
||||||
|
|
||||||
|
// Adjust pending operations
|
||||||
|
// Values based on https://dolp.in/pr8758 hwtest
|
||||||
|
const s32 ret = WiiSockMan::GetNetErrorCode(shutdown(fd, how), "SO_SHUTDOWN", false);
|
||||||
|
const bool shut_read = how == 0 || how == 2;
|
||||||
|
const bool shut_write = how == 1 || how == 2;
|
||||||
|
for (auto& op : pending_sockops)
|
||||||
|
{
|
||||||
|
// TODO: Create hwtest for SSL
|
||||||
|
if (op.is_ssl)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (op.net_type)
|
||||||
|
{
|
||||||
|
case IOCTL_SO_ACCEPT:
|
||||||
|
if (shut_write)
|
||||||
|
op.Abort(-SO_EINVAL);
|
||||||
|
break;
|
||||||
|
case IOCTL_SO_CONNECT:
|
||||||
|
if (shut_write && !nonBlock)
|
||||||
|
op.Abort(-SO_ENETUNREACH);
|
||||||
|
break;
|
||||||
|
case IOCTLV_SO_RECVFROM:
|
||||||
|
if (shut_read)
|
||||||
|
op.Abort(-SO_ENOTCONN);
|
||||||
|
break;
|
||||||
|
case IOCTLV_SO_SENDTO:
|
||||||
|
if (shut_write)
|
||||||
|
op.Abort(-SO_ENOTCONN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
s32 WiiSocket::CloseFd()
|
s32 WiiSocket::CloseFd()
|
||||||
{
|
{
|
||||||
s32 ReturnValue = 0;
|
s32 ReturnValue = 0;
|
||||||
|
@ -586,6 +634,12 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (it->is_aborted)
|
||||||
|
{
|
||||||
|
it = pending_sockops.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (nonBlock || forceNonBlock ||
|
if (nonBlock || forceNonBlock ||
|
||||||
(!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS &&
|
(!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS &&
|
||||||
ReturnValue != -SO_EALREADY) ||
|
ReturnValue != -SO_EALREADY) ||
|
||||||
|
@ -679,10 +733,18 @@ s32 WiiSockMan::GetHostSocket(s32 wii_fd) const
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 WiiSockMan::DeleteSocket(s32 s)
|
s32 WiiSockMan::ShutdownSocket(s32 wii_fd, u32 how)
|
||||||
|
{
|
||||||
|
auto socket_entry = WiiSockets.find(wii_fd);
|
||||||
|
if (socket_entry != WiiSockets.end())
|
||||||
|
return socket_entry->second.Shutdown(how);
|
||||||
|
return -SO_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 WiiSockMan::DeleteSocket(s32 wii_fd)
|
||||||
{
|
{
|
||||||
s32 ReturnValue = -SO_EBADF;
|
s32 ReturnValue = -SO_EBADF;
|
||||||
auto socket_entry = WiiSockets.find(s);
|
auto socket_entry = WiiSockets.find(wii_fd);
|
||||||
if (socket_entry != WiiSockets.end())
|
if (socket_entry != WiiSockets.end())
|
||||||
{
|
{
|
||||||
ReturnValue = socket_entry->second.CloseFd();
|
ReturnValue = socket_entry->second.CloseFd();
|
||||||
|
@ -913,6 +975,11 @@ void WiiSockMan::UpdateWantDeterminism(bool want)
|
||||||
Clean();
|
Clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WiiSocket::sockop::Abort(s32 value)
|
||||||
|
{
|
||||||
|
is_aborted = true;
|
||||||
|
GetIOS()->EnqueueIPCReply(request, value);
|
||||||
|
}
|
||||||
#undef ERRORCODE
|
#undef ERRORCODE
|
||||||
#undef EITHER
|
#undef EITHER
|
||||||
} // namespace IOS::HLE
|
} // namespace IOS::HLE
|
||||||
|
|
|
@ -186,16 +186,19 @@ private:
|
||||||
{
|
{
|
||||||
Request request;
|
Request request;
|
||||||
bool is_ssl;
|
bool is_ssl;
|
||||||
|
bool is_aborted = false;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
NET_IOCTL net_type;
|
NET_IOCTL net_type;
|
||||||
SSL_IOCTL ssl_type;
|
SSL_IOCTL ssl_type;
|
||||||
};
|
};
|
||||||
|
void Abort(s32 value);
|
||||||
};
|
};
|
||||||
|
|
||||||
friend class WiiSockMan;
|
friend class WiiSockMan;
|
||||||
void SetFd(s32 s);
|
void SetFd(s32 s);
|
||||||
void SetWiiFd(s32 s);
|
void SetWiiFd(s32 s);
|
||||||
|
s32 Shutdown(u32 how);
|
||||||
s32 CloseFd();
|
s32 CloseFd();
|
||||||
s32 FCntl(u32 cmd, u32 arg);
|
s32 FCntl(u32 cmd, u32 arg);
|
||||||
|
|
||||||
|
@ -246,7 +249,8 @@ public:
|
||||||
s32 AddSocket(s32 fd, bool is_rw);
|
s32 AddSocket(s32 fd, bool is_rw);
|
||||||
bool IsSocketBlocking(s32 wii_fd) const;
|
bool IsSocketBlocking(s32 wii_fd) const;
|
||||||
s32 GetHostSocket(s32 wii_fd) const;
|
s32 GetHostSocket(s32 wii_fd) const;
|
||||||
s32 DeleteSocket(s32 s);
|
s32 ShutdownSocket(s32 wii_fd, u32 how);
|
||||||
|
s32 DeleteSocket(s32 wii_fd);
|
||||||
s32 GetLastNetError() const { return errno_last; }
|
s32 GetLastNetError() const { return errno_last; }
|
||||||
void SetLastNetError(s32 error) { errno_last = error; }
|
void SetLastNetError(s32 error) { errno_last = error; }
|
||||||
void Clean() { WiiSockets.clear(); }
|
void Clean() { WiiSockets.clear(); }
|
||||||
|
|
Loading…
Reference in New Issue