From 4e2cb3bfcf3c45d5e79d9f4bf5231a1f632d5df5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 12 Jun 2024 20:53:42 +0200 Subject: [PATCH] lay base for the packet dispatcher --- src/frontend/qt_sdl/CMakeLists.txt | 2 + src/frontend/qt_sdl/LocalMP.cpp | 20 ++-- src/frontend/qt_sdl/Net.cpp | 113 +++++++++++++++++++ src/frontend/qt_sdl/Net.h | 40 +++++++ src/frontend/qt_sdl/Net_PCap.cpp | 77 +++++-------- src/frontend/qt_sdl/Net_PCap.h | 10 +- src/frontend/qt_sdl/Net_Slirp.cpp | 88 +-------------- src/frontend/qt_sdl/Net_Slirp.h | 13 +-- src/frontend/qt_sdl/PacketDispatcher.cpp | 136 +++++++++++++++++++++++ src/frontend/qt_sdl/PacketDispatcher.h | 46 ++++++++ 10 files changed, 387 insertions(+), 158 deletions(-) create mode 100644 src/frontend/qt_sdl/Net.cpp create mode 100644 src/frontend/qt_sdl/Net.h create mode 100644 src/frontend/qt_sdl/PacketDispatcher.cpp create mode 100644 src/frontend/qt_sdl/PacketDispatcher.h diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 2bb4c91e..f4e1f6e8 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -31,6 +31,8 @@ set(SOURCES_QT_SDL ROMInfoDialog.cpp RAMInfoDialog.cpp TitleManagerDialog.cpp + PacketDispatcher.cpp + Net.cpp Net_PCap.cpp Net_Slirp.cpp LocalMP.cpp diff --git a/src/frontend/qt_sdl/LocalMP.cpp b/src/frontend/qt_sdl/LocalMP.cpp index 89b47146..effe73d3 100644 --- a/src/frontend/qt_sdl/LocalMP.cpp +++ b/src/frontend/qt_sdl/LocalMP.cpp @@ -50,17 +50,17 @@ struct MPPacketHeader u64 Timestamp; }; -QMutex MPQueueLock; -MPStatusData MPStatus; -u8* MPPacketQueue = nullptr; -u8* MPReplyQueue = nullptr; -u32 PacketReadOffset[16]; -u32 ReplyReadOffset[16]; - const u32 kPacketQueueSize = 0x10000; const u32 kReplyQueueSize = 0x10000; const u32 kMaxFrameSize = 0x948; +QMutex MPQueueLock; +MPStatusData MPStatus; +u8 MPPacketQueue[kPacketQueueSize]; +u8 MPReplyQueue[kReplyQueueSize]; +u32 PacketReadOffset[16]; +u32 ReplyReadOffset[16]; + int RecvTimeout; int LastHostID; @@ -100,8 +100,6 @@ bool Init() { MPQueueLock.lock(); - MPPacketQueue = new u8[kPacketQueueSize]; - MPReplyQueue = new u8[kReplyQueueSize]; memset(MPPacketQueue, 0, kPacketQueueSize); memset(MPReplyQueue, 0, kReplyQueueSize); memset(&MPStatus, 0, sizeof(MPStatus)); @@ -127,10 +125,6 @@ bool Init() void DeInit() { - delete MPPacketQueue; - delete MPReplyQueue; - MPPacketQueue = nullptr; - MPReplyQueue = nullptr; } void SetRecvTimeout(int timeout) diff --git a/src/frontend/qt_sdl/Net.cpp b/src/frontend/qt_sdl/Net.cpp new file mode 100644 index 00000000..6e64a5b6 --- /dev/null +++ b/src/frontend/qt_sdl/Net.cpp @@ -0,0 +1,113 @@ +/* + Copyright 2016-2023 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include +#include "Net.h" +#include "FIFO.h" +#include "Platform.h" +#include "Config.h" + +using namespace melonDS; + +namespace Net +{ + +using Platform::Log; +using Platform::LogLevel; + +bool Inited = false; +bool DirectMode; + +QMutex RXMutex; +RingBuffer<0x10000> RXBuffer; + + +bool Init() +{ + if (Inited) DeInit(); + + RXBuffer.Clear(); + + Config::Table cfg = Config::GetGlobalTable(); + DirectMode = cfg.GetBool("LAN.DirectMode"); + + bool ret = false; + if (DirectMode) + ret = Net_PCap::Init(); + else + ret = Net_Slirp::Init(); + + Inited = ret; + return ret; +} + +void DeInit() +{ + if (!Inited) return; + + if (DirectMode) + Net_PCap::DeInit(); + else + Net_Slirp::DeInit(); + + Inited = false; +} + + +void RXEnqueue(const void* buf, int len) +{ + int totallen = len + 4; + + RXMutex.lock(); + + if (!RXBuffer.CanFit(totallen)) + { + RXMutex.unlock(); + Log(LogLevel::Warn, "Net: !! NOT ENOUGH SPACE IN RX BUFFER\n"); + return; + } + + u32 header = (len & 0xFFFF) | (len << 16); + RXBuffer.Write(&header, sizeof(u32)); + RXBuffer.Write(buf, len); + RXMutex.unlock(); +} + + +int SendPacket(u8* data, int len) +{ + if (DirectMode) + return Net_PCap::SendPacket(data, len); + else + return Net_Slirp::SendPacket(data, len); +} + +int RecvPacket(u8* data) +{ + if (DirectMode) + Net_PCap::RecvCheck(); + else + Net_Slirp::RecvCheck(); + + // TODO: check MAC + // FIFO header | destination MAC | source MAC | frame type +} + +} diff --git a/src/frontend/qt_sdl/Net.h b/src/frontend/qt_sdl/Net.h new file mode 100644 index 00000000..dd3feff3 --- /dev/null +++ b/src/frontend/qt_sdl/Net.h @@ -0,0 +1,40 @@ +/* + Copyright 2016-2023 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef NET_H +#define NET_H + +#include "types.h" +#include "Net_PCap.h" +#include "Net_Slirp.h" + +namespace Net +{ +using namespace melonDS; + +bool Init(); +void DeInit(); + +void RXEnqueue(const void* buf, int len); + +int SendPacket(u8* data, int len); +int RecvPacket(u8* data); + +} + +#endif // NET_H diff --git a/src/frontend/qt_sdl/Net_PCap.cpp b/src/frontend/qt_sdl/Net_PCap.cpp index b635cfb4..0eeba938 100644 --- a/src/frontend/qt_sdl/Net_PCap.cpp +++ b/src/frontend/qt_sdl/Net_PCap.cpp @@ -16,21 +16,13 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ -// direct LAN interface. Currently powered by libpcap, may change. - -#include -#include #include #include -#include "Wifi.h" -#include "Net_PCap.h" +#include "Net.h" #include "Config.h" #include "Platform.h" #include "main.h" -// REMOVE ME -//extern EmuInstance* testinst; - #ifdef __WIN32__ #include #else @@ -57,7 +49,7 @@ using Platform::LogLevel; #define DECL_PCAP_FUNC(ret, name, args, args2) \ typedef ret (*type_##name) args; \ - type_##name ptr_##name = NULL; \ + type_##name ptr_##name = nullptr; \ ret name args { return ptr_##name args2; } DECL_PCAP_FUNC(int, pcap_findalldevs, (pcap_if_t** alldevs, char* errbuf), (alldevs,errbuf)) @@ -70,7 +62,7 @@ DECL_PCAP_FUNC(int, pcap_dispatch, (pcap_t* dev, int num, pcap_handler callback, DECL_PCAP_FUNC(const u_char*, pcap_next, (pcap_t* dev, struct pcap_pkthdr* hdr), (dev,hdr)) -namespace LAN_PCap +namespace Net_PCap { const char* PCapLibNames[] = @@ -86,14 +78,14 @@ const char* PCapLibNames[] = "libpcap.so.1", "libpcap.so", #endif - NULL + nullptr }; -AdapterData* Adapters = NULL; +AdapterData* Adapters = nullptr; int NumAdapters = 0; -Platform::DynamicLibrary* PCapLib = NULL; -pcap_t* PCapAdapter = NULL; +Platform::DynamicLibrary* PCapLib = nullptr; +pcap_t* PCapAdapter = nullptr; AdapterData* PCapAdapterData; u8 PacketBuffer[2048]; @@ -121,7 +113,7 @@ bool TryLoadPCap(Platform::DynamicLibrary *lib) bool Init(bool open_adapter) { - PCapAdapter = NULL; + PCapAdapter = nullptr; PacketLen = 0; RXNum = 0; @@ -130,7 +122,7 @@ bool Init(bool open_adapter) // TODO: how to deal with cases where an adapter is unplugged or changes config?? if (!PCapLib) { - PCapLib = NULL; + PCapLib = nullptr; for (int i = 0; PCapLibNames[i]; i++) { @@ -148,7 +140,7 @@ bool Init(bool open_adapter) break; } - if (PCapLib == NULL) + if (PCapLib == nullptr) { Log(LogLevel::Error, "PCap: init failed\n"); return false; @@ -160,7 +152,7 @@ bool Init(bool open_adapter) pcap_if_t* alldevs; ret = pcap_findalldevs(&alldevs, errbuf); - if (ret < 0 || alldevs == NULL) + if (ret < 0 || alldevs == nullptr) { Log(LogLevel::Warn, "PCap: no devices available\n"); return false; @@ -200,12 +192,12 @@ bool Init(bool open_adapter) ULONG bufsize = 16384; IP_ADAPTER_ADDRESSES* buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize); - ULONG uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize); + ULONG uret = GetAdaptersAddresses(AF_INET, 0, nullptr, buf, &bufsize); if (uret == ERROR_BUFFER_OVERFLOW) { HeapFree(GetProcessHeap(), 0, buf); buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize); - uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize); + uret = GetAdaptersAddresses(AF_INET, 0, nullptr, buf, &bufsize); } if (uret != ERROR_SUCCESS) { @@ -225,10 +217,10 @@ bool Init(bool open_adapter) continue; } - WideCharToMultiByte(CP_UTF8, 0, addr->FriendlyName, 127, adata->FriendlyName, 127, NULL, NULL); + WideCharToMultiByte(CP_UTF8, 0, addr->FriendlyName, 127, adata->FriendlyName, 127, nullptr, nullptr); adata->FriendlyName[127] = '\0'; - WideCharToMultiByte(CP_UTF8, 0, addr->Description, 127, adata->Description, 127, NULL, NULL); + WideCharToMultiByte(CP_UTF8, 0, addr->Description, 127, adata->Description, 127, nullptr, nullptr); adata->Description[127] = '\0'; if (addr->PhysicalAddressLength != 6) @@ -322,8 +314,8 @@ bool Init(bool open_adapter) if (PCapAdapter) pcap_close(PCapAdapter); // open pcap device - //std::string devicename = testinst->getGlobalConfig().GetString("LAN.Device"); - std::string devicename = "FIXME"; + Config::Table cfg = Config::GetGlobalTable(); + std::string devicename = cfg.GetString("LAN.Device"); PCapAdapterData = &Adapters[0]; for (int i = 0; i < NumAdapters; i++) { @@ -344,7 +336,7 @@ bool Init(bool open_adapter) if (pcap_setnonblock(PCapAdapter, 1, errbuf) < 0) { Log(LogLevel::Error, "PCap: failed to set nonblocking mode\n"); - pcap_close(PCapAdapter); PCapAdapter = NULL; + pcap_close(PCapAdapter); PCapAdapter = nullptr; return false; } @@ -358,29 +350,23 @@ void DeInit() if (PCapAdapter) { pcap_close(PCapAdapter); - PCapAdapter = NULL; + PCapAdapter = nullptr; } Platform::DynamicLibrary_Unload(PCapLib); - PCapLib = NULL; + PCapLib = nullptr; } } -void RXCallback(u_char* blarg, const struct pcap_pkthdr* header, const u_char* data) +void RXCallback(u_char* userdata, const struct pcap_pkthdr* header, const u_char* data) { - while (RXNum > 0); - - if (header->len > 2048-64) return; - - PacketLen = header->len; - memcpy(PacketBuffer, data, PacketLen); - RXNum = 1; + Net::RXEnqueue(data, header->len); } int SendPacket(u8* data, int len) { - if (PCapAdapter == NULL) + if (PCapAdapter == nullptr) return 0; if (len > 2048) @@ -394,21 +380,12 @@ int SendPacket(u8* data, int len) return len; } -int RecvPacket(u8* data) +void RecvCheck() { - if (PCapAdapter == NULL) - return 0; + if (PCapAdapter == nullptr) + return; - int ret = 0; - if (RXNum > 0) - { - memcpy(data, PacketBuffer, PacketLen); - ret = PacketLen; - RXNum = 0; - } - - pcap_dispatch(PCapAdapter, 1, RXCallback, NULL); - return ret; + pcap_dispatch(PCapAdapter, 1, RXCallback, nullptr); } } diff --git a/src/frontend/qt_sdl/Net_PCap.h b/src/frontend/qt_sdl/Net_PCap.h index 2e03d66a..6d506480 100644 --- a/src/frontend/qt_sdl/Net_PCap.h +++ b/src/frontend/qt_sdl/Net_PCap.h @@ -16,12 +16,12 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ -#ifndef LAN_PCAP_H -#define LAN_PCAP_H +#ifndef NET_PCAP_H +#define NET_PCAP_H #include "types.h" -namespace LAN_PCap +namespace Net_PCap { using namespace melonDS; @@ -46,8 +46,8 @@ bool Init(bool open_adapter); void DeInit(); int SendPacket(u8* data, int len); -int RecvPacket(u8* data); +void RecvCheck(); } -#endif // LAN_PCAP_H +#endif // NET_PCAP_H diff --git a/src/frontend/qt_sdl/Net_Slirp.cpp b/src/frontend/qt_sdl/Net_Slirp.cpp index 1054ef52..a3c44844 100644 --- a/src/frontend/qt_sdl/Net_Slirp.cpp +++ b/src/frontend/qt_sdl/Net_Slirp.cpp @@ -16,13 +16,9 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ -// indirect LAN interface, powered by BSD sockets. - #include -#include #include -#include "Wifi.h" -#include "Net_Slirp.h" +#include "Net.h" #include "FIFO.h" #include "Platform.h" @@ -39,7 +35,7 @@ using namespace melonDS; -namespace LAN_Socket +namespace Net_Slirp { using Platform::Log; @@ -58,10 +54,6 @@ u32 IPv4ID; Slirp* Ctx = nullptr; -/*const int FDListMax = 64; -struct pollfd FDList[FDListMax]; -int FDListSize;*/ - #ifdef __WIN32__ @@ -85,23 +77,6 @@ int clock_gettime(int, struct timespec *spec) #endif // __WIN32__ -void RXEnqueue(const void* buf, int len) -{ - int alignedlen = (len + 3) & ~3; - int totallen = alignedlen + 4; - - if (!RXBuffer.CanFit(totallen >> 2)) - { - Log(LogLevel::Warn, "slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n"); - return; - } - - u32 header = (alignedlen & 0xFFFF) | (len << 16); - RXBuffer.Write(header); - for (int i = 0; i < alignedlen; i += 4) - RXBuffer.Write(((u32*)buf)[i>>2]); -} - ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) { if (len > 2048) @@ -112,7 +87,7 @@ ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) Log(LogLevel::Debug, "slirp: response packet of %zu bytes, type %04X\n", len, ntohs(((u16*)buf)[6])); - RXEnqueue(buf, len); + Net::RXEnqueue(buf, len); return len; } @@ -145,40 +120,11 @@ void SlirpCbTimerMod(void* timer, int64_t expire_time, void* opaque) void SlirpCbRegisterPollFD(int fd, void* opaque) { Log(LogLevel::Debug, "Slirp: register poll FD %d\n", fd); - - /*if (FDListSize >= FDListMax) - { - printf("!! SLIRP FD LIST FULL\n"); - return; - } - - for (int i = 0; i < FDListSize; i++) - { - if (FDList[i].fd == fd) return; - } - - FDList[FDListSize].fd = fd; - FDListSize++;*/ } void SlirpCbUnregisterPollFD(int fd, void* opaque) { Log(LogLevel::Debug, "Slirp: unregister poll FD %d\n", fd); - - /*if (FDListSize < 1) - { - printf("!! SLIRP FD LIST EMPTY\n"); - return; - } - - for (int i = 0; i < FDListSize; i++) - { - if (FDList[i].fd == fd) - { - FDListSize--; - FDList[i] = FDList[FDListSize]; - } - }*/ } void SlirpCbNotify(void* opaque) @@ -203,9 +149,6 @@ bool Init() { IPv4ID = 0; - //FDListSize = 0; - //memset(FDList, 0, sizeof(FDList)); - SlirpConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.version = 1; @@ -425,7 +368,7 @@ void HandleDNSFrame(u8* data, int len) if (framelen & 1) { *out++ = 0; framelen++; } FinishUDPFrame(resp, framelen); - RXEnqueue(resp, framelen); + Net::RXEnqueue(resp, framelen); } int SendPacket(u8* data, int len) @@ -472,8 +415,6 @@ int SlirpCbAddPoll(int fd, int events, void* opaque) int idx = PollListSize++; - //printf("Slirp: add poll: fd=%d, idx=%d, events=%08X\n", fd, idx, events); - u16 evt = 0; if (events & SLIRP_POLL_IN) evt |= POLLIN; @@ -497,8 +438,6 @@ int SlirpCbGetREvents(int idx, void* opaque) if (idx < 0 || idx >= PollListSize) return 0; - //printf("Slirp: get revents, idx=%d, res=%04X\n", idx, FDList[idx].revents); - u16 evt = PollList[idx].revents; int ret = 0; @@ -511,11 +450,9 @@ int SlirpCbGetREvents(int idx, void* opaque) return ret; } -int RecvPacket(u8* data) +void RecvCheck() { - if (!Ctx) return 0; - - int ret = 0; + if (!Ctx) return; //if (PollListSize > 0) { @@ -525,19 +462,6 @@ int RecvPacket(u8* data) int res = poll(PollList, PollListSize, timeout); slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr); } - - if (!RXBuffer.IsEmpty()) - { - u32 header = RXBuffer.Read(); - u32 len = header & 0xFFFF; - - for (int i = 0; i < len; i += 4) - ((u32*)data)[i>>2] = RXBuffer.Read(); - - ret = header >> 16; - } - - return ret; } } diff --git a/src/frontend/qt_sdl/Net_Slirp.h b/src/frontend/qt_sdl/Net_Slirp.h index 043e1330..03b5e344 100644 --- a/src/frontend/qt_sdl/Net_Slirp.h +++ b/src/frontend/qt_sdl/Net_Slirp.h @@ -16,24 +16,21 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ -#ifndef LAN_SOCKET_H -#define LAN_SOCKET_H +#ifndef NET_SLIRP_H +#define NET_SLIRP_H #include "types.h" -namespace LAN_Socket +namespace Net_Slirp { using namespace melonDS; -// - - bool Init(); void DeInit(); int SendPacket(u8* data, int len); -int RecvPacket(u8* data); +void RecvCheck(); } -#endif // LAN_SOCKET_H +#endif // NET_SLIRP_H diff --git a/src/frontend/qt_sdl/PacketDispatcher.cpp b/src/frontend/qt_sdl/PacketDispatcher.cpp new file mode 100644 index 00000000..6ea4356e --- /dev/null +++ b/src/frontend/qt_sdl/PacketDispatcher.cpp @@ -0,0 +1,136 @@ +/* + Copyright 2016-2023 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include "PacketDispatcher.h" + +using namespace melonDS; + +struct PacketHeader +{ + u32 magic; + u32 senderID; + u32 headerLength; + u32 dataLength; +}; + +const u32 kPacketMagic = 0x4B504C4D; + + +PacketDispatcher::PacketDispatcher() +{ + instanceMask = 0; + memset(packetQueues, 0, sizeof(packetQueues)); +} + +PacketDispatcher::~PacketDispatcher() +{ + // +} + + +void PacketDispatcher::registerInstance(int inst) +{ + mutex.lock(); + + instanceMask |= (1 << inst); + packetQueues[inst] = new PacketQueue(); + + mutex.unlock(); +} + +void PacketDispatcher::unregisterInstance(int inst) +{ + mutex.lock(); + + instanceMask &= ~(1 << inst); + delete packetQueues[inst]; + + mutex.unlock(); +} + + +void PacketDispatcher::sendPacket(const void* header, int headerlen, const void* data, int datalen, int sender, u16 recv_mask) +{ + if (!header) headerlen = 0; + if (!data) datalen = 0; + if ((!headerlen) && (!datalen)) return; + if ((sizeof(PacketHeader) + headerlen + datalen) >= 0x8000) return; + if (sender < 0 || sender > 15) return; + + recv_mask &= instanceMask; + recv_mask &= ~(1 << sender); + if (!recv_mask) return; + + PacketHeader phdr; + phdr.magic = kPacketMagic; + phdr.senderID = sender; + phdr.headerLength = headerlen; + phdr.dataLength = datalen; + + mutex.lock(); + for (int i = 0; i < 16; i++) + { + if (!(recv_mask & (1 << i))) + continue; + + PacketQueue* queue = packetQueues[i]; + queue->Write(&phdr, sizeof(phdr)); + if (headerlen) queue->Write(header, headerlen); + if (datalen) queue->Write(data, datalen); + } + mutex.unlock(); +} + +bool PacketDispatcher::recvPacket(void *header, int *headerlen, void *data, int *datalen, int receiver) +{ + if ((!header) && (!data)) return false; + if (receiver < 0 || receiver > 15) return false; + + mutex.lock(); + PacketQueue* queue = packetQueues[receiver]; + + PacketHeader phdr; + if (!queue->Read(&phdr, sizeof(phdr))) + { + mutex.unlock(); + return false; + } + + if (phdr.magic != kPacketMagic) + { + mutex.unlock(); + return false; + } + + if (phdr.headerLength) + { + if (headerlen) *headerlen = phdr.headerLength; + if (header) queue->Read(header, phdr.headerLength); + else queue->Skip(phdr.headerLength); + } + + if (phdr.dataLength) + { + if (datalen) *datalen = phdr.dataLength; + if (data) queue->Read(data, phdr.dataLength); + else queue->Skip(phdr.dataLength); + } + + mutex.unlock(); + return true; +} diff --git a/src/frontend/qt_sdl/PacketDispatcher.h b/src/frontend/qt_sdl/PacketDispatcher.h new file mode 100644 index 00000000..b6715433 --- /dev/null +++ b/src/frontend/qt_sdl/PacketDispatcher.h @@ -0,0 +1,46 @@ +/* + Copyright 2016-2023 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef PACKETDISPATCHER_H +#define PACKETDISPATCHER_H + +#include +#include "types.h" +#include "FIFO.h" + +using PacketQueue = melonDS::RingBuffer<0x8000>; + +class PacketDispatcher +{ +public: + PacketDispatcher(); + ~PacketDispatcher(); + + void registerInstance(int inst); + void unregisterInstance(int inst); + + void sendPacket(const void* header, int headerlen, const void* data, int datalen, int sender, melonDS::u16 recv_mask); + bool recvPacket(void* header, int* headerlen, void* data, int* datalen, int receiver); + +private: + QMutex mutex; + melonDS::u16 instanceMask; + PacketQueue* packetQueues[16]; +}; + +#endif // PACKETDISPATCHER_H