more graceful handling of disconnects

This commit is contained in:
Arisotura 2022-08-27 13:17:15 +02:00
parent 47bc7bb323
commit b858114c48
5 changed files with 85 additions and 16 deletions

View File

@ -157,10 +157,11 @@ void WriteGBASave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen
bool MP_Init();
void MP_DeInit();
int MP_SendPacket(u8* data, int len, u64 timestamp);
int MP_RecvPacket(u8* data, bool block, u64* timestamp);
int MP_RecvPacket(u8* data, u64* timestamp);
int MP_SendCmd(u8* data, int len, u64 timestamp);
int MP_SendReply(u8* data, int len, u64 timestamp, u16 aid);
int MP_SendAck(u8* data, int len, u64 timestamp);
int MP_RecvHostPacket(u8* data, u64* timestamp);
u16 MP_RecvReplies(u8* data, u64 timestamp, u16 aidmask);

View File

@ -1150,6 +1150,7 @@ bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames
if (IOPORT(W_RXBufBegin) == IOPORT(W_RXBufEnd))
return false;
int rxlen;
u16 framelen;
u16 framectl;
u8 txrate;
@ -1160,9 +1161,24 @@ bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames
for (;;)
{
timestamp = 0;
int rxlen = Platform::MP_RecvPacket(RXBuffer, (type != 0), &timestamp);
if ((rxlen == 0) && (type == 0)) rxlen = WifiAP::RecvPacket(RXBuffer);
if (rxlen == 0) return false;
if (type == 0)
{
rxlen = Platform::MP_RecvPacket(RXBuffer, &timestamp);
if (rxlen <= 0)
rxlen = WifiAP::RecvPacket(RXBuffer);
}
else
{
rxlen = Platform::MP_RecvHostPacket(RXBuffer, &timestamp);
if (rxlen < 0)
{
// host is gone
IsMPClient = false;
}
}
if (rxlen <= 0) return false;
if (rxlen < 12+24) continue;
framelen = *(u16*)&RXBuffer[10];

View File

@ -81,6 +81,8 @@ const u32 kReplyEnd = kQueueSize;
const int RecvTimeout = 500;
int LastHostID;
// we need to come up with our own abstraction layer for named semaphores
// because QSystemSemaphore doesn't support waiting with a timeout
@ -220,6 +222,8 @@ bool Init()
SemInit(InstanceID);
SemInit(16+InstanceID);
LastHostID = -1;
printf("MP comm init OK, instance ID %d\n", InstanceID);
return true;
@ -363,12 +367,7 @@ int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
return len;
}
int SendPacket(u8* packet, int len, u64 timestamp)
{
return SendPacketGeneric(0, packet, len, timestamp);
}
int RecvPacket(u8* packet, bool block, u64* timestamp)
int RecvPacketGeneric(u8* packet, bool block, u64* timestamp)
{
for (;;)
{
@ -402,14 +401,29 @@ int RecvPacket(u8* packet, bool block, u64* timestamp)
}
if (pktheader.Length)
{
FIFORead(0, packet, pktheader.Length);
if (pktheader.Type == 1)
LastHostID = pktheader.SenderID;
}
if (timestamp) *timestamp = pktheader.Timestamp;
MPQueue->unlock();
return pktheader.Length;
}
}
int SendPacket(u8* packet, int len, u64 timestamp)
{
return SendPacketGeneric(0, packet, len, timestamp);
}
int RecvPacket(u8* packet, u64* timestamp)
{
return RecvPacketGeneric(packet, false, timestamp);
}
int SendCmd(u8* packet, int len, u64 timestamp)
{
@ -426,10 +440,42 @@ int SendAck(u8* packet, int len, u64 timestamp)
return SendPacketGeneric(3, packet, len, timestamp);
}
int RecvHostPacket(u8* packet, u64* timestamp)
{
if (LastHostID != -1)
{
// check if the host is still connected
MPQueue->lock();
u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0];
u16 curinstmask = header->InstanceBitmask;
MPQueue->unlock();
if (!(curinstmask & (1 << LastHostID)))
return -1;
}
return RecvPacketGeneric(packet, true, timestamp);
}
u16 RecvReplies(u8* packets, u64 timestamp, u16 aidmask)
{
u16 ret = 0;
u16 instmask = (1 << InstanceID);
u16 myinstmask = (1 << InstanceID);
u16 curinstmask;
{
MPQueue->lock();
u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0];
curinstmask = header->InstanceBitmask;
MPQueue->unlock();
}
// if all clients have left: return early
if ((myinstmask & curinstmask) == curinstmask)
return 0;
for (;;)
{
@ -472,8 +518,8 @@ u16 RecvReplies(u8* packets, u64 timestamp, u16 aidmask)
ret |= (1 << aid);
}
instmask |= (1 << pktheader.SenderID);
if ((instmask & header->InstanceBitmask) == header->InstanceBitmask)
myinstmask |= (1 << pktheader.SenderID);
if ((myinstmask & curinstmask) == curinstmask)
{
// all the clients have sent their reply

View File

@ -27,10 +27,11 @@ namespace LocalMP
bool Init();
void DeInit();
int SendPacket(u8* data, int len, u64 timestamp);
int RecvPacket(u8* data, bool block, u64* timestamp);
int RecvPacket(u8* data, u64* timestamp);
int SendCmd(u8* data, int len, u64 timestamp);
int SendReply(u8* data, int len, u64 timestamp, u16 aid);
int SendAck(u8* data, int len, u64 timestamp);
int RecvHostPacket(u8* data, u64* timestamp);
u16 RecvReplies(u8* data, u64 timestamp, u16 aidmask);
}

View File

@ -374,9 +374,9 @@ int MP_SendPacket(u8* data, int len, u64 timestamp)
return LocalMP::SendPacket(data, len, timestamp);
}
int MP_RecvPacket(u8* data, bool block, u64* timestamp)
int MP_RecvPacket(u8* data, u64* timestamp)
{
return LocalMP::RecvPacket(data, block, timestamp);
return LocalMP::RecvPacket(data, timestamp);
}
int MP_SendCmd(u8* data, int len, u64 timestamp)
@ -394,6 +394,11 @@ int MP_SendAck(u8* data, int len, u64 timestamp)
return LocalMP::SendAck(data, len, timestamp);
}
int MP_RecvHostPacket(u8* data, u64* timestamp)
{
return LocalMP::RecvHostPacket(data, timestamp);
}
u16 MP_RecvReplies(u8* data, u64 timestamp, u16 aidmask)
{
return LocalMP::RecvReplies(data, timestamp, aidmask);