summaryrefslogtreecommitdiff
path: root/engine/net_chan.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/net_chan.h
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'engine/net_chan.h')
-rw-r--r--engine/net_chan.h354
1 files changed, 354 insertions, 0 deletions
diff --git a/engine/net_chan.h b/engine/net_chan.h
new file mode 100644
index 0000000..d0b4c51
--- /dev/null
+++ b/engine/net_chan.h
@@ -0,0 +1,354 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: net_chan.h
+//
+//=============================================================================//
+
+#ifndef NET_CHAN_H
+#define NET_CHAN_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "net.h"
+#include "netadr.h"
+#include "qlimits.h"
+#include "bitbuf.h"
+#include <inetmessage.h>
+#include <filesystem.h>
+#include "utlvector.h"
+#include "utlbuffer.h"
+#include "const.h"
+#include "inetchannel.h"
+
+// How fast to converge flow estimates
+#define FLOW_AVG ( 3.0 / 4.0 )
+ // Don't compute more often than this
+#define FLOW_INTERVAL 0.25
+
+
+#define NET_FRAMES_BACKUP 64 // must be power of 2
+#define NET_FRAMES_MASK (NET_FRAMES_BACKUP-1)
+#define MAX_SUBCHANNELS 8 // we have 8 alternative send&wait bits
+
+#define SUBCHANNEL_FREE 0 // subchannel is free to use
+#define SUBCHANNEL_TOSEND 1 // subchannel has data, but not send yet
+#define SUBCHANNEL_WAITING 2 // sbuchannel sent data, waiting for ACK
+#define SUBCHANNEL_DIRTY 3 // subchannel is marked as dirty during changelevel
+
+
+class CNetChan : public INetChannel
+{
+
+private: // netchan structurs
+
+ typedef struct dataFragments_s
+ {
+ FileHandle_t file; // open file handle
+ char filename[MAX_OSPATH]; // filename
+ char* buffer; // if NULL it's a file
+ unsigned int bytes; // size in bytes
+ unsigned int bits; // size in bits
+ unsigned int transferID; // only for files
+ bool isCompressed; // true if data is bzip compressed
+ unsigned int nUncompressedSize; // full size in bytes
+ bool asTCP; // send as TCP stream
+ int numFragments; // number of total fragments
+ int ackedFragments; // number of fragments send & acknowledged
+ int pendingFragments; // number of fragments send, but not acknowledged yet
+ } dataFragments_t;
+
+ struct subChannel_s
+ {
+ int startFraggment[MAX_STREAMS];
+ int numFragments[MAX_STREAMS];
+ int sendSeqNr;
+ int state; // 0 = free, 1 = scheduled to send, 2 = send & waiting, 3 = dirty
+ int index; // index in m_SubChannels[]
+
+ void Free()
+ {
+ state = SUBCHANNEL_FREE;
+ sendSeqNr = -1;
+ for ( int i = 0; i < MAX_STREAMS; i++ )
+ {
+ numFragments[i] = 0;
+ startFraggment[i] = -1;
+ }
+ }
+ };
+
+ // Client's now store the command they sent to the server and the entire results set of
+ // that command.
+ typedef struct netframe_s
+ {
+ // Data received from server
+ float time; // net_time received/send
+ int size; // total size in bytes
+ float latency; // raw ping for this packet, not cleaned. set when acknowledged otherwise -1.
+ float avg_latency; // averaged ping for this packet
+ bool valid; // false if dropped, lost, flushed
+ int choked; // number of previously chocked packets
+ int dropped;
+ float m_flInterpolationAmount;
+ unsigned short msggroups[INetChannelInfo::TOTAL]; // received bytes for each message group
+ } netframe_t;
+
+ typedef struct
+ {
+ float nextcompute; // Time when we should recompute k/sec data
+ float avgbytespersec; // average bytes/sec
+ float avgpacketspersec;// average packets/sec
+ float avgloss; // average packet loss [0..1]
+ float avgchoke; // average packet choke [0..1]
+ float avglatency; // average ping, not cleaned
+ float latency; // current ping, more accurate also more jittering
+ int totalpackets; // total processed packets
+ int totalbytes; // total processed bytes
+ int currentindex; // current frame index
+ netframe_t frames[ NET_FRAMES_BACKUP ]; // frame history
+ netframe_t *currentframe; // current frame
+ } netflow_t;
+
+public:
+ CNetChan();
+ ~CNetChan();
+
+public: // INetChannelInfo interface
+
+ const char *GetName( void ) const;
+ const char *GetAddress( void ) const;
+ float GetTime( void ) const;
+ float GetTimeConnected( void ) const;
+ float GetTimeSinceLastReceived( void ) const;
+ int GetDataRate( void ) const;
+ int GetBufferSize( void ) const;
+
+ bool IsLoopback( void ) const;
+ bool IsNull() const; // .dem file playback channel is of type NA_NULL!!!
+ bool IsTimingOut( void ) const;
+ bool IsPlayback( void ) const;
+
+ float GetLatency( int flow ) const;
+ float GetAvgLatency( int flow ) const;
+ float GetAvgLoss( int flow ) const;
+ float GetAvgData( int flow ) const;
+ float GetAvgChoke( int flow ) const;
+ float GetAvgPackets( int flow ) const;
+ int GetTotalData( int flow ) const;
+ int GetSequenceNr( int flow ) const ;
+ bool IsValidPacket( int flow, int frame_number ) const ;
+ float GetPacketTime( int flow, int frame_number ) const ;
+ int GetPacketBytes( int flow, int frame_number, int group ) const ;
+ bool GetStreamProgress( int flow, int *received, int *total ) const;
+ float GetCommandInterpolationAmount( int flow, int frame_number ) const;
+ void GetPacketResponseLatency( int flow, int frame_number, int *pnLatencyMsecs, int *pnChoke ) const;
+ void GetRemoteFramerate( float *pflFrameTime, float *pflFrameTimeStdDeviation ) const;
+ float GetTimeoutSeconds() const;
+
+public: // INetChannel interface
+
+ void SetDataRate(float rate);
+ bool RegisterMessage(INetMessage *msg);
+ bool StartStreaming( unsigned int challengeNr );
+ void ResetStreaming( void );
+ void SetTimeout(float seconds);
+ void SetDemoRecorder(IDemoRecorder *recorder);
+ void SetChallengeNr(unsigned int chnr);
+
+ void Reset( void );
+ void Clear( void );
+ void Shutdown(const char * reason);
+
+ void ProcessPlayback( void );
+ bool ProcessStream( void );
+ void ProcessPacket( netpacket_t * packet, bool bHasHeader );
+
+ void SetCompressionMode( bool bUseCompression );
+ void SetFileTransmissionMode(bool bBackgroundMode);
+ bool SendNetMsg( INetMessage &msg, bool bForceReliable = false, bool bVoice = false ); // send a net message
+ bool SendData(bf_write &msg, bool bReliable = true); // send a chunk of data
+ bool SendFile(const char *filename, unsigned int transferID); // transmit a local file
+ void SetChoked( void ); // choke a packet
+ int SendDatagram(bf_write *data); // build and send datagram packet
+ unsigned int RequestFile(const char *filename); // request remote file to upload, returns request ID
+ void RequestFile_OLD(const char *filename, unsigned int transferID); // request remote file to upload, returns request ID
+ void DenyFile(const char *filename, unsigned int transferID); // deny a file request
+ bool Transmit(bool onlyReliable = false); // send data from buffers
+
+ const netadr_t &GetRemoteAddress( void ) const;
+ INetChannelHandler *GetMsgHandler( void ) const;
+ int GetDropNumber( void ) const;
+ int GetSocket( void ) const;
+ unsigned int GetChallengeNr( void ) const;
+ void GetSequenceData( int &nOutSequenceNr, int &nInSequenceNr, int &nOutSequenceNrAck );
+ void SetSequenceData( int nOutSequenceNr, int nInSequenceNr, int nOutSequenceNrAck );
+
+ void UpdateMessageStats( int msggroup, int bits);
+ bool CanPacket( void ) const;
+ bool IsOverflowed( void ) const;
+ bool IsTimedOut( void ) const;
+ bool HasPendingReliableData( void );
+ void SetMaxBufferSize(bool bReliable, int nBytes, bool bVoice = false );
+ virtual int GetNumBitsWritten( bool bReliable );
+ virtual void SetInterpolationAmount( float flInterpolationAmount );
+ virtual void SetRemoteFramerate( float flFrameTime, float flFrameTimeStdDeviation );
+
+ // Max # of payload bytes before we must split/fragment the packet
+ virtual void SetMaxRoutablePayloadSize( int nSplitSize );
+ virtual int GetMaxRoutablePayloadSize();
+
+ virtual int GetProtocolVersion();
+
+ int IncrementSplitPacketSequence();
+
+public:
+
+ static bool IsValidFileForTransfer( const char *pFilename );
+
+ void Setup(int sock, netadr_t *adr, const char * name, INetChannelHandler * handler, int nProtocolVersion);
+ // Send queue management
+ void IncrementQueuedPackets();
+ void DecrementQueuedPackets();
+ bool HasQueuedPackets() const;
+
+private:
+
+ void FlowReset( void );
+ void FlowUpdate( int flow, int addbytes );
+ void FlowNewPacket(int flow, int seqnr, int acknr, int nChoked, int nDropped, int nSize );
+
+ bool ProcessMessages( bf_read &buf );
+ bool ProcessControlMessage( int cmd, bf_read &buf);
+ bool SendReliableViaStream( dataFragments_t *data);
+ bool SendReliableAcknowledge( int seqnr );
+ int ProcessPacketHeader( netpacket_t *packet );
+ void AcknowledgeSubChannel(int seqnr, int list );
+
+ bool CreateFragmentsFromBuffer( bf_write *buffer, int stream );
+ bool CreateFragmentsFromFile( const char *filename, int stream, unsigned int transferID);
+
+ void CompressFragments();
+ void UncompressFragments( dataFragments_t *data );
+
+ bool SendSubChannelData( bf_write &buf );
+ bool ReadSubChannelData( bf_read &buf, int stream );
+ void AcknowledgeSeqNr( int seqnr );
+ void CheckWaitingList(int nList);
+ bool CheckReceivingList(int nList);
+ void RemoveHeadInWaitingList( int nList );
+ bool IsFileInWaitingList( const char *filename );
+ subChannel_s *GetFreeSubChannel(); // NULL == all subchannels in use
+ void UpdateSubChannels( void );
+ void SendTCPData( void );
+
+ INetMessage *FindMessage(int type);
+
+ static bool HandleUpload( dataFragments_t *data, INetChannelHandler *MessageHandler );
+
+#ifdef STAGING_ONLY
+public:
+ static bool TestUpload( const char *filename );
+#endif
+
+public:
+
+ bool m_bProcessingMessages;
+ bool m_bClearedDuringProcessing;
+ bool m_bShouldDelete;
+
+ // last send outgoing sequence number
+ int m_nOutSequenceNr;
+ // last received incoming sequnec number
+ int m_nInSequenceNr;
+ // last received acknowledge outgoing sequnce number
+ int m_nOutSequenceNrAck;
+
+ // state of outgoing reliable data (0/1) flip flop used for loss detection
+ int m_nOutReliableState;
+ // state of incoming reliable data
+ int m_nInReliableState;
+
+ int m_nChokedPackets; //number of choked packets
+
+
+ // Reliable data buffer, send which each packet (or put in waiting list)
+ bf_write m_StreamReliable;
+ CUtlMemory<byte> m_ReliableDataBuffer;
+
+ // unreliable message buffer, cleared which each packet
+ bf_write m_StreamUnreliable;
+ CUtlMemory<byte> m_UnreliableDataBuffer;
+
+ bf_write m_StreamVoice;
+ CUtlMemory<byte> m_VoiceDataBuffer;
+
+// don't use any vars below this (only in net_ws.cpp)
+
+ int m_Socket; // NS_SERVER or NS_CLIENT index, depending on channel.
+ int m_StreamSocket; // TCP socket handle
+
+ unsigned int m_MaxReliablePayloadSize; // max size of reliable payload in a single packet
+
+ // Address this channel is talking to.
+ netadr_t remote_address;
+
+ // For timeouts. Time last message was received.
+ float last_received;
+ // Time when channel was connected.
+ double connect_time;
+
+ // Bandwidth choke
+ // Bytes per second
+ int m_Rate;
+ // If realtime > cleartime, free to send next packet
+ double m_fClearTime;
+
+ CUtlVector<dataFragments_t*> m_WaitingList[MAX_STREAMS]; // waiting list for reliable data and file transfer
+ dataFragments_t m_ReceiveList[MAX_STREAMS]; // receive buffers for streams
+ subChannel_s m_SubChannels[MAX_SUBCHANNELS];
+
+ unsigned int m_FileRequestCounter; // increasing counter with each file request
+ bool m_bFileBackgroundTranmission; // if true, only send 1 fragment per packet
+ bool m_bUseCompression; // if true, larger reliable data will be bzip compressed
+
+ // TCP stream state maschine:
+ bool m_StreamActive; // true if TCP is active
+ int m_SteamType; // STREAM_CMD_*
+ int m_StreamSeqNr; // each blob send of TCP as an increasing ID
+ int m_StreamLength; // total length of current stream blob
+ int m_StreamReceived; // length of already received bytes
+ char m_SteamFile[MAX_OSPATH]; // if receiving file, this is it's name
+ CUtlMemory<byte> m_StreamData; // Here goes the stream data (if not file). Only allocated if we're going to use it.
+
+ // packet history
+ netflow_t m_DataFlow[ MAX_FLOWS ];
+ int m_MsgStats[INetChannelInfo::TOTAL]; // total bytes for each message group
+
+
+ int m_PacketDrop; // packets lost before getting last update (was global net_drop)
+
+ char m_Name[32]; // channel name
+
+ unsigned int m_ChallengeNr; // unique, random challenge number
+
+ float m_Timeout; // in seconds
+
+ INetChannelHandler *m_MessageHandler; // who registers and processes messages
+ CUtlVector<INetMessage*> m_NetMessages; // list of registered message
+ IDemoRecorder *m_DemoRecorder; // if != NULL points to a recording/playback demo object
+ int m_nQueuedPackets;
+
+ float m_flInterpolationAmount;
+ float m_flRemoteFrameTime;
+ float m_flRemoteFrameTimeStdDeviation;
+ int m_nMaxRoutablePayloadSize;
+
+ int m_nSplitPacketSequence;
+ bool m_bStreamContainsChallenge; // true if PACKET_FLAG_CHALLENGE was set when receiving packets from the sender
+
+ int m_nProtocolVersion; // PROTOCOL_VERSION if we're not playing a demo - otherwise, whatever was in the demo header's networkprotocol if the CNetChan instance was created by a demo player.
+};
+
+
+#endif // NET_CHAN_H