166 lines
5.4 KiB
C++
166 lines
5.4 KiB
C++
/*
|
|
ZNetPacketChannel.hpp
|
|
Author: Patrick Baggett <ptbaggett@762studios.com>
|
|
Created: 6/14/2013
|
|
|
|
Purpose:
|
|
|
|
** NOT PART OF PUBLIC SDK **
|
|
This class is not part of the public SDK; its fields and methods are not present
|
|
in the documentation and cannot be guaranteed in future revisions.
|
|
** NOT PART OF PUBLIC SDK **
|
|
|
|
Queue of incoming and outgoing packets.
|
|
|
|
License:
|
|
|
|
Copyright 2013, 762 Studios
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef _ZNETPACKETCHANNEL_HPP
|
|
#define _ZNETPACKETCHANNEL_HPP
|
|
|
|
#include <ZSTL/ZList.hpp>
|
|
#include <ZNet/ZNetConsts.hpp>
|
|
|
|
struct ZNetPacket;
|
|
class ZNetHost;
|
|
|
|
namespace ZNetPrivate { struct ZNetMessageContainer; } //urgh
|
|
|
|
class ZNetPacketChannel
|
|
{
|
|
public:
|
|
struct ZNetQueuedPacket
|
|
{
|
|
uint64_t timeSent; //< Time this packet was sent (or 0 for never)
|
|
ZNetPacket* packet; //< Logical packet data (payload)
|
|
uint32_t subsequence; //< For data packets, this is the number of bytes successfully acked on the remote end
|
|
uint32_t command; //< Logical packet command such as ZNETCMD_CONNECT, ZNETCMD_DATA, ...
|
|
uint16_t sequence; //< Logical packet sequence
|
|
};
|
|
|
|
ZNetPacketChannel() :
|
|
packetCount(0), overflowLimit(1024), localAck(0), remoteAck(0), nextSequenceNumber(1), critical(false)
|
|
{
|
|
|
|
}
|
|
|
|
void SetOverflowThreshold(uint32_t _overflowLimit) { overflowLimit = _overflowLimit; }
|
|
|
|
|
|
/*
|
|
ZNetPacketChannel::QueueForSending()
|
|
|
|
Attempts to queue a new packet to the channel. If the overflow limit is reached,
|
|
this returns false and the client should be disconnected.
|
|
*/
|
|
bool QueueForSending(ZNetPacket* packet, uint32_t command);
|
|
|
|
bool QueueForReceiving();
|
|
|
|
|
|
/*
|
|
ZNetPacketChannel::SetChannelId()
|
|
|
|
Sets the channel's ID value for use in outgoing packets.
|
|
*/
|
|
void SetChannelId(uint32_t chId) { channelId = chId; }
|
|
|
|
/*
|
|
ZNetPacketChannel::FillBuffer()
|
|
|
|
Fills a buffer with as many packets as the buffer can hold. If all packets
|
|
have been added, this returns true. If there was not enough space to hold
|
|
all of the packets, this returns false and the index to resume at is provided.
|
|
|
|
@param buffer - Input buffer pointer
|
|
@param bufferSize - The size of the buffer pointed to by buffer[]
|
|
@param packetStartIndex - The starting index. Should start at 0, and use the value returned in restartIndexReturn to resume
|
|
@param restartIndexReturn - The index to resume packet storage.
|
|
@param bytesWritten - The number of bytes written
|
|
*/
|
|
bool FillBuffer(uint8_t* buffer, uint32_t bufferSize, uint32_t packetStartIndex, uint32_t* restartIndexReturn, uint32_t* bytesWritten);
|
|
|
|
/*
|
|
ZNetPacketChannel::Deinitialize()
|
|
*/
|
|
void Deinitialize();
|
|
|
|
|
|
/*
|
|
ZNetPacketChannel::UpdateRemoteAck()
|
|
|
|
Updates the remote ack counter and dequeues packets as necessary.
|
|
|
|
@param newHighest - The new highest sequence number
|
|
@param pingAdjust - Set to the current ping value, this value is adjusted by the RTT on a per-packet basis
|
|
*/
|
|
void UpdateRemoteAck(uint16_t newHighest, int32_t* pingAdjust);
|
|
|
|
/*
|
|
ZNetPacketChannel::UpdateLocalAck()
|
|
|
|
Updates the local sequence counter for this time period.
|
|
*/
|
|
void UpdateLocalAck(uint16_t seq);
|
|
|
|
/*
|
|
ZNetPacketChannel::QueueLocally()
|
|
|
|
Queue a received packet for local consumption. Since packets have an ordering and they may be received out of
|
|
order (e.g. send 1, 2, 3 may be processed as 2, 1, 3), this allows ZNet to reorder them and generate the
|
|
appropriate sequence of events.
|
|
*/
|
|
bool QueueLocally(const ZNetPacketChannel::ZNetQueuedPacket* container);
|
|
|
|
/*
|
|
ZNetPacketChannel::QueueData()
|
|
|
|
Queue a received data packet. This has one of three effects:
|
|
1) Full data packet received (e.g. short packet), so it just acts like QueueLocally()
|
|
2) Fragmented data packet, did not exist before now -- creates a reassembly buffer.
|
|
3) Fragmented data packet, did exist -- adds to reassembly and check if reassembly is complete. If it is, QueueLocally().
|
|
*/
|
|
bool QueueData(ZNetPrivate::ZNetMessageContainer* data);
|
|
|
|
void ProcessLocalAcks();
|
|
|
|
void SetHost(ZNetHost* _host) { host = _host; }
|
|
|
|
ZNetHost* GetHost() const { return host; }
|
|
|
|
uint16_t GetLocalAck() { return localAck; }
|
|
|
|
//Return the highest sequence number for this channel. This is one less than the "next", intuitively.
|
|
uint16_t GetHighestSent() { return nextSequenceNumber == 0 ? UINT16_MAX : nextSequenceNumber; }
|
|
private:
|
|
|
|
struct ZNetDataReassemblyPacket
|
|
{
|
|
ZNetPacket* packet; //< Logical packet data (not yet fully assembled)
|
|
uint32_t subsequence; //< Highest contiguous amount of data received
|
|
uint16_t sequence; //< The sequence number of this packet
|
|
};
|
|
|
|
ZList<ZNetQueuedPacket> packets; //List of packets we've sent (or will send) but have not yet been acknowledged
|
|
ZList<ZNetDataReassemblyPacket> reassembly;
|
|
ZList<ZNetQueuedPacket> assembled;
|
|
ZList<uint16_t> sequencesFound; //The sequence numbers found this time around (sorted)
|
|
ZNetHost* host; //Owner (used for memory allocations)
|
|
uint32_t packetCount; //ZList::Size() is O(n), keep track manually
|
|
uint32_t overflowLimit; //When this many outgoing packets are unacknowledged,
|
|
uint32_t channelId; //This channel's ID value for outgoing packets
|
|
uint16_t localAck; //Local acknowledge counter (i.e. highest number of incoming packets we've confirmed)
|
|
uint16_t remoteAck; //Remote acknowledge counter (i.e. highest number the remote host has told us it has confirmed)
|
|
uint16_t nextSequenceNumber; //Next outgoing sequence number
|
|
|
|
bool critical; //Is the remote host in a critical state?
|
|
|
|
};
|
|
|
|
#endif
|
|
|