|
| 1 | +/// @file |
| 2 | +/// @brief Copy-pasted `CSteamNetworkingMessage` declaration from GNS. |
| 3 | + |
| 4 | +#pragma once |
| 5 | + |
| 6 | +#include <steam/steamnetworkingtypes.h> |
| 7 | + |
| 8 | +#include <limits> |
| 9 | + |
| 10 | +#ifdef STEAMNETWORKINGSOCKETS_ENABLE_MEM_OVERRIDE |
| 11 | +#define STEAMNETWORKINGSOCKETS_DECLARE_CLASS_OPERATOR_NEW \ |
| 12 | + static void* operator new(size_t s) noexcept \ |
| 13 | + { \ |
| 14 | + return malloc(s); \ |
| 15 | + } \ |
| 16 | + static void* operator new[](size_t) = delete; \ |
| 17 | + static void operator delete(void* p) noexcept \ |
| 18 | + { \ |
| 19 | + free(p); \ |
| 20 | + } \ |
| 21 | + static void operator delete[](void*) = delete; |
| 22 | +#else |
| 23 | +#define STEAMNETWORKINGSOCKETS_DECLARE_CLASS_OPERATOR_NEW |
| 24 | +#endif |
| 25 | + |
| 26 | +typedef unsigned char byte; |
| 27 | + |
| 28 | +namespace SteamNetworkingSocketsLib |
| 29 | +{ |
| 30 | + |
| 31 | +struct SteamNetworkingMessageQueue; |
| 32 | + |
| 33 | +/// We implement priority groups using Weighted Fair Queueing. |
| 34 | +/// https://en.wikipedia.org/wiki/Weighted_fair_queueing |
| 35 | +/// The idea is to assign a virtual "timestamp" when the message |
| 36 | +/// would finish sending, and each time we have an opportunity to |
| 37 | +/// send, we select the group with the earliest finish time. |
| 38 | +/// Virtual time is essentially an arbitrary counter that increases |
| 39 | +/// at a fixed rate per outbound byte sent. |
| 40 | +typedef int64 VirtualSendTime; |
| 41 | +static constexpr VirtualSendTime k_virtSendTime_Infinite = std::numeric_limits<VirtualSendTime>::max(); |
| 42 | + |
| 43 | +/// Actual implementation of SteamNetworkingMessage_t, which is the API |
| 44 | +/// visible type. Has extra fields needed to put the message into intrusive |
| 45 | +/// linked lists. |
| 46 | +class CSteamNetworkingMessage : public SteamNetworkingMessage_t |
| 47 | +{ |
| 48 | +public: |
| 49 | + STEAMNETWORKINGSOCKETS_DECLARE_CLASS_OPERATOR_NEW |
| 50 | + static CSteamNetworkingMessage* New(uint32 cbSize); |
| 51 | + static void DefaultFreeData(SteamNetworkingMessage_t* pMsg); |
| 52 | + |
| 53 | + /// OK to delay sending this message until this time. Set to zero to explicitly force |
| 54 | + /// Nagle timer to expire and send now (but this should behave the same as if the |
| 55 | + /// timer < usecNow). If the timer is cleared, then all messages with lower message numbers |
| 56 | + /// are also cleared. |
| 57 | + // NOTE: Intentionally reusing the m_usecTimeReceived field, which is not used on outbound messages |
| 58 | + inline SteamNetworkingMicroseconds SNPSend_UsecNagle() const |
| 59 | + { |
| 60 | + return m_usecTimeReceived; |
| 61 | + } |
| 62 | + inline void SNPSend_SetUsecNagle(SteamNetworkingMicroseconds x) |
| 63 | + { |
| 64 | + m_usecTimeReceived = x; |
| 65 | + } |
| 66 | + |
| 67 | + /// "Virtual finish time". This is the "virtual time" when we |
| 68 | + /// wound have finished sending the current message, if any, |
| 69 | + /// if all priority groups were busy and we got our proportionate |
| 70 | + /// share. |
| 71 | + inline VirtualSendTime SNPSend_VirtualFinishTime() const |
| 72 | + { |
| 73 | + return m_nConnUserData; |
| 74 | + } |
| 75 | + inline void SNPSend_SetVirtualFinishTime(VirtualSendTime x) |
| 76 | + { |
| 77 | + m_nConnUserData = x; |
| 78 | + } |
| 79 | + |
| 80 | + /// Offset in reliable stream of the header byte. 0 if we're not reliable. |
| 81 | + inline int SNPSend_ReliableStreamSize() const; |
| 82 | + |
| 83 | + inline bool SNPSend_IsReliable() const; |
| 84 | + |
| 85 | + inline int64 SNPSend_ReliableStreamPos() const; |
| 86 | + inline void SNPSend_SetReliableStreamPos(int64 x); |
| 87 | + |
| 88 | + // Working data for reliable messages. |
| 89 | + struct ReliableSendInfo_t |
| 90 | + { |
| 91 | + int64 m_nStreamPos; |
| 92 | + |
| 93 | + // Number of reliable segments that refer to this message. |
| 94 | + // Also while we are in the queue waiting to be sent the queue holds a reference |
| 95 | + int m_nSentReliableSegRefCount; |
| 96 | + int m_cbHdr; |
| 97 | + byte m_hdr[16]; |
| 98 | + }; |
| 99 | + const ReliableSendInfo_t& ReliableSendInfo() const; |
| 100 | + ReliableSendInfo_t& ReliableSendInfo(); |
| 101 | + |
| 102 | + /// Remove it from queues |
| 103 | + void Unlink(); |
| 104 | + |
| 105 | + struct Links |
| 106 | + { |
| 107 | + SteamNetworkingMessageQueue* m_pQueue; |
| 108 | + CSteamNetworkingMessage* m_pPrev; |
| 109 | + CSteamNetworkingMessage* m_pNext; |
| 110 | + |
| 111 | + inline void Clear() |
| 112 | + { |
| 113 | + m_pQueue = nullptr; |
| 114 | + m_pPrev = nullptr; |
| 115 | + m_pNext = nullptr; |
| 116 | + } |
| 117 | + }; |
| 118 | + |
| 119 | + /// Intrusive links for the "primary" list we are in |
| 120 | + Links m_links; |
| 121 | + |
| 122 | + /// Intrusive links for any secondary list we may be in. (Same listen socket or |
| 123 | + /// P2P channel, depending on message type) |
| 124 | + Links m_linksSecondaryQueue; |
| 125 | + |
| 126 | + void LinkBefore(CSteamNetworkingMessage* pSuccessor, Links CSteamNetworkingMessage::* pMbrLinks, |
| 127 | + SteamNetworkingMessageQueue* pQueue); |
| 128 | + void LinkToQueueTail(Links CSteamNetworkingMessage::* pMbrLinks, SteamNetworkingMessageQueue* pQueue); |
| 129 | + void UnlinkFromQueue(Links CSteamNetworkingMessage::* pMbrLinks); |
| 130 | + |
| 131 | +//private: |
| 132 | + // Use New and Release()!! |
| 133 | + inline CSteamNetworkingMessage() |
| 134 | + { |
| 135 | + } |
| 136 | + inline ~CSteamNetworkingMessage() |
| 137 | + { |
| 138 | + } |
| 139 | + static void ReleaseFunc(SteamNetworkingMessage_t* pIMsg); |
| 140 | +}; |
| 141 | + |
| 142 | +} // namespace SteamNetworkingSocketsLib |
0 commit comments