Initial commit
This commit is contained in:
243
ZNet/ZNetPrivate.hpp
Normal file
243
ZNet/ZNetPrivate.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
ZNetPrivate.hpp
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 7/19/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
ZNet private functions and definitions
|
||||
|
||||
License:
|
||||
|
||||
Copyright 2013, 762 Studios
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZNETPRIVATE_HPP
|
||||
#define _ZNETPRIVATE_HPP
|
||||
|
||||
#include <ZUtil/ZBinaryBufferReader.hpp>
|
||||
#include <ZUtil/ZBinaryBufferWriter.hpp>
|
||||
#include <SST/SST_Net.h>
|
||||
|
||||
//========================================
|
||||
// Wire format constants
|
||||
//========================================
|
||||
|
||||
#define ZNET_BYTEORDER SST_BIG_ENDIAN //< Global byte order for all of ZNet
|
||||
|
||||
|
||||
#define ZNET_MAGIC 0x5A //'Z' in ASCII (i.e. uppercase zed)
|
||||
|
||||
#define ZNET_SYSCHANNEL 0x00u //System channel
|
||||
|
||||
#define ZNETCMD_CONNECT 0x00u //Connect request, sent from client to server
|
||||
#define ZNETCMD_DATA 0x01u //Data packet (or fragment of one)
|
||||
#define ZNETCMD_DISCONNECT 0x02u //Disconnect request
|
||||
#define ZNETCMD_ACK 0x03u //Acknowledge a range of packets, possibly including a subsequence value
|
||||
#define ZNETCMD_CONNRESP 0x04u //Connection response, send from server to client
|
||||
#define ZNETCMD_MAX 0x05u //First invalid value
|
||||
|
||||
//For ZNETCMD_ACK/DATA, the "flag" field will be set to one of these values.
|
||||
#define ZNETCMDFLAGS_LEN8 0x00u
|
||||
#define ZNETCMDFLAGS_LEN16 0x01u
|
||||
#define ZNETCMDFLAGS_LEN32 0x02u
|
||||
|
||||
#define ZNETCMDFLAGS_FULL 0x01u
|
||||
|
||||
/*
|
||||
Wire Format
|
||||
|
||||
RAW PACKET {
|
||||
u8 ZNET_MAGIC
|
||||
[ messages ]
|
||||
}
|
||||
|
||||
|
||||
MESSAGE {
|
||||
u8 channel
|
||||
u4 flags
|
||||
u4 cmd
|
||||
u16 seq
|
||||
[ message data ]
|
||||
}
|
||||
|
||||
CONNECT MESSAGE {
|
||||
u32 userdata
|
||||
}
|
||||
|
||||
DATA MESSAGE {
|
||||
[if flags == ZNETCMDFLAGS_LEN8]
|
||||
u8 offset
|
||||
u8 max
|
||||
u8 length
|
||||
[if flags == ZNETCMDFLAGS_LEN16]
|
||||
u16 offset
|
||||
u16 max
|
||||
u16 length
|
||||
[if flags == ZNETCMDFLAGS_LEN32]
|
||||
u32 offset
|
||||
u32 max
|
||||
u32 length
|
||||
|
||||
u8 data[ length ]
|
||||
}
|
||||
|
||||
DISCONNECT MESSAGE {
|
||||
u32 userdata
|
||||
}
|
||||
|
||||
ACK MESSAGE {
|
||||
u16 highestAcked : I have received up to this point
|
||||
u16 localSequence : I have sent up to this point
|
||||
|
||||
[if flags == ZNETCMDFLAGS_LEN8]
|
||||
u8 subsequence8
|
||||
[if flags == ZNETCMDFLAGS_LEN16]
|
||||
u16 subsequence16
|
||||
[if flags == ZNETCMDFLAGS_LEN32]
|
||||
u32 subsequence32
|
||||
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#define ZNET_WIRESIZE_PACKET_HEADER (sizeof(uint8_t)) //< Size of a packet header (overhead)
|
||||
#define ZNET_WIRESIZE_MESSAGE_HEADER (2*sizeof(uint8_t) + sizeof(uint16_t)) //< Size of a message header (overhead)
|
||||
|
||||
#define ZNET_WIRESIZE_PACKET_MINIMUM ZNET_WIRESIZE_PACKET_HEADER + ZNET_WIRESIZE_MESSAGE_HEADER
|
||||
|
||||
class ZNetPeer;
|
||||
|
||||
namespace ZNetPrivate
|
||||
{
|
||||
|
||||
//Used for CONNECT, DISCONNECT, CONNRESP
|
||||
struct ZNetMessageConnect
|
||||
{
|
||||
uint32_t userdata;
|
||||
};
|
||||
|
||||
//Used for ACK, ACKSUBSEQ
|
||||
struct ZNetMessageAck
|
||||
{
|
||||
uint32_t subsequence;
|
||||
uint16_t highestReceived; //Highest contiguous sequence remote host has received
|
||||
uint16_t highestSent; //Highest local sequence remote host has sent
|
||||
};
|
||||
|
||||
struct ZNetMessagePing
|
||||
{
|
||||
uint32_t token;
|
||||
};
|
||||
|
||||
//Used for DATA8, DATA16, DATA32
|
||||
struct ZNetMessageData
|
||||
{
|
||||
uint8_t* data; //Pointer within the packet
|
||||
uint32_t offset; //Offset into reassembly buffer
|
||||
uint32_t maxSize; //Maximum size of reassembled packet
|
||||
uint32_t length; //Length of this packet
|
||||
};
|
||||
|
||||
union ZNetMessage
|
||||
{
|
||||
ZNetMessageConnect connect;
|
||||
ZNetMessageAck ack;
|
||||
ZNetMessageData data;
|
||||
ZNetMessagePing ping;
|
||||
};
|
||||
|
||||
struct ZNetMessageContainer
|
||||
{
|
||||
uint32_t channel;
|
||||
uint32_t command;
|
||||
uint32_t flags;
|
||||
uint16_t sequence;
|
||||
ZNetMessage parsed;
|
||||
};
|
||||
|
||||
/*
|
||||
ZNetPrivate::ParseWirePacketHeader()
|
||||
|
||||
Parses the wire format packet header and returns true/false if successful.
|
||||
|
||||
@param reader - The reader set to the first byte of the packet in the proper byte order
|
||||
@return (bool) - True if the header is valid, false if not.
|
||||
*/
|
||||
bool ParseWirePacketHeader(ZBinaryBufferReader* reader);
|
||||
|
||||
void WriteWirePacketHeader(ZBinaryBufferWriter* writer);
|
||||
|
||||
void WriteWireMessageHeader(ZBinaryBufferWriter* writer, uint32_t channel, uint32_t flags, uint32_t command, uint16_t sequenceNumber);
|
||||
|
||||
bool SendAll(SST_Socket s, const SST_NetAddress* addr, uint8_t* data, uint32_t length);
|
||||
|
||||
/*
|
||||
ZNetPrivate::ReadNextMessage()
|
||||
|
||||
Attempt to parse the next message from a stream.
|
||||
|
||||
@param reader - The binary reader
|
||||
@param msgReturn - The parsed message (only when returning > 0)
|
||||
@return (int) - < 0: error in stream. 0: end of stream. > 0 successfully parsed message
|
||||
*/
|
||||
int ReadNextMessage(ZBinaryBufferReader* reader, ZNetPrivate::ZNetMessageContainer* msgReturn);
|
||||
|
||||
/*
|
||||
ZNetPrivate::MinimumSizeForCommand()
|
||||
|
||||
Gets the minimum size (in bytes) of a command's payload.
|
||||
|
||||
@return (uint32_t) - The number of bytes
|
||||
*/
|
||||
uint32_t MinimumSizeForCommand(uint32_t command);
|
||||
|
||||
/*
|
||||
ZNetPrivate::WireSizeForCommand()
|
||||
|
||||
Gets the approximate size for a simple command. This means packet header + message header + payload
|
||||
|
||||
@return (uint32_t) - The number of bytes
|
||||
*/
|
||||
inline uint32_t WireSizeForSimpleCommand(uint32_t command) { return MinimumSizeForCommand(command) + ZNET_WIRESIZE_PACKET_MINIMUM; }
|
||||
|
||||
/*
|
||||
ZNetPrivate::SequenceAfter()
|
||||
|
||||
Checks if seq1 comes after seq2, taking into account sequence number wraps.
|
||||
|
||||
@param seq1 - The sequence number to check
|
||||
@param seq2 - The existing sequence number
|
||||
@return (bool) - True if seq1 comes after seq2, false if seq2 comes first or equals seq1
|
||||
*/
|
||||
inline bool SequenceAfter(uint16_t seq1, uint16_t seq2)
|
||||
{
|
||||
return ((seq2 > seq1) && (seq2 - seq1 > UINT16_MAX/2)) || ((seq1 > seq2) && (seq1 - seq2 <= UINT16_MAX/2));
|
||||
}
|
||||
|
||||
inline uint32_t PackedIntegerSize(uint32_t value)
|
||||
{
|
||||
if(value <= UINT8_MAX) return sizeof(uint8_t);
|
||||
if(value <= UINT16_MAX) return sizeof(uint16_t);
|
||||
|
||||
return sizeof(uint32_t);
|
||||
}
|
||||
|
||||
void SendPingCommand(bool isReply, uint32_t givenToken, ZNetPeer* peer);
|
||||
|
||||
inline bool IsValidCommand(uint32_t command) { return (command < ZNETCMD_MAX); }
|
||||
|
||||
inline uint32_t ZNetByteOrder32(uint32_t v)
|
||||
{
|
||||
#if (SST_BYTEORDER_HOST != ZNET_BYTEORDER)
|
||||
v = SST_OS_ByteSwap32(v);
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user