Skip to content

Commit

Permalink
Merge pull request #13169 from hrydgard/multiple-instance-ANR2ME
Browse files Browse the repository at this point in the history
Multiple instance support (broken out from #13132)
  • Loading branch information
hrydgard committed Jul 20, 2020
2 parents 92bbe97 + fa683bf commit dadffa3
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 13 deletions.
51 changes: 49 additions & 2 deletions Core/HLE/proAdhoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
// This is a direct port of Coldbird's code from http://code.google.com/p/aemu/
// All credit goes to him!

#if !defined(_WIN32)
#include <unistd.h>
#endif

#include <cstring>
#include "util/text/parsers.h"
#include "Core/Core.h"
Expand Down Expand Up @@ -63,6 +67,10 @@ bool chatScreenVisible = false;
bool updateChatScreen = false;
int newChat = 0;

bool isLocalServer = false;
uint8_t PPSSPP_ID = 0;
sockaddr localIP; // This might serves the same purpose with existing "localip" above, but since this is copied from my old code so here it is (too lazy to rewrite the code)

int isLocalMAC(const SceNetEtherAddr * addr) {
SceNetEtherAddr saddr;
getLocalMac(&saddr);
Expand Down Expand Up @@ -1345,7 +1353,7 @@ int getActivePeerCount(void) {
int getLocalIp(sockaddr_in * SocketAddress){
#if defined(_WIN32)
// Get local host name
char szHostName[128] = "";
char szHostName[256] = "";

if(::gethostname(szHostName, sizeof(szHostName))) {
// Error handling
Expand All @@ -1355,11 +1363,26 @@ int getLocalIp(sockaddr_in * SocketAddress){
pHost = ::gethostbyname(szHostName);
if(pHost) {
memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length);
if (isLocalServer) {
SocketAddress->sin_addr = ((sockaddr_in*)&localIP)->sin_addr;
}
return 0;
}
return -1;
#else
memcpy(&SocketAddress->sin_addr, &localip, sizeof(uint32_t));
char szHostName[256] = "";
gethostname(szHostName, sizeof(szHostName));
struct hostent* pHost = 0;
pHost = gethostbyname(szHostName);
if (pHost) {
memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length);
if (isLocalServer) {
SocketAddress->sin_addr = ((sockaddr_in*)&localIP)->sin_addr;
}
return 0;
}
//return -1;
return 0;
#endif
}
Expand All @@ -1369,12 +1392,19 @@ uint32_t getLocalIp(int sock) {
localAddr.sin_addr.s_addr = INADDR_ANY;
socklen_t addrLen = sizeof(localAddr);
getsockname(sock, (struct sockaddr*)&localAddr, &addrLen);
if (isLocalServer) {
localAddr.sin_addr = ((sockaddr_in*)&localIP)->sin_addr;
}
return localAddr.sin_addr.s_addr;
}

void getLocalMac(SceNetEtherAddr * addr){
// Read MAC Address from config
uint8_t mac[ETHER_ADDR_LEN] = {0};
if (PPSSPP_ID > 1) {
memset(&mac, PPSSPP_ID, sizeof(mac));
}
else
if (!ParseMacAddress(g_Config.sMACAddress.c_str(), mac)) {
ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.sMACAddress.c_str());
}
Expand Down Expand Up @@ -1486,6 +1516,23 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
break;
}
}

freeaddrinfo(resultAddr);

// If Server is at localhost Try to Bind socket to specific adapter before connecting to prevent 2nd instance being recognized as already existing 127.0.0.1 by AdhocServer
// (may not works in WinXP/2003 for IPv4 due to "Weak End System" model)
if (((uint8_t*)&serverIp.s_addr)[0] == 0x7f) { // (serverIp.S_un.S_un_b.s_b1 == 0x7f)
int on = 1;
setsockopt(metasocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
setsockopt(metasocket, SOL_SOCKET, SO_DONTROUTE, (const char*)&on, sizeof(on));

((struct sockaddr_in*) & localIP)->sin_port = 0;
// Bind Local Address to Socket
iResult = bind(metasocket, (struct sockaddr*) & localIP, sizeof(sockaddr));
if (iResult == SOCKET_ERROR) {
ERROR_LOG(SCENET, "Bind to alternate localhost[%s] failed(%i).", inet_ntoa(((struct sockaddr_in*) & localIP)->sin_addr), iResult);
}
}

memset(&parameter, 0, sizeof(parameter));
strcpy((char *)&parameter.nickname.data, g_Config.sNickName.c_str());
Expand Down Expand Up @@ -1537,7 +1584,7 @@ bool resolveIP(uint32_t ip, SceNetEtherAddr * mac) {
getLocalIp(&addr);
uint32_t localIp = addr.sin_addr.s_addr;

if (ip == localIp){
if (ip == localIp || ip == ((sockaddr_in*)&localIP)->sin_addr.s_addr){
getLocalMac(mac);
return true;
}
Expand Down
3 changes: 3 additions & 0 deletions Core/HLE/proAdhoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,9 @@ extern SceNetAdhocPtpStat * ptp[255];
extern std::map<int, AdhocctlHandler> adhocctlHandlers;

extern uint16_t portOffset;
extern bool isLocalServer;
extern uint8_t PPSSPP_ID;
extern sockaddr localIP;
extern uint32_t fakePoolSize;
extern SceNetAdhocMatchingContext * contexts;
extern int one;
Expand Down
38 changes: 28 additions & 10 deletions Core/HLE/proAdhocServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ void login_user_stream(int fd, uint32_t ip)

if (u != NULL) { // IP Already existed
uint8_t * ip4 = (uint8_t *)&u->resolver.ip;
INFO_LOG(SCENET, "AdhocServer: Already Existing IP: %u.%u.%u.%u\n", ip4[0], ip4[1], ip4[2], ip4[3]);
WARN_LOG(SCENET, "AdhocServer: Already Existing IP: %u.%u.%u.%u\n", ip4[0], ip4[1], ip4[2], ip4[3]);
}

// Unique IP Address
Expand Down Expand Up @@ -567,6 +567,15 @@ void login_user_data(SceNetAdhocctlUserNode * user, SceNetAdhocctlLoginPacketC2S
// Valid Packet Data
if(valid_product_code == 1 && memcmp(&data->mac, "\xFF\xFF\xFF\xFF\xFF\xFF", sizeof(data->mac)) != 0 && memcmp(&data->mac, "\x00\x00\x00\x00\x00\x00", sizeof(data->mac)) != 0 && data->name.data[0] != 0)
{
// Check for duplicated MAC as most games identify Players by MAC
SceNetAdhocctlUserNode* u = _db_user;
while (u != NULL && !IsMatch(u->resolver.mac, data->mac)) u = u->next;

if (u != NULL) { // MAC Already existed
uint8_t* ip4 = (uint8_t*)&u->resolver.ip;
WARN_LOG(SCENET, "AdhocServer: Already Existing MAC: %02X:%02X:%02X:%02X:%02X:%02X [%u.%u.%u.%u]\n", data->mac.data[0], data->mac.data[1], data->mac.data[2], data->mac.data[3], data->mac.data[4], data->mac.data[5], ip4[0], ip4[1], ip4[2], ip4[3]);
}

// Game Product Override
game_product_override(&data->game);

Expand Down Expand Up @@ -631,7 +640,7 @@ void login_user_data(SceNetAdhocctlUserNode * user, SceNetAdhocctlLoginPacketC2S
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
INFO_LOG(SCENET, "AdhocServer: Invalid Login Packet Contents from %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Invalid Login Packet Contents from %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
}

// Logout User - Out of Memory or Invalid Arguments
Expand Down Expand Up @@ -694,7 +703,7 @@ void logout_user(SceNetAdhocctlUserNode * user)
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
INFO_LOG(SCENET, "AdhocServer: Dropped Connection to %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Dropped Connection to %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
}

// Free Memory
Expand Down Expand Up @@ -907,7 +916,7 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
char safegroupstr2[9];
memset(safegroupstr2, 0, sizeof(safegroupstr2));
strncpy(safegroupstr2, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to join %s group %s without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr, safegroupstr2);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to join %s group %s without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr, safegroupstr2);
}
}

Expand All @@ -922,7 +931,7 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
char safegroupstr[9];
memset(safegroupstr, 0, sizeof(safegroupstr));
strncpy(safegroupstr, (char *)group->data, ADHOCCTL_GROUPNAME_LEN);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to join invalid %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to join invalid %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
}

// Invalid State, Out of Memory or Invalid Group Name
Expand Down Expand Up @@ -1023,7 +1032,7 @@ void disconnect_user(SceNetAdhocctlUserNode * user)
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to leave %s group without joining one first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to leave %s group without joining one first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
}

// Delete User
Expand Down Expand Up @@ -1099,7 +1108,7 @@ void send_scan_results(SceNetAdhocctlUserNode * user)
char safegroupstr[9];
memset(safegroupstr, 0, sizeof(safegroupstr));
strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to scan for %s groups without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to scan for %s groups without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
}

// Delete User
Expand Down Expand Up @@ -1213,7 +1222,7 @@ void spread_message(SceNetAdhocctlUserNode *user, const char *message)
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to send a text message without joining a %s group first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to send a text message without joining a %s group first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
}

// Delete User
Expand Down Expand Up @@ -1786,6 +1795,13 @@ 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. Doesn't work well when PPSSPP_ID reseted everytime emulation restarted.
/*
if (PPSSPP_ID > 1) {
local.sin_addr = ((sockaddr_in *)&localIP)->sin_addr;
}
*/

// Bind Local Address to Socket
int bindresult = bind(fd, (struct sockaddr *)&local, sizeof(local));

Expand Down Expand Up @@ -1857,6 +1873,7 @@ int server_loop(int server)
// Login User (Stream)
if (loginresult != -1) {
u32_le sip = addr.sin_addr.s_addr;
/* // Replacing 127.0.0.x with Ethernet IP will cause issue with multiple-instance of localhost (127.0.0.x)
if (sip == 0x0100007f) { //127.0.0.1 should be replaced with LAN/WAN IP whenever available
char str[100];
gethostname(str, 100);
Expand All @@ -1865,6 +1882,7 @@ int server_loop(int server)
sip = *(u32_le*)pip;
WARN_LOG(SCENET, "AdhocServer: Replacing IP %s with %u.%u.%u.%u", inet_ntoa(addr.sin_addr), pip[0], pip[1], pip[2], pip[3]);
}
*/
login_user_stream(loginresult, sip);
}
} while(loginresult != -1);
Expand Down Expand Up @@ -1925,7 +1943,7 @@ int server_loop(int server)
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
INFO_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Waiting State from %u.%u.%u.%u", user->rx[0], ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Waiting State from %u.%u.%u.%u", user->rx[0], ip[0], ip[1], ip[2], ip[3]);

// Logout User
logout_user(user);
Expand Down Expand Up @@ -2009,7 +2027,7 @@ int server_loop(int server)
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
INFO_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Logged-In State from %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u)", user->rx[0], (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Logged-In State from %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u)", user->rx[0], (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3]);

// Logout User
logout_user(user);
Expand Down
Loading

0 comments on commit dadffa3

Please sign in to comment.