diff --git a/pcsx2/DEV9/net.cpp b/pcsx2/DEV9/net.cpp index 091d400f86..d5bcb03d9a 100644 --- a/pcsx2/DEV9/net.cpp +++ b/pcsx2/DEV9/net.cpp @@ -17,6 +17,7 @@ #include #include +#include #if defined(__POSIX__) #include #endif @@ -27,14 +28,15 @@ #endif #include "pcap_io.h" -#ifdef _WIN32 -#include "Win32\tap.h" -#endif -#include "pcap_io.h" +#include "PacketReader/EthernetFrame.h" +#include "PacketReader/IP/IP_Packet.h" +#include "PacketReader/IP/UDP/UDP_Packet.h" NetAdapter* nif; std::thread rx_thread; +std::mutex rx_mutex; + volatile bool RxRunning = false; //rx thread void NetRxThread() @@ -44,8 +46,14 @@ void NetRxThread() { while (rx_fifo_can_rx() && nif->recv(&tmp)) { - rx_process(&tmp); + std::lock_guard rx_lock(rx_mutex); + //Check if we can still rx + if (rx_fifo_can_rx()) + rx_process(&tmp); + else + Console.Error("DEV9: rx_fifo_can_rx() false after nif->recv(), dropping"); } + std::this_thread::yield(); } } @@ -158,7 +166,11 @@ const wchar_t* NetApiToWstring(NetApi api) } } -const PacketReader::IP::IP_Address NetAdapter::internalIP{192, 0, 2, 1}; +using namespace PacketReader; +using namespace PacketReader::IP; +using namespace PacketReader::IP::UDP; + +const IP_Address NetAdapter::internalIP{192, 0, 2, 1}; const u8 NetAdapter::broadcastMAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; const u8 NetAdapter::internalMAC[6] = {0x76, 0x6D, 0xF4, 0x63, 0x30, 0x31}; @@ -168,6 +180,36 @@ NetAdapter::NetAdapter() SetMACAddress(nullptr); } +bool NetAdapter::recv(NetPacket* pkt) +{ + if (!internalRxThreadRunning.load()) + return InternalServerRecv(pkt); + return false; +} + +bool NetAdapter::send(NetPacket* pkt) +{ + return InternalServerSend(pkt); +} + +//RxRunning must be set false before this +NetAdapter::~NetAdapter() +{ + //unblock InternalServerRX thread + if (internalRxThreadRunning.load()) + { + internalRxThreadRunning.store(false); + + { + std::lock_guard srvlock(internalRxMutex); + internalRxHasData = true; + } + + internalRxCV.notify_all(); + internalRxThread.join(); + } +} + void NetAdapter::SetMACAddress(u8* mac) { if (mac == nullptr) @@ -198,3 +240,72 @@ bool NetAdapter::VerifyPkt(NetPacket* pkt, int read_size) pkt->size = read_size; return true; } + +#ifdef _WIN32 +void NetAdapter::InitInternalServer(PIP_ADAPTER_ADDRESSES adapter) +#elif defined(__POSIX__) +void NetAdapter::InitInternalServer(ifaddrs* adapter) +#endif +{ + if (adapter == nullptr) + Console.Error("DEV9: InitInternalServer() got nullptr for adapter"); + + if (blocks()) + { + internalRxThreadRunning.store(true); + internalRxThread = std::thread(&NetAdapter::InternalServerThread, this); + } +} + +bool NetAdapter::InternalServerRecv(NetPacket* pkt) +{ + return false; +} + +bool NetAdapter::InternalServerSend(NetPacket* pkt) +{ + EthernetFrame frame(pkt); + if (frame.protocol == (u16)EtherType::IPv4) + { + PayloadPtr* payload = static_cast(frame.GetPayload()); + IP_Packet ippkt(payload->data, payload->GetLength()); + + if (ippkt.destinationIP == internalIP) + { + return true; + } + } + return false; +} + +void NetAdapter::InternalSignalReceived() +{ + //Signal internal server thread to read + if (internalRxThreadRunning.load()) + { + { + std::lock_guard srvlock(internalRxMutex); + internalRxHasData = true; + } + + internalRxCV.notify_all(); + } +} + +void NetAdapter::InternalServerThread() +{ + NetPacket tmp; + while (internalRxThreadRunning.load()) + { + std::unique_lock srvLock(internalRxMutex); + internalRxCV.wait(srvLock, [&] { return internalRxHasData; }); + + { + std::lock_guard rx_lock(rx_mutex); + while (rx_fifo_can_rx() && InternalServerRecv(&tmp)) + rx_process(&tmp); + } + + internalRxHasData = false; + } +} diff --git a/pcsx2/DEV9/net.h b/pcsx2/DEV9/net.h index baba94d21a..5e3a17530c 100644 --- a/pcsx2/DEV9/net.h +++ b/pcsx2/DEV9/net.h @@ -17,6 +17,20 @@ #include #include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#elif defined(__POSIX__) +#include +#include +#endif + #include "PacketReader/IP/IP_Address.h" // first three recognized by Xlink as Sony PS2 @@ -69,18 +83,39 @@ protected: static const u8 broadcastMAC[6]; static const u8 internalMAC[6]; +private: + std::thread internalRxThread; + std::atomic internalRxThreadRunning{false}; + + std::mutex internalRxMutex; + std::condition_variable internalRxCV; + bool internalRxHasData = false; + public: NetAdapter(); virtual bool blocks() = 0; virtual bool isInitialised() = 0; - virtual bool recv(NetPacket* pkt) = 0; //gets a packet - virtual bool send(NetPacket* pkt) = 0; //sends the packet and deletes it when done - virtual void close() {} - virtual ~NetAdapter() {} + virtual bool recv(NetPacket* pkt); //gets a packet + virtual bool send(NetPacket* pkt); //sends the packet and deletes it when done + virtual void close(){}; + virtual ~NetAdapter(); protected: void SetMACAddress(u8* mac); bool VerifyPkt(NetPacket* pkt, int read_size); + +#ifdef _WIN32 + void InitInternalServer(PIP_ADAPTER_ADDRESSES adapter); +#elif defined(__POSIX__) + void InitInternalServer(ifaddrs* adapter); +#endif + +private: + bool InternalServerRecv(NetPacket* pkt); + bool InternalServerSend(NetPacket* pkt); + + void InternalSignalReceived(); + void InternalServerThread(); }; void tx_put(NetPacket* ptr); diff --git a/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters b/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters index dcd53c890d..bffe0e0199 100644 --- a/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters +++ b/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters @@ -178,6 +178,9 @@ {9e9b52d7-7b1c-44b2-82d8-1e0d8085e7e0} + + {93da3d51-9457-4fde-b374-c2fbe4780f59} + {57c4be94-9a2c-469b-9b02-b3b324857fc5}