Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Reply
 
Thread Tools Display Modes
  #1  
Old 03-02-2005, 03:09 AM
Wiz
Dragon
 
Join Date: Feb 2002
Posts: 583
Default Improved NetCode

OK, first of all, this code will *not* work with the big netcode changes on EQlive. This is ONLY for people who run older-version servers.

That said, this rewrite to netcode will fix a lot of existing issues such as login bug, insta-LD bug, and in general is a lot more stable than the current netcode.

Simply do the following swaps in the below /common/ files.

EQNetwork.cpp

Swap out EQNetworkConnection::Process for:

Code:
#ifdef WIN32
void EQNetworkConnection::Process(SOCKET sock) {
#else
void EQNetworkConnection::Process(int sock) {
#endif
	if (!CheckNetActive())
		return;
	InQueue_Struct* iqs = 0;
	while ((iqs = InQueuePop())) {
		MakeEQPacket(iqs->app, iqs->ackreq);
		safe_delete(iqs->app);
		delete iqs;
	}
	CreateCombinedPacket();
	if (timeout_timer->Check()) {
		Close();
	}
	fraglist.CheckTimers();

	if (datarate_timer->Check(0))
	{
		datarate_timer->Start();
		dataflow -= datarate_tic;
		if (dataflow < 0)
			dataflow = 0;
	}

	EQNetworkPacket* pack;
	int32 size;
	uchar* data;
	sockaddr_in to;
	memset(&to, 0, sizeof(to));
	to.sin_family = AF_INET;
	to.sin_port = rPort;
	to.sin_addr.s_addr = rIP;

	LinkedListIterator<EQNetworkPacket*> iterator(SendQueue);
	iterator.Reset();
	if (iterator.MoreElements()) {
		keep_alive_timer->Start();
	}
	else if (IsFree()) {
		SetState(EQNC_Finished);
	}
#ifdef PRIORITYTEST
	if(DataQueueFull() && GetState() == EQNC_Active && queue_check_timer->Check())
	{
		PacketPriority();
	}
#endif

	int nas=0, ka=0;
	//This sends out "pure" packets that verify to the client that it and the server is still on talking terms
	if ( (GetState() == EQNC_Active) && ((nas=no_ack_sent_timer->Check(0)) || (ka=keep_alive_timer->Check(0))) )
	{
		APPLAYER outapp;
		outapp.opcode = 0xFFFF;
		outapp.priority = 5;
		MakeEQPacket(&outapp, ka);
	}

	iterator.Reset();
	while (iterator.MoreElements() && (!DataQueueFull())) {
		pack = iterator.GetData();
		if (GetState() != EQNC_Active || (pack->SentCount == 0 && Timer::GetCurrentTime() >= (pack->LastSent+1000)))
		{
			cout<<""; //Magic cout. This tiny artifical pause will keep the packet process from sending out packets too rapidly and getting them discarded in the process. Especially important during log in/zone processes.

			pack->SentCount = 1; //A packet that's been sent shouldn't be resent as long as the connection is moving along smoothly, this just inflates packetrate and causes trouble.

			if (GetState() == EQNC_Active && pack->dwARQ == arsp_response + 10) //This code checks if 10 packets have been sent since last ARSP ("we got this packet yo") response from client, and if so, tags those ten packets that haven't been verifiably recieved for a resend. Should probably be condensed into a function for cleanliness :P
			{
				LinkedListIterator<EQNetworkPacket*> iterator2(SendQueue);
				iterator2.Reset();
				while (iterator2.MoreElements())
				{
					EQNetworkPacket* pack2 = iterator2.GetData();
					if (pack2->dwARQ == pack->dwARQ)
						break;
					iterator2.Advance();
				}
			}

			if (pack->HDR.a2_Closing && pack->HDR.a6_Closing) //Closing bits. Terminates the connection properly.
			{
				size = pack->ReturnPacket(&data);
				sendto(sock, (char*) data, size, 0, (sockaddr*) &to, sizeof(to));
				delete[] data;

				iterator.RemoveCurrent();
				continue;
			}
			else if (GetState() != EQNC_Active) { //Nothing but closing bits to be sent after a connection close. It's not recieved, so why waste processing power?
				iterator.RemoveCurrent();
				continue;
			}
			else //SendOut
			{
				size = pack->ReturnPacket(&data);
				sendto(sock, (char*) data, size, 0, (sockaddr*) &to, sizeof(to));
				delete[] data;

				if (!pack->HDR.a1_ARQ) { //Wtf is this for?
					iterator.RemoveCurrent();
					continue;
				}

				dataflow += size;
				pack->LastSent = Timer::GetCurrentTime();
			}
		}
		iterator.Advance();
		if (!iterator.MoreElements()) //This terminates the process properly after a closed connection has cleaned out the queue.
		{
			if (GetState() != EQNC_Active)
			{
				SetState(EQNC_Error);
			}
		}
	}
}
Add this line to the IncomingARSP() function, just below iterator.Reset();

Code:
arsp_response = arsp;
Add this line to EQNetworkConnection::EQNetworkConnection

Code:
arsp_response = 0;
Add this line under the private part of the EQNetworkConnection class in EQNetwork.h

Code:
	int16	arsp_response;
There, you're done. Pat yourself on the back and feel free to feedback any issues.
Reply With Quote
  #2  
Old 03-02-2005, 07:56 AM
mangoo
Items Master
 
Join Date: Apr 2003
Posts: 293
Default

Very nice Wiz, thanks =).
__________________
Reply With Quote
  #3  
Old 03-04-2005, 06:56 AM
fathernitwit
Developer
 
Join Date: Jul 2004
Posts: 773
Default

Hey wiz,

in this code:
Code:
			if (GetState() == EQNC_Active && pack->dwARQ == arsp_response + 10) //This code checks if 10 packets have been sent since last ARSP ("we got this packet yo") response from client, and if so, tags those ten packets that haven't been verifiably recieved for a resend. Should probably be condensed into a function for cleanliness :P
			{
				LinkedListIterator<EQNetworkPacket*> iterator2(SendQueue);
				iterator2.Reset();
				while (iterator2.MoreElements())
				{
					EQNetworkPacket* pack2 = iterator2.GetData();
					if (pack2->dwARQ == pack->dwARQ)
						break;
					iterator2.Advance();
				}
			}
I imagine that you wanted to set SentCount to 0 so it would be resent.. but you dont, so I imagine packets will never get resent. In fact, this loop does nothing at all.
Reply With Quote
  #4  
Old 03-04-2005, 07:23 AM
Wiz
Dragon
 
Join Date: Feb 2002
Posts: 583
Default

Quote:
Originally Posted by fathernitwit
Hey wiz,

in this code:
Code:
			if (GetState() == EQNC_Active && pack->dwARQ == arsp_response + 10) //This code checks if 10 packets have been sent since last ARSP ("we got this packet yo") response from client, and if so, tags those ten packets that haven't been verifiably recieved for a resend. Should probably be condensed into a function for cleanliness :P
			{
				LinkedListIterator<EQNetworkPacket*> iterator2(SendQueue);
				iterator2.Reset();
				while (iterator2.MoreElements())
				{
					EQNetworkPacket* pack2 = iterator2.GetData();
					if (pack2->dwARQ == pack->dwARQ)
						break;
					iterator2.Advance();
				}
			}
I imagine that you wanted to set SentCount to 0 so it would be resent.. but you dont, so I imagine packets will never get resent. In fact, this loop does nothing at all.
... strange. It most certainly does something in my code, I must have omitted it somehow doesn't in the pasted code. Just throw in a pack2->SentCount = 0 there.
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 09:29 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3