244 lines
5.7 KiB
C++
244 lines
5.7 KiB
C++
/*
|
|
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
|
|
|