mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-26 15:44:51 +01:00
196 lines
7.2 KiB
C++
196 lines
7.2 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
#ifndef SE_INCL_PACKET_H
|
|
#define SE_INCL_PACKET_H
|
|
#ifdef PRAGMA_ONCE
|
|
#pragma once
|
|
#endif
|
|
|
|
#include <Engine/Base/Lists.h>
|
|
#include <Engine/Base/Timer.h>
|
|
|
|
|
|
// The total size of the UDP packet should be below 1450 bytes, to reduce the
|
|
// packet drop rate caused by routers dropping large UDP packets. UDP_BLOCK_SIZE is the
|
|
// maximum length of real data, not counting the packet header (ulPacketSequence, bReliable,uwID)
|
|
#define MAX_UDP_BLOCK_SIZE 1400
|
|
#define MAX_HEADER_SIZE (sizeof(UBYTE) + sizeof(ULONG) + sizeof(UWORD) + sizeof(ULONG)) // pa_bReliable + pa_ulPacketSequence + pa_uwID + pa_ulTransferSize
|
|
#define MAX_PACKET_SIZE (MAX_UDP_BLOCK_SIZE + MAX_HEADER_SIZE)
|
|
|
|
// flags for different kinds of packets used by the netcode - note that the acknowledge packets are unreliable
|
|
#define UDP_PACKET_UNRELIABLE 0
|
|
#define UDP_PACKET_RELIABLE 1
|
|
#define UDP_PACKET_RELIABLE_HEAD 2
|
|
#define UDP_PACKET_RELIABLE_TAIL 4
|
|
#define UDP_PACKET_ACKNOWLEDGE 8
|
|
#define UDP_PACKET_CONNECT_REQUEST 16
|
|
#define UDP_PACKET_CONNECT_RESPONSE 32
|
|
|
|
// constants for CPacket::CanRetry() function - they describe the retry state of the packet
|
|
#define RS_NOW 0 // the packet should be resent immediately
|
|
#define RS_NOTNOW 1 // the packet should be resent at a later time
|
|
#define RS_NOTATALL 2 // the packet has reached the maximum number of retries - give up
|
|
|
|
|
|
class CAddress {
|
|
public:
|
|
ULONG adr_ulAddress; // host address
|
|
UWORD adr_uwPort; // host port
|
|
UWORD adr_uwID; // host id
|
|
void MakeBroadcast(void);
|
|
void Clear(void) {
|
|
adr_ulAddress = 0;
|
|
adr_uwPort = 0;
|
|
adr_uwID = 0;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* A class that contains a single UDP packet.
|
|
*/
|
|
class CPacket {
|
|
public:
|
|
ULONG pa_ulSequence; // Sequence number of this packet
|
|
UBYTE pa_ubReliable; // Is packet reliable or not
|
|
SLONG pa_slSize; // Number of data bytes in packet (without header)
|
|
SLONG pa_slTransferSize; // Number of data bytes in a data transfer unit this packet belongs to
|
|
|
|
UBYTE pa_ubRetryNumber; // How many retries so far for this packet
|
|
CTimerValue pa_tvSendWhen; // When to try sending this packet (includes latency bandwidth limitations
|
|
// as well as retry intervals)
|
|
|
|
UBYTE pa_pubPacketData[MAX_PACKET_SIZE]; // Packet header + actual data contained in the packet
|
|
|
|
CListNode pa_lnListNode; // used to create a linked list of packets - buffer
|
|
|
|
CAddress pa_adrAddress; // packet address, port and client ID
|
|
|
|
// Constructors/destructors
|
|
CPacket() { Clear(); } // Default Constructor
|
|
CPacket(CPacket &paOriginal); // Copy constructor
|
|
~CPacket() { Clear(); }
|
|
|
|
// Reset all packet data and free allocated memory
|
|
void Clear();
|
|
|
|
// Write data to the packet and add header data
|
|
BOOL WriteToPacket(void* pv,SLONG slSize,UBYTE ubReliable,ULONG ulSequence,UWORD uwClientID,SLONG slTransferSize);
|
|
// Write raw data to the packet and extract header data from the data
|
|
BOOL WriteToPacketRaw(void* pv,SLONG slSize);
|
|
// Read data from the packet (no header data)
|
|
BOOL ReadFromPacket(void* pv,SLONG &slExpectedSize);
|
|
|
|
// Is packet reliable
|
|
BOOL IsReliable();
|
|
// Is packet a head of a reliable stream?
|
|
BOOL IsReliableHead();
|
|
// Is packet a tail of a reliable stream?
|
|
BOOL IsReliableTail();
|
|
// Is the packet from a broadcast address (pa_uwID not assigned)
|
|
BOOL IsBroadcast();
|
|
|
|
// Get the sequence number of the packet (must be reliable)
|
|
ULONG GetSequence();
|
|
// What is the current retry status?
|
|
UBYTE CanRetry();
|
|
// Drop the packet from the list
|
|
void Drop();
|
|
|
|
// get the size of data transfer unit this packet belongs to
|
|
SLONG CPacket::GetTransferSize();
|
|
|
|
// Copy operator
|
|
void operator=(const CPacket &paOriginal);
|
|
|
|
};
|
|
|
|
|
|
// data used to limit bandwidth/lantency and calculate statistics in packet-buffers
|
|
class CPacketBufferStats {
|
|
public:
|
|
FLOAT pbs_fLatencyLimit; // minimum latency in seconds
|
|
FLOAT pbs_fLatencyVariation;// additional latency variation
|
|
FLOAT pbs_fBandwidthLimit; // maximum bandwidth in bps (bits per second)
|
|
CTimerValue pbs_tvTimeNextPacketStart; // next point in time free for data receiving
|
|
|
|
|
|
void Clear(void);
|
|
// get time when the packet will be allowed to leave the buffer
|
|
CTimerValue GetPacketSendTime(SLONG slSize);
|
|
};
|
|
|
|
|
|
class CPacketBuffer {
|
|
public:
|
|
ULONG pb_ulTotalSize; // Total size of data in packets stored in this buffer (no headers)
|
|
ULONG pb_ulLastSequenceOut; // Sequence number of the last packet taken out of the buffer
|
|
|
|
CListHead pb_lhPacketStorage;
|
|
|
|
ULONG pb_ulNumOfPackets; // Total number of packets currently in storage
|
|
ULONG pb_ulNumOfReliablePackets; // Number of reliable packets in storage (0 if no reliable stream in progress)
|
|
|
|
CPacketBufferStats *pb_ppbsStats; // for bandwidth/latency emulation stats and limits
|
|
CPacketBufferStats pb_pbsLimits; // maximum output BPS for the buffer, to prevent client flooding
|
|
|
|
CPacketBuffer() { Clear(); };
|
|
~CPacketBuffer() { Clear(); };
|
|
|
|
// Empty the packet buffer
|
|
void Clear();
|
|
// Is the packet buffer empty?
|
|
BOOL IsEmpty();
|
|
|
|
// Calculate when the packet can be output from the buffer
|
|
CTimerValue GetPacketSendTime(SLONG slSize);
|
|
|
|
// Adds a packet to the end of the packet buffer
|
|
BOOL AppendPacket(CPacket &paPacket,BOOL bDelay);
|
|
// Inserts the packet in the buffer, according to it's sequence number
|
|
BOOL InsertPacket(CPacket &paPacket,BOOL bDelay);
|
|
// Bumps up the retry count and time, and appends the packet to the buffer
|
|
BOOL Retry(CPacket &paPacket);
|
|
// Reads the data from the first packet in the bufffer, but does not remove it
|
|
CPacket* PeekFirstPacket();
|
|
// Reads the first packet in the bufffer
|
|
CPacket* GetFirstPacket();
|
|
// Reads the data from the packet with the requested sequence, but does not remove it
|
|
CPacket* PeekPacket(ULONG ulSequence);
|
|
// Reads the packet with the requested sequence
|
|
CPacket* GetPacket(ULONG ulSequence);
|
|
// Reads the first connection request packet from the buffer
|
|
CPacket* GetConnectRequestPacket();
|
|
// Removes the first packet from the buffer
|
|
BOOL RemoveFirstPacket(BOOL bDelete);
|
|
// Removes the packet with the requested sequence from the buffer
|
|
BOOL RemovePacket(ULONG ulSequence,BOOL bDelete);
|
|
// Remove connect response packets from the buffer
|
|
BOOL RemoveConnectResponsePackets();
|
|
|
|
// Gets the sequence number of the first packet in the buffer
|
|
ULONG GetFirstSequence();
|
|
// Gets the sequence number of the last packet in the buffer
|
|
ULONG GetLastSequence();
|
|
// Is the packet with the given sequence in the buffer?
|
|
BOOL IsSequenceInBuffer(ULONG ulSequence);
|
|
// Check if the buffer contains a complete sequence of reliable packets at the start of the buffer
|
|
BOOL CheckSequence(SLONG &slSize);
|
|
|
|
};
|
|
|
|
|
|
#endif /* include-once check. */
|