Initial commit
This commit is contained in:
156
ZNet/ZNetPeer.cpp
Normal file
156
ZNet/ZNetPeer.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
ZNetPeer.cpp
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 7/18/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
ZNet peer class, representing a remote host
|
||||
|
||||
License:
|
||||
|
||||
Copyright 2013, 762 Studios
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#include <ZNet/ZNetPeer.hpp>
|
||||
#include <ZNet/ZNetPacketChannel.hpp>
|
||||
#include <ZNet/ZNetHost.hpp>
|
||||
#include "ZNetPrivate.hpp"
|
||||
#include <SST/SST_OS.h>
|
||||
#include <new>
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZNetPeer::ZNetPeer()
|
||||
{
|
||||
lastValidIncoming = 0;
|
||||
lastOutgoingAck = 0;
|
||||
socketCopy = 0;
|
||||
channels = NULL;
|
||||
userdata = NULL;
|
||||
nrChannels = 0;
|
||||
ping = -1;
|
||||
state = STATE_UNCONNECTED;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool ZNetPeer::Initialize(ZNetHost* _host, const SST_NetAddress* newAddr, SST_Socket s, uint32_t _nrChannels)
|
||||
{
|
||||
SST_OS_DebugAssert(_host != NULL, "Host may not be NULL");
|
||||
SST_OS_DebugAssert(channels == NULL, "This should have been NULL; memory leak!");
|
||||
|
||||
channels = new(std::nothrow) ZNetPacketChannel[_nrChannels];
|
||||
if(channels == NULL)
|
||||
return false;
|
||||
|
||||
//Initialize channel ID (new[] doesn't allow non-default constructors)
|
||||
for(uint32_t i=0; i<_nrChannels; i++)
|
||||
{
|
||||
channels[i].SetChannelId(i);
|
||||
channels[i].SetHost(_host);
|
||||
}
|
||||
|
||||
//Store other properties
|
||||
memcpy(&addr, newAddr, sizeof(SST_NetAddress));
|
||||
nrChannels = _nrChannels;
|
||||
socketCopy = s;
|
||||
userdata = NULL;
|
||||
lastValidIncoming = SST_OS_GetMilliTime();
|
||||
state = STATE_HANDSHAKE;
|
||||
|
||||
//OK
|
||||
return true;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZNetPeer::Deinitialize()
|
||||
{
|
||||
for(uint32_t i=0; i<nrChannels; i++)
|
||||
channels[i].Deinitialize();
|
||||
|
||||
delete[] channels;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
ZNetPacketChannel* ZNetPeer::GetPacketChannel(uint32_t chId)
|
||||
{
|
||||
//Really, this is trivial, but I don't want asserts to be conditional on whether
|
||||
//the user of the API has enabled them vs how the library was built.
|
||||
SST_OS_DebugAssert(chId < nrChannels, "Invalid channel number");
|
||||
|
||||
return &channels[chId];
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZNetPeer::ProcessLocalAcks()
|
||||
{
|
||||
for(uint32_t i=0; i<nrChannels; i++)
|
||||
channels[i].ProcessLocalAcks();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void ZNetPeer::SendAcksForAllChannels()
|
||||
{
|
||||
uint8_t data[9000];
|
||||
uint32_t mtu = this->GetPacketChannel(ZNET_SYSCHANNEL)->GetHost()->GetMTU();
|
||||
bool unsent = true;
|
||||
|
||||
uint64_t now = SST_OS_GetMilliTime();
|
||||
|
||||
//TODO: maybe not the best idea...? it will start out by sending an ACK 0...kinda silly I guess
|
||||
if(lastOutgoingAck == 0 ||
|
||||
((ping > 0) && (now > lastOutgoingAck + (uint64_t)ping) && (now - lastOutgoingAck > 50)) ) //TODO: does a minimum ack latency of 50 make any sense? in the cases where ping is realllly low (e.g. <= 1msec) don't need to spam?
|
||||
{
|
||||
lastOutgoingAck = now;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
|
||||
ZBinaryBufferWriter writer(data, mtu, ZNET_BYTEORDER);
|
||||
|
||||
//Write the write header
|
||||
ZNetPrivate::WriteWirePacketHeader(&writer);
|
||||
|
||||
//Write an ACK point for each channel
|
||||
for(uint32_t i=0; i<nrChannels; i++)
|
||||
{
|
||||
ZNetPacketChannel* channel = GetPacketChannel(i);
|
||||
uint32_t remain = mtu - (uint32_t)writer.GetOffset();
|
||||
|
||||
//Can we fit another ack?
|
||||
if(remain > ZNetPrivate::WireSizeForSimpleCommand(ZNETCMD_ACK))
|
||||
{
|
||||
//TODO: flags??
|
||||
ZNetPrivate::WriteWireMessageHeader(&writer, i, 0, ZNETCMD_ACK, 0);
|
||||
|
||||
writer.WriteU16(channel->GetLocalAck());
|
||||
writer.WriteU16(channel->GetHighestSent());
|
||||
|
||||
unsent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZNetPrivate::SendAll(socketCopy, &addr, data, (uint32_t)writer.GetOffset());
|
||||
unsent = false;
|
||||
|
||||
//Restart
|
||||
writer.Rewind();
|
||||
ZNetPrivate::WriteWirePacketHeader(&writer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(unsent)
|
||||
ZNetPrivate::SendAll(socketCopy, &addr, data, (uint32_t)writer.GetOffset());
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
Reference in New Issue
Block a user