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

146 lines
3.4 KiB
C++

/*
ZNetHost.cpp
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 6/4/2013
Purpose:
ZNet host class, represents the local system
License:
Copyright 2013, 762 Studios
*/
#include <ZNet/ZNetHost.hpp>
#include <ZNet/ZNetPacket.hpp>
#include <ZNet/ZNetConsts.hpp>
#include <ZNet/ZNetPeer.hpp>
#include <SST/SST_Alloc.h> //SST_OS_Alloca()
#include "ZNetPrivate.hpp"
#include <SST/SST_OS.h>
#include <ZUtil/ZBinaryBufferReader.hpp>
#include <stdio.h> //HACKHACK
/*************************************************************************/
ZNetHost::ZNetHost()
{
mtu = ZNET_MTU_IPV4SAFE; //Safe, but small MTU as a default
dropChance = 0;
}
/*************************************************************************/
ZNetPacket* ZNetHost::CreatePacket(const void* initData, uint32_t dataSize, uint32_t flags)
{
ZNetPacket* packet;
//Validate that ONLY legitimate bits are set
if(flags != 0)
return NULL;
//Allocate packet structure + data
packet = (ZNetPacket*)malloc(sizeof(ZNetPacket) + dataSize);
if(packet == NULL)
return NULL;
packet->flags = flags;
packet->dataSize = dataSize;
packet->refCount = 1;
if(initData != NULL)
memcpy(packet->GetData(), initData, dataSize);
return packet;
}
/*************************************************************************/
bool ZNetHost::GetNextEvent(ZNetEvent* eventReturn)
{
if(!events.Empty())
{
*eventReturn = events.PopFront();
return true;
}
return false;
}
/*************************************************************************/
bool ZNetHost::SendToPeer(ZNetPeer* peer)
{
uint8_t* data = (uint8_t*)SST_OS_Alloca(GetMTU());
bool unsent = false;
//TODO: No bandwidth allocations done here
//TODO: send in round-robin fashion across channels
ZBinaryBufferWriter writer(data, GetMTU(), ZNET_BYTEORDER);
ZNetPrivate::WriteWirePacketHeader(&writer);
//OUTER LOOP: for each channel
for(uint32_t i=0; i<peer->GetNumberChannels(); i++)
{
ZNetPacketChannel* channel = peer->GetPacketChannel(i);
bool moreInChannel = true;
uint32_t index = 0;
uint32_t newIndex;
uint32_t nrWritten;
//INNER LOOP: fill buffer with channel data
do
{
uint32_t remain = mtu - (uint32_t)writer.GetOffset();
if(!channel->FillBuffer((uint8_t*)writer.GetBufferWriteAddress(), remain, index, &newIndex, &nrWritten))//TODO: update to make use of ZBinaryBufferWriter interface
{
//Buffer is full, send now
index = newIndex;
writer.SeekForward(nrWritten);
if(!ZNetPrivate::SendAll(peer->GetSocket(), peer->GetNetAddress(), data, (uint32_t)writer.GetOffset()))
{
printf("SendToPeer FAILED %u bytes\n", (uint32_t)writer.GetOffset());
return false;
}
printf("SendToPeer -> Sent %u bytes\n", (uint32_t)writer.GetOffset());
//Restart!
writer.Rewind();
ZNetPrivate::WriteWirePacketHeader(&writer);
unsent = false;
}
else //Done with this channel
{
if(nrWritten > 0 && !unsent)
{
unsent = true;
writer.SeekForward(nrWritten);
}
moreInChannel = false;
}
} while(moreInChannel);
}
//Any unsent data?
if(unsent)
{
//Then send it!
if(!ZNetPrivate::SendAll(peer->GetSocket(), peer->GetNetAddress(), data, (uint32_t)writer.GetOffset()))
{
printf("SendToPeer FAILED %u bytes\n", (uint32_t)writer.GetOffset());
return false;
}
printf("SendToPeer -> Sent %u bytes\n", (uint32_t)writer.GetOffset());
}
return true;
}