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)
|
||||
{
|
||||
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);
|
||||
u32 how = Memory::Read_U32(request.buffer_in + 4);
|
||||
int ret = shutdown(WiiSockMan::GetInstance().GetHostSocket(fd), how);
|
||||
|
||||
return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_SHUTDOWN", false));
|
||||
const u32 fd = Memory::Read_U32(request.buffer_in);
|
||||
const u32 how = Memory::Read_U32(request.buffer_in + 4);
|
||||
WiiSockMan& sm = WiiSockMan::GetInstance();
|
||||
const s32 return_value = sm.ShutdownSocket(fd, how);
|
||||
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)
|
||||
|
|
|
@ -156,6 +156,54 @@ void WiiSocket::SetWiiFd(s32 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 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 ||
|
||||
(!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS &&
|
||||
ReturnValue != -SO_EALREADY) ||
|
||||
|
@ -679,10 +733,18 @@ s32 WiiSockMan::GetHostSocket(s32 wii_fd) const
|
|||
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;
|
||||
auto socket_entry = WiiSockets.find(s);
|
||||
auto socket_entry = WiiSockets.find(wii_fd);
|
||||
if (socket_entry != WiiSockets.end())
|
||||
{
|
||||
ReturnValue = socket_entry->second.CloseFd();
|
||||
|
@ -913,6 +975,11 @@ void WiiSockMan::UpdateWantDeterminism(bool want)
|
|||
Clean();
|
||||
}
|
||||
|
||||
void WiiSocket::sockop::Abort(s32 value)
|
||||
{
|
||||
is_aborted = true;
|
||||
GetIOS()->EnqueueIPCReply(request, value);
|
||||
}
|
||||
#undef ERRORCODE
|
||||
#undef EITHER
|
||||
} // namespace IOS::HLE
|
||||
|
|
|
@ -186,16 +186,19 @@ private:
|
|||
{
|
||||
Request request;
|
||||
bool is_ssl;
|
||||
bool is_aborted = false;
|
||||
union
|
||||
{
|
||||
NET_IOCTL net_type;
|
||||
SSL_IOCTL ssl_type;
|
||||
};
|
||||
void Abort(s32 value);
|
||||
};
|
||||
|
||||
friend class WiiSockMan;
|
||||
void SetFd(s32 s);
|
||||
void SetWiiFd(s32 s);
|
||||
s32 Shutdown(u32 how);
|
||||
s32 CloseFd();
|
||||
s32 FCntl(u32 cmd, u32 arg);
|
||||
|
||||
|
@ -246,7 +249,8 @@ public:
|
|||
s32 AddSocket(s32 fd, bool is_rw);
|
||||
bool IsSocketBlocking(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; }
|
||||
void SetLastNetError(s32 error) { errno_last = error; }
|
||||
void Clean() { WiiSockets.clear(); }
|
||||
|
|
Loading…
Reference in New Issue