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

📄 trackernet.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// 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 + -