⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trackernet.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		}

		// 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 + -