Merge pull request #13519 from ANR2ME/adhoc_fix

Adhoc Fix - various fix
This commit is contained in:
Henrik Rydgård 2020-10-09 23:42:04 +02:00 committed by GitHub
commit cf669e6a21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 850 additions and 647 deletions

View file

@ -974,8 +974,9 @@ static ConfigSetting networkSettings[] = {
ConfigSetting("PortOffset", &g_Config.iPortOffset, 0, true, true),
ConfigSetting("MinTimeout", &g_Config.iMinTimeout, 1, true, true),
ConfigSetting("TCPNoDelay", &g_Config.bTCPNoDelay, false, true, true),
ConfigSetting("ForcedFirstConnect", &g_Config.bForcedFirstConnect, false, true, true),
ConfigSetting("EnableUPnP", &g_Config.bEnableUPnP, false, true, true),
ConfigSetting("UPnPUseOriginalPort", &g_Config.bUPnPUseOriginalPort, true, true, true),
ConfigSetting("UPnPUseOriginalPort", &g_Config.bUPnPUseOriginalPort, false, true, true),
ConfigSetting("EnableNetworkChat", &g_Config.bEnableNetworkChat, false, true, true),
ConfigSetting("ChatButtonPosition",&g_Config.iChatButtonPosition,BOTTOM_LEFT,true,true),

View file

@ -422,6 +422,7 @@ public:
bool bTCPNoDelay;
bool bEnableUPnP;
bool bUPnPUseOriginalPort;
bool bForcedFirstConnect;
int iPortOffset;
int iMinTimeout;
int iWlanAdhocChannel;

View file

@ -44,9 +44,8 @@
static const float FONT_SCALE = 0.65f;
// Needs testing.
const static int NET_INIT_DELAY_US = 300000;
const static int NET_SHUTDOWN_DELAY_US = 260000;
const static int NET_RUNNING_DELAY_US = 1000000; // KHBBS is showing adhoc dialog for about 3-4 seconds, but feels too long, so we're faking it to 1 sec instead to let players read the text
const static int NET_INIT_DELAY_US = 200000;
const static int NET_SHUTDOWN_DELAY_US = 200000;
const static int NET_CONNECT_TIMEOUT = 15000000; // Using 15 secs to match the timeout on Adhoc Server side (SERVER_USER_TIMEOUT)
struct ScanInfos {
@ -306,27 +305,24 @@ int PSPNetconfDialog::Update(int animSpeed) {
}
DisplayButtons(DS_BUTTON_CANCEL, di->T("Cancel"));
// The Netconf dialog stays visible until the network reaches
// the state PSP_NET_APCTL_STATE_GOT_IP.
// The Netconf dialog stays visible until the network reaches the state PSP_NET_APCTL_STATE_GOT_IP.
if (state == PSP_NET_APCTL_STATE_GOT_IP) {
if (pendingStatus != SCE_UTILITY_STATUS_FINISHED) {
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NET_RUNNING_DELAY_US);
}
else if (GetStatus() == SCE_UTILITY_STATUS_FINISHED) {
// We are done!
StartFade(false);
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NET_SHUTDOWN_DELAY_US);
}
}
else if (state == PSP_NET_APCTL_STATE_GETTING_IP) {
else if (state == PSP_NET_APCTL_STATE_JOINING) {
// Switch to the next message
StartFade(true);
}
else if (state == PSP_NET_APCTL_STATE_DISCONNECTED) {
// When connecting with infrastructure, simulate a connection
// using the first network configuration entry.
connResult = sceNetApctlConnect(1);
// When connecting with infrastructure, simulate a connection using the first network configuration entry.
if (connResult < 0) {
connResult = sceNetApctlConnect(1);
}
}
}
@ -442,17 +438,14 @@ int PSPNetconfDialog::Update(int animSpeed) {
}
}
// The Netconf dialog stays visible until the network reaches
// the state ADHOCCTL_STATE_CONNECTED.
// The Netconf dialog stays visible until the network reaches the state ADHOCCTL_STATE_CONNECTED.
if (state == ADHOCCTL_STATE_CONNECTED) {
// Checking pendingStatus to make sure ChangeStatus not to continously extending the delay ticks on every call for eternity
if (pendingStatus != SCE_UTILITY_STATUS_FINISHED) {
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NET_RUNNING_DELAY_US);
}
// Start fading only when the actual status has changed
else if (GetStatus() == SCE_UTILITY_STATUS_FINISHED) {
StartFade(false);
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NET_SHUTDOWN_DELAY_US);
}
// Let's not leaks any memory
if (Memory::IsValidAddress(scanInfosAddr))
userMemory.Free(scanInfosAddr);

