mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
implement nonblock ptp connect
This commit is contained in:
@@ -45,8 +45,6 @@
|
||||
#include "GPU/GPU.h"
|
||||
#include "GPU/GPUCommon.h"
|
||||
|
||||
#include "ext/aemu_postoffice/client/postoffice_client.h"
|
||||
|
||||
// Step command to execute next
|
||||
static std::mutex g_stepMutex;
|
||||
|
||||
@@ -158,9 +156,6 @@ void Core_NotifyLifecycle(CoreLifecycle stage) {
|
||||
void Core_Stop() {
|
||||
Core_ResetException();
|
||||
Core_UpdateState(CORE_POWERDOWN);
|
||||
|
||||
// close all active aemu postoffice sessions if exist
|
||||
aemu_post_office_init();
|
||||
}
|
||||
|
||||
void Core_UpdateState(CoreState newState) {
|
||||
|
||||
+36
-9
@@ -57,6 +57,8 @@
|
||||
|
||||
#include "Core/HLE/NetAdhocCommon.h"
|
||||
|
||||
#include "ext/aemu_postoffice/client/postoffice_client.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef errno
|
||||
#define errno WSAGetLastError()
|
||||
@@ -418,17 +420,42 @@ void deleteAllAdhocSockets() {
|
||||
// Active Socket
|
||||
if (adhocSockets[i] != NULL) {
|
||||
auto sock = adhocSockets[i];
|
||||
int fd = -1;
|
||||
|
||||
if (sock->type == SOCK_PTP)
|
||||
fd = sock->data.ptp.id;
|
||||
else if (sock->type == SOCK_PDP)
|
||||
fd = sock->data.pdp.id;
|
||||
if (g_Config.bServerHasRelay){
|
||||
if (sock->type == SOCK_PTP){
|
||||
// sync
|
||||
if (sock->connect_threads != NULL){
|
||||
while(sock->connect_threads->size() != 0){
|
||||
sock->connect_threads->at(sock->connect_threads->size() - 1).join();
|
||||
sock->connect_threads->pop_back();
|
||||
}
|
||||
delete sock->connect_threads;
|
||||
}
|
||||
void *socket = sock->postoffice_handle;
|
||||
if (socket != NULL){
|
||||
if (sock->data.ptp.state == ADHOC_PTP_STATE_LISTEN){
|
||||
ptp_listen_close(socket);
|
||||
}else{
|
||||
ptp_close(socket);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (sock->postoffice_handle != NULL){
|
||||
pdp_delete(sock->postoffice_handle);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int fd = -1;
|
||||
if (sock->type == SOCK_PTP)
|
||||
fd = sock->data.ptp.id;
|
||||
else if (sock->type == SOCK_PDP)
|
||||
fd = sock->data.pdp.id;
|
||||
|
||||
if (fd > 0) {
|
||||
// Close Socket
|
||||
shutdown(fd, SD_RECEIVE);
|
||||
closesocket(fd);
|
||||
if (fd > 0) {
|
||||
// Close Socket
|
||||
shutdown(fd, SD_RECEIVE);
|
||||
closesocket(fd);
|
||||
}
|
||||
}
|
||||
// Free Memory
|
||||
free(adhocSockets[i]);
|
||||
|
||||
@@ -329,6 +329,7 @@ typedef struct AdhocSocket {
|
||||
SceNetAdhocPtpStat ptp;
|
||||
} data;
|
||||
void *postoffice_handle; // aemu_postoffice mode handle
|
||||
std::vector<std::thread> *connect_threads;
|
||||
} PACK AdhocSocket;
|
||||
|
||||
// Gamemode Optional Peer Buffer Data
|
||||
|
||||
+74
-11
@@ -1021,6 +1021,7 @@ static int ptp_accept_postoffice(int idx, SceNetEtherAddr *saddr, uint16_t *spor
|
||||
internal->data.ptp.snd_sb_cc = adhocSockets[idx]->data.ptp.snd_sb_cc;
|
||||
internal->data.ptp.id = AEMU_POSTOFFICE_ID;
|
||||
internal->flags = 0;
|
||||
internal->connect_threads = NULL;
|
||||
|
||||
AdhocSocket **slot = NULL;
|
||||
int i;
|
||||
@@ -3778,6 +3779,27 @@ int RecreatePtpSocket(int ptpId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t get_random_unused_ptp_port(){
|
||||
uint16_t test_port = rand() % 65534 + 1;
|
||||
auto port_in_use = [&test_port] {
|
||||
for (int i = 0; i < MAX_SOCKET; i++){
|
||||
if (adhocSockets[i] != NULL &&
|
||||
adhocSockets[i]->type == SOCK_PTP &&
|
||||
test_port == adhocSockets[i]->data.ptp.lport)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
while(port_in_use()){
|
||||
test_port = rand() % 65534 + 1;
|
||||
}
|
||||
|
||||
return test_port;
|
||||
}
|
||||
|
||||
static int ptp_open_postoffice(const SceNetEtherAddr *saddr, uint16_t sport, const SceNetEtherAddr *daddr, uint16_t dport, uint32_t bufsize){
|
||||
AdhocSocket *internal = (AdhocSocket *)malloc(sizeof(AdhocSocket));
|
||||
if (internal == NULL){
|
||||
@@ -3789,13 +3811,14 @@ static int ptp_open_postoffice(const SceNetEtherAddr *saddr, uint16_t sport, con
|
||||
internal->postoffice_handle = NULL;
|
||||
internal->data.ptp.state = ADHOC_PTP_STATE_CLOSED;
|
||||
internal->data.ptp.laddr = *saddr;
|
||||
internal->data.ptp.lport = sport;
|
||||
internal->data.ptp.lport = sport == 0 ? get_random_unused_ptp_port() : sport;
|
||||
internal->data.ptp.paddr = *daddr;
|
||||
internal->data.ptp.pport = dport;
|
||||
internal->data.ptp.rcv_sb_cc = bufsize;
|
||||
internal->data.ptp.snd_sb_cc = 0;
|
||||
internal->data.ptp.id = AEMU_POSTOFFICE_ID;
|
||||
internal->flags = 0;
|
||||
internal->connect_threads = new std::vector<std::thread>();
|
||||
|
||||
AdhocSocket **slot = NULL;
|
||||
int i;
|
||||
@@ -3852,7 +3875,7 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac,
|
||||
}
|
||||
|
||||
// Random Port required
|
||||
if (sport == 0) {
|
||||
if (sport == 0 && !g_Config.bServerHasRelay) {
|
||||
isClient = true;
|
||||
//sport 0 should be shifted back to 0 when using offset Phantasy Star Portable 2 use this
|
||||
sport = -static_cast<int>(portOffset);
|
||||
@@ -4235,23 +4258,51 @@ static int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int
|
||||
}
|
||||
|
||||
static int ptp_connect_postoffice(int idx, uint32_t timeout, int nonblock){
|
||||
INFO_LOG(Log::sceNet, "%s: id %d timeout %u nonblock %d", __func__, idx + 1, timeout, nonblock);
|
||||
AdhocSocket *internal = adhocSockets[idx];
|
||||
|
||||
// Phantasy Star Portable 2 will try to reconnect even when previous connect already success, so we should return success too if it's already connected
|
||||
if (internal->data.ptp.state == ADHOC_PTP_STATE_ESTABLISHED)
|
||||
return 0;
|
||||
|
||||
uint64_t begin = CoreTiming::GetGlobalTimeUsScaled();
|
||||
uint64_t end = begin + timeout;
|
||||
|
||||
struct aemu_post_office_sock_addr addr;
|
||||
addr.addr = g_adhocServerIP.in.sin_addr.s_addr;
|
||||
addr.port = htons(AEMU_POSTOFFICE_PORT);
|
||||
|
||||
void *ptp_socket = NULL;
|
||||
if (nonblock || timeout != 0){
|
||||
// TODO actual notify based timeout
|
||||
int timeout_return = nonblock ? SCE_NET_ADHOC_ERROR_WOULD_BLOCK : SCE_NET_ADHOC_ERROR_TIMEOUT;
|
||||
|
||||
if (internal->data.ptp.state == ADHOC_PTP_STATE_CLOSED){
|
||||
while(internal->connect_threads->size() != 0){
|
||||
internal->connect_threads->at(internal->connect_threads->size() - 1).join();
|
||||
internal->connect_threads->pop_back();
|
||||
}
|
||||
|
||||
internal->data.ptp.state = ADHOC_PTP_STATE_SYN_SENT;
|
||||
|
||||
internal->connect_threads->push_back(std::thread([internal, addr, idx] {
|
||||
int state;
|
||||
void *ptp_socket = ptp_connect_v4(&addr, (const char *)&internal->data.ptp.laddr, internal->data.ptp.lport + portOffset, (const char *)&internal->data.ptp.paddr, internal->data.ptp.pport + portOffset, &state);
|
||||
if (ptp_socket == NULL){
|
||||
ERROR_LOG(Log::sceNet, "%s: failed connecting to ptp socket, %d", __func__, state);
|
||||
internal->data.ptp.state = ADHOC_PTP_STATE_CLOSED;
|
||||
return;
|
||||
}
|
||||
internal->postoffice_handle = ptp_socket;
|
||||
INFO_LOG(Log::sceNet, "%s: connected ptp socket with id %d %p", __func__, idx + 1, internal->postoffice_handle);
|
||||
internal->data.ptp.state = ADHOC_PTP_STATE_ESTABLISHED;
|
||||
return;
|
||||
}));
|
||||
|
||||
return timeout_return;
|
||||
}
|
||||
// ADHOC_PTP_STATE_SYN_SENT
|
||||
return timeout_return;
|
||||
}
|
||||
|
||||
// note that postoffice connect was designed to be a blocked operation, if the other side don't accept, or listen session not found, the server will kick us out
|
||||
int state;
|
||||
ptp_socket = ptp_connect_v4(&addr, (const char *)&internal->data.ptp.laddr, internal->data.ptp.lport + portOffset, (const char *)&internal->data.ptp.paddr, internal->data.ptp.pport + portOffset, &state);
|
||||
void *ptp_socket = ptp_connect_v4(&addr, (const char *)&internal->data.ptp.laddr, internal->data.ptp.lport + portOffset, (const char *)&internal->data.ptp.paddr, internal->data.ptp.pport + portOffset, &state);
|
||||
if (ptp_socket == NULL){
|
||||
ERROR_LOG(Log::sceNet, "%s: failed connecting to ptp socket, %d", __func__, state);
|
||||
return SCE_NET_ADHOC_ERROR_CONNECTION_REFUSED;
|
||||
@@ -4409,12 +4460,23 @@ static int sceNetAdhocPtpConnect(int id, int timeout, int flag) {
|
||||
|
||||
static int ptp_close_postoffice(int idx){
|
||||
AdhocSocket *internal = adhocSockets[idx];
|
||||
|
||||
// sync
|
||||
if (internal->connect_threads != NULL){
|
||||
while(internal->connect_threads->size() != 0){
|
||||
internal->connect_threads->at(internal->connect_threads->size() - 1).join();
|
||||
internal->connect_threads->pop_back();
|
||||
}
|
||||
|
||||
delete internal->connect_threads;
|
||||
}
|
||||
|
||||
void *socket = internal->postoffice_handle;
|
||||
if (socket != NULL){
|
||||
if (internal->data.ptp.state == ADHOC_PTP_STATE_ESTABLISHED){
|
||||
ptp_close(socket);
|
||||
}else if (internal->data.ptp.state == ADHOC_PTP_STATE_LISTEN){
|
||||
if (internal->data.ptp.state == ADHOC_PTP_STATE_LISTEN){
|
||||
ptp_listen_close(socket);
|
||||
}else{
|
||||
ptp_close(socket);
|
||||
}
|
||||
}
|
||||
adhocSockets[idx] = NULL;
|
||||
@@ -4497,6 +4559,7 @@ static int ptp_listen_postoffice(const SceNetEtherAddr *saddr, uint16_t sport, u
|
||||
internal->data.ptp.snd_sb_cc = 0;
|
||||
internal->data.ptp.id = AEMU_POSTOFFICE_ID;
|
||||
internal->flags = 0;
|
||||
internal->connect_threads = NULL;
|
||||
|
||||
AdhocSocket **slot = NULL;
|
||||
int i;
|
||||
|
||||
Reference in New Issue
Block a user