mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 18:15:14 +00:00
Extract EpollTable from net
This commit is contained in:
parent
980732d65b
commit
52107fa5ad
@ -378,6 +378,8 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
|||||||
src/core/libraries/network/net_ctl_codes.h
|
src/core/libraries/network/net_ctl_codes.h
|
||||||
src/core/libraries/network/net_util.cpp
|
src/core/libraries/network/net_util.cpp
|
||||||
src/core/libraries/network/net_util.h
|
src/core/libraries/network/net_util.h
|
||||||
|
src/core/libraries/network/net_epoll.cpp
|
||||||
|
src/core/libraries/network/net_epoll.h
|
||||||
src/core/libraries/network/net_error.h
|
src/core/libraries/network/net_error.h
|
||||||
src/core/libraries/network/net.h
|
src/core/libraries/network/net.h
|
||||||
src/core/libraries/network/ssl.cpp
|
src/core/libraries/network/ssl.cpp
|
||||||
|
@ -20,45 +20,15 @@
|
|||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/libraries/network/net.h"
|
#include "core/libraries/network/net.h"
|
||||||
|
#include "net_epoll.h"
|
||||||
#include "net_error.h"
|
#include "net_error.h"
|
||||||
#include "net_util.h"
|
#include "net_util.h"
|
||||||
#include "netctl.h"
|
#include "netctl.h"
|
||||||
#include "sockets.h"
|
#include "sockets.h"
|
||||||
#include "sys_net.h"
|
#include "sys_net.h"
|
||||||
#ifdef __linux__
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Libraries::Net {
|
namespace Libraries::Net {
|
||||||
|
|
||||||
struct Epoll {
|
|
||||||
std::vector<std::pair<u32 /*netId*/, OrbisNetEpollEvent>> events{};
|
|
||||||
const char* name;
|
|
||||||
int epoll_fd;
|
|
||||||
|
|
||||||
explicit Epoll(const char* name_) : name(name_), epoll_fd(epoll_create1(0)) {
|
|
||||||
ASSERT(epoll_fd != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Destroyed() const noexcept {
|
|
||||||
return destroyed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Destroy() noexcept {
|
|
||||||
events.clear();
|
|
||||||
close(epoll_fd);
|
|
||||||
epoll_fd = -1;
|
|
||||||
name = nullptr;
|
|
||||||
destroyed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool destroyed{};
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Epoll> epolls;
|
|
||||||
std::mutex epolls_mutex;
|
|
||||||
|
|
||||||
static thread_local int32_t net_errno = 0;
|
static thread_local int32_t net_errno = 0;
|
||||||
|
|
||||||
static bool g_isNetInitialized = true; // TODO init it properly
|
static bool g_isNetInitialized = true; // TODO init it properly
|
||||||
@ -705,50 +675,18 @@ int PS4_SYSV_ABI sceNetEpollAbort() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ConvertEpollEventsIn(u32 orbis_events) {
|
|
||||||
u32 ret = 0;
|
|
||||||
|
|
||||||
if ((orbis_events & ORBIS_NET_EPOLLIN) != 0) {
|
|
||||||
ret |= EPOLLIN;
|
|
||||||
}
|
|
||||||
if ((orbis_events & ORBIS_NET_EPOLLOUT) != 0) {
|
|
||||||
ret |= EPOLLOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 ConvertEpollEventsOut(u32 epoll_events) {
|
|
||||||
u32 ret = 0;
|
|
||||||
|
|
||||||
if ((epoll_events & EPOLLIN) != 0) {
|
|
||||||
ret |= ORBIS_NET_EPOLLIN;
|
|
||||||
}
|
|
||||||
if ((epoll_events & EPOLLOUT) != 0) {
|
|
||||||
ret |= ORBIS_NET_EPOLLOUT;
|
|
||||||
}
|
|
||||||
if ((epoll_events & EPOLLERR) != 0) {
|
|
||||||
ret |= ORBIS_NET_EPOLLERR;
|
|
||||||
}
|
|
||||||
if ((epoll_events & EPOLLHUP) != 0) {
|
|
||||||
ret |= ORBIS_NET_EPOLLHUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, OrbisNetId id,
|
int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, OrbisNetId id,
|
||||||
OrbisNetEpollEvent* event) {
|
OrbisNetEpollEvent* event) {
|
||||||
LOG_WARNING(Lib_Net, "called, epollid = {}, op = {}, id = {}", epollid,
|
LOG_WARNING(Lib_Net, "called, epollid = {}, op = {}, id = {}", epollid,
|
||||||
magic_enum::enum_name(op), id);
|
magic_enum::enum_name(op), id);
|
||||||
|
|
||||||
std::scoped_lock lock{epolls_mutex};
|
auto epoll = Common::Singleton<EpollTable>::Instance()->GetEpoll(epollid);
|
||||||
if (epollid >= epolls.size() || epolls[epollid].Destroyed()) {
|
if (!epoll) {
|
||||||
return -ORBIS_NET_EBADF;
|
return -ORBIS_NET_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto find_id = [&](OrbisNetId id) {
|
auto find_id = [&](OrbisNetId id) {
|
||||||
return std::ranges::find_if(epolls[epollid].events,
|
return std::ranges::find_if(epoll->events,
|
||||||
[&](const auto& el) { return el.first == id; });
|
[&](const auto& el) { return el.first == id; });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -757,7 +695,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
|||||||
if (event == nullptr) {
|
if (event == nullptr) {
|
||||||
return -ORBIS_NET_EINVAL;
|
return -ORBIS_NET_EINVAL;
|
||||||
}
|
}
|
||||||
if (find_id(id) != epolls[epollid].events.end()) {
|
if (find_id(id) != epoll->events.end()) {
|
||||||
return -ORBIS_NET_EEXIST;
|
return -ORBIS_NET_EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,10 +709,11 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
|||||||
const auto socket = file->socket;
|
const auto socket = file->socket;
|
||||||
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
||||||
.data = {.fd = id}};
|
.data = {.fd = id}};
|
||||||
ASSERT(epoll_ctl(epolls[epollid].epoll_fd, EPOLL_CTL_ADD, socket->Native(),
|
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, socket->Native(),
|
||||||
&native_event) == 0);
|
&native_event) == 0);
|
||||||
|
LOG_DEBUG(Lib_Net, "epoll_ctl succeeded");
|
||||||
#endif
|
#endif
|
||||||
epolls[epollid].events.emplace_back(id, *event);
|
epoll->events.emplace_back(id, *event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ORBIS_NET_EPOLL_CTL_MOD: {
|
case ORBIS_NET_EPOLL_CTL_MOD: {
|
||||||
@ -783,7 +722,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto it = find_id(id);
|
auto it = find_id(id);
|
||||||
if (it == epolls[epollid].events.end()) {
|
if (it == epoll->events.end()) {
|
||||||
return -ORBIS_NET_EEXIST;
|
return -ORBIS_NET_EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,15 +736,15 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto it = find_id(id);
|
auto it = find_id(id);
|
||||||
if (it == epolls[epollid].events.end()) {
|
if (it == epoll->events.end()) {
|
||||||
return -ORBIS_NET_EBADF;
|
return -ORBIS_NET_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
const auto socket = Common::Singleton<NetInternal>::Instance()->socks[id];
|
const auto socket = Common::Singleton<NetInternal>::Instance()->socks[id];
|
||||||
ASSERT(epoll_ctl(epolls[epollid].epoll_fd, EPOLL_CTL_DEL, socket->Native(), nullptr) == 0);
|
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, socket->Native(), nullptr) == 0);
|
||||||
#endif
|
#endif
|
||||||
epolls[epollid].events.erase(it);
|
epoll->events.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -821,30 +760,20 @@ int PS4_SYSV_ABI sceNetEpollCreate(const char* name, int flags) {
|
|||||||
return -ORBIS_NET_EINVAL;
|
return -ORBIS_NET_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lock{epolls_mutex};
|
auto epoll = Common::Singleton<EpollTable>::Instance()->CreateHandle(name);
|
||||||
if (auto it = std::ranges::find_if(epolls, [](const Epoll& e) { return e.Destroyed(); });
|
|
||||||
it != epolls.end()) {
|
return epoll;
|
||||||
*it = Epoll(name);
|
|
||||||
const auto ret = std::distance(epolls.begin(), it);
|
|
||||||
LOG_DEBUG(Lib_Net, "epollid = {}", ret);
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
epolls.emplace_back(name);
|
|
||||||
const auto ret = epolls.size() - 1;
|
|
||||||
LOG_DEBUG(Lib_Net, "epollid = {}", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid) {
|
int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid) {
|
||||||
LOG_INFO(Lib_Net, "called, epollid = {}", epollid);
|
LOG_INFO(Lib_Net, "called, epollid = {}", epollid);
|
||||||
|
|
||||||
std::scoped_lock lock{epolls_mutex};
|
auto epoll = Common::Singleton<EpollTable>::Instance()->GetEpoll(epollid);
|
||||||
if (epollid >= epolls.size() || epolls[epollid].Destroyed()) {
|
if (!epoll) {
|
||||||
return -ORBIS_NET_EBADF;
|
return -ORBIS_NET_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
epolls[epollid].Destroy();
|
epoll->Destroy();
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
@ -854,13 +783,13 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events,
|
|||||||
LOG_WARNING(Lib_Net, "called, epollid = {}, maxevents = {}, timeout = {}", epollid, maxevents,
|
LOG_WARNING(Lib_Net, "called, epollid = {}, maxevents = {}, timeout = {}", epollid, maxevents,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
std::scoped_lock lock{epolls_mutex};
|
auto epoll = Common::Singleton<EpollTable>::Instance()->GetEpoll(epollid);
|
||||||
if (epollid >= epolls.size() || epolls[epollid].Destroyed()) {
|
if (!epoll) {
|
||||||
return -ORBIS_NET_EBADF;
|
return -ORBIS_NET_EBADF;
|
||||||
}
|
}
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
std::vector<epoll_event> native_events{static_cast<size_t>(maxevents)};
|
std::vector<epoll_event> native_events{static_cast<size_t>(maxevents)};
|
||||||
int result = epoll_wait(epolls[epollid].epoll_fd, native_events.data(), maxevents,
|
int result = epoll_wait(epoll->epoll_fd, native_events.data(), maxevents,
|
||||||
timeout == -1 ? timeout : timeout / 1000);
|
timeout == -1 ? timeout : timeout / 1000);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
LOG_ERROR(Lib_Net, "epoll_wait failed with {}", Common::GetLastErrorMsg());
|
LOG_ERROR(Lib_Net, "epoll_wait failed with {}", Common::GetLastErrorMsg());
|
||||||
@ -873,10 +802,10 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events,
|
|||||||
const auto& current_event = native_events[i];
|
const auto& current_event = native_events[i];
|
||||||
LOG_INFO(Lib_Net, "native_event[{}] = ( .events = {}, .data = {:#x} )", i,
|
LOG_INFO(Lib_Net, "native_event[{}] = ( .events = {}, .data = {:#x} )", i,
|
||||||
current_event.events, current_event.data.u64);
|
current_event.events, current_event.data.u64);
|
||||||
const auto it = std::ranges::find_if(epolls[epollid].events, [&](auto& el) {
|
const auto it = std::ranges::find_if(epoll->events, [&](auto& el) {
|
||||||
return el.first == current_event.data.fd;
|
return el.first == current_event.data.fd;
|
||||||
});
|
});
|
||||||
ASSERT(it != epolls[epollid].events.end());
|
ASSERT(it != epoll->events.end());
|
||||||
events[i] = {
|
events[i] = {
|
||||||
.events = ConvertEpollEventsOut(current_event.events),
|
.events = ConvertEpollEventsOut(current_event.events),
|
||||||
.ident = static_cast<u64>(current_event.data.fd),
|
.ident = static_cast<u64>(current_event.data.fd),
|
||||||
|
68
src/core/libraries/network/net_epoll.cpp
Normal file
68
src/core/libraries/network/net_epoll.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "net_epoll.h"
|
||||||
|
|
||||||
|
namespace Libraries::Net {
|
||||||
|
|
||||||
|
u32 ConvertEpollEventsIn(u32 orbis_events) {
|
||||||
|
u32 ret = 0;
|
||||||
|
|
||||||
|
if ((orbis_events & ORBIS_NET_EPOLLIN) != 0) {
|
||||||
|
ret |= EPOLLIN;
|
||||||
|
}
|
||||||
|
if ((orbis_events & ORBIS_NET_EPOLLOUT) != 0) {
|
||||||
|
ret |= EPOLLOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ConvertEpollEventsOut(u32 epoll_events) {
|
||||||
|
u32 ret = 0;
|
||||||
|
|
||||||
|
if ((epoll_events & EPOLLIN) != 0) {
|
||||||
|
ret |= ORBIS_NET_EPOLLIN;
|
||||||
|
}
|
||||||
|
if ((epoll_events & EPOLLOUT) != 0) {
|
||||||
|
ret |= ORBIS_NET_EPOLLOUT;
|
||||||
|
}
|
||||||
|
if ((epoll_events & EPOLLERR) != 0) {
|
||||||
|
ret |= ORBIS_NET_EPOLLERR;
|
||||||
|
}
|
||||||
|
if ((epoll_events & EPOLLHUP) != 0) {
|
||||||
|
ret |= ORBIS_NET_EPOLLHUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EpollTable::CreateHandle(const char* name) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
|
if (auto it = std::ranges::find_if(epolls, [](const Epoll& e) { return e.Destroyed(); });
|
||||||
|
it != epolls.end()) {
|
||||||
|
*it = Epoll(name);
|
||||||
|
const auto ret = std::distance(epolls.begin(), it);
|
||||||
|
LOG_DEBUG(Lib_Net, "epollid = {}", ret);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
epolls.emplace_back(name);
|
||||||
|
const auto ret = epolls.size() - 1;
|
||||||
|
LOG_DEBUG(Lib_Net, "epollid = {}", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpollTable::DeleteHandle(int d) {
|
||||||
|
UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Epoll* EpollTable::GetEpoll(int d) {
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Libraries::Net
|
61
src/core/libraries/network/net_epoll.h
Normal file
61
src/core/libraries/network/net_epoll.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "core/libraries/network/net.h"
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Libraries::Net {
|
||||||
|
|
||||||
|
struct Epoll {
|
||||||
|
std::vector<std::pair<u32 /*netId*/, OrbisNetEpollEvent>> events{};
|
||||||
|
const char* name;
|
||||||
|
int epoll_fd;
|
||||||
|
|
||||||
|
explicit Epoll(const char* name_) : name(name_), epoll_fd(epoll_create1(0)) {
|
||||||
|
ASSERT(epoll_fd != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Destroyed() const noexcept {
|
||||||
|
return destroyed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destroy() noexcept {
|
||||||
|
events.clear();
|
||||||
|
close(epoll_fd);
|
||||||
|
epoll_fd = -1;
|
||||||
|
name = nullptr;
|
||||||
|
destroyed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool destroyed{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
u32 ConvertEpollEventsIn(u32 orbis_events);
|
||||||
|
u32 ConvertEpollEventsOut(u32 epoll_events);
|
||||||
|
|
||||||
|
class EpollTable {
|
||||||
|
public:
|
||||||
|
EpollTable() = default;
|
||||||
|
virtual ~EpollTable() = default;
|
||||||
|
|
||||||
|
int CreateHandle(const char* name);
|
||||||
|
void DeleteHandle(int d);
|
||||||
|
Epoll* GetEpoll(int d);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Epoll> epolls;
|
||||||
|
std::mutex m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Net
|
Loading…
Reference in New Issue
Block a user