DEV9: Adjust comments in UDP_Session

This commit is contained in:
TheLastRar 2024-05-01 21:21:04 +01:00 committed by Connor McLaughlin
parent c6e7e15599
commit cf3ad3f855
3 changed files with 41 additions and 29 deletions

View File

@ -30,6 +30,19 @@ using namespace PacketReader::IP::UDP;
namespace Sessions namespace Sessions
{ {
/*
* The default UDP_Session backend don't bind to the src port the PS2 uses.
* Some games, however, sends the response to a set port, rather than the message source port
* A set of heuristics are used to determine when we should bind the port, these are;
* Any broadcast & multicast packet, and any packet where the src and dst ports are close to each other
* UDP_FixedPort manages the lifetime of socket bound to a specific port, and shares that socket
* with any UDP_Sessions created from it.
* For a UDP_Session with a parent UDP_FixedPort, packets are sent from the UDP_Session, but received
* by the UDP_FixedPort, with the UDP_FixedPort asking each UDP_Session associated with it whether
* it can accept the received packet, broadcast/multicast will accept eveything, while unicast sessions
* only accept packets from the address it sent to
*/
UDP_FixedPort::UDP_FixedPort(ConnectionKey parKey, IP_Address parAdapterIP, u16 parPort) UDP_FixedPort::UDP_FixedPort(ConnectionKey parKey, IP_Address parAdapterIP, u16 parPort)
: BaseSession(parKey, parAdapterIP) : BaseSession(parKey, parAdapterIP)
, client{socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)} , client{socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)}
@ -44,11 +57,15 @@ namespace Sessions
#elif defined(__POSIX__) #elif defined(__POSIX__)
errno); errno);
#endif #endif
//RaiseEventConnectionClosed(); //TODO /*
* TODO: Currently error is not correctly handled here
* We would need to call RaiseEventConnectionClosed()
* and also deal with the follow up call to NewClientSession()
*/
return; return;
} }
const int reuseAddress = true; //BOOL const int reuseAddress = true; // BOOL on Windows
ret = setsockopt(client, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&reuseAddress), sizeof(reuseAddress)); ret = setsockopt(client, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&reuseAddress), sizeof(reuseAddress));
if (ret == SOCKET_ERROR) if (ret == SOCKET_ERROR)
@ -59,7 +76,7 @@ namespace Sessions
errno); errno);
#endif #endif
const int broadcastEnable = true; //BOOL const int broadcastEnable = true; // BOOL on Windows
ret = setsockopt(client, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char*>(&broadcastEnable), sizeof(broadcastEnable)); ret = setsockopt(client, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char*>(&broadcastEnable), sizeof(broadcastEnable));
if (ret == SOCKET_ERROR) if (ret == SOCKET_ERROR)
@ -140,8 +157,8 @@ namespace Sessions
std::unique_ptr<u8[]> buffer; std::unique_ptr<u8[]> buffer;
sockaddr_in endpoint{}; sockaddr_in endpoint{};
//FIONREAD returns total size of all available messages // FIONREAD returns total size of all available messages
//but we will read one message at a time // however, we only read one message at a time
#ifdef _WIN32 #ifdef _WIN32
ret = ioctlsocket(client, FIONREAD, &available); ret = ioctlsocket(client, FIONREAD, &available);
#elif defined(__POSIX__) #elif defined(__POSIX__)

View File

@ -31,9 +31,7 @@ using namespace std::chrono_literals;
namespace Sessions namespace Sessions
{ {
const std::chrono::duration<std::chrono::steady_clock::rep, std::chrono::steady_clock::period> const std::chrono::duration<std::chrono::steady_clock::rep, std::chrono::steady_clock::period>
UDP_Session::MAX_IDLE = 120s; //See RFC 4787 Section 4.3 UDP_Session::MAX_IDLE = 120s; // See RFC 4787 section 4.3
//TODO, figure out handling of multicast
UDP_Session::UDP_Session(ConnectionKey parKey, IP_Address parAdapterIP) UDP_Session::UDP_Session(ConnectionKey parKey, IP_Address parAdapterIP)
: UDP_BaseSession(parKey, parAdapterIP) : UDP_BaseSession(parKey, parAdapterIP)
@ -125,8 +123,8 @@ namespace Sessions
std::unique_ptr<u8[]> buffer; std::unique_ptr<u8[]> buffer;
sockaddr_in endpoint{}; sockaddr_in endpoint{};
//FIONREAD returns total size of all available messages // FIONREAD returns total size of all available messages
//but we will read one message at a time // however, we only read one message at a time
#ifdef _WIN32 #ifdef _WIN32
ret = ioctlsocket(client, FIONREAD, &available); ret = ioctlsocket(client, FIONREAD, &available);
#elif defined(__POSIX__) #elif defined(__POSIX__)
@ -170,7 +168,6 @@ namespace Sessions
if (std::chrono::steady_clock::now() - deathClockStart.load() > MAX_IDLE) if (std::chrono::steady_clock::now() - deathClockStart.load() > MAX_IDLE)
{ {
//CloseSocket();
Console.WriteLn("DEV9: UDP: Max idle reached"); Console.WriteLn("DEV9: UDP: Max idle reached");
RaiseEventConnectionClosed(); RaiseEventConnectionClosed();
} }
@ -200,7 +197,7 @@ namespace Sessions
if (destPort != 0) if (destPort != 0)
{ {
//client already created // Already created client!?
if (!(udp.destinationPort == destPort && udp.sourcePort == srcPort)) if (!(udp.destinationPort == destPort && udp.sourcePort == srcPort))
{ {
Console.Error("DEV9: UDP: Packet invalid for current session (duplicate key?)"); Console.Error("DEV9: UDP: Packet invalid for current session (duplicate key?)");
@ -209,11 +206,11 @@ namespace Sessions
} }
else else
{ {
//create client // Create client
destPort = udp.destinationPort; destPort = udp.destinationPort;
srcPort = udp.sourcePort; srcPort = udp.sourcePort;
//Multicast address start with 0b1110 // Multicast address start with 0b1110
if ((destIP.bytes[0] & 0xF0) == 0xE0) if ((destIP.bytes[0] & 0xF0) == 0xE0)
{ {
isMulticast = true; isMulticast = true;
@ -234,7 +231,7 @@ namespace Sessions
return false; return false;
} }
const int reuseAddress = true; //BOOL const int reuseAddress = true; // BOOL on Windows
ret = setsockopt(client, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&reuseAddress), sizeof(reuseAddress)); ret = setsockopt(client, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&reuseAddress), sizeof(reuseAddress));
if (ret == SOCKET_ERROR) if (ret == SOCKET_ERROR)
@ -289,7 +286,7 @@ namespace Sessions
PayloadPtr* udpPayload = static_cast<PayloadPtr*>(udp.GetPayload()); PayloadPtr* udpPayload = static_cast<PayloadPtr*>(udp.GetPayload());
//Send // Send Packet
int ret = SOCKET_ERROR; int ret = SOCKET_ERROR;
if (isBroadcast) if (isBroadcast)
{ {
@ -321,11 +318,12 @@ namespace Sessions
#endif #endif
Console.Error("DEV9: UDP: Send error %d", ret); Console.Error("DEV9: UDP: Send error %d", ret);
//We can recive an ICMP Port Unreacable error, which can get raised in send (and maybe sendto?) /*
//On Windows this an WSAECONNRESET error, although I've not been able to reproduce in testing * We can receive an ICMP Port Unreacable error, which can get raised in send (and maybe sendto?)
//On Linux this is an ECONNREFUSED error (Testing needed to confirm full behaviour) * On Windows this is an WSAECONNRESET error, although I've not been able to reproduce in testing
* On Linux this is an ECONNREFUSED error (Testing needed to confirm full behaviour)
//The decision to ignore the error and retry was made to allow R&C Deadlock ressurection team to packet capture eveything * We ignore the error and resend to allow packet capture (i.e. wireshark) for server resurrection projects
*/
#ifdef _WIN32 #ifdef _WIN32
if (ret == WSAECONNRESET) if (ret == WSAECONNRESET)
#elif defined(__POSIX__) #elif defined(__POSIX__)
@ -343,7 +341,6 @@ namespace Sessions
ret = sendto(client, reinterpret_cast<const char*>(udpPayload->data), udpPayload->GetLength(), 0, reinterpret_cast<const sockaddr*>(&endpoint), sizeof(endpoint)); ret = sendto(client, reinterpret_cast<const char*>(udpPayload->data), udpPayload->GetLength(), 0, reinterpret_cast<const sockaddr*>(&endpoint), sizeof(endpoint));
} }
else else
//Do we need to clear the error somehow?
ret = send(client, reinterpret_cast<const char*>(udpPayload->data), udpPayload->GetLength(), 0); ret = send(client, reinterpret_cast<const char*>(udpPayload->data), udpPayload->GetLength(), 0);
if (ret == SOCKET_ERROR) if (ret == SOCKET_ERROR)
@ -387,7 +384,6 @@ namespace Sessions
void UDP_Session::Reset() void UDP_Session::Reset()
{ {
//CloseSocket();
RaiseEventConnectionClosed(); RaiseEventConnectionClosed();
} }

View File

@ -28,19 +28,18 @@ namespace Sessions
u16 srcPort = 0; u16 srcPort = 0;
u16 destPort = 0; u16 destPort = 0;
//Broadcast // UDP_Session flags
const bool isBroadcast; // = false; const bool isBroadcast;
bool isMulticast = false; bool isMulticast = false;
const bool isFixedPort; // = false; const bool isFixedPort;
//EndBroadcast
std::atomic<std::chrono::steady_clock::time_point> deathClockStart; std::atomic<std::chrono::steady_clock::time_point> deathClockStart;
const static std::chrono::duration<std::chrono::steady_clock::rep, std::chrono::steady_clock::period> MAX_IDLE; const static std::chrono::duration<std::chrono::steady_clock::rep, std::chrono::steady_clock::period> MAX_IDLE;
public: public:
//Normal Port // Normal Port
UDP_Session(ConnectionKey parKey, PacketReader::IP::IP_Address parAdapterIP); UDP_Session(ConnectionKey parKey, PacketReader::IP::IP_Address parAdapterIP);
//Fixed Port // Fixed Port
#ifdef _WIN32 #ifdef _WIN32
UDP_Session(ConnectionKey parKey, PacketReader::IP::IP_Address parAdapterIP, bool parIsBroadcast, bool parIsMulticast, SOCKET parClient); UDP_Session(ConnectionKey parKey, PacketReader::IP::IP_Address parAdapterIP, bool parIsBroadcast, bool parIsMulticast, SOCKET parClient);
#elif defined(__POSIX__) #elif defined(__POSIX__)