// Copyright (c) 2013- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819#include "Common/Net/SocketCompat.h"2021#ifdef _MSC_VER22#define PACK // on MSVC we use #pragma pack() instead so let's kill this.23#else24#define PACK __attribute__((packed))25#endif2627#include <atomic>28#include <mutex>29#include <thread>30#include <climits>3132#include "Common/Net/Resolve.h"33#include "Common/Serialize/Serializer.h"34#include "Core/MemMap.h"35#include "Core/HLE/sceKernelThread.h"36#include "Core/HLE/sceKernel.h"37#include "Core/HLE/sceKernelMutex.h"38#include "Core/HLE/sceUtility.h"3940#define IsMatch(buf1, buf2) (memcmp(&buf1, &buf2, sizeof(buf1)) == 0)4142// Server Listening Port43#define SERVER_PORT 273124445// Default GameMode definitions46#define ADHOC_GAMEMODE_PORT 3100047#define GAMEMODE_UPDATE_INTERVAL 500 // 12000 usec on JPCSP, but lower value works better on BattleZone (in order to get full speed 60 FPS)48#define GAMEMODE_INIT_DELAY 1000049#define GAMEMODE_SYNC_TIMEOUT 25000050#define GAMEMODE_WAITID 0x2001 // Just to differentiate WaitID with other ID on WAITTYPE_NET5152// GameMode Type53#define ADHOCCTL_GAMETYPE_1A 154#define ADHOCCTL_GAMETYPE_1B 255#define ADHOCCTL_GAMETYPE_2A 35657// psp strutcs and definitions58#define ADHOCCTL_MODE_NONE -1 // We only use this internally as initial value before attempting to create/connect/join/scan any group59#define ADHOCCTL_MODE_NORMAL 0 // ADHOCCTL_MODE_ADHOC60#define ADHOCCTL_MODE_GAMEMODE 16162// Event Types for Event Handler63#define ADHOCCTL_EVENT_ERROR 0 // Used to pass error code to Adhocctl Handler?64#define ADHOCCTL_EVENT_CONNECT 165#define ADHOCCTL_EVENT_DISCONNECT 266#define ADHOCCTL_EVENT_SCAN 367#define ADHOCCTL_EVENT_GAME 468#define ADHOCCTL_EVENT_DISCOVER 569#define ADHOCCTL_EVENT_WOL 670#define ADHOCCTL_EVENT_WOL_INTERRUPT 77172// Internal Thread States73#define ADHOCCTL_STATE_DISCONNECTED 074#define ADHOCCTL_STATE_CONNECTED 175#define ADHOCCTL_STATE_SCANNING 276#define ADHOCCTL_STATE_GAMEMODE 377#define ADHOCCTL_STATE_DISCOVER 478#define ADHOCCTL_STATE_WOL 57980// ProductType ( extracted from SSID along with ProductId & GroupName, Pattern = "PSP_([AXS])(.........)_([LG])_(.*)" )81#define PSP_ADHOCCTL_TYPE_COMMERCIAL 082#define PSP_ADHOCCTL_TYPE_DEBUG 183#define PSP_ADHOCCTL_TYPE_SYSTEM 2 // Used for GameSharing?8485// Kernel Utility Netconf Adhoc Types86#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 287#define UTILITY_NETCONF_TYPE_CREATE_ADHOC 488#define UTILITY_NETCONF_TYPE_JOIN_ADHOC 58990// Kernel Utility States91#define UTILITY_NETCONF_STATUS_NONE 092#define UTILITY_NETCONF_STATUS_INITIALIZE 193#define UTILITY_NETCONF_STATUS_RUNNING 294#define UTILITY_NETCONF_STATUS_FINISHED 395#define UTILITY_NETCONF_STATUS_SHUTDOWN 49697// Event Flags98#define ADHOC_EV_SEND 0x000199#define ADHOC_EV_RECV 0x0002100#define ADHOC_EV_CONNECT 0x0004101#define ADHOC_EV_ACCEPT 0x0008102#define ADHOC_EV_FLUSH 0x0010103#define ADHOC_EV_INVALID 0x0100 // ignored on events but can be raised on revents? similar to POLLNVAL on posix poll?104#define ADHOC_EV_DELETE 0x0200 // ignored on events but can be raised on revents? similar to POLLERR on posix poll?105#define ADHOC_EV_ALERT 0x0400106#define ADHOC_EV_DISCONNECT 0x0800 // ignored on events but can be raised on revents? similar to POLLHUP on posix poll?107108// PTP Connection States109#define ADHOC_PTP_STATE_CLOSED 0110#define ADHOC_PTP_STATE_LISTEN 1111#define ADHOC_PTP_STATE_SYN_SENT 2 // 3-way handshake normally: [client]send SYN -> [server]recv SYN and reply with ACK+SYN -> [client]recv SYN and reply with ACK -> Established112#define ADHOC_PTP_STATE_SYN_RCVD 3113#define ADHOC_PTP_STATE_ESTABLISHED 4114115// Nonblocking Flag for Adhoc socket API116#define ADHOC_F_NONBLOCK 0x0001117// Alert Flags118#define ADHOC_F_ALERTSEND 0x0010119#define ADHOC_F_ALERTRECV 0x0020120#define ADHOC_F_ALERTPOLL 0x0040121#define ADHOC_F_ALERTCONNECT 0x0080122#define ADHOC_F_ALERTACCEPT 0x0100123#define ADHOC_F_ALERTFLUSH 0x0200124#define ADHOC_F_ALERTALL (ADHOC_F_ALERTSEND | ADHOC_F_ALERTRECV | ADHOC_F_ALERTPOLL | ADHOC_F_ALERTCONNECT | ADHOC_F_ALERTACCEPT | ADHOC_F_ALERTFLUSH)125126/* PDP Maximum Fragment Size */127#define PSP_ADHOC_PDP_MFS 1444128129/* PDP Maximum Transfer Unit */130#define PSP_ADHOC_PDP_MTU 65523131132/* PTP Maximum Segment Size */133#define PSP_ADHOC_PTP_MSS 1444134135/* GameMode Optional Data */136#define ADHOC_GAMEMODE_F_UPDATE 0x00000001137138// Timeouts139#define PSP_ADHOCCTL_RECV_TIMEOUT 100000140#define PSP_ADHOCCTL_PING_TIMEOUT 2000000141142#ifdef _MSC_VER143#pragma pack(push, 1)144#endif145// Ethernet Address146#define ETHER_ADDR_LEN 6147typedef struct SceNetEtherAddr {148uint8_t data[ETHER_ADDR_LEN];149} PACK SceNetEtherAddr;150151inline bool operator<(const SceNetEtherAddr& lhs, const SceNetEtherAddr& rhs) {152uint64_t l = 0;153uint64_t r = 0;154const uint8_t* lp = lhs.data;155const uint8_t* rp = rhs.data;156for (int8_t i = 5; i >= 0; i--) {157int8_t sb = (CHAR_BIT * i);158l |= (uint64_t)*lp++ << sb;159r |= (uint64_t)*rp++ << sb;160}161return (l < r);162}163164// Broadcast MAC165extern uint8_t broadcastMAC[ETHER_ADDR_LEN];166167// Malloc Pool Information168typedef struct SceNetMallocStat {169s32_le pool; // On Vantage Master Portable this is 0x1ffe0 on sceNetGetMallocStat, while the poolSize arg on sceNetInit was 0x20000170s32_le maximum; // On Vantage Master Portable this is 0x4050, Footprint of Highest amount allocated so far?171s32_le free; // On Vantage Master Portable this is 0x1f300, VMP compares this value with required size before sending data172} PACK SceNetMallocStat;173174// Adhoc Virtual Network Name175#define ADHOCCTL_GROUPNAME_LEN 8176typedef struct SceNetAdhocctlGroupName {177uint8_t data[ADHOCCTL_GROUPNAME_LEN];178} PACK SceNetAdhocctlGroupName;179180// Virtual Network Host Information181typedef struct SceNetAdhocctlBSSId {182SceNetEtherAddr mac_addr;183uint8_t padding[2];184} PACK SceNetAdhocctlBSSId;185186// Virtual Network Information187typedef struct SceNetAdhocctlScanInfo {188struct SceNetAdhocctlScanInfo * next;189s32_le channel;190SceNetAdhocctlGroupName group_name;191SceNetAdhocctlBSSId bssid;192s32_le mode;193} PACK SceNetAdhocctlScanInfo;194195// Virtual Network Information with u32 pointers196typedef struct SceNetAdhocctlScanInfoEmu {197u32_le next;198s32_le channel;199SceNetAdhocctlGroupName group_name;200SceNetAdhocctlBSSId bssid;201s32_le mode;202} PACK SceNetAdhocctlScanInfoEmu;203204// Player Nickname205#define ADHOCCTL_NICKNAME_LEN 128206typedef struct SceNetAdhocctlNickname {207uint8_t data[ADHOCCTL_NICKNAME_LEN];208} PACK SceNetAdhocctlNickname;209210// Active Virtual Network Information (Adhoc Group Host/Creator's device info, similar to AP?)211typedef struct SceNetAdhocctlParameter {212s32_le channel;213SceNetAdhocctlGroupName group_name; // This group name is probably similar to SSID name on AP214SceNetAdhocctlNickname nickname; // According to the old PSPSDK this is the bssid, but according to the dumped content when using newer firmware this is the nickname (this is also the nickname on VitaSDK)215SceNetAdhocctlBSSId bssid; // FIXME: bssid and nickname position might be swapped on older/newer firmware?216} PACK SceNetAdhocctlParameter;217218// Peer Information (internal use only)219typedef struct SceNetAdhocctlPeerInfo {220SceNetAdhocctlPeerInfo * next;221SceNetAdhocctlNickname nickname;222SceNetEtherAddr mac_addr;223u16_le padding; // a copy of the padding(?) from SceNetAdhocctlPeerInfoEmu224u32_le flags;225u64_le last_recv; // Need to use the same method with sceKernelGetSystemTimeWide (ie. CoreTiming::GetGlobalTimeUsScaled) to prevent timing issue (ie. in game timeout)226227u32_le ip_addr; // internal use only228u16_le port_offset; // IP-specific port offset (internal use only)229} PACK SceNetAdhocctlPeerInfo;230231// Peer Information with u32 pointers232typedef struct SceNetAdhocctlPeerInfoEmu {233u32_le next; // Changed the pointer to u32234SceNetAdhocctlNickname nickname;235SceNetEtherAddr mac_addr;236u16_le padding; //00 00 // Note: Not sure whether this is really padding or reserved/unknown field237u32_le flags; //00 04 00 00 on KHBBS and FF FF FF FF on Ys vs. Sora no Kiseki // State of the peer? Or related to sceNetAdhocAuth_CF4D9BED ?238u64_le last_recv; // Need to use the same method with sceKernelGetSystemTimeWide (ie. CoreTiming::GetGlobalTimeUsScaled) to prevent timing issue (ie. in game timeout)239} PACK SceNetAdhocctlPeerInfoEmu;240241// Member Information242typedef struct SceNetAdhocMatchingMemberInfo {243SceNetAdhocMatchingMemberInfo * next;244SceNetEtherAddr mac_addr;245uint8_t padding[2];246} PACK SceNetAdhocctlMemberInfo;247248// Member Information with u32 pointers249typedef struct SceNetAdhocMatchingMemberInfoEmu {250u32_le next; // Changed the pointer to u32251SceNetEtherAddr mac_addr;252uint8_t padding[2];253} PACK SceNetAdhocctlMemberInfoEmu;254255// Game Mode Peer List256#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16257typedef struct SceNetAdhocctlGameModeInfo {258s32_le num;259SceNetEtherAddr members[ADHOCCTL_GAMEMODE_MAX_MEMBERS];260} PACK SceNetAdhocctlGameModeInfo;261262// GameModeUpdateInfo263typedef struct GameModeUpdateInfo {264u32_le length; //size of GameModeUpdateInfo (16 bytes)265s32_le updated;266u64_le timeStamp;267} PACK GameModeUpdateInfo;268269// GameModeArea (Internal use only)270typedef struct GameModeArea {271int id; // started from 1 for replica? master = 0 or -1?272int size;273u32 addr;274//int socket; // PDP socket?275u64 updateTimestamp;276int dataUpdated;277int dataSent;278SceNetEtherAddr mac;279u8* data; // upto "size" bytes started from "addr" ?280} PACK GameModeArea;281282// Socket Polling Event Listener283typedef struct SceNetAdhocPollSd{284s32_le id;285s32_le events;286s32_le revents;287} PACK SceNetAdhocPollSd;288289// PDP Socket Status290typedef struct SceNetAdhocPdpStat {291u32_le next;292s32_le id; // posix socket id293SceNetEtherAddr laddr;294u16_le lport;295u32_le rcv_sb_cc; // Obscure The Aftermath will check if this is 0 or not before calling PdpRecv, Might to be number of bytes available to be Received?296} PACK SceNetAdhocPdpStat;297298// PTP Socket Status299typedef struct SceNetAdhocPtpStat {300u32_le next; // Changed the pointer to u32301s32_le id; // posix socket id302SceNetEtherAddr laddr;303SceNetEtherAddr paddr;304u16_le lport;305u16_le pport;306u32_le snd_sb_cc; // Number of bytes existed in sendBuffer to be sent/flushed307u32_le rcv_sb_cc; // Number of bytes available in recvBuffer to be received308s32_le state;309} PACK SceNetAdhocPtpStat;310311// PDP & PTP Socket Union (Internal use only)312typedef struct AdhocSocket {313s32_le type; // SOCK_PDP/SOCK_PTP314s32_le flags; // Socket Alert Flags315s32_le alerted_flags; // Socket Alerted Flags316s32_le nonblocking; // last non-blocking flag317u32 buffer_size;318u32 send_timeout; // default connect timeout319u32 recv_timeout; // default accept timeout320s32 retry_interval; // related to keepalive321s32 retry_count; // multiply with retry interval to be used as keepalive timeout322s32 attemptCount; // connect/accept attempts323u64 lastAttempt; // timestamp to retry again (attempted by the game)324u64 internalLastAttempt; // timestamp to retry again (internal use only)325bool isClient; // true if the game is using local port 0 when creating the socket326union {327SceNetAdhocPdpStat pdp;328SceNetAdhocPtpStat ptp;329} data;330void *postofficeHandle; // aemu_postoffice mode handle331std::thread *connectThread;332bool connectThreadDone;333int connectThreadResult;334} PACK AdhocSocket;335336// Gamemode Optional Peer Buffer Data337typedef struct SceNetAdhocGameModeOptData {338u32_le size;339u32_le flag;340u64_le last_recv; // Need to use the same method with sceKernelGetSystemTimeWide (ie. CoreTiming::GetGlobalTimeUsScaled) to prevent timing issue (ie. in game timeout)341} PACK SceNetAdhocGameModeOptData;342343// Gamemode Buffer Status344typedef struct SceNetAdhocGameModeBufferStat {345struct SceNetAdhocGameModeBufferStat * next; //should be u32_le ?346s32_le id;347void * ptr; //should be u32_le ?348u32_le size;349u32_le master;350SceNetAdhocGameModeOptData opt;351} PACK SceNetAdhocGameModeBufferStat;352353// Adhoc ID (Game Product Key)354#define ADHOCCTL_ADHOCID_LEN 9355typedef struct SceNetAdhocctlAdhocId {356s32_le type; // Air Conflicts - Aces Of World War 2 is using 2 for GameSharing?357uint8_t data[ADHOCCTL_ADHOCID_LEN]; // Air Conflicts - Aces Of World War 2 is using "000000001" for GameSharing?358uint8_t padding[3];359} PACK SceNetAdhocctlAdhocId; // should this be packed?360#ifdef _MSC_VER361#pragma pack(pop)362#endif363364365// Internal Matching Peer Information366typedef struct SceNetAdhocMatchingMemberInternal {367// Next Peer368struct SceNetAdhocMatchingMemberInternal * next;369370// MAC Address371SceNetEtherAddr mac;372373// State Variable374s32_le state;375376// Send in Progress377s32_le sending;378379// Last Heartbeat380u64_le lastping; // May need to use the same method with sceKernelGetSystemTimeWide (ie. CoreTiming::GetGlobalTimeUsScaled) to prevent timing issue (ie. in game timeout)381} SceNetAdhocMatchingMemberInternal;382383384// Matching handler385struct SceNetAdhocMatchingHandlerArgs {386s32_le id;387s32_le opcode; // event;388SceNetEtherAddr mac; // peer //u32_le macaddr;389s32_le optlen;390void * opt; //u32_le optaddr391};392393struct SceNetAdhocMatchingHandler {394u32_le entryPoint;395};396397struct AdhocctlHandler {398u32 entryPoint;399u32 argument;400};401402// Thread Message Stack Item403typedef struct ThreadMessage {404// Next Thread Message405struct ThreadMessage * next;406407// Stack Event Opcode408u32_le opcode;409410// Target MAC Address411SceNetEtherAddr mac;412413// Optional Data Length414s32_le optlen;415} ThreadMessage;416417// Established Peer418419// Context Information420typedef struct SceNetAdhocMatchingContext {421// Next Context422struct SceNetAdhocMatchingContext *next;423424// Externally Visible ID425s32_le id;426427// Matching Mode (HOST, CLIENT, P2P)428s32_le mode;429430// Running Flag (1 = running, 0 = created)431s32_le running;432433// Maximum Number of Peers (for HOST, P2P)434s32_le maxpeers;435436// Peer List for Connectees437SceNetAdhocMatchingMemberInternal *peerlist; // SceNetAdhocMatchingMemberInfo[Emu]438439// Peer Port list440std::map<SceNetEtherAddr, u16_le> *peerPort;441442// Local MAC Address443SceNetEtherAddr mac;444445// Local PDP Port446u16_le port;447448// Local PDP Socket449s32_le socket;450// Socket Lock451std::recursive_mutex *socketlock;452453// Receive Buffer Length454s32_le rxbuflen;455456// Receive Buffer457uint8_t *rxbuf;458459// Hello Broadcast Interval (Microseconds)460u32_le hello_int;461462// Keep-Alive Broadcast Interval (Microseconds)463u32_le keepalive_int;464465// Resend Interval (Microseconds)466u32_le resend_int;467468// Resend-Counter469s32_le resendcounter;470471// Keep-Alive Counter472s32_le keepalivecounter;473474// Event Handler475SceNetAdhocMatchingHandler handler;476477// Event Handler Args478u32_le handlerArgs[6]; //MatchingArgs handlerArgs; // actual arguments only 5, the 6th one is just for borrowing a space to store the callback address to use later479//SceNetAdhocMatchingHandlerArgs handlerArgs;480481// Hello Data Length482s32_le hellolen;483484// Hello Data Address485u32_le helloAddr;486487// Hello Data488uint8_t *hello;489490// Timeout491u64_le timeout;492493// Helper Thread (fake PSP Thread) needed to execute callback494//HLEHelperThread *matchingThread;495int matching_thid;496497// Event Caller Thread498std::thread eventThread;499//s32_le event_thid;500bool eventRunning = false;501bool IsMatchingInCB = false;502503// IO Handler Thread504std::thread inputThread;505//s32_le input_thid;506bool inputRunning = false;507508// Event Caller Thread Message Stack509std::recursive_mutex *eventlock; // s32_le event_stack_lock;510ThreadMessage *event_stack;511512// IO Handler Thread Message Stack513std::recursive_mutex *inputlock; // s32_le input_stack_lock;514ThreadMessage *input_stack;515516// Socket Connectivity517//bool connected = false;518//bool InConnection = false;519//u32_le handlerid = -1;520//int eventMatchingHandlerUpdate = -1;521} SceNetAdhocMatchingContext;522523// End of psp definitions524525const size_t MAX_ADHOCCTL_HANDLERS = 32; //4526const size_t MAX_MATCHING_HANDLERS = 32; //4527528enum {529/**530* Matching events used in pspAdhocMatchingCallback531*/532/** Hello event. optdata contains data if optlen > 0. */533PSP_ADHOC_MATCHING_EVENT_HELLO = 1,534/** Join request. optdata contains data if optlen > 0. */535PSP_ADHOC_MATCHING_EVENT_JOIN = 2,536/** Target left matching. */537PSP_ADHOC_MATCHING_EVENT_LEFT = 3,538/** Join request rejected. */539PSP_ADHOC_MATCHING_EVENT_REJECT = 4,540/** Join request cancelled. */541PSP_ADHOC_MATCHING_EVENT_CANCEL = 5,542/** Join request accepted. optdata contains data if optlen > 0. */543PSP_ADHOC_MATCHING_EVENT_ACCEPT = 6,544/** Matching is complete. */545PSP_ADHOC_MATCHING_EVENT_COMPLETE = 7,546/** Ping timeout event. */547PSP_ADHOC_MATCHING_EVENT_TIMEOUT = 8,548/** Error event. */549PSP_ADHOC_MATCHING_EVENT_ERROR = 9,550/** Peer disconnect event. */551PSP_ADHOC_MATCHING_EVENT_DISCONNECT = 10,552/** Data received event. optdata contains data if optlen > 0. */553PSP_ADHOC_MATCHING_EVENT_DATA = 11,554/** Data acknowledged event. */555PSP_ADHOC_MATCHING_EVENT_DATA_CONFIRM = 12,556/** Data timeout event. */557PSP_ADHOC_MATCHING_EVENT_DATA_TIMEOUT = 13,558559/** Internal ping message. */560PSP_ADHOC_MATCHING_EVENT_INTERNAL_PING = 100,561562/**563* Matching modes used in sceNetAdhocMatchingCreate564*/565/** Host */566PSP_ADHOC_MATCHING_MODE_HOST = 1,567/** Client */568PSP_ADHOC_MATCHING_MODE_CLIENT = 2,569/** Peer to peer */570PSP_ADHOC_MATCHING_MODE_PTP = 3,571};572573enum {574PSP_ADHOC_POLL_READY_TO_SEND = 1, // POLLIN ?575PSP_ADHOC_POLL_DATA_AVAILABLE = 2, // POLLPRI ?576PSP_ADHOC_POLL_CAN_CONNECT = 4, // POLLOUT ?577PSP_ADHOC_POLL_CAN_ACCEPT = 8, // POLLERR ?578};579580// Matching modes581#define PSP_ADHOC_MATCHING_MODE_PARENT 1582#define PSP_ADHOC_MATCHING_MODE_CHILD 2583#define PSP_ADHOC_MATCHING_MODE_P2P 3584585// Matching Events586#define PSP_ADHOC_MATCHING_EVENT_HELLO 1 // Should be ignored when Join Request is in progress ?587#define PSP_ADHOC_MATCHING_EVENT_REQUEST 2588#define PSP_ADHOC_MATCHING_EVENT_LEAVE 3589#define PSP_ADHOC_MATCHING_EVENT_DENY 4590#define PSP_ADHOC_MATCHING_EVENT_CANCEL 5591#define PSP_ADHOC_MATCHING_EVENT_ACCEPT 6592#define PSP_ADHOC_MATCHING_EVENT_ESTABLISHED 7 // Should only be triggered on Parent/P2P mode and for Parent/P2P peer ?593#define PSP_ADHOC_MATCHING_EVENT_TIMEOUT 8 // Should only be triggered on Parent/P2P mode and for Parent/P2P peer ?594#define PSP_ADHOC_MATCHING_EVENT_ERROR 9595#define PSP_ADHOC_MATCHING_EVENT_BYE 10 // Should only be triggered on Parent/P2P mode and for Parent/P2P peer ?596#define PSP_ADHOC_MATCHING_EVENT_DATA 11597#define PSP_ADHOC_MATCHING_EVENT_DATA_ACK 12598#define PSP_ADHOC_MATCHING_EVENT_DATA_TIMEOUT 13599600// Peer Status601// Offer only seen in P2P and PARENT mode after hello602// Parent only seen in CHILD mode after connection accept603// Child only seen in PARENT and CHILD mode after connection accept604// P2P only seen in P2P mode after connection accept605// Requester only seen in P2P and PARENT mode after connection request606#define PSP_ADHOC_MATCHING_PEER_OFFER 1607#define PSP_ADHOC_MATCHING_PEER_PARENT 2608#define PSP_ADHOC_MATCHING_PEER_CHILD 3609#define PSP_ADHOC_MATCHING_PEER_P2P 4610#define PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST 5611#define PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST 6612#define PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS 7613614// Stack Targets615#define PSP_ADHOC_MATCHING_INPUT_STACK 1616#define PSP_ADHOC_MATCHING_EVENT_STACK 2617618// Packet Opcodes619#define PSP_ADHOC_MATCHING_PACKET_PING 0620#define PSP_ADHOC_MATCHING_PACKET_HELLO 1621#define PSP_ADHOC_MATCHING_PACKET_JOIN 2622#define PSP_ADHOC_MATCHING_PACKET_ACCEPT 3623#define PSP_ADHOC_MATCHING_PACKET_CANCEL 4624#define PSP_ADHOC_MATCHING_PACKET_BULK 5625#define PSP_ADHOC_MATCHING_PACKET_BULK_ABORT 6626#define PSP_ADHOC_MATCHING_PACKET_BIRTH 7627#define PSP_ADHOC_MATCHING_PACKET_DEATH 8628#define PSP_ADHOC_MATCHING_PACKET_BYE 9629630// Pro Adhoc Server Packets Opcodes631#define OPCODE_PING 0632#define OPCODE_LOGIN 1633#define OPCODE_CONNECT 2634#define OPCODE_DISCONNECT 3635#define OPCODE_SCAN 4636#define OPCODE_SCAN_COMPLETE 5637#define OPCODE_CONNECT_BSSID 6638#define OPCODE_CHAT 7639640// PSP Product Code641#define PRODUCT_CODE_LENGTH 9642643#ifdef _MSC_VER644#pragma pack(push,1)645#endif646647typedef struct {648// Game Product Code (ex. ULUS12345)649char data[PRODUCT_CODE_LENGTH];650} PACK SceNetAdhocctlProductCode;651652// Basic Packet653typedef struct {654uint8_t opcode;655} PACK SceNetAdhocctlPacketBase;656657// C2S Login Packet658typedef struct {659SceNetAdhocctlPacketBase base;660SceNetEtherAddr mac;661SceNetAdhocctlNickname name;662SceNetAdhocctlProductCode game;663} PACK SceNetAdhocctlLoginPacketC2S;664665// C2S Connect Packet666typedef struct {667SceNetAdhocctlPacketBase base;668SceNetAdhocctlGroupName group;669} PACK SceNetAdhocctlConnectPacketC2S;670671#define ADHOCCTL_MESSAGE_LEN 64672// C2S Chat Packet673typedef struct {674SceNetAdhocctlPacketBase base;675char message[ADHOCCTL_MESSAGE_LEN];676} PACK SceNetAdhocctlChatPacketC2S;677678// S2C Connect Packet679typedef struct {680SceNetAdhocctlPacketBase base;681SceNetAdhocctlNickname name;682SceNetEtherAddr mac;683uint32_t ip;684} PACK SceNetAdhocctlConnectPacketS2C;685686// S2C Disconnect Packet687typedef struct {688SceNetAdhocctlPacketBase base;689uint32_t ip;690} PACK SceNetAdhocctlDisconnectPacketS2C;691692// S2C Scan Packet693typedef struct {694SceNetAdhocctlPacketBase base;695SceNetAdhocctlGroupName group;696SceNetEtherAddr mac;697} PACK SceNetAdhocctlScanPacketS2C;698699// S2C Connect BSSID Packet700typedef struct {701SceNetAdhocctlPacketBase base;702SceNetEtherAddr mac;703} PACK SceNetAdhocctlConnectBSSIDPacketS2C;704705// S2C Chat Packet706typedef struct {707SceNetAdhocctlChatPacketC2S base;708SceNetAdhocctlNickname name;709} PACK SceNetAdhocctlChatPacketS2C;710711// P2P Packet712typedef struct {713SceNetEtherAddr fromMAC;714SceNetEtherAddr toMAC;715u32_le dataPtr; //void * data716} PACK SceNetAdhocMatchingPacketBase;717718// P2P Accept Packet719typedef struct {720SceNetAdhocctlPacketBase base; //opcode721u32_le dataLen;722u32_le numMACs; //number of peers723u32_le dataPtr; //void * data724/*u32_le*/PSPPointer<SceNetEtherAddr> MACsPtr; //peers //SceNetEtherAddr * MACs725} PACK SceNetAdhocMatchingPacketAccept;726727#ifdef _MSC_VER728#pragma pack(pop)729#endif730731class PointerWrap;732733class AfterAdhocMipsCall : public PSPAction {734public:735AfterAdhocMipsCall() {}736static PSPAction* Create() { return new AfterAdhocMipsCall(); }737void DoState(PointerWrap& p) override;738void run(MipsCall& call) override;739void SetData(int handlerID, int eventId, u32_le argsAddr);740741private:742int HandlerID = -1;743int EventID = -1;744u32_le argsAddr = 0;745};746747class AfterMatchingMipsCall : public PSPAction {748public:749AfterMatchingMipsCall() {}750static PSPAction *Create() { return new AfterMatchingMipsCall(); }751void DoState(PointerWrap &p) override;752void run(MipsCall &call) override;753void SetData(int ContextID, int eventId, u32_le BufAddr);754755private:756int contextID = -1;757int EventID = -1;758u32_le bufAddr = 0;759SceNetAdhocMatchingContext* context = nullptr;760};761762extern int actionAfterAdhocMipsCall;763extern int actionAfterMatchingMipsCall;764765#define MAX_SOCKET 255 // FIXME: PSP might not allows more than 255 sockets? Hotshots Tennis doesn't seems to works with socketId > 255766#define SOCK_PDP 1767#define SOCK_PTP 2768// Aux vars769extern std::atomic<int> metasocket;770extern SceNetAdhocctlParameter parameter;771extern SceNetAdhocctlAdhocId product_code;772extern std::thread friendFinderThread;773extern std::recursive_mutex peerlock;774extern AdhocSocket* adhocSockets[MAX_SOCKET];775776union SockAddrIN4 {777sockaddr addr;778sockaddr_in in;779};780781extern uint16_t portOffset;782extern uint32_t minSocketTimeoutUS;783extern bool isOriPort;784extern bool isLocalServer;785extern SockAddrIN4 g_adhocServerIP; // Resolved Adhoc Server IP so we don't need to repeatedly resolve the DNS again later786extern SockAddrIN4 g_localhostIP; // Used to differentiate localhost IP on multiple-instance787extern sockaddr LocalIP; // IP of Network Adapter used to connect to Adhoc Server (LAN/WAN)788extern int defaultWlanChannel; // Default WLAN Channel for Auto, JPCSP uses 11789790extern uint32_t fakePoolSize;791extern SceNetAdhocMatchingContext * contexts;792extern char* dummyPeekBuf64k;793extern int dummyPeekBuf64kSize;794extern int one;795extern std::atomic<bool> friendFinderRunning;796extern SceNetAdhocctlPeerInfo * friends;797extern SceNetAdhocctlScanInfo * networks;798extern u64 adhocctlStartTime;799extern bool isAdhocctlNeedLogin;800extern bool isAdhocctlBusy;801extern int adhocctlState;802extern int adhocctlCurrentMode;803extern int adhocConnectionType;804805extern int gameModeSocket;806extern int gameModeBuffSize;807extern u8* gameModeBuffer;808extern GameModeArea masterGameModeArea;809extern std::vector<GameModeArea> replicaGameModeAreas;810extern std::vector<SceNetEtherAddr> requiredGameModeMacs;811extern std::vector<SceNetEtherAddr> gameModeMacs;812extern std::map<SceNetEtherAddr, u16_le> gameModePeerPorts;813// End of Aux vars814815enum AdhocConnectionType : int816{817ADHOC_CONNECT = 0,818ADHOC_CREATE = 1,819ADHOC_JOIN = 2,820};821822// Check if Matching callback is running823bool IsMatchingInCallback(SceNetAdhocMatchingContext * context);824bool SetMatchingInCallback(SceNetAdhocMatchingContext* context, bool IsInCB);825826int IsAdhocctlInCallback();827int SetAdhocctlInCallback(bool IsInCB);828829/**830* Compare MAC Addresses831* @param addr1 & addr2 To-be-compared MAC Address832* @return True if both matched833*/834bool isMacMatch(const SceNetEtherAddr* addr1, const SceNetEtherAddr* addr2);835836/**837* Local MAC Check838* @param saddr To-be-checked MAC Address839* @return True if it's local mac840*/841bool isLocalMAC(const SceNetEtherAddr * addr);842843/**844* PDP Port Check845* @param port To-be-checked Port846* @return 1 if in use or... 0847*/848bool isPDPPortInUse(uint16_t port);849850/**851* Check whether PTP Port is in use or not (only sockets with non-Listening state will be considered as in use)852* @param port To-be-checked Port Number853* @param forListen to check for listening or non-listening port854* @param dstmac destination address (non-listening only)855* @param dstport destination port (non-listening only)856* @return 1 if in use or... 0857*/858bool isPTPPortInUse(uint16_t port, bool forListen, SceNetEtherAddr* dstmac = nullptr, uint16_t dstport = 0);859860// Convert IPv4 address to string (Replacement for inet_ntoa since it's getting deprecated)861std::string ip2str(in_addr in, bool maskPublicIP = true);862863// Convert MAC address to string864std::string mac2str(const SceNetEtherAddr *mac);865866/*867* Matching Members868*/869//SceNetAdhocMatchingMemberInternal* findMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac); // findPeer870SceNetAdhocMatchingMemberInternal* addMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac);871//void deleteMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac); // deletePeer872//void deleteAllMembers(SceNetAdhocMatchingContext * context); // clearPeerList873874875/**876* Add Friend to Local List877* @param packet Friend Information878*/879void addFriend(SceNetAdhocctlConnectPacketS2C * packet);880881/**882* Send chat or get that883* @param std::string ChatString884*/885void sendChat(const std::string &chatString);886std::vector<std::string> getChatLog();887int GetChatChangeID();888int GetChatMessageCount();889890/*891* Find a Peer/Friend by MAC address892*/893SceNetAdhocctlPeerInfo * findFriend(SceNetEtherAddr * MAC);894895/*896* Find a Peer/Friend by IP address897*/898SceNetAdhocctlPeerInfo* findFriendByIP(uint32_t ip);899900/**901* Get the Readability(ie. recv) and/or Writability(ie. send) of a socket902* @param fd File Descriptor of the socket903* @param timeout in usec (micro seconds), 0 = non-blocking904* @return > 0 = ready, 0 = timeout, -1 = error (errorcode only represent error of select and doesn't represent error of the socket)905*/906int IsSocketReady(int fd, bool readfd, bool writefd, int* errorcode = nullptr, int timeoutUS = 0);907908/**909* Changes the Blocking Mode of the socket910* @param fd File Descriptor of the socket911* @param nonblocking 1 to set to nonblock and 0 to set blocking912*/913void changeBlockingMode(int fd, int nonblocking);914915/**916* Count Virtual Networks by analyzing the Friend List917* @return Number of Virtual Networks918*/919int countAvailableNetworks(const bool excludeSelf = false);920921/*922* Find an existing group in networks923*/924SceNetAdhocctlScanInfo * findGroup(SceNetEtherAddr * MAC);925926/*927* Deletes all groups in networks928*/929void freeGroupsRecursive(SceNetAdhocctlScanInfo * node);930931/**932* Closes & Deletes all PDP & PTP Sockets933*/934void deleteAllAdhocSockets();935936/*937* Deletes all GameMode Buffers938*/939void deleteAllGMB();940941/**942* Delete Friend from Local List943* @param ip Friend IP944*/945void deleteFriendByIP(uint32_t ip);946947/**948* Recursive Memory Freeing-Helper for Friend-Structures949* @param node Current Node in List950*/951void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node, int32_t* count = nullptr);952953void timeoutFriendsRecursive(SceNetAdhocctlPeerInfo * node, int32_t* count = nullptr);954955/**956* Friend Finder Thread (Receives Peer Information)957* @param args Length of argp in Bytes (Unused)958* @param argp Argument (Unused)959* @return Unused Value - Return 0960*/961int friendFinder();962963/**964* Find Free Matching ID965* @return First unoccupied Matching ID966*/967int findFreeMatchingID();968969/**970* Find Internal Matching Context for Matching ID971* @param id Matching ID972* @return Matching Context Pointer or... NULL973*/974SceNetAdhocMatchingContext * findMatchingContext(int id);975976// Notifiy Adhocctl Handlers977void notifyAdhocctlHandlers(u32 flag, u32 error);978979/*980* Packet Handler981*/982void postAcceptCleanPeerList(SceNetAdhocMatchingContext * context);983void postAcceptAddSiblings(SceNetAdhocMatchingContext * context, int siblingcount, SceNetEtherAddr * siblings);984985/*986* Timeout Handler987*/988void handleTimeout(SceNetAdhocMatchingContext * context);989990/**991* Clear Thread Stack992* @param context Matching Context Pointer993* @param stack ADHOC_MATCHING_EVENT_STACK or ADHOC_MATCHING_INPUT_STACK994*/995void clearStack(SceNetAdhocMatchingContext * context, int stack);996997/**998* Clear Peer List999* @param context Matching Context Pointer1000*/1001void clearPeerList(SceNetAdhocMatchingContext * context);10021003/**1004* Find Outgoing Request Target Peer1005* @param context Matching Context Pointer1006* @return Internal Peer Reference or... NULL1007*/1008SceNetAdhocMatchingMemberInternal * findOutgoingRequest(SceNetAdhocMatchingContext * context);10091010/**1011* Send Accept Message from P2P -> P2P or Parent -> Children1012* @param context Matching Context Pointer1013* @param peer Target Peer1014* @param optlen Optional Data Length1015* @param opt Optional Data1016*/1017void sendAcceptMessage(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal * peer, int optlen, const void * opt);10181019/**1020* Send Join Request from P2P -> P2P or Children -> Parent1021* @param context Matching Context Pointer1022* @param peer Target Peer1023* @param optlen Optional Data Length1024* @param opt Optional Data1025*/1026void sendJoinRequest(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal * peer, int optlen, const void * opt);10271028/**1029* Send Cancel Message to Peer (has various effects)1030* @param context Matching Context Pointer1031* @param peer Target Peer1032* @param optlen Optional Data Length1033* @param opt Optional Data1034*/1035void sendCancelMessage(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal * peer, int optlen, const void * opt);10361037/**1038* Send Bulk Data to Peer1039* @param context Matching Context Pointer1040* @param peer Target Peer1041* @param datalen Data Length1042* @param data Data1043*/1044void sendBulkData(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal * peer, int datalen, const void * data);10451046/**1047* Abort Bulk Data Transfer (if in progress)1048* @param context Matching Context Pointer1049* @param peer Target Peer1050*/1051void abortBulkTransfer(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal * peer);10521053/**1054* Notify all established Peers about new Kid in the Neighborhood1055* @param context Matching Context Pointer1056* @param peer New Kid1057*/1058void sendBirthMessage(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal * peer);10591060/**1061* Notify all established Peers about abandoned Child1062* @param context Matching Context Pointer1063* @param peer Abandoned Child1064*/1065void sendDeathMessage(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal * peer);10661067/**1068* Count Children Peers (for Parent)1069* @param context Matching Context Pointer1070* @return Number of Children1071*/1072s32_le countChildren(SceNetAdhocMatchingContext * context, const bool excludeTimedout = false);10731074/**1075* Delete Peer from List1076* @param context Matching Context Pointer1077* @param peer Internal Peer Reference1078*/1079void deletePeer(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberInternal *& peer);10801081/**1082* Find Peer in Context by MAC1083* @param context Matching Context Pointer1084* @param mac Peer MAC Address1085* @return Internal Peer Reference or... NULL1086*/1087SceNetAdhocMatchingMemberInternal * findPeer(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac);10881089/**1090* Find Parent Peer1091* @param context Matching Context Pointer1092* @return Internal Peer Reference or... NULL1093*/1094SceNetAdhocMatchingMemberInternal * findParent(SceNetAdhocMatchingContext * context);10951096/**1097* Find P2P Buddy Peer1098* @param context Matching Context Pointer1099* @return Internal Peer Reference or... NULL1100*/1101SceNetAdhocMatchingMemberInternal * findP2P(SceNetAdhocMatchingContext * context, const bool excludeTimedout = false);11021103/**1104* Return Number of Connected Peers1105* @param context Matching Context Pointer1106* @return Number of Connected Peers1107*/1108uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context, const bool excludeTimedout = false);11091110/**1111* Spawn Local Event for Event Thread1112* @param context Matching Context Pointer1113* @param event Event ID1114* @param mac Event Source MAC1115* @param optlen Optional Data Length1116* @param opt Optional Data1117*/1118void spawnLocalEvent(SceNetAdhocMatchingContext * context, int event, SceNetEtherAddr * mac, int optlen, void * opt);11191120/*1121* Matching Event Thread (Send Ping and Hello Data) Part of AdhocMatching1122*/1123//int matchingEvent(int matchingId);1124//int matchingEventThread(int matchingId); //(uint32_t args, void * argp)11251126/*1127* Matching Input Thread (process Members) Part of AdhocMatching1128*/1129//int matchingInputThread(int matchingId); //(uint32_t args, void * argp)11301131/**1132* Return Number of active Peers in the same Network as the Local Player1133* @return Number of active Peers1134*/1135int getActivePeerCount(const bool excludeTimedout = true);11361137/**1138* Returns the locall Ip of this machine1139* @param SocketAddres OUT: local ip1140*/1141int getLocalIp(sockaddr_in * SocketAddress);1142uint32_t getLocalIp(int sock);11431144/*1145* Check if an IP (big-endian/network order) is Private or Public IP1146*/1147bool isMulticastIP(uint32_t ip);11481149/*1150* Check if an IP (big-endian/network order) is Private or Public IP1151*/1152bool isPrivateIP(uint32_t ip);11531154/*1155* Check if an IP (big-endian/network order) is APIPA(169.254.x.x) IP1156*/1157bool isAPIPA(uint32_t ip);11581159/*1160* Check if an IP (big-endian/network order) is Loopback IP1161*/1162bool isLoopbackIP(uint32_t ip);11631164/*1165* Check if an IP (big-endian/network order) is a Broadcast IP1166* Default subnet mask is 255.255.255.01167*/1168bool isBroadcastIP(uint32_t ip, const uint32_t subnetmask = 0x00ffffff);11691170/*1171* Get Number of bytes available in buffer to be Received1172* @param sock fd1173* @param udpBufferSize (UDP only)1174*/1175u_long getAvailToRecv(int sock, int udpBufferSize = 0);11761177/*1178* Get UDP Socket Max Message Size1179*/1180int getSockMaxSize(int udpsock);11811182/*1183* Get Socket Buffer Size (opt = SO_RCVBUF/SO_SNDBUF)1184*/1185int getSockBufferSize(int sock, int opt);11861187/*1188* Set Socket Buffer Size (opt = SO_RCVBUF/SO_SNDBUF)1189*/1190int setSockBufferSize(int sock, int opt, int size);11911192/*1193* Set TCP Socket Maximum Segment Size (default is 1460 on 1500 MTU)1194*/1195int setSockMSS(int sock, int size);11961197/*1198* Set Socket TimeOut (opt = SO_SNDTIMEO/SO_RCVTIMEO)1199*/1200int setSockTimeout(int sock, int opt, unsigned long timeout_usec);12011202/*1203* Get Socket SO_ERROR (Requests and clears pending error information on the socket)1204*/1205int getSockError(int sock);12061207/*1208* Get TCP Socket TCP_NODELAY (Nagle Algo)1209*/1210int getSockNoDelay(int tcpsock);12111212/*1213* Set TCP Socket TCP_NODELAY (Nagle Algo)1214*/1215int setSockNoDelay(int tcpsock, int flag);12161217/*1218* Set Socket SO_NOSIGPIPE when supported1219*/1220int setSockNoSIGPIPE(int sock, int flag);12211222/*1223* Set Socket SO_REUSEADDR and SO_REUSEPORT when supported1224*/1225int setSockReuseAddrPort(int sock);12261227/*1228* Set Socket Connection Reset on UDP (which could cause a strange behavior)1229*/1230int setUDPConnReset(int udpsock, bool enabled);12311232/*1233* Set Socket KeepAlive (opt = SO_KEEPALIVE)1234*/1235int setSockKeepAlive(int sock, bool keepalive, const int keepinvl = 60, const int keepcnt = 20, const int keepidle = 180);12361237/**1238* Return the Number of Players with the chosen Nickname in the Local Users current Network1239* @param nickname To-be-searched Nickname1240* @return Number of matching Players1241*/1242int getNicknameCount(const char * nickname);124312441245/**1246* Joins two 32 bits number into a 64 bit one1247* @param num1: first number1248* @param num2: second number1249* @return Single 64 bit number1250*/1251#define firstMask 0x00000000FFFFFFFF1252#define secondMask 0xFFFFFFFF000000001253u64 join32(u32 num1, u32 num2);12541255/**1256* Splits a 64 bit number into two 32 bit ones1257* @param num: The number to be split1258* @param buf OUT: Array containing the split numbers1259*/1260void split64(u64 num, int buff[]);12611262/**1263* Returns the local mac1264* @param addr OUT: 6-bytes of Local Mac1265*/1266void getLocalMac(SceNetEtherAddr * addr);12671268/*1269* Returns the local port used by the socket1270*/1271uint16_t getLocalPort(int sock);12721273/**1274* PDP Socket Counter1275* @return Number of internal PDP Sockets1276*/1277int getPDPSocketCount();12781279/**1280* PTP Socket Counter1281* @return Number of internal PTP Sockets1282*/1283int getPTPSocketCount();12841285/**1286* Initialize Networking Components for Adhocctl Emulator1287* @param adhoc_id Game Product Code1288* @param server_ip Server IP1289* @return 0 on success or... -11290*/1291int initNetwork(SceNetAdhocctlAdhocId *adhocid);12921293/**1294* Zero MAC Check1295* @param addr To-be-checked MAC Address1296* @return true if MAC is all zeroes1297*/1298bool isZeroMAC(const SceNetEtherAddr* addr);12991300/**1301* Broadcast MAC Check1302* @param addr To-be-checked MAC Address1303* @return true if Broadcast MAC or... 01304*/1305bool isBroadcastMAC(const SceNetEtherAddr * addr);13061307/**1308* Resolve IP to MAC1309* @param ip Peer IP Address1310* @param mac OUT: Peer MAC1311* @return true on success1312*/1313bool resolveIP(uint32_t ip, SceNetEtherAddr * mac);13141315/**1316* Resolve MAC to IP1317* @param mac Peer MAC Address1318* @param ip OUT: Peer IP1319* @param port_offset OUT: Peer IP-specific Port Offset1320* @return true on success1321*/1322bool resolveMAC(SceNetEtherAddr* mac, uint32_t* ip, u16* port_offset = nullptr);13231324/**1325* Check whether Network Name contains only valid symbols1326* @param group_name To-be-checked Network Name1327* @return 1 if valid or... 01328*/1329bool validNetworkName(const char *data);13301331// Convert Matching Event Code to String1332const char* getMatchingEventStr(int code);13331334// Convert Matching Opcode ID to String1335const char* getMatchingOpcodeStr(int code);13361337// Convert adhoc ctl state to string1338const char *AdhocCtlStateToString(int state);133913401341