📄 trackernet.cpp
字号:
// advance in the buffer over the packet header
packet->Advance(pHeader->headerSize);
//!! check for fragmentation/reassembly
// build a receive message out of it
CReceiveMessage *msg = new CReceiveMessage(packet, encrypted);
msg->SetNetAddress(netAddress);
msg->SetSessionID(pHeader->sessionID);
// throw away bad messages
if (!msg->IsValid())
{
delete msg;
return;
}
WriteToLog("<- Received '%d' (is:%d reply:%d)\n", msg->GetMsgID(), pHeader->sequenceNumber, pHeader->sequenceReply);
// throw away any Ack packets
if (msg->GetMsgID() == TMSG_ACK)
{
delete msg;
return;
}
// add message to received list
int receivedIndex = m_ReceivedMsgs.AddToTail();
m_ReceivedMsgs[receivedIndex].message = msg;
if (pHeader->sequenceNumber)
{
// update the sequence, this may add more messages to the queue
UpdateSequence(target, targetIndex, pHeader->sequenceNumber);
}
}
//-----------------------------------------------------------------------------
// Purpose: Updates the current sequence info with the new packet
// scans the message window to see if future packets can be used
//-----------------------------------------------------------------------------
void CTrackerNET::UpdateSequence(NetworkTarget_t *target, int targetIndex, int seqNum)
{
// update sequence
target->incomingSequence = seqNum;
// check to see when we should send acknowledgement
if (!target->needAck)
{
target->ackTime = m_pThreads->GetTime() + ACK_DELAY;
target->needAck = true;
// move the target to the end of the ack list
m_TargetList.Unlink(targetIndex);
if (m_TargetList.IsValidIndex(m_iHighestAckTarget) && m_TargetList.IsInList(m_iHighestAckTarget))
{
m_TargetList.LinkAfter(m_iHighestAckTarget, targetIndex);
}
else
{
m_TargetList.LinkToHead(targetIndex);
}
// set the need high mark for the packets that need ack
m_iHighestAckTarget = targetIndex;
}
// check to see if packets in the window are now valid
while (target->m_MessageWindow.Count())
{
int index = target->m_MessageWindow.Head();
if (target->m_MessageWindow[index].sequenceNumber == target->incomingSequence + 1)
{
// this is the next message
// update sequence numbers
target->incomingSequence = target->m_MessageWindow[index].sequenceNumber;
// add message to received list
int receivedIndex = m_ReceivedMsgs.AddToTail();
m_ReceivedMsgs[receivedIndex].message = target->m_MessageWindow[index].message;
WriteToLog("-> Recv match in window (is: %d)\n", target->m_MessageWindow[index].sequenceNumber);
// remove message from window
target->m_MessageWindow.Remove(index);
}
else
{
// no more
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Deals with when we receive a reliable packet out of sequence
//-----------------------------------------------------------------------------
void CTrackerNET::HandleOutOfSequencePacket(IBinaryBuffer *packet, packet_header_t *pHeader, NetworkTarget_t *target, CNetAddress &netAddress, bool encrypted)
{
if (pHeader->sequenceNumber <= target->incomingSequence)
{
// mark that we may need to re-acknowledge their packets (since they could lose the acknowledgement)
target->incomingAcknowledged = (target->incomingSequence - 1);
// throw away the packet, since we've already acknowledged it
packet->Release();
return;
}
// it's a message from the future, maybe we should hold it
// if it's too far in the future, dump it
if (pHeader->sequenceNumber > (target->incomingSequence + MESSAGE_WINDOW))
{
packet->Release();
return;
}
// add to message window - we can use it later when we've got the missing packets from the sequence
// find where the packet should go in the list
// message should be in order of lowest sequence number to highest
int insertAfterIndex = target->m_MessageWindow.Tail();
while (target->m_MessageWindow.IsValidIndex(insertAfterIndex))
{
int incseq = target->m_MessageWindow[insertAfterIndex].sequenceNumber;
if (incseq < pHeader->sequenceNumber)
{
// this has a lower sequence number, so we should insert after it
break;
}
else if (incseq == pHeader->sequenceNumber)
{
// we already have this sequence number, so throw this duplicate away
packet->Release();
return;
}
insertAfterIndex = target->m_MessageWindow.Previous(insertAfterIndex);
}
// build into message
// advance in the buffer over the packet header
packet->Advance(pHeader->headerSize);
// build a receive message out of it
CReceiveMessage *msg = new CReceiveMessage(packet, encrypted);
msg->SetNetAddress(netAddress);
msg->SetSessionID(pHeader->sessionID);
// throw away bad messages
if (!msg->IsValid())
{
delete msg;
return;
}
// add it into the list
int newIndex = target->m_MessageWindow.InsertAfter(insertAfterIndex);
target->m_MessageWindow[newIndex].sequenceNumber = pHeader->sequenceNumber;
target->m_MessageWindow[newIndex].message = msg;
WriteToLog("-> Inserting recv into window (is: %d)\n", target->m_MessageWindow[newIndex].sequenceNumber);
}
//-----------------------------------------------------------------------------
// Purpose: Frees the message buffer
//-----------------------------------------------------------------------------
void CTrackerNET::ReleaseMessage(IReceiveMessage *msg)
{
msg->deleteThis();
}
//-----------------------------------------------------------------------------
// Purpose: Returns an interface to the networkings thread API
// Output : IThreads *
//-----------------------------------------------------------------------------
IThreads *CTrackerNET::GetThreadAPI( void )
{
return m_pThreads;
}
//-----------------------------------------------------------------------------
// Purpose: Creates an empty network message
//-----------------------------------------------------------------------------
ISendMessage *CTrackerNET::CreateMessage(int msgID)
{
return new CSendMessage(msgID, Create_BinaryBuffer(PACKET_DATA_MAX, PACKET_HEADER_SIZE));
}
//-----------------------------------------------------------------------------
// Purpose: Creates a preconstructed message
//-----------------------------------------------------------------------------
ISendMessage *CTrackerNET::CreateMessage(int msgID, void const *pBuf, int bufSize)
{
return new CSendMessage(msgID, pBuf, bufSize, Create_BinaryBuffer(PACKET_DATA_MAX, PACKET_HEADER_SIZE));
}
//-----------------------------------------------------------------------------
// Purpose: Creates a reply to the message
// Input : *msgName -
// *msgToReplyTo -
// Output : ISendMessage
//-----------------------------------------------------------------------------
ISendMessage *CTrackerNET::CreateReply(int msgID, IReceiveMessage *msgToReplyTo)
{
ISendMessage *reply = CreateMessage(msgID);
// setup reply
reply->SetNetAddress(msgToReplyTo->NetAddress());
reply->SetSessionID(msgToReplyTo->SessionID());
reply->SetEncrypted(msgToReplyTo->WasEncrypted());
return reply;
}
//-----------------------------------------------------------------------------
// Purpose: Converts a string to a net address
// Input : *stringAddress -
// Output : CNetAddress
//-----------------------------------------------------------------------------
CNetAddress CTrackerNET::GetNetAddress(const char *stringAddress)
{
CNetAddress addr;
int ip;
unsigned short port;
m_pSockets->StringToAddress( stringAddress, &ip, &port );
addr.SetIP( ip );
addr.SetPort( port );
return addr;
}
//-----------------------------------------------------------------------------
// Purpose: Returns port number
// Output : int
//-----------------------------------------------------------------------------
int CTrackerNET::GetPort()
{
return m_pSockets->GetListenPort();
}
//-----------------------------------------------------------------------------
// Purpose: Returns the address of the local machine
// Output : CNetAddress
//-----------------------------------------------------------------------------
CNetAddress CTrackerNET::GetLocalAddress()
{
return m_pSockets->GetLocalAddress();
}
//-----------------------------------------------------------------------------
// Purpose: Creates a target address, for sending messages to reliably
//-----------------------------------------------------------------------------
int CTrackerNET::FindTarget(CNetAddress &address, int targetID, int sequenceNumber)
{
bool createNew = true;
NetworkTarget_t *target = NULL;
int listIndex = 0;
// find the address in the map
int targetIndex = FindTargetIndexByAddress(address);
if (m_TargetMap.IsValidIndex(targetIndex))
{
listIndex = m_TargetMap[targetIndex].targetIndex;
target = &(m_TargetList[listIndex]);
// make sure the targetID's match, otherwise the connection has been invalidated
if (targetID == -1 || target->targetID == targetID)
{
return listIndex;
}
else
{
if (sequenceNumber == 1)
{
//!! reset the connection
WriteToLog("-> Connection Reset (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID);
}
else
{
WriteToLog("-> Connection Restart (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID);
}
createNew = false;
}
}
if (createNew)
{
// add a new connection to the end of the list
listIndex = m_TargetList.AddToTail();
target = &(m_TargetList[listIndex]);
target->needAck = false;
// add the target to the map
TargetMapItem_t newItem;
newItem.targetIndex = listIndex;
newItem.netAddress = address;
m_TargetMap.Insert(newItem);
// ensure that it's the first one in the sequence
if (sequenceNumber > 1)
{
WriteToLog("-> Contacted by unknown old connection (targetID:%d)\n", targetID);
}
}
// append to the end of the list
target->netAddress = address;
// initialize sequence numbers
target->outgoingSequence = 1;
target->outgoingAcknowledged = 0;
target->incomingSequence = 0;
target->incomingAcknowledged = 0;
if (sequenceNumber != -1)
{
// this is the first packet we've received, but from and old connection; so jump the correct sequence number
target->incomingSequence = sequenceNumber - 1;
}
// target->createTime = m_pThreads->GetTime();
if (targetID >= 0)
{
target->targetID = targetID;
}
else
{
target->targetID = RandomLong(1, MAX_RANDOM_RANGE);
}
if (createNew && targetID >= 0)
{
WriteToLog("Creating new target ID (%d)\n", target->targetID);
}
else
{
WriteToLog("Establishing connection to target ID (%d)\n", target->targetID);
}
return listIndex;
}
#ifdef _DEBUG
//-----------------------------------------------------------------------------
// Purpose: logs networking info to a text file
// Input : *str -
// ... -
//-----------------------------------------------------------------------------
void CTrackerNET::WriteToLog(const char *format, ...)
{
static bool firstThrough = true;
FILE *f;
if (firstThrough)
{
f = fopen("netlog.txt", "wt");
firstThrough = false;
}
else
{
f = fopen("netlog.txt", "at");
}
if (!f)
return;
char buf[2048];
va_list argList;
va_start(argList,format);
vsprintf(buf, format, argList);
va_end(argList);
float time = m_pThreads->GetTime();
fprintf(f, "(%.2f) %s", time, buf);
fclose(f);
}
#endif // _DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -