-
Notifications
You must be signed in to change notification settings - Fork 46
Add ConnectionClass and SendQueueType #75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: phobos-dev
Are you sure you want to change the base?
Changes from 4 commits
8d49d2a
602db14
79d2425
ae9a841
b103398
b88367a
6dc5570
7b7e4ab
3f4a1c5
0f867bd
cc0f08c
24f844e
3a3ee66
04b1576
f9792d9
11b06bd
af29bc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| #pragma once | ||
|
|
||
| #include <YRPP.h> | ||
|
|
||
| struct CommHeaderType; | ||
|
|
||
| // Flag bits shared by both queue entry types. Westwood declared these as | ||
| // single-bit bitfields; the game reads and writes them as a plain int. | ||
| enum CommQueueFlags | ||
| { | ||
| COMMQUEUE_IS_ACTIVE = 0x1, // this entry holds a packet and is ready to be processed | ||
| COMMQUEUE_IS_READ = 0x2, // send queue: ACK received. receive queue: caller has read it | ||
| COMMQUEUE_IS_ACK = 0x4, // an ACK has been sent for this packet | ||
| }; | ||
|
|
||
| // One outgoing queue entry. | ||
| struct SendQueueType | ||
| { | ||
| int Flags; | ||
| int FirstTime; // time this packet was first sent | ||
| int LastTime; // time this packet was last sent | ||
| int SendCount; // number of times this packet has been sent | ||
| int BufLen; // size of the packet stored in this entry | ||
| CommHeaderType* Buffer; | ||
| int ExtraLen; // size of the extra data (an IPXAddressClass, for global conns) | ||
| void* ExtraBuffer; | ||
| __int16 Port; // destination port this entry was queued for | ||
| }; | ||
| static_assert(sizeof(SendQueueType) == 0x24); | ||
|
|
||
| // One incoming queue entry. Unlike RA's, YR's tracks the time the packet was | ||
| // received so IPXGlobalConnClass::Strip_Packets can age entries out. | ||
| struct ReceiveQueueType | ||
| { | ||
| int Flags; | ||
| int Time; | ||
| int BufLen; | ||
| void* Buffer; | ||
| int ExtraLen; | ||
| void* ExtraBuffer; | ||
| }; | ||
| static_assert(sizeof(ReceiveQueueType) == 0x18); | ||
|
|
||
| // Stores the packets sent and received by a single ConnectionClass. Entries | ||
| // are addressed through an index array rather than moved, so unqueueing an | ||
| // entry does not disturb the others. | ||
| class NOVTABLE CommBufferClass | ||
| { | ||
| public: | ||
| virtual ~CommBufferClass() RX; | ||
|
|
||
| // Clears both queues. Init_Send_Queue clears only the send queue, which | ||
| // is what a reconnect needs. | ||
| void Init() | ||
| { JMP_THIS(0x48B2A0); } | ||
| void Init_Send_Queue() | ||
| { JMP_THIS(0x48B390); } | ||
|
|
||
| // Send queue. Queue_Send returns zero when the queue is full. | ||
| int Queue_Send(void* buf, int buflen, void* extrabuf, int extralen, __int16 port) | ||
| { JMP_THIS(0x48B410); } | ||
| int UnQueue_Send(void* buf, int* buflen, int index, void* extrabuf, int* extralen, __int16 port) | ||
| { JMP_THIS(0x48B570); } | ||
| SendQueueType* Get_Send(int index) | ||
| { JMP_THIS(0x48B720); } | ||
| int Num_Send() const | ||
| { return this->SendCount; } | ||
| int Max_Send() const | ||
| { return this->MaxSend; } | ||
|
|
||
| // Receive queue. | ||
| int Queue_Receive(void* buf, int buflen, void* extrabuf, int extralen) | ||
| { JMP_THIS(0x48B750); } | ||
| int UnQueue_Receive(void* buf, int* buflen, int index, void* extrabuf, int* extralen) | ||
| { JMP_THIS(0x48B890); } | ||
| ReceiveQueueType* Get_Receive(int index) | ||
| { JMP_THIS(0x48B9E0); } | ||
| int Num_Receive() const | ||
| { return this->ReceiveCount; } | ||
| int Max_Receive() const | ||
| { return this->MaxReceive; } | ||
|
|
||
| // Response time tracking. The caller feeds in a delay whenever it detects | ||
| // an outgoing message has been ACK'd; the class keeps a running mean. | ||
| void Add_Delay(DWORD delay) | ||
| { JMP_THIS(0x48BA10); } | ||
| DWORD Avg_Response_Time() | ||
| { JMP_THIS(0x48BA80); } | ||
| DWORD Max_Response_Time() | ||
| { JMP_THIS(0x48BA90); } | ||
|
|
||
| // Properties | ||
| public: | ||
| int MaxSend; | ||
| int MaxReceive; | ||
| int MaxPacketSize; | ||
| int MaxExtraSize; | ||
|
|
||
| DWORD DelaySum; | ||
| DWORD NumDelay; | ||
| DWORD MeanDelay; | ||
| DWORD MaxDelay; | ||
|
|
||
| SendQueueType* SendQueue; | ||
| int SendCount; // number of entries currently queued | ||
| DWORD SendTotal; // total ever added, used as the outgoing packet ID | ||
| int* SendIndex; | ||
|
|
||
| ReceiveQueueType* ReceiveQueue; | ||
| int ReceiveCount; | ||
| DWORD ReceiveTotal; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not use DWORD please
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| int* ReceiveIndex; | ||
|
|
||
| int DebugOffset; | ||
| int DebugSize; | ||
| char** DebugNames; | ||
| int DebugNameStart; | ||
| int DebugNameCount; | ||
| }; | ||
| static_assert(sizeof(CommBufferClass) == 0x58); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,126 @@ | ||||||||||||||||||||||
| #pragma once | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| #include <YRPP.h> | ||||||||||||||||||||||
| #include <CommBufferClass.h> | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // A single "connection" with another system. This is a pure virtual base | ||||||||||||||||||||||
| // class; a derived class supplies Init (protocol-specific setup) and Send | ||||||||||||||||||||||
| // (the actual hardware-dependent transmit). | ||||||||||||||||||||||
| // | ||||||||||||||||||||||
| // Every packet the application sends is prefixed with a CommHeaderType. The | ||||||||||||||||||||||
| // header carries a magic number (unique per product, so foreign traffic can | ||||||||||||||||||||||
| // be rejected), a code saying whether this is data or an ACK, and a packet ID | ||||||||||||||||||||||
| // used to detect resends and to hand packets to the application in order. | ||||||||||||||||||||||
| // | ||||||||||||||||||||||
| // Service() drives the ACK/retry logic and must be polled as often as | ||||||||||||||||||||||
| // possible. Because a derived class can override Service_Send_Queue and | ||||||||||||||||||||||
| // Service_Receive_Queue, a protocol that already guarantees delivery can skip | ||||||||||||||||||||||
| // ACKing entirely. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Values for CommHeaderType::Code. | ||||||||||||||||||||||
| enum class ConnectionEnum : unsigned char | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| PACKET_DATA_ACK = 0, // a data packet requiring an ACK | ||||||||||||||||||||||
| PACKET_DATA_NOACK = 1, // a data packet not requiring an ACK | ||||||||||||||||||||||
| PACKET_ACK = 2, // an ACK for a packet | ||||||||||||||||||||||
| PACKET_COUNT = 3, // for computational purposes | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // The header prefixed to every packet the connection sends. YR widened RA's | ||||||||||||||||||||||
| // 7-byte header to 14 bytes; `forwardto` holds the packet router forwarding | ||||||||||||||||||||||
| // mask and is only filled in for internet games routed via the packet router. | ||||||||||||||||||||||
| #pragma pack(push, 1) | ||||||||||||||||||||||
| struct CommHeaderType | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| __int16 MagicNumber; | ||||||||||||||||||||||
| ConnectionEnum Code; | ||||||||||||||||||||||
| char forwardto; | ||||||||||||||||||||||
| int PacketID; | ||||||||||||||||||||||
| char field_8; | ||||||||||||||||||||||
| char field_9; | ||||||||||||||||||||||
| char field_A; | ||||||||||||||||||||||
| char field_B; | ||||||||||||||||||||||
| char field_C; | ||||||||||||||||||||||
| char field_D; | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
| #pragma pack(pop) | ||||||||||||||||||||||
| static_assert(sizeof(CommHeaderType) == 14); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // The header used by IPXGlobalConnClass. It adds a product ID so several | ||||||||||||||||||||||
| // applications can share one socket and still tell their own packets apart. | ||||||||||||||||||||||
| struct GlobalHeaderType | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| CommHeaderType Header; | ||||||||||||||||||||||
| __int16 ProductID; | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is technically not a thing, the functions actually pass void* and then cast as necessary
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||
| static_assert(sizeof(GlobalHeaderType) == 16); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class NOVTABLE ConnectionClass | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| public: | ||||||||||||||||||||||
| virtual ~ConnectionClass() RX; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| virtual void Init() | ||||||||||||||||||||||
| { JMP_THIS(0x48BF10); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Queues a packet for sending. `forwardto` is only written into the | ||||||||||||||||||||||
| // header when the game is an internet game running via the packet router. | ||||||||||||||||||||||
| virtual int Send_Packet(void* buf, int buflen, int ack_req, char forwardto) | ||||||||||||||||||||||
| { JMP_THIS(0x48BF40); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Tells the connection a packet has arrived; the connection manager calls | ||||||||||||||||||||||
| // this after parsing an incoming datagram. | ||||||||||||||||||||||
| virtual int Receive_Packet(CommHeaderType* buf, int buflen) | ||||||||||||||||||||||
| { JMP_THIS(0x48C040); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Pulls the next application packet out of the receive queue, stripping | ||||||||||||||||||||||
| // the CommHeaderType. Returns zero when nothing is ready. | ||||||||||||||||||||||
| virtual int Get_Packet(void* buf, int* buflen) | ||||||||||||||||||||||
| { JMP_THIS(0x48C320); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // The main polling routine. Should be called as often as possible. | ||||||||||||||||||||||
| virtual int Service() | ||||||||||||||||||||||
| { JMP_THIS(0x48C3B0); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Returns the current time in 60ths of a second, which is the unit the | ||||||||||||||||||||||
| // retry logic works in. | ||||||||||||||||||||||
| static DWORD Time() | ||||||||||||||||||||||
| { JMP_STD(0x48C600); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| protected: | ||||||||||||||||||||||
| // Drops send queue entries that have been ACK'd. The base implementation | ||||||||||||||||||||||
| // is a stub returning zero; IPXGlobalConnClass overrides it. | ||||||||||||||||||||||
| virtual int Purge_Send_Queue() | ||||||||||||||||||||||
| { JMP_THIS(0x48C590); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| virtual int Service_Send_Queue() | ||||||||||||||||||||||
| { JMP_THIS(0x48C3E0); } | ||||||||||||||||||||||
| virtual int Service_Receive_Queue() | ||||||||||||||||||||||
| { JMP_THIS(0x48C5A0); } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Performs the hardware-dependent send. Pure virtual, and protected | ||||||||||||||||||||||
| // because only the ACK/retry logic calls it, never the application. | ||||||||||||||||||||||
| virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) = 0; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Properties | ||||||||||||||||||||||
| public: | ||||||||||||||||||||||
| CommBufferClass* Queue; | ||||||||||||||||||||||
| int __resends; | ||||||||||||||||||||||
| int __numlost; | ||||||||||||||||||||||
| int __percentlost; | ||||||||||||||||||||||
| int __missedoverall; | ||||||||||||||||||||||
| int __missedmagic; | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||
| DWORD MaxPacketLen; // includes the CommHeaderType | ||||||||||||||||||||||
| GlobalHeaderType* PacketBuf; | ||||||||||||||||||||||
| WORD MagicNum; | ||||||||||||||||||||||
| DWORD RetryDelta; // delay before a packet is re-sent | ||||||||||||||||||||||
| DWORD MaxRetries; | ||||||||||||||||||||||
| DWORD Timeout; | ||||||||||||||||||||||
| int NumRecNoAck; | ||||||||||||||||||||||
| int NumRecAck; | ||||||||||||||||||||||
| int NumSendNoAck; | ||||||||||||||||||||||
| int NumSendAck; | ||||||||||||||||||||||
| int LastSeqID; // ID of the last consecutively-received packet | ||||||||||||||||||||||
| int LastReadID; // ID of the last PACKET_DATA_ACK packet read | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
| static_assert(sizeof(ConnectionClass) == 0x4C); | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,28 @@ | ||
| #pragma once | ||
|
|
||
| // The four-byte network number and six-byte node (MAC) address that together | ||
| // identify a machine on an IPX network. Westwood declared these as raw array | ||
| // typedefs; they are wrapped in structs here so they can be used as members | ||
| // without decaying to pointers. | ||
| struct NetNumType | ||
| { | ||
| unsigned char Value[4]; | ||
| }; | ||
| static_assert(sizeof(NetNumType) == 4); | ||
|
|
||
| struct NetNodeType | ||
| { | ||
| unsigned char Value[6]; | ||
| }; | ||
| static_assert(sizeof(NetNodeType) == 6); | ||
|
|
||
| class IPXAddressClass | ||
| { | ||
| public: | ||
| unsigned char NetworkNumber[4]; | ||
| unsigned char NodeAddress[6]; | ||
| // YR carries UDP/IP endpoints in this struct as well as real IPX | ||
| // addresses, so the trailing two bytes are only meaningful in IP mode. | ||
| unsigned char field_A[2]; | ||
| }; | ||
| static_assert(sizeof(IPXAddressClass) == 12); |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,52 @@ | ||||||||||
| #pragma once | ||||||||||
|
|
||||||||||
| #include <YRPP.h> | ||||||||||
| #include <ConnectionClass.h> | ||||||||||
| #include <IPX.h> | ||||||||||
|
|
||||||||||
| class NOVTABLE IPXConnClass : public ConnectionClass | ||||||||||
| { | ||||||||||
| public: | ||||||||||
| enum IPXConnTag | ||||||||||
| { | ||||||||||
| CONN_NAME_MAX = 40 | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| DEFINE_REFERENCE(WORD, Socket, 0xAA0568) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||
| DEFINE_REFERENCE(int, Configured, 0xAA05A4) | ||||||||||
| DEFINE_REFERENCE(int, SocketOpen, 0xAA05A8) | ||||||||||
| DEFINE_REFERENCE(int, Listening, 0xAA05AC) | ||||||||||
|
|
||||||||||
| virtual void Init() override | ||||||||||
| { JMP_THIS(0x53F4E0); } | ||||||||||
|
|
||||||||||
| static int __fastcall Open_Socket(WORD socket) | ||||||||||
| { JMP_THIS(0x53F5F0); } | ||||||||||
| static void __fastcall Close_Socket(WORD socket) | ||||||||||
| { JMP_THIS(0x53F630); } | ||||||||||
|
|
||||||||||
| static int Start_Listening() | ||||||||||
| { JMP_STD(0x53F540); } | ||||||||||
| static int Stop_Listening() | ||||||||||
| { JMP_STD(0x53F5B0); } | ||||||||||
|
|
||||||||||
| static int __fastcall Broadcast(void* buf, int buflen) | ||||||||||
| { JMP_THIS(0x53F830); } | ||||||||||
|
|
||||||||||
| protected: | ||||||||||
| virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) override | ||||||||||
| { JMP_THIS(0x53F5D0); } | ||||||||||
|
|
||||||||||
| virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, __int16 port) | ||||||||||
| { JMP_THIS(0x53F650); } | ||||||||||
|
|
||||||||||
| public: | ||||||||||
| IPXAddressClass Address; | ||||||||||
| NetNodeType ImmediateAddress; | ||||||||||
| PROTECTED_PROPERTY(BYTE, align_5E[0x2]); | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a need for all this alignment to excplicitly be here? Applies to everywhere.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||
|
|
||||||||||
| DWORD Immed_Set; | ||||||||||
| DWORD ID; | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||
| wchar_t Name[CONN_NAME_MAX]; | ||||||||||
| }; | ||||||||||
| static_assert(sizeof(IPXConnClass) == 0xB8); | ||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7b7e4ab