mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
upd proAdhoc
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)")));
|
||||
|
||||
Reference in New Issue
Block a user