mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
lay base for the packet dispatcher
This commit is contained in:
parent
9c3749bfa0
commit
4e2cb3bfcf
@ -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
|
||||
|
@ -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)
|
||||
|
113
src/frontend/qt_sdl/Net.cpp
Normal file
113
src/frontend/qt_sdl/Net.cpp
Normal file
@ -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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <QMutex>
|
||||
#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
|
||||
}
|
||||
|
||||
}
|
40
src/frontend/qt_sdl/Net.h
Normal file
40
src/frontend/qt_sdl/Net.h
Normal file
@ -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
|
@ -16,21 +16,13 @@
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
// direct LAN interface. Currently powered by libpcap, may change.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pcap/pcap.h>
|
||||
#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 <iphlpapi.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -16,13 +16,9 @@
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
// indirect LAN interface, powered by BSD sockets.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
136
src/frontend/qt_sdl/PacketDispatcher.cpp
Normal file
136
src/frontend/qt_sdl/PacketDispatcher.cpp
Normal file
@ -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;
|
||||
}
|
46
src/frontend/qt_sdl/PacketDispatcher.h
Normal file
46
src/frontend/qt_sdl/PacketDispatcher.h
Normal file
@ -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 <QMutex>
|
||||
#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
|
Loading…
Reference in New Issue
Block a user