View file

@ -123,12 +123,15 @@ bool isPDPPortInUse(uint16_t port) {
return false;
}
bool isPTPPortInUse(uint16_t port) {
bool isPTPPortInUse(uint16_t port, bool forListen) {
// Iterate Sockets
for (int i = 0; i < MAX_SOCKET; i++) {
auto sock = adhocSockets[i];
if (sock != NULL && sock->type == SOCK_PTP)
if (sock->data.ptp.lport == port)
// It's allowed to Listen and Open the same PTP port, But it's not allowed to Listen or Open the same PTP port twice.
if (sock->data.ptp.lport == port &&
((forListen && sock->data.ptp.state == ADHOC_PTP_STATE_LISTEN) ||
(!forListen && sock->data.ptp.state != ADHOC_PTP_STATE_LISTEN)))
return true;
}
// Unused Port
@ -1412,7 +1415,7 @@ int friendFinder(){
getLocalMac(&localMac);
if (std::find_if(gameModeMacs.begin(), gameModeMacs.end(),
[localMac](SceNetEtherAddr const& e) {
return IsMatch(e, localMac);
return isMacMatch(&e, &localMac);
}) == gameModeMacs.end()) {
// Arrange the order to be consistent on all players (Host on top), Starting from our self the rest of new players will be added to the back
gameModeMacs.push_back(localMac);
@ -1501,14 +1504,14 @@ int friendFinder(){
if (adhocctlCurrentMode == ADHOCCTL_MODE_GAMEMODE) {
if (std::find_if(gameModeMacs.begin(), gameModeMacs.end(),
[packet](SceNetEtherAddr const& e) {
return IsMatch(e, packet->mac);
return isMacMatch(&e, &packet->mac);
}) == gameModeMacs.end()) {
// Arrange the order to be consistent on all players (Host on top), Existing players are sent in reverse by AdhocServer
SceNetEtherAddr localMac;
getLocalMac(&localMac);
auto it = std::find_if(gameModeMacs.begin(), gameModeMacs.end(),
[localMac](SceNetEtherAddr const& e) {
return IsMatch(e, localMac);
return isMacMatch(&e, &localMac);
});
// Starting from our self the rest of new players will be added to the back
if (it != gameModeMacs.end()) {
@ -1572,8 +1575,8 @@ int friendFinder(){
/*if (adhocctlCurrentMode == ADHOCCTL_MODE_GAMEMODE) {
auto peer = findFriendByIP(packet->ip);
gameModeMacs.erase(std::remove_if(gameModeMacs.begin(), gameModeMacs.end(),
[peer](auto const& e) {
return IsMatch(e, peer->mac_addr);
[peer](SceNetEtherAddr const& e) {
return isMacMatch(&e, &peer->mac_addr);
}), gameModeMacs.end());
}*/
@ -1985,7 +1988,7 @@ int getNicknameCount(const char * nickname)
for (; peer != NULL; peer = peer->next)
{
// Match found
if (strncmp((char *)&peer->nickname.data, nickname, ADHOCCTL_NICKNAME_LEN) == 0) count++;
if (peer->last_recv != 0 && strncmp((char *)&peer->nickname.data, nickname, ADHOCCTL_NICKNAME_LEN) == 0) count++;
}
// Return Result
@ -2078,9 +2081,9 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
errorcode = errno;
if (iResult == SOCKET_ERROR && errorcode != EISCONN) {
u64 startTime = (u64)(time_now_d() * 1000.0);
u64 startTime = (u64)(time_now_d() * 1000000.0);
while (IsSocketReady(metasocket, false, true) <= 0) {
u64 now = (u64)(time_now_d() * 1000.0);
u64 now = (u64)(time_now_d() * 1000000.0);
if (coreState == CORE_POWERDOWN) return iResult;
if (now - startTime > adhocDefaultTimeout) break;
sleep_ms(10);
@ -2102,7 +2105,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
packet.name.data[ADHOCCTL_NICKNAME_LEN - 1] = 0;
memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN);
IsSocketReady(metasocket, false, true, nullptr, adhocDefaultTimeout * 1000);
IsSocketReady(metasocket, false, true, nullptr, adhocDefaultTimeout);
int sent = send(metasocket, (char*)&packet, sizeof(packet), MSG_NOSIGNAL);
if (sent > 0) {
socklen_t addrLen = sizeof(LocalIP);

View file

@ -56,6 +56,7 @@
#ifdef _WIN32
#undef errno
#undef ESHUTDOWN
#undef ECONNABORTED
#undef ECONNRESET
#undef ENOTCONN
@ -65,6 +66,7 @@
#undef EALREADY
#undef ETIMEDOUT
#define errno WSAGetLastError()
#define ESHUTDOWN WSAESHUTDOWN
#define ECONNABORTED WSAECONNABORTED
#define ECONNRESET WSAECONNRESET
#define ENOTCONN WSAENOTCONN
@ -74,11 +76,13 @@
#define EALREADY WSAEALREADY
#define ETIMEDOUT WSAETIMEDOUT
inline bool connectInProgress(int errcode){ return (errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == WSAEALREADY); }
inline bool isDisconnected(int errcode) { return (errcode == WSAECONNRESET || errcode == WSAECONNABORTED || errcode == WSAESHUTDOWN); }
#else
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
inline bool connectInProgress(int errcode){ return (errcode == EAGAIN || errcode == EWOULDBLOCK || errcode == EINPROGRESS || errcode == EALREADY); }
inline bool isDisconnected(int errcode) { return (errcode == EPIPE || errcode == ECONNRESET || errcode == ECONNABORTED || errcode == ESHUTDOWN); }
#endif
#ifndef POLL_ERR
@ -104,11 +108,9 @@ inline bool connectInProgress(int errcode){ return (errcode == EAGAIN || errcode
// Server Listening Port
#define SERVER_PORT 27312
// Default GameMode Port
// Default GameMode definitions
#define ADHOC_GAMEMODE_PORT 31000
#define GAMEMODE_UPDATE_INTERVAL 12000 // usec, based on JPCSP
#define GAMEMODE_BUFFER_SIZE 0x8000
#define GAMEMODE_UPDATE_INTERVAL 10000 // 12000 usec on JPCSP, but 10000 works better on BattleZone (in order to get full speed 60 FPS)
// psp strutcs and definitions
#define ADHOCCTL_MODE_NONE -1
@ -156,15 +158,15 @@ inline bool connectInProgress(int errcode){ return (errcode == EAGAIN || errcode
#define ADHOC_EV_CONNECT 0x0004
#define ADHOC_EV_ACCEPT 0x0008
#define ADHOC_EV_FLUSH 0x0010
#define ADHOC_EV_INVALID 0x0100
#define ADHOC_EV_DELETE 0x0200
#define ADHOC_EV_INVALID 0x0100 // ignored on events but can be raised on revents? similar to POLLNVAL on posix poll?
#define ADHOC_EV_DELETE 0x0200 // ignored on events but can be raised on revents? similar to POLLERR on posix poll?
#define ADHOC_EV_ALERT 0x0400
#define ADHOC_EV_DISCONNECT 0x0800
#define ADHOC_EV_DISCONNECT 0x0800 // ignored on events but can be raised on revents? similar to POLLHUP on posix poll?
// PTP Connection States
#define ADHOC_PTP_STATE_CLOSED 0
#define ADHOC_PTP_STATE_LISTEN 1
#define ADHOC_PTP_STATE_SYN_SENT 2
#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 -> Established
#define ADHOC_PTP_STATE_SYN_RCVD 3
#define ADHOC_PTP_STATE_ESTABLISHED 4
@ -209,9 +211,9 @@ extern uint8_t broadcastMAC[ETHER_ADDR_LEN];
// Malloc Pool Information
typedef struct SceNetMallocStat {
s32_le pool; // Pointer to the pool? // This should be the poolSize isn't?
s32_le maximum; // Maximum size of the pool? Maximum usage (ie. pool- free) ?
s32_le free; // How much memory is free
s32_le pool; // On Vantage Master Portable this is 0x1ffe0 on sceNetGetMallocStat, while the poolSize arg on sceNetInit was 0x20000
s32_le maximum; // On Vantage Master Portable this is 0x4050, Footprint of Highest amount allocated so far?
s32_le free; // On Vantage Master Portable this is 0x1f300, VMP compares this value with required size before sending data
} PACK SceNetMallocStat;
// Adhoc Virtual Network Name
@ -303,6 +305,7 @@ typedef struct SceNetAdhocctlGameModeInfo {
// GameModeUpdateInfo
typedef struct GameModeUpdateInfo {
u32_le length; //size of GameModeUpdateInfo (16 bytes)
s32_le updated;
u64_le timeStamp;
} PACK GameModeUpdateInfo;
@ -353,10 +356,14 @@ typedef struct AdhocSocket {
s32_le type; // SOCK_PDP/SOCK_PTP
s32_le flags; // Socket Alert Flags
s32_le alerted_flags; // Socket Alerted Flags
s32_le nonblocking; // last non-blocking flag
u32 buffer_size;
u32 send_timeout; // default connect timeout
u32 recv_timeout; // default accept timeout
s32 retry_count; // combined with timeout to be used on keepalive
s32 retry_interval; // related to keepalive
s32 retry_count; // multiply with retry interval to be used as keepalive timeout
s32 attemptCount; // connect/accept attempts
u64 lastAttempt; // timestamp to retry again
union {
SceNetAdhocPdpStat pdp;
SceNetAdhocPtpStat ptp;
@ -939,12 +946,14 @@ bool isLocalMAC(const SceNetEtherAddr * addr);
bool isPDPPortInUse(uint16_t port);
/**
* Check whether PTP Port is in use or not
* Check whether PTP Port is in use or not (only sockets with non-Listening state will be considered as in use)
* @param port To-be-checked Port Number
* @param forListen to check for listening or non-listening port
* @return 1 if in use or... 0
*/
bool isPTPPortInUse(uint16_t port);
bool isPTPPortInUse(uint16_t port, bool forListen);
// Convert MAC address to string
std::string mac2str(SceNetEtherAddr* mac);
/*

View file

@ -68,6 +68,7 @@ u32 netApctlState;
u32 apctlThreadHackAddr = 0;
u32_le apctlThreadCode[3];
SceUID apctlThreadID = 0;
int apctlStateEvent = -1;
int actionAfterApctlMipsCall;
std::recursive_mutex apctlEvtMtx;
std::deque<ApctlArgs> apctlEvents;
@ -125,10 +126,47 @@ void InitLocalhostIP() {
isLocalServer = (!strcasecmp(serverStr.c_str(), "localhost") || serverStr.find("127.") == 0);
}
static void __ApctlState(u64 userdata, int cyclesLate) {
SceUID threadID = userdata >> 32;
int uid = (int)(userdata & 0xFFFFFFFF);
int event = uid - 1;
s64 result = 0;
u32 error = 0;
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_NET, error);
if (waitID == 0 || error != 0)
return;
u32 waitVal = __KernelGetWaitValue(threadID, error);
if (error == 0) {
netApctlState = waitVal;
}
__KernelResumeThreadFromWait(threadID, result);
DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %d) Result (%08x) of sceNetApctl - Event: %d, State: %d", waitID, error, (int)result, event, netApctlState);
}
// Used to change Apctl State after a delay and before executing callback mipscall (since we don't have beforeAction)
int ScheduleApctlState(int event, int newState, int usec, const char* reason) {
int uid = event + 1;
if (apctlStateEvent < 0)
apctlStateEvent = CoreTiming::RegisterEvent("__ApctlState", __ApctlState);
u64 param = ((u64)__KernelGetCurThread()) << 32 | uid;
CoreTiming::ScheduleEvent(usToCycles(usec), apctlStateEvent, param);
__KernelWaitCurThread(WAITTYPE_NET, uid, newState, 0, false, reason);
return 0;
}
void __NetApctlInit() {
netApctlInited = false;
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED;
apctlStateEvent = CoreTiming::RegisterEvent("__ApctlState", __ApctlState);
apctlHandlers.clear();
apctlEvents.clear();
memset(&netApctlInfo, 0, sizeof(netApctlInfo));
}
@ -182,6 +220,8 @@ void __NetApctlShutdown() {
kernelMemory.Free(apctlThreadHackAddr);
apctlThreadHackAddr = 0;
}
apctlHandlers.clear();
apctlEvents.clear();
}
void __NetShutdown() {
@ -216,7 +256,7 @@ void netValidateLoopMemory() {
// This feels like a dubious proposition, mostly...
void __NetDoState(PointerWrap &p) {
auto s = p.Section("sceNet", 1, 4);
auto s = p.Section("sceNet", 1, 5);
if (!s)
return;
@ -260,6 +300,15 @@ void __NetDoState(PointerWrap &p) {
apctlThreadHackAddr = 0;
apctlThreadID = 0;
}
if (s >= 5) {
Do(p, apctlStateEvent);
if (apctlStateEvent != -1) {
CoreTiming::RestoreRegisterEvent(apctlStateEvent, "__ApctlState", __ApctlState);
}
}
else {
apctlStateEvent = -1;
}
if (p.mode == p.MODE_READ) {
// Let's not change "Inited" value when Loading SaveState in the middle of multiplayer to prevent memory & port leaks
@ -370,78 +419,106 @@ std::string error2str(u32 errorCode) {
void __NetApctlCallbacks()
{
std::lock_guard<std::recursive_mutex> apctlGuard(apctlEvtMtx);
hleSkipDeadbeef();
int delayus = 10000;
// We are temporarily borrowing APctl thread for NpAuth callbacks for testing to simulate authentication
if (!npAuthEvents.empty())
{
auto args = npAuthEvents.front();
auto& id = args.data[0];
auto& result = args.data[1];
auto& argAddr = args.data[2];
npAuthEvents.pop_front();
delayus = (adhocEventDelay + adhocExtraDelay);
int handlerID = id - 1;
for (std::map<int, NpAuthHandler>::iterator it = npAuthHandlers.begin(); it != npAuthHandlers.end(); ++it) {
if (it->first == handlerID) {
DEBUG_LOG(SCENET, "NpAuthCallback [HandlerID=%i][RequestID=%d][Result=%d][ArgsPtr=%08x]", it->first, id, result, it->second.argument);
// TODO: Update result / args.data[1] with the actual ticket length (or error code?)
hleEnqueueCall(it->second.entryPoint, 3, args.data);
}
}
}
// How AP works probably like this: Game use sceNetApctl function -> sceNetApctl let the hardware know and do their's thing and have a new State -> Let the game know the resulting State through Event on their handler
if (!apctlEvents.empty())
{
auto args = apctlEvents.front();
auto oldState = &args.data[0];
auto newState = &args.data[1];
auto event = &args.data[2];
auto error = &args.data[3];
auto& oldState = args.data[0];
auto& newState = args.data[1];
auto& event = args.data[2];
auto& error = args.data[3];
apctlEvents.pop_front();
// Adjust delay according to current event. Added an extra delay to prevent I/O Timing method from causing disconnection
if (*event == PSP_NET_APCTL_EVENT_CONNECT_REQUEST || *event == PSP_NET_APCTL_EVENT_GET_IP || *event == PSP_NET_APCTL_EVENT_SCAN_REQUEST)
delayus = (adhocEventDelayMS + 2 * adhocExtraPollDelayMS) * 1000;
// Adjust delay according to current event.
if (event == PSP_NET_APCTL_EVENT_CONNECT_REQUEST || event == PSP_NET_APCTL_EVENT_GET_IP || event == PSP_NET_APCTL_EVENT_SCAN_REQUEST)
delayus = adhocEventDelay;
else
delayus = (adhocEventPollDelayMS + 2 * adhocExtraPollDelayMS) * 1000;
delayus = adhocEventPollDelay;
// Do we need to change the oldState? even if there was error?
//if (*error == 0)
*oldState = netApctlState;
//if (error == 0)
// oldState = netApctlState;
// Need to make sure netApctlState is updated before calling the callback's mipscall so the game can GetState()/GetInfo() within their handler's subroutine and make use the new State/Info
// Should we update NewState & Error accordingly to Event before executing the mipscall ? sceNetApctl* functions might want to set the error value tho, so we probably should leave it untouched
//*error = 0;
switch (*event) {
// Should we update NewState & Error accordingly to Event before executing the mipscall ? sceNetApctl* functions might want to set the error value tho, so we probably should leave it untouched, right?
//error = 0;
switch (event) {
case PSP_NET_APCTL_EVENT_CONNECT_REQUEST:
netApctlState = PSP_NET_APCTL_STATE_JOINING; // Should we set the State to PSP_NET_APCTL_STATE_DISCONNECTED if there was error?
if (*error == 0) apctlEvents.push_front({ netApctlState, netApctlState, PSP_NET_APCTL_EVENT_ESTABLISHED, 0 }); // Should we use PSP_NET_APCTL_EVENT_EAP_AUTH if securityType is not NONE?
newState = PSP_NET_APCTL_STATE_JOINING; // Should we set the State to PSP_NET_APCTL_STATE_DISCONNECTED if there was error?
if (error == 0)
apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_ESTABLISHED, 0 }); // Should we use PSP_NET_APCTL_EVENT_EAP_AUTH if securityType is not NONE?
break;
case PSP_NET_APCTL_EVENT_ESTABLISHED:
netApctlState = PSP_NET_APCTL_STATE_GETTING_IP;
if (*error == 0) apctlEvents.push_front({ netApctlState, netApctlState, PSP_NET_APCTL_EVENT_GET_IP, 0 });
newState = PSP_NET_APCTL_STATE_GETTING_IP;
if (error == 0)
apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_GET_IP, 0 });
break;
case PSP_NET_APCTL_EVENT_GET_IP:
netApctlState = PSP_NET_APCTL_STATE_GOT_IP;
newState = PSP_NET_APCTL_STATE_GOT_IP;
NetApctl_InitInfo();
break;
case PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST:
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED;
newState = PSP_NET_APCTL_STATE_DISCONNECTED;
break;
case PSP_NET_APCTL_EVENT_SCAN_REQUEST:
netApctlState = PSP_NET_APCTL_STATE_SCANNING;
if (*error == 0) apctlEvents.push_front({ netApctlState, netApctlState, PSP_NET_APCTL_EVENT_SCAN_COMPLETE, 0 });
newState = PSP_NET_APCTL_STATE_SCANNING;
if (error == 0)
apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_SCAN_COMPLETE, 0 });
break;
case PSP_NET_APCTL_EVENT_SCAN_COMPLETE:
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED;
newState = PSP_NET_APCTL_STATE_DISCONNECTED;
break;
case PSP_NET_APCTL_EVENT_EAP_AUTH: // Is this suppose to happen between JOINING and ESTABLISHED ?
netApctlState = PSP_NET_APCTL_STATE_EAP_AUTH;
if (*error == 0) apctlEvents.push_front({ netApctlState, netApctlState, PSP_NET_APCTL_EVENT_KEY_EXCHANGE, 0 }); // not sure if KEY_EXCHANGE is the next step after AUTH or not tho
newState = PSP_NET_APCTL_STATE_EAP_AUTH;
if (error == 0)
apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_KEY_EXCHANGE, 0 }); // not sure if KEY_EXCHANGE is the next step after AUTH or not tho
break;
case PSP_NET_APCTL_EVENT_KEY_EXCHANGE: // Is this suppose to happen between JOINING and ESTABLISHED ?
netApctlState = PSP_NET_APCTL_STATE_KEY_EXCHANGE;
if (*error == 0) apctlEvents.push_front({ netApctlState, netApctlState, PSP_NET_APCTL_EVENT_ESTABLISHED, 0 });
newState = PSP_NET_APCTL_STATE_KEY_EXCHANGE;
if (error == 0)
apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_ESTABLISHED, 0 });
break;
case PSP_NET_APCTL_EVENT_RECONNECT:
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED;
if (*error == 0) apctlEvents.push_front({ netApctlState, netApctlState, PSP_NET_APCTL_EVENT_CONNECT_REQUEST, 0 });
newState = PSP_NET_APCTL_STATE_DISCONNECTED;
if (error == 0)
apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_CONNECT_REQUEST, 0 });
break;
}
// Do we need to change the newState? even if there were error?
//if (*error == 0)
*newState = netApctlState;
//if (error != 0)
// newState = netApctlState;
// Since 0 is a valid index to types_ we use -1 to detects if it was loaded from an old save state
if (actionAfterApctlMipsCall < 0) {
@ -450,38 +527,19 @@ void __NetApctlCallbacks()
// Run mipscall. Should we skipped executing the mipscall if oldState == newState?
for (std::map<int, ApctlHandler>::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); ++it) {
DEBUG_LOG(SCENET, "ApctlCallback [ID=%i][OldState=%d][NewState=%d][Event=%d][Error=%d][ArgsPtr=%08x]", it->first, *oldState, *newState, *event, *error, it->second.argument);
DEBUG_LOG(SCENET, "ApctlCallback [ID=%i][OldState=%d][NewState=%d][Event=%d][Error=%08x][ArgsPtr=%08x]", it->first, oldState, newState, event, error, it->second.argument);
args.data[4] = it->second.argument;
AfterApctlMipsCall* after = (AfterApctlMipsCall*)__KernelCreateAction(actionAfterApctlMipsCall);
after->SetData(it->first, *oldState, *newState, *event, *error, it->second.argument);
after->SetData(it->first, oldState, newState, event, error, it->second.argument);
hleEnqueueCall(it->second.entryPoint, 5, args.data, after);
}
// Similar to Adhocctl, new State might need to be set after delayed, right before executing the mipscall (ie. simulated beforeAction)
ScheduleApctlState(event, newState, delayus, "apctl callback state");
return;
}
// We are temporarily borrowing APctl thread for NpAuth callbacks for testing to simulate authentication
if (!npAuthEvents.empty())
{
auto args = npAuthEvents.front();
auto id = &args.data[0];
auto result = &args.data[1];
auto argAddr = &args.data[2];
npAuthEvents.pop_front();
delayus = (adhocEventDelayMS + 2 * adhocExtraPollDelayMS) * 1000;
int handlerID = *id - 1;
for (std::map<int, NpAuthHandler>::iterator it = npAuthHandlers.begin(); it != npAuthHandlers.end(); ++it) {
if (it->first == handlerID) {
DEBUG_LOG(SCENET, "NpAuthCallback [HandlerID=%i][RequestID=%d][Result=%d][ArgsPtr=%08x]", it->first, *id, *result, it->second.argument);
// TODO: Update result / args.data[1] with the actual ticket length (or error code?)
hleEnqueueCall(it->second.entryPoint, 3, args.data);
}
}
}
// Must be delayed long enough whenever there is a pending callback.
// Must be delayed long enough whenever there is a pending callback to make sure previous callback & it's afterAction are fully executed
sceKernelDelayThread(delayus);
hleSkipDeadbeef();
}
static inline u32 AllocUser(u32 size, bool fromTop, const char *name) {
@ -535,7 +593,7 @@ static u32 sceNetTerm() {
int retval = Net_Term();
// Give time to make sure everything are cleaned up
hleDelayResult(retval, "give time to init/cleanup", adhocEventDelayMS * 1000);
hleEatMicro(adhocDefaultDelay);
return retval;
}
@ -583,14 +641,15 @@ static int sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netini
}
WARN_LOG(SCENET, "sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d) at %08x", poolSize, calloutPri, calloutStack, netinitPri, netinitStack, currentMIPS->pc);
netInited = true;
netMallocStat.pool = poolSize; // This should be the poolSize isn't?
netMallocStat.maximum = poolSize/2; // According to JPCSP's sceNetGetMallocStat this is Currently Used size = (poolSize - free), faked to half the pool
netMallocStat.free = poolSize - netMallocStat.maximum;
netMallocStat.pool = poolSize - 0x20; // On Vantage Master Portable this is slightly (32 bytes) smaller than the poolSize arg when tested with JPCSP + prx files
netMallocStat.maximum = 0x4050; // Dummy maximum foot print
netMallocStat.free = netMallocStat.pool; // Dummy free size, we should set this high enough to prevent any issue (ie. Vantage Master Portable), this is probably the only field being checked by games?
// Clear Socket Translator Memory
memset(&adhocSockets, 0, sizeof(adhocSockets));
netInited = true;
return hleLogSuccessI(SCENET, 0);
}
@ -712,7 +771,7 @@ static void sceNetEtherStrton(u32 bufferPtr, u32 macPtr) {
// Write static data since we don't actually manage any memory for sceNet* yet.
static int sceNetGetMallocStat(u32 statPtr) {
VERBOSE_LOG(SCENET, "UNTESTED sceNetGetMallocStat(%x)", statPtr);
VERBOSE_LOG(SCENET, "UNTESTED sceNetGetMallocStat(%x) at %08x", statPtr, currentMIPS->pc);
if(Memory::IsValidAddress(statPtr))
Memory::WriteStruct(statPtr, &netMallocStat);
else

View file

@ -219,6 +219,7 @@ private:
extern bool netInetInited;
extern bool netApctlInited;
extern u32 netApctlState;
extern SceNetApctlInfoInternal netApctlInfo;
template <typename I> std::string num2hex(I w, size_t hex_len = sizeof(I) << 1);

File diff suppressed because it is too large Load diff

View file

@ -98,11 +98,12 @@ int NetAdhoc_Term();
extern bool netAdhocInited;
extern bool netAdhocctlInited;
extern bool networkInited;
extern int adhocDefaultTimeout;
extern int adhocExtraPollDelayMS;
extern int adhocEventPollDelayMS;
extern int adhocMatchingEventDelayMS;
extern int adhocEventDelayMS; // This will affect the duration of "Connecting..." dialog/message box in .Hack//Link and Naruto Ultimate Ninja Heroes 3
extern int adhocDefaultTimeout; //3000000 usec
extern int adhocDefaultDelay; //10000
extern int adhocExtraDelay; //20000
extern int adhocEventPollDelay; //100000; // Seems to be the same with PSP_ADHOCCTL_RECV_TIMEOUT
extern int adhocMatchingEventDelay; //30000
extern int adhocEventDelay; //1000000
extern std::recursive_mutex adhocEvtMtx;
extern int IsAdhocctlInCB;

View file

@ -844,6 +844,7 @@ void GameSettingsScreen::CreateViews() {
networkingSettings->Add(new PopupSliderChoice(&g_Config.iPortOffset, 0, 60000, n->T("Port offset", "Port offset (0 = PSP compatibility)"), 100, screenManager()));
networkingSettings->Add(new PopupSliderChoice(&g_Config.iMinTimeout, 1, 15000, n->T("Minimum Timeout", "Minimum Timeout (override low latency in ms)"), 100, screenManager()));
networkingSettings->Add(new CheckBox(&g_Config.bTCPNoDelay, n->T("TCP No Delay", "TCP No Delay (faster TCP)")));
networkingSettings->Add(new CheckBox(&g_Config.bForcedFirstConnect, n->T("Forced First Connect", "Forced First Connect (faster Connect)")));
ViewGroup *toolsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
toolsScroll->SetTag("GameSettingsTools");
@ -1806,7 +1807,7 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) {
buttonsRow2->Add(new Button(di->T("Toggle List")))->OnClick.Handle(this, &HostnameSelectScreen::OnShowIPListClick);
buttonsRow2->Add(new Spacer(new LinearLayoutParams(1.0, G_RIGHT)));
std::vector<std::string> listIP = {"myneighborsushicat.com", "localhost"};
std::vector<std::string> listIP = {"myneighborsushicat.com", "socom.cc", "localhost"}; // TODO: Add some saved recent history too?
net::GetIPList(listIP);
ipRows_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0));
ScrollView* scrollView = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));