175 lines
4.7 KiB
C++
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;
|
|
}
|