upd proAdhoc

This commit is contained in:
MMaZaHaKa
2026-01-16 06:17:03 +02:00
parent 21611bfb52
commit aa350b3082
8 changed files with 156 additions and 15 deletions
+133
View File
@@ -54,6 +54,139 @@ void Shutdown()
#endif
}
bool HostPortExists(const std::string& host, int port, int timeout_ms) {
if (host.empty() || (port <= 0 || port > 65535) || timeout_ms < 0) return false;
addrinfo hints;
addrinfo* res = nullptr;
std::memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM; // TCP
hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
int gai = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res);
if (gai != 0) {
// getaddrinfo failed (DNS resolve failed or bad port)
return false;
}
bool ok = false;
for (addrinfo* p = res; p != nullptr && !ok; p = p->ai_next) {
// create socket
int sockfd =
#ifdef _WIN32
(int)socket(p->ai_family, p->ai_socktype, p->ai_protocol);
#else
socket(p->ai_family, p->ai_socktype, p->ai_protocol);
#endif
if (sockfd < 0) {
continue;
}
// make non-blocking
#ifdef _WIN32
unsigned long mode = 1;
ioctlsocket((SOCKET)sockfd, FIONBIO, &mode);
#else
int flags = fcntl(sockfd, F_GETFL, 0);
if (flags == -1) flags = 0;
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
#endif
// try connect
int conn = connect(sockfd, p->ai_addr, (int)p->ai_addrlen);
#ifdef _WIN32
if (conn == 0) {
ok = true; // immediate success
}
else {
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS) {
// fall through to select
}
else {
// immediate failure
}
}
#else
if (conn == 0) {
ok = true; // immediate success
}
else {
if (errno == EINPROGRESS) {
// fall through to select
}
else {
// immediate failure
}
}
#endif
if (!ok) {
// wait for writable with timeout
fd_set writefds;
FD_ZERO(&writefds);
#ifdef _WIN32
FD_SET((SOCKET)sockfd, &writefds);
#else
FD_SET(sockfd, &writefds);
#endif
fd_set exceptfds;
FD_ZERO(&exceptfds);
#ifdef _WIN32
FD_SET((SOCKET)sockfd, &exceptfds);
#else
FD_SET(sockfd, &exceptfds);
#endif
timeval tv;
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
int sel = select(
#ifdef _WIN32
0,
#else
sockfd + 1,
#endif
nullptr, &writefds, &exceptfds, &tv);
if (sel > 0) {
// check for error on socket
int sock_err = 0;
socklen_t len = sizeof(sock_err);
#ifdef _WIN32
int ret = getsockopt((SOCKET)sockfd, SOL_SOCKET, SO_ERROR, (char*)&sock_err, &len);
#else
int ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sock_err, &len);
#endif
#ifdef _WIN32
bool writable = FD_ISSET(static_cast<SOCKET>(sockfd), &writefds) != 0;
#else
bool writable = FD_ISSET(sockfd, &writefds) != 0;
#endif
if (ret == 0 && sock_err == 0 && writable) {
ok = true;
}
}
// else timeout or error -> try next addr
}
// close socket
#ifdef _WIN32
closesocket((SOCKET)sockfd);
#else
close(sockfd);
#endif
}
freeaddrinfo(res);
return ok;
}
// NOTE: Due to the nature of getaddrinfo, this can block indefinitely. Not good.
bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error, DNSType type) {
#if PPSSPP_PLATFORM(SWITCH)
+2
View File
@@ -18,6 +18,8 @@ enum class DNSType {
IPV6 = 2,
};
bool HostPortExists(const std::string& host, int port, int timeout_ms);
bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error, DNSType type = DNSType::ANY);
void DNSResolveFree(addrinfo *res);
bool GetLocalIP4List(std::vector<std::string>& IP4s);
+1 -1
View File
@@ -1011,7 +1011,7 @@ static const ConfigSetting controlSettings[] = {
static const ConfigSetting networkSettings[] = {
ConfigSetting("EnableWlan", SETTING(g_Config, bEnableWlan), false, CfgFlag::PER_GAME),
ConfigSetting("EnableAdhocServer", SETTING(g_Config, bEnableAdhocServer), false, CfgFlag::PER_GAME),
ConfigSetting("proAdhocServer", SETTING(g_Config, proAdhocServer), "socom.cc", CfgFlag::PER_GAME),
ConfigSetting("proAdhocServer", SETTING(g_Config, sProAdhocServer), "socom.cc", CfgFlag::PER_GAME),
ConfigSetting("proAdhocServerList", SETTING(g_Config, proAdhocServerList), &defaultProAdhocServerList, CfgFlag::DEFAULT),
ConfigSetting("PortOffset", SETTING(g_Config, iPortOffset), 10000, CfgFlag::PER_GAME),
ConfigSetting("PrimaryDNSServer", SETTING(g_Config, sInfrastructureDNSServer), "67.222.156.250", CfgFlag::PER_GAME),
+1 -1
View File
@@ -538,7 +538,7 @@ public:
// Networking
bool bEnableAdhocServer;
std::string proAdhocServer;
std::string sProAdhocServer;
std::vector<std::string> proAdhocServerList;
std::string sInfrastructureDNSServer;
std::string sInfrastructureUsername; // Username used for Infrastructure play. Different restrictions.
+4 -4
View File
@@ -1353,9 +1353,9 @@ int friendFinder() {
addrinfo* resolved = nullptr;
std::string err;
g_adhocServerIP.in.sin_addr.s_addr = INADDR_NONE;
if (g_Config.bEnableWlan && !net::DNSResolve(g_Config.proAdhocServer, "", &resolved, err)) {
ERROR_LOG(Log::sceNet, "DNS Error Resolving %s\n", g_Config.proAdhocServer.c_str());
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("DNS Error Resolving")) + g_Config.proAdhocServer);
if (g_Config.bEnableWlan && !net::DNSResolve(g_Config.sProAdhocServer, "", &resolved, err)) {
ERROR_LOG(Log::sceNet, "DNS Error Resolving %s\n", g_Config.sProAdhocServer.c_str());
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("DNS Error Resolving")) + g_Config.sProAdhocServer);
}
if (resolved) {
for (auto ptr = resolved; ptr != NULL; ptr = ptr->ai_next) {
@@ -2238,7 +2238,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
sleep_ms(10, "pro-adhoc-socket-poll");
}
if (!done) {
ERROR_LOG(Log::sceNet, "Socket error (%i) when connecting to AdhocServer [%s/%s:%u]", errorcode, g_Config.proAdhocServer.c_str(), ip2str(g_adhocServerIP.in.sin_addr).c_str(), ntohs(g_adhocServerIP.in.sin_port));
ERROR_LOG(Log::sceNet, "Socket error (%i) when connecting to AdhocServer [%s/%s:%u]", errorcode, g_Config.sProAdhocServer.c_str(), ip2str(g_adhocServerIP.in.sin_addr).c_str(), ntohs(g_adhocServerIP.in.sin_port));
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to connect to Adhoc Server")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(errorcode) + ")");
return iResult;
}
+12 -6
View File
@@ -36,9 +36,11 @@
#include "Common/File/FileUtil.h"
#include "Common/TimeUtil.h"
#include "Common/Net/Resolve.h"
#include "Core/Util/PortManager.h"
#include "Core/Instance.h"
#include "Core/Core.h"
#include "Core/Config.h"
#include "Core/HLE/proAdhocServer.h"
#ifdef _WIN32
@@ -344,6 +346,8 @@ static const db_productid default_productids[] = {
{ "ULES01432", "Full Metal Alchemist - Brotherhood" },
{ "ULUS10490", "GTA Chinatown Wars" },
{ "ULUS10160", "GTA Vice City Stories" },
{ "ULUS10041", "GTA Liberty City Stories" },
{ "ULES00151", "GTA Liberty City Stories" },
{ "ULUS10210", "Ghost Rider" },
{ "ULJS00237", "God Eater" },
{ "NPJH50832", "God Eater 2" },
@@ -462,6 +466,7 @@ static const db_productid default_productids[] = {
{ "ULJM05151", "Yu-Gi-Oh! GX Tag Force" },
{ "ULJM05373", "Yu-Gi-Oh! GX Tag Force 3" },
{ "NPUG80086", "flOw" },
// TODO? GTA 10160,beta,10041,00151
};
// Function Prototypes
@@ -1660,7 +1665,13 @@ int proAdhocServerThread(int port) // (int argc, char * argv[])
// Result
int result = 0;
INFO_LOG(Log::sceNet, "AdhocServer: Begin of AdhocServer Thread");
if (net::HostPortExists(g_Config.sProAdhocServer, SERVER_PORT, 200)) {
INFO_LOG(Log::sceNet, "AdhocServer: Skiped starting because the server is already available");
return 0;
}
else {
INFO_LOG(Log::sceNet, "AdhocServer: Begin of AdhocServer Thread");
}
// Create Signal Receiver for CTRL + C
//signal(SIGINT, interrupt);
@@ -1816,11 +1827,6 @@ int create_listen_socket(uint16_t port)
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(port);
// Should only bind to specific IP for the 2nd or more instance of PPSSPP to prevent communication interference issue when sharing the same port. (ie. Capcom Classics Collection Remixed)
if (PPSSPP_ID > 1) {
local.sin_addr = g_localhostIP.in.sin_addr;
}
// Bind Local Address to Socket
int bindresult = bind(fd, (struct sockaddr *)&local, sizeof(local));
+1 -1
View File
@@ -521,7 +521,7 @@ void InitLocalhostIP() {
g_localhostIP.in.sin_addr.s_addr = htonl(localIP);
g_localhostIP.in.sin_port = 0;
std::string serverStr(StripSpaces(g_Config.proAdhocServer));
std::string serverStr(StripSpaces(g_Config.sProAdhocServer));
isLocalServer = (!strcasecmp(serverStr.c_str(), "localhost") || serverStr.find("127.") == 0);
}
+2 -2
View File
@@ -1015,8 +1015,8 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti
networkingSettings->Add(new ItemHeader(n->T("AdHoc server")));
networkingSettings->Add(new CheckBox(&g_Config.bEnableAdhocServer, n->T("Enable built-in PRO Adhoc Server", "Enable built-in PRO Adhoc Server")));
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), I18NCat::NONE))->OnClick.Add([=](UI::EventParams &) {
screenManager()->push(new HostnameSelectScreen(&g_Config.proAdhocServer, &g_Config.proAdhocServerList, n->T("proAdhocServer Address:")));
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sProAdhocServer, n->T("Change proAdhocServer Address"), I18NCat::NONE))->OnClick.Add([=](UI::EventParams &) {
screenManager()->push(new HostnameSelectScreen(&g_Config.sProAdhocServer, &g_Config.proAdhocServerList, n->T("proAdhocServer Address:")));
});
networkingSettings->Add(new SettingHint(n->T("Change proAdhocServer address hint")));
networkingSettings->Add(new ItemHeader(n->T("UPnP (port-forwarding)")));