mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
Better (and portable) fd_set handling for NetDll_select, and properly tracks guest handles as well.
This commit is contained in:
parent
d43af82889
commit
5cbb542fa3
|
|
@ -727,38 +727,47 @@ dword_result_t NetDll_accept(dword_t caller, dword_t socket_handle,
|
||||||
DECLARE_XAM_EXPORT(NetDll_accept,
|
DECLARE_XAM_EXPORT(NetDll_accept,
|
||||||
ExportTag::kImplemented | ExportTag::kNetworking);
|
ExportTag::kImplemented | ExportTag::kNetworking);
|
||||||
|
|
||||||
void LoadFdset(const uint8_t* src, fd_set* dest) {
|
typedef struct x_fd_set {
|
||||||
dest->fd_count = xe::load_and_swap<uint32_t>(src);
|
xe::be<uint32_t> fd_count;
|
||||||
for (u_int i = 0; i < 64; ++i) {
|
xe::be<uint32_t> fd_array[64];
|
||||||
SOCKET native_handle = INVALID_SOCKET;
|
} x_fd_set;
|
||||||
if (i < dest->fd_count) {
|
|
||||||
auto socket_handle =
|
struct host_set {
|
||||||
static_cast<X_HANDLE>(xe::load_and_swap<uint32_t>(src + 4 + i * 4));
|
uint32_t fd_count;
|
||||||
if (socket_handle) {
|
object_ref<XSocket> sockets[64];
|
||||||
// Convert from Xenia -> native
|
};
|
||||||
auto socket = kernel_state()->object_table()->LookupObject<XSocket>(
|
|
||||||
socket_handle);
|
void LoadFdset(const x_fd_set* guest_set, host_set* host_set) {
|
||||||
assert_not_null(socket);
|
assert_true(guest_set->fd_count < 64);
|
||||||
native_handle = socket->native_handle();
|
host_set->fd_count = guest_set->fd_count;
|
||||||
}
|
for (uint32_t i = 0; i < host_set->fd_count; ++i) {
|
||||||
|
auto socket_handle = static_cast<X_HANDLE>(guest_set->fd_array[i]);
|
||||||
|
if (socket_handle == -1) {
|
||||||
|
host_set->fd_count = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
dest->fd_array[i] = native_handle;
|
// Convert from Xenia -> native
|
||||||
|
auto socket =
|
||||||
|
kernel_state()->object_table()->LookupObject<XSocket>(socket_handle);
|
||||||
|
assert_not_null(socket);
|
||||||
|
host_set->sockets[i] = socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoreFdset(const fd_set& src, uint8_t* dest) {
|
void ImportFdset(host_set* host_set, fd_set* native_set) {
|
||||||
xe::store_and_swap<uint32_t>(dest, src.fd_count);
|
FD_ZERO(native_set);
|
||||||
for (u_int i = 0; i < src.fd_count; ++i) {
|
for (uint32_t i = 0; i < host_set->fd_count; ++i) {
|
||||||
SOCKET socket_handle = src.fd_array[i];
|
FD_SET(host_set->sockets[i]->native_handle(), native_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Native -> Xenia
|
void StoreFdset(fd_set* native_set, host_set* host_set, x_fd_set* guest_set) {
|
||||||
|
guest_set->fd_count = 0;
|
||||||
if (socket_handle != INVALID_SOCKET) {
|
for (uint32_t i = 0; i < host_set->fd_count; ++i) {
|
||||||
assert_true(socket_handle >> 32 == 0);
|
auto socket = host_set->sockets[i];
|
||||||
xe::store_and_swap<uint32_t>(dest + 4 + i * 4,
|
auto native_handle = socket->native_handle();
|
||||||
static_cast<uint32_t>(socket_handle));
|
if (FD_ISSET(native_handle, native_set)) {
|
||||||
} else {
|
guest_set->fd_array[guest_set->fd_count++] = socket->handle();
|
||||||
xe::store_and_swap<uint32_t>(dest + 4 + i * 4, -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -775,17 +784,23 @@ SHIM_CALL NetDll_select_shim(PPCContext* ppc_context,
|
||||||
XELOGD("NetDll_select(%d, %d, %.8X, %.8X, %.8X, %.8X)", caller, nfds,
|
XELOGD("NetDll_select(%d, %d, %.8X, %.8X, %.8X, %.8X)", caller, nfds,
|
||||||
readfds_ptr, writefds_ptr, exceptfds_ptr, timeout_ptr);
|
readfds_ptr, writefds_ptr, exceptfds_ptr, timeout_ptr);
|
||||||
|
|
||||||
|
host_set hostreadfds = {0};
|
||||||
fd_set readfds = {0};
|
fd_set readfds = {0};
|
||||||
if (readfds_ptr) {
|
if (readfds_ptr) {
|
||||||
LoadFdset(SHIM_MEM_ADDR(readfds_ptr), &readfds);
|
LoadFdset((x_fd_set*)SHIM_MEM_ADDR(readfds_ptr), &hostreadfds);
|
||||||
|
ImportFdset(&hostreadfds, &readfds);
|
||||||
}
|
}
|
||||||
|
host_set hostwritefds = {0};
|
||||||
fd_set writefds = {0};
|
fd_set writefds = {0};
|
||||||
if (writefds_ptr) {
|
if (writefds_ptr) {
|
||||||
LoadFdset(SHIM_MEM_ADDR(writefds_ptr), &writefds);
|
LoadFdset((x_fd_set*)SHIM_MEM_ADDR(writefds_ptr), &hostwritefds);
|
||||||
|
ImportFdset(&hostwritefds, &writefds);
|
||||||
}
|
}
|
||||||
|
host_set hostexceptfds = {0};
|
||||||
fd_set exceptfds = {0};
|
fd_set exceptfds = {0};
|
||||||
if (exceptfds_ptr) {
|
if (exceptfds_ptr) {
|
||||||
LoadFdset(SHIM_MEM_ADDR(exceptfds_ptr), &exceptfds);
|
LoadFdset((x_fd_set*)SHIM_MEM_ADDR(exceptfds_ptr), &hostexceptfds);
|
||||||
|
ImportFdset(&hostexceptfds, &exceptfds);
|
||||||
}
|
}
|
||||||
timeval* timeout_in = nullptr;
|
timeval* timeout_in = nullptr;
|
||||||
timeval timeout;
|
timeval timeout;
|
||||||
|
|
@ -801,15 +816,18 @@ SHIM_CALL NetDll_select_shim(PPCContext* ppc_context,
|
||||||
writefds_ptr ? &writefds : nullptr,
|
writefds_ptr ? &writefds : nullptr,
|
||||||
exceptfds_ptr ? &exceptfds : nullptr, timeout_in);
|
exceptfds_ptr ? &exceptfds : nullptr, timeout_in);
|
||||||
if (readfds_ptr) {
|
if (readfds_ptr) {
|
||||||
StoreFdset(readfds, SHIM_MEM_ADDR(readfds_ptr));
|
StoreFdset(&readfds, &hostreadfds, (x_fd_set*)SHIM_MEM_ADDR(readfds_ptr));
|
||||||
}
|
}
|
||||||
if (writefds_ptr) {
|
if (writefds_ptr) {
|
||||||
StoreFdset(writefds, SHIM_MEM_ADDR(writefds_ptr));
|
StoreFdset(&writefds, &hostwritefds,
|
||||||
|
(x_fd_set*)SHIM_MEM_ADDR(writefds_ptr));
|
||||||
}
|
}
|
||||||
if (exceptfds_ptr) {
|
if (exceptfds_ptr) {
|
||||||
StoreFdset(exceptfds, SHIM_MEM_ADDR(exceptfds_ptr));
|
StoreFdset(&exceptfds, &hostexceptfds,
|
||||||
|
(x_fd_set*)SHIM_MEM_ADDR(exceptfds_ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(gibbed): modify ret to be what's actually copied to the guest fd_sets?
|
||||||
SHIM_SET_RETURN_32(ret);
|
SHIM_SET_RETURN_32(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue