146 lines
3.4 KiB
C++
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;
|
|
}
|