Caches IP-specific Port Offset to avoid recalculating them.

This commit is contained in:
ANR2ME 2022-03-16 05:12:25 +07:00
parent 5e739f32b2
commit 267757a5e4
3 changed files with 23 additions and 13 deletions

View file

@ -228,6 +228,8 @@ void addFriend(SceNetAdhocctlConnectPacketS2C * packet) {
peer->nickname = packet->name;
peer->mac_addr = packet->mac;
peer->ip_addr = packet->ip;
// Calculate final IP-specific Port Offset
peer->port_offset = ((isOriPort && !isPrivateIP(peer->ip_addr)) ? 0 : portOffset);
// Update TimeStamp
peer->last_recv = CoreTiming::GetGlobalTimeUsScaled();
}
@ -248,6 +250,9 @@ void addFriend(SceNetAdhocctlConnectPacketS2C * packet) {
// Save IP Address
peer->ip_addr = packet->ip;
// Calculate final IP-specific Port Offset
peer->port_offset = ((isOriPort && !isPrivateIP(peer->ip_addr)) ? 0 : portOffset);
// TimeStamp
peer->last_recv = CoreTiming::GetGlobalTimeUsScaled();
@ -2286,7 +2291,7 @@ bool resolveIP(uint32_t ip, SceNetEtherAddr * mac) {
return false;
}
bool resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) {
bool resolveMAC(SceNetEtherAddr* mac, uint32_t* ip, u16* port_offset) {
// Get Local MAC Address
SceNetEtherAddr localMac;
getLocalMac(&localMac);
@ -2296,6 +2301,8 @@ bool resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) {
sockaddr_in sockAddr;
getLocalIp(&sockAddr);
*ip = sockAddr.sin_addr.s_addr;
if (port_offset)
*port_offset = portOffset;
return true; // return succes
}
@ -2311,7 +2318,8 @@ bool resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) {
if (isMacMatch(&peer->mac_addr, mac)) {
// Copy Data
*ip = peer->ip_addr;
if (port_offset)
*port_offset = peer->port_offset;
// Return Success
return true;
}

View file

@ -294,11 +294,12 @@ typedef struct SceNetAdhocctlPeerInfo {
SceNetAdhocctlPeerInfo * next;
SceNetAdhocctlNickname nickname;
SceNetEtherAddr mac_addr;
u16_le padding;
u16_le padding; // a copy of the padding(?) from SceNetAdhocctlPeerInfoEmu
u32_le flags;
u64_le last_recv; // Need to use the same method with sceKernelGetSystemTimeWide (ie. CoreTiming::GetGlobalTimeUsScaled) to prevent timing issue (ie. in game timeout)
u32_le ip_addr; // internal use only
u16_le port_offset; // IP-specific port offset (internal use only)
} PACK SceNetAdhocctlPeerInfo;
// Peer Information with u32 pointers
@ -306,7 +307,7 @@ typedef struct SceNetAdhocctlPeerInfoEmu {
u32_le next; // Changed the pointer to u32
SceNetAdhocctlNickname nickname;
SceNetEtherAddr mac_addr;
u16_le padding; //00 00
u16_le padding; //00 00 // Note: Not sure whether this is really padding or reserved/unknown field
u32_le flags; //00 04 00 00 on KHBBS and FF FF FF FF on Ys vs. Sora no Kiseki // State of the peer? Or related to sceNetAdhocAuth_CF4D9BED ?
u64_le last_recv; // Need to use the same method with sceKernelGetSystemTimeWide (ie. CoreTiming::GetGlobalTimeUsScaled) to prevent timing issue (ie. in game timeout)
} PACK SceNetAdhocctlPeerInfoEmu;
@ -1448,9 +1449,10 @@ bool resolveIP(uint32_t ip, SceNetEtherAddr * mac);
* Resolve MAC to IP
* @param mac Peer MAC Address
* @param ip OUT: Peer IP
* @param port_offset OUT: Peer IP-specific Port Offset
* @return true on success
*/
bool resolveMAC(SceNetEtherAddr * mac, uint32_t * ip);
bool resolveMAC(SceNetEtherAddr* mac, uint32_t* ip, u16* port_offset = nullptr);
/**
* Check whether Network Name contains only valid symbols

View file

@ -603,7 +603,7 @@ int DoBlockingPdpSend(int uid, AdhocSocketRequest& req, s64& result, AdhocSendTa
struct sockaddr_in target {};
target.sin_family = AF_INET;
target.sin_addr.s_addr = peer->ip;
target.sin_port = htons(peer->port + ((isOriPort && !isPrivateIP(peer->ip)) ? 0 : portOffset));
target.sin_port = htons(peer->port + peer->portOffset);
int ret = sendto(pdpsocket.id, (const char*)req.buffer, targetPeers.length, MSG_NOSIGNAL, (struct sockaddr*)&target, sizeof(target));
int sockerr = errno;
@ -1580,11 +1580,11 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int
struct sockaddr_in target {};
target.sin_family = AF_INET;
target.sin_port = htons(dport + portOffset);
u16 finalPortOffset;
// Get Peer IP. Some games (ie. Vulcanus Seek and Destroy) seems to try to send to zero-MAC (ie. 00:00:00:00:00:00) first before sending to the actual destination MAC.. So may be sending to zero-MAC has a special meaning? (ie. to peek send buffer availability may be?)
if (resolveMAC((SceNetEtherAddr *)daddr, (uint32_t *)&target.sin_addr.s_addr)) {
if (resolveMAC((SceNetEtherAddr *)daddr, (uint32_t *)&target.sin_addr.s_addr, &finalPortOffset)) {
// Some games (ie. PSP2) might try to talk to it's self, not sure if they talked through WAN or LAN when using public Adhoc Server tho
uint16_t finalPortOffset = ((isOriPort && !isPrivateIP(target.sin_addr.s_addr)) ? 0 : portOffset);
target.sin_port = htons(dport + finalPortOffset);
// Acquire Network Lock
@ -1604,7 +1604,7 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int
}
AdhocSendTargets dest = { len, {}, false };
dest.peers.push_back({ target.sin_addr.s_addr, dport });
dest.peers.push_back({ target.sin_addr.s_addr, dport, finalPortOffset });
sendTargetPeers[threadSocketId] = dest;
return WaitBlockingAdhocSocket(threadSocketId, PDP_SEND, id, data, nullptr, timeout, nullptr, nullptr, "pdp send");
}
@ -1665,7 +1665,7 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int
if (peer->last_recv == 0)
continue;
dest.peers.push_back({ peer->ip_addr, dport });
dest.peers.push_back({ peer->ip_addr, dport, peer->port_offset });
}
// Free Peer Lock
peerlock.unlock();
@ -1690,7 +1690,7 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int
struct sockaddr_in target {};
target.sin_family = AF_INET;
target.sin_addr.s_addr = peer.ip;
target.sin_port = htons(dport + ((isOriPort && !isPrivateIP(peer.ip)) ? 0 : portOffset));
target.sin_port = htons(dport + peer.portOffset);
int sent = sendto(pdpsocket.id, (const char*)data, len, MSG_NOSIGNAL, (struct sockaddr*)&target, sizeof(target));
int error = errno;
@ -3665,11 +3665,11 @@ int NetAdhocPtp_Connect(int id, int timeout, int flag, bool allowForcedConnect)
// sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(ptpsocket.pport + portOffset);
u16 finalPortOffset;
// Grab Peer IP
if (resolveMAC(&ptpsocket.paddr, (uint32_t*)&sin.sin_addr.s_addr)) {
if (resolveMAC(&ptpsocket.paddr, (uint32_t*)&sin.sin_addr.s_addr, &finalPortOffset)) {
// Some games (ie. PSP2) might try to talk to it's self, not sure if they talked through WAN or LAN when using public Adhoc Server tho
uint16_t finalPortOffset = ((isOriPort && !isPrivateIP(sin.sin_addr.s_addr)) ? 0 : portOffset);
sin.sin_port = htons(ptpsocket.pport + finalPortOffset);
// Connect Socket to Peer