Files
libsst/ZNet/ZNetPrivate.cpp
2026-04-03 00:22:39 -05:00

175 lines
4.7 KiB
C++

/*
ZNetPrivate.cpp
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 7/19/2013
Purpose:
ZNet private functions and definitions
License:
Copyright 2013, 762 Studios
*/
#include "ZNetPrivate.hpp"
#include <ZNet/ZNetPeer.hpp>
#include <SST/SST_Assert.h>
/*************************************************************************/
bool ZNetPrivate::ParseWirePacketHeader(ZBinaryBufferReader* reader)
{
//Packet is absolutely too small to have any useful data (i.e. size < minimum overhead)
if(reader->GetLength() < ZNET_WIRESIZE_PACKET_MINIMUM)
return false;
if(reader->ReadU8() != ZNET_MAGIC)
return false;
return true;
}
/*************************************************************************/
void ZNetPrivate::WriteWirePacketHeader(ZBinaryBufferWriter* writer)
{
writer->WriteU8(ZNET_MAGIC);
}
/*************************************************************************/
void ZNetPrivate::WriteWireMessageHeader(ZBinaryBufferWriter* writer, uint32_t channel, uint32_t flags, uint32_t command, uint16_t sequenceNumber)
{
uint8_t merged = (uint8_t)(((flags & 0x0F) << 4) | (command & 0x0F));
writer->WriteU8((uint8_t)channel);
writer->WriteU8(merged);
writer->WriteU16(sequenceNumber);
}
/*************************************************************************/
bool ZNetPrivate::SendAll(SST_Socket s, const SST_NetAddress* addr, uint8_t* data, uint32_t length)
{
size_t totalSent;
if(SST_Net_SendTo(s, data, length, 0, addr, &totalSent) == SSTNETRESULT_SUCCESS)
{
//Return true if and only if all data was sent
return ((uint32_t)totalSent == length);
}
//Failed to send at all... :(
return false;
}
/*************************************************************************/
int ZNetPrivate::ReadNextMessage(ZBinaryBufferReader* reader, ZNetPrivate::ZNetMessageContainer* msgReturn)
{
if(reader->GetLength() - reader->GetOffset() == 0)
return 0;
if(!reader->CanRead(ZNET_WIRESIZE_MESSAGE_HEADER))
return -1; //error in stream
//Read channel
msgReturn->channel = reader->ReadU8();
//Read command+flags (merged 8-bit value)
uint8_t cmdAndFlags = reader->ReadU8();
msgReturn->command = (cmdAndFlags & 0x0F) >> 0;
msgReturn->flags = (cmdAndFlags & 0xF0) >> 4;
msgReturn->sequence = reader->ReadU16();
//Validate the command is OK
if(!ZNetPrivate::IsValidCommand(msgReturn->command))
return -1;
//TODO: validate flags for each command.
//Ensure we can read at least the minimum number of bytes required for the command
if(!reader->CanRead(ZNetPrivate::MinimumSizeForCommand(msgReturn->command)))
return -1;
switch(msgReturn->command)
{
case ZNETCMD_CONNECT:
case ZNETCMD_DISCONNECT:
case ZNETCMD_CONNRESP:
{
msgReturn->parsed.connect.userdata = reader->ReadU32();
break;
}
case ZNETCMD_DATA:
{
if(msgReturn->flags & ZNETCMDFLAGS_LEN8)
{
msgReturn->parsed.data.offset = reader->ReadU8();
msgReturn->parsed.data.maxSize = reader->ReadU8();
msgReturn->parsed.data.length = reader->ReadU8();
}
else if(msgReturn->flags & ZNETCMDFLAGS_LEN16)
{
msgReturn->parsed.data.offset = reader->ReadU16();
msgReturn->parsed.data.maxSize = reader->ReadU16();
msgReturn->parsed.data.length = reader->ReadU16();
}
else if(msgReturn->flags & ZNETCMDFLAGS_LEN32)
{
msgReturn->parsed.data.offset = reader->ReadU32();
msgReturn->parsed.data.maxSize = reader->ReadU32();
msgReturn->parsed.data.length = reader->ReadU32();
}
msgReturn->parsed.data.data = (uint8_t*)reader->GetBufferReadAddress();
//Verify access
if(!reader->CanRead(msgReturn->parsed.data.length))
return -1;
break;
}
case ZNETCMD_ACK:
{
msgReturn->parsed.ack.highestReceived = reader->ReadU16();
msgReturn->parsed.ack.highestSent = reader->ReadU16();
//Read 8-bit, 16-bit, or 32-bit subsequence
if(msgReturn->flags & ZNETCMDFLAGS_LEN8)
msgReturn->parsed.ack.subsequence = reader->ReadU8();
else if(msgReturn->flags & ZNETCMDFLAGS_LEN16)
msgReturn->parsed.ack.subsequence = reader->ReadU16();
else if(msgReturn->flags & ZNETCMDFLAGS_LEN32)
msgReturn->parsed.ack.subsequence = reader->ReadU32();
break;
}
}
//Read a full message
return 1;
}
/*************************************************************************/
uint32_t ZNetPrivate::MinimumSizeForCommand(uint32_t command)
{
uint32_t size;
switch(command)
{
case ZNETCMD_CONNECT: size = sizeof(uint32_t); break;
case ZNETCMD_DATA: size = sizeof(uint8_t)*3; break;
case ZNETCMD_DISCONNECT: size = sizeof(uint32_t); break;
case ZNETCMD_ACK: size = 2*sizeof(uint16_t); break;
case ZNETCMD_CONNRESP: size = sizeof(uint32_t); break;
default:
SST_OS_DebugError("Should not reach here");
size = UINT32_MAX;
break;
}
return size;
}