From 553f1d4e4e1d859009f10e991b17dca20d90608e Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Sat, 26 Oct 2013 15:47:52 +0100 Subject: [PATCH 01/21] Implements a bunch of adhoc functions --- Core/HLE/FunctionWrappers.h | 10 + Core/HLE/sceNet.cpp | 11 +- Core/HLE/sceNetAdhoc.cpp | 2092 +++++++++++++++++++++++++++++------ 3 files changed, 1788 insertions(+), 325 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index b80a51b139..bd5f672a30 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -806,3 +806,13 @@ template void WrapI_ICI() { int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2)); RETURN(retval); } + +template void WrapI_IVVVVUI(){ + u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); + RETURN(retval); +} + +template void WrapI_ICUVIII(){ + u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6)); + RETURN(retval); +} diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 80b963d169..b224de26e8 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -130,6 +130,7 @@ u32 sceNetTerm() { } u32 sceWlanGetEtherAddr(u32 addrAddr) { + // TODO: Read from config static const u8 fakeEtherAddr[6] = { 1, 2, 3, 4, 5, 6 }; DEBUG_LOG(SCENET, "sceWlanGetEtherAddr(%08x)", addrAddr); for (int i = 0; i < 6; i++) @@ -138,14 +139,18 @@ u32 sceWlanGetEtherAddr(u32 addrAddr) { return 0; } +u32 sceNetGetLocalEtherAddr(u32 addrAddr) { + return sceWlanGetEtherAddr(addrAddr); +} + u32 sceWlanDevIsPowerOn() { DEBUG_LOG(SCENET, "UNTESTED 0=sceWlanDevIsPowerOn()"); - return 0; + return 1; } u32 sceWlanGetSwitchState() { DEBUG_LOG(SCENET, "UNTESTED sceWlanGetSwitchState()"); - return 0; + return 1; } // Probably a void function, but often returns a useful value. @@ -348,7 +353,7 @@ const HLEFunction sceNet[] = { {0x281928A9, WrapU_V, "sceNetTerm"}, {0x89360950, WrapI_UU, "sceNetEtherNtostr"}, {0xd27961c9, WrapI_UU, "sceNetEtherStrton"}, - {0x0bf0a3ae, 0, "sceNetGetLocalEtherAddr"}, + {0x0bf0a3ae, WrapU_U, "sceNetGetLocalEtherAddr"}, {0x50647530, 0, "sceNetFreeThreadinfo"}, {0xcc393e48, WrapI_U, "sceNetGetMallocStat"}, {0xad6844c6, 0, "sceNetThreadAbort"}, diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 852b29b6d3..8728e34ff0 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -29,45 +29,70 @@ // group players per game. Maybe allow players to join rooms and then start the game, // instead of the other way around? - +#include "../Config.h" #include "Core/HLE/HLE.h" +#include "../CoreTiming.h" #include "Core/HLE/sceNetAdhoc.h" #include "sceKernel.h" #include "sceKernelThread.h" #include "sceKernelMutex.h" #include "sceUtility.h" - #include "net/resolve.h" -enum { - ERROR_NET_ADHOC_INVALID_SOCKET_ID = 0x80410701, - ERROR_NET_ADHOC_INVALID_ADDR = 0x80410702, - ERROR_NET_ADHOC_NO_DATA_AVAILABLE = 0x80410709, - ERROR_NET_ADHOC_PORT_IN_USE = 0x8041070a, - ERROR_NET_ADHOC_NOT_INITIALIZED = 0x80410712, - ERROR_NET_ADHOC_ALREADY_INITIALIZED = 0x80410713, - ERROR_NET_ADHOC_DISCONNECTED = 0x8041070c, - ERROR_NET_ADHOC_TIMEOUT = 0x80410715, - ERROR_NET_ADHOC_NO_ENTRY = 0x80410716, - ERROR_NET_ADHOC_CONNECTION_REFUSED = 0x80410718, - ERROR_NET_ADHOC_INVALID_MATCHING_ID = 0x80410807, - ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED = 0x80410812, - ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED = 0x80410813, +// Temporary stuff +#include +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#include +#include +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define Sleep sleep +#define closesocket close +#endif +#include +// End of extra includes - ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF = 0x80410b03, - ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED = 0x80410b07, - ERROR_NET_ADHOCCTL_NOT_INITIALIZED = 0x80410b08, - ERROR_NET_ADHOCCTL_DISCONNECTED = 0x80410b09, - ERROR_NET_ADHOCCTL_BUSY = 0x80410b10, - ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS = 0x80410b12, +enum { + ERROR_NET_ADHOC_INVALID_SOCKET_ID = 0x80410701, + ERROR_NET_ADHOC_INVALID_ADDR = 0x80410702, + ERROR_NET_ADHOC_INVALID_ARG = 0x80410B04, + ERROR_NET_ADHOC_NO_DATA_AVAILABLE = 0x80410709, + ERROR_NET_ADHOC_PORT_IN_USE = 0x8041070a, + ERROR_NET_ADHOC_NOT_INITIALIZED = 0x80410712, + ERROR_NET_ADHOC_ALREADY_INITIALIZED = 0x80410713, + ERROR_NET_ADHOC_DISCONNECTED = 0x8041070c, + ERROR_NET_ADHOC_TIMEOUT = 0x80410715, + ERROR_NET_ADHOC_NO_ENTRY = 0x80410716, + ERROR_NET_ADHOC_CONNECTION_REFUSED = 0x80410718, + ERROR_NET_ADHOC_INVALID_MATCHING_ID = 0x80410807, + ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED = 0x80410812, + ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED = 0x80410813, + ERROR_NET_ADHOC_WOULD_BLOCK = 0x80410709, + ERROR_NET_ADHOC_INVALID_DATALEN = 0x80410705, + ERROR_NET_ADHOC_INVALID_PORT = 0x80410703, + + ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF = 0x80410b03, + ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED = 0x80410b07, + ERROR_NET_ADHOCCTL_NOT_INITIALIZED = 0x80410b08, + ERROR_NET_ADHOCCTL_DISCONNECTED = 0x80410b09, + ERROR_NET_ADHOCCTL_BUSY = 0x80410b10, + ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS = 0x80410b12, + + ERROR_NET_NO_SPACE = 0x80410001, }; enum { - PSP_ADHOC_POLL_READY_TO_SEND = 1, - PSP_ADHOC_POLL_DATA_AVAILABLE = 2, - PSP_ADHOC_POLL_CAN_CONNECT = 4, - PSP_ADHOC_POLL_CAN_ACCEPT = 8, + PSP_ADHOC_POLL_READY_TO_SEND = 1, + PSP_ADHOC_POLL_DATA_AVAILABLE = 2, + PSP_ADHOC_POLL_CAN_CONNECT = 4, + PSP_ADHOC_POLL_CAN_ACCEPT = 8, }; const size_t MAX_ADHOCCTL_HANDLERS = 32; @@ -78,24 +103,260 @@ static bool netAdhocMatchingInited; // These might come in handy in the future, if PPSSPP ever supports wifi/ad-hoc.. struct SceNetAdhocctlParams { - s32_le channel; //which ad-hoc channel to connect to - char name[8]; //connection name - u8 bssid[6]; //BSSID of the connection? - char nickname[128]; //PSP's nickname? + s32_le channel; //which ad-hoc channel to connect to + char name[8]; //connection name + u8 bssid[6]; //BSSID of the connection? + char nickname[128]; //PSP's nickname? }; +// psp strutcs and definitions +#define ADHOCCTL_MODE_ADHOC 0 +#define ADHOCCTL_MODE_GAMEMODE 1 + +// Event Types for Event Handler +#define ADHOCCTL_EVENT_CONNECT 1 +#define ADHOCCTL_EVENT_DISCONNECT 2 +#define ADHOCCTL_EVENT_SCAN 3 + +// Internal Thread States +#define ADHOCCTL_STATE_DISCONNECTED 0 +#define ADHOCCTL_STATE_CONNECTED 1 +#define ADHOCCTL_STATE_SCANNING 2 +#define ADHOCCTL_STATE_GAMEMODE 3 + +// Kernel Utility Netconf Adhoc Types +#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2 +#define UTILITY_NETCONF_TYPE_CREATE_ADHOC 4 +#define UTILITY_NETCONF_TYPE_JOIN_ADHOC 5 + +// Kernel Utility States +#define UTILITY_NETCONF_STATUS_NONE 0 +#define UTILITY_NETCONF_STATUS_INITIALIZE 1 +#define UTILITY_NETCONF_STATUS_RUNNING 2 +#define UTILITY_NETCONF_STATUS_FINISHED 3 +#define UTILITY_NETCONF_STATUS_SHUTDOWN 4 + +// Ethernet Address (MAC) +#define ETHER_ADDR_LEN 6 +typedef struct SceNetEtherAddr { + uint8_t data[ETHER_ADDR_LEN]; +} SceNetEtherAddr; + +// Adhoc Virtual Network Name (1234ABCD) +#define ADHOCCTL_GROUPNAME_LEN 8 +typedef struct SceNetAdhocctlGroupName { + uint8_t data[ADHOCCTL_GROUPNAME_LEN]; +} SceNetAdhocctlGroupName; + +// Player Nickname +#define ADHOCCTL_NICKNAME_LEN 128 +typedef struct SceNetAdhocctlNickname { + uint8_t data[ADHOCCTL_NICKNAME_LEN]; +} SceNetAdhocctlNickname; + +// Adhoc ID (Game Product Key) +#define ADHOCCTL_ADHOCID_LEN 9 +typedef struct SceNetAdhocctlAdhocId { + int type; + uint8_t data[ADHOCCTL_ADHOCID_LEN]; + uint8_t padding[3]; +} SceNetAdhocctlAdhocId; + +// Virtual Network Host Information +typedef struct SceNetAdhocctlBSSId { + SceNetEtherAddr mac_addr; + uint8_t padding[2]; +}; + +// Virtual Network Information +typedef struct SceNetAdhocctlScanInfo { + struct SceNetAdhocctlScanInfo * next; + int channel; + SceNetAdhocctlGroupName group_name; + SceNetAdhocctlBSSId bssid; + int mode; +}; +// Active Virtual Network Information +typedef struct SceNetAdhocctlParameter { + int channel; + SceNetAdhocctlGroupName group_name; + SceNetAdhocctlBSSId bssid; + SceNetAdhocctlNickname nickname; +}; + +// Peer Information +typedef struct SceNetAdhocctlPeerInfo { + struct SceNetAdhocctlPeerInfo * next; + SceNetAdhocctlNickname nickname; + SceNetEtherAddr mac_addr; + uint32_t ip_addr; + uint8_t padding[2]; + uint64_t last_recv; +}; + +// Game Mode Peer List +#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16 +typedef struct SceNetAdhocctlGameModeInfo { + int num; + SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS]; +}; + +// Socket Polling Event Listener +typedef struct SceNetAdhocPollSd { + int id; + int events; + int revents; +}; + +// PDP Socket Status +typedef struct SceNetAdhocPdpStat { + struct SceNetAdhocPdpStat * next; + int id; + SceNetEtherAddr laddr; + uint16_t lport; + uint32_t rcv_sb_cc; +}; + +// PTP Socket Status +typedef struct SceNetAdhocPtpStat { + struct SceNetAdhocPtpStat * next; + int id; + SceNetEtherAddr laddr; + SceNetEtherAddr paddr; + uint16_t lport; + uint16_t pport; + uint32_t snd_sb_cc; + uint32_t rcv_sb_cc; + int state; +}; + +// Gamemode Optional Peer Buffer Data +typedef struct SceNetAdhocGameModeOptData { + uint32_t size; + uint32_t flag; + uint64_t last_recv; +}; + +// Gamemode Buffer Status +typedef struct SceNetAdhocGameModeBufferStat { + struct SceNetAdhocGameModeBufferStat * next; + int id; + void * ptr; + uint32_t size; + uint32_t master; + SceNetAdhocGameModeOptData opt; +}; +// End of psp definitions + +#define OPCODE_PING 0 +#define OPCODE_LOGIN 1 +#define OPCODE_CONNECT 2 +#define OPCODE_DISCONNECT 3 +#define OPCODE_SCAN 4 +#define OPCODE_SCAN_COMPLETE 5 +#define OPCODE_CONNECT_BSSID 6 +#define OPCODE_CHAT 7 + +// PSP Product Code +#define PRODUCT_CODE_LENGTH 9 +typedef struct +{ + // Game Product Code (ex. ULUS12345) + char data[PRODUCT_CODE_LENGTH]; +} __attribute__((packed)) SceNetAdhocctlProductCode; + +// Basic Packet +typedef struct +{ + uint8_t opcode; +} __attribute__((packed)) SceNetAdhocctlPacketBase; + +// C2S Login Packet +typedef struct +{ + SceNetAdhocctlPacketBase base; + SceNetEtherAddr mac; + SceNetAdhocctlNickname name; + SceNetAdhocctlProductCode game; +} __attribute__((packed)) SceNetAdhocctlLoginPacketC2S; + +// C2S Connect Packet +typedef struct +{ + SceNetAdhocctlPacketBase base; + SceNetAdhocctlGroupName group; +} __attribute__((packed)) SceNetAdhocctlConnectPacketC2S; + +// C2S Chat Packet +typedef struct +{ + SceNetAdhocctlPacketBase base; + char message[64]; +} __attribute__((packed)) SceNetAdhocctlChatPacketC2S; + +// S2C Connect Packet +typedef struct +{ + SceNetAdhocctlPacketBase base; + SceNetAdhocctlNickname name; + SceNetEtherAddr mac; + uint32_t ip; +} __attribute__((packed)) SceNetAdhocctlConnectPacketS2C; + +// S2C Disconnect Packet +typedef struct +{ + SceNetAdhocctlPacketBase base; + uint32_t ip; +} __attribute__((packed)) SceNetAdhocctlDisconnectPacketS2C; + +// S2C Scan Packet +typedef struct +{ + SceNetAdhocctlPacketBase base; + SceNetAdhocctlGroupName group; + SceNetEtherAddr mac; +} __attribute__((packed)) SceNetAdhocctlScanPacketS2C; + +// S2C Connect BSSID Packet +typedef struct +{ + SceNetAdhocctlPacketBase base; + SceNetEtherAddr mac; +} __attribute__((packed)) SceNetAdhocctlConnectBSSIDPacketS2C; + +// S2C Chat Packet +typedef struct +{ + SceNetAdhocctlChatPacketC2S base; + SceNetAdhocctlNickname name; +} __attribute__((packed)) SceNetAdhocctlChatPacketS2C; + +// Aux vars +static int metasocket; +static int eventHandlerUpdate = -1; +static int threadStatus = ADHOCCTL_STATE_DISCONNECTED; +static SceNetAdhocctlParameter parameter; +static std::thread friendFinderThread; +static SceNetAdhocctlPeerInfo * friends = NULL; +static SceNetAdhocctlScanInfo * networks = NULL; +static std::mutex peerlock; +static SceNetAdhocPdpStat * pdp[255]; +static SceNetAdhocPtpStat * ptp[255]; +// End of Aux vars + struct AdhocctlHandler { - u32 entryPoint; - u32 argument; + u32 entryPoint; + u32 argument; }; static std::map adhocctlHandlers; void __NetAdhocInit() { - netAdhocInited = false; - netAdhocctlInited = false; - netAdhocMatchingInited = false; - adhocctlHandlers.clear(); + netAdhocInited = false; + netAdhocctlInited = false; + netAdhocMatchingInited = false; + adhocctlHandlers.clear(); } void __NetAdhocShutdown() { @@ -103,44 +364,734 @@ void __NetAdhocShutdown() { } void __NetAdhocDoState(PointerWrap &p) { - auto s = p.Section("sceNetAdhoc", 1); - if (!s) - return; + auto s = p.Section("sceNetAdhoc", 1); + if (!s) + return; - p.Do(netAdhocInited); - p.Do(netAdhocctlInited); - p.Do(netAdhocMatchingInited); - p.Do(adhocctlHandlers); + p.Do(netAdhocInited); + p.Do(netAdhocctlInited); + p.Do(netAdhocMatchingInited); + p.Do(adhocctlHandlers); } void __UpdateAdhocctlHandlers(int flag, int error) { - u32 args[3] = { 0, 0, 0 }; - args[0] = flag; - args[1] = error; + u32 args[3] = { 0, 0, 0 }; + args[0] = flag; + args[1] = error; - for (std::map::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); ++it) { - args[2] = it->second.argument; + for (std::map::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); ++it) { + args[2] = it->second.argument; - __KernelDirectMipsCall(it->second.entryPoint, NULL, args, 3, true); - } + __KernelDirectMipsCall(it->second.entryPoint, NULL, args, 3, true); + } +} + +#define firstMask 0x00000000FFFFFFFF +#define secondMask 0xFFFFFFFF00000000 +void split64(u64 num, int buff[]){ + int num1 = (int)(num&firstMask); + int num2 = (int)((num&secondMask)>>32); + buff[0] = num1; + buff[1] = num2; +} + +u64 join32(u32 num1, u32 num2){ + return (u64)num2 << 32 | num1; +} + +// Gets the local mac TODO: Read from config +void __getLocalMac(SceNetEtherAddr * addr){ + uint8_t mac[] = {1, 2, 3, 4, 5, 6}; + memcpy(addr,mac,ETHER_ADDR_LEN); +} + +// This only usefull if the server is running on the same machine as the client +int __getLocalIp(sockaddr_in * SocketAddress){ +#ifdef _WIN32 + // Get local host name + char szHostName[128] = ""; + + if(::gethostname(szHostName, sizeof(szHostName))) { + // Error handling + } + // Get local IP addresses + struct hostent *pHost = 0; + pHost = ::gethostbyname(szHostName); + if(pHost) { + memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length); + return 0; + } + return -1; +#else + char ip[] = "192.168.12.1"; + SocketAddress->sin_addr.s_addr = inet_addr("192.168.12.1"); + return 0; +#endif +} + +// Returns current system time in miliseconds, windows only! +long long __milliseconds_now() { +#ifdef _WIN32 + static LARGE_INTEGER s_frequency; + static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency); + if (s_use_qpc) { + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + return (1000LL * now.QuadPart) / s_frequency.QuadPart; + } else { + return GetTickCount(); + } +#else + timeval val; + gettimeofday(&val,NULL); + return val.tv_usec * 1000; +#endif +} + +/* chages to the blocking mode of the socket + 1 to set noblocking + 0 to set blocking +*/ +void __change_blocking_mode(int fd, int nonblocking) { + unsigned long on = 1; + unsigned long off = 0; +#ifdef _WIN32 + if(nonblocking){ + // Change to Non-Blocking Mode + ioctlsocket(fd,FIONBIO,&on); + }else { + // Change to Blocking Mode + ioctlsocket(fd, FIONBIO, &off); + } +#else + if(nonblocking) fcntl(fd, F_SETFL, O_NONBLOCK); + else { + // Get Flags + int flags = fcntl(fd, F_GETFL); + // Remove Non-Blocking Flag + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + } +#endif +} + +// Inits all basic net functionality and logins the user to the main server +int __init_network(SceNetAdhocctlAdhocId *adhoc_id){ + int iResult = 0; +#ifdef _WIN32 + WSADATA data; + iResult = WSAStartup(MAKEWORD(2,2),&data); + if(iResult != NOERROR){ + printf("Wsa failed with error %d\n",iResult); + return iResult; + } +#endif + metasocket = INVALID_SOCKET; + metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); + if(metasocket == INVALID_SOCKET){ + printf("invalid socket"); + return INVALID_SOCKET; + } + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(27312); + server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); + + if(iResult == SOCKET_ERROR){ + printf("Socket error %d", iResult); + return iResult; + } + + SceNetAdhocctlLoginPacketC2S packet; + packet.base.opcode = OPCODE_LOGIN; + SceNetEtherAddr addres; + __getLocalMac(&addres); + packet.mac = addres; + strcpy((char *)packet.name.data, g_Config.sNickName.c_str()); + memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN); + int sent = send(metasocket, (char*)&packet, sizeof(packet), 0); + __change_blocking_mode(metasocket,1); // Change to non-blocking + if(sent > 0){ + return 0; + }else{ + return -1; + } +} + +/** + * Add Friend to Local List + * @param packet Friend Information + */ +void __addFriend(SceNetAdhocctlConnectPacketS2C * packet) { + // Allocate Structure + SceNetAdhocctlPeerInfo * peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo)); + // Allocated Structure + if(peer != NULL) + { + // Clear Memory + memset(peer, 0, sizeof(SceNetAdhocctlPeerInfo)); + + // Link to existing Peers + peer->next = friends; + + // Save Nickname + peer->nickname = packet->name; + + // Save MAC Address + peer->mac_addr = packet->mac; + + // Save IP Address + peer->ip_addr = packet->ip; + + // Multithreading Lock + peerlock.lock(); + + // Link into Peerlist + friends = peer; + + // Multithreading Unlock + peerlock.unlock(); + } +} + +/** + * Delete Friend from Local List + * @param ip Friend IP + */ +void __deleteFriendByIP(uint32_t ip) { + // Previous Peer Reference + SceNetAdhocctlPeerInfo * prev = NULL; + + // Peer Pointer + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) + { + // Found Peer + if(peer->ip_addr == ip) + { + // Multithreading Lock + peerlock.lock(); + + // Unlink Left (Beginning) + if(prev == NULL)friends = peer->next; + + // Unlink Left (Other) + else prev->next = peer->next; + + // Multithreading Unlock + peerlock.unlock(); + + // Free Memory + free(peer); + + // Stop Search + break; + } + + // Set Previous Reference + prev = peer; + } +} + +/** + * Recursive Memory Freeing-Helper for Friend-Structures + * @param node Current Node in List + */ +void __freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) { + // End of List + if(node == NULL) return; + + // Increase Recursion Depth + __freeFriendsRecursive(node->next); + + // Free Memory + free(node); +} + +// Thread that listens to all relevant messages from the server +int __friendFinder(){ + // Receive Buffer + int rxpos = 0; + uint8_t rx[1024]; + + // Chat Packet + SceNetAdhocctlChatPacketC2S chat; + chat.base.opcode = OPCODE_CHAT; + + // Last Ping Time + long long lastping = 0; + + // Last Time Reception got updated + uint64_t lastreceptionupdate = 0; + + // Finder Loop + while(netAdhocctlInited) { + // Acquire Network Lock + //_acquireNetworkLock(); + + // Ping Server + + if(__milliseconds_now() - lastping >= 100) { + // Update Ping Time + lastping = __milliseconds_now(); + + // Prepare Packet + uint8_t opcode = OPCODE_PING; + + // Send Ping to Server + send(metasocket, (const char *)&opcode, 1,0); + } + + // Send Chat Messages + //while(popFromOutbox(chat.message)) + //{ + // // Send Chat to Server + // sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0); + //} + + // Wait for Incoming Data + int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos,0); + + // Free Network Lock + //_freeNetworkLock(); + + // Received Data + if(received > 0) { + // Fix Position + rxpos += received; + + // Log Incoming Traffic + //printf("Received %d Bytes of Data from Server\n", received); + INFO_LOG(SCENET, "Received %d Bytes of Data from Adhoc Server", received); + } + + // Handle Packets + if(rxpos > 0) { + // BSSID Packet + if(rx[0] == OPCODE_CONNECT_BSSID) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) { + // Cast Packet + SceNetAdhocctlConnectBSSIDPacketS2C * packet = (SceNetAdhocctlConnectBSSIDPacketS2C *)rx; + // Update BSSID + parameter.bssid.mac_addr = packet->mac; + // Change State + threadStatus = ADHOCCTL_STATE_CONNECTED; + // Notify Event Handlers + CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0)); + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlConnectBSSIDPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C); + } + } + + // Chat Packet + else if(rx[0] == OPCODE_CHAT) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlChatPacketS2C)) { + // Cast Packet + SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx; + + // Fix for Idiots that try to troll the "ME" Nametag +#ifdef _WIN32 + if(stricmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); +#else + if(strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); +#endif + + // Add Incoming Chat to HUD + //printf("Receive chat message %s", packet->base.message); + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlChatPacketS2C); + } + } + + // Connect Packet + else if(rx[0] == OPCODE_CONNECT) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlConnectPacketS2C)) { + // Log Incoming Peer + INFO_LOG(SCENET,"Incoming Peer Data...\n"); + + // Cast Packet + SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx; + + // Add User + __addFriend(packet); + + // Update HUD User Count +#ifdef LOCALHOST_AS_PEER + setUserCount(_getActivePeerCount()); +#else + //setUserCount(_getActivePeerCount()+1); +#endif + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlConnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlConnectPacketS2C); + } + } + + // Disconnect Packet + else if(rx[0] == OPCODE_DISCONNECT) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlDisconnectPacketS2C)) { + // Log Incoming Peer Delete Request + INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request...\n"); + + // Cast Packet + SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx; + + // Delete User by IP + __deleteFriendByIP(packet->ip); + + // Update HUD User Count +#ifdef LOCALHOST_AS_PEER + setUserCount(_getActivePeerCount()); +#else + //setUserCount(_getActivePeerCount()+1); +#endif + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlDisconnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlDisconnectPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlDisconnectPacketS2C); + } + } + + // Scan Packet + else if(rx[0] == OPCODE_SCAN) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlScanPacketS2C)) { + // Log Incoming Network Information + INFO_LOG(SCENET,"Incoming Group Information...\n"); + // Cast Packet + SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx; + + // Allocate Structure Data + SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo)); + + // Allocated Structure Data + if(group != NULL) + { + // Clear Memory + memset(group, 0, sizeof(SceNetAdhocctlScanInfo)); + + // Link to existing Groups + group->next = networks; + + // Copy Group Name + group->group_name = packet->group; + + // Set Group Host + group->bssid.mac_addr = packet->mac; + + // Link into Group List + networks = group; + } + + // 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) { + // Log Scan Completion + INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response...\n"); + + // Change State + threadStatus = ADHOCCTL_STATE_DISCONNECTED; + + // Notify Event Handlers + CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate,join32(ADHOCCTL_EVENT_SCAN, 0)); + //int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++) + //{ + // // Active Handler + // if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]); + //} + + // Move RX Buffer + memmove(rx, rx + 1, sizeof(rx) - 1); + + // Fix RX Buffer Length + rxpos -= 1; + } + } + + // Delay Thread (10ms) +#ifdef _WIN32 + Sleep(10); +#else + sleep(10); +#endif + } + + // Log Shutdown + INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread\n"); + + // Return Success + return 0; +} + +/** + * Check whether Network Name contains only valid symbols + * @param group_name To-be-checked Network Name + * @return 1 if valid or... 0 + */ +int __validNetworkName(const SceNetAdhocctlGroupName * group_name) { + // Result + int valid = 1; + + // Name given + if(group_name != NULL) { + // Iterate Name Characters + int i = 0; for(; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) { + // End of Name + if(group_name->data[i] == 0) break; + + // Not a digit + if(group_name->data[i] < '0' || group_name->data[i] > '9') { + // Not 'A' to 'Z' + if(group_name->data[i] < 'A' || group_name->data[i] > 'Z') { + // Not 'a' to 'z' + if(group_name->data[i] < 'a' || group_name->data[i] > 'z') { + // Invalid Name + valid = 0; + } + } + } + } + } + + // Return Result + return valid; +} + +/** + * Local MAC Check + * @param saddr To-be-checked MAC Address + * @return 1 if valid or... 0 + */ +int _IsLocalMAC(const SceNetEtherAddr * addr) { + // Get Local MAC Address + SceNetEtherAddr saddr; + __getLocalMac(&saddr); + //sceNetGetLocalEtherAddr(&saddr); + + // Compare MAC Addresses + int match = memcmp((const void *)addr, (const void *)&saddr, ETHER_ADDR_LEN); + + // Return Result + return (match == 0); +} + +/** + * Resolve IP to MAC + * @param ip Peer IP Address + * @param mac OUT: Peer MAC + * @return 0 on success or... ADHOC_NO_ENTRY + */ +int __resolveIP(uint32_t ip, SceNetEtherAddr * mac) { + sockaddr_in addr; + __getLocalIp(&addr); + uint32 localIp = addr.sin_addr.s_addr; + if(ip == localIp){ + __getLocalMac(mac); + return 0; + } + + // Multithreading Lock + peerlock.lock(); + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Matching Peer + if(peer->ip_addr == ip) { + // Copy Data + *mac = peer->mac_addr; + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + } + + // Multithreading Unlock + peerlock.unlock(); + + // Peer not found + return ERROR_NET_ADHOC_NO_ENTRY; +} +/** + * Resolve MAC to IP + * @param mac Peer MAC Address + * @param ip OUT: Peer IP + * @return 0 on success or... ADHOC_NO_ENTRY + */ +int __resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) { + // Get Local MAC Address + SceNetEtherAddr localMac; + __getLocalMac(&localMac); + // Local MAC Requested + if(memcmp(&localMac, mac, sizeof(SceNetEtherAddr)) == 0) { + // Get Local IP Address + sockaddr_in sockAddr; + __getLocalIp(&sockAddr); + *ip = sockAddr.sin_addr.s_addr; + return 0; // return succes + } + + // Multithreading Lock + peerlock.lock(); + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Matching Peer + if(memcmp(&peer->mac_addr, mac, sizeof(SceNetEtherAddr)) == 0) { + // Copy Data + *ip = peer->ip_addr; + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + } + + // Multithreading Unlock + peerlock.unlock(); + + // Peer not found + return ERROR_NET_ADHOC_NO_ENTRY; +} +/** + * PDP Port Check + * @param port To-be-checked Port + * @return 1 if in use or... 0 + */ +int _IsPDPPortInUse(uint16_t port) { + // Iterate Elements + int i = 0; for(; i < 255; i++) if(pdp[i] != NULL && pdp[i]->lport == port) return 1; + + // Unused Port + return 0; +} + +/** + * Broadcast MAC Check + * @param addr To-be-checked MAC Address + * @return 1 if Broadcast MAC or... 0 + */ +int __isBroadcastMAC(const SceNetEtherAddr * addr) { + // Broadcast MAC + if(memcmp(addr->data, "\xFF\xFF\xFF\xFF\xFF\xFF", ETHER_ADDR_LEN) == 0) return 1; + // Normal MAC + return 0; +} + +/** + * Closes & Deletes all PDP Sockets + */ +void __deleteAllPDP(void) { + // Iterate Element + int i = 0; for(; i < 255; i++) { + // Active Socket + if(pdp[i] != NULL) { + // Close Socket + closesocket(pdp[i]->id); + + // Free Memory + free(pdp[i]); + + // Delete Reference + pdp[i] = NULL; + } + } +} + +/** + * Closes & Deletes all PTP Sockets + */ +void __deleteAllPTP(void) { + // Iterate Element + int i = 0; for(; i < 255; i++) { + // Active Socket + if(ptp[i] != NULL) { + // Close Socket + closesocket(ptp[i]->id); + + // Free Memory + free(ptp[i]); + + // Delete Reference + ptp[i] = NULL; + } + } +} + +void __handlerUpdateCallback(u64 userdata, int cycleslate){ + int buff[2]; + split64(userdata,buff); + __UpdateAdhocctlHandlers(buff[0], buff[1]); } u32 sceNetAdhocInit() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocInit()"); - if (netAdhocInited) - return ERROR_NET_ADHOC_ALREADY_INITIALIZED; - netAdhocInited = true; + // Library uninitialized + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocInit()"); + if(!netAdhocInited) { + // Clear Translator Memory + memset(&pdp, 0, sizeof(pdp)); + memset(&ptp, 0, sizeof(ptp)); - return 0; + // Library initialized + netAdhocInited = true; + + // Return Success + return 0; + } + // Already initialized + return ERROR_NET_ADHOC_ALREADY_INITIALIZED; } u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlInit(%i, %i, %08x)", stackSize, prio, productAddr); - if (netAdhocctlInited) - return ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED; - netAdhocctlInited = true; - - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlInit(%i, %i, %08x)", stackSize, prio, productAddr); + if (netAdhocctlInited) { + return ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED; + }else{ + if(__init_network((SceNetAdhocctlAdhocId *)Memory::GetPointer(productAddr)) == 0){ + netAdhocctlInited = true; + eventHandlerUpdate = CoreTiming::RegisterEvent("HandlerUpdateEvent", __handlerUpdateCallback); + friendFinderThread = std::thread(__friendFinder); + }else{ + return -1; // Generic error + } + } + return 0; } @@ -148,474 +1099,971 @@ u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { // Seems to always return 0, and write 0 to the pointer.. // TODO: Eventually research what possible states there are int sceNetAdhocctlGetState(u32 ptrToStatus) { - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x)", ptrToStatus); - if (Memory::IsValidAddress(ptrToStatus)) - Memory::Write_U32(0, ptrToStatus); - else - ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x): Tried to write invalid location", ptrToStatus); + WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x)", ptrToStatus); + if (Memory::IsValidAddress(ptrToStatus)) + Memory::Write_U32(0, ptrToStatus); + else + ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x): Tried to write invalid location", ptrToStatus); - return 0; + return 0; } -// Always return -1 since we don't have any real networking... +/** + * Adhoc Emulator PDP Socket Creator + * @param saddr Local MAC (Unused) + * @param sport Local Binding Port + * @param bufsize Socket Buffer Size + * @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 + */ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpCreate(%s, %x, %x, %x)", mac, port, bufferSize, unknown); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpCreate(%s, %x, %x, %x)", mac, port, bufferSize, unknown); + // Library is initialized + SceNetEtherAddr * saddr = (SceNetEtherAddr *)mac; + if(netAdhocInited) { + // Valid Arguments are supplied + if(mac != NULL && bufferSize > 0) { + // Valid MAC supplied + if(_IsLocalMAC(saddr)) { + //// Unused Port supplied + //if(!_IsPDPPortInUse(port)) {} + // + //// Port is in use by another PDP Socket + //return ERROR_NET_ADHOC_PORT_IN_USE; + + // Create Internet UDP Socket + int usocket = INVALID_SOCKET; + usocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + // Valid Socket produced + if(usocket != INVALID_SOCKET) { + // Enable Port Re-use + //setsockopt(usocket, SOL_SOCKET, SO_REUSEADDR, &_one, sizeof(_one)); NO idea if we need this + // Binding Information for local Port + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + + addr.sin_port = port; //This not safe in any way... + + // Bound Socket to local Port + if(bind(usocket, (sockaddr *)&addr, sizeof(addr)) == 0) { + // Allocate Memory for Internal Data + SceNetAdhocPdpStat * internal = (SceNetAdhocPdpStat *)malloc(sizeof(SceNetAdhocPdpStat)); + + // Allocated Memory + if(internal != NULL) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPdpStat)); + + // Find Free Translator Index + int i = 0; for(; i < 255; i++) if(pdp[i] == NULL) break; + + // Found Free Translator Index + if(i < 255) { + // Fill in Data + internal->id = usocket; + internal->laddr = *saddr; + internal->lport = port; + internal->rcv_sb_cc = bufferSize; + + // Link Socket to Translator ID + pdp[i] = internal; + + // Forward Port on Router + //sceNetPortOpen("UDP", sport); // I need to figure out how to use this in windows/linux + + // Success + return i + 1; + } + + // Free Memory for Internal Data + free(internal); + } + } + + // Close Socket + closesocket(usocket); + } + + // Default to No-Space Error + return ERROR_NET_NO_SPACE; + + } + + // Invalid MAC supplied + return ERROR_NET_ADHOC_INVALID_ADDR; + } + + // Invalid Arguments were supplied + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } // TODO: Should we really write the struct if we're disconnected? int sceNetAdhocctlGetParameter(u32 paramAddr) { - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetParameter(%x)", paramAddr); - struct SceNetAdhocctlParams params; - params.channel = 0; - for (int i = 0; i < 6; i++) - params.bssid[i] = i + 1; - strcpy(params.name, ""); - strcpy(params.nickname, ""); + WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetParameter(%x)", paramAddr); + struct SceNetAdhocctlParams params; + params.channel = 0; + for (int i = 0; i < 6; i++) + params.bssid[i] = i + 1; + strcpy(params.name, ""); + strcpy(params.nickname, ""); - if (Memory::IsValidAddress(paramAddr)) - Memory::WriteStruct(paramAddr, ¶ms); + if (Memory::IsValidAddress(paramAddr)) + Memory::WriteStruct(paramAddr, ¶ms); - return ERROR_NET_ADHOCCTL_DISCONNECTED; + return ERROR_NET_ADHOCCTL_DISCONNECTED; } -int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, void *dataLength, u32 timeout, int nonBlock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpSend(%d, %s, %d, %p, %p, %d, %d)", id, mac, port, data, dataLength, timeout, nonBlock); - return -1; +/** + * Adhoc Emulator PDP Send Call + * @param id Socket File Descriptor + * @param daddr Target MAC Address + * @param dport Target Port + * @param data Data Payload + * @param len Payload Length + * @param timeout Send Timeout + * @param flag Nonblocking Flag + * @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) { + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpSend(%d, %s, %d, %p, %p, %d, %d)", id, mac, port, data, len, timeout, flag); + SceNetEtherAddr * daddr = (SceNetEtherAddr *)mac; + uint16 dport = (uint16 )port; + // Library is initialized + if(netAdhocInited) { + // Valid Port + if(dport != 0) { + // Valid Data Length + if(len > 0) { + // Valid Socket ID + if(id > 0 && id <= 255 && pdp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPdpStat * socket = pdp[id - 1]; + + // Valid Data Buffer + if(data != NULL) { + // Valid Destination Address + if(daddr != NULL) { + // Log Destination +// #ifdef DEBUG +// printk("Attempting PDP Send to %02X:%02X:%02X:%02X:%02X:%02X on Port %u\n", daddr->data[0], daddr->data[1], daddr->data[2], daddr->data[3], daddr->data[4], daddr->data[5], dport); +// #endif + + // Schedule Timeout Removal + if(flag) timeout = 0; + + // Apply Send Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)); + + // Single Target + if(!__isBroadcastMAC(daddr)) + { + // Fill in Target Structure + sockaddr_in target; + target.sin_family = AF_INET; + target.sin_port = htons(dport); + + // Get Peer IP + if(__resolveMAC((SceNetEtherAddr *)daddr, &target.sin_addr.s_addr) == 0) { + // Acquire Network Lock + //_acquireNetworkLock(); + + // Send Data + __change_blocking_mode(socket->id, flag); + int sent = sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target)); + __change_blocking_mode(socket->id, 0); + + // Free Network Lock + //_freeNetworkLock(); + + // Sent Data + if(sent == len) { + // Success + return 0; + } + + // Blocking Situation + if(flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + } + + // Broadcast Target + else { + // Acquire Network Lock + //_acquireNetworkLock(); + +#ifdef BROADCAST_TO_LOCALHOST + //// Get Local IP Address + //union SceNetApctlInfo info; if(sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info) == 0) { + // // Fill in Target Structure + // SceNetInetSockaddrIn target; + // target.sin_family = AF_INET; + // sceNetInetInetAton(info.ip, &target.sin_addr); + // target.sin_port = sceNetHtons(dport); + // + // // Send Data + // sceNetInetSendto(socket->id, data, len, ((flag != 0) ? (INET_MSG_DONTWAIT) : (0)), (SceNetInetSockaddr *)&target, sizeof(target)); + //} +#endif + + // Acquire Peer Lock + peerlock.lock(); + + // Iterate Peers + SceNetAdhocctlPeerInfo * peer = friends; + for(; peer != NULL; peer = peer->next) { + // Fill in Target Structure + sockaddr_in target; + target.sin_family = AF_INET; + target.sin_addr.s_addr = peer->ip_addr; + target.sin_port = htons(dport); + + // Send Data + sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target)); + } + + // Free Peer Lock + peerlock.unlock(); + + // Free Network Lock + //_freeNetworkLock(); + + // Broadcast never fails! + return 0; + } + } + + // Invalid Destination Address + return ERROR_NET_ADHOC_INVALID_ADDR; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Socket ID + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Invalid Data Length + return ERROR_NET_ADHOC_INVALID_DATALEN; + } + + // Invalid Destination Port + return ERROR_NET_ADHOC_INVALID_PORT; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; + } -// Return -1 packets since we don't have networking yet.. -int sceNetAdhocPdpRecv(int id, const char *mac, u32 port, void *data, void *dataLength, u32 timeout, int nonBlock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpRecv(%d, %s, %d, %p, %p, %d, %d)", id, mac, port, data, dataLength, timeout, nonBlock); - return -1; +/** + * Adhoc Emulator PDP Receive Call + * @param id Socket File Descriptor + * @param saddr OUT: Source MAC Address + * @param sport OUT: Source Port + * @param buf OUT: Received Data + * @param len IN: Buffer Size OUT: Received Data Length + * @param timeout Receive Timeout + * @param flag Nonblocking Flag + * @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) { + //ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpRecv(%d, %s, %d, %p, %p, %d, %d)", id, addr, port, buf, dataLength, timeout, flag); + // This spams a lot... + SceNetEtherAddr *saddr = (SceNetEtherAddr *)addr; + uint16_t * sport = (uint16_t *)port; + int * len = (int *)dataLength; + if(netAdhocInited) { + // Valid Socket ID + if(id > 0 && id <= 255 && pdp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPdpStat * socket = pdp[id - 1]; + + // Valid Arguments + if(saddr != NULL && port != NULL && buf != NULL && len != NULL && *len > 0) { +#ifndef PDP_DIRTY_MAGIC + // Schedule Timeout Removal + if(flag == 1) timeout = 0; +#else + // Nonblocking Simulator + int wouldblock = 0; + + // Minimum Timeout + uint32_t mintimeout = 250000; + + // Nonblocking Call + if(flag == 1) { + // Erase Nonblocking Flag + flag = 0; + + // Set Wouldblock Behaviour + wouldblock = 1; + + // Set Minimum Timeout (250ms) + if(timeout < mintimeout) timeout = mintimeout; + } +#endif + + // Apply Receive Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); + + // Sender Address + sockaddr_in sin; + + // Set Address Length (so we get the sender ip) + socklen_t sinlen = sizeof(sin); + //sin.sin_len = (uint8_t)sinlen; + // Acquire Network Lock + //_acquireNetworkLock(); + + // Receive Data + __change_blocking_mode(socket->id,flag); + int received = recvfrom(socket->id, (char *)buf, *len,0,(sockaddr *)&sin, &sinlen); + __change_blocking_mode(socket->id,0); + + // Received Data + if(received > 0) { + // Peer MAC + SceNetEtherAddr mac; + + // Find Peer MAC + if(__resolveIP(sin.sin_addr.s_addr, &mac) == 0) { + // Provide Sender Information + *saddr = mac; + *sport = htons(sin.sin_port); + + // Save Length + *len = received; + + // Free Network Lock + //_freeNetworkLock(); + + // Return Success + return 0; + } + } + + // Free Network Lock + //_freeNetworkLock(); + +#ifdef PDP_DIRTY_MAGIC + // Restore Nonblocking Flag for Return Value + if(wouldblock) flag = 1; +#endif + + // Nothing received + if(flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Socket ID + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } // Assuming < 0 for failure, homebrew SDK doesn't have much to say about this one.. int sceNetAdhocSetSocketAlert(int id, int flag) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocSetSocketAlert(%d, %d)", id, flag); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocSetSocketAlert(%d, %d)", id, flag); + return -1; } int sceNetAdhocPollSocket(u32 socketStructAddr, int count, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPollSocket(%08x, %i, %i, %i)", socketStructAddr, count, timeout, nonblock); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPollSocket(%08x, %i, %i, %i)", socketStructAddr, count, timeout, nonblock); + return -1; } - +/** + * Adhoc Emulator PDP Socket Delete + * @param id Socket File Descriptor + * @param flag Bitflags (Unused) + * @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED, ADHOC_INVALID_SOCKET_ID + */ int sceNetAdhocPdpDelete(int id, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpDelete(%d, %d)", id, unknown); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpDelete(%d, %d)", id, unknown); + // Library is initialized + if(netAdhocInited) { + // Valid Arguments + if(id > 0 && id <= 255) { + // Cast Socket + SceNetAdhocPdpStat * sock = pdp[id - 1]; + + // Valid Socket + if(socket != NULL) { + // Close Connection + closesocket(sock->id); + + // Remove Port Forward from Router + //sceNetPortClose("UDP", socket->lport); + + // Free Memory + // free(socket); + + // Free Translation Slot + pdp[id - 1] = NULL; + + // Success + return 0; + } + + // Invalid Socket ID + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } int sceNetAdhocctlGetAdhocId(u32 productStructAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetAdhocId(%x)", productStructAddr); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetAdhocId(%x)", productStructAddr); + return 0; } int sceNetAdhocctlScan() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlScan()"); - __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlScan()"); + __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); - return 0; + return 0; } int sceNetAdhocctlGetScanInfo() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetScanInfo()"); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetScanInfo()"); + return 0; } // TODO: How many handlers can the PSP actually have for Adhocctl? // TODO: Should we allow the same handler to be added more than once? u32 sceNetAdhocctlAddHandler(u32 handlerPtr, u32 handlerArg) { - bool foundHandler = false; - u32 retval = 0; - struct AdhocctlHandler handler; - memset(&handler, 0, sizeof(handler)); + bool foundHandler = false; + u32 retval = 0; + struct AdhocctlHandler handler; + memset(&handler, 0, sizeof(handler)); - while (adhocctlHandlers.find(retval) != adhocctlHandlers.end()) - ++retval; + while (adhocctlHandlers.find(retval) != adhocctlHandlers.end()) + ++retval; - handler.entryPoint = handlerPtr; - handler.argument = handlerArg; + handler.entryPoint = handlerPtr; + handler.argument = handlerArg; - for (std::map::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); it++) { - if (it->second.entryPoint == handlerPtr) { - foundHandler = true; - break; - } - } + for (std::map::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); it++) { + if (it->second.entryPoint == handlerPtr) { + foundHandler = true; + break; + } + } - if (!foundHandler && Memory::IsValidAddress(handlerPtr)) { - if (adhocctlHandlers.size() >= MAX_ADHOCCTL_HANDLERS) { - ERROR_LOG(SCENET, "UNTESTED UNTESTED sceNetAdhocctlAddHandler(%x, %x): Too many handlers", handlerPtr, handlerArg); - retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS; - return retval; - } - adhocctlHandlers[retval] = handler; - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): added handler %d", handlerPtr, handlerArg, retval); - } else { - ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): Same handler already exists", handlerPtr, handlerArg); - } + if (!foundHandler && Memory::IsValidAddress(handlerPtr)) { + if (adhocctlHandlers.size() >= MAX_ADHOCCTL_HANDLERS) { + ERROR_LOG(SCENET, "UNTESTED UNTESTED sceNetAdhocctlAddHandler(%x, %x): Too many handlers", handlerPtr, handlerArg); + retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS; + return retval; + } + adhocctlHandlers[retval] = handler; + WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): added handler %d", handlerPtr, handlerArg, retval); + } else { + ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlAddHandler(%x, %x): Same handler already exists", handlerPtr, handlerArg); + } - // The id to return is the number of handlers currently registered - return retval; + // The id to return is the number of handlers currently registered + return retval; } -int sceNetAdhocctlConnect(u32 ptrToGroupName) { - if (Memory::IsValidAddress(ptrToGroupName)) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlConnect(groupName=%s)", Memory::GetCharPointer(ptrToGroupName)); - } else { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlConnect(%x)", ptrToGroupName); - } - __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); - - return 0; -} u32 sceNetAdhocctlDisconnect() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlDisconnect()"); - __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); + // Library initialized + if(netAdhocctlInited) { + // Connected State (Adhoc Mode) + if(threadStatus == ADHOCCTL_STATE_CONNECTED) { + // Clear Network Name + memset(¶meter.group_name, 0, sizeof(parameter.group_name)); - return 0; + // Set Disconnected State + threadStatus = ADHOCCTL_STATE_DISCONNECTED; + + // Set HUD Connection Status + //setConnectionStatus(0); + + // Prepare Packet + uint8_t opcode = OPCODE_DISCONNECT; + + // Acquire Network Lock + //_acquireNetworkLock(); + + // Send Disconnect Request Packet + send(metasocket, (const char *)&opcode, 1, 0); + + // Free Network Lock + //_freeNetworkLock(); + + // Multithreading Lock + peerlock.lock(); + + // Clear Peer List + __freeFriendsRecursive(friends); + + // Delete Peer Reference + friends = 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 0; + } + + // Library uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -u32 sceNetAdhocctlDelHandler(u32 handlerID) { - if (adhocctlHandlers.find(handlerID) != adhocctlHandlers.end()) { - adhocctlHandlers.erase(handlerID); - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlDelHandler(%d): deleted handler %d", handlerID, handlerID); - } else { - ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlDelHandler(%d): asked to delete invalid handler %d", handlerID, handlerID); - } - return 0; +u32 sceNetAdhocctlDelHandler(u32 handlerID) { + if (adhocctlHandlers.find(handlerID) != adhocctlHandlers.end()) { + adhocctlHandlers.erase(handlerID); + WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlDelHandler(%d): deleted handler %d", handlerID, handlerID); + } else { + ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlDelHandler(%d): asked to delete invalid handler %d", handlerID, handlerID); + } + + return 0; } int sceNetAdhocctlTerm() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlTerm()"); - netAdhocctlInited = false; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlTerm()"); + if(netAdhocInited){ + netAdhocctlInited = false; + friendFinderThread.join(); + // Free sttuf here + closesocket(metasocket); + metasocket = -1; - return 0; +#ifdef _WIN32 + WSACleanup(); // WINDOWS ONLY! +#endif + } + + return 0; } int sceNetAdhocctlGetNameByAddr(const char *mac, u32 nameAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetNameByAddr(%s, %08x)", mac, nameAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetNameByAddr(%s, %08x)", mac, nameAddr); + return -1; } int sceNetAdhocctlJoin(u32 scanInfoAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlJoin(%08x)", scanInfoAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlJoin(%08x)", scanInfoAddr); + return -1; } int sceNetAdhocctlGetPeerInfo(const char *mac, int size, u32 peerInfoAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerInfo(%s, %i, %08x)", mac, size, peerInfoAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerInfo(%s, %i, %08x)", mac, size, peerInfoAddr); + return -1; } +/** + * Create and / or Join a Virtual Network of the specified Name + * @param group_name Virtual Network Name + * @return 0 on success or... ADHOCCTL_NOT_INITIALIZED, ADHOCCTL_INVALID_ARG, ADHOCCTL_BUSY + */ int sceNetAdhocctlCreate(const char *groupName) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlCreate(%s)", groupName); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlCreate(%s)", groupName); + const SceNetAdhocctlGroupName * groupNameStruct = (const SceNetAdhocctlGroupName *)groupName; + // Library initialized + if(netAdhocctlInited) { + // Valid Argument + if(__validNetworkName(groupNameStruct)) { + // Disconnected State + if(threadStatus == ADHOCCTL_STATE_DISCONNECTED) { + // Set Network Name + if(groupNameStruct != NULL) parameter.group_name = *groupNameStruct; + + // Reset Network Name + else memset(¶meter.group_name, 0, sizeof(parameter.group_name)); + + // 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(groupNameStruct != NULL) packet.group = *groupNameStruct; + + // Acquire Network Lock + + // Send Packet + send(metasocket, (const char *)&packet, sizeof(packet), 0); + + // Free Network Lock + + // Set HUD Connection Status + //setConnectionStatus(1); + + // Return Success + return 0; + } + + // Connected State + return ERROR_NET_ADHOCCTL_BUSY; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_ARG; + } + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; +} + +int sceNetAdhocctlConnect(u32 ptrToGroupName) { + if (Memory::IsValidAddress(ptrToGroupName)) { + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlConnect(groupName=%s)", Memory::GetCharPointer(ptrToGroupName)); + return sceNetAdhocctlCreate(Memory::GetCharPointer(ptrToGroupName)); + } else { + return ERROR_NET_ADHOC_INVALID_ADDR; + } } 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); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlCreateEnterGameMode(%s, %i, %i, %08x, %i, %i)", groupName, unknown, playerNum, macsAddr, timeout, unknown2); + 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); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlJoinEnterGameMode(%s, %s, %i, %i)", groupName, macAddr, timeout, unknown2); + return -1; } int sceNetAdhocTerm() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocTerm()"); - // Seems to return this when called a second time after being terminated without another initialisation - if(!netAdhocInited) - return SCE_KERNEL_ERROR_LWMUTEX_NOT_FOUND; - netAdhocInited = false; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocTerm()"); + // Library is initialized + if(netAdhocInited) { + // Delete PDP Sockets + __deleteAllPDP(); - return 0; + // Delete PTP Sockets + __deleteAllPTP(); + + // Delete Gamemode Buffer + //_deleteAllGMB(); + + // Terminate Internet Library + //sceNetInetTerm(); + + // Unload Internet Modules (Just keep it in memory... unloading crashes?!) + // if(_manage_modules != 0) sceUtilityUnloadModule(PSP_MODULE_NET_INET); + // Library shutdown + netAdhocInited = false; + return 0; + }else { + // Seems to return this when called a second time after being terminated without another initialisation + return SCE_KERNEL_ERROR_LWMUTEX_NOT_FOUND; + } } int sceNetAdhocGetPdpStat(int structSize, u32 structAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetPdpStat(%i, %08x)", structSize, structAddr); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetPdpStat(%i, %08x)", structSize, structAddr); + return 0; } int sceNetAdhocGetPtpStat(int structSize, u32 structAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetPtpStat(%i, %08x)", structSize, structAddr); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetPtpStat(%i, %08x)", structSize, structAddr); + return 0; } int sceNetAdhocPtpOpen(const char *srcmac, int srcport, const char *dstmac, int dstport, int bufsize, int retryDelay, int retryCount, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpOpen(%s : %i, %s : %i, %i, %i, %i, %08x)", srcmac, srcport, dstmac, dstport, bufsize, retryDelay, retryCount, unknown); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpOpen(%s : %i, %s : %i, %i, %i, %i, %08x)", srcmac, srcport, dstmac, dstport, bufsize, retryDelay, retryCount, unknown); + return 0; } int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpAccept(%i, %08x, %08x, %i, %i)", id, peerMacAddrPtr, peerPortPtr, timeout, nonblock); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpAccept(%i, %08x, %08x, %i, %i)", id, peerMacAddrPtr, peerPortPtr, timeout, nonblock); + return 0; } int sceNetAdhocPtpConnect(int id, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpConnect(%i, %i, %i)", id, timeout, nonblock); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpConnect(%i, %i, %i)", id, timeout, nonblock); + return -1; } int sceNetAdhocPtpClose(int id, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpClose(%i, %i)", id, unknown); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpClose(%i, %i)", id, unknown); + return 0; } int sceNetAdhocPtpListen(const char *srcmac, int srcport, int bufsize, int retryDelay, int retryCount, int queue, int unk) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpListen(%s : %i, %i, %i, %i, %i, %i)", srcmac, srcport, bufsize, retryDelay, retryCount, queue, unk); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpListen(%s : %i, %i, %i, %i, %i, %i)", srcmac, srcport, bufsize, retryDelay, retryCount, queue, unk); + return 0; } int sceNetAdhocPtpSend(int id, u32 data, u32 dataSizeAddr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpSend(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpSend(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); + return 0; } int sceNetAdhocPtpRecv(int id, u32 data, u32 dataSizeAddr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpRecv(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpRecv(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); + return 0; } int sceNetAdhocPtpFlush(int id, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpFlush(%i, %i, %i)", id, timeout, nonblock); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpFlush(%i, %i, %i)", id, timeout, nonblock); + return 0; } int sceNetAdhocGameModeCreateMaster(u32 data, int size) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateMaster(%08x, %i)", data, size); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateMaster(%08x, %i)", data, size); + return -1; } int sceNetAdhocGameModeCreateReplica(const char *mac, u32 data, int size) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateReplica(%s, %08x, %i)", mac, data, size); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeCreateReplica(%s, %08x, %i)", mac, data, size); + return -1; } int sceNetAdhocGameModeUpdateMaster() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeUpdateMaster()"); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeUpdateMaster()"); + return -1; } int sceNetAdhocGameModeDeleteMaster() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeDeleteMaster()"); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeDeleteMaster()"); + return -1; } int sceNetAdhocGameModeUpdateReplica(int id, u32 infoAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeUpdateReplica(%i, %08x)", id, infoAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeUpdateReplica(%i, %08x)", id, infoAddr); + return -1; } int sceNetAdhocGameModeDeleteReplica(int id) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeDeleteReplica(%i)", id); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGameModeDeleteReplica(%i)", id); + return -1; } int sceNetAdhocGetSocketAlert() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetSocketAlert()"); - return 0; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetSocketAlert()"); + return 0; } int sceNetAdhocMatchingInit(u32 memsize) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingInit(%08x)", memsize); - if (netAdhocMatchingInited) - return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED; - netAdhocMatchingInited = true; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingInit(%08x)", memsize); + if (netAdhocMatchingInited) + return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED; + netAdhocMatchingInited = true; - return 0; + return 0; } int sceNetAdhocMatchingTerm() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingTerm()"); - netAdhocMatchingInited = false; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingTerm()"); + netAdhocMatchingInited = false; - return 0; + return 0; } // Presumably returns a "matchingId". int sceNetAdhocMatchingCreate(int mode, int maxPeers, int port, int bufSize, int helloDelay, int pingDelay, int initCount, int msgDelay, u32 callbackAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCreate(%i, %i, %i, %i, %i, %i, %i, %i, %08x)", mode, maxPeers, port, bufSize, helloDelay, pingDelay, initCount, msgDelay, callbackAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCreate(%i, %i, %i, %i, %i, %i, %i, %i, %08x)", mode, maxPeers, port, bufSize, helloDelay, pingDelay, initCount, msgDelay, callbackAddr); + return -1; } 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); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingStart(%i, %i, %i, %i, %i, %i, %08x)", matchingId, evthPri, evthStack, inthPri, inthStack, optLen, optDataAddr); + return -1; } int sceNetAdhocMatchingStop(int matchingId) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingStop(%i)", matchingId); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingStop(%i)", matchingId); + return -1; } int sceNetAdhocMatchingDelete(int matchingId) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingDelete(%i)", matchingId); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingDelete(%i)", matchingId); + return -1; } int sceNetAdhocMatchingSelectTarget(int matchingId, const char *macAddress, int optLen, u32 optDataPtr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingSelectTarget(%i, %s, %i, %08x)", matchingId, macAddress, optLen, optDataPtr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingSelectTarget(%i, %s, %i, %08x)", matchingId, macAddress, optLen, optDataPtr); + return -1; } int sceNetAdhocMatchingCancelTargetWithOpt(int matchingId, const char *macAddress, int optLen, u32 optDataPtr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCancelTargetWithOpt(%i, %s, %i, %08x)", matchingId, macAddress, optLen, optDataPtr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCancelTargetWithOpt(%i, %s, %i, %08x)", matchingId, macAddress, optLen, optDataPtr); + return -1; } int sceNetAdhocMatchingCancelTarget(int matchingId, const char *macAddress) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCancelTarget(%i, %s)", matchingId, macAddress); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCancelTarget(%i, %s)", matchingId, macAddress); + return -1; } int sceNetAdhocMatchingGetHelloOpt(int matchingId, u32 optLenAddr, u32 optDataAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetHelloOpt(%i, %08x, %08x)", matchingId, optLenAddr, optDataAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetHelloOpt(%i, %08x, %08x)", matchingId, optLenAddr, optDataAddr); + return -1; } int sceNetAdhocMatchingSetHelloOpt(int matchingId, int optLenAddr, u32 optDataAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingSetHelloOpt(%i, %i, %08x)", matchingId, optLenAddr, optDataAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingSetHelloOpt(%i, %i, %08x)", matchingId, optLenAddr, optDataAddr); + return -1; } int sceNetAdhocMatchingGetMembers(int matchingId, u32 sizeAddr, u32 buf) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetMembers(%i, %08x, %08x)", matchingId, sizeAddr, buf); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetMembers(%i, %08x, %08x)", matchingId, sizeAddr, buf); + return -1; } int sceNetAdhocMatchingSendData(int matchingId, const char *mac, int dataLen, u32 dataAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingSendData(%i, %s, %i, %08x)", matchingId, mac, dataLen, dataAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingSendData(%i, %s, %i, %08x)", matchingId, mac, dataLen, dataAddr); + return -1; } int sceNetAdhocMatchingAbortSendData(int matchingId, const char *mac) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingAbortSendData(%i, %s)", matchingId, mac); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingAbortSendData(%i, %s)", matchingId, mac); + return -1; } int sceNetAdhocMatchingGetPoolMaxAlloc() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetPoolMaxAlloc()"); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetPoolMaxAlloc()"); + return -1; } int sceNetAdhocMatchingGetPoolStat() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetPoolStat()"); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetPoolStat()"); + return -1; } const HLEFunction sceNetAdhoc[] = { - {0xE1D621D7, WrapU_V, "sceNetAdhocInit"}, - {0xA62C6F57, WrapI_V, "sceNetAdhocTerm"}, - {0x0AD043ED, WrapI_U, "sceNetAdhocctlConnect"}, - {0x6f92741b, WrapI_CUIU, "sceNetAdhocPdpCreate"}, - {0xabed3790, WrapI_ICUVVUI, "sceNetAdhocPdpSend"}, - {0xdfe53e03, WrapI_ICUVVUI, "sceNetAdhocPdpRecv"}, - {0x7f27bb5e, WrapI_II, "sceNetAdhocPdpDelete"}, - {0xc7c1fc57, WrapI_IU, "sceNetAdhocGetPdpStat"}, - {0x157e6225, WrapI_II, "sceNetAdhocPtpClose"}, - {0x4da4c788, WrapI_IUUII, "sceNetAdhocPtpSend"}, - {0x877f6d66, WrapI_CICIIIII, "sceNetAdhocPtpOpen"}, - {0x8bea2b3e, WrapI_IUUII, "sceNetAdhocPtpRecv"}, - {0x9df81198, WrapI_IUUII, "sceNetAdhocPtpAccept"}, - {0xe08bdac1, WrapI_CIIIIII, "sceNetAdhocPtpListen"}, - {0xfc6fc07b, WrapI_III, "sceNetAdhocPtpConnect"}, - {0x9ac2eeac, WrapI_III, "sceNetAdhocPtpFlush"}, - {0xb9685118, WrapI_IU, "sceNetAdhocGetPtpStat"}, - {0x3278ab0c, WrapI_CUI, "sceNetAdhocGameModeCreateReplica"}, - {0x98c204c8, WrapI_V, "sceNetAdhocGameModeUpdateMaster"}, - {0xfa324b4e, WrapI_IU, "sceNetAdhocGameModeUpdateReplica"}, - {0xa0229362, WrapI_V, "sceNetAdhocGameModeDeleteMaster"}, - {0x0b2228e9, WrapI_I, "sceNetAdhocGameModeDeleteReplica"}, - {0x7F75C338, WrapI_UI, "sceNetAdhocGameModeCreateMaster"}, - {0x73bfd52d, WrapI_II, "sceNetAdhocSetSocketAlert"}, - {0x4d2ce199, WrapI_V, "sceNetAdhocGetSocketAlert"}, - {0x7a662d6b, WrapI_UIII, "sceNetAdhocPollSocket"}, + {0xE1D621D7, WrapU_V, "sceNetAdhocInit"}, + {0xA62C6F57, WrapI_V, "sceNetAdhocTerm"}, + {0x0AD043ED, WrapI_U, "sceNetAdhocctlConnect"}, + {0x6f92741b, WrapI_CUIU, "sceNetAdhocPdpCreate"}, + {0xabed3790, WrapI_ICUVIII, "sceNetAdhocPdpSend"}, + {0xdfe53e03, WrapI_IVVVVUI, "sceNetAdhocPdpRecv"}, + {0x7f27bb5e, WrapI_II, "sceNetAdhocPdpDelete"}, + {0xc7c1fc57, WrapI_IU, "sceNetAdhocGetPdpStat"}, + {0x157e6225, WrapI_II, "sceNetAdhocPtpClose"}, + {0x4da4c788, WrapI_IUUII, "sceNetAdhocPtpSend"}, + {0x877f6d66, WrapI_CICIIIII, "sceNetAdhocPtpOpen"}, + {0x8bea2b3e, WrapI_IUUII, "sceNetAdhocPtpRecv"}, + {0x9df81198, WrapI_IUUII, "sceNetAdhocPtpAccept"}, + {0xe08bdac1, WrapI_CIIIIII, "sceNetAdhocPtpListen"}, + {0xfc6fc07b, WrapI_III, "sceNetAdhocPtpConnect"}, + {0x9ac2eeac, WrapI_III, "sceNetAdhocPtpFlush"}, + {0xb9685118, WrapI_IU, "sceNetAdhocGetPtpStat"}, + {0x3278ab0c, WrapI_CUI, "sceNetAdhocGameModeCreateReplica"}, + {0x98c204c8, WrapI_V, "sceNetAdhocGameModeUpdateMaster"}, + {0xfa324b4e, WrapI_IU, "sceNetAdhocGameModeUpdateReplica"}, + {0xa0229362, WrapI_V, "sceNetAdhocGameModeDeleteMaster"}, + {0x0b2228e9, WrapI_I, "sceNetAdhocGameModeDeleteReplica"}, + {0x7F75C338, WrapI_UI, "sceNetAdhocGameModeCreateMaster"}, + {0x73bfd52d, WrapI_II, "sceNetAdhocSetSocketAlert"}, + {0x4d2ce199, WrapI_V, "sceNetAdhocGetSocketAlert"}, + {0x7a662d6b, WrapI_UIII, "sceNetAdhocPollSocket"}, }; const HLEFunction sceNetAdhocMatching[] = { - {0x2a2a1e07, WrapI_U, "sceNetAdhocMatchingInit"}, - {0x7945ecda, WrapI_V, "sceNetAdhocMatchingTerm"}, - {0xca5eda6f, WrapI_IIIIIIIIU, "sceNetAdhocMatchingCreate"}, - {0x93ef3843, WrapI_IIIIIIU, "sceNetAdhocMatchingStart"}, - {0x32b156b3, WrapI_I, "sceNetAdhocMatchingStop"}, - {0xf16eaf4f, WrapI_I, "sceNetAdhocMatchingDelete"}, - {0x5e3d4b79, WrapI_ICIU, "sceNetAdhocMatchingSelectTarget"}, - {0xea3c6108, WrapI_IC, "sceNetAdhocMatchingCancelTarget"}, - {0x8f58bedf, WrapI_ICIU, "sceNetAdhocMatchingCancelTargetWithOpt"}, - {0xb5d96c2a, WrapI_IUU, "sceNetAdhocMatchingGetHelloOpt"}, - {0xb58e61b7, WrapI_IIU, "sceNetAdhocMatchingSetHelloOpt"}, - {0xc58bcd9e, WrapI_IUU, "sceNetAdhocMatchingGetMembers"}, - {0xf79472d7, WrapI_ICIU, "sceNetAdhocMatchingSendData"}, - {0xec19337d, WrapI_IC, "sceNetAdhocMatchingAbortSendData"}, - {0x40F8F435, WrapI_V, "sceNetAdhocMatchingGetPoolMaxAlloc"}, - {0x9c5cfb7d, WrapI_V, "sceNetAdhocMatchingGetPoolStat"}, + {0x2a2a1e07, WrapI_U, "sceNetAdhocMatchingInit"}, + {0x7945ecda, WrapI_V, "sceNetAdhocMatchingTerm"}, + {0xca5eda6f, WrapI_IIIIIIIIU, "sceNetAdhocMatchingCreate"}, + {0x93ef3843, WrapI_IIIIIIU, "sceNetAdhocMatchingStart"}, + {0x32b156b3, WrapI_I, "sceNetAdhocMatchingStop"}, + {0xf16eaf4f, WrapI_I, "sceNetAdhocMatchingDelete"}, + {0x5e3d4b79, WrapI_ICIU, "sceNetAdhocMatchingSelectTarget"}, + {0xea3c6108, WrapI_IC, "sceNetAdhocMatchingCancelTarget"}, + {0x8f58bedf, WrapI_ICIU, "sceNetAdhocMatchingCancelTargetWithOpt"}, + {0xb5d96c2a, WrapI_IUU, "sceNetAdhocMatchingGetHelloOpt"}, + {0xb58e61b7, WrapI_IIU, "sceNetAdhocMatchingSetHelloOpt"}, + {0xc58bcd9e, WrapI_IUU, "sceNetAdhocMatchingGetMembers"}, + {0xf79472d7, WrapI_ICIU, "sceNetAdhocMatchingSendData"}, + {0xec19337d, WrapI_IC, "sceNetAdhocMatchingAbortSendData"}, + {0x40F8F435, WrapI_V, "sceNetAdhocMatchingGetPoolMaxAlloc"}, + {0x9c5cfb7d, WrapI_V, "sceNetAdhocMatchingGetPoolStat"}, }; int sceNetAdhocctlExitGameMode() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlExitGameMode()"); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlExitGameMode()"); + return -1; } int sceNetAdhocctlGetGameModeInfo(u32 infoAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetGameModeInfo(%08x)", infoAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetGameModeInfo(%08x)", infoAddr); + return -1; } int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerList(%08x, %08x)", sizeAddr, bufAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerList(%08x, %08x)", sizeAddr, bufAddr); + return -1; } int sceNetAdhocctlGetAddrByName(const char *nickName, u32 sizeAddr, u32 bufAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerList(%s, %08x, %08x)", nickName, sizeAddr, bufAddr); - return -1; + ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerList(%s, %08x, %08x)", nickName, sizeAddr, bufAddr); + return -1; } const HLEFunction sceNetAdhocctl[] = { - {0xE26F226E, WrapU_IIU, "sceNetAdhocctlInit"}, - {0x9D689E13, WrapI_V, "sceNetAdhocctlTerm"}, - {0x20B317A0, WrapU_UU, "sceNetAdhocctlAddHandler"}, - {0x6402490B, WrapU_U, "sceNetAdhocctlDelHandler"}, - {0x34401D65, WrapU_V, "sceNetAdhocctlDisconnect"}, - {0x0ad043ed, WrapI_U, "sceNetAdhocctlConnect"}, - {0x08fff7a0, WrapI_V, "sceNetAdhocctlScan"}, - {0x75ecd386, WrapI_U, "sceNetAdhocctlGetState"}, - {0x8916c003, WrapI_CU, "sceNetAdhocctlGetNameByAddr"}, - {0xded9d28e, WrapI_U, "sceNetAdhocctlGetParameter"}, - {0x81aee1be, WrapI_V, "sceNetAdhocctlGetScanInfo"}, - {0x5e7f79c9, WrapI_U, "sceNetAdhocctlJoin"}, - {0x8db83fdc, WrapI_CIU, "sceNetAdhocctlGetPeerInfo"}, - {0xec0635c1, WrapI_C, "sceNetAdhocctlCreate"}, - {0xa5c055ce, WrapI_CIIUII, "sceNetAdhocctlCreateEnterGameMode"}, - {0x1ff89745, WrapI_CCII, "sceNetAdhocctlJoinEnterGameMode"}, - {0xcf8e084d, WrapI_V, "sceNetAdhocctlExitGameMode"}, - {0xe162cb14, WrapI_UU, "sceNetAdhocctlGetPeerList"}, - {0x362cbe8f, WrapI_U, "sceNetAdhocctlGetAdhocId"}, - {0x5a014ce0, WrapI_U, "sceNetAdhocctlGetGameModeInfo"}, - {0x99560abe, WrapI_CUU, "sceNetAdhocctlGetAddrByName"}, - {0xb0b80e80, 0, "sceNetAdhocctlCreateEnterGameModeMin"}, // ?? + {0xE26F226E, WrapU_IIU, "sceNetAdhocctlInit"}, + {0x9D689E13, WrapI_V, "sceNetAdhocctlTerm"}, + {0x20B317A0, WrapU_UU, "sceNetAdhocctlAddHandler"}, + {0x6402490B, WrapU_U, "sceNetAdhocctlDelHandler"}, + {0x34401D65, WrapU_V, "sceNetAdhocctlDisconnect"}, + {0x0ad043ed, WrapI_U, "sceNetAdhocctlConnect"}, + {0x08fff7a0, WrapI_V, "sceNetAdhocctlScan"}, + {0x75ecd386, WrapI_U, "sceNetAdhocctlGetState"}, + {0x8916c003, WrapI_CU, "sceNetAdhocctlGetNameByAddr"}, + {0xded9d28e, WrapI_U, "sceNetAdhocctlGetParameter"}, + {0x81aee1be, WrapI_V, "sceNetAdhocctlGetScanInfo"}, + {0x5e7f79c9, WrapI_U, "sceNetAdhocctlJoin"}, + {0x8db83fdc, WrapI_CIU, "sceNetAdhocctlGetPeerInfo"}, + {0xec0635c1, WrapI_C, "sceNetAdhocctlCreate"}, + {0xa5c055ce, WrapI_CIIUII, "sceNetAdhocctlCreateEnterGameMode"}, + {0x1ff89745, WrapI_CCII, "sceNetAdhocctlJoinEnterGameMode"}, + {0xcf8e084d, WrapI_V, "sceNetAdhocctlExitGameMode"}, + {0xe162cb14, WrapI_UU, "sceNetAdhocctlGetPeerList"}, + {0x362cbe8f, WrapI_U, "sceNetAdhocctlGetAdhocId"}, + {0x5a014ce0, WrapI_U, "sceNetAdhocctlGetGameModeInfo"}, + {0x99560abe, WrapI_CUU, "sceNetAdhocctlGetAddrByName"}, + {0xb0b80e80, 0, "sceNetAdhocctlCreateEnterGameModeMin"}, // ?? }; const HLEFunction sceNetAdhocDiscover[] = { - {0x941B3877, 0, "sceNetAdhocDiscoverInitStart"}, - {0x52DE1B97, 0, "sceNetAdhocDiscoverUpdate"}, - {0x944DDBC6, 0, "sceNetAdhocDiscoverGetStatus"}, - {0xA2246614, 0, "sceNetAdhocDiscoverTerm"}, - {0xF7D13214, 0, "sceNetAdhocDiscoverStop"}, - {0xA423A21B, 0, "sceNetAdhocDiscoverRequestSuspend"}, + {0x941B3877, 0, "sceNetAdhocDiscoverInitStart"}, + {0x52DE1B97, 0, "sceNetAdhocDiscoverUpdate"}, + {0x944DDBC6, 0, "sceNetAdhocDiscoverGetStatus"}, + {0xA2246614, 0, "sceNetAdhocDiscoverTerm"}, + {0xF7D13214, 0, "sceNetAdhocDiscoverStop"}, + {0xA423A21B, 0, "sceNetAdhocDiscoverRequestSuspend"}, }; void Register_sceNetAdhoc() { - RegisterModule("sceNetAdhoc", ARRAY_SIZE(sceNetAdhoc), sceNetAdhoc); - RegisterModule("sceNetAdhocMatching", ARRAY_SIZE(sceNetAdhocMatching), sceNetAdhocMatching); - RegisterModule("sceNetAdhocDiscover", ARRAY_SIZE(sceNetAdhocDiscover), sceNetAdhocDiscover); - RegisterModule("sceNetAdhocctl", ARRAY_SIZE(sceNetAdhocctl), sceNetAdhocctl); + RegisterModule("sceNetAdhoc", ARRAY_SIZE(sceNetAdhoc), sceNetAdhoc); + RegisterModule("sceNetAdhocMatching", ARRAY_SIZE(sceNetAdhocMatching), sceNetAdhocMatching); + RegisterModule("sceNetAdhocDiscover", ARRAY_SIZE(sceNetAdhocDiscover), sceNetAdhocDiscover); + RegisterModule("sceNetAdhocctl", ARRAY_SIZE(sceNetAdhocctl), sceNetAdhocctl); } From 0574e6e1d142d1276985af99ee915df50ddd93bd Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Sat, 26 Oct 2013 23:08:21 +0100 Subject: [PATCH 02/21] More functions and support for games that use the netdiag --- Core/Dialog/PSPNetconfDialog.cpp | 15 +- Core/Dialog/PSPNetconfDialog.h | 2 +- Core/HLE/sceNetAdhoc.cpp | 386 +++++++++++++++++++++++++++++-- Core/HLE/sceNetAdhoc.h | 3 + 4 files changed, 387 insertions(+), 19 deletions(-) diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index d047c75cd1..f4b9a832ea 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -18,6 +18,11 @@ #include "PSPNetconfDialog.h" #include "ChunkFile.h" #include "../Core/MemMap.h" +#include "../Core/HLE/sceNetAdhoc.h" + +#define NETCONF_CONNECT_ADHOC 2 +#define NETCONF_CREATE_ADHOC 4 +#define NETCONF_JOIN_ADHOC 5 PSPNetconfDialog::PSPNetconfDialog() { } @@ -40,6 +45,14 @@ int PSPNetconfDialog::Init(u32 paramAddr) { } int PSPNetconfDialog::Update(int animSpeed) { + if(request.netAction == NETCONF_CONNECT_ADHOC || + request.netAction == NETCONF_CREATE_ADHOC || + request.netAction == NETCONF_JOIN_ADHOC){ + if(request.NetconfData != NULL){ + Shutdown(true); + return sceNetAdhocctlCreate(request.NetconfData->groupName); + } + } return 0; } @@ -58,4 +71,4 @@ void PSPNetconfDialog::DoState(PointerWrap &p) { return; p.Do(request); -} \ No newline at end of file +} diff --git a/Core/Dialog/PSPNetconfDialog.h b/Core/Dialog/PSPNetconfDialog.h index 421e41ac69..9774e74891 100644 --- a/Core/Dialog/PSPNetconfDialog.h +++ b/Core/Dialog/PSPNetconfDialog.h @@ -46,4 +46,4 @@ public: private: SceUtilityNetconfParam request; -}; \ No newline at end of file +}; diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 8728e34ff0..60e71adb16 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -78,6 +78,8 @@ enum { ERROR_NET_ADHOC_INVALID_DATALEN = 0x80410705, ERROR_NET_ADHOC_INVALID_PORT = 0x80410703, + ERROR_NET_ADHOCCTL_INVALID_ARG = 0x80410B04, + ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF = 0x80410b03, ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED = 0x80410b07, ERROR_NET_ADHOCCTL_NOT_INITIALIZED = 0x80410b08, @@ -246,6 +248,127 @@ typedef struct SceNetAdhocGameModeBufferStat { uint32_t master; SceNetAdhocGameModeOptData opt; }; + +// Matching Peer Information +typedef struct SceNetAdhocMatchingMember { + struct SceNetAdhocMatchingMember * next; + SceNetEtherAddr addr; + uint8_t padding[2]; +} __attribute__((packed)) SceNetAdhocMatchingMember; + +// Internal Matching Peer Information +typedef struct SceNetAdhocMatchingMemberInternal { + // Next Peer + struct SceNetAdhocMatchingMemberInternal * next; + + // MAC Address + SceNetEtherAddr mac; + + // State Variable + int state; + + // Send in Progress + int sending; + + // Last Heartbeat + uint64_t lastping; +} SceNetAdhocMatchingMemberInternal; + +// Adhoc Matching Handler +typedef void(*SceNetAdhocMatchingHandler)(int id, int event, SceNetEtherAddr * peer, int optlen, void * opt); + +// Thread Message Stack Item +typedef struct ThreadMessage +{ + // Next Thread Message + struct ThreadMessage * next; + + // Stack Event Opcode + uint32_t opcode; + + // Target MAC Address + SceNetEtherAddr mac; + + // Optional Data Length + int optlen; +} ThreadMessage; + +// Established Peer + +// Context Information +typedef struct SceNetAdhocMatchingContext { + // Next Context + struct SceNetAdhocMatchingContext * next; + + // Externally Visible ID + int id; + + // Matching Mode (HOST, CLIENT, P2P) + int mode; + + // Running Flag (1 = running, 0 = created) + int running; + + // Maximum Number of Peers (for HOST, P2P) + int maxpeers; + + // Local MAC Address + SceNetEtherAddr mac; + + // Peer List for Connectees + SceNetAdhocMatchingMemberInternal * peerlist; + + // Local PDP Port + uint16_t port; + + // Local PDP Socket + int socket; + + // Receive Buffer Length + int rxbuflen; + + // Receive Buffer + uint8_t * rxbuf; + + // Hello Broadcast Interval (Microseconds) + uint32_t hello_int; + + // Keep-Alive Broadcast Interval (Microseconds) + uint32_t keepalive_int; + + // Resend Interval (Microseconds) + uint32_t resend_int; + + // Resend-Counter + int resendcounter; + + // Keep-Alive Counter + int keepalivecounter; + + // Event Handler + SceNetAdhocMatchingHandler handler; + + // Hello Data Length + uint32_t hellolen; + + // Hello Data + void * hello; + + // Event Caller Thread + int event_thid; + + // IO Handler Thread + int input_thid; + + // Event Caller Thread Message Stack + int event_stack_lock; + ThreadMessage * event_stack; + + // IO Handler Thread Message Stack + int input_stack_lock; + ThreadMessage * input_stack; +} SceNetAdhocMatchingContext; + // End of psp definitions #define OPCODE_PING 0 @@ -343,6 +466,8 @@ static SceNetAdhocctlScanInfo * networks = NULL; static std::mutex peerlock; static SceNetAdhocPdpStat * pdp[255]; static SceNetAdhocPtpStat * ptp[255]; +static uint32_t fakePoolSize = 0; +static SceNetAdhocMatchingContext * contexts = NULL; // End of Aux vars struct AdhocctlHandler { @@ -1054,6 +1179,51 @@ void __deleteAllPTP(void) { } } + +/** + * Count Virtual Networks by analyzing the Friend List + * @return Number of Virtual Networks + */ +int __countAvailableNetworks(void) { + // Network Count + int count = 0; + + // Group Reference + SceNetAdhocctlScanInfo * group = networks; + + // Count Groups + for(; group != NULL; group = group->next) count++; + + // Return Network Count + return count; +} + +/** + * Return Number of active Peers in the same Network as the Local Player + * @return Number of active Peers + */ +int __getActivePeerCount(void) { + // Counter + int count = 0; + + // #ifdef LOCALHOST_AS_PEER + // // Increase for Localhost + // count++; + // #endif + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Increase Counter + count++; + } + + // Return Result + return count; +} + void __handlerUpdateCallback(u64 userdata, int cycleslate){ int buff[2]; split64(userdata,buff); @@ -1143,7 +1313,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = port; //This not safe in any way... + addr.sin_port = htons(port); //This not safe in any way... // Bound Socket to local Port if(bind(usocket, (sockaddr *)&addr, sizeof(addr)) == 0) { @@ -1230,7 +1400,6 @@ 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) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpSend(%d, %s, %d, %p, %p, %d, %d)", id, mac, port, data, len, timeout, flag); SceNetEtherAddr * daddr = (SceNetEtherAddr *)mac; uint16 dport = (uint16 )port; // Library is initialized @@ -1249,10 +1418,6 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i // Valid Destination Address if(daddr != NULL) { // Log Destination -// #ifdef DEBUG -// printk("Attempting PDP Send to %02X:%02X:%02X:%02X:%02X:%02X on Port %u\n", daddr->data[0], daddr->data[1], daddr->data[2], daddr->data[3], daddr->data[4], daddr->data[5], dport); -// #endif - // Schedule Timeout Removal if(flag) timeout = 0; @@ -1325,8 +1490,12 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i target.sin_addr.s_addr = peer->ip_addr; target.sin_port = htons(dport); + uint8_t * thing = (uint8_t *)&peer->ip_addr; + // printf("Attempting PDP Send to %u.%u.%u.%u on Port %u\n", thing[0], thing[1], thing[2], thing[3], dport); // Send Data + __change_blocking_mode(socket->id, flag); sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target)); + __change_blocking_mode(socket->id, 0); } // Free Peer Lock @@ -1377,8 +1546,6 @@ 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) { - //ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpRecv(%d, %s, %d, %p, %p, %d, %d)", id, addr, port, buf, dataLength, timeout, flag); - // This spams a lot... SceNetEtherAddr *saddr = (SceNetEtherAddr *)addr; uint16_t * sport = (uint16_t *)port; int * len = (int *)dataLength; @@ -1539,15 +1706,108 @@ int sceNetAdhocctlGetAdhocId(u32 productStructAddr) { } int sceNetAdhocctlScan() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlScan()"); - __UpdateAdhocctlHandlers(0, ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF); - return 0; + // Library initialized + if(netAdhocctlInited) { + // Not connected + if(threadStatus == ADHOCCTL_STATE_DISCONNECTED) { + threadStatus = ADHOCCTL_STATE_SCANNING; + + // Prepare Scan Request Packet + uint8_t opcode = OPCODE_SCAN; + + // Send Scan Request Packet + send(metasocket, (char *)&opcode, 1, 0); + + // Return Success + return 0; + } + + // Library is busy + return ERROR_NET_ADHOCCTL_BUSY; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } -int sceNetAdhocctlGetScanInfo() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetScanInfo()"); - return 0; +int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) { + int * buflen = (int *)Memory::GetPointer(size); + SceNetAdhocctlScanInfo * buf = NULL; + if(Memory::IsValidAddress(bufAddr)){ + buf = (SceNetAdhocctlScanInfo *)Memory::GetPointer(bufAddr); + } + // Library initialized + if(netAdhocctlInited) { + // Minimum Argument Requirements + if(buflen != NULL) { + // Multithreading Lock + peerlock.lock(); + + // Length Returner Mode + if(buf == NULL) *buflen = __countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfo); + + // Normal Information Mode + else { + // Clear Memory + memset(buf, 0, *buflen); + + // Network Discovery Counter + int discovered = 0; + + // Count requested Networks + int requestcount = *buflen / sizeof(SceNetAdhocctlScanInfo); + + // Minimum Argument Requirements + if(requestcount > 0) { + // Group List Element + SceNetAdhocctlScanInfo * group = networks; + + // Iterate Group List + for(; group != NULL && discovered < requestcount; group = group->next) { + // Copy Group Information + buf[discovered] = *group; + + // Exchange Adhoc Channel + // sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_ADHOC_CHANNEL, &buf[discovered].channel); + + // Fake Channel Number 1 on Automatic Channel + // if(buf[discovered].channel == 0) buf[discovered].channel = 1; + + //Always Fake Channel 1 + buf[discovered].channel = 1; + + // Increase Discovery Counter + discovered++; + } + + // Link List + int i = 0; for(; i < discovered - 1; i++) { + // Link Network + buf[i].next = &buf[i + 1]; + } + + // Fix Last Element + if(discovered > 0) buf[discovered - 1].next = NULL; + } + + // Fix Size + *buflen = discovered * sizeof(SceNetAdhocctlScanInfo); + } + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + + // Generic Error + return -1; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } // TODO: How many handlers can the PSP actually have for Adhocctl? @@ -1871,6 +2131,21 @@ int sceNetAdhocGetSocketAlert() { } int sceNetAdhocMatchingInit(u32 memsize) { + // Uninitialized Library + if(netAdhocMatchingInited) { + // Save Fake Pool Size + fakePoolSize = memsize; + + // Initialize Library + netAdhocMatchingInited = true; + + // Return Success + return 0; + }else{ + } + + + // Initialized Library ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingInit(%08x)", memsize); if (netAdhocMatchingInited) return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED; @@ -2018,8 +2293,85 @@ int sceNetAdhocctlGetGameModeInfo(u32 infoAddr) { } int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlGetPeerList(%08x, %08x)", sizeAddr, bufAddr); - return -1; + int * buflen = (int *)Memory::GetPointer(sizeAddr); + SceNetAdhocctlPeerInfo * buf = NULL; + if(Memory::IsValidAddress(bufAddr)){ + buf = (SceNetAdhocctlPeerInfo *)Memory::GetPointer(bufAddr); + } + // Initialized Library + if(netAdhocctlInited) { + // Minimum Arguments + if(buflen != NULL) { + // Multithreading Lock + peerlock.lock(); + + // Length Calculation Mode + if(buf == NULL) *buflen = __getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfo); + + // Normal Mode + else { + // Discovery Counter + int discovered = 0; + + // Calculate Request Count + int requestcount = *buflen / sizeof(SceNetAdhocctlPeerInfo); + + // Clear Memory + memset(buf, 0, *buflen); + + // Minimum Arguments + if(requestcount > 0) { + #ifdef LOCALHOST_AS_PEER + // // Get Local IP Address + // union SceNetApctlInfo info; if(sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info) == 0) + // { + // // Add Local Address + // buf[discovered].nickname = _parameter.nickname; + // sceWlanGetEtherAddr((void *)buf[discovered].mac_addr.data); + // sceNetInetInetAton(info.ip, &buf[discovered].ip_addr); + // buf[discovered++].last_recv = sceKernelGetSystemTimeWide(); + // } + #endif + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL && discovered < requestcount; peer = peer->next) { + // Fake Receive Time + peer->last_recv = (uint64_t)time(NULL); + + // Copy Peer Info + buf[discovered++] = *peer; + } + + // Link List + int i = 0; for(; i < discovered - 1; i++) { + // Link Network + buf[i].next = &buf[i + 1]; + } + + // Fix Last Element + if(discovered > 0) buf[discovered - 1].next = NULL; + } + + // Fix Size + *buflen = discovered * sizeof(SceNetAdhocctlPeerInfo); + } + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + + // Invalid Arguments + return ERROR_NET_ADHOCCTL_INVALID_ARG; + } + + // Uninitialized Library + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } int sceNetAdhocctlGetAddrByName(const char *nickName, u32 sizeAddr, u32 bufAddr) { @@ -2038,7 +2390,7 @@ const HLEFunction sceNetAdhocctl[] = { {0x75ecd386, WrapI_U, "sceNetAdhocctlGetState"}, {0x8916c003, WrapI_CU, "sceNetAdhocctlGetNameByAddr"}, {0xded9d28e, WrapI_U, "sceNetAdhocctlGetParameter"}, - {0x81aee1be, WrapI_V, "sceNetAdhocctlGetScanInfo"}, + {0x81aee1be, WrapI_UU, "sceNetAdhocctlGetScanInfo"}, {0x5e7f79c9, WrapI_U, "sceNetAdhocctlJoin"}, {0x8db83fdc, WrapI_CIU, "sceNetAdhocctlGetPeerInfo"}, {0xec0635c1, WrapI_C, "sceNetAdhocctlCreate"}, diff --git a/Core/HLE/sceNetAdhoc.h b/Core/HLE/sceNetAdhoc.h index 2c7c1ec89b..1529557593 100644 --- a/Core/HLE/sceNetAdhoc.h +++ b/Core/HLE/sceNetAdhoc.h @@ -24,3 +24,6 @@ void Register_sceNetAdhoc(); void __NetAdhocInit(); void __NetAdhocShutdown(); void __NetAdhocDoState(PointerWrap &p); + +// I have to call this from netdialog +int sceNetAdhocctlCreate(const char * groupName); From 47947fd3f783c29ab67c9c085f990ef2d676a09e Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Mon, 28 Oct 2013 19:34:09 +0000 Subject: [PATCH 03/21] adds some matching functions --- Core/HLE/sceNetAdhoc.cpp | 197 +++++++++++++++++++++++++++++++++++---- 1 file changed, 180 insertions(+), 17 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 60e71adb16..6ad80a11ba 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -85,11 +85,35 @@ enum { ERROR_NET_ADHOCCTL_NOT_INITIALIZED = 0x80410b08, ERROR_NET_ADHOCCTL_DISCONNECTED = 0x80410b09, ERROR_NET_ADHOCCTL_BUSY = 0x80410b10, - ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS = 0x80410b12, + ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS = 0x80410b12, - ERROR_NET_NO_SPACE = 0x80410001, + ERROR_NET_ADHOC_MATCHING_INVALID_MODE = 0x80410801, + ERROR_NET_ADHOC_MATCHING_INVALID_MAXNUM = 0x80410803, + ERROR_NET_ADHOC_MATCHING_RXBUF_TOO_SHORT = 0x80410804, + ERROR_NET_ADHOC_MATCHING_INVALID_OPTLEN = 0x80410805, + ERROR_NET_ADHOC_MATCHING_INVALID_ARG = 0x80410806, + ERROR_NET_ADHOC_MATCHING_INVALID_ID = 0x80410807, + ERROR_NET_ADHOC_MATCHING_ID_NOT_AVAIL = 0x80410808, + ERROR_NET_ADHOC_MATCHING_NO_SPACE = 0x80410809, + ERROR_NET_ADHOC_MATCHING_IS_RUNNING = 0x8041080A, + ERROR_NET_ADHOC_MATCHING_NOT_RUNNING = 0x8041080B, + ERROR_NET_ADHOC_MATCHING_UNKNOWN_TARGET = 0x8041080C, + ERROR_NET_ADHOC_MATCHING_TARGET_NOT_READY = 0x8041080D, + ERROR_NET_ADHOC_MATCHING_EXCEED_MAXNUM = 0x8041080E, + ERROR_NET_ADHOC_MATCHING_REQUEST_IN_PROGRESS = 0x8041080F, + ERROR_NET_ADHOC_MATCHING_ALREADY_ESTABLISHED = 0x80410810, + ERROR_NET_ADHOC_MATCHING_BUSY = 0x80410811, + ERROR_NET_ADHOC_MATCHING_PORT_IN_USE = 0x80410814, + ERROR_NET_ADHOC_MATCHING_STACKSIZE_TOO_SHORT = 0x80410815, + ERROR_NET_ADHOC_MATCHING_INVALID_DATALEN = 0x80410816, + ERROR_NET_ADHOC_MATCHING_NOT_ESTABLISHED = 0x80410817, + ERROR_NET_ADHOC_MATCHING_DATA_BUSY = 0x80410818, + + ERROR_NET_NO_SPACE = 0x80410001 }; +int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown); + enum { PSP_ADHOC_POLL_READY_TO_SEND = 1, PSP_ADHOC_POLL_DATA_AVAILABLE = 2, @@ -274,8 +298,19 @@ typedef struct SceNetAdhocMatchingMemberInternal { uint64_t lastping; } SceNetAdhocMatchingMemberInternal; -// Adhoc Matching Handler -typedef void(*SceNetAdhocMatchingHandler)(int id, int event, SceNetEtherAddr * peer, int optlen, void * opt); + +// Matching handler +struct SceNetAdhocMatchingHandlerArgs { + int id; + int event; + SceNetEtherAddr * peer; + int optlen; + void * opt; +}; + +struct SceNetAdhocMatchingHandler { + u32 entryPoint; +}; // Thread Message Stack Item typedef struct ThreadMessage @@ -1224,6 +1259,49 @@ int __getActivePeerCount(void) { return count; } +/** + * Find Internal Matching Context for Matching ID + * @param id Matching ID + * @return Matching Context Pointer or... NULL + */ +SceNetAdhocMatchingContext * __findMatchingContext(int id) { + // Iterate Matching Context List + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // Found Matching ID + if(item->id == id) return item; + } + + // Context not found + return NULL; +} + +/** + * Find Free Matching ID + * @return First unoccupied Matching ID + */ +int __findFreeMatchingID(void) { + // Minimum Matching ID + int min = 1; + + // Maximum Matching ID + int max = 0; + + // Find highest Matching ID + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // New Maximum + if(max < item->id) max = item->id; + } + + // Find unoccupied ID + int i = min; for(; i < max; i++) { + // Found unoccupied ID + if(__findMatchingContext(i) == NULL) return i; + } + + // Append at virtual end + return max + 1; +} + void __handlerUpdateCallback(u64 userdata, int cycleslate){ int buff[2]; split64(userdata,buff); @@ -2132,7 +2210,7 @@ int sceNetAdhocGetSocketAlert() { int sceNetAdhocMatchingInit(u32 memsize) { // Uninitialized Library - if(netAdhocMatchingInited) { + if(!netAdhocMatchingInited) { // Save Fake Pool Size fakePoolSize = memsize; @@ -2142,16 +2220,8 @@ int sceNetAdhocMatchingInit(u32 memsize) { // Return Success return 0; }else{ - } - - - // Initialized Library - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingInit(%08x)", memsize); - if (netAdhocMatchingInited) return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED; - netAdhocMatchingInited = true; - - return 0; + } } int sceNetAdhocMatchingTerm() { @@ -2164,9 +2234,102 @@ int sceNetAdhocMatchingTerm() { // Presumably returns a "matchingId". -int sceNetAdhocMatchingCreate(int mode, int maxPeers, int port, int bufSize, int helloDelay, int pingDelay, int initCount, int msgDelay, u32 callbackAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingCreate(%i, %i, %i, %i, %i, %i, %i, %i, %08x)", mode, maxPeers, port, bufSize, helloDelay, pingDelay, initCount, msgDelay, callbackAddr); - return -1; +int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int hello_int, int keepalive_int, int init_count, int rexmt_int, u32 callbackAddr) { + ERROR_LOG(SCENET, "sceNetAdhocMatchingCreate"); + SceNetAdhocMatchingHandler handler; + handler.entryPoint = callbackAddr; + + // Library initialized + if(netAdhocMatchingInited) { + // Valid Member Limit + if(maxnum > 1 && maxnum <= 16) { + // Valid Receive Buffer size + if(rxbuflen >= 1024) { + // Valid Arguments + if(mode >= 1 && mode <= 3) { + // Iterate Matching Contexts + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // Port Match found + if(item->port == port) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; + } + + // Allocate Context Memory + SceNetAdhocMatchingContext * context = (SceNetAdhocMatchingContext *)malloc(sizeof(SceNetAdhocMatchingContext)); + + // Allocated Memory + if(context != NULL) { + // Create PDP Socket + SceNetEtherAddr localmac; __getLocalMac(&localmac); + const char * mac = (const char *)&localmac.data; + int socket = sceNetAdhocPdpCreate(mac, (uint32_t)port, rxbuflen, 0); + // Created PDP Socket + if(socket > 0) { + // Clear Memory + memset(context, 0, sizeof(SceNetAdhocMatchingContext)); + + // Allocate Receive Buffer + context->rxbuf = (uint8_t *)malloc(rxbuflen); + + // Allocated Memory + if(context->rxbuf != NULL) { + // Clear Memory + memset(context->rxbuf, 0, rxbuflen); + + // Fill in Context Data + context->id = __findFreeMatchingID(); + context->mode = mode; + context->maxpeers = maxnum; + context->port = port; + context->socket = socket; + context->rxbuflen = rxbuflen; + context->hello_int = hello_int; + context->keepalive_int = 500000; + //context->keepalive_int = keepalive_int; + context->resendcounter = init_count; + context->keepalivecounter = 100; + //context->keepalivecounter = init_count; + context->resend_int = rexmt_int; + context->handler = handler; + + // Fill in Selfpeer + context->mac = localmac; + + // Link Context + context->next = contexts; + contexts = context; + + // Return Matching ID + return context->id; + } + + // Close PDP Socket + sceNetAdhocPdpDelete(socket, 0); + } + + // Free Memory + free(context); + + // Port in use + if(socket < 1) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; + } + + // Out of Memory + return ERROR_NET_ADHOC_MATCHING_NO_SPACE; + } + + // InvalidERROR_NET_Arguments + return ERROR_NET_ADHOC_MATCHING_INVALID_ARG; + } + + // Invalid Receive Buffer Size + return ERROR_NET_ADHOC_MATCHING_RXBUF_TOO_SHORT; + } + + // Invalid Member Limit + return ERROR_NET_ADHOC_MATCHING_INVALID_MAXNUM; + } + // Uninitialized Library + return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED; } int sceNetAdhocMatchingStart(int matchingId, int evthPri, int evthStack, int inthPri, int inthStack, int optLen, u32 optDataAddr) { From 5959f5b48608744b94a8dbe137bd4e5f2e07a7f2 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Mon, 28 Oct 2013 20:30:25 +0000 Subject: [PATCH 04/21] Packs most of psp data structs and fixes sceNetAdhocctlGetParameter --- Core/HLE/sceNetAdhoc.cpp | 958 ++++++++++++++++++++------------------- 1 file changed, 488 insertions(+), 470 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 6ad80a11ba..951d19bc91 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -127,14 +127,6 @@ static bool netAdhocInited; static bool netAdhocctlInited; static bool netAdhocMatchingInited; -// These might come in handy in the future, if PPSSPP ever supports wifi/ad-hoc.. -struct SceNetAdhocctlParams { - s32_le channel; //which ad-hoc channel to connect to - char name[8]; //connection name - u8 bssid[6]; //BSSID of the connection? - char nickname[128]; //PSP's nickname? -}; - // psp strutcs and definitions #define ADHOCCTL_MODE_ADHOC 0 #define ADHOCCTL_MODE_GAMEMODE 1 @@ -162,23 +154,12 @@ struct SceNetAdhocctlParams { #define UTILITY_NETCONF_STATUS_FINISHED 3 #define UTILITY_NETCONF_STATUS_SHUTDOWN 4 -// Ethernet Address (MAC) + +// Ethernet Address #define ETHER_ADDR_LEN 6 typedef struct SceNetEtherAddr { uint8_t data[ETHER_ADDR_LEN]; -} SceNetEtherAddr; - -// Adhoc Virtual Network Name (1234ABCD) -#define ADHOCCTL_GROUPNAME_LEN 8 -typedef struct SceNetAdhocctlGroupName { - uint8_t data[ADHOCCTL_GROUPNAME_LEN]; -} SceNetAdhocctlGroupName; - -// Player Nickname -#define ADHOCCTL_NICKNAME_LEN 128 -typedef struct SceNetAdhocctlNickname { - uint8_t data[ADHOCCTL_NICKNAME_LEN]; -} SceNetAdhocctlNickname; +} __attribute__((packed)) SceNetEtherAddr; // Adhoc ID (Game Product Key) #define ADHOCCTL_ADHOCID_LEN 9 @@ -188,11 +169,17 @@ typedef struct SceNetAdhocctlAdhocId { uint8_t padding[3]; } SceNetAdhocctlAdhocId; +// Adhoc Virtual Network Name +#define ADHOCCTL_GROUPNAME_LEN 8 +typedef struct SceNetAdhocctlGroupName { + uint8_t data[ADHOCCTL_GROUPNAME_LEN]; +} __attribute__((packed)) SceNetAdhocctlGroupName; + // Virtual Network Host Information typedef struct SceNetAdhocctlBSSId { SceNetEtherAddr mac_addr; uint8_t padding[2]; -}; +} __attribute__((packed)) SceNetAdhocctlBSSId; // Virtual Network Information typedef struct SceNetAdhocctlScanInfo { @@ -201,14 +188,21 @@ typedef struct SceNetAdhocctlScanInfo { SceNetAdhocctlGroupName group_name; SceNetAdhocctlBSSId bssid; int mode; -}; +} __attribute__((packed)) SceNetAdhocctlScanInfo; + +// Player Nickname +#define ADHOCCTL_NICKNAME_LEN 128 +typedef struct SceNetAdhocctlNickname { + uint8_t data[ADHOCCTL_NICKNAME_LEN]; +} __attribute__((packed)) SceNetAdhocctlNickname; + // Active Virtual Network Information typedef struct SceNetAdhocctlParameter { int channel; SceNetAdhocctlGroupName group_name; SceNetAdhocctlBSSId bssid; SceNetAdhocctlNickname nickname; -}; +} __attribute__((packed)) SceNetAdhocctlParameter; // Peer Information typedef struct SceNetAdhocctlPeerInfo { @@ -218,14 +212,15 @@ typedef struct SceNetAdhocctlPeerInfo { uint32_t ip_addr; uint8_t padding[2]; uint64_t last_recv; -}; +} __attribute__((packed)) SceNetAdhocctlPeerInfo; // Game Mode Peer List #define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16 typedef struct SceNetAdhocctlGameModeInfo { int num; SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS]; -}; +} __attribute__((packed)) SceNetAdhocctlGameModeInfo; +// Ethernet Address (MAC) // Socket Polling Event Listener typedef struct SceNetAdhocPollSd { @@ -275,27 +270,27 @@ typedef struct SceNetAdhocGameModeBufferStat { // Matching Peer Information typedef struct SceNetAdhocMatchingMember { - struct SceNetAdhocMatchingMember * next; - SceNetEtherAddr addr; - uint8_t padding[2]; + struct SceNetAdhocMatchingMember * next; + SceNetEtherAddr addr; + uint8_t padding[2]; } __attribute__((packed)) SceNetAdhocMatchingMember; // Internal Matching Peer Information typedef struct SceNetAdhocMatchingMemberInternal { - // Next Peer - struct SceNetAdhocMatchingMemberInternal * next; - - // MAC Address - SceNetEtherAddr mac; - - // State Variable - int state; - - // Send in Progress - int sending; - - // Last Heartbeat - uint64_t lastping; + // Next Peer + struct SceNetAdhocMatchingMemberInternal * next; + + // MAC Address + SceNetEtherAddr mac; + + // State Variable + int state; + + // Send in Progress + int sending; + + // Last Heartbeat + uint64_t lastping; } SceNetAdhocMatchingMemberInternal; @@ -315,93 +310,93 @@ struct SceNetAdhocMatchingHandler { // Thread Message Stack Item typedef struct ThreadMessage { - // Next Thread Message - struct ThreadMessage * next; - - // Stack Event Opcode - uint32_t opcode; - - // Target MAC Address - SceNetEtherAddr mac; - - // Optional Data Length - int optlen; + // Next Thread Message + struct ThreadMessage * next; + + // Stack Event Opcode + uint32_t opcode; + + // Target MAC Address + SceNetEtherAddr mac; + + // Optional Data Length + int optlen; } ThreadMessage; // Established Peer // Context Information typedef struct SceNetAdhocMatchingContext { - // Next Context - struct SceNetAdhocMatchingContext * next; - - // Externally Visible ID - int id; - - // Matching Mode (HOST, CLIENT, P2P) - int mode; - - // Running Flag (1 = running, 0 = created) - int running; - - // Maximum Number of Peers (for HOST, P2P) - int maxpeers; - - // Local MAC Address - SceNetEtherAddr mac; - - // Peer List for Connectees - SceNetAdhocMatchingMemberInternal * peerlist; - - // Local PDP Port - uint16_t port; - - // Local PDP Socket - int socket; - - // Receive Buffer Length - int rxbuflen; - - // Receive Buffer - uint8_t * rxbuf; - - // Hello Broadcast Interval (Microseconds) - uint32_t hello_int; - - // Keep-Alive Broadcast Interval (Microseconds) - uint32_t keepalive_int; - - // Resend Interval (Microseconds) - uint32_t resend_int; - - // Resend-Counter - int resendcounter; - - // Keep-Alive Counter - int keepalivecounter; - - // Event Handler - SceNetAdhocMatchingHandler handler; - - // Hello Data Length - uint32_t hellolen; - - // Hello Data - void * hello; - - // Event Caller Thread - int event_thid; - - // IO Handler Thread - int input_thid; - - // Event Caller Thread Message Stack - int event_stack_lock; - ThreadMessage * event_stack; - - // IO Handler Thread Message Stack - int input_stack_lock; - ThreadMessage * input_stack; + // Next Context + struct SceNetAdhocMatchingContext * next; + + // Externally Visible ID + int id; + + // Matching Mode (HOST, CLIENT, P2P) + int mode; + + // Running Flag (1 = running, 0 = created) + int running; + + // Maximum Number of Peers (for HOST, P2P) + int maxpeers; + + // Local MAC Address + SceNetEtherAddr mac; + + // Peer List for Connectees + SceNetAdhocMatchingMemberInternal * peerlist; + + // Local PDP Port + uint16_t port; + + // Local PDP Socket + int socket; + + // Receive Buffer Length + int rxbuflen; + + // Receive Buffer + uint8_t * rxbuf; + + // Hello Broadcast Interval (Microseconds) + uint32_t hello_int; + + // Keep-Alive Broadcast Interval (Microseconds) + uint32_t keepalive_int; + + // Resend Interval (Microseconds) + uint32_t resend_int; + + // Resend-Counter + int resendcounter; + + // Keep-Alive Counter + int keepalivecounter; + + // Event Handler + SceNetAdhocMatchingHandler handler; + + // Hello Data Length + uint32_t hellolen; + + // Hello Data + void * hello; + + // Event Caller Thread + int event_thid; + + // IO Handler Thread + int input_thid; + + // Event Caller Thread Message Stack + int event_stack_lock; + ThreadMessage * event_stack; + + // IO Handler Thread Message Stack + int input_stack_lock; + ThreadMessage * input_stack; } SceNetAdhocMatchingContext; // End of psp definitions @@ -611,7 +606,7 @@ long long __milliseconds_now() { /* chages to the blocking mode of the socket 1 to set noblocking 0 to set blocking -*/ + */ void __change_blocking_mode(int fd, int nonblocking) { unsigned long on = 1; unsigned long off = 0; @@ -624,13 +619,13 @@ void __change_blocking_mode(int fd, int nonblocking) { ioctlsocket(fd, FIONBIO, &off); } #else - if(nonblocking) fcntl(fd, F_SETFL, O_NONBLOCK); - else { - // Get Flags - int flags = fcntl(fd, F_GETFL); - // Remove Non-Blocking Flag - fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); - } + if(nonblocking) fcntl(fd, F_SETFL, O_NONBLOCK); + else { + // Get Flags + int flags = fcntl(fd, F_GETFL); + // Remove Non-Blocking Flag + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + } #endif } @@ -662,6 +657,12 @@ int __init_network(SceNetAdhocctlAdhocId *adhoc_id){ return iResult; } + memset(¶meter,0,sizeof(parameter)); + strcpy((char *)¶meter.nickname.data, g_Config.sNickName.c_str()); + parameter.channel = 1; // Fake Channel 1 + __getLocalMac(¶meter.bssid.mac_addr); + + SceNetAdhocctlLoginPacketC2S packet; packet.base.opcode = OPCODE_LOGIN; SceNetEtherAddr addres; @@ -1220,17 +1221,17 @@ void __deleteAllPTP(void) { * @return Number of Virtual Networks */ int __countAvailableNetworks(void) { - // Network Count - int count = 0; - - // Group Reference - SceNetAdhocctlScanInfo * group = networks; - - // Count Groups - for(; group != NULL; group = group->next) count++; - - // Return Network Count - return count; + // Network Count + int count = 0; + + // Group Reference + SceNetAdhocctlScanInfo * group = networks; + + // Count Groups + for(; group != NULL; group = group->next) count++; + + // Return Network Count + return count; } /** @@ -1238,25 +1239,25 @@ int __countAvailableNetworks(void) { * @return Number of active Peers */ int __getActivePeerCount(void) { - // Counter - int count = 0; - - // #ifdef LOCALHOST_AS_PEER - // // Increase for Localhost - // count++; - // #endif - - // Peer Reference - SceNetAdhocctlPeerInfo * peer = friends; - - // Iterate Peers - for(; peer != NULL; peer = peer->next) { - // Increase Counter - count++; - } - - // Return Result - return count; + // Counter + int count = 0; + + // #ifdef LOCALHOST_AS_PEER + // // Increase for Localhost + // count++; + // #endif + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Increase Counter + count++; + } + + // Return Result + return count; } /** @@ -1265,14 +1266,14 @@ int __getActivePeerCount(void) { * @return Matching Context Pointer or... NULL */ SceNetAdhocMatchingContext * __findMatchingContext(int id) { - // Iterate Matching Context List - SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { - // Found Matching ID - if(item->id == id) return item; - } - - // Context not found - return NULL; + // Iterate Matching Context List + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // Found Matching ID + if(item->id == id) return item; + } + + // Context not found + return NULL; } /** @@ -1280,26 +1281,26 @@ SceNetAdhocMatchingContext * __findMatchingContext(int id) { * @return First unoccupied Matching ID */ int __findFreeMatchingID(void) { - // Minimum Matching ID - int min = 1; - - // Maximum Matching ID - int max = 0; - - // Find highest Matching ID - SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { - // New Maximum - if(max < item->id) max = item->id; - } - - // Find unoccupied ID - int i = min; for(; i < max; i++) { - // Found unoccupied ID - if(__findMatchingContext(i) == NULL) return i; - } - - // Append at virtual end - return max + 1; + // Minimum Matching ID + int min = 1; + + // Maximum Matching ID + int max = 0; + + // Find highest Matching ID + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // New Maximum + if(max < item->id) max = item->id; + } + + // Find unoccupied ID + int i = min; for(; i < max; i++) { + // Found unoccupied ID + if(__findMatchingContext(i) == NULL) return i; + } + + // Append at virtual end + return max + 1; } void __handlerUpdateCallback(u64 userdata, int cycleslate){ @@ -1347,13 +1348,22 @@ u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { // Seems to always return 0, and write 0 to the pointer.. // TODO: Eventually research what possible states there are int sceNetAdhocctlGetState(u32 ptrToStatus) { - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x)", ptrToStatus); - if (Memory::IsValidAddress(ptrToStatus)) - Memory::Write_U32(0, ptrToStatus); - else - ERROR_LOG(SCENET, "UNTESTED sceNetAdhocctlGetState(%x): Tried to write invalid location", ptrToStatus); - - return 0; + // Library initialized + if(netAdhocctlInited) { + // Valid Arguments + if(Memory::IsValidAddress(ptrToStatus)) { + // Return Thread Status + Memory::Write_U32(threadStatus,ptrToStatus); + // Return Success + return 0; + } + + // Invalid Arguments + return ERROR_NET_ADHOCCTL_INVALID_ARG; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } /** @@ -1450,20 +1460,28 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) return ERROR_NET_ADHOC_NOT_INITIALIZED; } -// TODO: Should we really write the struct if we're disconnected? +/** + * Get Adhoc Parameter + * @param parameter OUT: Adhoc Parameter + * @return 0 on success or... ADHOCCTL_NOT_INITIALIZED, ADHOCCTL_INVALID_ARG + */ int sceNetAdhocctlGetParameter(u32 paramAddr) { - WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlGetParameter(%x)", paramAddr); - struct SceNetAdhocctlParams params; - params.channel = 0; - for (int i = 0; i < 6; i++) - params.bssid[i] = i + 1; - strcpy(params.name, ""); - strcpy(params.nickname, ""); + // Library initialized + if(netAdhocctlInited) { + // Valid Arguments + if(Memory::IsValidAddress(paramAddr)) { + // Copy Parameter + Memory::WriteStruct(paramAddr,¶meter); + // Return Success + return 0; + } - if (Memory::IsValidAddress(paramAddr)) - Memory::WriteStruct(paramAddr, ¶ms); + // Invalid Arguments + return ERROR_NET_ADHOCCTL_INVALID_ARG; + } - return ERROR_NET_ADHOCCTL_DISCONNECTED; + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } /** @@ -1785,107 +1803,107 @@ int sceNetAdhocctlGetAdhocId(u32 productStructAddr) { int sceNetAdhocctlScan() { - // Library initialized - if(netAdhocctlInited) { - // Not connected - if(threadStatus == ADHOCCTL_STATE_DISCONNECTED) { + // Library initialized + if(netAdhocctlInited) { + // Not connected + if(threadStatus == ADHOCCTL_STATE_DISCONNECTED) { threadStatus = ADHOCCTL_STATE_SCANNING; - // Prepare Scan Request Packet - uint8_t opcode = OPCODE_SCAN; - - // Send Scan Request Packet - send(metasocket, (char *)&opcode, 1, 0); - - // Return Success - return 0; - } - - // Library is busy - return ERROR_NET_ADHOCCTL_BUSY; - } - - // Library uninitialized - return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; + // Prepare Scan Request Packet + uint8_t opcode = OPCODE_SCAN; + + // Send Scan Request Packet + send(metasocket, (char *)&opcode, 1, 0); + + // Return Success + return 0; + } + + // Library is busy + return ERROR_NET_ADHOCCTL_BUSY; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) { int * buflen = (int *)Memory::GetPointer(size); SceNetAdhocctlScanInfo * buf = NULL; if(Memory::IsValidAddress(bufAddr)){ - buf = (SceNetAdhocctlScanInfo *)Memory::GetPointer(bufAddr); + buf = (SceNetAdhocctlScanInfo *)Memory::GetPointer(bufAddr); } - // Library initialized - if(netAdhocctlInited) { - // Minimum Argument Requirements - if(buflen != NULL) { - // Multithreading Lock + // Library initialized + if(netAdhocctlInited) { + // Minimum Argument Requirements + if(buflen != NULL) { + // Multithreading Lock peerlock.lock(); - - // Length Returner Mode - if(buf == NULL) *buflen = __countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfo); - - // Normal Information Mode - else { - // Clear Memory - memset(buf, 0, *buflen); - - // Network Discovery Counter - int discovered = 0; - - // Count requested Networks - int requestcount = *buflen / sizeof(SceNetAdhocctlScanInfo); - - // Minimum Argument Requirements - if(requestcount > 0) { - // Group List Element - SceNetAdhocctlScanInfo * group = networks; - - // Iterate Group List - for(; group != NULL && discovered < requestcount; group = group->next) { - // Copy Group Information - buf[discovered] = *group; - - // Exchange Adhoc Channel - // sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_ADHOC_CHANNEL, &buf[discovered].channel); - - // Fake Channel Number 1 on Automatic Channel - // if(buf[discovered].channel == 0) buf[discovered].channel = 1; + + // Length Returner Mode + if(buf == NULL) *buflen = __countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfo); + + // Normal Information Mode + else { + // Clear Memory + memset(buf, 0, *buflen); + + // Network Discovery Counter + int discovered = 0; + + // Count requested Networks + int requestcount = *buflen / sizeof(SceNetAdhocctlScanInfo); + + // Minimum Argument Requirements + if(requestcount > 0) { + // Group List Element + SceNetAdhocctlScanInfo * group = networks; + + // Iterate Group List + for(; group != NULL && discovered < requestcount; group = group->next) { + // Copy Group Information + buf[discovered] = *group; + + // Exchange Adhoc Channel + // sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_ADHOC_CHANNEL, &buf[discovered].channel); + + // Fake Channel Number 1 on Automatic Channel + // if(buf[discovered].channel == 0) buf[discovered].channel = 1; //Always Fake Channel 1 buf[discovered].channel = 1; - - // Increase Discovery Counter - discovered++; - } - - // Link List - int i = 0; for(; i < discovered - 1; i++) { - // Link Network - buf[i].next = &buf[i + 1]; - } - - // Fix Last Element - if(discovered > 0) buf[discovered - 1].next = NULL; - } - - // Fix Size - *buflen = discovered * sizeof(SceNetAdhocctlScanInfo); - } - - // Multithreading Unlock + + // Increase Discovery Counter + discovered++; + } + + // Link List + int i = 0; for(; i < discovered - 1; i++) { + // Link Network + buf[i].next = &buf[i + 1]; + } + + // Fix Last Element + if(discovered > 0) buf[discovered - 1].next = NULL; + } + + // Fix Size + *buflen = discovered * sizeof(SceNetAdhocctlScanInfo); + } + + // Multithreading Unlock peerlock.unlock(); - - // Return Success - return 0; - } - - // Generic Error - return -1; - } - - // Library uninitialized - return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; + + // Return Success + return 0; + } + + // Generic Error + return -1; + } + + // Library uninitialized + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } // TODO: How many handlers can the PSP actually have for Adhocctl? @@ -2209,17 +2227,17 @@ int sceNetAdhocGetSocketAlert() { } int sceNetAdhocMatchingInit(u32 memsize) { - // Uninitialized Library - if(!netAdhocMatchingInited) { - // Save Fake Pool Size - fakePoolSize = memsize; - - // Initialize Library - netAdhocMatchingInited = true; - - // Return Success - return 0; - }else{ + // Uninitialized Library + if(!netAdhocMatchingInited) { + // Save Fake Pool Size + fakePoolSize = memsize; + + // Initialize Library + netAdhocMatchingInited = true; + + // Return Success + return 0; + }else{ return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED; } } @@ -2239,97 +2257,97 @@ int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int SceNetAdhocMatchingHandler handler; handler.entryPoint = callbackAddr; - // Library initialized - if(netAdhocMatchingInited) { - // Valid Member Limit - if(maxnum > 1 && maxnum <= 16) { - // Valid Receive Buffer size - if(rxbuflen >= 1024) { - // Valid Arguments - if(mode >= 1 && mode <= 3) { - // Iterate Matching Contexts - SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { - // Port Match found - if(item->port == port) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; - } - - // Allocate Context Memory - SceNetAdhocMatchingContext * context = (SceNetAdhocMatchingContext *)malloc(sizeof(SceNetAdhocMatchingContext)); - - // Allocated Memory - if(context != NULL) { - // Create PDP Socket - SceNetEtherAddr localmac; __getLocalMac(&localmac); + // Library initialized + if(netAdhocMatchingInited) { + // Valid Member Limit + if(maxnum > 1 && maxnum <= 16) { + // Valid Receive Buffer size + if(rxbuflen >= 1024) { + // Valid Arguments + if(mode >= 1 && mode <= 3) { + // Iterate Matching Contexts + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // Port Match found + if(item->port == port) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; + } + + // Allocate Context Memory + SceNetAdhocMatchingContext * context = (SceNetAdhocMatchingContext *)malloc(sizeof(SceNetAdhocMatchingContext)); + + // Allocated Memory + if(context != NULL) { + // Create PDP Socket + SceNetEtherAddr localmac; __getLocalMac(&localmac); const char * mac = (const char *)&localmac.data; - int socket = sceNetAdhocPdpCreate(mac, (uint32_t)port, rxbuflen, 0); - // Created PDP Socket - if(socket > 0) { - // Clear Memory - memset(context, 0, sizeof(SceNetAdhocMatchingContext)); - - // Allocate Receive Buffer - context->rxbuf = (uint8_t *)malloc(rxbuflen); - - // Allocated Memory - if(context->rxbuf != NULL) { - // Clear Memory - memset(context->rxbuf, 0, rxbuflen); - - // Fill in Context Data - context->id = __findFreeMatchingID(); - context->mode = mode; - context->maxpeers = maxnum; - context->port = port; - context->socket = socket; - context->rxbuflen = rxbuflen; - context->hello_int = hello_int; - context->keepalive_int = 500000; - //context->keepalive_int = keepalive_int; - context->resendcounter = init_count; - context->keepalivecounter = 100; - //context->keepalivecounter = init_count; - context->resend_int = rexmt_int; - context->handler = handler; - - // Fill in Selfpeer - context->mac = localmac; - - // Link Context - context->next = contexts; - contexts = context; - - // Return Matching ID - return context->id; - } - - // Close PDP Socket - sceNetAdhocPdpDelete(socket, 0); - } - - // Free Memory - free(context); - - // Port in use - if(socket < 1) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; - } - - // Out of Memory - return ERROR_NET_ADHOC_MATCHING_NO_SPACE; - } - - // InvalidERROR_NET_Arguments - return ERROR_NET_ADHOC_MATCHING_INVALID_ARG; - } - - // Invalid Receive Buffer Size - return ERROR_NET_ADHOC_MATCHING_RXBUF_TOO_SHORT; - } - - // Invalid Member Limit - return ERROR_NET_ADHOC_MATCHING_INVALID_MAXNUM; - } - // Uninitialized Library - return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED; + int socket = sceNetAdhocPdpCreate(mac, (uint32_t)port, rxbuflen, 0); + // Created PDP Socket + if(socket > 0) { + // Clear Memory + memset(context, 0, sizeof(SceNetAdhocMatchingContext)); + + // Allocate Receive Buffer + context->rxbuf = (uint8_t *)malloc(rxbuflen); + + // Allocated Memory + if(context->rxbuf != NULL) { + // Clear Memory + memset(context->rxbuf, 0, rxbuflen); + + // Fill in Context Data + context->id = __findFreeMatchingID(); + context->mode = mode; + context->maxpeers = maxnum; + context->port = port; + context->socket = socket; + context->rxbuflen = rxbuflen; + context->hello_int = hello_int; + context->keepalive_int = 500000; + //context->keepalive_int = keepalive_int; + context->resendcounter = init_count; + context->keepalivecounter = 100; + //context->keepalivecounter = init_count; + context->resend_int = rexmt_int; + context->handler = handler; + + // Fill in Selfpeer + context->mac = localmac; + + // Link Context + context->next = contexts; + contexts = context; + + // Return Matching ID + return context->id; + } + + // Close PDP Socket + sceNetAdhocPdpDelete(socket, 0); + } + + // Free Memory + free(context); + + // Port in use + if(socket < 1) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE; + } + + // Out of Memory + return ERROR_NET_ADHOC_MATCHING_NO_SPACE; + } + + // InvalidERROR_NET_Arguments + return ERROR_NET_ADHOC_MATCHING_INVALID_ARG; + } + + // Invalid Receive Buffer Size + return ERROR_NET_ADHOC_MATCHING_RXBUF_TOO_SHORT; + } + + // Invalid Member Limit + return ERROR_NET_ADHOC_MATCHING_INVALID_MAXNUM; + } + // Uninitialized Library + return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED; } int sceNetAdhocMatchingStart(int matchingId, int evthPri, int evthStack, int inthPri, int inthStack, int optLen, u32 optDataAddr) { @@ -2459,82 +2477,82 @@ int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { int * buflen = (int *)Memory::GetPointer(sizeAddr); SceNetAdhocctlPeerInfo * buf = NULL; if(Memory::IsValidAddress(bufAddr)){ - buf = (SceNetAdhocctlPeerInfo *)Memory::GetPointer(bufAddr); + buf = (SceNetAdhocctlPeerInfo *)Memory::GetPointer(bufAddr); } - // Initialized Library - if(netAdhocctlInited) { - // Minimum Arguments - if(buflen != NULL) { - // Multithreading Lock + // Initialized Library + if(netAdhocctlInited) { + // Minimum Arguments + if(buflen != NULL) { + // Multithreading Lock peerlock.lock(); - - // Length Calculation Mode - if(buf == NULL) *buflen = __getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfo); - - // Normal Mode - else { - // Discovery Counter - int discovered = 0; - - // Calculate Request Count - int requestcount = *buflen / sizeof(SceNetAdhocctlPeerInfo); - - // Clear Memory - memset(buf, 0, *buflen); - - // Minimum Arguments - if(requestcount > 0) { - #ifdef LOCALHOST_AS_PEER - // // Get Local IP Address - // union SceNetApctlInfo info; if(sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info) == 0) - // { - // // Add Local Address - // buf[discovered].nickname = _parameter.nickname; - // sceWlanGetEtherAddr((void *)buf[discovered].mac_addr.data); - // sceNetInetInetAton(info.ip, &buf[discovered].ip_addr); - // buf[discovered++].last_recv = sceKernelGetSystemTimeWide(); - // } - #endif - - // Peer Reference - SceNetAdhocctlPeerInfo * peer = friends; - - // Iterate Peers - for(; peer != NULL && discovered < requestcount; peer = peer->next) { - // Fake Receive Time - peer->last_recv = (uint64_t)time(NULL); - - // Copy Peer Info - buf[discovered++] = *peer; - } - - // Link List - int i = 0; for(; i < discovered - 1; i++) { - // Link Network - buf[i].next = &buf[i + 1]; - } - - // Fix Last Element - if(discovered > 0) buf[discovered - 1].next = NULL; - } - - // Fix Size - *buflen = discovered * sizeof(SceNetAdhocctlPeerInfo); - } - - // Multithreading Unlock + + // Length Calculation Mode + if(buf == NULL) *buflen = __getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfo); + + // Normal Mode + else { + // Discovery Counter + int discovered = 0; + + // Calculate Request Count + int requestcount = *buflen / sizeof(SceNetAdhocctlPeerInfo); + + // Clear Memory + memset(buf, 0, *buflen); + + // Minimum Arguments + if(requestcount > 0) { +#ifdef LOCALHOST_AS_PEER + // // Get Local IP Address + // union SceNetApctlInfo info; if(sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info) == 0) + // { + // // Add Local Address + // buf[discovered].nickname = _parameter.nickname; + // sceWlanGetEtherAddr((void *)buf[discovered].mac_addr.data); + // sceNetInetInetAton(info.ip, &buf[discovered].ip_addr); + // buf[discovered++].last_recv = sceKernelGetSystemTimeWide(); + // } +#endif + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL && discovered < requestcount; peer = peer->next) { + // Fake Receive Time + peer->last_recv = (uint64_t)time(NULL); + + // Copy Peer Info + buf[discovered++] = *peer; + } + + // Link List + int i = 0; for(; i < discovered - 1; i++) { + // Link Network + buf[i].next = &buf[i + 1]; + } + + // Fix Last Element + if(discovered > 0) buf[discovered - 1].next = NULL; + } + + // Fix Size + *buflen = discovered * sizeof(SceNetAdhocctlPeerInfo); + } + + // Multithreading Unlock peerlock.unlock(); - - // Return Success - return 0; - } - - // Invalid Arguments - return ERROR_NET_ADHOCCTL_INVALID_ARG; - } - - // Uninitialized Library - return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; + + // Return Success + return 0; + } + + // Invalid Arguments + return ERROR_NET_ADHOCCTL_INVALID_ARG; + } + + // Uninitialized Library + return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; } int sceNetAdhocctlGetAddrByName(const char *nickName, u32 sizeAddr, u32 bufAddr) { From ecb1411f0f5375ea0a60ce3800204e19970be9e2 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Tue, 29 Oct 2013 11:16:27 +0000 Subject: [PATCH 05/21] Fixes getPeerList, now it's using the correct pointer values in the struct --- Core/HLE/sceNetAdhoc.cpp | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 951d19bc91..62cd772dfc 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -206,7 +206,7 @@ typedef struct SceNetAdhocctlParameter { // Peer Information typedef struct SceNetAdhocctlPeerInfo { - struct SceNetAdhocctlPeerInfo * next; + SceNetAdhocctlPeerInfo * next; SceNetAdhocctlNickname nickname; SceNetEtherAddr mac_addr; uint32_t ip_addr; @@ -2473,11 +2473,21 @@ int sceNetAdhocctlGetGameModeInfo(u32 infoAddr) { return -1; } +// Peer Information with u32 pointers +typedef struct SceNetAdhocctlPeerInfoEmu { + u32 next; // Changed the pointer to u32 + SceNetAdhocctlNickname nickname; + SceNetEtherAddr mac_addr; + uint32_t ip_addr; + u32 padding; // Changed the pointer to u32 + uint64_t last_recv; +} __attribute__((packed)) SceNetAdhocctlPeerInfoEmu; + int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { int * buflen = (int *)Memory::GetPointer(sizeAddr); - SceNetAdhocctlPeerInfo * buf = NULL; + SceNetAdhocctlPeerInfoEmu * buf = NULL; if(Memory::IsValidAddress(bufAddr)){ - buf = (SceNetAdhocctlPeerInfo *)Memory::GetPointer(bufAddr); + buf = (SceNetAdhocctlPeerInfoEmu *)Memory::GetPointer(bufAddr); } // Initialized Library if(netAdhocctlInited) { @@ -2487,7 +2497,7 @@ int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { peerlock.lock(); // Length Calculation Mode - if(buf == NULL) *buflen = __getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfo); + if(buf == NULL) *buflen = __getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfoEmu); // Normal Mode else { @@ -2495,25 +2505,13 @@ int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { int discovered = 0; // Calculate Request Count - int requestcount = *buflen / sizeof(SceNetAdhocctlPeerInfo); + int requestcount = *buflen / sizeof(SceNetAdhocctlPeerInfoEmu); // Clear Memory memset(buf, 0, *buflen); // Minimum Arguments if(requestcount > 0) { -#ifdef LOCALHOST_AS_PEER - // // Get Local IP Address - // union SceNetApctlInfo info; if(sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info) == 0) - // { - // // Add Local Address - // buf[discovered].nickname = _parameter.nickname; - // sceWlanGetEtherAddr((void *)buf[discovered].mac_addr.data); - // sceNetInetInetAton(info.ip, &buf[discovered].ip_addr); - // buf[discovered++].last_recv = sceKernelGetSystemTimeWide(); - // } -#endif - // Peer Reference SceNetAdhocctlPeerInfo * peer = friends; @@ -2523,17 +2521,22 @@ int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { peer->last_recv = (uint64_t)time(NULL); // Copy Peer Info - buf[discovered++] = *peer; + buf[discovered].nickname = peer->nickname; + buf[discovered].mac_addr = peer->mac_addr; + buf[discovered].ip_addr = peer->ip_addr; + buf[discovered].last_recv = peer->last_recv; + discovered++; + } // Link List int i = 0; for(; i < discovered - 1; i++) { // Link Network - buf[i].next = &buf[i + 1]; + buf[i].next = bufAddr+(sizeof(SceNetAdhocctlPeerInfoEmu)*i)+ + sizeof(SceNetAdhocctlPeerInfoEmu); } - // Fix Last Element - if(discovered > 0) buf[discovered - 1].next = NULL; + if(discovered > 0) buf[discovered - 1].next = 0; } // Fix Size From cce8ad050d5275ff89f5bc47db808628aad30637 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Tue, 29 Oct 2013 15:38:09 +0000 Subject: [PATCH 06/21] Adds compability for packed structs on windows, and removes some redundant typedefs --- Core/HLE/sceNetAdhoc.cpp | 127 ++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 63 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 62cd772dfc..1b05bf3102 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -18,16 +18,8 @@ // sceNetAdhoc -// These acronyms are seen in function names: -// * PDP: a proprietary Sony protocol similar to UDP. -// * PTP: a proprietary Sony protocol similar to TCP. - -// We will need to wrap them into the similar UDP and TCP messages. If we want to -// play adhoc remotely online, I guess we'll need to wrap both into TCP/IP. - -// We will need some server infrastructure to provide match making. We'll -// group players per game. Maybe allow players to join rooms and then start the game, -// instead of the other way around? +// This is a direct port of colorbird code from http://code.google.com/p/aemu/ +// All credit goes to him! #include "../Config.h" #include "Core/HLE/HLE.h" @@ -42,7 +34,7 @@ // Temporary stuff #include -#ifdef _WIN32 +#ifdef _MSC_VER #include #else #include @@ -51,13 +43,19 @@ #include #include #include +#endif +#include +// End of extra includes + +#ifdef _MSC_VER +#define PACK +#else #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #define Sleep sleep #define closesocket close +#define PACK __attribute__((packed)) #endif -#include -// End of extra includes enum { ERROR_NET_ADHOC_INVALID_SOCKET_ID = 0x80410701, @@ -154,32 +152,27 @@ static bool netAdhocMatchingInited; #define UTILITY_NETCONF_STATUS_FINISHED 3 #define UTILITY_NETCONF_STATUS_SHUTDOWN 4 - +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif // Ethernet Address #define ETHER_ADDR_LEN 6 typedef struct SceNetEtherAddr { uint8_t data[ETHER_ADDR_LEN]; -} __attribute__((packed)) SceNetEtherAddr; +} PACK SceNetEtherAddr; -// Adhoc ID (Game Product Key) -#define ADHOCCTL_ADHOCID_LEN 9 -typedef struct SceNetAdhocctlAdhocId { - int type; - uint8_t data[ADHOCCTL_ADHOCID_LEN]; - uint8_t padding[3]; -} SceNetAdhocctlAdhocId; // Adhoc Virtual Network Name #define ADHOCCTL_GROUPNAME_LEN 8 typedef struct SceNetAdhocctlGroupName { uint8_t data[ADHOCCTL_GROUPNAME_LEN]; -} __attribute__((packed)) SceNetAdhocctlGroupName; +} PACK SceNetAdhocctlGroupName; // Virtual Network Host Information typedef struct SceNetAdhocctlBSSId { SceNetEtherAddr mac_addr; uint8_t padding[2]; -} __attribute__((packed)) SceNetAdhocctlBSSId; +} PACK SceNetAdhocctlBSSId; // Virtual Network Information typedef struct SceNetAdhocctlScanInfo { @@ -188,13 +181,13 @@ typedef struct SceNetAdhocctlScanInfo { SceNetAdhocctlGroupName group_name; SceNetAdhocctlBSSId bssid; int mode; -} __attribute__((packed)) SceNetAdhocctlScanInfo; +} PACK SceNetAdhocctlScanInfo; // Player Nickname #define ADHOCCTL_NICKNAME_LEN 128 typedef struct SceNetAdhocctlNickname { uint8_t data[ADHOCCTL_NICKNAME_LEN]; -} __attribute__((packed)) SceNetAdhocctlNickname; +} PACK SceNetAdhocctlNickname; // Active Virtual Network Information typedef struct SceNetAdhocctlParameter { @@ -202,7 +195,7 @@ typedef struct SceNetAdhocctlParameter { SceNetAdhocctlGroupName group_name; SceNetAdhocctlBSSId bssid; SceNetAdhocctlNickname nickname; -} __attribute__((packed)) SceNetAdhocctlParameter; +} PACK SceNetAdhocctlParameter; // Peer Information typedef struct SceNetAdhocctlPeerInfo { @@ -212,25 +205,35 @@ typedef struct SceNetAdhocctlPeerInfo { uint32_t ip_addr; uint8_t padding[2]; uint64_t last_recv; -} __attribute__((packed)) SceNetAdhocctlPeerInfo; +} PACK SceNetAdhocctlPeerInfo; // Game Mode Peer List #define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16 typedef struct SceNetAdhocctlGameModeInfo { int num; SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS]; -} __attribute__((packed)) SceNetAdhocctlGameModeInfo; -// Ethernet Address (MAC) +} PACK SceNetAdhocctlGameModeInfo; +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +// Adhoc ID (Game Product Key) +#define ADHOCCTL_ADHOCID_LEN 9 +typedef struct SceNetAdhocctlAdhocId { + int type; + uint8_t data[ADHOCCTL_ADHOCID_LEN]; + uint8_t padding[3]; +} SceNetAdhocctlAdhocId; // Socket Polling Event Listener -typedef struct SceNetAdhocPollSd { +struct SceNetAdhocPollSd { int id; int events; int revents; }; // PDP Socket Status -typedef struct SceNetAdhocPdpStat { +struct SceNetAdhocPdpStat { struct SceNetAdhocPdpStat * next; int id; SceNetEtherAddr laddr; @@ -239,7 +242,7 @@ typedef struct SceNetAdhocPdpStat { }; // PTP Socket Status -typedef struct SceNetAdhocPtpStat { +struct SceNetAdhocPtpStat { struct SceNetAdhocPtpStat * next; int id; SceNetEtherAddr laddr; @@ -252,14 +255,14 @@ typedef struct SceNetAdhocPtpStat { }; // Gamemode Optional Peer Buffer Data -typedef struct SceNetAdhocGameModeOptData { +struct SceNetAdhocGameModeOptData { uint32_t size; uint32_t flag; uint64_t last_recv; }; // Gamemode Buffer Status -typedef struct SceNetAdhocGameModeBufferStat { +struct SceNetAdhocGameModeBufferStat { struct SceNetAdhocGameModeBufferStat * next; int id; void * ptr; @@ -268,12 +271,6 @@ typedef struct SceNetAdhocGameModeBufferStat { SceNetAdhocGameModeOptData opt; }; -// Matching Peer Information -typedef struct SceNetAdhocMatchingMember { - struct SceNetAdhocMatchingMember * next; - SceNetEtherAddr addr; - uint8_t padding[2]; -} __attribute__((packed)) SceNetAdhocMatchingMember; // Internal Matching Peer Information typedef struct SceNetAdhocMatchingMemberInternal { @@ -412,17 +409,22 @@ typedef struct SceNetAdhocMatchingContext { // PSP Product Code #define PRODUCT_CODE_LENGTH 9 + +#ifdef _MSC_VER +#pragma pack(push,1) +#endif + typedef struct { // Game Product Code (ex. ULUS12345) char data[PRODUCT_CODE_LENGTH]; -} __attribute__((packed)) SceNetAdhocctlProductCode; +} PACK SceNetAdhocctlProductCode; // Basic Packet typedef struct { uint8_t opcode; -} __attribute__((packed)) SceNetAdhocctlPacketBase; +} PACK SceNetAdhocctlPacketBase; // C2S Login Packet typedef struct @@ -431,21 +433,21 @@ typedef struct SceNetEtherAddr mac; SceNetAdhocctlNickname name; SceNetAdhocctlProductCode game; -} __attribute__((packed)) SceNetAdhocctlLoginPacketC2S; +} PACK SceNetAdhocctlLoginPacketC2S; // C2S Connect Packet typedef struct { SceNetAdhocctlPacketBase base; SceNetAdhocctlGroupName group; -} __attribute__((packed)) SceNetAdhocctlConnectPacketC2S; +} PACK SceNetAdhocctlConnectPacketC2S; // C2S Chat Packet typedef struct { SceNetAdhocctlPacketBase base; char message[64]; -} __attribute__((packed)) SceNetAdhocctlChatPacketC2S; +} PACK SceNetAdhocctlChatPacketC2S; // S2C Connect Packet typedef struct @@ -454,14 +456,14 @@ typedef struct SceNetAdhocctlNickname name; SceNetEtherAddr mac; uint32_t ip; -} __attribute__((packed)) SceNetAdhocctlConnectPacketS2C; +} PACK SceNetAdhocctlConnectPacketS2C; // S2C Disconnect Packet typedef struct { SceNetAdhocctlPacketBase base; uint32_t ip; -} __attribute__((packed)) SceNetAdhocctlDisconnectPacketS2C; +} PACK SceNetAdhocctlDisconnectPacketS2C; // S2C Scan Packet typedef struct @@ -469,21 +471,24 @@ typedef struct SceNetAdhocctlPacketBase base; SceNetAdhocctlGroupName group; SceNetEtherAddr mac; -} __attribute__((packed)) SceNetAdhocctlScanPacketS2C; +} PACK SceNetAdhocctlScanPacketS2C; // S2C Connect BSSID Packet typedef struct { SceNetAdhocctlPacketBase base; SceNetEtherAddr mac; -} __attribute__((packed)) SceNetAdhocctlConnectBSSIDPacketS2C; +} PACK SceNetAdhocctlConnectBSSIDPacketS2C; // S2C Chat Packet typedef struct { SceNetAdhocctlChatPacketC2S base; SceNetAdhocctlNickname name; -} __attribute__((packed)) SceNetAdhocctlChatPacketS2C; +} PACK SceNetAdhocctlChatPacketS2C; +#ifdef _MSC_VER +#pragma pack(pop) +#endif // Aux vars static int metasocket; @@ -562,7 +567,7 @@ void __getLocalMac(SceNetEtherAddr * addr){ // This only usefull if the server is running on the same machine as the client int __getLocalIp(sockaddr_in * SocketAddress){ -#ifdef _WIN32 +#ifdef _MSC_VER // Get local host name char szHostName[128] = ""; @@ -586,7 +591,7 @@ int __getLocalIp(sockaddr_in * SocketAddress){ // Returns current system time in miliseconds, windows only! long long __milliseconds_now() { -#ifdef _WIN32 +#ifdef _MSC_VER static LARGE_INTEGER s_frequency; static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency); if (s_use_qpc) { @@ -606,11 +611,11 @@ long long __milliseconds_now() { /* chages to the blocking mode of the socket 1 to set noblocking 0 to set blocking - */ +*/ void __change_blocking_mode(int fd, int nonblocking) { unsigned long on = 1; unsigned long off = 0; -#ifdef _WIN32 +#ifdef _MSC_VER if(nonblocking){ // Change to Non-Blocking Mode ioctlsocket(fd,FIONBIO,&on); @@ -632,7 +637,7 @@ void __change_blocking_mode(int fd, int nonblocking) { // Inits all basic net functionality and logins the user to the main server int __init_network(SceNetAdhocctlAdhocId *adhoc_id){ int iResult = 0; -#ifdef _WIN32 +#ifdef _MSC_VER WSADATA data; iResult = WSAStartup(MAKEWORD(2,2),&data); if(iResult != NOERROR){ @@ -859,7 +864,7 @@ int __friendFinder(){ SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx; // Fix for Idiots that try to troll the "ME" Nametag -#ifdef _WIN32 +#ifdef _MSC_VER if(stricmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); #else if(strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); @@ -996,11 +1001,7 @@ int __friendFinder(){ } // Delay Thread (10ms) -#ifdef _WIN32 - Sleep(10); -#else sleep(10); -#endif } // Log Shutdown @@ -2015,7 +2016,7 @@ int sceNetAdhocctlTerm() { closesocket(metasocket); metasocket = -1; -#ifdef _WIN32 +#ifdef _MSC_VER WSACleanup(); // WINDOWS ONLY! #endif } @@ -2481,7 +2482,7 @@ typedef struct SceNetAdhocctlPeerInfoEmu { uint32_t ip_addr; u32 padding; // Changed the pointer to u32 uint64_t last_recv; -} __attribute__((packed)) SceNetAdhocctlPeerInfoEmu; +} SceNetAdhocctlPeerInfoEmu; int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { int * buflen = (int *)Memory::GetPointer(sizeAddr); From 28ab767c8844156cd476f3404f9c56c725081ff1 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Tue, 29 Oct 2013 21:06:26 +0000 Subject: [PATCH 07/21] Adds common sleep function, and implements ptp functions --- Core/HLE/sceNetAdhoc.cpp | 902 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 853 insertions(+), 49 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 1b05bf3102..d5cdc93d5c 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -39,10 +39,11 @@ #else #include #include -#include +#include #include #include #include +#include #endif #include // End of extra includes @@ -52,7 +53,6 @@ #else #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 -#define Sleep sleep #define closesocket close #define PACK __attribute__((packed)) #endif @@ -75,9 +75,12 @@ enum { ERROR_NET_ADHOC_WOULD_BLOCK = 0x80410709, ERROR_NET_ADHOC_INVALID_DATALEN = 0x80410705, ERROR_NET_ADHOC_INVALID_PORT = 0x80410703, - + ERROR_NET_ADHOC_NOT_LISTENED = 0x8040070E, + ERROR_NET_ADHOC_NOT_OPENED = 0x8040070D, + ERROR_NET_ADHOC_SOCKET_ID_NOT_AVAIL = 0x8041070F, + ERROR_NET_ADHOC_NOT_CONNECTED = 0x8041070B, + ERROR_NET_ADHOCCTL_INVALID_ARG = 0x80410B04, - ERROR_NET_ADHOCCTL_WLAN_SWITCH_OFF = 0x80410b03, ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED = 0x80410b07, ERROR_NET_ADHOCCTL_NOT_INITIALIZED = 0x80410b08, @@ -152,6 +155,11 @@ static bool netAdhocMatchingInited; #define UTILITY_NETCONF_STATUS_FINISHED 3 #define UTILITY_NETCONF_STATUS_SHUTDOWN 4 +// PTP Connection States +#define PTP_STATE_CLOSED 0 +#define PTP_STATE_LISTEN 1 +#define PTP_STATE_ESTABLISHED 4 + #ifdef _MSC_VER #pragma pack(push, 1) #endif @@ -243,7 +251,7 @@ struct SceNetAdhocPdpStat { // PTP Socket Status struct SceNetAdhocPtpStat { - struct SceNetAdhocPtpStat * next; + u32 next; // Changed the pointer to u32 int id; SceNetEtherAddr laddr; SceNetEtherAddr paddr; @@ -503,6 +511,7 @@ static SceNetAdhocPdpStat * pdp[255]; static SceNetAdhocPtpStat * ptp[255]; static uint32_t fakePoolSize = 0; static SceNetAdhocMatchingContext * contexts = NULL; +static int one = 1; // End of Aux vars struct AdhocctlHandler { @@ -555,6 +564,16 @@ void split64(u64 num, int buff[]){ buff[1] = num2; } +void __msleep(int mseconds){ +#ifdef _MSVER + Sleep(mseconds); +#else + timespec t_spec; + t_spec.tv_sec = 0; + t_spec.tv_nsec = 100000*mseconds; + nanosleep(&t_spec, NULL); +#endif +} u64 join32(u32 num1, u32 num2){ return (u64)num2 << 32 | num1; } @@ -624,7 +643,7 @@ void __change_blocking_mode(int fd, int nonblocking) { ioctlsocket(fd, FIONBIO, &off); } #else - if(nonblocking) fcntl(fd, F_SETFL, O_NONBLOCK); + if(nonblocking == 1) fcntl(fd, F_SETFL, O_NONBLOCK); else { // Get Flags int flags = fcntl(fd, F_GETFL); @@ -800,6 +819,7 @@ int __friendFinder(){ // Ping Server if(__milliseconds_now() - lastping >= 100) { + printf("sent ping\n"); // Update Ping Time lastping = __milliseconds_now(); @@ -999,9 +1019,7 @@ int __friendFinder(){ rxpos -= 1; } } - - // Delay Thread (10ms) - sleep(10); + __msleep(1000); } // Log Shutdown @@ -1304,6 +1322,37 @@ int __findFreeMatchingID(void) { return max + 1; } + +/** + * PTP Socket Counter + * @return Number of internal PTP Sockets + */ +int __getPTPSocketCount(void) { + // Socket Counter + int counter = 0; + + // Count Sockets + int i = 0; for(; i < 255; i++) if(ptp[i] != NULL) counter++; + + // Return Socket Count + return counter; +} + + +/** + * Check whether PTP Port is in use or not + * @param port To-be-checked Port Number + * @return 1 if in use or... 0 + */ +int __IsPTPPortInUse(uint16_t port) { + // Iterate Sockets + int i = 0; for(; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return 1; + + // Unused Port + return 0; +} + + void __handlerUpdateCallback(u64 userdata, int cycleslate){ int buff[2]; split64(userdata,buff); @@ -1312,7 +1361,7 @@ void __handlerUpdateCallback(u64 userdata, int cycleslate){ u32 sceNetAdhocInit() { // Library uninitialized - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocInit()"); + INFO_LOG(SCENET, "sceNetAdhocInit()"); if(!netAdhocInited) { // Clear Translator Memory memset(&pdp, 0, sizeof(pdp)); @@ -1329,7 +1378,7 @@ u32 sceNetAdhocInit() { } u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlInit(%i, %i, %08x)", stackSize, prio, productAddr); + INFO_LOG(SCENET, "sceNetAdhocctlInit(%i, %i, %08x)", stackSize, prio, productAddr); if (netAdhocctlInited) { return ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED; }else{ @@ -1344,10 +1393,6 @@ u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { return 0; } - - -// Seems to always return 0, and write 0 to the pointer.. -// TODO: Eventually research what possible states there are int sceNetAdhocctlGetState(u32 ptrToStatus) { // Library initialized if(netAdhocctlInited) { @@ -1376,7 +1421,7 @@ int sceNetAdhocctlGetState(u32 ptrToStatus) { * @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 */ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpCreate(%s, %x, %x, %x)", mac, port, bufferSize, unknown); + INFO_LOG(SCENET, "sceNetAdhocPdpCreate(%s, %d, %d, %d)", mac, port, bufferSize, unknown); // Library is initialized SceNetEtherAddr * saddr = (SceNetEtherAddr *)mac; if(netAdhocInited) { @@ -1402,7 +1447,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); //This not safe in any way... + addr.sin_port = htons(port); // This not safe in any way... // Bound Socket to local Port if(bind(usocket, (sockaddr *)&addr, sizeof(addr)) == 0) { @@ -1467,6 +1512,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) * @return 0 on success or... ADHOCCTL_NOT_INITIALIZED, ADHOCCTL_INVALID_ARG */ int sceNetAdhocctlGetParameter(u32 paramAddr) { + INFO_LOG(SCENET, "sceNetAdhocctlGetParameter(%u)",paramAddr); // Library initialized if(netAdhocctlInited) { // Valid Arguments @@ -1759,7 +1805,7 @@ 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) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPdpDelete(%d, %d)", id, unknown); + INFO_LOG(SCENET, "sceNetAdhocPdpDelete(%d, %d)", id, unknown); // Library is initialized if(netAdhocInited) { // Valid Arguments @@ -2008,7 +2054,7 @@ u32 sceNetAdhocctlDelHandler(u32 handlerID) { } int sceNetAdhocctlTerm() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlTerm()"); + INFO_LOG(SCENET, "sceNetAdhocctlTerm()"); if(netAdhocInited){ netAdhocctlInited = false; friendFinderThread.join(); @@ -2045,7 +2091,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) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlCreate(%s)", groupName); + INFO_LOG(SCENET, "sceNetAdhocctlCreate(%s)", groupName); const SceNetAdhocctlGroupName * groupNameStruct = (const SceNetAdhocctlGroupName *)groupName; // Library initialized if(netAdhocctlInited) { @@ -2098,7 +2144,7 @@ int sceNetAdhocctlCreate(const char *groupName) { int sceNetAdhocctlConnect(u32 ptrToGroupName) { if (Memory::IsValidAddress(ptrToGroupName)) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocctlConnect(groupName=%s)", Memory::GetCharPointer(ptrToGroupName)); + INFO_LOG(SCENET, "sceNetAdhocctlConnect(groupName=%s)", Memory::GetCharPointer(ptrToGroupName)); return sceNetAdhocctlCreate(Memory::GetCharPointer(ptrToGroupName)); } else { return ERROR_NET_ADHOC_INVALID_ADDR; @@ -2116,7 +2162,7 @@ int sceNetAdhocctlJoinEnterGameMode(const char *groupName, const char *macAddr, } int sceNetAdhocTerm() { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocTerm()"); + INFO_LOG(SCENET, "sceNetAdhocTerm()"); // Library is initialized if(netAdhocInited) { // Delete PDP Sockets @@ -2147,49 +2193,807 @@ int sceNetAdhocGetPdpStat(int structSize, u32 structAddr) { return 0; } -int sceNetAdhocGetPtpStat(int structSize, u32 structAddr) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocGetPtpStat(%i, %08x)", structSize, structAddr); + +/** + * Adhoc Emulator PTP Socket List Getter + * @param buflen IN: Length of Buffer in Bytes OUT: Required Length of Buffer in Bytes + * @param buf PTP Socket List Buffer (can be NULL if you wish to receive Required Length) + * @return 0 on success or... ADHOC_INVALID_ARG, ADHOC_NOT_INITIALIZED + */ +int sceNetAdhocGetPtpStat(u32 structSize, u32 structAddr) { + // INFO_LOG(SCENET,"sceNetAdhocGetPtpStat(%u,%u)",structSize,structAddr); + // Spams a lot + int * buflen = (int *)Memory::GetPointer(structSize); + // Library is initialized + if(netAdhocInited) { + // Length Returner Mode + if(buflen != NULL && !Memory::IsValidAddress(structAddr)) { + // Return Required Size + *buflen = sizeof(SceNetAdhocPtpStat) * __getPTPSocketCount(); + + // Success + return 0; + } + + // Status Returner Mode + else if(buflen != NULL && Memory::IsValidAddress(structAddr)) { + // Socket Count + int socketcount = __getPTPSocketCount(); + SceNetAdhocPtpStat * buf = (SceNetAdhocPtpStat *)Memory::GetPointer(structAddr); + + // Figure out how many Sockets we will return + int count = *buflen / sizeof(SceNetAdhocPtpStat); + if(count > socketcount) count = socketcount; + + // Copy Counter + int i = 0; + + // Iterate Sockets + int j = 0; for(; j < 255 && i < count; j++) { + // Active Socket + if(ptp[j] != NULL) { + // Copy Socket Data from internal Memory + buf[i] = *ptp[j]; + + // Fix Client View Socket ID + buf[i].id = j + 1; + + // Write End of List Reference + buf[i].next = 0; + + // Link previous Element to this one + if(i > 0) buf[i-1].next = structAddr+(i*sizeof(SceNetAdhocPtpStat))+ + sizeof(SceNetAdhocPtpStat); + + // Increment Counter + i++; + } + } + + // Update Buffer Length + *buflen = i * sizeof(SceNetAdhocPtpStat); + + // Success + return 0; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; +} + + +/** + * Adhoc Emulator PTP Active Socket Creator + * @param saddr Local MAC (Unused) + * @param sport Local Binding Port + * @param daddr Target MAC + * @param dport Target Port + * @param bufsize Socket Buffer Size + * @param rexmt_int Retransmit Interval (in Microseconds) + * @param rexmt_cnt Retransmit Count + * @param flag Bitflags (Unused) + * @return Socket ID > 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_ADDR, ADHOC_INVALID_PORT + */ +int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, int dport, int bufsize, int rexmt_int, int rexmt_cnt, int unknown) { + INFO_LOG(SCENET, "sceNetAdhocPtpOpen(%s,%d,%s,%d,%d,%d,%d,%d)", srcmac, sport, + dstmac,dport,bufsize, rexmt_int, rexmt_cnt, unknown); + SceNetEtherAddr * saddr = (SceNetEtherAddr *)srcmac; + SceNetEtherAddr * daddr = (SceNetEtherAddr *)dstmac; + // Library is initialized + if(netAdhocInited) { + // Valid Addresses + if(saddr != NULL && _IsLocalMAC(saddr) && daddr != NULL && !__isBroadcastMAC(daddr)) { + // Random Port required + if(sport == 0) { + // Find unused Port + // while(sport == 0 || _IsPTPPortInUse(sport)) { + // // Generate Port Number + // sport = (uint16_t)_getRandomNumber(65535); + // } + } + + // Valid Ports + if(!__IsPTPPortInUse(sport) && dport != 0) { + // Valid Arguments + if(bufsize > 0 && rexmt_int > 0 && rexmt_cnt > 0) { + // Create Infrastructure Socket + int tcpsocket = INVALID_SOCKET; + tcpsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + // Valid Socket produced + if(tcpsocket > 0) { + // Enable Port Re-use + setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + // Binding Information for local Port + sockaddr_in addr; + // addr.sin_len = sizeof(addr); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(sport); + + // Bound Socket to local Port + if(bind(tcpsocket, (sockaddr *)&addr, sizeof(addr)) == 0) { + // Allocate Memory + SceNetAdhocPtpStat * internal = (SceNetAdhocPtpStat *)malloc(sizeof(SceNetAdhocPtpStat)); + + // Allocated Memory + if(internal != NULL) { + // Find Free Translator ID + int i = 0; for(; i < 255; i++) if(ptp[i] == NULL) break; + + // Found Free Translator ID + if(i < 255) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPtpStat)); + + // Copy Infrastructure Socket ID + internal->id = tcpsocket; + + // Copy Address Information + internal->laddr = *saddr; + internal->paddr = *daddr; + internal->lport = sport; + internal->pport = dport; + + // Set Buffer Size + internal->rcv_sb_cc = bufsize; + + // Link PTP Socket + ptp[i] = internal; + + // Add Port Forward to Router + // sceNetPortOpen("TCP", sport); + + // Return PTP Socket Pointer + return i + 1; + } + + // Free Memory + free(internal); + } + } + + // Close Socket + closesocket(tcpsocket); + } + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Ports + return ERROR_NET_ADHOC_INVALID_PORT; + } + + // Invalid Addresses + return ERROR_NET_ADHOC_INVALID_ADDR; + } + return 0; } -int sceNetAdhocPtpOpen(const char *srcmac, int srcport, const char *dstmac, int dstport, int bufsize, int retryDelay, int retryCount, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpOpen(%s : %i, %s : %i, %i, %i, %i, %08x)", srcmac, srcport, dstmac, dstport, bufsize, retryDelay, retryCount, unknown); - return 0; + +/** + * Adhoc Emulator PTP Connection Acceptor + * @param id Socket File Descriptor + * @param addr OUT: Peer MAC Address + * @param port OUT: Peer Port + * @param timeout Accept Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return Socket ID >= 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_SOCKET_ID_NOT_AVAIL, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_LISTENED, ADHOC_THREAD_ABORTED, NET_INTERNAL + */ +int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeout, int flag) { + SceNetEtherAddr * addr = NULL; + if(Memory::IsValidAddress(peerMacAddrPtr)){ + addr = Memory::GetStruct(peerMacAddrPtr); + } + uint16_t * port = NULL; + if(Memory::IsValidAddress(peerPortPtr)){ + port = (uint16_t *)Memory::GetPointer(peerPortPtr); + } + INFO_LOG(SCENET, "sceNetAdhocPtpAccept(%d,%s,%d,%u,%d)",id, addr->data,*port,timeout, + flag); + // Library is initialized + if(netAdhocInited) { + // Valid Socket + if(id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Listener Socket + if(socket->state == PTP_STATE_LISTEN) { + // Valid Arguments + if(addr != NULL && port != NULL) { + // Address Information + sockaddr_in peeraddr; + memset(&peeraddr, 0, sizeof(peeraddr)); + uint32_t peeraddrlen = sizeof(peeraddr); + + // Local Address Information + sockaddr_in local; + memset(&local, 0, sizeof(local)); + uint32_t locallen = sizeof(local); + + // Grab Nonblocking Flag + uint32_t nbio = 0; + int sockflag = fcntl(socket->id, F_GETFL, O_NONBLOCK); + nbio = sockflag & O_NONBLOCK; + // Switch to Nonblocking Behaviour + if(nbio == 0) { + // Overwrite Socket Option + __change_blocking_mode(socket->id,1); + } + + // Accept Connection + int newsocket = accept(socket->id, (sockaddr *)&peeraddr, &peeraddrlen); + + // Blocking Behaviour + if(!flag && newsocket == -1) { + // Get Start Time + uint32_t starttime = __milliseconds_now(); + + // Retry until Timeout hits + while((timeout == 0 || (__milliseconds_now() - starttime) < timeout) && newsocket == -1) { + // Accept Connection + newsocket = accept(socket->id, (sockaddr *)&peeraddr, &peeraddrlen); + + // Wait a bit... + __msleep(1); + } + } + + // Restore Blocking Behaviour + if(nbio == 0) { + // Restore Socket Option + __change_blocking_mode(socket->id,0); + } + + // Accepted New Connection + if(newsocket > 0) { + // Enable Port Re-use + setsockopt(newsocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + // Grab Local Address + if(getsockname(newsocket, (sockaddr *)&local, &locallen) == 0) { + // Peer MAC + SceNetEtherAddr mac; + + // Find Peer MAC + if(__resolveIP(peeraddr.sin_addr.s_addr, &mac) == 0) { + // Allocate Memory + SceNetAdhocPtpStat * internal = (SceNetAdhocPtpStat *)malloc(sizeof(SceNetAdhocPtpStat)); + + // Allocated Memory + if(internal != NULL) { + // Find Free Translator ID + int i = 0; for(; i < 255; i++) if(ptp[i] == NULL) break; + + // Found Free Translator ID + if(i < 255) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPtpStat)); + + // Copy Socket Descriptor to Structure + internal->id = newsocket; + + // Copy Local Address Data to Structure + __getLocalMac(&internal->laddr); + internal->lport = htons(local.sin_port); + + // Copy Peer Address Data to Structure + internal->paddr = mac; + internal->pport = htons(peeraddr.sin_port); + + // Set Connected State + internal->state = PTP_STATE_ESTABLISHED; + + // Return Peer Address Information + *addr = internal->paddr; + *port = internal->pport; + + // Link PTP Socket + ptp[i] = internal; + + // Add Port Forward to Router + // sceNetPortOpen("TCP", internal->lport); + + // Return Socket + return i + 1; + } + + // Free Memory + free(internal); + } + } + } + + // Close Socket + closesocket(newsocket); + } + + // Action would block + if(flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Client Socket + return ERROR_NET_ADHOC_NOT_LISTENED; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpAccept(%i, %08x, %08x, %i, %i)", id, peerMacAddrPtr, peerPortPtr, timeout, nonblock); - return 0; + +/** + * Adhoc Emulator PTP Connection Opener + * @param id Socket File Descriptor + * @param timeout Connect Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_CONNECTION_REFUSED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_OPENED, ADHOC_THREAD_ABORTED, NET_INTERNAL + */ +int sceNetAdhocPtpConnect(int id, int timeout, int flag) { + // Library is initialized + if(netAdhocInited) + { + // Valid Socket + if(id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Valid Client Socket + if(socket->state == 0) { + // Target Address + sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + + // Setup Target Address + // sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(socket->pport); + + // Grab Peer IP + if(__resolveMAC(&socket->paddr, &sin.sin_addr.s_addr) == 0) { + // Grab Nonblocking Flag + uint32_t nbio = 0; + int fileflags = fcntl(socket->id,F_GETFL,O_NONBLOCK); + nbio = fileflags & O_NONBLOCK; + // Switch to Nonblocking Behaviour + if(nbio == 0) { + // Overwrite Socket Option + __change_blocking_mode(socket->id, 1); + } + + // Connect Socket to Peer (Nonblocking) + int connectresult = connect(socket->id, (sockaddr *)&sin, sizeof(sin)); + + // Grab Error Code + int errorcode = errno; + + // Restore Blocking Behaviour + if(nbio == 0) { + // Restore Socket Option + __change_blocking_mode(socket->id,0); + } + + // Instant Connection (Lucky!) + if(connectresult == 0 || (connectresult == -1 && errorcode == EISCONN)) { + // Set Connected State + socket->state = PTP_STATE_ESTABLISHED; + + // Success + return 0; + } + + // Connection in Progress + else if(connectresult == -1 && errorcode == EINPROGRESS) { + // Nonblocking Mode + if(flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Blocking Mode + else { + // Grab Connection Start Time + uint32_t starttime = __milliseconds_now(); + + // Peer Information (for Connection-Polling) + sockaddr_in peer; + memset(&peer, 0, sizeof(peer)); + uint32_t peerlen = sizeof(peer); + + // Wait for Connection + while((timeout == 0 || (__milliseconds_now() - starttime) < timeout) && getpeername(socket->id, (sockaddr *)&peer, &peerlen) != 0) { + // Wait 1ms + __msleep(1); + } + + // Connected in Time + if(sin.sin_addr.s_addr == peer.sin_addr.s_addr/* && sin.sin_port == peer.sin_port*/) { + // Set Connected State + socket->state = PTP_STATE_ESTABLISHED; + + // Success + return 0; + } + + // Timeout occured + return ERROR_NET_ADHOC_TIMEOUT; + } + } + } + + // Peer not found + return ERROR_NET_ADHOC_CONNECTION_REFUSED; + } + + // Not a valid Client Socket + return ERROR_NET_ADHOC_NOT_OPENED; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpConnect(int id, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpConnect(%i, %i, %i)", id, timeout, nonblock); - return -1; -} +/** + * Adhoc Emulator PTP Socket Closer + * @param id Socket File Descriptor + * @param flag Bitflags (Unused) + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED + */ int sceNetAdhocPtpClose(int id, int unknown) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpClose(%i, %i)", id, unknown); - return 0; + INFO_LOG(SCENET,"sceNetAdhocPtpClose(%d,%d)",id,unknown); + // Library is initialized + if(netAdhocInited) { + // Valid Arguments & Atleast one Socket + if(id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Close Connection + closesocket(socket->id); + + // Remove Port Forward from Router + // sceNetPortClose("TCP", socket->lport); + + // Free Memory + free(socket); + + // Free Reference + ptp[id - 1] = NULL; + + // Success + return 0; + } + + // Invalid Argument + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpListen(const char *srcmac, int srcport, int bufsize, int retryDelay, int retryCount, int queue, int unk) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpListen(%s : %i, %i, %i, %i, %i, %i)", srcmac, srcport, bufsize, retryDelay, retryCount, queue, unk); - return 0; + +/** + * Adhoc Emulator PTP Passive Socket Creator + * @param saddr Local MAC (Unused) + * @param sport Local Binding Port + * @param bufsize Socket Buffer Size + * @param rexmt_int Retransmit Interval (in Microseconds) + * @param rexmt_cnt Retransmit Count + * @param backlog Size of Connection Queue + * @param flag Bitflags (Unused) + * @return Socket ID > 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_ADDR, ADHOC_INVALID_PORT, ADHOC_SOCKET_ID_NOT_AVAIL, ADHOC_PORT_NOT_AVAIL, ADHOC_PORT_IN_USE, NET_NO_SPACE + */ +int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int rexmt_int, int rexmt_cnt, int backlog, int unk) { + INFO_LOG(SCENET, "sceNetAdhocPtpListen(%s,%d,%d,%d,%d,%d,%d)", + srcmac,sport,bufsize,rexmt_int,rexmt_cnt,backlog,unk); + // Library is initialized + SceNetEtherAddr * saddr = (SceNetEtherAddr *)srcmac; + if(netAdhocInited) { + // Valid Address + if(saddr != NULL && _IsLocalMAC(saddr)) + { + // Random Port required + if(sport == 0) { + // Find unused Port + // while(sport == 0 || __IsPTPPortInUse(sport)) + // { + // // Generate Port Number + // sport = (uint16_t)_getRandomNumber(65535); + // } + } + + // Valid Ports + if(!__IsPTPPortInUse(sport)) { + // Valid Arguments + if(bufsize > 0 && rexmt_int > 0 && rexmt_cnt > 0 && backlog > 0) + { + // Create Infrastructure Socket + int tcpsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + // Valid Socket produced + if(tcpsocket > 0) { + // Enable Port Re-use + setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + // Binding Information for local Port + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(sport); + + // Bound Socket to local Port + if(bind(tcpsocket, (sockaddr *)&addr, sizeof(addr)) == 0) { + // Switch into Listening Mode + if(listen(tcpsocket, backlog) == 0) { + // Allocate Memory + SceNetAdhocPtpStat * internal = (SceNetAdhocPtpStat *)malloc(sizeof(SceNetAdhocPtpStat)); + + // Allocated Memory + if(internal != NULL) { + // Find Free Translator ID + int i = 0; for(; i < 255; i++) if(ptp[i] == NULL) break; + + // Found Free Translator ID + if(i < 255) { + // Clear Memory + memset(internal, 0, sizeof(SceNetAdhocPtpStat)); + + // Copy Infrastructure Socket ID + internal->id = tcpsocket; + + // Copy Address Information + internal->laddr = *saddr; + internal->lport = sport; + + // Flag Socket as Listener + internal->state = PTP_STATE_LISTEN; + + // Set Buffer Size + internal->rcv_sb_cc = bufsize; + + // Link PTP Socket + ptp[i] = internal; + + // Add Port Forward to Router + // sceNetPortOpen("TCP", sport); + + // Return PTP Socket Pointer + return i + 1; + } + + // Free Memory + free(internal); + } + } + } + + // Close Socket + closesocket(tcpsocket); + } + + // Socket not available + return ERROR_NET_ADHOC_SOCKET_ID_NOT_AVAIL; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Ports + return ERROR_NET_ADHOC_PORT_IN_USE; + } + + // Invalid Addresses + return ERROR_NET_ADHOC_INVALID_ADDR; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpSend(int id, u32 data, u32 dataSizeAddr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpSend(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); - return 0; +/** + * Adhoc Emulator PTP Sender + * @param id Socket File Descriptor + * @param data Data Payload + * @param len IN: Length of Payload OUT: Sent Data (in Bytes) + * @param timeout Send Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_NOT_CONNECTED, ADHOC_THREAD_ABORTED, ADHOC_INVALID_DATALEN, ADHOC_DISCONNECTED, NET_INTERNAL, NET_NO_SPACE + */ +int sceNetAdhocPtpSend(int id, u32 dataAddr, u32 dataSizeAddr, int timeout, int flag) { + int * len = (int *)Memory::GetPointer(dataSizeAddr); + const char * data = Memory::GetCharPointer(dataAddr); + // Library is initialized + if(netAdhocInited) { + // Valid Socket + if(id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Connected Socket + if(socket->state == PTP_STATE_ESTABLISHED) { + // Valid Arguments + if(data != NULL && len != NULL && *len > 0) { + // Schedule Timeout Removal + if(flag) timeout = 0; + + // Apply Send Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + + // Acquire Network Lock + // _acquireNetworkLock(); + + // Send Data + __change_blocking_mode(socket->id, flag); + int sent = send(socket->id, data, *len, 0); + int error = errno; + __change_blocking_mode(socket->id, 0); + + // Free Network Lock + // _freeNetworkLock(); + + // Success + if(sent > 0) { + // Save Length + *len = sent; + + // Return Success + return 0; + } + + // Non-Critical Error + else if(sent == -1 && error == EAGAIN) { + // Blocking Situation + if(flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Change Socket State + socket->state = PTP_STATE_CLOSED; + + // Disconnected + return ERROR_NET_ADHOC_DISCONNECTED; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Not connected + return ERROR_NET_ADHOC_NOT_CONNECTED; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } -int sceNetAdhocPtpRecv(int id, u32 data, u32 dataSizeAddr, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpRecv(%i, %08x, %08x, %i, %i)", id, data, dataSizeAddr, timeout, nonblock); - return 0; + +/** + * Adhoc Emulator PTP Receiver + * @param id Socket File Descriptor + * @param buf Data Buffer + * @param len IN: Buffersize OUT: Received Data (in Bytes) + * @param timeout Receive Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_THREAD_ABORTED, ADHOC_DISCONNECTED, NET_INTERNAL + */ +int sceNetAdhocPtpRecv(int id, u32 data, u32 dataSizeAddr, int timeout, int flag) { + void * buf = (void *)Memory::GetPointer(data); + int * len = (int *)Memory::GetPointer(dataSizeAddr); + // Library is initialized + if(netAdhocInited) { + // Valid Socket + if(id > 0 && id <= 255 && ptp[id - 1] != NULL && ptp[id - 1]->state == PTP_STATE_ESTABLISHED) { + // Cast Socket + SceNetAdhocPtpStat * socket = ptp[id - 1]; + + // Valid Arguments + if(buf != NULL && len != NULL && *len > 0) { + // Schedule Timeout Removal + if(flag) timeout = 0; + + // Apply Send Timeout Settings to Socket + setsockopt(socket->id, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + // Acquire Network Lock + // _acquireNetworkLock(); + + // Receive Data + __change_blocking_mode(socket->id, flag); + int received = recv(socket->id, buf, *len, 0); + int error = errno; + __change_blocking_mode(socket->id, 0); + + // Free Network Lock + // _freeNetworkLock(); + + // Received Data + if(received > 0) { + // Save Length + *len = received; + + // Return Success + return 0; + } + + // Non-Critical Error + else if(received == -1 && error == EAGAIN) { + // Blocking Situation + if(flag) return ERROR_NET_ADHOC_WOULD_BLOCK; + + // Timeout + return ERROR_NET_ADHOC_TIMEOUT; + } + + // Change Socket State + socket->state = PTP_STATE_CLOSED; + + // Disconnected + return ERROR_NET_ADHOC_DISCONNECTED; + } + + // Invalid Arguments + return ERROR_NET_ADHOC_INVALID_ARG; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + + // Library is uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } +/** + * Adhoc Emulator PTP Flusher + * @param id Socket File Descriptor + * @param timeout Flush Timeout (in Microseconds) + * @param flag Nonblocking Flag + * @return 0 on success or... ADHOC_NOT_INITIALIZED, ADHOC_INVALID_ARG, ADHOC_INVALID_SOCKET_ID, ADHOC_SOCKET_DELETED, ADHOC_SOCKET_ALERTED, ADHOC_WOULD_BLOCK, ADHOC_TIMEOUT, ADHOC_THREAD_ABORTED, ADHOC_DISCONNECTED, ADHOC_NOT_CONNECTED, NET_INTERNAL + */ int sceNetAdhocPtpFlush(int id, int timeout, int nonblock) { - ERROR_LOG(SCENET, "UNIMPL sceNetAdhocPtpFlush(%i, %i, %i)", id, timeout, nonblock); - return 0; + INFO_LOG(SCENET,"sceNetAdhocPtpFlush(%d,%d,%d)", id, timeout, nonblock); + // Library initialized + if(netAdhocInited) { + // Valid Socket + if(id > 0 && id <= 255 && ptp[id - 1] != NULL) { + // Dummy Result + return 0; + } + + // Invalid Socket + return ERROR_NET_ADHOC_INVALID_SOCKET_ID; + } + // Library uninitialized + return ERROR_NET_ADHOC_NOT_INITIALIZED; } int sceNetAdhocGameModeCreateMaster(u32 data, int size) { @@ -2254,7 +3058,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) { - ERROR_LOG(SCENET, "sceNetAdhocMatchingCreate"); + INFO_LOG(SCENET, "sceNetAdhocMatchingCreate"); SceNetAdhocMatchingHandler handler; handler.entryPoint = callbackAddr; @@ -2433,7 +3237,7 @@ const HLEFunction sceNetAdhoc[] = { {0xe08bdac1, WrapI_CIIIIII, "sceNetAdhocPtpListen"}, {0xfc6fc07b, WrapI_III, "sceNetAdhocPtpConnect"}, {0x9ac2eeac, WrapI_III, "sceNetAdhocPtpFlush"}, - {0xb9685118, WrapI_IU, "sceNetAdhocGetPtpStat"}, + {0xb9685118, WrapI_UU, "sceNetAdhocGetPtpStat"}, {0x3278ab0c, WrapI_CUI, "sceNetAdhocGameModeCreateReplica"}, {0x98c204c8, WrapI_V, "sceNetAdhocGameModeUpdateMaster"}, {0xfa324b4e, WrapI_IU, "sceNetAdhocGameModeUpdateReplica"}, From 0bc7dee02c5983a6911a962a411c6aca1ca1beab Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Tue, 29 Oct 2013 21:31:25 +0000 Subject: [PATCH 08/21] Fixes time function --- Core/HLE/sceNetAdhoc.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index d5cdc93d5c..577eeb6a6d 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -609,7 +609,7 @@ int __getLocalIp(sockaddr_in * SocketAddress){ } // Returns current system time in miliseconds, windows only! -long long __milliseconds_now() { +uint64_t __milliseconds_now() { #ifdef _MSC_VER static LARGE_INTEGER s_frequency; static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency); @@ -623,7 +623,7 @@ long long __milliseconds_now() { #else timeval val; gettimeofday(&val,NULL); - return val.tv_usec * 1000; + return val.tv_usec/1000; #endif } @@ -806,22 +806,22 @@ int __friendFinder(){ chat.base.opcode = OPCODE_CHAT; // Last Ping Time - long long lastping = 0; + uint64_t lastping = 0; // Last Time Reception got updated uint64_t lastreceptionupdate = 0; - + + uint64_t now; // Finder Loop while(netAdhocctlInited) { // Acquire Network Lock //_acquireNetworkLock(); // Ping Server - - if(__milliseconds_now() - lastping >= 100) { - printf("sent ping\n"); + now = __milliseconds_now(); + if(now - lastping >= 100) { // Update Ping Time - lastping = __milliseconds_now(); + lastping = now; // Prepare Packet uint8_t opcode = OPCODE_PING; @@ -906,7 +906,7 @@ int __friendFinder(){ // Enough Data available if(rxpos >= sizeof(SceNetAdhocctlConnectPacketS2C)) { // Log Incoming Peer - INFO_LOG(SCENET,"Incoming Peer Data...\n"); + INFO_LOG(SCENET,"Incoming Peer Data..."); // Cast Packet SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx; @@ -934,7 +934,7 @@ int __friendFinder(){ // Enough Data available if(rxpos >= sizeof(SceNetAdhocctlDisconnectPacketS2C)) { // Log Incoming Peer Delete Request - INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request...\n"); + INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request..."); // Cast Packet SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx; @@ -962,7 +962,7 @@ int __friendFinder(){ // Enough Data available if(rxpos >= sizeof(SceNetAdhocctlScanPacketS2C)) { // Log Incoming Network Information - INFO_LOG(SCENET,"Incoming Group Information...\n"); + INFO_LOG(SCENET,"Incoming Group Information..."); // Cast Packet SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx; @@ -999,7 +999,7 @@ int __friendFinder(){ // Scan Complete Packet else if(rx[0] == OPCODE_SCAN_COMPLETE) { // Log Scan Completion - INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response...\n"); + INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response..."); // Change State threadStatus = ADHOCCTL_STATE_DISCONNECTED; @@ -1019,11 +1019,12 @@ int __friendFinder(){ rxpos -= 1; } } - __msleep(1000); + // Original value was 10 ms, I think 100 is just fine + __msleep(100); } // Log Shutdown - INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread\n"); + INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread"); // Return Success return 0; From 2c484c9bee71d3fa0f54f6000f73bd406bf81c9d Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Wed, 30 Oct 2013 00:18:06 +0000 Subject: [PATCH 09/21] Adds adhoc support notes on readme, and option to load server address from config --- Core/Config.cpp | 2 ++ Core/Config.h | 1 + Core/HLE/sceNetAdhoc.cpp | 29 ++++++++++++++++++----------- README.md | 23 ++++++++++++++++++++++- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 80ae8d41b0..13c905c309 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -255,6 +255,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); pspConfig->Get("NickName", &sNickName, "PPSSPP"); + pspConfig->Get("proAdhocServer", &proAdhocServer, "localhost"); pspConfig->Get("Language", &iLanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); pspConfig->Get("TimeFormat", &iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR); pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD); @@ -451,6 +452,7 @@ void Config::Save() { IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); pspConfig->Set("NickName", sNickName.c_str()); + pspConfig->Set("proAdhocServer", proAdhocServer.c_str()); pspConfig->Set("Language", iLanguage); pspConfig->Set("TimeFormat", iTimeFormat); pspConfig->Set("DateFormat", iDateFormat); diff --git a/Core/Config.h b/Core/Config.h index 61163f596f..f9731f5641 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -184,6 +184,7 @@ public: // SystemParam std::string sNickName; + std::string proAdhocServer; int iLanguage; int iTimeFormat; int iDateFormat; diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 577eeb6a6d..55900a12ab 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -39,10 +39,11 @@ #else #include #include +#include +#include +#include #include #include -#include -#include #include #endif #include @@ -660,33 +661,39 @@ int __init_network(SceNetAdhocctlAdhocId *adhoc_id){ WSADATA data; iResult = WSAStartup(MAKEWORD(2,2),&data); if(iResult != NOERROR){ - printf("Wsa failed with error %d\n",iResult); + ERROR_LOG(SCENET, "Wsa failed"); return iResult; } #endif metasocket = INVALID_SOCKET; metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); if(metasocket == INVALID_SOCKET){ - printf("invalid socket"); + ERROR_LOG(SCENET,"invalid socket"); return INVALID_SOCKET; } struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(27312); - server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); + server_addr.sin_port = htons(27312); // Maybe read this from config too + // Resolve dns + addrinfo * resultAddr; + iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr); + if(iResult != 0){ + printf("Dns error\n"); + return iResult; + } + server_addr.sin_addr.s_addr = ((sockaddr_in *)resultAddr->ai_addr)->sin_addr.s_addr; + iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); if(iResult == SOCKET_ERROR){ - printf("Socket error %d", iResult); + ERROR_LOG(SCENET,"Socket error"); return iResult; } - memset(¶meter,0,sizeof(parameter)); strcpy((char *)¶meter.nickname.data, g_Config.sNickName.c_str()); parameter.channel = 1; // Fake Channel 1 + + // Prepare Login Packet __getLocalMac(¶meter.bssid.mac_addr); - - SceNetAdhocctlLoginPacketC2S packet; packet.base.opcode = OPCODE_LOGIN; SceNetEtherAddr addres; diff --git a/README.md b/README.md index b8b61e8815..dca4055f21 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,24 @@ +ADHOC SUPPORT +============= +This is based on coldbird code: http://code.google.com/p/aemu/ All Credit goes +to him! + +Status +------ +Code is a complete mess and it's not fully functional yet, I still need to implement +some functions and add a upnp lib(really important for people with routers). + +I did test it with some games(emulator <-> real psp with the server running locally) +and it's looking good: +* Worms Open Warfare: Ran just fine, I was able to play a whole match without problems +* Monster Hunter Freedom Unite: Runs fine too. Gathering Hall and embarking on quests Works +* Dissidia Duodecim 012: Doesn't work. It requires some functions that I haven't implemented +yet. Also, it uses a port < 1000 and thats reserved for admin apps on linux, running the emu +as sudo "solves" it, but it's far from ideal. +* Pacman World Rally: Works too. + +Oh, and it probably only compiles on linux for now. + PPSSPP - a fast and portable PSP emulator ========================================= @@ -8,7 +29,7 @@ Originally released under the GPL 2.0 (and later) in November 2012 Official website: http://www.ppsspp.org/ -To contribute, see [the development page](http://www.ppsspp.org/development.html). +To contribute, see [the development page](http://www.ppspp.org/development.html). For the latest source code, see [our github page](https://github.com/hrydgard/ppsspp). From abdcf5dbf97f98e13601566149f4ea884c3e1778 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Wed, 30 Oct 2013 14:24:13 +0000 Subject: [PATCH 10/21] Typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dca4055f21..bd78169b42 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Originally released under the GPL 2.0 (and later) in November 2012 Official website: http://www.ppsspp.org/ -To contribute, see [the development page](http://www.ppspp.org/development.html). +To contribute, see [the development page](http://www.ppsspp.org/development.html). For the latest source code, see [our github page](https://github.com/hrydgard/ppsspp). From ca2b0a9b9a888d28b2aabf2f3b1bc13221dfc1b2 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Wed, 30 Oct 2013 14:45:32 +0000 Subject: [PATCH 11/21] Uses native functions for timing --- Core/HLE/sceNetAdhoc.cpp | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 55900a12ab..3ebb939a5a 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -25,6 +25,7 @@ #include "Core/HLE/HLE.h" #include "../CoreTiming.h" #include "Core/HLE/sceNetAdhoc.h" +#include "native/base/timeutil.h" #include "sceKernel.h" #include "sceKernelThread.h" @@ -42,7 +43,6 @@ #include #include #include -#include #include #include #endif @@ -609,25 +609,6 @@ int __getLocalIp(sockaddr_in * SocketAddress){ #endif } -// Returns current system time in miliseconds, windows only! -uint64_t __milliseconds_now() { -#ifdef _MSC_VER - static LARGE_INTEGER s_frequency; - static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency); - if (s_use_qpc) { - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - return (1000LL * now.QuadPart) / s_frequency.QuadPart; - } else { - return GetTickCount(); - } -#else - timeval val; - gettimeofday(&val,NULL); - return val.tv_usec/1000; -#endif -} - /* chages to the blocking mode of the socket 1 to set noblocking 0 to set blocking @@ -825,7 +806,7 @@ int __friendFinder(){ //_acquireNetworkLock(); // Ping Server - now = __milliseconds_now(); + now = real_time_now()*1000.0; if(now - lastping >= 100) { // Update Ping Time lastping = now; @@ -1027,7 +1008,7 @@ int __friendFinder(){ } } // Original value was 10 ms, I think 100 is just fine - __msleep(100); + sleep_ms(100); } // Log Shutdown @@ -2444,15 +2425,15 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou // Blocking Behaviour if(!flag && newsocket == -1) { // Get Start Time - uint32_t starttime = __milliseconds_now(); + uint32_t starttime = (uint32_t)(real_time_now()*1000.0); // Retry until Timeout hits - while((timeout == 0 || (__milliseconds_now() - starttime) < timeout) && newsocket == -1) { + while((timeout == 0 ||((uint32_t)(real_time_now()*1000.0) - starttime) < timeout) && newsocket == -1) { // Accept Connection newsocket = accept(socket->id, (sockaddr *)&peeraddr, &peeraddrlen); // Wait a bit... - __msleep(1); + sleep_ms(1); } } @@ -2617,7 +2598,7 @@ int sceNetAdhocPtpConnect(int id, int timeout, int flag) { // Blocking Mode else { // Grab Connection Start Time - uint32_t starttime = __milliseconds_now(); + uint32_t starttime = (uint32_t)(real_time_now()*1000.0); // Peer Information (for Connection-Polling) sockaddr_in peer; @@ -2625,9 +2606,9 @@ int sceNetAdhocPtpConnect(int id, int timeout, int flag) { uint32_t peerlen = sizeof(peer); // Wait for Connection - while((timeout == 0 || (__milliseconds_now() - starttime) < timeout) && getpeername(socket->id, (sockaddr *)&peer, &peerlen) != 0) { + while((timeout == 0 || ( (uint32_t)(real_time_now()*1000.0) - starttime) < timeout) && getpeername(socket->id, (sockaddr *)&peer, &peerlen) != 0) { // Wait 1ms - __msleep(1); + sleep_ms(1); } // Connected in Time From 24d2ac7c1b09ef10140f40046c24727ef3ce94eb Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Wed, 30 Oct 2013 14:56:08 +0000 Subject: [PATCH 12/21] Uses native mutex --- Core/HLE/sceNetAdhoc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 3ebb939a5a..1b94a73a67 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -26,6 +26,7 @@ #include "../CoreTiming.h" #include "Core/HLE/sceNetAdhoc.h" #include "native/base/timeutil.h" +#include "native/base/mutex.h" #include "sceKernel.h" #include "sceKernelThread.h" @@ -46,7 +47,6 @@ #include #include #endif -#include // End of extra includes #ifdef _MSC_VER @@ -507,7 +507,7 @@ static SceNetAdhocctlParameter parameter; static std::thread friendFinderThread; static SceNetAdhocctlPeerInfo * friends = NULL; static SceNetAdhocctlScanInfo * networks = NULL; -static std::mutex peerlock; +static recursive_mutex peerlock; static SceNetAdhocPdpStat * pdp[255]; static SceNetAdhocPtpStat * ptp[255]; static uint32_t fakePoolSize = 0; From 13718aed6e105ea9833fc102785a5718489dd0d6 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Wed, 30 Oct 2013 16:10:59 +0000 Subject: [PATCH 13/21] Changes psp ram structs to use correct int types --- Core/HLE/sceNetAdhoc.cpp | 123 ++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 1b94a73a67..b006e4508e 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -186,10 +186,10 @@ typedef struct SceNetAdhocctlBSSId { // Virtual Network Information typedef struct SceNetAdhocctlScanInfo { struct SceNetAdhocctlScanInfo * next; - int channel; + s32_le channel; SceNetAdhocctlGroupName group_name; SceNetAdhocctlBSSId bssid; - int mode; + s32_le mode; } PACK SceNetAdhocctlScanInfo; // Player Nickname @@ -200,7 +200,7 @@ typedef struct SceNetAdhocctlNickname { // Active Virtual Network Information typedef struct SceNetAdhocctlParameter { - int channel; + s32_le channel; SceNetAdhocctlGroupName group_name; SceNetAdhocctlBSSId bssid; SceNetAdhocctlNickname nickname; @@ -211,15 +211,25 @@ typedef struct SceNetAdhocctlPeerInfo { SceNetAdhocctlPeerInfo * next; SceNetAdhocctlNickname nickname; SceNetEtherAddr mac_addr; - uint32_t ip_addr; + u32_le ip_addr; uint8_t padding[2]; - uint64_t last_recv; + u64_le last_recv; } PACK SceNetAdhocctlPeerInfo; +// Peer Information with u32 pointers +typedef struct SceNetAdhocctlPeerInfoEmu { + u32_le next; // Changed the pointer to u32 + SceNetAdhocctlNickname nickname; + SceNetEtherAddr mac_addr; + u32_le ip_addr; + u32 padding; // Changed the pointer to u32 + u64_le last_recv; +} SceNetAdhocctlPeerInfoEmu; + // Game Mode Peer List #define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16 typedef struct SceNetAdhocctlGameModeInfo { - int num; + s32_le num; SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS]; } PACK SceNetAdhocctlGameModeInfo; #ifdef _MSC_VER @@ -229,54 +239,54 @@ typedef struct SceNetAdhocctlGameModeInfo { // Adhoc ID (Game Product Key) #define ADHOCCTL_ADHOCID_LEN 9 typedef struct SceNetAdhocctlAdhocId { - int type; + s32_le type; uint8_t data[ADHOCCTL_ADHOCID_LEN]; uint8_t padding[3]; } SceNetAdhocctlAdhocId; // Socket Polling Event Listener struct SceNetAdhocPollSd { - int id; - int events; - int revents; + s32_le id; + s32_le events; + s32_le revents; }; // PDP Socket Status struct SceNetAdhocPdpStat { struct SceNetAdhocPdpStat * next; - int id; + s32_le id; SceNetEtherAddr laddr; - uint16_t lport; - uint32_t rcv_sb_cc; + u16_le lport; + u32_le rcv_sb_cc; }; // PTP Socket Status struct SceNetAdhocPtpStat { - u32 next; // Changed the pointer to u32 - int id; + u32_le next; // Changed the pointer to u32 + s32_le id; SceNetEtherAddr laddr; SceNetEtherAddr paddr; - uint16_t lport; - uint16_t pport; - uint32_t snd_sb_cc; - uint32_t rcv_sb_cc; - int state; + u16_le lport; + u16_le pport; + u32_le snd_sb_cc; + u32_le rcv_sb_cc; + s32_le state; }; // Gamemode Optional Peer Buffer Data struct SceNetAdhocGameModeOptData { - uint32_t size; - uint32_t flag; - uint64_t last_recv; + u32_le size; + u32_le flag; + u64_le last_recv; }; // Gamemode Buffer Status struct SceNetAdhocGameModeBufferStat { struct SceNetAdhocGameModeBufferStat * next; - int id; + s32_le id; void * ptr; - uint32_t size; - uint32_t master; + u32_le size; + u32_le master; SceNetAdhocGameModeOptData opt; }; @@ -290,27 +300,27 @@ typedef struct SceNetAdhocMatchingMemberInternal { SceNetEtherAddr mac; // State Variable - int state; + s32_le state; // Send in Progress - int sending; + s32_le sending; // Last Heartbeat - uint64_t lastping; + u64_le lastping; } SceNetAdhocMatchingMemberInternal; // Matching handler struct SceNetAdhocMatchingHandlerArgs { - int id; - int event; + s32_le id; + s32_le event; SceNetEtherAddr * peer; - int optlen; + s32_le optlen; void * opt; }; struct SceNetAdhocMatchingHandler { - u32 entryPoint; + u32_le entryPoint; }; // Thread Message Stack Item @@ -320,13 +330,13 @@ typedef struct ThreadMessage struct ThreadMessage * next; // Stack Event Opcode - uint32_t opcode; + u32_le opcode; // Target MAC Address SceNetEtherAddr mac; // Optional Data Length - int optlen; + s32_le optlen; } ThreadMessage; // Established Peer @@ -337,16 +347,16 @@ typedef struct SceNetAdhocMatchingContext { struct SceNetAdhocMatchingContext * next; // Externally Visible ID - int id; + s32_le id; // Matching Mode (HOST, CLIENT, P2P) - int mode; + s32_le mode; // Running Flag (1 = running, 0 = created) - int running; + s32_le running; // Maximum Number of Peers (for HOST, P2P) - int maxpeers; + s32_le maxpeers; // Local MAC Address SceNetEtherAddr mac; @@ -355,53 +365,53 @@ typedef struct SceNetAdhocMatchingContext { SceNetAdhocMatchingMemberInternal * peerlist; // Local PDP Port - uint16_t port; + u16_le port; // Local PDP Socket - int socket; + s32_le socket; // Receive Buffer Length - int rxbuflen; + s32_le rxbuflen; // Receive Buffer uint8_t * rxbuf; // Hello Broadcast Interval (Microseconds) - uint32_t hello_int; + u32_le hello_int; // Keep-Alive Broadcast Interval (Microseconds) - uint32_t keepalive_int; + u32_le keepalive_int; // Resend Interval (Microseconds) - uint32_t resend_int; + u32_le resend_int; // Resend-Counter - int resendcounter; + s32_le resendcounter; // Keep-Alive Counter - int keepalivecounter; + s32_le keepalivecounter; // Event Handler SceNetAdhocMatchingHandler handler; // Hello Data Length - uint32_t hellolen; + u32_le hellolen; // Hello Data void * hello; // Event Caller Thread - int event_thid; + s32_le event_thid; // IO Handler Thread - int input_thid; + s32_le input_thid; // Event Caller Thread Message Stack - int event_stack_lock; + s32_le event_stack_lock; ThreadMessage * event_stack; // IO Handler Thread Message Stack - int input_stack_lock; + s32_le input_stack_lock; ThreadMessage * input_stack; } SceNetAdhocMatchingContext; @@ -3267,15 +3277,6 @@ int sceNetAdhocctlGetGameModeInfo(u32 infoAddr) { return -1; } -// Peer Information with u32 pointers -typedef struct SceNetAdhocctlPeerInfoEmu { - u32 next; // Changed the pointer to u32 - SceNetAdhocctlNickname nickname; - SceNetEtherAddr mac_addr; - uint32_t ip_addr; - u32 padding; // Changed the pointer to u32 - uint64_t last_recv; -} SceNetAdhocctlPeerInfoEmu; int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { int * buflen = (int *)Memory::GetPointer(sizeAddr); From 2d22ccadcabb55cc18a5879d6eecbaa9465a0f3f Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Wed, 30 Oct 2013 16:19:35 +0000 Subject: [PATCH 14/21] Fixes crash when server is not available --- Core/HLE/sceNetAdhoc.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index b006e4508e..bfc90bccc8 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -2056,13 +2056,14 @@ int sceNetAdhocctlTerm() { INFO_LOG(SCENET, "sceNetAdhocctlTerm()"); if(netAdhocInited){ netAdhocctlInited = false; - friendFinderThread.join(); + if(friendFinderThread.joinable()){ + friendFinderThread.join(); + } // Free sttuf here closesocket(metasocket); - metasocket = -1; - + metasocket = INVALID_SOCKET; #ifdef _MSC_VER - WSACleanup(); // WINDOWS ONLY! + WSACleanup(); #endif } From f3f0bc231b4b73f4b004a40e8b80edac3719d417 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Tue, 5 Nov 2013 16:36:01 +0000 Subject: [PATCH 15/21] Adds cleanup method after game exit --- Core/HLE/sceNetAdhoc.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index bfc90bccc8..54cec443ad 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -525,6 +525,7 @@ static SceNetAdhocMatchingContext * contexts = NULL; static int one = 1; // End of Aux vars + struct AdhocctlHandler { u32 entryPoint; u32 argument; @@ -539,8 +540,15 @@ void __NetAdhocInit() { adhocctlHandlers.clear(); } -void __NetAdhocShutdown() { +int sceNetAdhocTerm(); +int sceNetAdhocctlTerm(); +int sceNetAdhocMatchingTerm(); + +void __NetAdhocShutdown() { + sceNetAdhocTerm(); + sceNetAdhocctlTerm(); + sceNetAdhocMatchingTerm(); } void __NetAdhocDoState(PointerWrap &p) { @@ -2054,7 +2062,7 @@ u32 sceNetAdhocctlDelHandler(u32 handlerID) { int sceNetAdhocctlTerm() { INFO_LOG(SCENET, "sceNetAdhocctlTerm()"); - if(netAdhocInited){ + if(netAdhocctlInited){ netAdhocctlInited = false; if(friendFinderThread.joinable()){ friendFinderThread.join(); From 33f4b440610c6ecb9d5c7aa048cf30990d35a0e4 Mon Sep 17 00:00:00 2001 From: Igor Calabria Date: Sun, 10 Nov 2013 01:26:31 +0000 Subject: [PATCH 16/21] Moves proAdhoc extra functions to a separate file --- CMakeLists.txt | 2 + Core/HLE/proAdhoc.cpp | 700 ++++++++++++++++++++ Core/HLE/proAdhoc.h | 586 +++++++++++++++++ Core/HLE/sceNetAdhoc.cpp | 1299 ++------------------------------------ 4 files changed, 1328 insertions(+), 1259 deletions(-) create mode 100644 Core/HLE/proAdhoc.cpp create mode 100644 Core/HLE/proAdhoc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d7bb332779..4d76a7b746 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -848,6 +848,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/HLE/sceNet.h Core/HLE/sceNetAdhoc.cpp Core/HLE/sceNetAdhoc.h + Core/HLE/proAdhoc.h + Core/HLE/proAdhoc.cpp Core/HLE/sceOpenPSID.cpp Core/HLE/sceOpenPSID.h Core/HLE/sceP3da.cpp diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp new file mode 100644 index 0000000000..fa68024350 --- /dev/null +++ b/Core/HLE/proAdhoc.cpp @@ -0,0 +1,700 @@ +#include "proAdhoc.h" + +uint32_t fakePoolSize = 0; +SceNetAdhocMatchingContext * contexts = NULL; +int one = 1; +bool friendFinderRunning = false; +SceNetAdhocctlPeerInfo * friends = NULL; +SceNetAdhocctlScanInfo * networks = NULL; +int eventHandlerUpdate = -1; +int threadStatus = ADHOCCTL_STATE_DISCONNECTED; + +int metasocket; +SceNetAdhocctlParameter parameter; +std::thread friendFinderThread; +recursive_mutex peerlock; +SceNetAdhocPdpStat * pdp[255]; +SceNetAdhocPtpStat * ptp[255]; + +int isLocalMAC(const SceNetEtherAddr * addr) { + SceNetEtherAddr saddr; + getLocalMac(&saddr); + + // Compare MAC Addresses + int match = memcmp((const void *)addr, (const void *)&saddr, ETHER_ADDR_LEN); + + // Return Result + return (match == 0); +} + +int isPDPPortInUse(uint16_t port) { + // Iterate Elements + int i = 0; for(; i < 255; i++) if(pdp[i] != NULL && pdp[i]->lport == port) return 1; + + // Unused Port + return 0; +} + +int isPTPPortInUse(uint16_t port) { + // Iterate Sockets + int i = 0; for(; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return 1; + + // Unused Port + return 0; +} + +void addFriend(SceNetAdhocctlConnectPacketS2C * packet) { + // Allocate Structure + SceNetAdhocctlPeerInfo * peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo)); + // Allocated Structure + if(peer != NULL) { + // Clear Memory + memset(peer, 0, sizeof(SceNetAdhocctlPeerInfo)); + + // Link to existing Peers + peer->next = friends; + + // Save Nickname + peer->nickname = packet->name; + + // Save MAC Address + peer->mac_addr = packet->mac; + + // Save IP Address + peer->ip_addr = packet->ip; + + // Multithreading Lock + peerlock.lock(); + + // Link into Peerlist + friends = peer; + + // Multithreading Unlock + peerlock.unlock(); + } +} + +void changeBlockingMode(int fd, int nonblocking) { + unsigned long on = 1; + unsigned long off = 0; +#ifdef _MSC_VER + if(nonblocking){ + // Change to Non-Blocking Mode + ioctlsocket(fd,FIONBIO,&on); + }else { + // Change to Blocking Mode + ioctlsocket(fd, FIONBIO, &off); + } +#else + if(nonblocking == 1) fcntl(fd, F_SETFL, O_NONBLOCK); + else { + // Get Flags + int flags = fcntl(fd, F_GETFL); + // Remove Non-Blocking Flag + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + } +#endif +} + +int countAvailableNetworks(void) { + // Network Count + int count = 0; + + // Group Reference + SceNetAdhocctlScanInfo * group = networks; + + // Count Groups + for(; group != NULL; group = group->next) count++; + + // Return Network Count + return count; +} + +void deleteAllPDP(void) { + // Iterate Element + int i = 0; for(; i < 255; i++) { + // Active Socket + if(pdp[i] != NULL) { + // Close Socket + closesocket(pdp[i]->id); + + // Free Memory + free(pdp[i]); + + // Delete Reference + pdp[i] = NULL; + } + } +} + +void deleteAllPTP(void) { + // Iterate Element + int i = 0; for(; i < 255; i++) { + // Active Socket + if(ptp[i] != NULL) { + // Close Socket + closesocket(ptp[i]->id); + + // Free Memory + free(ptp[i]); + + // Delete Reference + ptp[i] = NULL; + } + } +} + +void deleteFriendByIP(uint32_t ip) { + // Previous Peer Reference + SceNetAdhocctlPeerInfo * prev = NULL; + + // Peer Pointer + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Peer + if(peer->ip_addr == ip) { + // Multithreading Lock + peerlock.lock(); + + // Unlink Left (Beginning) + if(prev == NULL)friends = peer->next; + + // Unlink Left (Other) + else prev->next = peer->next; + + // Multithreading Unlock + peerlock.unlock(); + + // Free Memory + free(peer); + + // Stop Search + break; + } + + // Set Previous Reference + prev = peer; + } +} + +int findFreeMatchingID(void) { + // Minimum Matching ID + int min = 1; + + // Maximum Matching ID + int max = 0; + + // Find highest Matching ID + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { + // New Maximum + if(max < item->id) max = item->id; + } + + // Find unoccupied ID + int i = min; for(; i < max; i++) { + // Found unoccupied ID + if(findMatchingContext(i) == NULL) return i; + } + + // Append at virtual end + return max + 1; +} + +SceNetAdhocMatchingContext * findMatchingContext(int id) { + // Iterate Matching Context List + SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { // Found Matching ID + if(item->id == id) return item; + } + + // Context not found + return NULL; +} + +void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) { + // End of List + if(node == NULL) return; + + // Increase Recursion Depth + freeFriendsRecursive(node->next); + + // Free Memory + free(node); +} + +int friendFinder(){ + // Receive Buffer + int rxpos = 0; + uint8_t rx[1024]; + + // Chat Packet + SceNetAdhocctlChatPacketC2S chat; + chat.base.opcode = OPCODE_CHAT; + + // Last Ping Time + uint64_t lastping = 0; + + // Last Time Reception got updated + uint64_t lastreceptionupdate = 0; + + uint64_t now; + + // Finder Loop + while(friendFinderRunning) { + // Acquire Network Lock + //_acquireNetworkLock(); + + // Ping Server + now = real_time_now()*1000.0; + if(now - lastping >= 100) { + // Update Ping Time + lastping = now; + + // Prepare Packet + uint8_t opcode = OPCODE_PING; + + // Send Ping to Server + send(metasocket, (const char *)&opcode, 1,0); + } + + // Send Chat Messages + //while(popFromOutbox(chat.message)) + //{ + // // Send Chat to Server + // sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0); + //} + + // Wait for Incoming Data + int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos,0); + + // Free Network Lock + //_freeNetworkLock(); + + // Received Data + if(received > 0) { + // Fix Position + rxpos += received; + + // Log Incoming Traffic + //printf("Received %d Bytes of Data from Server\n", received); + INFO_LOG(SCENET, "Received %d Bytes of Data from Adhoc Server", received); + } + + // Handle Packets + if(rxpos > 0) { + // BSSID Packet + if(rx[0] == OPCODE_CONNECT_BSSID) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) { + // Cast Packet + SceNetAdhocctlConnectBSSIDPacketS2C * packet = (SceNetAdhocctlConnectBSSIDPacketS2C *)rx; + // Update BSSID + parameter.bssid.mac_addr = packet->mac; + // Change State + threadStatus = ADHOCCTL_STATE_CONNECTED; + // Notify Event Handlers + CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0)); + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlConnectBSSIDPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C); + } + } + + // Chat Packet + else if(rx[0] == OPCODE_CHAT) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlChatPacketS2C)) { + // Cast Packet + SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx; + + // Fix for Idiots that try to troll the "ME" Nametag +#ifdef _MSC_VER + if(stricmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); +#else + if(strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); +#endif + + // Add Incoming Chat to HUD + //printf("Receive chat message %s", packet->base.message); + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlChatPacketS2C); + } + } + + // Connect Packet + else if(rx[0] == OPCODE_CONNECT) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlConnectPacketS2C)) { + // Log Incoming Peer + INFO_LOG(SCENET,"Incoming Peer Data..."); + + // Cast Packet + SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx; + + // Add User + addFriend(packet); + + // Update HUD User Count +#ifdef LOCALHOST_AS_PEER + setUserCount(getActivePeerCount()); +#else + // setUserCount(getActivePeerCount()+1); +#endif + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlConnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlConnectPacketS2C); + } + } + + // Disconnect Packet + else if(rx[0] == OPCODE_DISCONNECT) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlDisconnectPacketS2C)) { + // Log Incoming Peer Delete Request + INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request..."); + + // Cast Packet + SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx; + + // Delete User by IP + deleteFriendByIP(packet->ip); + + // Update HUD User Count +#ifdef LOCALHOST_AS_PEER + setUserCount(_getActivePeerCount()); +#else + //setUserCount(_getActivePeerCount()+1); +#endif + + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlDisconnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlDisconnectPacketS2C)); + + // Fix RX Buffer Length + rxpos -= sizeof(SceNetAdhocctlDisconnectPacketS2C); + } + } + + // Scan Packet + else if(rx[0] == OPCODE_SCAN) { + // Enough Data available + if(rxpos >= sizeof(SceNetAdhocctlScanPacketS2C)) { + // Log Incoming Network Information + INFO_LOG(SCENET,"Incoming Group Information..."); + // Cast Packet + SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx; + + // Allocate Structure Data + SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo)); + + // Allocated Structure Data + if(group != NULL) + { + // Clear Memory + memset(group, 0, sizeof(SceNetAdhocctlScanInfo)); + + // Link to existing Groups + group->next = networks; + + // Copy Group Name + group->group_name = packet->group; + + // Set Group Host + group->bssid.mac_addr = packet->mac; + + // Link into Group List + networks = group; + } + + // 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) { + // Log Scan Completion + INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response..."); + + // Change State + threadStatus = ADHOCCTL_STATE_DISCONNECTED; + + // Notify Event Handlers + CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate,join32(ADHOCCTL_EVENT_SCAN, 0)); + //int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++) + //{ + // // Active Handler + // if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]); + //} + + // Move RX Buffer + memmove(rx, rx + 1, sizeof(rx) - 1); + + // Fix RX Buffer Length + rxpos -= 1; + } + } + // Original value was 10 ms, I think 100 is just fine + sleep_ms(100); + } + + // Log Shutdown + INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread"); + + // Return Success + return 0; +} + +int getActivePeerCount(void) { + // Counter + int count = 0; + + // #ifdef LOCALHOST_AS_PEER + // // Increase for Localhost + // count++; + // #endif + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Increase Counter + count++; + } + + // Return Result + return count; +} + +int getLocalIp(sockaddr_in * SocketAddress){ +#ifdef _MSC_VER + // Get local host name + char szHostName[128] = ""; + + if(::gethostname(szHostName, sizeof(szHostName))) { + // Error handling + } + // Get local IP addresses + struct hostent *pHost = 0; + pHost = ::gethostbyname(szHostName); + if(pHost) { + memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length); + return 0; + } + return -1; +#else + char ip[] = "192.168.12.1"; + SocketAddress->sin_addr.s_addr = inet_addr("192.168.12.1"); + return 0; +#endif +} + +void getLocalMac(SceNetEtherAddr * addr){ + uint8_t mac[] = {1, 2, 3, 4, 5, 6}; + memcpy(addr,mac,ETHER_ADDR_LEN); +} + +int getPTPSocketCount(void) { + // Socket Counter + int counter = 0; + + // Count Sockets + int i = 0; for(; i < 255; i++) if(ptp[i] != NULL) counter++; + + // Return Socket Count + return counter; +} + +int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ + int iResult = 0; +#ifdef _MSC_VER + WSADATA data; + iResult = WSAStartup(MAKEWORD(2,2),&data); + if(iResult != NOERROR){ + ERROR_LOG(SCENET, "Wsa failed"); + return iResult; + } +#endif + metasocket = INVALID_SOCKET; + metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); + if(metasocket == INVALID_SOCKET){ + ERROR_LOG(SCENET,"invalid socket"); + return INVALID_SOCKET; + } + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(27312); // Maybe read this from config too + + // Resolve dns + addrinfo * resultAddr; + iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr); + if(iResult != 0){ + ERROR_LOG(SCENET, "Dns error\n"); + return iResult; + } + server_addr.sin_addr.s_addr = ((sockaddr_in *)resultAddr->ai_addr)->sin_addr.s_addr; + iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); + if(iResult == SOCKET_ERROR){ + ERROR_LOG(SCENET,"Socket error"); + return iResult; + } + memset(¶meter,0,sizeof(parameter)); + strcpy((char *)¶meter.nickname.data, g_Config.sNickName.c_str()); + parameter.channel = 1; // Fake Channel 1 + + // Prepare Login Packet + getLocalMac(¶meter.bssid.mac_addr); + SceNetAdhocctlLoginPacketC2S packet; + packet.base.opcode = OPCODE_LOGIN; + SceNetEtherAddr addres; + getLocalMac(&addres); + packet.mac = addres; + strcpy((char *)packet.name.data, g_Config.sNickName.c_str()); + memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN); + int sent = send(metasocket, (char*)&packet, sizeof(packet), 0); + changeBlockingMode(metasocket,1); // Change to non-blocking + if(sent > 0){ + return 0; + }else{ + return -1; + } +} + +int isBroadcastMAC(const SceNetEtherAddr * addr) { + // Broadcast MAC + if(memcmp(addr->data, "\xFF\xFF\xFF\xFF\xFF\xFF", ETHER_ADDR_LEN) == 0) return 1; + // Normal MAC + return 0; +} + +int resolveIP(uint32_t ip, SceNetEtherAddr * mac) { + sockaddr_in addr; + getLocalIp(&addr); + uint32 localIp = addr.sin_addr.s_addr; + + if(ip == localIp){ + getLocalMac(mac); + return 0; + } + + // Multithreading Lock + peerlock.lock(); + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Matching Peer + if(peer->ip_addr == ip) { + // Copy Data + *mac = peer->mac_addr; + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + } + + // Multithreading Unlock + peerlock.unlock(); + + // Peer not found + return -1; +} + +int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) { + // Get Local MAC Address + SceNetEtherAddr localMac; + getLocalMac(&localMac); + // Local MAC Requested + if(memcmp(&localMac, mac, sizeof(SceNetEtherAddr)) == 0) { + // Get Local IP Address + sockaddr_in sockAddr; + getLocalIp(&sockAddr); + *ip = sockAddr.sin_addr.s_addr; + return 0; // return succes + } + + // Multithreading Lock + peerlock.lock(); + + // Peer Reference + SceNetAdhocctlPeerInfo * peer = friends; + + // Iterate Peers + for(; peer != NULL; peer = peer->next) { + // Found Matching Peer + if(memcmp(&peer->mac_addr, mac, sizeof(SceNetEtherAddr)) == 0) { + // Copy Data + *ip = peer->ip_addr; + + // Multithreading Unlock + peerlock.unlock(); + + // Return Success + return 0; + } + } + + // Multithreading Unlock + peerlock.unlock(); + + // Peer not found + return -1; +} + +int validNetworkName(const SceNetAdhocctlGroupName * group_name) { + // Result + int valid = 1; + + // Name given + if(group_name != NULL) { + // Iterate Name Characters + int i = 0; for(; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) { + // End of Name + if(group_name->data[i] == 0) break; + + // Not a digit + if(group_name->data[i] < '0' || group_name->data[i] > '9') { + // Not 'A' to 'Z' + if(group_name->data[i] < 'A' || group_name->data[i] > 'Z') { + // Not 'a' to 'z' + if(group_name->data[i] < 'a' || group_name->data[i] > 'z') { + // Invalid Name + valid = 0; + } + } + } + } + } + // Return Result + return valid; +} + +u64 join32(u32 num1, u32 num2){ + return (u64)num2 << 32 | num1; +} + +void split64(u64 num, int buff[]){ + int num1 = (int)(num&firstMask); + int num2 = (int)((num&secondMask)>>32); + buff[0] = num1; + buff[1] = num2; +} diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h new file mode 100644 index 0000000000..7ed7185d4b --- /dev/null +++ b/Core/HLE/proAdhoc.h @@ -0,0 +1,586 @@ +#pragma once + +#include "Common/ChunkFile.h" +#include "../Config.h" +#include "Core/HLE/HLE.h" +#include "../CoreTiming.h" +#include "Core/HLE/sceNetAdhoc.h" +#include "native/base/timeutil.h" +#include "native/base/mutex.h" + +#include "sceKernel.h" +#include "sceKernelThread.h" +#include "sceKernelMutex.h" +#include "sceUtility.h" +#include "net/resolve.h" +#include + +// Net stuff +#ifdef _MSC_VER +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif +#ifdef _MSC_VER +#define PACK +#else +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define closesocket close +#define PACK __attribute__((packed)) +#endif + +// psp strutcs and definitions +#define ADHOCCTL_MODE_ADHOC 0 +#define ADHOCCTL_MODE_GAMEMODE 1 + +// Event Types for Event Handler +#define ADHOCCTL_EVENT_CONNECT 1 +#define ADHOCCTL_EVENT_DISCONNECT 2 +#define ADHOCCTL_EVENT_SCAN 3 + +// Internal Thread States +#define ADHOCCTL_STATE_DISCONNECTED 0 +#define ADHOCCTL_STATE_CONNECTED 1 +#define ADHOCCTL_STATE_SCANNING 2 +#define ADHOCCTL_STATE_GAMEMODE 3 + +// Kernel Utility Netconf Adhoc Types +#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2 +#define UTILITY_NETCONF_TYPE_CREATE_ADHOC 4 +#define UTILITY_NETCONF_TYPE_JOIN_ADHOC 5 + +// Kernel Utility States +#define UTILITY_NETCONF_STATUS_NONE 0 +#define UTILITY_NETCONF_STATUS_INITIALIZE 1 +#define UTILITY_NETCONF_STATUS_RUNNING 2 +#define UTILITY_NETCONF_STATUS_FINISHED 3 +#define UTILITY_NETCONF_STATUS_SHUTDOWN 4 + +// PTP Connection States +#define PTP_STATE_CLOSED 0 +#define PTP_STATE_LISTEN 1 +#define PTP_STATE_ESTABLISHED 4 + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif +// Ethernet Address +#define ETHER_ADDR_LEN 6 +typedef struct SceNetEtherAddr { + uint8_t data[ETHER_ADDR_LEN]; +} PACK SceNetEtherAddr; + + +// Adhoc Virtual Network Name +#define ADHOCCTL_GROUPNAME_LEN 8 +typedef struct SceNetAdhocctlGroupName { + uint8_t data[ADHOCCTL_GROUPNAME_LEN]; +} PACK SceNetAdhocctlGroupName; + +// Virtual Network Host Information +typedef struct SceNetAdhocctlBSSId { + SceNetEtherAddr mac_addr; + uint8_t padding[2]; +} PACK SceNetAdhocctlBSSId; + +// Virtual Network Information +typedef struct SceNetAdhocctlScanInfo { + struct SceNetAdhocctlScanInfo * next; + s32_le channel; + SceNetAdhocctlGroupName group_name; + SceNetAdhocctlBSSId bssid; + s32_le mode; +} PACK SceNetAdhocctlScanInfo; + +// Player Nickname +#define ADHOCCTL_NICKNAME_LEN 128 +typedef struct SceNetAdhocctlNickname { + uint8_t data[ADHOCCTL_NICKNAME_LEN]; +} PACK SceNetAdhocctlNickname; + +// Active Virtual Network Information +typedef struct SceNetAdhocctlParameter { + s32_le channel; + SceNetAdhocctlGroupName group_name; + SceNetAdhocctlBSSId bssid; + SceNetAdhocctlNickname nickname; +} PACK SceNetAdhocctlParameter; + +// Peer Information +typedef struct SceNetAdhocctlPeerInfo { + SceNetAdhocctlPeerInfo * next; + SceNetAdhocctlNickname nickname; + SceNetEtherAddr mac_addr; + u32_le ip_addr; + uint8_t padding[2]; + u64_le last_recv; +} PACK SceNetAdhocctlPeerInfo; + +// Peer Information with u32 pointers +typedef struct SceNetAdhocctlPeerInfoEmu { + u32_le next; // Changed the pointer to u32 + SceNetAdhocctlNickname nickname; + SceNetEtherAddr mac_addr; + u32_le ip_addr; + u32 padding; // Changed the pointer to u32 + u64_le last_recv; +} SceNetAdhocctlPeerInfoEmu; + +// Game Mode Peer List +#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16 +typedef struct SceNetAdhocctlGameModeInfo { + s32_le num; + SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS]; +} PACK SceNetAdhocctlGameModeInfo; +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +// Adhoc ID (Game Product Key) +#define ADHOCCTL_ADHOCID_LEN 9 +typedef struct SceNetAdhocctlAdhocId { + s32_le type; + uint8_t data[ADHOCCTL_ADHOCID_LEN]; + uint8_t padding[3]; +} SceNetAdhocctlAdhocId; + +// Socket Polling Event Listener +struct SceNetAdhocPollSd { + s32_le id; + s32_le events; + s32_le revents; +}; + +// PDP Socket Status +struct SceNetAdhocPdpStat { + struct SceNetAdhocPdpStat * next; + s32_le id; + SceNetEtherAddr laddr; + u16_le lport; + u32_le rcv_sb_cc; +}; + +// PTP Socket Status +struct SceNetAdhocPtpStat { + u32_le next; // Changed the pointer to u32 + s32_le id; + SceNetEtherAddr laddr; + SceNetEtherAddr paddr; + u16_le lport; + u16_le pport; + u32_le snd_sb_cc; + u32_le rcv_sb_cc; + s32_le state; +}; + +// Gamemode Optional Peer Buffer Data +struct SceNetAdhocGameModeOptData { + u32_le size; + u32_le flag; + u64_le last_recv; +}; + +// Gamemode Buffer Status +struct SceNetAdhocGameModeBufferStat { + struct SceNetAdhocGameModeBufferStat * next; + s32_le id; + void * ptr; + u32_le size; + u32_le master; + SceNetAdhocGameModeOptData opt; +}; + + +// Internal Matching Peer Information +typedef struct SceNetAdhocMatchingMemberInternal { + // Next Peer + struct SceNetAdhocMatchingMemberInternal * next; + + // MAC Address + SceNetEtherAddr mac; + + // State Variable + s32_le state; + + // Send in Progress + s32_le sending; + + // Last Heartbeat + u64_le lastping; +} SceNetAdhocMatchingMemberInternal; + + +// Matching handler +struct SceNetAdhocMatchingHandlerArgs { + s32_le id; + s32_le event; + SceNetEtherAddr * peer; + s32_le optlen; + void * opt; +}; + +struct SceNetAdhocMatchingHandler { + u32_le entryPoint; +}; + +// Thread Message Stack Item +typedef struct ThreadMessage { + // Next Thread Message + struct ThreadMessage * next; + + // Stack Event Opcode + u32_le opcode; + + // Target MAC Address + SceNetEtherAddr mac; + + // Optional Data Length + s32_le optlen; +} ThreadMessage; + +// Established Peer + +// Context Information +typedef struct SceNetAdhocMatchingContext { + // Next Context + struct SceNetAdhocMatchingContext * next; + + // Externally Visible ID + s32_le id; + + // Matching Mode (HOST, CLIENT, P2P) + s32_le mode; + + // Running Flag (1 = running, 0 = created) + s32_le running; + + // Maximum Number of Peers (for HOST, P2P) + s32_le maxpeers; + + // Local MAC Address + SceNetEtherAddr mac; + + // Peer List for Connectees + SceNetAdhocMatchingMemberInternal * peerlist; + + // Local PDP Port + u16_le port; + + // Local PDP Socket + s32_le socket; + + // Receive Buffer Length + s32_le rxbuflen; + + // Receive Buffer + uint8_t * rxbuf; + + // Hello Broadcast Interval (Microseconds) + u32_le hello_int; + + // Keep-Alive Broadcast Interval (Microseconds) + u32_le keepalive_int; + + // Resend Interval (Microseconds) + u32_le resend_int; + + // Resend-Counter + s32_le resendcounter; + + // Keep-Alive Counter + s32_le keepalivecounter; + + // Event Handler + SceNetAdhocMatchingHandler handler; + + // Hello Data Length + u32_le hellolen; + + // Hello Data + void * hello; + + // Event Caller Thread + s32_le event_thid; + + // IO Handler Thread + s32_le input_thid; + + // Event Caller Thread Message Stack + s32_le event_stack_lock; + ThreadMessage * event_stack; + + // IO Handler Thread Message Stack + s32_le input_stack_lock; + ThreadMessage * input_stack; +} SceNetAdhocMatchingContext; + +// End of psp definitions + +#define OPCODE_PING 0 +#define OPCODE_LOGIN 1 +#define OPCODE_CONNECT 2 +#define OPCODE_DISCONNECT 3 +#define OPCODE_SCAN 4 +#define OPCODE_SCAN_COMPLETE 5 +#define OPCODE_CONNECT_BSSID 6 +#define OPCODE_CHAT 7 + +// PSP Product Code +#define PRODUCT_CODE_LENGTH 9 + +#ifdef _MSC_VER +#pragma pack(push,1) +#endif + +typedef struct { + // Game Product Code (ex. ULUS12345) + char data[PRODUCT_CODE_LENGTH]; +} PACK SceNetAdhocctlProductCode; + +// Basic Packet +typedef struct { + uint8_t opcode; +} PACK SceNetAdhocctlPacketBase; + +// C2S Login Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetEtherAddr mac; + SceNetAdhocctlNickname name; + SceNetAdhocctlProductCode game; +} PACK SceNetAdhocctlLoginPacketC2S; + +// C2S Connect Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetAdhocctlGroupName group; +} PACK SceNetAdhocctlConnectPacketC2S; + +// C2S Chat Packet +typedef struct { + SceNetAdhocctlPacketBase base; + char message[64]; +} PACK SceNetAdhocctlChatPacketC2S; + +// S2C Connect Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetAdhocctlNickname name; + SceNetEtherAddr mac; + uint32_t ip; +} PACK SceNetAdhocctlConnectPacketS2C; + +// S2C Disconnect Packet +typedef struct { + SceNetAdhocctlPacketBase base; + uint32_t ip; +} PACK SceNetAdhocctlDisconnectPacketS2C; + +// S2C Scan Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetAdhocctlGroupName group; + SceNetEtherAddr mac; +} PACK SceNetAdhocctlScanPacketS2C; + +// S2C Connect BSSID Packet +typedef struct { + SceNetAdhocctlPacketBase base; + SceNetEtherAddr mac; +} PACK SceNetAdhocctlConnectBSSIDPacketS2C; + +// S2C Chat Packet +typedef struct { + SceNetAdhocctlChatPacketC2S base; + SceNetAdhocctlNickname name; +} PACK SceNetAdhocctlChatPacketS2C; +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +// Aux vars +extern int metasocket; +extern SceNetAdhocctlParameter parameter; +extern std::thread friendFinderThread; +extern recursive_mutex peerlock; +extern SceNetAdhocPdpStat * pdp[255]; +extern SceNetAdhocPtpStat * ptp[255]; + +extern uint32_t fakePoolSize; +extern SceNetAdhocMatchingContext * contexts; +extern int one; +extern bool friendFinderRunning; +extern SceNetAdhocctlPeerInfo * friends; +extern SceNetAdhocctlScanInfo * networks; +extern int eventHandlerUpdate; +extern int threadStatus; +// End of Aux vars + +/** + * Local MAC Check + * @param saddr To-be-checked MAC Address + * @return 1 if valid or... 0 + */ +int isLocalMAC(const SceNetEtherAddr * addr); + +/** + * PDP Port Check + * @param port To-be-checked Port + * @return 1 if in use or... 0 + */ +int isPDPPortInUse(uint16_t port); + +/** + * Check whether PTP Port is in use or not + * @param port To-be-checked Port Number + * @return 1 if in use or... 0 + */ +int isPTPPortInUse(uint16_t port); + +/** + * Add Friend to Local List + * @param packet Friend Information + */ +void addFriend(SceNetAdhocctlConnectPacketS2C * packet); + +/** + * Changes the Blocking Mode of the socket + * @param fd File Descriptor of the socket + * @param nonblocking 1 to set to nonblock and 0 to set blocking + */ +void changeBlockingMode(int fd, int nonblocking); + +/** + * Count Virtual Networks by analyzing the Friend List + * @return Number of Virtual Networks + */ +int countAvailableNetworks(); + +/** + * Closes & Deletes all PDP Sockets + */ +void deleteAllPDP(void); + +/** + * Closes & Deletes all PTP sockets + */ +void deleteAllPTP(void); + +/** + * Delete Friend from Local List + * @param ip Friend IP + */ +void deleteFriendByIP(uint32_t ip); + +/** + * Find Free Matching ID + * @return First unoccupied Matching ID + */ +int findFreeMatchingID(void); + +/** + * Find Internal Matching Context for Matching ID + * @param id Matching ID + * @return Matching Context Pointer or... NULL + */ +SceNetAdhocMatchingContext * findMatchingContext(int id); + +/** + * Recursive Memory Freeing-Helper for Friend-Structures + * @param node Current Node in List + */ +void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node); + +/** + * Friend Finder Thread (Receives Peer Information) + * @param args Length of argp in Bytes (Unused) + * @param argp Argument (Unused) + * @return Unused Value - Return 0 + */ +int friendFinder(); + +/** + * Return Number of active Peers in the same Network as the Local Player + * @return Number of active Peers + */ +int getActivePeerCount(void); + +/** + * Returns the locall Ip of this machine, TODO: Implement the linux version + * @param SocketAddres OUT: local ip + */ +int getLocalIp(sockaddr_in * SocketAddress); + +/** + * Joins two 32 bits number into a 64 bit one + * @param num1: first number + * @param num2: second number + * @return Single 64 bit number + */ +#define firstMask 0x00000000FFFFFFFF +#define secondMask 0xFFFFFFFF00000000 +u64 join32(u32 num1, u32 num2); + +/** + * Splits a 64 bit number into two 32 bit ones + * @param num: The number to be split + * @param buf OUT: Array containing the split numbers + */ +void split64(u64 num, int buff[]); + +/** + * Returns the local mac, TODO: Read from Config file + * @param addr OUT: Local Mac + */ +void getLocalMac(SceNetEtherAddr * addr); + +/** + * PTP Socket Counter + * @return Number of internal PTP Sockets + */ +int getPTPSocketCount(void); + +/** + * Initialize Networking Components for Adhocctl Emulator + * @param adhoc_id Game Product Code + * @param server_ip Server IP + * @return 0 on success or... -1 + */ +int initNetwork(SceNetAdhocctlAdhocId *adhocid); + +/** + * Broadcast MAC Check + * @param addr To-be-checked MAC Address + * @return 1 if Broadcast MAC or... 0 + */ +int isBroadcastMAC(const SceNetEtherAddr * addr); + +/** + * Resolve IP to MAC + * @param ip Peer IP Address + * @param mac OUT: Peer MAC + * @return 0 on success or... ADHOC_NO_ENTRY + */ +int resolveIP(uint32_t ip, SceNetEtherAddr * mac); + +/** + * Resolve MAC to IP + * @param mac Peer MAC Address + * @param ip OUT: Peer IP + * @return 0 on success or... ADHOC_NO_ENTRY + */ +int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip); + +/** + * Check whether Network Name contains only valid symbols + * @param group_name To-be-checked Network Name + * @return 1 if valid or... 0 + */ + int validNetworkName(const SceNetAdhocctlGroupName * groupname); diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 54cec443ad..4c25f675e9 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -20,43 +20,7 @@ // This is a direct port of colorbird code from http://code.google.com/p/aemu/ // All credit goes to him! - -#include "../Config.h" -#include "Core/HLE/HLE.h" -#include "../CoreTiming.h" -#include "Core/HLE/sceNetAdhoc.h" -#include "native/base/timeutil.h" -#include "native/base/mutex.h" - -#include "sceKernel.h" -#include "sceKernelThread.h" -#include "sceKernelMutex.h" -#include "sceUtility.h" -#include "net/resolve.h" - -// Temporary stuff -#include -#ifdef _MSC_VER -#include -#else -#include -#include -#include -#include -#include -#include -#include -#endif -// End of extra includes - -#ifdef _MSC_VER -#define PACK -#else -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -#define closesocket close -#define PACK __attribute__((packed)) -#endif +#include "proAdhoc.h" enum { ERROR_NET_ADHOC_INVALID_SOCKET_ID = 0x80410701, @@ -114,8 +78,6 @@ enum { ERROR_NET_NO_SPACE = 0x80410001 }; -int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown); - enum { PSP_ADHOC_POLL_READY_TO_SEND = 1, PSP_ADHOC_POLL_DATA_AVAILABLE = 2, @@ -129,403 +91,6 @@ static bool netAdhocInited; static bool netAdhocctlInited; static bool netAdhocMatchingInited; -// psp strutcs and definitions -#define ADHOCCTL_MODE_ADHOC 0 -#define ADHOCCTL_MODE_GAMEMODE 1 - -// Event Types for Event Handler -#define ADHOCCTL_EVENT_CONNECT 1 -#define ADHOCCTL_EVENT_DISCONNECT 2 -#define ADHOCCTL_EVENT_SCAN 3 - -// Internal Thread States -#define ADHOCCTL_STATE_DISCONNECTED 0 -#define ADHOCCTL_STATE_CONNECTED 1 -#define ADHOCCTL_STATE_SCANNING 2 -#define ADHOCCTL_STATE_GAMEMODE 3 - -// Kernel Utility Netconf Adhoc Types -#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2 -#define UTILITY_NETCONF_TYPE_CREATE_ADHOC 4 -#define UTILITY_NETCONF_TYPE_JOIN_ADHOC 5 - -// Kernel Utility States -#define UTILITY_NETCONF_STATUS_NONE 0 -#define UTILITY_NETCONF_STATUS_INITIALIZE 1 -#define UTILITY_NETCONF_STATUS_RUNNING 2 -#define UTILITY_NETCONF_STATUS_FINISHED 3 -#define UTILITY_NETCONF_STATUS_SHUTDOWN 4 - -// PTP Connection States -#define PTP_STATE_CLOSED 0 -#define PTP_STATE_LISTEN 1 -#define PTP_STATE_ESTABLISHED 4 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif -// Ethernet Address -#define ETHER_ADDR_LEN 6 -typedef struct SceNetEtherAddr { - uint8_t data[ETHER_ADDR_LEN]; -} PACK SceNetEtherAddr; - - -// Adhoc Virtual Network Name -#define ADHOCCTL_GROUPNAME_LEN 8 -typedef struct SceNetAdhocctlGroupName { - uint8_t data[ADHOCCTL_GROUPNAME_LEN]; -} PACK SceNetAdhocctlGroupName; - -// Virtual Network Host Information -typedef struct SceNetAdhocctlBSSId { - SceNetEtherAddr mac_addr; - uint8_t padding[2]; -} PACK SceNetAdhocctlBSSId; - -// Virtual Network Information -typedef struct SceNetAdhocctlScanInfo { - struct SceNetAdhocctlScanInfo * next; - s32_le channel; - SceNetAdhocctlGroupName group_name; - SceNetAdhocctlBSSId bssid; - s32_le mode; -} PACK SceNetAdhocctlScanInfo; - -// Player Nickname -#define ADHOCCTL_NICKNAME_LEN 128 -typedef struct SceNetAdhocctlNickname { - uint8_t data[ADHOCCTL_NICKNAME_LEN]; -} PACK SceNetAdhocctlNickname; - -// Active Virtual Network Information -typedef struct SceNetAdhocctlParameter { - s32_le channel; - SceNetAdhocctlGroupName group_name; - SceNetAdhocctlBSSId bssid; - SceNetAdhocctlNickname nickname; -} PACK SceNetAdhocctlParameter; - -// Peer Information -typedef struct SceNetAdhocctlPeerInfo { - SceNetAdhocctlPeerInfo * next; - SceNetAdhocctlNickname nickname; - SceNetEtherAddr mac_addr; - u32_le ip_addr; - uint8_t padding[2]; - u64_le last_recv; -} PACK SceNetAdhocctlPeerInfo; - -// Peer Information with u32 pointers -typedef struct SceNetAdhocctlPeerInfoEmu { - u32_le next; // Changed the pointer to u32 - SceNetAdhocctlNickname nickname; - SceNetEtherAddr mac_addr; - u32_le ip_addr; - u32 padding; // Changed the pointer to u32 - u64_le last_recv; -} SceNetAdhocctlPeerInfoEmu; - -// Game Mode Peer List -#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16 -typedef struct SceNetAdhocctlGameModeInfo { - s32_le num; - SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS]; -} PACK SceNetAdhocctlGameModeInfo; -#ifdef _MSC_VER -#pragma pack(pop) -#endif - -// Adhoc ID (Game Product Key) -#define ADHOCCTL_ADHOCID_LEN 9 -typedef struct SceNetAdhocctlAdhocId { - s32_le type; - uint8_t data[ADHOCCTL_ADHOCID_LEN]; - uint8_t padding[3]; -} SceNetAdhocctlAdhocId; - -// Socket Polling Event Listener -struct SceNetAdhocPollSd { - s32_le id; - s32_le events; - s32_le revents; -}; - -// PDP Socket Status -struct SceNetAdhocPdpStat { - struct SceNetAdhocPdpStat * next; - s32_le id; - SceNetEtherAddr laddr; - u16_le lport; - u32_le rcv_sb_cc; -}; - -// PTP Socket Status -struct SceNetAdhocPtpStat { - u32_le next; // Changed the pointer to u32 - s32_le id; - SceNetEtherAddr laddr; - SceNetEtherAddr paddr; - u16_le lport; - u16_le pport; - u32_le snd_sb_cc; - u32_le rcv_sb_cc; - s32_le state; -}; - -// Gamemode Optional Peer Buffer Data -struct SceNetAdhocGameModeOptData { - u32_le size; - u32_le flag; - u64_le last_recv; -}; - -// Gamemode Buffer Status -struct SceNetAdhocGameModeBufferStat { - struct SceNetAdhocGameModeBufferStat * next; - s32_le id; - void * ptr; - u32_le size; - u32_le master; - SceNetAdhocGameModeOptData opt; -}; - - -// Internal Matching Peer Information -typedef struct SceNetAdhocMatchingMemberInternal { - // Next Peer - struct SceNetAdhocMatchingMemberInternal * next; - - // MAC Address - SceNetEtherAddr mac; - - // State Variable - s32_le state; - - // Send in Progress - s32_le sending; - - // Last Heartbeat - u64_le lastping; -} SceNetAdhocMatchingMemberInternal; - - -// Matching handler -struct SceNetAdhocMatchingHandlerArgs { - s32_le id; - s32_le event; - SceNetEtherAddr * peer; - s32_le optlen; - void * opt; -}; - -struct SceNetAdhocMatchingHandler { - u32_le entryPoint; -}; - -// Thread Message Stack Item -typedef struct ThreadMessage -{ - // Next Thread Message - struct ThreadMessage * next; - - // Stack Event Opcode - u32_le opcode; - - // Target MAC Address - SceNetEtherAddr mac; - - // Optional Data Length - s32_le optlen; -} ThreadMessage; - -// Established Peer - -// Context Information -typedef struct SceNetAdhocMatchingContext { - // Next Context - struct SceNetAdhocMatchingContext * next; - - // Externally Visible ID - s32_le id; - - // Matching Mode (HOST, CLIENT, P2P) - s32_le mode; - - // Running Flag (1 = running, 0 = created) - s32_le running; - - // Maximum Number of Peers (for HOST, P2P) - s32_le maxpeers; - - // Local MAC Address - SceNetEtherAddr mac; - - // Peer List for Connectees - SceNetAdhocMatchingMemberInternal * peerlist; - - // Local PDP Port - u16_le port; - - // Local PDP Socket - s32_le socket; - - // Receive Buffer Length - s32_le rxbuflen; - - // Receive Buffer - uint8_t * rxbuf; - - // Hello Broadcast Interval (Microseconds) - u32_le hello_int; - - // Keep-Alive Broadcast Interval (Microseconds) - u32_le keepalive_int; - - // Resend Interval (Microseconds) - u32_le resend_int; - - // Resend-Counter - s32_le resendcounter; - - // Keep-Alive Counter - s32_le keepalivecounter; - - // Event Handler - SceNetAdhocMatchingHandler handler; - - // Hello Data Length - u32_le hellolen; - - // Hello Data - void * hello; - - // Event Caller Thread - s32_le event_thid; - - // IO Handler Thread - s32_le input_thid; - - // Event Caller Thread Message Stack - s32_le event_stack_lock; - ThreadMessage * event_stack; - - // IO Handler Thread Message Stack - s32_le input_stack_lock; - ThreadMessage * input_stack; -} SceNetAdhocMatchingContext; - -// End of psp definitions - -#define OPCODE_PING 0 -#define OPCODE_LOGIN 1 -#define OPCODE_CONNECT 2 -#define OPCODE_DISCONNECT 3 -#define OPCODE_SCAN 4 -#define OPCODE_SCAN_COMPLETE 5 -#define OPCODE_CONNECT_BSSID 6 -#define OPCODE_CHAT 7 - -// PSP Product Code -#define PRODUCT_CODE_LENGTH 9 - -#ifdef _MSC_VER -#pragma pack(push,1) -#endif - -typedef struct -{ - // Game Product Code (ex. ULUS12345) - char data[PRODUCT_CODE_LENGTH]; -} PACK SceNetAdhocctlProductCode; - -// Basic Packet -typedef struct -{ - uint8_t opcode; -} PACK SceNetAdhocctlPacketBase; - -// C2S Login Packet -typedef struct -{ - SceNetAdhocctlPacketBase base; - SceNetEtherAddr mac; - SceNetAdhocctlNickname name; - SceNetAdhocctlProductCode game; -} PACK SceNetAdhocctlLoginPacketC2S; - -// C2S Connect Packet -typedef struct -{ - SceNetAdhocctlPacketBase base; - SceNetAdhocctlGroupName group; -} PACK SceNetAdhocctlConnectPacketC2S; - -// C2S Chat Packet -typedef struct -{ - SceNetAdhocctlPacketBase base; - char message[64]; -} PACK SceNetAdhocctlChatPacketC2S; - -// S2C Connect Packet -typedef struct -{ - SceNetAdhocctlPacketBase base; - SceNetAdhocctlNickname name; - SceNetEtherAddr mac; - uint32_t ip; -} PACK SceNetAdhocctlConnectPacketS2C; - -// S2C Disconnect Packet -typedef struct -{ - SceNetAdhocctlPacketBase base; - uint32_t ip; -} PACK SceNetAdhocctlDisconnectPacketS2C; - -// S2C Scan Packet -typedef struct -{ - SceNetAdhocctlPacketBase base; - SceNetAdhocctlGroupName group; - SceNetEtherAddr mac; -} PACK SceNetAdhocctlScanPacketS2C; - -// S2C Connect BSSID Packet -typedef struct -{ - SceNetAdhocctlPacketBase base; - SceNetEtherAddr mac; -} PACK SceNetAdhocctlConnectBSSIDPacketS2C; - -// S2C Chat Packet -typedef struct -{ - SceNetAdhocctlChatPacketC2S base; - SceNetAdhocctlNickname name; -} PACK SceNetAdhocctlChatPacketS2C; -#ifdef _MSC_VER -#pragma pack(pop) -#endif - -// Aux vars -static int metasocket; -static int eventHandlerUpdate = -1; -static int threadStatus = ADHOCCTL_STATE_DISCONNECTED; -static SceNetAdhocctlParameter parameter; -static std::thread friendFinderThread; -static SceNetAdhocctlPeerInfo * friends = NULL; -static SceNetAdhocctlScanInfo * networks = NULL; -static recursive_mutex peerlock; -static SceNetAdhocPdpStat * pdp[255]; -static SceNetAdhocPtpStat * ptp[255]; -static uint32_t fakePoolSize = 0; -static SceNetAdhocMatchingContext * contexts = NULL; -static int one = 1; -// End of Aux vars - - struct AdhocctlHandler { u32 entryPoint; u32 argument; @@ -574,792 +139,6 @@ void __UpdateAdhocctlHandlers(int flag, int error) { } } -#define firstMask 0x00000000FFFFFFFF -#define secondMask 0xFFFFFFFF00000000 -void split64(u64 num, int buff[]){ - int num1 = (int)(num&firstMask); - int num2 = (int)((num&secondMask)>>32); - buff[0] = num1; - buff[1] = num2; -} - -void __msleep(int mseconds){ -#ifdef _MSVER - Sleep(mseconds); -#else - timespec t_spec; - t_spec.tv_sec = 0; - t_spec.tv_nsec = 100000*mseconds; - nanosleep(&t_spec, NULL); -#endif -} -u64 join32(u32 num1, u32 num2){ - return (u64)num2 << 32 | num1; -} - -// Gets the local mac TODO: Read from config -void __getLocalMac(SceNetEtherAddr * addr){ - uint8_t mac[] = {1, 2, 3, 4, 5, 6}; - memcpy(addr,mac,ETHER_ADDR_LEN); -} - -// This only usefull if the server is running on the same machine as the client -int __getLocalIp(sockaddr_in * SocketAddress){ -#ifdef _MSC_VER - // Get local host name - char szHostName[128] = ""; - - if(::gethostname(szHostName, sizeof(szHostName))) { - // Error handling - } - // Get local IP addresses - struct hostent *pHost = 0; - pHost = ::gethostbyname(szHostName); - if(pHost) { - memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length); - return 0; - } - return -1; -#else - char ip[] = "192.168.12.1"; - SocketAddress->sin_addr.s_addr = inet_addr("192.168.12.1"); - return 0; -#endif -} - -/* chages to the blocking mode of the socket - 1 to set noblocking - 0 to set blocking -*/ -void __change_blocking_mode(int fd, int nonblocking) { - unsigned long on = 1; - unsigned long off = 0; -#ifdef _MSC_VER - if(nonblocking){ - // Change to Non-Blocking Mode - ioctlsocket(fd,FIONBIO,&on); - }else { - // Change to Blocking Mode - ioctlsocket(fd, FIONBIO, &off); - } -#else - if(nonblocking == 1) fcntl(fd, F_SETFL, O_NONBLOCK); - else { - // Get Flags - int flags = fcntl(fd, F_GETFL); - // Remove Non-Blocking Flag - fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); - } -#endif -} - -// Inits all basic net functionality and logins the user to the main server -int __init_network(SceNetAdhocctlAdhocId *adhoc_id){ - int iResult = 0; -#ifdef _MSC_VER - WSADATA data; - iResult = WSAStartup(MAKEWORD(2,2),&data); - if(iResult != NOERROR){ - ERROR_LOG(SCENET, "Wsa failed"); - return iResult; - } -#endif - metasocket = INVALID_SOCKET; - metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); - if(metasocket == INVALID_SOCKET){ - ERROR_LOG(SCENET,"invalid socket"); - return INVALID_SOCKET; - } - struct sockaddr_in server_addr; - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(27312); // Maybe read this from config too - - // Resolve dns - addrinfo * resultAddr; - iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr); - if(iResult != 0){ - printf("Dns error\n"); - return iResult; - } - server_addr.sin_addr.s_addr = ((sockaddr_in *)resultAddr->ai_addr)->sin_addr.s_addr; - iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); - if(iResult == SOCKET_ERROR){ - ERROR_LOG(SCENET,"Socket error"); - return iResult; - } - memset(¶meter,0,sizeof(parameter)); - strcpy((char *)¶meter.nickname.data, g_Config.sNickName.c_str()); - parameter.channel = 1; // Fake Channel 1 - - // Prepare Login Packet - __getLocalMac(¶meter.bssid.mac_addr); - SceNetAdhocctlLoginPacketC2S packet; - packet.base.opcode = OPCODE_LOGIN; - SceNetEtherAddr addres; - __getLocalMac(&addres); - packet.mac = addres; - strcpy((char *)packet.name.data, g_Config.sNickName.c_str()); - memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN); - int sent = send(metasocket, (char*)&packet, sizeof(packet), 0); - __change_blocking_mode(metasocket,1); // Change to non-blocking - if(sent > 0){ - return 0; - }else{ - return -1; - } -} - -/** - * Add Friend to Local List - * @param packet Friend Information - */ -void __addFriend(SceNetAdhocctlConnectPacketS2C * packet) { - // Allocate Structure - SceNetAdhocctlPeerInfo * peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo)); - // Allocated Structure - if(peer != NULL) - { - // Clear Memory - memset(peer, 0, sizeof(SceNetAdhocctlPeerInfo)); - - // Link to existing Peers - peer->next = friends; - - // Save Nickname - peer->nickname = packet->name; - - // Save MAC Address - peer->mac_addr = packet->mac; - - // Save IP Address - peer->ip_addr = packet->ip; - - // Multithreading Lock - peerlock.lock(); - - // Link into Peerlist - friends = peer; - - // Multithreading Unlock - peerlock.unlock(); - } -} - -/** - * Delete Friend from Local List - * @param ip Friend IP - */ -void __deleteFriendByIP(uint32_t ip) { - // Previous Peer Reference - SceNetAdhocctlPeerInfo * prev = NULL; - - // Peer Pointer - SceNetAdhocctlPeerInfo * peer = friends; - - // Iterate Peers - for(; peer != NULL; peer = peer->next) - { - // Found Peer - if(peer->ip_addr == ip) - { - // Multithreading Lock - peerlock.lock(); - - // Unlink Left (Beginning) - if(prev == NULL)friends = peer->next; - - // Unlink Left (Other) - else prev->next = peer->next; - - // Multithreading Unlock - peerlock.unlock(); - - // Free Memory - free(peer); - - // Stop Search - break; - } - - // Set Previous Reference - prev = peer; - } -} - -/** - * Recursive Memory Freeing-Helper for Friend-Structures - * @param node Current Node in List - */ -void __freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) { - // End of List - if(node == NULL) return; - - // Increase Recursion Depth - __freeFriendsRecursive(node->next); - - // Free Memory - free(node); -} - -// Thread that listens to all relevant messages from the server -int __friendFinder(){ - // Receive Buffer - int rxpos = 0; - uint8_t rx[1024]; - - // Chat Packet - SceNetAdhocctlChatPacketC2S chat; - chat.base.opcode = OPCODE_CHAT; - - // Last Ping Time - uint64_t lastping = 0; - - // Last Time Reception got updated - uint64_t lastreceptionupdate = 0; - - uint64_t now; - // Finder Loop - while(netAdhocctlInited) { - // Acquire Network Lock - //_acquireNetworkLock(); - - // Ping Server - now = real_time_now()*1000.0; - if(now - lastping >= 100) { - // Update Ping Time - lastping = now; - - // Prepare Packet - uint8_t opcode = OPCODE_PING; - - // Send Ping to Server - send(metasocket, (const char *)&opcode, 1,0); - } - - // Send Chat Messages - //while(popFromOutbox(chat.message)) - //{ - // // Send Chat to Server - // sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0); - //} - - // Wait for Incoming Data - int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos,0); - - // Free Network Lock - //_freeNetworkLock(); - - // Received Data - if(received > 0) { - // Fix Position - rxpos += received; - - // Log Incoming Traffic - //printf("Received %d Bytes of Data from Server\n", received); - INFO_LOG(SCENET, "Received %d Bytes of Data from Adhoc Server", received); - } - - // Handle Packets - if(rxpos > 0) { - // BSSID Packet - if(rx[0] == OPCODE_CONNECT_BSSID) { - // Enough Data available - if(rxpos >= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) { - // Cast Packet - SceNetAdhocctlConnectBSSIDPacketS2C * packet = (SceNetAdhocctlConnectBSSIDPacketS2C *)rx; - // Update BSSID - parameter.bssid.mac_addr = packet->mac; - // Change State - threadStatus = ADHOCCTL_STATE_CONNECTED; - // Notify Event Handlers - CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0)); - - // Move RX Buffer - memmove(rx, rx + sizeof(SceNetAdhocctlConnectBSSIDPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)); - - // Fix RX Buffer Length - rxpos -= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C); - } - } - - // Chat Packet - else if(rx[0] == OPCODE_CHAT) { - // Enough Data available - if(rxpos >= sizeof(SceNetAdhocctlChatPacketS2C)) { - // Cast Packet - SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx; - - // Fix for Idiots that try to troll the "ME" Nametag -#ifdef _MSC_VER - if(stricmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); -#else - if(strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME"); -#endif - - // Add Incoming Chat to HUD - //printf("Receive chat message %s", packet->base.message); - - // Move RX Buffer - memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C)); - - // Fix RX Buffer Length - rxpos -= sizeof(SceNetAdhocctlChatPacketS2C); - } - } - - // Connect Packet - else if(rx[0] == OPCODE_CONNECT) { - // Enough Data available - if(rxpos >= sizeof(SceNetAdhocctlConnectPacketS2C)) { - // Log Incoming Peer - INFO_LOG(SCENET,"Incoming Peer Data..."); - - // Cast Packet - SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx; - - // Add User - __addFriend(packet); - - // Update HUD User Count -#ifdef LOCALHOST_AS_PEER - setUserCount(_getActivePeerCount()); -#else - //setUserCount(_getActivePeerCount()+1); -#endif - - // Move RX Buffer - memmove(rx, rx + sizeof(SceNetAdhocctlConnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectPacketS2C)); - - // Fix RX Buffer Length - rxpos -= sizeof(SceNetAdhocctlConnectPacketS2C); - } - } - - // Disconnect Packet - else if(rx[0] == OPCODE_DISCONNECT) { - // Enough Data available - if(rxpos >= sizeof(SceNetAdhocctlDisconnectPacketS2C)) { - // Log Incoming Peer Delete Request - INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request..."); - - // Cast Packet - SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx; - - // Delete User by IP - __deleteFriendByIP(packet->ip); - - // Update HUD User Count -#ifdef LOCALHOST_AS_PEER - setUserCount(_getActivePeerCount()); -#else - //setUserCount(_getActivePeerCount()+1); -#endif - - // Move RX Buffer - memmove(rx, rx + sizeof(SceNetAdhocctlDisconnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlDisconnectPacketS2C)); - - // Fix RX Buffer Length - rxpos -= sizeof(SceNetAdhocctlDisconnectPacketS2C); - } - } - - // Scan Packet - else if(rx[0] == OPCODE_SCAN) { - // Enough Data available - if(rxpos >= sizeof(SceNetAdhocctlScanPacketS2C)) { - // Log Incoming Network Information - INFO_LOG(SCENET,"Incoming Group Information..."); - // Cast Packet - SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx; - - // Allocate Structure Data - SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo)); - - // Allocated Structure Data - if(group != NULL) - { - // Clear Memory - memset(group, 0, sizeof(SceNetAdhocctlScanInfo)); - - // Link to existing Groups - group->next = networks; - - // Copy Group Name - group->group_name = packet->group; - - // Set Group Host - group->bssid.mac_addr = packet->mac; - - // Link into Group List - networks = group; - } - - // 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) { - // Log Scan Completion - INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response..."); - - // Change State - threadStatus = ADHOCCTL_STATE_DISCONNECTED; - - // Notify Event Handlers - CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate,join32(ADHOCCTL_EVENT_SCAN, 0)); - //int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++) - //{ - // // Active Handler - // if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]); - //} - - // Move RX Buffer - memmove(rx, rx + 1, sizeof(rx) - 1); - - // Fix RX Buffer Length - rxpos -= 1; - } - } - // Original value was 10 ms, I think 100 is just fine - sleep_ms(100); - } - - // Log Shutdown - INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread"); - - // Return Success - return 0; -} - -/** - * Check whether Network Name contains only valid symbols - * @param group_name To-be-checked Network Name - * @return 1 if valid or... 0 - */ -int __validNetworkName(const SceNetAdhocctlGroupName * group_name) { - // Result - int valid = 1; - - // Name given - if(group_name != NULL) { - // Iterate Name Characters - int i = 0; for(; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) { - // End of Name - if(group_name->data[i] == 0) break; - - // Not a digit - if(group_name->data[i] < '0' || group_name->data[i] > '9') { - // Not 'A' to 'Z' - if(group_name->data[i] < 'A' || group_name->data[i] > 'Z') { - // Not 'a' to 'z' - if(group_name->data[i] < 'a' || group_name->data[i] > 'z') { - // Invalid Name - valid = 0; - } - } - } - } - } - - // Return Result - return valid; -} - -/** - * Local MAC Check - * @param saddr To-be-checked MAC Address - * @return 1 if valid or... 0 - */ -int _IsLocalMAC(const SceNetEtherAddr * addr) { - // Get Local MAC Address - SceNetEtherAddr saddr; - __getLocalMac(&saddr); - //sceNetGetLocalEtherAddr(&saddr); - - // Compare MAC Addresses - int match = memcmp((const void *)addr, (const void *)&saddr, ETHER_ADDR_LEN); - - // Return Result - return (match == 0); -} - -/** - * Resolve IP to MAC - * @param ip Peer IP Address - * @param mac OUT: Peer MAC - * @return 0 on success or... ADHOC_NO_ENTRY - */ -int __resolveIP(uint32_t ip, SceNetEtherAddr * mac) { - sockaddr_in addr; - __getLocalIp(&addr); - uint32 localIp = addr.sin_addr.s_addr; - if(ip == localIp){ - __getLocalMac(mac); - return 0; - } - - // Multithreading Lock - peerlock.lock(); - - // Peer Reference - SceNetAdhocctlPeerInfo * peer = friends; - - // Iterate Peers - for(; peer != NULL; peer = peer->next) { - // Found Matching Peer - if(peer->ip_addr == ip) { - // Copy Data - *mac = peer->mac_addr; - - // Multithreading Unlock - peerlock.unlock(); - - // Return Success - return 0; - } - } - - // Multithreading Unlock - peerlock.unlock(); - - // Peer not found - return ERROR_NET_ADHOC_NO_ENTRY; -} -/** - * Resolve MAC to IP - * @param mac Peer MAC Address - * @param ip OUT: Peer IP - * @return 0 on success or... ADHOC_NO_ENTRY - */ -int __resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) { - // Get Local MAC Address - SceNetEtherAddr localMac; - __getLocalMac(&localMac); - // Local MAC Requested - if(memcmp(&localMac, mac, sizeof(SceNetEtherAddr)) == 0) { - // Get Local IP Address - sockaddr_in sockAddr; - __getLocalIp(&sockAddr); - *ip = sockAddr.sin_addr.s_addr; - return 0; // return succes - } - - // Multithreading Lock - peerlock.lock(); - - // Peer Reference - SceNetAdhocctlPeerInfo * peer = friends; - - // Iterate Peers - for(; peer != NULL; peer = peer->next) { - // Found Matching Peer - if(memcmp(&peer->mac_addr, mac, sizeof(SceNetEtherAddr)) == 0) { - // Copy Data - *ip = peer->ip_addr; - - // Multithreading Unlock - peerlock.unlock(); - - // Return Success - return 0; - } - } - - // Multithreading Unlock - peerlock.unlock(); - - // Peer not found - return ERROR_NET_ADHOC_NO_ENTRY; -} -/** - * PDP Port Check - * @param port To-be-checked Port - * @return 1 if in use or... 0 - */ -int _IsPDPPortInUse(uint16_t port) { - // Iterate Elements - int i = 0; for(; i < 255; i++) if(pdp[i] != NULL && pdp[i]->lport == port) return 1; - - // Unused Port - return 0; -} - -/** - * Broadcast MAC Check - * @param addr To-be-checked MAC Address - * @return 1 if Broadcast MAC or... 0 - */ -int __isBroadcastMAC(const SceNetEtherAddr * addr) { - // Broadcast MAC - if(memcmp(addr->data, "\xFF\xFF\xFF\xFF\xFF\xFF", ETHER_ADDR_LEN) == 0) return 1; - // Normal MAC - return 0; -} - -/** - * Closes & Deletes all PDP Sockets - */ -void __deleteAllPDP(void) { - // Iterate Element - int i = 0; for(; i < 255; i++) { - // Active Socket - if(pdp[i] != NULL) { - // Close Socket - closesocket(pdp[i]->id); - - // Free Memory - free(pdp[i]); - - // Delete Reference - pdp[i] = NULL; - } - } -} - -/** - * Closes & Deletes all PTP Sockets - */ -void __deleteAllPTP(void) { - // Iterate Element - int i = 0; for(; i < 255; i++) { - // Active Socket - if(ptp[i] != NULL) { - // Close Socket - closesocket(ptp[i]->id); - - // Free Memory - free(ptp[i]); - - // Delete Reference - ptp[i] = NULL; - } - } -} - - -/** - * Count Virtual Networks by analyzing the Friend List - * @return Number of Virtual Networks - */ -int __countAvailableNetworks(void) { - // Network Count - int count = 0; - - // Group Reference - SceNetAdhocctlScanInfo * group = networks; - - // Count Groups - for(; group != NULL; group = group->next) count++; - - // Return Network Count - return count; -} - -/** - * Return Number of active Peers in the same Network as the Local Player - * @return Number of active Peers - */ -int __getActivePeerCount(void) { - // Counter - int count = 0; - - // #ifdef LOCALHOST_AS_PEER - // // Increase for Localhost - // count++; - // #endif - - // Peer Reference - SceNetAdhocctlPeerInfo * peer = friends; - - // Iterate Peers - for(; peer != NULL; peer = peer->next) { - // Increase Counter - count++; - } - - // Return Result - return count; -} - -/** - * Find Internal Matching Context for Matching ID - * @param id Matching ID - * @return Matching Context Pointer or... NULL - */ -SceNetAdhocMatchingContext * __findMatchingContext(int id) { - // Iterate Matching Context List - SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { - // Found Matching ID - if(item->id == id) return item; - } - - // Context not found - return NULL; -} - -/** - * Find Free Matching ID - * @return First unoccupied Matching ID - */ -int __findFreeMatchingID(void) { - // Minimum Matching ID - int min = 1; - - // Maximum Matching ID - int max = 0; - - // Find highest Matching ID - SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { - // New Maximum - if(max < item->id) max = item->id; - } - - // Find unoccupied ID - int i = min; for(; i < max; i++) { - // Found unoccupied ID - if(__findMatchingContext(i) == NULL) return i; - } - - // Append at virtual end - return max + 1; -} - - -/** - * PTP Socket Counter - * @return Number of internal PTP Sockets - */ -int __getPTPSocketCount(void) { - // Socket Counter - int counter = 0; - - // Count Sockets - int i = 0; for(; i < 255; i++) if(ptp[i] != NULL) counter++; - - // Return Socket Count - return counter; -} - - -/** - * Check whether PTP Port is in use or not - * @param port To-be-checked Port Number - * @return 1 if in use or... 0 - */ -int __IsPTPPortInUse(uint16_t port) { - // Iterate Sockets - int i = 0; for(; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return 1; - - // Unused Port - return 0; -} - - void __handlerUpdateCallback(u64 userdata, int cycleslate){ int buff[2]; split64(userdata,buff); @@ -1389,10 +168,11 @@ u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { if (netAdhocctlInited) { return ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED; }else{ - if(__init_network((SceNetAdhocctlAdhocId *)Memory::GetPointer(productAddr)) == 0){ + if(initNetwork((SceNetAdhocctlAdhocId *)Memory::GetPointer(productAddr)) == 0){ netAdhocctlInited = true; eventHandlerUpdate = CoreTiming::RegisterEvent("HandlerUpdateEvent", __handlerUpdateCallback); - friendFinderThread = std::thread(__friendFinder); + friendFinderRunning = true; + friendFinderThread = std::thread(friendFinder); }else{ return -1; // Generic error } @@ -1435,7 +215,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) // Valid Arguments are supplied if(mac != NULL && bufferSize > 0) { // Valid MAC supplied - if(_IsLocalMAC(saddr)) { + if(isLocalMAC(saddr)) { //// Unused Port supplied //if(!_IsPDPPortInUse(port)) {} // @@ -1575,7 +355,7 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i setsockopt(socket->id, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)); // Single Target - if(!__isBroadcastMAC(daddr)) + if(!isBroadcastMAC(daddr)) { // Fill in Target Structure sockaddr_in target; @@ -1583,14 +363,14 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i target.sin_port = htons(dport); // Get Peer IP - if(__resolveMAC((SceNetEtherAddr *)daddr, &target.sin_addr.s_addr) == 0) { + if(resolveMAC((SceNetEtherAddr *)daddr, &target.sin_addr.s_addr) == 0) { // Acquire Network Lock //_acquireNetworkLock(); // Send Data - __change_blocking_mode(socket->id, flag); + changeBlockingMode(socket->id, flag); int sent = sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target)); - __change_blocking_mode(socket->id, 0); + changeBlockingMode(socket->id, 0); // Free Network Lock //_freeNetworkLock(); @@ -1643,9 +423,9 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i uint8_t * thing = (uint8_t *)&peer->ip_addr; // printf("Attempting PDP Send to %u.%u.%u.%u on Port %u\n", thing[0], thing[1], thing[2], thing[3], dport); // Send Data - __change_blocking_mode(socket->id, flag); + changeBlockingMode(socket->id, flag); sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target)); - __change_blocking_mode(socket->id, 0); + changeBlockingMode(socket->id, 0); } // Free Peer Lock @@ -1743,9 +523,9 @@ int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLen //_acquireNetworkLock(); // Receive Data - __change_blocking_mode(socket->id,flag); + changeBlockingMode(socket->id,flag); int received = recvfrom(socket->id, (char *)buf, *len,0,(sockaddr *)&sin, &sinlen); - __change_blocking_mode(socket->id,0); + changeBlockingMode(socket->id,0); // Received Data if(received > 0) { @@ -1753,7 +533,7 @@ int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *dataLen SceNetEtherAddr mac; // Find Peer MAC - if(__resolveIP(sin.sin_addr.s_addr, &mac) == 0) { + if(resolveIP(sin.sin_addr.s_addr, &mac) == 0) { // Provide Sender Information *saddr = mac; *sport = htons(sin.sin_port); @@ -1895,7 +675,7 @@ int sceNetAdhocctlGetScanInfo(u32 size, u32 bufAddr) { peerlock.lock(); // Length Returner Mode - if(buf == NULL) *buflen = __countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfo); + if(buf == NULL) *buflen = countAvailableNetworks() * sizeof(SceNetAdhocctlScanInfo); // Normal Information Mode else { @@ -2028,7 +808,7 @@ u32 sceNetAdhocctlDisconnect() { peerlock.lock(); // Clear Peer List - __freeFriendsRecursive(friends); + freeFriendsRecursive(friends); // Delete Peer Reference friends = NULL; @@ -2064,6 +844,7 @@ int sceNetAdhocctlTerm() { INFO_LOG(SCENET, "sceNetAdhocctlTerm()"); if(netAdhocctlInited){ netAdhocctlInited = false; + friendFinderRunning = false; if(friendFinderThread.joinable()){ friendFinderThread.join(); } @@ -2104,7 +885,7 @@ int sceNetAdhocctlCreate(const char *groupName) { // Library initialized if(netAdhocctlInited) { // Valid Argument - if(__validNetworkName(groupNameStruct)) { + if(validNetworkName(groupNameStruct)) { // Disconnected State if(threadStatus == ADHOCCTL_STATE_DISCONNECTED) { // Set Network Name @@ -2174,10 +955,10 @@ int sceNetAdhocTerm() { // Library is initialized if(netAdhocInited) { // Delete PDP Sockets - __deleteAllPDP(); + deleteAllPDP(); // Delete PTP Sockets - __deleteAllPTP(); + deleteAllPTP(); // Delete Gamemode Buffer //_deleteAllGMB(); @@ -2217,7 +998,7 @@ int sceNetAdhocGetPtpStat(u32 structSize, u32 structAddr) { // Length Returner Mode if(buflen != NULL && !Memory::IsValidAddress(structAddr)) { // Return Required Size - *buflen = sizeof(SceNetAdhocPtpStat) * __getPTPSocketCount(); + *buflen = sizeof(SceNetAdhocPtpStat) * getPTPSocketCount(); // Success return 0; @@ -2226,7 +1007,7 @@ int sceNetAdhocGetPtpStat(u32 structSize, u32 structAddr) { // Status Returner Mode else if(buflen != NULL && Memory::IsValidAddress(structAddr)) { // Socket Count - int socketcount = __getPTPSocketCount(); + int socketcount = getPTPSocketCount(); SceNetAdhocPtpStat * buf = (SceNetAdhocPtpStat *)Memory::GetPointer(structAddr); // Figure out how many Sockets we will return @@ -2294,7 +1075,7 @@ int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, int dp // Library is initialized if(netAdhocInited) { // Valid Addresses - if(saddr != NULL && _IsLocalMAC(saddr) && daddr != NULL && !__isBroadcastMAC(daddr)) { + if(saddr != NULL && isLocalMAC(saddr) && daddr != NULL && !isBroadcastMAC(daddr)) { // Random Port required if(sport == 0) { // Find unused Port @@ -2305,7 +1086,7 @@ int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, int dp } // Valid Ports - if(!__IsPTPPortInUse(sport) && dport != 0) { + if(!isPTPPortInUse(sport) && dport != 0) { // Valid Arguments if(bufsize > 0 && rexmt_int > 0 && rexmt_cnt > 0) { // Create Infrastructure Socket @@ -2435,7 +1216,7 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou // Switch to Nonblocking Behaviour if(nbio == 0) { // Overwrite Socket Option - __change_blocking_mode(socket->id,1); + changeBlockingMode(socket->id,1); } // Accept Connection @@ -2459,7 +1240,7 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou // Restore Blocking Behaviour if(nbio == 0) { // Restore Socket Option - __change_blocking_mode(socket->id,0); + changeBlockingMode(socket->id,0); } // Accepted New Connection @@ -2473,7 +1254,7 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou SceNetEtherAddr mac; // Find Peer MAC - if(__resolveIP(peeraddr.sin_addr.s_addr, &mac) == 0) { + if(resolveIP(peeraddr.sin_addr.s_addr, &mac) == 0) { // Allocate Memory SceNetAdhocPtpStat * internal = (SceNetAdhocPtpStat *)malloc(sizeof(SceNetAdhocPtpStat)); @@ -2491,7 +1272,7 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou internal->id = newsocket; // Copy Local Address Data to Structure - __getLocalMac(&internal->laddr); + getLocalMac(&internal->laddr); internal->lport = htons(local.sin_port); // Copy Peer Address Data to Structure @@ -2577,7 +1358,7 @@ int sceNetAdhocPtpConnect(int id, int timeout, int flag) { sin.sin_port = htons(socket->pport); // Grab Peer IP - if(__resolveMAC(&socket->paddr, &sin.sin_addr.s_addr) == 0) { + if(resolveMAC(&socket->paddr, &sin.sin_addr.s_addr) == 0) { // Grab Nonblocking Flag uint32_t nbio = 0; int fileflags = fcntl(socket->id,F_GETFL,O_NONBLOCK); @@ -2585,7 +1366,7 @@ int sceNetAdhocPtpConnect(int id, int timeout, int flag) { // Switch to Nonblocking Behaviour if(nbio == 0) { // Overwrite Socket Option - __change_blocking_mode(socket->id, 1); + changeBlockingMode(socket->id, 1); } // Connect Socket to Peer (Nonblocking) @@ -2597,7 +1378,7 @@ int sceNetAdhocPtpConnect(int id, int timeout, int flag) { // Restore Blocking Behaviour if(nbio == 0) { // Restore Socket Option - __change_blocking_mode(socket->id,0); + changeBlockingMode(socket->id,0); } // Instant Connection (Lucky!) @@ -2720,7 +1501,7 @@ int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int rexmt_i SceNetEtherAddr * saddr = (SceNetEtherAddr *)srcmac; if(netAdhocInited) { // Valid Address - if(saddr != NULL && _IsLocalMAC(saddr)) + if(saddr != NULL && isLocalMAC(saddr)) { // Random Port required if(sport == 0) { @@ -2733,7 +1514,7 @@ int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int rexmt_i } // Valid Ports - if(!__IsPTPPortInUse(sport)) { + if(!isPTPPortInUse(sport)) { // Valid Arguments if(bufsize > 0 && rexmt_int > 0 && rexmt_cnt > 0 && backlog > 0) { @@ -2854,10 +1635,10 @@ int sceNetAdhocPtpSend(int id, u32 dataAddr, u32 dataSizeAddr, int timeout, int // _acquireNetworkLock(); // Send Data - __change_blocking_mode(socket->id, flag); + changeBlockingMode(socket->id, flag); int sent = send(socket->id, data, *len, 0); int error = errno; - __change_blocking_mode(socket->id, 0); + changeBlockingMode(socket->id, 0); // Free Network Lock // _freeNetworkLock(); @@ -2935,10 +1716,10 @@ int sceNetAdhocPtpRecv(int id, u32 data, u32 dataSizeAddr, int timeout, int flag // _acquireNetworkLock(); // Receive Data - __change_blocking_mode(socket->id, flag); + changeBlockingMode(socket->id, flag); int received = recv(socket->id, buf, *len, 0); int error = errno; - __change_blocking_mode(socket->id, 0); + changeBlockingMode(socket->id, 0); // Free Network Lock // _freeNetworkLock(); @@ -3090,7 +1871,7 @@ int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int // Allocated Memory if(context != NULL) { // Create PDP Socket - SceNetEtherAddr localmac; __getLocalMac(&localmac); + SceNetEtherAddr localmac; getLocalMac(&localmac); const char * mac = (const char *)&localmac.data; int socket = sceNetAdhocPdpCreate(mac, (uint32_t)port, rxbuflen, 0); // Created PDP Socket @@ -3107,7 +1888,7 @@ int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbuflen, int memset(context->rxbuf, 0, rxbuflen); // Fill in Context Data - context->id = __findFreeMatchingID(); + context->id = findFreeMatchingID(); context->mode = mode; context->maxpeers = maxnum; context->port = port; @@ -3301,7 +2082,7 @@ int sceNetAdhocctlGetPeerList(u32 sizeAddr, u32 bufAddr) { peerlock.lock(); // Length Calculation Mode - if(buf == NULL) *buflen = __getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfoEmu); + if(buf == NULL) *buflen = getActivePeerCount() * sizeof(SceNetAdhocctlPeerInfoEmu); // Normal Mode else { From 0f7f90d0acab4b885604a59bfffea63a4e171412 Mon Sep 17 00:00:00 2001 From: Kyhel Date: Mon, 25 Nov 2013 02:57:08 +0100 Subject: [PATCH 17/21] =?UTF-8?q?Added=20windows=20changes=20for=20a=20uni?= =?UTF-8?q?fied=20build.=20Added=20Dialog=20fix=20which=20prevented=20from?= =?UTF-8?q?=20saving=20after=20going=20online.=20Added=20windows=20=C2=AB?= =?UTF-8?q?=C2=A0errno=C2=A0=C2=BB=20use=20redefinition=20to=20suit=20WSAG?= =?UTF-8?q?etLastError=20and=20protocl=20needs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Common/FileUtil.cpp | 5 ++- Core/Config.cpp | 6 ++-- Core/Config.h | 3 +- Core/Dialog/PSPNetconfDialog.cpp | 7 ++++- Core/HLE/proAdhoc.cpp | 15 ++++++--- Core/HLE/proAdhoc.h | 9 ++++++ Core/HLE/sceNet.cpp | 3 +- Core/HLE/sceNetAdhoc.cpp | 53 ++++++++++++++++++++------------ 8 files changed, 72 insertions(+), 29 deletions(-) diff --git a/Common/FileUtil.cpp b/Common/FileUtil.cpp index 24f151ba92..46735bd75c 100644 --- a/Common/FileUtil.cpp +++ b/Common/FileUtil.cpp @@ -37,7 +37,10 @@ #include #include #include -#endif +#if !defined(IOS) +#include +#endif // !defined(IOS) +#endif // __APPLE__ #include "util/text/utf8.h" diff --git a/Core/Config.cpp b/Core/Config.cpp index 13c905c309..99aa6d772c 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -255,7 +255,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); pspConfig->Get("NickName", &sNickName, "PPSSPP"); - pspConfig->Get("proAdhocServer", &proAdhocServer, "localhost"); + pspConfig->Get("proAdhocServer", &proAdhocServer, "localhost"); + pspConfig->Get("MacAddress", &localMacAddress, "01:02:03:04:05:06"); pspConfig->Get("Language", &iLanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); pspConfig->Get("TimeFormat", &iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR); pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD); @@ -452,7 +453,8 @@ void Config::Save() { IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); pspConfig->Set("NickName", sNickName.c_str()); - pspConfig->Set("proAdhocServer", proAdhocServer.c_str()); + pspConfig->Set("proAdhocServer", proAdhocServer.c_str()); + pspConfig->Set("MacAddress", localMacAddress.c_str()); pspConfig->Set("Language", iLanguage); pspConfig->Set("TimeFormat", iTimeFormat); pspConfig->Set("DateFormat", iDateFormat); diff --git a/Core/Config.h b/Core/Config.h index f9731f5641..41eead2a38 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -184,7 +184,8 @@ public: // SystemParam std::string sNickName; - std::string proAdhocServer; + std::string proAdhocServer; + std::string localMacAddress; int iLanguage; int iTimeFormat; int iDateFormat; diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index f4b9a832ea..31775cefa0 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -50,7 +50,12 @@ int PSPNetconfDialog::Update(int animSpeed) { request.netAction == NETCONF_JOIN_ADHOC){ if(request.NetconfData != NULL){ Shutdown(true); - return sceNetAdhocctlCreate(request.NetconfData->groupName); + if(sceNetAdhocctlCreate(request.NetconfData->groupName) == 0) + { + status = SCE_UTILITY_STATUS_FINISHED; + return 0; + } + return -1; } } return 0; diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index fa68024350..4dcd969d1e 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -497,15 +497,15 @@ int getLocalIp(sockaddr_in * SocketAddress){ } return -1; #else - char ip[] = "192.168.12.1"; SocketAddress->sin_addr.s_addr = inet_addr("192.168.12.1"); return 0; #endif } void getLocalMac(SceNetEtherAddr * addr){ - uint8_t mac[] = {1, 2, 3, 4, 5, 6}; + uint8_t mac[] = {1, 2, 3, 4, 5, 5}; memcpy(addr,mac,ETHER_ADDR_LEN); + printf("mem copied\n"); } int getPTPSocketCount(void) { @@ -541,13 +541,20 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ // Resolve dns addrinfo * resultAddr; + addrinfo * ptr; + in_addr serverIp; iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr); if(iResult != 0){ ERROR_LOG(SCENET, "Dns error\n"); return iResult; } - server_addr.sin_addr.s_addr = ((sockaddr_in *)resultAddr->ai_addr)->sin_addr.s_addr; - iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); + for(ptr = resultAddr; ptr != NULL; ptr = ptr->ai_next){ + switch(ptr->ai_family){ + case AF_INET: + serverIp = ((sockaddr_in *)ptr->ai_addr)->sin_addr; + } + } + server_addr.sin_addr = serverIp; iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr)); if(iResult == SOCKET_ERROR){ ERROR_LOG(SCENET,"Socket error"); return iResult; diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index 7ed7185d4b..9d66d595c5 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -13,7 +13,12 @@ #include "sceKernelMutex.h" #include "sceUtility.h" #include "net/resolve.h" + +#ifdef _MSC_VER +#include +#else #include +#endif // Net stuff #ifdef _MSC_VER @@ -29,6 +34,10 @@ #endif #ifdef _MSC_VER #define PACK +#define errno WSAGetLastError() +#define EAGAIN WSAEWOULDBLOCK +#define EINPROGRESS WSAEWOULDBLOCK +#define EISCONN WSAEISCONN #else #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index b224de26e8..59816449ec 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -18,6 +18,7 @@ #include "Common/ChunkFile.h" #include "HLE.h" #include "../MIPS/MIPS.h" +#include "../Config.h" #include "sceKernel.h" #include "sceKernelThread.h" @@ -131,7 +132,7 @@ u32 sceNetTerm() { u32 sceWlanGetEtherAddr(u32 addrAddr) { // TODO: Read from config - static const u8 fakeEtherAddr[6] = { 1, 2, 3, 4, 5, 6 }; + static const u8 fakeEtherAddr[6] = { 1, 2, 3, 4, 5, 5 }; DEBUG_LOG(SCENET, "sceWlanGetEtherAddr(%08x)", addrAddr); for (int i = 0; i < 6; i++) Memory::Write_U8(fakeEtherAddr[i], addrAddr + i); diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 4c25f675e9..684b6283a6 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -139,6 +139,15 @@ void __UpdateAdhocctlHandlers(int flag, int error) { } } +int getBlockingFlag(int id){ +#ifdef _MSC_VER + return 0; +#else + int sockflag = fcntl(id, F_GETFL, O_NONBLOCK); + return sockflag & O_NONBLOCK; +#endif +} + void __handlerUpdateCallback(u64 userdata, int cycleslate){ int buff[2]; split64(userdata,buff); @@ -363,7 +372,7 @@ int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int len, i target.sin_port = htons(dport); // Get Peer IP - if(resolveMAC((SceNetEtherAddr *)daddr, &target.sin_addr.s_addr) == 0) { + if(resolveMAC((SceNetEtherAddr *)daddr, (uint32_t *)&target.sin_addr.s_addr) == 0) { // Acquire Network Lock //_acquireNetworkLock(); @@ -1096,7 +1105,7 @@ int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, int dp // Valid Socket produced if(tcpsocket > 0) { // Enable Port Re-use - setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)); // Binding Information for local Port sockaddr_in addr; @@ -1202,17 +1211,22 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou // Address Information sockaddr_in peeraddr; memset(&peeraddr, 0, sizeof(peeraddr)); +#ifdef _MSC_VER + int peeraddrlen = sizeof(peeraddr); +#else uint32_t peeraddrlen = sizeof(peeraddr); - +#endif // Local Address Information sockaddr_in local; memset(&local, 0, sizeof(local)); +#ifdef _MSC_VER + int locallen = sizeof(local); +#else uint32_t locallen = sizeof(local); +#endif // Grab Nonblocking Flag - uint32_t nbio = 0; - int sockflag = fcntl(socket->id, F_GETFL, O_NONBLOCK); - nbio = sockflag & O_NONBLOCK; + uint32_t nbio = getBlockingFlag(socket->id); // Switch to Nonblocking Behaviour if(nbio == 0) { // Overwrite Socket Option @@ -1246,7 +1260,7 @@ int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int timeou // Accepted New Connection if(newsocket > 0) { // Enable Port Re-use - setsockopt(newsocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + setsockopt(newsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)); // Grab Local Address if(getsockname(newsocket, (sockaddr *)&local, &locallen) == 0) { @@ -1358,11 +1372,9 @@ int sceNetAdhocPtpConnect(int id, int timeout, int flag) { sin.sin_port = htons(socket->pport); // Grab Peer IP - if(resolveMAC(&socket->paddr, &sin.sin_addr.s_addr) == 0) { + if(resolveMAC(&socket->paddr, (uint32_t *)&sin.sin_addr.s_addr) == 0) { // Grab Nonblocking Flag - uint32_t nbio = 0; - int fileflags = fcntl(socket->id,F_GETFL,O_NONBLOCK); - nbio = fileflags & O_NONBLOCK; + uint32_t nbio = getBlockingFlag(socket->id); // Switch to Nonblocking Behaviour if(nbio == 0) { // Overwrite Socket Option @@ -1403,8 +1415,11 @@ int sceNetAdhocPtpConnect(int id, int timeout, int flag) { // Peer Information (for Connection-Polling) sockaddr_in peer; memset(&peer, 0, sizeof(peer)); +#ifdef _MSC_VER + int peerlen = sizeof(peer); +#else uint32_t peerlen = sizeof(peer); - +#endif // Wait for Connection while((timeout == 0 || ( (uint32_t)(real_time_now()*1000.0) - starttime) < timeout) && getpeername(socket->id, (sockaddr *)&peer, &peerlen) != 0) { // Wait 1ms @@ -1524,7 +1539,7 @@ int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int rexmt_i // Valid Socket produced if(tcpsocket > 0) { // Enable Port Re-use - setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)); // Binding Information for local Port sockaddr_in addr; @@ -1629,16 +1644,16 @@ int sceNetAdhocPtpSend(int id, u32 dataAddr, u32 dataSizeAddr, int timeout, int if(flag) timeout = 0; // Apply Send Timeout Settings to Socket - setsockopt(socket->id, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + setsockopt(socket->id, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)); // Acquire Network Lock // _acquireNetworkLock(); // Send Data - changeBlockingMode(socket->id, flag); + changeBlockingMode(socket->id, flag); int sent = send(socket->id, data, *len, 0); - int error = errno; - changeBlockingMode(socket->id, 0); + int error = errno; + changeBlockingMode(socket->id, 0); // Free Network Lock // _freeNetworkLock(); @@ -1710,14 +1725,14 @@ int sceNetAdhocPtpRecv(int id, u32 data, u32 dataSizeAddr, int timeout, int flag if(flag) timeout = 0; // Apply Send Timeout Settings to Socket - setsockopt(socket->id, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(socket->id, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)); // Acquire Network Lock // _acquireNetworkLock(); // Receive Data changeBlockingMode(socket->id, flag); - int received = recv(socket->id, buf, *len, 0); + int received = recv(socket->id, (char *)buf, *len, 0); int error = errno; changeBlockingMode(socket->id, 0); From 3e4e0fc2037c88687afb929e01fc3a0691ccb677 Mon Sep 17 00:00:00 2001 From: Kyhel Date: Mon, 25 Nov 2013 03:03:34 +0100 Subject: [PATCH 18/21] =?UTF-8?q?Removed=20useless=20printf,=20and=20also,?= =?UTF-8?q?=20last=20commit=20i=20added=20a=20Config=20for=20MacAddress,?= =?UTF-8?q?=20but=20i=20didn=E2=80=99t=20yet=20find=20a=20way=20to=20use?= =?UTF-8?q?=20it=20properly.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/HLE/proAdhoc.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 4dcd969d1e..d516fe5745 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -505,7 +505,6 @@ int getLocalIp(sockaddr_in * SocketAddress){ void getLocalMac(SceNetEtherAddr * addr){ uint8_t mac[] = {1, 2, 3, 4, 5, 5}; memcpy(addr,mac,ETHER_ADDR_LEN); - printf("mem copied\n"); } int getPTPSocketCount(void) { From a627f2656ad334cb1c850787269e25f9aa5dd2f4 Mon Sep 17 00:00:00 2001 From: Kyhel Date: Mon, 25 Nov 2013 03:16:17 +0100 Subject: [PATCH 19/21] Tested build on windows x64 --- Core/Core.vcxproj | 2 ++ Core/Core.vcxproj.filters | 8 +++++++- Windows/PPSSPP.vcxproj | 1 + ext/zlib/zlib.vcxproj | 1 + headless/Headless.vcxproj | 1 + unittest/UnitTests.vcxproj | 2 +- 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 6b04261733..7bfe51efb3 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -194,6 +194,7 @@ + @@ -449,6 +450,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index f336712f86..c178a9406b 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -496,6 +496,9 @@ Dialog + + HLE\Libraries + @@ -912,6 +915,9 @@ Dialog + + HLE\Libraries + @@ -919,4 +925,4 @@ - + \ No newline at end of file diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index ed527c4a07..24a1f255d6 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -38,6 +38,7 @@ Application Unicode false + Windows7.1SDK Application diff --git a/ext/zlib/zlib.vcxproj b/ext/zlib/zlib.vcxproj index e3499d2ec0..ed20a4c517 100644 --- a/ext/zlib/zlib.vcxproj +++ b/ext/zlib/zlib.vcxproj @@ -75,6 +75,7 @@ false false Unicode + Windows7.1SDK diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj index 238aa92bec..8000da2518 100644 --- a/headless/Headless.vcxproj +++ b/headless/Headless.vcxproj @@ -46,6 +46,7 @@ false false Unicode + Windows7.1SDK diff --git a/unittest/UnitTests.vcxproj b/unittest/UnitTests.vcxproj index 0ef1bb9656..30ba95543f 100644 --- a/unittest/UnitTests.vcxproj +++ b/unittest/UnitTests.vcxproj @@ -47,7 +47,7 @@ Application false - v100 + Windows7.1SDK false Unicode From a4135dadbcfdcee9ce12f804274a894257e745ad Mon Sep 17 00:00:00 2001 From: Kyhel Date: Mon, 25 Nov 2013 04:46:03 +0100 Subject: [PATCH 20/21] Added MAC address from config --- Core/HLE/proAdhoc.cpp | 6 ++++-- Core/HLE/sceNet.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index d516fe5745..fe446c68e8 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -503,8 +503,10 @@ int getLocalIp(sockaddr_in * SocketAddress){ } void getLocalMac(SceNetEtherAddr * addr){ - uint8_t mac[] = {1, 2, 3, 4, 5, 5}; - memcpy(addr,mac,ETHER_ADDR_LEN); + //MAC Adress from config + uint8_t mac[ETHER_ADDR_LEN]; + sscanf(g_Config.localMacAddress.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); + memcpy(addr,mac,ETHER_ADDR_LEN); } int getPTPSocketCount(void) { diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 59816449ec..8212f025eb 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -131,11 +131,12 @@ u32 sceNetTerm() { } u32 sceWlanGetEtherAddr(u32 addrAddr) { - // TODO: Read from config - static const u8 fakeEtherAddr[6] = { 1, 2, 3, 4, 5, 5 }; + //MAC Adress from config + uint8_t mac[6]; + sscanf(g_Config.localMacAddress.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); DEBUG_LOG(SCENET, "sceWlanGetEtherAddr(%08x)", addrAddr); for (int i = 0; i < 6; i++) - Memory::Write_U8(fakeEtherAddr[i], addrAddr + i); + Memory::Write_U8(mac[i], addrAddr + i); return 0; } From c07ca43fb341fd509a104a337e3faf2d555fe960 Mon Sep 17 00:00:00 2001 From: Kyhel Date: Mon, 25 Nov 2013 06:50:23 +0100 Subject: [PATCH 21/21] Updated README --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bd78169b42..1dfa7b2863 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,12 @@ yet. Also, it uses a port < 1000 and thats reserved for admin apps on linux, run as sudo "solves" it, but it's far from ideal. * Pacman World Rally: Works too. -Oh, and it probably only compiles on linux for now. +Update (Kyhel) : +--------------- +* Now compiles on both Mac OSX and Windows. For more details on how to play and build +go to see there http://forums.ppsspp.org/showthread.php?tid=3595&pid=59241#pid59241 +* Got it tested windows <-> mac osx <-> psp, it works +* Monster Hunter 3rd HD works too, as well as God Eater Burst. PPSSPP - a fast and portable PSP emulator =========================================