Implemented NetDll_shutdown.

De-borked LoadFdset/StoreFdset in regards to handling of correct counts
and invalid sockets.
This commit is contained in:
gibbed 2017-01-09 06:56:35 -06:00
parent f3ed9ab91b
commit 2e8c34377f
4 changed files with 44 additions and 15 deletions

View File

@ -317,6 +317,7 @@ using lpunknown_t = const shim::PointerParam&;
template <typename T>
using pointer_t = const shim::TypedPointerParam<T>&;
using int_result_t = shim::Result<int32_t>;
using dword_result_t = shim::Result<uint32_t>;
using pointer_result_t = shim::Result<uint32_t>;

View File

@ -577,6 +577,25 @@ dword_result_t NetDll_closesocket(dword_t caller, dword_t socket_handle) {
DECLARE_XAM_EXPORT(NetDll_closesocket,
ExportTag::kImplemented | ExportTag::kNetworking);
int_result_t NetDll_shutdown(dword_t caller, dword_t socket_handle, int_t how) {
auto socket =
kernel_state()->object_table()->LookupObject<XSocket>(socket_handle);
if (!socket) {
// WSAENOTSOCK
XThread::SetLastError(0x2736);
return -1;
}
auto ret = socket->Shutdown(how);
if (ret == SOCKET_ERROR) {
uint32_t error_code = WSAGetLastError();
XThread::SetLastError(error_code);
}
return ret;
}
DECLARE_XAM_EXPORT(NetDll_shutdown,
ExportTag::kImplemented | ExportTag::kNetworking);
dword_result_t NetDll_setsockopt(dword_t caller, dword_t socket_handle,
dword_t level, dword_t optname,
lpvoid_t optval_ptr, dword_t optlen) {
@ -710,32 +729,38 @@ DECLARE_XAM_EXPORT(NetDll_accept,
void LoadFdset(const uint8_t* src, fd_set* dest) {
dest->fd_count = xe::load_and_swap<uint32_t>(src);
for (int i = 0; i < 64; ++i) {
auto socket_handle =
static_cast<X_HANDLE>(xe::load_and_swap<uint32_t>(src + 4 + i * 4));
if (!socket_handle) {
break;
for (u_int i = 0; i < 64; ++i) {
SOCKET native_handle = INVALID_SOCKET;
if (i < dest->fd_count) {
auto socket_handle =
static_cast<X_HANDLE>(xe::load_and_swap<uint32_t>(src + 4 + i * 4));
if (socket_handle) {
// Convert from Xenia -> native
auto socket = kernel_state()->object_table()->LookupObject<XSocket>(
socket_handle);
assert_not_null(socket);
auto native_handle = socket->native_handle();
dest->fd_array[i] = native_handle;
}
}
// Convert from Xenia -> native
auto socket =
kernel_state()->object_table()->LookupObject<XSocket>(socket_handle);
auto native_handle = socket->native_handle();
dest->fd_array[i] = native_handle;
}
}
void StoreFdset(const fd_set& src, uint8_t* dest) {
xe::store_and_swap<uint32_t>(dest, src.fd_count);
for (int i = 0; i < 64; ++i) {
for (u_int i = 0; i < src.fd_count; ++i) {
SOCKET socket_handle = src.fd_array[i];
// TODO: Native -> Xenia
assert_true(socket_handle >> 32 == 0);
xe::store_and_swap<uint32_t>(dest + 4 + i * 4,
static_cast<uint32_t>(socket_handle));
if (socket_handle != INVALID_SOCKET) {
assert_true(socket_handle >> 32 == 0);
xe::store_and_swap<uint32_t>(dest + 4 + i * 4,
static_cast<uint32_t>(socket_handle));
} else {
xe::store_and_swap<uint32_t>(dest + 4 + i * 4, -1);
}
}
}

View File

@ -150,6 +150,8 @@ object_ref<XSocket> XSocket::Accept(N_XSOCKADDR* name, int* name_len) {
return socket;
}
int XSocket::Shutdown(int how) { return shutdown(native_handle_, how); }
int XSocket::Recv(uint8_t* buf, uint32_t buf_len, uint32_t flags) {
return recv(native_handle_, reinterpret_cast<char*>(buf), buf_len, flags);
}

View File

@ -104,6 +104,7 @@ class XSocket : public XObject {
X_STATUS Bind(N_XSOCKADDR_IN* name, int name_len);
X_STATUS Listen(int backlog);
object_ref<XSocket> Accept(N_XSOCKADDR* name, int* name_len);
int Shutdown(int how);
int Recv(uint8_t* buf, uint32_t buf_len, uint32_t flags);
int Send(const uint8_t* buf, uint32_t buf_len, uint32_t flags);