📄 trackernet.cpp
字号:
}
// check to see if we should resend this packet
msg.resendAttempt++;
if (msg.resendAttempt < MAX_SEND_ATTEMPTS)
{
// only send the message if it's in the message send window
if (msg.sequenceNumber < target.outgoingAcknowledged + MESSAGE_WINDOW)
{
WriteToLog("-> Resending '%d' (os:%d > %d) (%s)\n", msg.message->GetMsgID(), msg.sequenceNumber, target.outgoingAcknowledged, target.netAddress.ToStaticString());
// send that it again
InternalSendMessage(msg.message, &target, msg.sequenceNumber);
}
else
{
// hold back on sending the message
WriteToLog("-> Holding back resend '%d' (os:%d > %d) (%s)\n", msg.message->GetMsgID(), msg.sequenceNumber, target.outgoingAcknowledged, target.netAddress.ToStaticString());
msg.resendAttempt--;
}
// set the time before retrying again
// send times: 0.0 1.5 1.5 1.5 (1.5) = 6.0 second timeout, 4 packets sent
msg.resendTime = time + RESEND_TIME;
// move it to the end of the list
m_ReliableMessages.Unlink(index);
m_ReliableMessages.LinkToTail(index);
// next packet
continue;
}
// target has failed to respond, remove the target and respond with a failed message
WriteToLog("Could not deliver packet: %d (os:%d)\n", msg.message->GetMsgID(), msg.sequenceNumber);
// send back a send failure message to the app
// convert the send message into a receive message
CSendMessage *sendMsg = dynamic_cast<CSendMessage *>(msg.message);
if (sendMsg)
{
IBinaryBuffer *buf = sendMsg->GetBuffer();
buf->SetPosition(buf->GetBufferData());
buf->Advance(buf->GetReservedSize());
CReceiveMessage *failMsg = new CReceiveMessage(buf, true);
if (failMsg->IsValid())
{
failMsg->SetFailed();
failMsg->SetNetAddress(target.netAddress);
failMsg->SetSessionID(sendMsg->SessionID());
int newIndex = m_FailedMsgs.AddToTail();
FailedMsg_t &fmsg = m_FailedMsgs[newIndex];
fmsg.message = failMsg;
}
else
{
delete failMsg;
}
}
// target not responding, so cancel the connection
// remove from target map
int mapindex = FindTargetIndexByAddress(target.netAddress);
assert(m_TargetMap.IsValidIndex(mapindex));
m_TargetMap.RemoveAt(mapindex);
// remove target from list
m_TargetList.Remove(msg.networkTargetHandle);
// message will automatically be delete since it's target is gone
}
}
//-----------------------------------------------------------------------------
// Purpose: finds a network target by net address
//-----------------------------------------------------------------------------
int CTrackerNET::FindTargetIndexByAddress(CNetAddress &addr)
{
TargetMapItem_t searchItem;
searchItem.netAddress = addr;
return m_TargetMap.Find(searchItem);
}
//-----------------------------------------------------------------------------
// Purpose: returns the number of buffers current in the input and output queues
//-----------------------------------------------------------------------------
int CTrackerNET::BuffersInQueue()
{
return m_pThreadedSocket->BuffersInQueue();
}
//-----------------------------------------------------------------------------
// Purpose: returns the peak number of buffers in the queues
//-----------------------------------------------------------------------------
int CTrackerNET::PeakBuffersInQueue()
{
return m_pThreadedSocket->PeakBuffersInQueue();
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int CTrackerNET::BytesSent()
{
return m_pThreadedSocket->BytesSent();
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int CTrackerNET::BytesReceived()
{
return m_pThreadedSocket->BytesReceived();
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int CTrackerNET::BytesSentPerSecond()
{
return m_pThreadedSocket->BytesSentPerSecond();
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int CTrackerNET::BytesReceivedPerSecond()
{
return m_pThreadedSocket->BytesReceivedPerSecond();
}
//-----------------------------------------------------------------------------
// Purpose: sets the windows event to signal when we get a new message
//-----------------------------------------------------------------------------
void CTrackerNET::SetWindowsEvent(unsigned long event)
{
m_hEvent = event;
// set it in networking layer
m_pThreadedSocket->SetWindowsEvent(event);
}
//-----------------------------------------------------------------------------
// Purpose: Sends a message to a target address
//-----------------------------------------------------------------------------
void CTrackerNET::SendMessage(ISendMessage *pMsg, Reliability_e state)
{
pMsg->SetReliable(state == NET_RELIABLE);
if (state == NET_RELIABLE && (pMsg->NetAddress().IP() == 0 || pMsg->NetAddress().Port() == 0))
return;
assert(state != NET_RELIABLE || pMsg->NetAddress().IP() > 0);
assert(state != NET_RELIABLE || pMsg->NetAddress().Port() > 0);
CNetAddress address;
int sequenceNumber = 0;
int targetIndex = -1;
NetworkTarget_t *target = NULL;
if (state != NET_BROADCAST)
{
targetIndex = FindTarget(pMsg->NetAddress());
target = &m_TargetList[targetIndex];
// mark the activity time
// target->activityTime = m_pThreads->GetTime();
// setup the message with the target info
address = target->netAddress;
}
if (pMsg->IsReliable())
{
// set and increment the sequence number
if (target)
{
sequenceNumber = target->outgoingSequence++;
}
// save off the message
int newIndex = m_ReliableMessages.AddToTail();
SentMessage_t &msg = m_ReliableMessages[newIndex];
msg.sequenceNumber = sequenceNumber;
msg.message = pMsg;
msg.resendAttempt = 0;
msg.resendTime = m_pThreads->GetTime() + RESEND_TIME;
msg.networkTargetHandle = targetIndex;
msg.networkTargetID = target->targetID;
// make sure we're in the message window before sending, other just hold until the resend attempt
if (msg.sequenceNumber < target->outgoingAcknowledged + MESSAGE_WINDOW)
{
WriteToLog("-> Sending '%d' (os:%d) (%s)\n", pMsg->GetMsgID(), sequenceNumber, target->netAddress.ToStaticString());
}
else
{
// don't send yet
WriteToLog("-> Holding for send '%d' (os:%d) (%s)\n", pMsg->GetMsgID(), sequenceNumber, target->netAddress.ToStaticString());
return;
}
}
else if (state == NET_BROADCAST)
{
WriteToLog("-> Sending '%d' (BROADCAST)\n", pMsg->GetMsgID(), sequenceNumber);
}
else
{
WriteToLog("-> Sending '%d' (UNRELIABLE)\n", pMsg->GetMsgID(), sequenceNumber);
}
InternalSendMessage(pMsg, target, sequenceNumber);
}
//-----------------------------------------------------------------------------
// Purpose: Internal message send
//-----------------------------------------------------------------------------
void CTrackerNET::InternalSendMessage(ISendMessage *pMsg, NetworkTarget_t *target, int sequenceNumber)
{
// ugly cast
CSendMessage *sendMsg = dynamic_cast<CSendMessage *>(pMsg);
if (target)
{
// reply with the last received sequence number
int sequenceReply = target->incomingSequence;
// mark as have acknowledged this sequence
target->incomingAcknowledged = target->incomingSequence;
// send it
m_pThreadedSocket->SendMessage(sendMsg->GetBuffer(), target->netAddress, sendMsg->SessionID(), target->targetID, sequenceNumber, sequenceReply, pMsg->IsEncrypted());
}
else
{
// no target, so it must be a broadcast msg
m_pThreadedSocket->BroadcastMessage(sendMsg->GetBuffer(), pMsg->NetAddress().Port());
}
// delete the unreliable messages since we don't have the stored in the resend buffer
if (!pMsg->IsReliable())
{
delete sendMsg;
}
}
//-----------------------------------------------------------------------------
// Purpose: Checks for any waiting messages
//-----------------------------------------------------------------------------
IReceiveMessage *CTrackerNET::GetIncomingData()
{
// check the receive list
if (m_ReceivedMsgs.Count())
{
int head = m_ReceivedMsgs.Head();
IReceiveMessage *msg = m_ReceivedMsgs[head].message;
m_ReceivedMsgs.Remove(head);
return msg;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Gets any failed sends - returns any packet that could not be delivered
//-----------------------------------------------------------------------------
IReceiveMessage *CTrackerNET::GetFailedMessage()
{
if (m_FailedMsgs.Count())
{
// pop the failed message from the front of the queue and return it
FailedMsg_t &msg = m_FailedMsgs[m_FailedMsgs.Head()];
IReceiveMessage *recvMsg = msg.message;
m_FailedMsgs.Remove(m_FailedMsgs.Head());
return recvMsg;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Creates a buffer
// Output : IBinaryBuffer
//-----------------------------------------------------------------------------
IBinaryBuffer *CTrackerNET::CreateRawMessage()
{
return Create_BinaryBuffer(PACKET_DATA_MAX, 0);
}
//-----------------------------------------------------------------------------
// Purpose: Sends a raw data buffer
// Input : *message -
// &address -
//-----------------------------------------------------------------------------
void CTrackerNET::SendRawMessage(IBinaryBuffer *message, CNetAddress &address)
{
m_pThreadedSocket->SendRawMessage(message, address);
}
//-----------------------------------------------------------------------------
// Purpose: gets any info that has been received from out-of-band engine packets
//-----------------------------------------------------------------------------
IBinaryBuffer *CTrackerNET::GetIncomingRawData(CNetAddress &address)
{
IBinaryBuffer *recvBuf = NULL;
if (m_pThreadedSocket->GetNewNonTrackerMessage(&recvBuf, &address))
{
return recvBuf;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Constructs a network message out of the packet
//-----------------------------------------------------------------------------
void CTrackerNET::ParseIncomingPacket(IBinaryBuffer *packet, CNetAddress netAddress, bool encrypted)
{
// construct a ReceiveMessage from it
// parse out the packet header
void *bufData = packet->GetBufferData();
packet_header_t *pHeader = (packet_header_t *)bufData;
// check the protocol version
if (pHeader->protocolNumber != PROTOCOL_VERSION)
{
// just throw away the packet if protocol is bad
WriteToLog("!! Packet with invalid protocol - dropped\n");
packet->Release();
return;
}
// check the packet header size
if (pHeader->headerSize != PACKET_HEADER_SIZE)
{
// just throw away the packet if protocol is bad
packet->Release();
WriteToLog("!! Malformed packet - dropped\n");
return;
}
// match to a target
int targetIndex = FindTarget(netAddress, pHeader->targetID, pHeader->sequenceNumber);
NetworkTarget_t *target = &m_TargetList[targetIndex];
// mark the activity time
// target->activityTime = m_pThreads->GetTime();
// update received
if (pHeader->sequenceReply)
{
if (pHeader->sequenceReply > target->outgoingAcknowledged)
{
WriteToLog("<- Sequence acknowledged (%d in target %d)\n", target->outgoingAcknowledged, target->targetID);
// this affects which packets we have to resend
target->outgoingAcknowledged = pHeader->sequenceReply;
}
if (pHeader->sequenceReply > target->outgoingSequence)
{
// we've got a mismatch in the network stream; the Client is acknowledging a packet we haven't sent yet
// just bump our outgoing up to match
WriteToLog("<- Mismatched sequence numbers; increasing local outgoingSequence to match (%d -> %d)\n", target->outgoingSequence, pHeader->sequenceReply);
target->outgoingSequence = pHeader->sequenceReply + 1;
}
}
if (pHeader->sequenceNumber)
{
// check it against the incoming sequence number
// if it's not the next packet in the sequence, just throw it away
if (pHeader->sequenceNumber != target->incomingSequence + 1 && (target->incomingSequence > 0))
{
HandleOutOfSequencePacket(packet, pHeader, target, netAddress, encrypted);
return;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -