mirror of
https://github.com/ValveSoftware/GameNetworkingSockets.git
synced 2026-05-29 16:20:34 +00:00
Promote DataPacketSerializer from SDR code to shared code
Use this in the plain UDP code, so now all serializers are the same. P4:9135021
This commit is contained in:
@@ -539,45 +539,37 @@ int CConnectionTransportUDPBase::SendEncryptedDataChunk( const void *pChunk, int
|
||||
UDPSendPacketContext_t &ctx = static_cast<UDPSendPacketContext_t &>( ctxBase );
|
||||
|
||||
uint8 pkt[ k_cbSteamNetworkingSocketsMaxUDPMsgLen ];
|
||||
UDPDataMsgHdr *hdr = (UDPDataMsgHdr *)pkt;
|
||||
hdr->m_unMsgFlags = 0x80;
|
||||
iovec gather[2];
|
||||
gather[0].iov_base = pkt;
|
||||
DataPacketSerializer<UDPDataMsgHdr> out( gather, pChunk, cbChunk );
|
||||
out.hdr.m_unMsgFlags = 0x80;
|
||||
Assert( m_connection.m_unConnectionIDRemote != 0 );
|
||||
hdr->m_unToConnectionID = LittleDWord( m_connection.m_unConnectionIDRemote );
|
||||
hdr->m_unSeqNum = LittleWord( m_connection.m_statsEndToEnd.ConsumeSendPacketNumberAndGetWireFmt( ctx.m_usecNow ) );
|
||||
|
||||
byte *p = (byte*)( hdr + 1 );
|
||||
out.hdr.m_unToConnectionID = LittleDWord( m_connection.m_unConnectionIDRemote );
|
||||
out.hdr.m_unSeqNum = LittleWord( m_connection.m_statsEndToEnd.ConsumeSendPacketNumberAndGetWireFmt( ctx.m_usecNow ) );
|
||||
|
||||
// Check how much bigger we could grow the header
|
||||
// and still fit in a packet
|
||||
int cbHdrOutSpaceRemaining = pkt + sizeof(pkt) - p - cbChunk;
|
||||
if ( cbHdrOutSpaceRemaining < 0 )
|
||||
if ( out.HdrBytesRemaining() < 0 )
|
||||
{
|
||||
AssertMsg( false, "MTU / header size problem!" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try to trim stuff from blob, if it won't fit
|
||||
ctx.Trim( cbHdrOutSpaceRemaining );
|
||||
ctx.Trim( out.HdrBytesRemaining() );
|
||||
|
||||
if ( ctx.Serialize( p ) )
|
||||
if ( ctx.Serialize( out.m_pOut ) )
|
||||
{
|
||||
// Update bookkeeping with the stuff we are actually sending
|
||||
TrackSentStats( ctx );
|
||||
|
||||
// Mark header with the flag
|
||||
hdr->m_unMsgFlags |= hdr->kFlag_ProtobufBlob;
|
||||
out.hdr.m_unMsgFlags |= out.hdr.kFlag_ProtobufBlob;
|
||||
}
|
||||
|
||||
// !FIXME! Time since previous, for jitter measurement?
|
||||
|
||||
// Use gather-based send. This saves one memcpy of every payload
|
||||
iovec gather[2];
|
||||
gather[0].iov_base = pkt;
|
||||
gather[0].iov_len = p - pkt;
|
||||
gather[1].iov_base = const_cast<void*>( pChunk );
|
||||
gather[1].iov_len = cbChunk;
|
||||
|
||||
int cbSend = gather[0].iov_len + gather[1].iov_len;
|
||||
int cbSend = out.Finish();
|
||||
Assert( cbSend <= sizeof(pkt) ); // Bug in the code above. We should never "overflow" the packet. (Ignoring the fact that we using a gather-based send. The data could be tiny with a large header for piggy-backed stats.)
|
||||
|
||||
// !FIXME! Should we track data payload separately? Maybe we ought to track
|
||||
|
||||
@@ -1036,6 +1036,62 @@ protected:
|
||||
virtual ~CPossibleOutOfOrderPacket();
|
||||
};
|
||||
|
||||
// Helper used to serialize data packets with a header and optional inline stats blob
|
||||
struct DataPacketSerializerBase
|
||||
{
|
||||
int HdrBytesRemaining() const { return int( m_pMaxOut - m_pOut ); }
|
||||
|
||||
inline void PutUint16( uint16 x )
|
||||
{
|
||||
*(uint16*)m_pOut = x;
|
||||
m_pOut += sizeof(uint16);
|
||||
Assert( m_pOut <= m_pMaxOut );
|
||||
}
|
||||
|
||||
uint8 *m_pOut;
|
||||
uint8 *m_pMaxOut;
|
||||
};
|
||||
|
||||
// Data packet serializer used in client code, where we use iovec
|
||||
// so that we let th OS gather the header and the payload in
|
||||
// a single system call
|
||||
template <typename THdr >
|
||||
struct DataPacketSerializer : DataPacketSerializerBase
|
||||
{
|
||||
DataPacketSerializer( iovec *pOvecOut, const void *pPayloadIn, int cbPayload )
|
||||
: m_iov_out( pOvecOut )
|
||||
, hdr( *(THdr *)( pOvecOut[0].iov_base ) )
|
||||
{
|
||||
|
||||
// Make sure we have room for our header, and some occasional inline stats, and the max payload
|
||||
COMPILE_TIME_ASSERT( sizeof(THdr) + k_cbSteamNetworkingSocketsMaxEncryptedPayloadSend + 32 <= k_cbSteamNetworkingSocketsMaxUDPMsgLen );
|
||||
|
||||
// Set payload
|
||||
m_iov_out[1].iov_base = (void*)pPayloadIn;
|
||||
m_iov_out[1].iov_len = cbPayload;
|
||||
|
||||
// Write pointer for data after header
|
||||
m_pOut = (uint8*)( &hdr + 1 );
|
||||
|
||||
// Max place we could advance this cursor, and still fit in the payload
|
||||
m_pMaxOut = m_pOut + ( k_cbSteamNetworkingSocketsMaxUDPMsgLen - sizeof(THdr) - cbPayload );
|
||||
Assert( m_pMaxOut >= m_pOut );
|
||||
}
|
||||
|
||||
int Finish()
|
||||
{
|
||||
Assert( m_pOut <= m_pMaxOut );
|
||||
|
||||
// Set header size
|
||||
m_iov_out[0].iov_len = m_pOut - (uint8*)m_iov_out[0].iov_base;
|
||||
|
||||
return int( m_iov_out[0].iov_len + m_iov_out[1].iov_len );
|
||||
}
|
||||
|
||||
THdr &hdr;
|
||||
iovec *m_iov_out;
|
||||
};
|
||||
|
||||
} // namespace SteamNetworkingSocketsLib
|
||||
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
Reference in New Issue
Block a user