mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 21:39:52 +00:00
Merge pull request #6421 from ANR2ME/master
Fixed some bugs (ie. possible of memory leaks) on Adhoc, and implement a...
This commit is contained in:
commit
a1d359f22c
@ -47,7 +47,87 @@ int isPTPPortInUse(uint16_t port) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceNetAdhocMatchingMemberInternal* findMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac) {
|
||||
if (context == NULL || mac == NULL) return NULL;
|
||||
|
||||
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
|
||||
while (peer != NULL) {
|
||||
if (IsMatch(peer->mac, *mac))
|
||||
return peer;
|
||||
peer = peer->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void addMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac) {
|
||||
if (context == NULL || mac == NULL) return;
|
||||
|
||||
SceNetAdhocMatchingMemberInternal * peer = findMember(context, mac);
|
||||
// Member is not added yet
|
||||
if (peer == NULL) {
|
||||
peer = (SceNetAdhocMatchingMemberInternal *)malloc(sizeof(SceNetAdhocMatchingMemberInternal));
|
||||
if (peer != NULL) {
|
||||
memset(peer, 0, sizeof(SceNetAdhocMatchingMemberInternal));
|
||||
peer->mac = *mac;
|
||||
peer->next = context->peerlist;
|
||||
context->peerlist = peer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac) {
|
||||
if (context == NULL || mac == NULL) return;
|
||||
|
||||
// Previous Peer Reference
|
||||
SceNetAdhocMatchingMemberInternal * prev = NULL;
|
||||
|
||||
// Peer Pointer
|
||||
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
|
||||
|
||||
// Iterate Peers
|
||||
for (; peer != NULL; peer = peer->next) {
|
||||
// Found Peer
|
||||
if (IsMatch(context->mac, *mac)) {
|
||||
// Multithreading Lock
|
||||
//context->peerlock.lock();
|
||||
|
||||
// Unlink Left (Beginning)
|
||||
if (prev == NULL) context->peerlist = peer->next;
|
||||
|
||||
// Unlink Left (Other)
|
||||
else prev->next = peer->next;
|
||||
|
||||
// Multithreading Unlock
|
||||
//context->peerlock.unlock();
|
||||
|
||||
// Free Memory
|
||||
free(peer);
|
||||
|
||||
// Stop Search
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Previous Reference
|
||||
prev = peer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void deleteAllMembers(SceNetAdhocMatchingContext * context) {
|
||||
if (context == NULL) return;
|
||||
|
||||
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
|
||||
while (peer != NULL) {
|
||||
context->peerlist = peer->next;
|
||||
free(peer);
|
||||
peer = context->peerlist;
|
||||
}
|
||||
}
|
||||
|
||||
void addFriend(SceNetAdhocctlConnectPacketS2C * packet) {
|
||||
if (packet == NULL) return;
|
||||
|
||||
// Allocate Structure
|
||||
SceNetAdhocctlPeerInfo * peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo));
|
||||
// Allocated Structure
|
||||
@ -114,6 +194,32 @@ int countAvailableNetworks(void) {
|
||||
return count;
|
||||
}
|
||||
|
||||
SceNetAdhocctlScanInfo * findGroup(SceNetEtherAddr * MAC) {
|
||||
if (MAC == NULL) return NULL;
|
||||
|
||||
// Group Reference
|
||||
SceNetAdhocctlScanInfo * group = networks;
|
||||
|
||||
// Count Groups
|
||||
for (; group != NULL; group = group->next) {
|
||||
if (IsMatch(group->bssid.mac_addr, *MAC)) break;
|
||||
}
|
||||
|
||||
// Return Network Count
|
||||
return group;
|
||||
}
|
||||
|
||||
void freeGroupsRecursive(SceNetAdhocctlScanInfo * node) {
|
||||
// End of List
|
||||
if (node == NULL) return;
|
||||
|
||||
// Increase Recursion Depth
|
||||
freeGroupsRecursive(node->next);
|
||||
|
||||
// Free Memory
|
||||
free(node);
|
||||
}
|
||||
|
||||
void deleteAllPDP(void) {
|
||||
// Iterate Element
|
||||
int i = 0; for(; i < 255; i++) {
|
||||
@ -244,6 +350,9 @@ int friendFinder(){
|
||||
|
||||
uint64_t now;
|
||||
|
||||
// Log Startup
|
||||
INFO_LOG(SCENET, "FriendFinder: Begin of Friend Finder Thread");
|
||||
|
||||
// Finder Loop
|
||||
while(friendFinderRunning) {
|
||||
// Acquire Network Lock
|
||||
@ -258,8 +367,12 @@ int friendFinder(){
|
||||
// Prepare Packet
|
||||
uint8_t opcode = OPCODE_PING;
|
||||
|
||||
// Send Ping to Server
|
||||
send(metasocket, (const char *)&opcode, 1,0);
|
||||
// Send Ping to Server, may failed with socket error 10054/10053 if someone else with the same IP already connected to AdHoc Server (the server might need to be modified to differentiate MAC instead of IP)
|
||||
int iResult = send(metasocket, (const char *)&opcode, 1,0);
|
||||
/*if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "FriendFinder: Socket Error (%i) when sending OPCODE_PING", errno);
|
||||
//friendFinderRunning = false;
|
||||
}*/
|
||||
}
|
||||
|
||||
// Send Chat Messages
|
||||
@ -289,6 +402,7 @@ int friendFinder(){
|
||||
if(rxpos > 0) {
|
||||
// BSSID Packet
|
||||
if(rx[0] == OPCODE_CONNECT_BSSID) {
|
||||
INFO_LOG(SCENET, "FriendFinder: Incoming OPCODE_CONNECT_BSSID");
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) {
|
||||
// Cast Packet
|
||||
@ -310,6 +424,7 @@ int friendFinder(){
|
||||
|
||||
// Chat Packet
|
||||
else if(rx[0] == OPCODE_CHAT) {
|
||||
INFO_LOG(SCENET, "FriendFinder: Incoming OPCODE_CHAT");
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlChatPacketS2C)) {
|
||||
// Cast Packet
|
||||
@ -320,6 +435,7 @@ int friendFinder(){
|
||||
|
||||
// Add Incoming Chat to HUD
|
||||
//printf("Receive chat message %s", packet->base.message);
|
||||
DEBUG_LOG(SCENET, "Received chat message %s", packet->base.message);
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C));
|
||||
@ -331,6 +447,7 @@ int friendFinder(){
|
||||
|
||||
// Connect Packet
|
||||
else if(rx[0] == OPCODE_CONNECT) {
|
||||
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_CONNECT");
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlConnectPacketS2C)) {
|
||||
// Log Incoming Peer
|
||||
@ -359,6 +476,7 @@ int friendFinder(){
|
||||
|
||||
// Disconnect Packet
|
||||
else if(rx[0] == OPCODE_DISCONNECT) {
|
||||
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_DISCONNECT");
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlDisconnectPacketS2C)) {
|
||||
// Log Incoming Peer Delete Request
|
||||
@ -367,8 +485,8 @@ int friendFinder(){
|
||||
// Cast Packet
|
||||
SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx;
|
||||
|
||||
// Delete User by IP
|
||||
deleteFriendByIP(packet->ip);
|
||||
// Delete User by IP, should delete by MAC since IP can be shared (behind NAT) isn't?
|
||||
deleteFriendByIP(packet->ip);
|
||||
|
||||
// Update HUD User Count
|
||||
#ifdef LOCALHOST_AS_PEER
|
||||
@ -387,6 +505,7 @@ int friendFinder(){
|
||||
|
||||
// Scan Packet
|
||||
else if(rx[0] == OPCODE_SCAN) {
|
||||
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_SCAN");
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlScanPacketS2C)) {
|
||||
// Log Incoming Network Information
|
||||
@ -394,38 +513,59 @@ int friendFinder(){
|
||||
// Cast Packet
|
||||
SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx;
|
||||
|
||||
// Allocate Structure Data
|
||||
SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo));
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Allocated Structure Data
|
||||
if(group != NULL)
|
||||
{
|
||||
// Clear Memory
|
||||
memset(group, 0, sizeof(SceNetAdhocctlScanInfo));
|
||||
// It seems AdHoc Server always sent the full group list, so we should reset group list during Scan initialization
|
||||
|
||||
// Link to existing Groups
|
||||
group->next = networks;
|
||||
// Should only add non-existing group (or replace an existing group) to prevent Ford Street Racing from showing a strange game session list
|
||||
/*SceNetAdhocctlScanInfo * group = findGroup(&packet->mac);
|
||||
|
||||
// Copy Group Name
|
||||
group->group_name = packet->group;
|
||||
if (group != NULL) {
|
||||
// Copy Group Name
|
||||
group->group_name = packet->group;
|
||||
|
||||
// Set Group Host
|
||||
group->bssid.mac_addr = packet->mac;
|
||||
// Set Group Host
|
||||
group->bssid.mac_addr = packet->mac;
|
||||
}
|
||||
else*/ {
|
||||
// Allocate Structure Data
|
||||
SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo));
|
||||
|
||||
// Link into Group List
|
||||
networks = group;
|
||||
}
|
||||
// Allocated Structure Data
|
||||
if (group != NULL)
|
||||
{
|
||||
// Clear Memory, should this be done only when allocating new group?
|
||||
memset(group, 0, sizeof(SceNetAdhocctlScanInfo));
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlScanPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlScanPacketS2C));
|
||||
// Link to existing Groups
|
||||
group->next = networks;
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlScanPacketS2C);
|
||||
}
|
||||
// Copy Group Name
|
||||
group->group_name = packet->group;
|
||||
|
||||
// Set Group Host
|
||||
group->bssid.mac_addr = packet->mac;
|
||||
|
||||
// Link into Group List
|
||||
networks = group;
|
||||
}
|
||||
}
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlScanPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlScanPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlScanPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Scan Complete Packet
|
||||
else if(rx[0] == OPCODE_SCAN_COMPLETE) {
|
||||
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_SCAN_COMPLETE");
|
||||
// Log Scan Completion
|
||||
INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response...");
|
||||
|
||||
@ -451,6 +591,11 @@ int friendFinder(){
|
||||
sleep_ms(100);
|
||||
}
|
||||
|
||||
// Groups/Networks should be deallocated isn't?
|
||||
|
||||
// Prevent the games from having trouble to reInitiate Adhoc (the next NetInit -> PdpCreate after NetTerm)
|
||||
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
|
||||
|
||||
// Log Shutdown
|
||||
INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread");
|
||||
|
||||
@ -504,6 +649,14 @@ int getLocalIp(sockaddr_in * SocketAddress){
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t getLocalIp(int sock) {
|
||||
struct sockaddr_in localAddr;
|
||||
localAddr.sin_addr.s_addr = INADDR_ANY;
|
||||
socklen_t addrLen = sizeof(localAddr);
|
||||
getsockname(sock, (struct sockaddr*)&localAddr, &addrLen);
|
||||
return localAddr.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
void getLocalMac(SceNetEtherAddr * addr){
|
||||
// Read MAC Address from config
|
||||
uint8_t mac[ETHER_ADDR_LEN] = {0};
|
||||
@ -513,6 +666,14 @@ void getLocalMac(SceNetEtherAddr * addr){
|
||||
memcpy(addr, mac, ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
uint16_t getLocalPort(int sock) {
|
||||
struct sockaddr_in localAddr;
|
||||
localAddr.sin_port = 0;
|
||||
socklen_t addrLen = sizeof(localAddr);
|
||||
getsockname(sock, (struct sockaddr*)&localAddr, &addrLen);
|
||||
return localAddr.sin_port;
|
||||
}
|
||||
|
||||
int getPTPSocketCount(void) {
|
||||
// Socket Counter
|
||||
int counter = 0;
|
||||
@ -531,16 +692,16 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
||||
int iResult = 0;
|
||||
#ifdef _MSC_VER
|
||||
WSADATA data;
|
||||
iResult = WSAStartup(MAKEWORD(2,2),&data);
|
||||
iResult = WSAStartup(MAKEWORD(2,2),&data); // Might be better to call WSAStartup/WSACleanup from sceNetInit/sceNetTerm isn't? since it's the first/last network function being used
|
||||
if(iResult != NOERROR){
|
||||
ERROR_LOG(SCENET, "Wsa failed");
|
||||
ERROR_LOG(SCENET, "WSA failed");
|
||||
return iResult;
|
||||
}
|
||||
#endif
|
||||
metasocket = (int)INVALID_SOCKET;
|
||||
metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
|
||||
if(metasocket == INVALID_SOCKET){
|
||||
ERROR_LOG(SCENET,"invalid socket");
|
||||
ERROR_LOG(SCENET,"Invalid socket");
|
||||
return -1;
|
||||
}
|
||||
struct sockaddr_in server_addr;
|
||||
@ -555,7 +716,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
||||
|
||||
iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr);
|
||||
if (iResult != 0) {
|
||||
ERROR_LOG(SCENET, "Dns error\n");
|
||||
ERROR_LOG(SCENET, "DNS error (%s)\n", g_Config.proAdhocServer.c_str());
|
||||
return iResult;
|
||||
}
|
||||
for (ptr = resultAddr; ptr != NULL; ptr = ptr->ai_next) {
|
||||
@ -568,7 +729,8 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
||||
server_addr.sin_addr = serverIp;
|
||||
iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr));
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET,"Socket error");
|
||||
uint8_t * sip = (uint8_t *)&server_addr.sin_addr.s_addr;
|
||||
ERROR_LOG(SCENET, "Socket error (%i) when connecting to %s/%u.%u.%u.%u:%u", errno, g_Config.proAdhocServer.c_str(), sip[0], sip[1], sip[2], sip[3], ntohs(server_addr.sin_port));
|
||||
return iResult;
|
||||
}
|
||||
memset(¶meter,0,sizeof(parameter));
|
||||
|
@ -49,6 +49,8 @@ inline bool connectInProgress(int errcode){ return (errcode == WSAEWOULDBLOCK ||
|
||||
inline bool connectInProgress(int errcode){ return (errcode == EINPROGRESS); }
|
||||
#endif
|
||||
|
||||
#define IsMatch(buf1, buf2) (memcmp(&buf1, &buf2, sizeof(buf1)) == 0)
|
||||
|
||||
// psp strutcs and definitions
|
||||
#define ADHOCCTL_MODE_ADHOC 0
|
||||
#define ADHOCCTL_MODE_GAMEMODE 1
|
||||
@ -112,6 +114,15 @@ typedef struct SceNetAdhocctlScanInfo {
|
||||
s32_le mode;
|
||||
} PACK SceNetAdhocctlScanInfo;
|
||||
|
||||
// Virtual Network Information with u32 pointers
|
||||
typedef struct SceNetAdhocctlScanInfoEmu {
|
||||
u32_le next;
|
||||
s32_le channel;
|
||||
SceNetAdhocctlGroupName group_name;
|
||||
SceNetAdhocctlBSSId bssid;
|
||||
s32_le mode;
|
||||
} PACK SceNetAdhocctlScanInfoEmu;
|
||||
|
||||
// Player Nickname
|
||||
#define ADHOCCTL_NICKNAME_LEN 128
|
||||
typedef struct SceNetAdhocctlNickname {
|
||||
@ -144,7 +155,21 @@ typedef struct SceNetAdhocctlPeerInfoEmu {
|
||||
u32_le ip_addr;
|
||||
u32 padding; // Changed the pointer to u32
|
||||
u64_le last_recv;
|
||||
} SceNetAdhocctlPeerInfoEmu;
|
||||
} PACK SceNetAdhocctlPeerInfoEmu;
|
||||
|
||||
// Member Information
|
||||
typedef struct SceNetAdhocMatchingMemberInfo {
|
||||
SceNetAdhocMatchingMemberInfo * next;
|
||||
SceNetEtherAddr mac_addr;
|
||||
uint8_t padding[2];
|
||||
} PACK SceNetAdhocctlMemberInfo;
|
||||
|
||||
// Member Information with u32 pointers
|
||||
typedef struct SceNetAdhocMatchingMemberInfoEmu {
|
||||
u32_le next; // Changed the pointer to u32
|
||||
SceNetEtherAddr mac_addr;
|
||||
uint8_t padding[2];
|
||||
} PACK SceNetAdhocctlMemberInfoEmu;
|
||||
|
||||
// Game Mode Peer List
|
||||
#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16
|
||||
@ -281,7 +306,7 @@ typedef struct SceNetAdhocMatchingContext {
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
// Peer List for Connectees
|
||||
SceNetAdhocMatchingMemberInternal * peerlist;
|
||||
SceNetAdhocMatchingMemberInternal * peerlist; // SceNetAdhocMatchingMemberInfo[Emu]
|
||||
|
||||
// Local PDP Port
|
||||
u16_le port;
|
||||
@ -313,9 +338,15 @@ typedef struct SceNetAdhocMatchingContext {
|
||||
// Event Handler
|
||||
SceNetAdhocMatchingHandler handler;
|
||||
|
||||
// Socket Connectivity
|
||||
//bool connected;
|
||||
|
||||
// Hello Data Length
|
||||
u32_le hellolen;
|
||||
|
||||
// Hello Data Address
|
||||
u32_le helloAddr;
|
||||
|
||||
// Hello Data
|
||||
void * hello;
|
||||
|
||||
@ -457,6 +488,15 @@ int isPDPPortInUse(uint16_t port);
|
||||
*/
|
||||
int isPTPPortInUse(uint16_t port);
|
||||
|
||||
/*
|
||||
* Matching Members
|
||||
*/
|
||||
SceNetAdhocMatchingMemberInternal* findMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac);
|
||||
void addMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac);
|
||||
void deleteMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac);
|
||||
void deleteAllMembers(SceNetAdhocMatchingContext * context);
|
||||
|
||||
|
||||
/**
|
||||
* Add Friend to Local List
|
||||
* @param packet Friend Information
|
||||
@ -476,6 +516,16 @@ void changeBlockingMode(int fd, int nonblocking);
|
||||
*/
|
||||
int countAvailableNetworks();
|
||||
|
||||
/*
|
||||
* Find an existing group in networks
|
||||
*/
|
||||
SceNetAdhocctlScanInfo * findGroup(SceNetEtherAddr * MAC);
|
||||
|
||||
/*
|
||||
* Deletes all groups in networks
|
||||
*/
|
||||
void freeGroupsRecursive(SceNetAdhocctlScanInfo * node);
|
||||
|
||||
/**
|
||||
* Closes & Deletes all PDP Sockets
|
||||
*/
|
||||
@ -530,6 +580,7 @@ int getActivePeerCount(void);
|
||||
* @param SocketAddres OUT: local ip
|
||||
*/
|
||||
int getLocalIp(sockaddr_in * SocketAddress);
|
||||
uint32_t getLocalIp(int sock);
|
||||
|
||||
/**
|
||||
* Joins two 32 bits number into a 64 bit one
|
||||
@ -554,6 +605,11 @@ void split64(u64 num, int buff[]);
|
||||
*/
|
||||
void getLocalMac(SceNetEtherAddr * addr);
|
||||
|
||||
/*
|
||||
* Returns the local port used by the socket
|
||||
*/
|
||||
uint16_t getLocalPort(int sock);
|
||||
|
||||
/**
|
||||
* PTP Socket Counter
|
||||
* @return Number of internal PTP Sockets
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "sceKernelMutex.h"
|
||||
#include "sceUtility.h"
|
||||
|
||||
#include "Core/HLE/sceNetAdhoc.h"
|
||||
|
||||
static bool netInited;
|
||||
static bool netInetInited;
|
||||
static bool netApctlInited;
|
||||
@ -119,9 +121,22 @@ void __NetDoState(PointerWrap &p) {
|
||||
p.Do(netMallocStat);
|
||||
}
|
||||
|
||||
u32 sceNetTerm() {
|
||||
//May also need to Terminate netAdhocctl and netAdhoc since the game (ie. GTA:VCS, Wipeout Pulse, etc) might not called them before calling sceNetTerm and causing them to behave strangely on the next sceNetInit+sceNetAdhocInit
|
||||
if (netAdhocctlInited) sceNetAdhocctlTerm();
|
||||
if (netAdhocInited) sceNetAdhocTerm();
|
||||
|
||||
WARN_LOG(SCENET, "UNTESTED sceNetTerm()");
|
||||
netInited = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: should that struct actually be initialized here?
|
||||
u32 sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netinitPri, u32 netinitStack) {
|
||||
ERROR_LOG(SCENET,"UNIMPL sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d)", poolSize, calloutPri, calloutStack, netinitPri, netinitStack);
|
||||
// May need to Terminate old one first since the game (ie. GTA:VCS) might not called sceNetTerm before the next sceNetInit and behave strangely
|
||||
if (netInited) sceNetTerm();
|
||||
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d) at %08x", poolSize, calloutPri, calloutStack, netinitPri, netinitStack, currentMIPS->pc);
|
||||
netInited = true;
|
||||
netMallocStat.maximum = poolSize;
|
||||
netMallocStat.free = poolSize;
|
||||
@ -130,13 +145,6 @@ u32 sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netinitPri, u
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceNetTerm() {
|
||||
ERROR_LOG(SCENET,"UNIMPL sceNetTerm()");
|
||||
netInited = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceWlanGetEtherAddr(u32 addrAddr) {
|
||||
// Read MAC Address from config
|
||||
uint8_t mac[6] = {0};
|
||||
|
@ -136,8 +136,9 @@ enum {
|
||||
|
||||
const size_t MAX_ADHOCCTL_HANDLERS = 32;
|
||||
|
||||
static bool netAdhocInited;
|
||||
static bool netAdhocctlInited;
|
||||
// shared in sceNetAdhoc.h since it need to be used from sceNet.cpp also
|
||||
/*static*/ bool netAdhocInited;
|
||||
/*static*/ bool netAdhocctlInited;
|
||||
static bool netAdhocMatchingInited;
|
||||
|
||||
struct AdhocctlHandler {
|
||||
@ -160,6 +161,7 @@ void __NetAdhocInit() {
|
||||
int sceNetAdhocTerm();
|
||||
int sceNetAdhocctlTerm();
|
||||
int sceNetAdhocMatchingTerm();
|
||||
int sceNetAdhocMatchingSetHelloOpt(int matchingId, int optLenAddr, u32 optDataAddr);
|
||||
|
||||
void __NetAdhocShutdown() {
|
||||
// Checks to avoid confusing logspam
|
||||
@ -213,7 +215,7 @@ void __handlerUpdateCallback(u64 userdata, int cycleslate) {
|
||||
|
||||
u32 sceNetAdhocInit() {
|
||||
// Library uninitialized
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocInit()");
|
||||
INFO_LOG(SCENET, "sceNetAdhocInit() at %08x", currentMIPS->pc);
|
||||
if (!netAdhocInited) {
|
||||
// Clear Translator Memory
|
||||
memset(&pdp, 0, sizeof(pdp));
|
||||
@ -230,7 +232,7 @@ u32 sceNetAdhocInit() {
|
||||
}
|
||||
|
||||
u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlInit(%i, %i, %08x)", stackSize, prio, productAddr);
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlInit(%i, %i, %08x) at %08x", stackSize, prio, productAddr, currentMIPS->pc);
|
||||
if (netAdhocctlInited) {
|
||||
return ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED;
|
||||
} else if (!g_Config.bEnableWlan) {
|
||||
@ -244,9 +246,12 @@ u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) {
|
||||
friendFinderRunning = true;
|
||||
friendFinderThread = std::thread(friendFinder);
|
||||
} else {
|
||||
//WARN_LOG(SCENET, "sceNetAdhocctlInit: Failed to initialize");
|
||||
//return -1; // ERROR_NET_ADHOCCTL_NOT_INITIALIZED; //returning success while initNetwork failed to connect to ProServer may cause some games (ie. GTA:VCS) to behave strangely/stuck, but if not success some games (ie. Ford Street Racing) will also stuck
|
||||
WARN_LOG(SCENET, "sceNetAdhocctlInit: Faking success");
|
||||
return 0; // Generic error, but just return success to make games conform.
|
||||
//return 0; // Generic error, but just return success to make games conform.
|
||||
}
|
||||
netAdhocctlInited = true; //needed for cleanup during ctlTerm even when it failed to connect to Adhoc Server (since it's being faked as success)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -277,12 +282,14 @@ int sceNetAdhocctlGetState(u32 ptrToStatus) {
|
||||
* @param flag Bitflags (Unused)
|
||||
* @return Socket ID > 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_SOCKET_ID_NOT_AVAIL, ADHOC_INVALID_ADDR, ADHOC_PORT_NOT_AVAIL, ADHOC_INVALID_PORT, ADHOC_PORT_IN_USE, NET_NO_SPACE
|
||||
*/
|
||||
// When choosing AdHoc menu in Wipeout Pulse sometimes it's saying that "WLAN is turned off" on game screen and getting "kUnityCommandCode_MediaDisconnected" error in the Log Console when calling sceNetAdhocPdpCreate, probably it needed to wait something from the thread before calling this (ie. need to receives 7 bytes from adhoc server 1st?)
|
||||
int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpCreate(%s, %d, %d, %d)", mac, port, bufferSize, unknown);
|
||||
INFO_LOG(SCENET, "sceNetAdhocPdpCreate(%08x, %u, %u, %u) at %08x", mac, port, bufferSize, unknown, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int retval = ERROR_NET_ADHOC_NOT_INITIALIZED;
|
||||
// Library is initialized
|
||||
SceNetEtherAddr * saddr = (SceNetEtherAddr *)mac;
|
||||
if (netAdhocInited) {
|
||||
@ -309,9 +316,16 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown)
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
addr.sin_port = htons(port); // This not safe in any way...
|
||||
// The port might be under 1024 (ie. GTA:VCS use port 1, Ford Street Racing use port 0 (UNUSED_PORT), etc) and already used by other application/host OS, should we add 1024 to the port whenever it tried to use an already used port?
|
||||
|
||||
// Bound Socket to local Port
|
||||
if (bind(usocket, (sockaddr *)&addr, sizeof(addr)) == 0) {
|
||||
int iResult = bind(usocket, (sockaddr *)&addr, sizeof(addr));
|
||||
/*if (iResult == SOCKET_ERROR && errno == 10048) { //Forcing PdpCreate to be successfull using a different Port might not works and might affect other players sharing the same IP due to "deleteFriendByIP" (should delete by MAC instead of IP)
|
||||
addr.sin_port = 0; //UNUSED_PORT
|
||||
iResult = bind(usocket, (sockaddr *)&addr, sizeof(addr));
|
||||
WARN_LOG(SCENET, "Port %u is already used, replaced with UNUSED_PORT(%u)", port, ntohs(addr.sin_port));
|
||||
}*/
|
||||
if (iResult == 0) {
|
||||
// Allocate Memory for Internal Data
|
||||
SceNetAdhocPdpStat * internal = (SceNetAdhocPdpStat *)malloc(sizeof(SceNetAdhocPdpStat));
|
||||
|
||||
@ -328,7 +342,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown)
|
||||
// Fill in Data
|
||||
internal->id = usocket;
|
||||
internal->laddr = *saddr;
|
||||
internal->lport = port;
|
||||
internal->lport = ntohs(getLocalPort(usocket)); // port; //should use the port given to the socket (in case it's UNUSED_PORT port) isn't?
|
||||
internal->rcv_sb_cc = bufferSize;
|
||||
|
||||
// Link Socket to Translator ID
|
||||
@ -337,17 +351,34 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown)
|
||||
// Forward Port on Router
|
||||
//sceNetPortOpen("UDP", sport); // I need to figure out how to use this in windows/linux
|
||||
|
||||
// Wait for Status to be connected to prevent Wipeout Pulse from showing "WLAN is turned off"
|
||||
if ((i == 0) && friendFinderRunning) {
|
||||
int cnt = 0;
|
||||
while ((threadStatus != ADHOCCTL_STATE_CONNECTED) && (cnt < 5000)) {
|
||||
sleep_ms(1);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
// Success
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Free Memory for Internal Data
|
||||
free(internal);
|
||||
}
|
||||
retval = ERROR_NET_NO_SPACE;
|
||||
}
|
||||
else {
|
||||
retval = ERROR_NET_ADHOC_PORT_IN_USE;
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket error (%i) when binding port %u", errno, ntohs(addr.sin_port));
|
||||
}
|
||||
}
|
||||
|
||||
// Close Socket
|
||||
closesocket(usocket);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Default to No-Space Error
|
||||
@ -355,7 +386,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown)
|
||||
}
|
||||
|
||||
// Invalid MAC supplied
|
||||
return ERROR_NET_ADHOC_INVALID_ADDR;
|
||||
//return ERROR_NET_ADHOC_INVALID_ADDR;
|
||||
}
|
||||
|
||||
// Invalid Arguments were supplied
|
||||
@ -406,7 +437,7 @@ int sceNetAdhocctlGetParameter(u32 paramAddr) {
|
||||
* @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_INVALID_ADDR, ADHOC_INVALID_PORT, ADHOC_INVALID_DATALEN, ADHOC_SOCKET_ALERTED, ADHOC_TIMEOUT, ADHOC_THREAD_ABORTED, ADHOC_WOULD_BLOCK, NET_NO_SPACE, NET_INTERNAL
|
||||
*/
|
||||
int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, int timeout, int flag) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpSend(%i, %s, %i, %p, %i, %i, %i)", id, mac, port, data, len, timeout, flag);
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpSend(%i, %08x, %i, %p, %i, %i, %i)", id, mac, port, data, len, timeout, flag);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return -1;
|
||||
}
|
||||
@ -420,7 +451,7 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i
|
||||
// Valid Port
|
||||
if (dport != 0) {
|
||||
// Valid Data Length
|
||||
if (len > 0) {
|
||||
if (len >= 0) { // should we allow 0 size packet (for ping) ?
|
||||
// Valid Socket ID
|
||||
if (id > 0 && id <= 255 && pdp[id - 1] != NULL) {
|
||||
// Cast Socket
|
||||
@ -452,22 +483,37 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i
|
||||
// Send Data
|
||||
changeBlockingMode(socket->id, flag);
|
||||
int sent = sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target));
|
||||
if (sent == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket Error (%i) on sceNetAdhocPdpSend", errno);
|
||||
}
|
||||
changeBlockingMode(socket->id, 0);
|
||||
|
||||
// Free Network Lock
|
||||
//_freeNetworkLock();
|
||||
|
||||
uint8_t * sip = (uint8_t *)&target.sin_addr.s_addr;
|
||||
// Sent Data
|
||||
if (sent == len) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpSend[%i:%u]: Sent %u bytes to %u.%u.%u.%u:%u", socket->id, ntohs(getLocalPort(socket->id)), sent, sip[0], sip[1], sip[2], sip[3], ntohs(target.sin_port));
|
||||
|
||||
// Return sent size
|
||||
return sent;
|
||||
// Success
|
||||
return 0;
|
||||
//return 0;
|
||||
}
|
||||
// Partially Sent Data (when non-blocking socket's send buffer is smaller than len)
|
||||
else if (flag && (sent >= 0)) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpSend[%i:%u]: Partial Sent %u bytes to %u.%u.%u.%u:%u", socket->id, ntohs(getLocalPort(socket->id)), sent, sip[0], sip[1], sip[2], sip[3], ntohs(target.sin_port));
|
||||
|
||||
// Return sent size
|
||||
return sent;
|
||||
}
|
||||
|
||||
// Blocking Situation
|
||||
if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK;
|
||||
|
||||
// Timeout
|
||||
return ERROR_NET_ADHOC_TIMEOUT;
|
||||
return ERROR_NET_ADHOC_TIMEOUT; //-1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,6 +535,7 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i
|
||||
// sceNetInetSendto(socket->id, data, len, ((flag != 0) ? (INET_MSG_DONTWAIT) : (0)), (SceNetInetSockaddr *)&target, sizeof(target));
|
||||
//}
|
||||
#endif
|
||||
int maxsent = 0;
|
||||
|
||||
// Acquire Peer Lock
|
||||
peerlock.lock();
|
||||
@ -506,8 +553,16 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i
|
||||
// printf("Attempting PDP Send to %u.%u.%u.%u on Port %u\n", thing[0], thing[1], thing[2], thing[3], dport);
|
||||
// Send Data
|
||||
changeBlockingMode(socket->id, flag);
|
||||
sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target));
|
||||
int sent = sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target));
|
||||
if (sent > maxsent) maxsent = sent;
|
||||
if (sent == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket Error (%i) on sceNetAdhocPdpSend[i%](Broadcast)", errno, socket->id);
|
||||
}
|
||||
changeBlockingMode(socket->id, 0);
|
||||
if (sent >= 0) {
|
||||
uint8_t * sip = (uint8_t *)&target.sin_addr.s_addr;
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpSend[%i:%u](BC): Sent %u bytes to %u.%u.%u.%u:%u", socket->id, ntohs(getLocalPort(socket->id)), sent, sip[0], sip[1], sip[2], sip[3], ntohs(target.sin_port));
|
||||
}
|
||||
}
|
||||
|
||||
// Free Peer Lock
|
||||
@ -517,7 +572,9 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i
|
||||
//_freeNetworkLock();
|
||||
|
||||
// Broadcast never fails!
|
||||
return 0;
|
||||
//return 0;
|
||||
// Return sent size
|
||||
return maxsent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,13 +615,13 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i
|
||||
* @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_ENOUGH_SPACE, ADHOC_THREAD_ABORTED, NET_INTERNAL
|
||||
*/
|
||||
int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLength, u32 timeout, int flag) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpRecv(%i, %p, %p, %p, %p, %i, %i)", id, addr, port, buf, dataLength, timeout, flag);
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpRecv(%i, %p, %p, %p, %p, %i, %i) at %08x", id, addr, port, buf, dataLength, timeout, flag, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SceNetEtherAddr *saddr = (SceNetEtherAddr *)addr;
|
||||
uint16_t * sport = (uint16_t *)port;
|
||||
uint32_t * sport = (uint32_t *)port; // uint16_t * sport = (uint16_t *)port; //Looking at Quake3 sourcecode (net_adhoc.c) this should be 32bit isn't?
|
||||
int * len = (int *)dataLength;
|
||||
if (netAdhocInited) {
|
||||
// Valid Socket ID
|
||||
@ -573,7 +630,7 @@ int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLen
|
||||
SceNetAdhocPdpStat * socket = pdp[id - 1];
|
||||
|
||||
// Valid Arguments
|
||||
if (saddr != NULL && port != NULL && buf != NULL && len != NULL && *len > 0) {
|
||||
if (saddr != NULL && port != NULL && buf != NULL && len != NULL && *len >= 0) { // since it's possible to recv 0 size, should we allow 0 size also?
|
||||
#ifndef PDP_DIRTY_MAGIC
|
||||
// Schedule Timeout Removal
|
||||
if (flag == 1) timeout = 0;
|
||||
@ -612,10 +669,16 @@ int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLen
|
||||
// Receive Data
|
||||
changeBlockingMode(socket->id,flag);
|
||||
int received = recvfrom(socket->id, (char *)buf, *len,0,(sockaddr *)&sin, &sinlen);
|
||||
changeBlockingMode(socket->id,0);
|
||||
/*if (received == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket Error (%i) on sceNetAdhocPdpRecv", errno);
|
||||
}*/
|
||||
changeBlockingMode(socket->id, 0);
|
||||
|
||||
// Received Data
|
||||
if (received > 0) {
|
||||
if (received >= 0) { // (received > 0)
|
||||
uint8_t * sip = (uint8_t *)&sin.sin_addr.s_addr;
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpRecv[%i:%u]: Received %u bytes from %u.%u.%u.%u:%u", socket->id, ntohs(getLocalPort(socket->id)), received, sip[0], sip[1], sip[2], sip[3], ntohs(sin.sin_port));
|
||||
|
||||
// Peer MAC
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
@ -623,7 +686,7 @@ int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLen
|
||||
if (resolveIP(sin.sin_addr.s_addr, &mac) == 0) {
|
||||
// Provide Sender Information
|
||||
*saddr = mac;
|
||||
*sport = htons(sin.sin_port);
|
||||
*sport = ntohs(sin.sin_port); //htons(sin.sin_port);
|
||||
|
||||
// Save Length
|
||||
*len = received;
|
||||
@ -632,8 +695,11 @@ int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLen
|
||||
//_freeNetworkLock();
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
//return 0;
|
||||
}
|
||||
|
||||
//Return Received len
|
||||
return received;
|
||||
}
|
||||
|
||||
// Free Network Lock
|
||||
@ -645,8 +711,8 @@ int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLen
|
||||
#endif
|
||||
|
||||
// Nothing received
|
||||
if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK;
|
||||
return ERROR_NET_ADHOC_TIMEOUT;
|
||||
if (flag) return ERROR_NET_ADHOC_WOULD_BLOCK; //ERROR_NET_ADHOC_NO_DATA_AVAILABLE;
|
||||
return ERROR_NET_ADHOC_TIMEOUT; //
|
||||
}
|
||||
|
||||
// Invalid Argument
|
||||
@ -679,10 +745,14 @@ int sceNetAdhocPollSocket(u32 socketStructAddr, int count, int timeout, int nonb
|
||||
* @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED, ADHOC_INVALID_SOCKET_ID
|
||||
*/
|
||||
int sceNetAdhocPdpDelete(int id, int unknown) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpDelete(%d, %d)", id, unknown);
|
||||
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
|
||||
INFO_LOG(SCENET, "sceNetAdhocPdpDelete(%d, %d) at %08x", id, unknown, currentMIPS->pc);
|
||||
/*
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Library is initialized
|
||||
if (netAdhocInited) {
|
||||
// Valid Arguments
|
||||
@ -726,7 +796,7 @@ int sceNetAdhocctlGetAdhocId(u32 productStructAddr) {
|
||||
}
|
||||
|
||||
int sceNetAdhocctlScan() {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlScan()");
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlScan() at %08x", currentMIPS->pc);
|
||||
|
||||
// Library initialized
|
||||
if (netAdhocctlInited) {
|
||||
@ -734,18 +804,42 @@ int sceNetAdhocctlScan() {
|
||||
if (threadStatus == ADHOCCTL_STATE_DISCONNECTED) {
|
||||
threadStatus = ADHOCCTL_STATE_SCANNING;
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// It seems AdHoc Server always sent the full group list, so we should reset current networks to prevent leaving host to be listed again
|
||||
freeGroupsRecursive(networks);
|
||||
networks = NULL;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Prepare Scan Request Packet
|
||||
uint8_t opcode = OPCODE_SCAN;
|
||||
|
||||
// Send Scan Request Packet
|
||||
send(metasocket, (char *)&opcode, 1, 0);
|
||||
// Send Scan Request Packet, may failed with socket error 10054/10053 if someone else with the same IP already connected to AdHoc Server (the server might need to be modified to differentiate MAC instead of IP)
|
||||
int iResult = send(metasocket, (char *)&opcode, 1, 0);
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket error (%i) when sending", errno);
|
||||
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
|
||||
return ERROR_NET_ADHOCCTL_DISCONNECTED; // ERROR_NET_ADHOCCTL_BUSY
|
||||
}
|
||||
|
||||
// Wait for Status to be connected to prevent Ford Street Racing from Failed to find game session
|
||||
if (friendFinderRunning) {
|
||||
int cnt = 0;
|
||||
while ((threadStatus == ADHOCCTL_STATE_SCANNING) && (cnt < 5000)) {
|
||||
sleep_ms(1);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Library is busy
|
||||
return ERROR_NET_ADHOCCTL_BUSY;
|
||||
return ERROR_NET_ADHOCCTL_BUSY; // ERROR_NET_ADHOCCTL_BUSY may trigger the game (ie. Ford Street Racing) to call sceNetAdhocctlDisconnect
|
||||
}
|
||||
|
||||
// Library uninitialized
|
||||
@ -753,24 +847,27 @@ int sceNetAdhocctlScan() {
|
||||
}
|
||||
|
||||
int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlGetScanInfo(%08x, %08x)", size, bufAddr);
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlGetScanInfo([%08x]=%i, %08x)", size, Memory::Read_U32(size), bufAddr);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return 0;
|
||||
}
|
||||
int * buflen = (int *)Memory::GetPointer(size);
|
||||
SceNetAdhocctlScanInfo * buf = NULL;
|
||||
SceNetAdhocctlScanInfoEmu * buf = NULL;
|
||||
if (Memory::IsValidAddress(bufAddr)) {
|
||||
buf = (SceNetAdhocctlScanInfo *)Memory::GetPointer(bufAddr);
|
||||
buf = (SceNetAdhocctlScanInfoEmu *)Memory::GetPointer(bufAddr);
|
||||
}
|
||||
// Library initialized
|
||||
if (netAdhocctlInited) {
|
||||
|
||||
if (!Memory::IsValidAddress(size)) return ERROR_NET_ADHOCCTL_INVALID_ARG;
|
||||
|
||||
// Minimum Argument Requirements
|
||||
if (buflen != NULL) {
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Length Returner Mode
|
||||
if (buf == NULL) *buflen = countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfo);
|
||||
if (buf == NULL) *buflen = countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfoEmu);
|
||||
|
||||
// Normal Information Mode
|
||||
else {
|
||||
@ -781,7 +878,7 @@ int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) {
|
||||
int discovered = 0;
|
||||
|
||||
// Count requested Networks
|
||||
int requestcount = *buflen / sizeof(SceNetAdhocctlScanInfo);
|
||||
int requestcount = *buflen / sizeof(SceNetAdhocctlScanInfoEmu);
|
||||
|
||||
// Minimum Argument Requirements
|
||||
if (requestcount > 0) {
|
||||
@ -791,7 +888,10 @@ int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) {
|
||||
// Iterate Group List
|
||||
for (; group != NULL && discovered < requestcount; group = group->next) {
|
||||
// Copy Group Information
|
||||
buf[discovered] = *group;
|
||||
//buf[discovered] = *group;
|
||||
buf[discovered].group_name = group->group_name;
|
||||
buf[discovered].bssid = group->bssid;
|
||||
buf[discovered].mode = group->mode;
|
||||
|
||||
// Exchange Adhoc Channel
|
||||
// sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_ADHOC_CHANNEL, &buf[discovered].channel);
|
||||
@ -809,15 +909,15 @@ int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) {
|
||||
// Link List
|
||||
int i = 0; for (; i < discovered - 1; i++) {
|
||||
// Link Network
|
||||
buf[i].next = &buf[i + 1];
|
||||
buf[i].next = bufAddr + (sizeof(SceNetAdhocctlScanInfoEmu)*i) + sizeof(SceNetAdhocctlScanInfoEmu); // buf[i].next = &buf[i + 1];
|
||||
}
|
||||
|
||||
// Fix Last Element
|
||||
if (discovered > 0) buf[discovered - 1].next = NULL;
|
||||
if (discovered > 0) buf[discovered - 1].next = 0;
|
||||
}
|
||||
|
||||
// Fix Size
|
||||
*buflen = discovered * sizeof(SceNetAdhocctlScanInfo);
|
||||
*buflen = discovered * sizeof(SceNetAdhocctlScanInfoEmu);
|
||||
}
|
||||
|
||||
// Multithreading Unlock
|
||||
@ -864,8 +964,12 @@ u32 sceNetAdhocctlAddHandler(u32 handlerPtr, u32 handlerArg) {
|
||||
}
|
||||
adhocctlHandlers[retval] = handler;
|
||||
WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): added handler %d", handlerPtr, handlerArg, retval);
|
||||
} else {
|
||||
} else if(foundHandler) {
|
||||
ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): Same handler already exists", handlerPtr, handlerArg);
|
||||
retval = 0; //Faking success
|
||||
} else {
|
||||
ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): Invalid handler", handlerPtr, handlerArg);
|
||||
retval = ERROR_NET_ADHOCCTL_INVALID_ARG;
|
||||
}
|
||||
|
||||
// The id to return is the number of handlers currently registered
|
||||
@ -873,14 +977,18 @@ u32 sceNetAdhocctlAddHandler(u32 handlerPtr, u32 handlerArg) {
|
||||
}
|
||||
|
||||
u32 sceNetAdhocctlDisconnect() {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlDisconnect()");
|
||||
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlDisconnect() at %08x", currentMIPS->pc);
|
||||
/*
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Library initialized
|
||||
if (netAdhocctlInited) {
|
||||
// Connected State (Adhoc Mode)
|
||||
if (threadStatus == ADHOCCTL_STATE_CONNECTED) {
|
||||
if (threadStatus != ADHOCCTL_STATE_DISCONNECTED) { // (threadStatus == ADHOCCTL_STATE_CONNECTED)
|
||||
// Clear Network Name
|
||||
memset(¶meter.group_name, 0, sizeof(parameter.group_name));
|
||||
|
||||
@ -897,7 +1005,10 @@ u32 sceNetAdhocctlDisconnect() {
|
||||
//_acquireNetworkLock();
|
||||
|
||||
// Send Disconnect Request Packet
|
||||
send(metasocket, (const char *)&opcode, 1, 0);
|
||||
int iResult = send(metasocket, (const char *)&opcode, 1, 0);
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket error (%i) when sending", errno);
|
||||
}
|
||||
|
||||
// Free Network Lock
|
||||
//_freeNetworkLock();
|
||||
@ -911,19 +1022,25 @@ u32 sceNetAdhocctlDisconnect() {
|
||||
// Delete Peer Reference
|
||||
friends = NULL;
|
||||
|
||||
// Clear Group List
|
||||
freeGroupsRecursive(networks);
|
||||
|
||||
// Delete Group Reference
|
||||
networks = NULL;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
}
|
||||
|
||||
|
||||
// Notify Event Handlers (even if we weren't connected, not doing this will freeze games like God Eater, which expect this behaviour)
|
||||
__UpdateAdhocctlHandlers(ADHOCCTL_EVENT_DISCONNECT,0);
|
||||
|
||||
// Return Success
|
||||
// Return Success, some games might ignore returned value and always treat it as success, otherwise repeatedly calling this function
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Library uninitialized
|
||||
return ERROR_NET_ADHOC_NOT_INITIALIZED;
|
||||
return 0; //ERROR_NET_ADHOC_NOT_INITIALIZED; // Wipeout Pulse will repeatedly calling this function if returned value is ERROR_NET_ADHOC_NOT_INITIALIZED
|
||||
}
|
||||
|
||||
u32 sceNetAdhocctlDelHandler(u32 handlerID) {
|
||||
@ -938,11 +1055,14 @@ u32 sceNetAdhocctlDelHandler(u32 handlerID) {
|
||||
}
|
||||
|
||||
int sceNetAdhocctlTerm() {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlTerm()");
|
||||
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlTerm()");
|
||||
/*
|
||||
if (!g_Config.bEnableWlan) {
|
||||
netAdhocctlInited = false;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (netAdhocctlInited) {
|
||||
netAdhocctlInited = false;
|
||||
@ -950,11 +1070,13 @@ int sceNetAdhocctlTerm() {
|
||||
if (friendFinderThread.joinable()) {
|
||||
friendFinderThread.join();
|
||||
}
|
||||
//May also need to clear Handlers
|
||||
adhocctlHandlers.clear();
|
||||
// Free stuff here
|
||||
closesocket(metasocket);
|
||||
metasocket = (int)INVALID_SOCKET;
|
||||
#ifdef _MSC_VER
|
||||
WSACleanup();
|
||||
WSACleanup(); // Might be better to call WSAStartup/WSACleanup from sceNetInit/sceNetTerm isn't? since it's the first/last network function being used
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -967,8 +1089,66 @@ int sceNetAdhocctlGetNameByAddr(const char *mac, u32 nameAddr) {
|
||||
}
|
||||
|
||||
int sceNetAdhocctlJoin(u32 scanInfoAddr) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlJoin(%08x)", scanInfoAddr);
|
||||
return -1;
|
||||
WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlJoin(%08x) at %08x", scanInfoAddr, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Library initialized
|
||||
if (netAdhocctlInited) {
|
||||
|
||||
if (!Memory::IsValidAddress(scanInfoAddr)) return ERROR_NET_ADHOCCTL_INVALID_ARG;
|
||||
|
||||
// Disconnected State
|
||||
if (threadStatus == ADHOCCTL_STATE_DISCONNECTED) {
|
||||
|
||||
SceNetAdhocctlScanInfo * sinfo = (SceNetAdhocctlScanInfo*)Memory::GetPointer(scanInfoAddr);
|
||||
|
||||
// Prepare Connect Packet
|
||||
SceNetAdhocctlConnectPacketC2S packet;
|
||||
|
||||
// Clear Packet Memory
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
|
||||
// Set Packet Opcode
|
||||
packet.base.opcode = OPCODE_CONNECT;
|
||||
|
||||
// Set Target Group
|
||||
if (sinfo != NULL)
|
||||
packet.group = sinfo->group_name;
|
||||
|
||||
// Acquire Network Lock
|
||||
|
||||
// Send Packet
|
||||
int iResult = send(metasocket, (const char *)&packet, sizeof(packet), 0);
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket error (%i) when sending", errno);
|
||||
return ERROR_NET_ADHOCCTL_DISCONNECTED; // ERROR_NET_ADHOCCTL_BUSY;
|
||||
}
|
||||
|
||||
// Free Network Lock
|
||||
|
||||
// Set HUD Connection Status
|
||||
//setConnectionStatus(1);
|
||||
|
||||
// Wait for Status to be connected to prevent Ford Street Racing from Failed to create game session
|
||||
if (friendFinderRunning) {
|
||||
int cnt = 0;
|
||||
while ((threadStatus != ADHOCCTL_STATE_CONNECTED) && (cnt < 5000)) {
|
||||
sleep_ms(1);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Connected State
|
||||
return ERROR_NET_ADHOCCTL_BUSY; // ERROR_NET_ADHOCCTL_BUSY may trigger the game (ie. Ford Street Racing) to call sceNetAdhocctlDisconnect
|
||||
}
|
||||
|
||||
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
int sceNetAdhocctlGetPeerInfo(const char *mac, int size, u32 peerInfoAddr) {
|
||||
@ -982,7 +1162,7 @@ int sceNetAdhocctlGetPeerInfo(const char *mac, int size, u32 peerInfoAddr) {
|
||||
* @return 0 on success or... ADHOCCTL_NOT_INITIALIZED, ADHOCCTL_INVALID_ARG, ADHOCCTL_BUSY
|
||||
*/
|
||||
int sceNetAdhocctlCreate(const char *groupName) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlCreate(%s)", groupName);
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlCreate(%s) at %08x", groupName, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return -1;
|
||||
}
|
||||
@ -992,8 +1172,8 @@ int sceNetAdhocctlCreate(const char *groupName) {
|
||||
if (netAdhocctlInited) {
|
||||
// Valid Argument
|
||||
if (validNetworkName(groupNameStruct)) {
|
||||
// Disconnected State
|
||||
if (threadStatus == ADHOCCTL_STATE_DISCONNECTED) {
|
||||
// Disconnected State, may also need to check for Scanning state to prevent some games from failing to host a game session
|
||||
if ((threadStatus == ADHOCCTL_STATE_DISCONNECTED) || (threadStatus == ADHOCCTL_STATE_SCANNING)) {
|
||||
// Set Network Name
|
||||
if (groupNameStruct != NULL) parameter.group_name = *groupNameStruct;
|
||||
|
||||
@ -1015,21 +1195,34 @@ int sceNetAdhocctlCreate(const char *groupName) {
|
||||
// Acquire Network Lock
|
||||
|
||||
// Send Packet
|
||||
send(metasocket, (const char *)&packet, sizeof(packet), 0);
|
||||
int iResult = send(metasocket, (const char *)&packet, sizeof(packet), 0);
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Socket error (%i) when sending", errno);
|
||||
return ERROR_NET_ADHOCCTL_DISCONNECTED; // ERROR_NET_ADHOCCTL_BUSY;
|
||||
}
|
||||
|
||||
// Free Network Lock
|
||||
|
||||
// Set HUD Connection Status
|
||||
//setConnectionStatus(1);
|
||||
|
||||
// Wait for Status to be connected to prevent Ford Street Racing from Failed to create game session
|
||||
if (friendFinderRunning) {
|
||||
int cnt = 0;
|
||||
while ((threadStatus != ADHOCCTL_STATE_CONNECTED) && (cnt < 5000)) {
|
||||
sleep_ms(1);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Connected State
|
||||
return ERROR_NET_ADHOCCTL_BUSY;
|
||||
return ERROR_NET_ADHOCCTL_BUSY; // ERROR_NET_ADHOCCTL_BUSY may trigger the game (ie. Ford Street Racing) to call sceNetAdhocctlDisconnect
|
||||
}
|
||||
|
||||
|
||||
// Invalid Argument
|
||||
return ERROR_NET_ADHOC_INVALID_ARG;
|
||||
}
|
||||
@ -1039,29 +1232,32 @@ int sceNetAdhocctlCreate(const char *groupName) {
|
||||
|
||||
int sceNetAdhocctlConnect(u32 ptrToGroupName) {
|
||||
if (Memory::IsValidAddress(ptrToGroupName)) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlConnect(groupName=%s)", Memory::GetCharPointer(ptrToGroupName));
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlConnect(groupName=%s) at %08x", Memory::GetCharPointer(ptrToGroupName), currentMIPS->pc);
|
||||
return sceNetAdhocctlCreate(Memory::GetCharPointer(ptrToGroupName));
|
||||
} else {
|
||||
return ERROR_NET_ADHOC_INVALID_ADDR;
|
||||
return ERROR_NET_ADHOC_INVALID_ADDR; // shouldn't this be ERROR_NET_ADHOC_INVALID_ARG ?
|
||||
}
|
||||
}
|
||||
|
||||
int sceNetAdhocctlCreateEnterGameMode(const char *groupName, int unknown, int playerNum, u32 macsAddr, int timeout, int unknown2) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlCreateEnterGameMode(%s, %i, %i, %08x, %i, %i)", groupName, unknown, playerNum, macsAddr, timeout, unknown2);
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlCreateEnterGameMode(%s, %i, %i, %08x, %i, %i) at %08x", groupName, unknown, playerNum, macsAddr, timeout, unknown2, currentMIPS->pc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sceNetAdhocctlJoinEnterGameMode(const char *groupName, const char *macAddr, int timeout, int unknown2) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlJoinEnterGameMode(%s, %s, %i, %i)", groupName, macAddr, timeout, unknown2);
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlJoinEnterGameMode(%s, %s, %i, %i) at %08x", groupName, macAddr, timeout, unknown2, currentMIPS->pc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sceNetAdhocTerm() {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocTerm()");
|
||||
INFO_LOG(SCENET, "sceNetAdhocTerm()");
|
||||
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup all the sockets right?
|
||||
/*
|
||||
if (!g_Config.bEnableWlan) {
|
||||
netAdhocInited = false;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Library is initialized
|
||||
if (netAdhocInited) {
|
||||
@ -1307,7 +1503,7 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou
|
||||
if (Memory::IsValidAddress(peerMacAddrPtr)) {
|
||||
addr = PSPPointer<SceNetEtherAddr>::Create(peerMacAddrPtr);
|
||||
}
|
||||
uint16_t * port = NULL;
|
||||
uint16_t * port = NULL; //
|
||||
if (Memory::IsValidAddress(peerPortPtr)) {
|
||||
port = (uint16_t *)Memory::GetPointer(peerPortPtr);
|
||||
}
|
||||
@ -1398,11 +1594,11 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou
|
||||
|
||||
// Copy Local Address Data to Structure
|
||||
getLocalMac(&internal->laddr);
|
||||
internal->lport = htons(local.sin_port);
|
||||
internal->lport = ntohs(local.sin_port); // htons(local.sin_port);
|
||||
|
||||
// Copy Peer Address Data to Structure
|
||||
internal->paddr = mac;
|
||||
internal->pport = htons(peeraddr.sin_port);
|
||||
internal->pport = ntohs(peeraddr.sin_port); // htons(peeraddr.sin_port);
|
||||
|
||||
// Set Connected State
|
||||
internal->state = PTP_STATE_ESTABLISHED;
|
||||
@ -1930,12 +2126,12 @@ int sceNetAdhocPtpFlush(int id, int timeout, int nonblock) {
|
||||
}
|
||||
|
||||
int sceNetAdhocGameModeCreateMaster(u32 data, int size) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateMaster(%08x, %i)", data, size);
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateMaster(%08x, %i) at %08x", data, size, currentMIPS->pc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sceNetAdhocGameModeCreateReplica(const char *mac, u32 data, int size) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateReplica(%s, %08x, %i)", mac, data, size);
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateReplica(%s, %08x, %i) at %08x", mac, data, size, currentMIPS->pc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1965,6 +2161,7 @@ int sceNetAdhocGetSocketAlert() {
|
||||
}
|
||||
|
||||
int sceNetAdhocMatchingInit(u32 memsize) {
|
||||
INFO_LOG(SCENET, "sceNetAdhocMatchingInit(%d) at %08x", memsize, currentMIPS->pc);
|
||||
// Uninitialized Library
|
||||
if (!netAdhocMatchingInited) {
|
||||
// Save Fake Pool Size
|
||||
@ -1981,6 +2178,13 @@ int sceNetAdhocMatchingInit(u32 memsize) {
|
||||
}
|
||||
|
||||
int sceNetAdhocMatchingTerm() {
|
||||
// Should we cleanup all created matching contexts first? just in case there are games that doesn't delete them before calling this
|
||||
/*
|
||||
if (netAdhocMatchingInited) {
|
||||
// Should we also delete all PDP? since creating a matching context will also create a PDP socket
|
||||
|
||||
}
|
||||
*/
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingTerm()");
|
||||
netAdhocMatchingInited = false;
|
||||
|
||||
@ -1991,7 +2195,7 @@ int sceNetAdhocMatchingTerm() {
|
||||
|
||||
// Presumably returns a "matchingId".
|
||||
int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int hello_int, int keepalive_int, int init_count, int rexmt_int, u32 callbackAddr) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocMatchingCreate");
|
||||
INFO_LOG(SCENET, "sceNetAdhocMatchingCreate(mode=%i, maxnum=%i, port=%i, rxbuflen=%i, hello=%i, keepalive=%i, initcount=%i, rexmt=%i, callbackAddr=%08x) at %08x", mode, maxnum, port, rxbuflen, hello_int, keepalive_int, init_count, rexmt_int, callbackAddr, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return -1;
|
||||
}
|
||||
@ -2054,23 +2258,30 @@ int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int
|
||||
// Fill in Selfpeer
|
||||
context->mac = localmac;
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock(); //contextlock.lock();
|
||||
|
||||
// Link Context
|
||||
//context->connected = true;
|
||||
context->next = contexts;
|
||||
contexts = context;
|
||||
|
||||
// Multithreading UnLock
|
||||
peerlock.unlock(); //contextlock.unlock();
|
||||
|
||||
// Return Matching ID
|
||||
return context->id;
|
||||
}
|
||||
|
||||
// Close PDP Socket
|
||||
sceNetAdhocPdpDelete(socket, 0);
|
||||
sceNetAdhocPdpDelete(socket, 0); // context->connected = (sceNetAdhocPdpDelete(socket, 0) < 0);
|
||||
}
|
||||
|
||||
// Free Memory
|
||||
free(context);
|
||||
|
||||
// Port in use
|
||||
if (socket < 1) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE;
|
||||
if (socket < 1) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; // ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED; // -1; // ERROR_NET_ADHOC_MATCHING_NOT_ESTABLISHED;
|
||||
}
|
||||
|
||||
// Out of Memory
|
||||
@ -2092,10 +2303,36 @@ int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int
|
||||
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// TODO: Should we execute the callback used to create the Matching Id if it's a valid address?
|
||||
int sceNetAdhocMatchingStart(int matchingId, int evthPri, int evthStack, int inthPri, int inthStack, int optLen, u32 optDataAddr) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingStart(%i, %i, %i, %i, %i, %i, %08x)", matchingId, evthPri, evthStack, inthPri, inthStack, optLen, optDataAddr);
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingStart(%i, %i, %i, %i, %i, %i, %08x) at %08x", matchingId, evthPri, evthStack, inthPri, inthStack, optLen, optDataAddr, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan)
|
||||
return -1;
|
||||
|
||||
SceNetAdhocMatchingContext * item = findMatchingContext(matchingId);
|
||||
if (item != NULL) {
|
||||
sceNetAdhocMatchingSetHelloOpt(matchingId, optLen, optDataAddr);
|
||||
if ((optLen > 0) && Memory::IsValidAddress(optDataAddr)) {
|
||||
// Allocate the memory and copy the content
|
||||
if (item->hello != NULL) free(item->hello);
|
||||
item->hello = malloc(optLen);
|
||||
if (item->hello != NULL)
|
||||
Memory::Memcpy(item->hello, optDataAddr, optLen);
|
||||
}
|
||||
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ARG; // ERROR_NET_ADHOC_MATCHING_INVALID_OPTLEN; // Returning Not Success will cause GTA:VC unable to host/join
|
||||
|
||||
//Add your own MAC as a member (ony if it's empty?)
|
||||
addMember(item, &item->mac);
|
||||
|
||||
//TODO: Create a new thread
|
||||
// Easier to implement if using an existing thread (friendFinder) instead of creating a new one ^_^
|
||||
|
||||
//sceKernelCreateThread
|
||||
/*eventHandlerUpdate = CoreTiming::RegisterEvent("HandlerUpdateEvent", __handlerUpdateCallback);
|
||||
memberFinderRunning = true;
|
||||
memberFinderThread = std::thread(memberFinder);*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2103,13 +2340,68 @@ int sceNetAdhocMatchingStop(int matchingId) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingStop(%i)", matchingId);
|
||||
if (!g_Config.bEnableWlan)
|
||||
return -1;
|
||||
|
||||
SceNetAdhocMatchingContext * item = findMatchingContext(matchingId);
|
||||
if (item != NULL) {
|
||||
/*memberFinderRunning = false;
|
||||
if (memberFinderThread.joinable()) {
|
||||
friendFinderThread.join();
|
||||
}*/
|
||||
|
||||
// Remove your own MAC, or All memebers, don't remove at all?
|
||||
//delAllMembers();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceNetAdhocMatchingDelete(int matchingId) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingDelete(%i)", matchingId);
|
||||
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
|
||||
/*
|
||||
if (!g_Config.bEnableWlan)
|
||||
return -1;
|
||||
*/
|
||||
|
||||
// Previous Context Reference
|
||||
SceNetAdhocMatchingContext * prev = NULL;
|
||||
|
||||
// Context Pointer
|
||||
SceNetAdhocMatchingContext * item = contexts;
|
||||
|
||||
// Iterate contexts
|
||||
for (; item != NULL; item = item->next) {
|
||||
// Found matching ID
|
||||
if (item->id == matchingId) {
|
||||
// Multithreading Lock
|
||||
peerlock.lock(); //contextlock.lock();
|
||||
|
||||
// Unlink Left (Beginning)
|
||||
if (prev == NULL) contexts = item->next;
|
||||
|
||||
// Unlink Left (Other)
|
||||
else prev->next = item->next;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock(); //contextlock.unlock();
|
||||
|
||||
// Delete the socket
|
||||
sceNetAdhocPdpDelete(item->socket, 0); // item->connected = (sceNetAdhocPdpDelete(item->socket, 0) < 0);
|
||||
// Free allocated memories
|
||||
free(item->hello);
|
||||
free(item->rxbuf);
|
||||
deleteAllMembers(item);
|
||||
// Free item context memory
|
||||
free(item);
|
||||
|
||||
// Stop Search
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Previous Reference
|
||||
prev = item;
|
||||
}
|
||||
|
||||
WARN_LOG(SCENET, "UNTESTED sceNetAdhocMatchingDelete(%i) at %08x", matchingId, currentMIPS->pc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2142,16 +2434,98 @@ int sceNetAdhocMatchingGetHelloOpt(int matchingId, u32 optLenAddr, u32 optDataAd
|
||||
}
|
||||
|
||||
int sceNetAdhocMatchingSetHelloOpt(int matchingId, int optLenAddr, u32 optDataAddr) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingSetHelloOpt(%i, %i, %08x)", matchingId, optLenAddr, optDataAddr);
|
||||
DEBUG_LOG(SCENET, "UNTESTED sceNetAdhocMatchingSetHelloOpt(%i, %i, %08x) at %08x", matchingId, optLenAddr, optDataAddr, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan)
|
||||
return -1;
|
||||
|
||||
//if (!Memory::IsValidAddress(optDataAddr)) return ERROR_NET_ADHOC_MATCHING_INVALID_ARG;
|
||||
|
||||
SceNetAdhocMatchingContext * item = findMatchingContext(matchingId);
|
||||
if (item != NULL) {
|
||||
// Set OptData
|
||||
int oldLen = item->hellolen;
|
||||
item->hellolen = optLenAddr; //optLenAddr doesn't seems to be an address to the actual len
|
||||
item->helloAddr = optDataAddr;
|
||||
|
||||
if (optLenAddr <= 0 || !Memory::IsValidAddress(optDataAddr)) {
|
||||
if (item->hello != NULL) {
|
||||
free(item->hello);
|
||||
item->hello = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (optLenAddr > oldLen) {
|
||||
free(item->hello);
|
||||
item->hello = malloc(optLenAddr);
|
||||
}
|
||||
Memory::Memcpy(item->hello, optDataAddr, optLenAddr);
|
||||
}
|
||||
}
|
||||
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ID;
|
||||
|
||||
//sceNetAdhocctlScan();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceNetAdhocMatchingGetMembers(int matchingId, u32 sizeAddr, u32 buf) {
|
||||
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetMembers(%i, %08x, %08x)", matchingId, sizeAddr, buf);
|
||||
DEBUG_LOG(SCENET, "UNTESTED sceNetAdhocMatchingGetMembers(%i, [%08x]=%i, %08x) at %08x", matchingId, sizeAddr, Memory::Read_U32(sizeAddr), buf, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan)
|
||||
return -1;
|
||||
|
||||
// Minimum Argument
|
||||
if (!Memory::IsValidAddress(sizeAddr)) return ERROR_NET_ADHOC_MATCHING_INVALID_ARG;
|
||||
|
||||
SceNetAdhocMatchingContext * item = findMatchingContext(matchingId);
|
||||
if (item != NULL) {
|
||||
int * buflen = (int *)Memory::GetPointer(sizeAddr);
|
||||
SceNetAdhocMatchingMemberInfoEmu * buf2 = NULL;
|
||||
if (Memory::IsValidAddress(buf)) {
|
||||
buf2 = (SceNetAdhocMatchingMemberInfoEmu *)Memory::GetPointer(buf);
|
||||
}
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Iterate Members
|
||||
//SceNetAdhocMatchingMemberInternal * peer = item->peerlist;
|
||||
|
||||
//Using friend list instead, since it's easier to implement ^_^
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
int count = 0;
|
||||
if (!Memory::IsValidAddress(buf)) { // Returning needed buf size instead
|
||||
count++;
|
||||
for (; peer != NULL; peer = peer->next) count++;
|
||||
}
|
||||
else {
|
||||
buf2[count].mac_addr = item->mac; //add your own MAC
|
||||
buf2[count].padding[0] = 0; // does padding need to be 0 ?
|
||||
buf2[count++].padding[1] = 0;
|
||||
for (; peer != NULL; peer = peer->next) {
|
||||
buf2[count].mac_addr = peer->mac_addr;
|
||||
buf2[count].padding[0] = 0;
|
||||
buf2[count].padding[1] = 0;
|
||||
count++;
|
||||
}
|
||||
// Link List
|
||||
int i = 0;
|
||||
for (; i < count - 1; i++) {
|
||||
// Link Network
|
||||
buf2[i].next = buf + (sizeof(SceNetAdhocMatchingMemberInfoEmu)*i) + sizeof(SceNetAdhocMatchingMemberInfoEmu);
|
||||
}
|
||||
// Fix Last Element
|
||||
if (count > 0) buf2[count - 1].next = 0;
|
||||
}
|
||||
|
||||
// Fix Size
|
||||
*buflen = count * sizeof(SceNetAdhocMatchingMemberInfoEmu); //includes your own MAC
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
}
|
||||
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2243,7 +2617,7 @@ int sceNetAdhocctlGetGameModeInfo(u32 infoAddr) {
|
||||
|
||||
|
||||
int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocctlGetPeerList(%08x, %08x)", sizeAddr, bufAddr);
|
||||
INFO_LOG(SCENET, "sceNetAdhocctlGetPeerList(%08x, %08x) at %08x", sizeAddr, bufAddr, currentMIPS->pc);
|
||||
if (!g_Config.bEnableWlan) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -27,3 +27,9 @@ void __NetAdhocDoState(PointerWrap &p);
|
||||
|
||||
// I have to call this from netdialog
|
||||
int sceNetAdhocctlCreate(const char * groupName);
|
||||
|
||||
// May need to use these from sceNet.cpp
|
||||
extern bool netAdhocInited;
|
||||
extern bool netAdhocctlInited;
|
||||
int sceNetAdhocctlTerm();
|
||||
int sceNetAdhocTerm();
|
||||
|
Loading…
Reference in New Issue
Block a user