diff --git a/src/engine/net_chan.cpp b/src/engine/net_chan.cpp index 50b9299d..1aa23ed5 100644 --- a/src/engine/net_chan.cpp +++ b/src/engine/net_chan.cpp @@ -19,16 +19,18 @@ //----------------------------------------------------------------------------- -// Purpose: gets the netchannel network loss +// Purpose: gets the netchannel resend rate // Output : float //----------------------------------------------------------------------------- -float CNetChan::GetNetworkLoss() const +float CNetChan::GetResendRate() const { - int64_t totalupdates = this->m_DataFlow[FLOW_INCOMING].totalupdates; + const int64_t totalupdates = this->m_DataFlow[FLOW_INCOMING].totalupdates; + if (!totalupdates && !this->m_nSequencesSkipped_MAYBE) return 0.0f; float lossRate = (float)(totalupdates + m_nSequencesSkipped_MAYBE); + if (totalupdates + m_nSequencesSkipped_MAYBE < 0.0f) lossRate += float(2 ^ 64); @@ -64,6 +66,36 @@ double CNetChan::GetTimeConnected(void) const return (t > 0.0) ? t : 0.0; } +//----------------------------------------------------------------------------- +// Purpose: gets the number of bits written in selected stream +//----------------------------------------------------------------------------- +int CNetChan::GetNumBitsWritten(const bool bReliable) +{ + bf_write* pStream = &m_StreamUnreliable; + + if (bReliable) + { + pStream = &m_StreamReliable; + } + + return pStream->GetNumBitsWritten(); +} + +//----------------------------------------------------------------------------- +// Purpose: gets the number of bits written in selected stream +//----------------------------------------------------------------------------- +int CNetChan::GetNumBitsLeft(const bool bReliable) +{ + bf_write* pStream = &m_StreamUnreliable; + + if (bReliable) + { + pStream = &m_StreamReliable; + } + + return pStream->GetNumBitsLeft(); +} + //----------------------------------------------------------------------------- // Purpose: flows a new packet // Input : *pChan - @@ -394,8 +426,9 @@ bool CNetChan::ProcessMessages(bf_read* buf) if (!NET_ReadMessageType(&cmd, buf) && buf->m_bOverflow) { - Warning(eDLL_T::ENGINE, "%s(%s): Incoming buffer overflow!\n", __FUNCTION__, GetAddress()); + Error(eDLL_T::ENGINE, 0, "%s(%s): Incoming buffer overflow!\n", __FUNCTION__, GetAddress()); m_MessageHandler->ConnectionCrashed("Buffer overflow in net message"); + return false; } @@ -475,6 +508,12 @@ bool CNetChan::ProcessMessages(bf_read* buf) } } +bool CNetChan::ReadSubChannelData(bf_read& buf) +{ + // TODO: rebuild this and hook + return false; +} + //----------------------------------------------------------------------------- // Purpose: send message // Input : &msg - @@ -482,10 +521,10 @@ bool CNetChan::ProcessMessages(bf_read* buf) // bVoice - // Output : true on success, false on failure //----------------------------------------------------------------------------- -bool CNetChan::SendNetMsg(INetMessage& msg, bool bForceReliable, bool bVoice) +bool CNetChan::SendNetMsg(INetMessage& msg, const bool bForceReliable, const bool bVoice) { if (remote_address.GetType() == netadrtype_t::NA_NULL) - return false; + return true; bf_write* pStream = &m_StreamUnreliable; @@ -495,19 +534,59 @@ bool CNetChan::SendNetMsg(INetMessage& msg, bool bForceReliable, bool bVoice) if (bVoice) pStream = &m_StreamVoice; - if (pStream != &m_StreamUnreliable || - pStream->GetNumBytesLeft() >= NET_UNRELIABLE_STREAM_MINSIZE) - { - AcquireSRWLockExclusive(&m_Lock); + if (pStream == &m_StreamUnreliable && pStream->GetNumBytesLeft() < NET_UNRELIABLE_STREAM_MINSIZE) + return true; - pStream->WriteUBitLong(msg.GetType(), NETMSG_TYPE_BITS); - if (!pStream->IsOverflowed()) - msg.WriteToBuffer(pStream); + AcquireSRWLockExclusive(&m_Lock); - ReleaseSRWLockExclusive(&m_Lock); - } + pStream->WriteUBitLong(msg.GetType(), NETMSG_TYPE_BITS); + const bool ret = msg.WriteToBuffer(pStream); - return true; + ReleaseSRWLockExclusive(&m_Lock); + + return !pStream->IsOverflowed() && ret; +} + +//----------------------------------------------------------------------------- +// Purpose: send data +// Input : &msg - +// bReliable - +// Output : true on success, false on failure +//----------------------------------------------------------------------------- +bool CNetChan::SendData(bf_write& msg, const bool bReliable) +{ + // Always queue any pending reliable data ahead of the fragmentation buffer + + if (remote_address.GetType() == netadrtype_t::NA_NULL) + return true; + + if (msg.GetNumBitsWritten() <= 0) + return true; + + if (msg.IsOverflowed() && !bReliable) + return true; + + bf_write& buf = bReliable + ? m_StreamReliable + : m_StreamUnreliable; + + const int dataBits = msg.GetNumBitsWritten(); + const int bitsLeft = buf.GetNumBitsLeft(); + + if (dataBits > bitsLeft) + { + if (bReliable) + { + Error(eDLL_T::ENGINE, 0, "%s(%s): Data too large for reliable buffer (%i > %i)!\n", + __FUNCTION__, GetAddress(), msg.GetNumBytesWritten(), buf.GetNumBytesLeft()); + + m_MessageHandler->ChannelDisconnect("reliable buffer is full"); + } + + return false; + } + + return buf.WriteBits(msg.GetData(), dataBits); } //----------------------------------------------------------------------------- diff --git a/src/engine/net_chan.h b/src/engine/net_chan.h index 3cd8dec5..1a032bbe 100644 --- a/src/engine/net_chan.h +++ b/src/engine/net_chan.h @@ -110,7 +110,7 @@ public: inline int GetDataRate(void) const { return m_Rate; } inline int GetBufferSize(void) const { return NET_FRAMES_BACKUP; } - float GetNetworkLoss() const; + float GetResendRate() const; inline float GetLatency(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].latency; } inline float GetAvgChoke(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgchoke; } @@ -128,13 +128,17 @@ public: inline int GetSocket(void) const { return m_Socket; } inline const bf_write& GetStreamVoice(void) const { return m_StreamVoice; } inline const netadr_t& GetRemoteAddress(void) const { return remote_address; } + + int GetNumBitsWritten(const bool bReliable); + int GetNumBitsLeft(const bool bReliable); inline bool IsOverflowed(void) const { return m_StreamReliable.IsOverflowed(); } bool HasPendingReliableData(void); inline bool CanPacket(void) const { return CNetChan__CanPacket(this); } inline int SendDatagram(bf_write* pDatagram) { return CNetChan__SendDatagram(this, pDatagram); } - bool SendNetMsg(INetMessage& msg, bool bForceReliable, bool bVoice); + bool SendNetMsg(INetMessage& msg, const bool bForceReliable, const bool bVoice); + bool SendData(bf_write& msg, const bool bReliable); INetMessage* FindMessage(int type); bool RegisterMessage(INetMessage* msg); @@ -144,6 +148,8 @@ public: void FreeReceiveList(); bool ProcessMessages(bf_read* pMsg); + bool ReadSubChannelData(bf_read& buf); + static void _Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow); static bool _ProcessMessages(CNetChan* pChan, bf_read* pMsg);