BeginSend vs Conquer

02/13/2013 13:59 Super Aids#1
Can BeginSend really be a devil when working with conquer?

Just wondering since I am having random disconnections at times when using BeginSend.

This is the debug error from the client:
Quote:
ReleaseVer:F:\CQ2ClientRelease-42.0.1 MsgVer:124, FileTime:2011/07/21,16:24==ERROR: Receive package len[20820] > _MAX_MSGSIZE
As you can see it receives a packet on the size of 20k rofl.

However if I use a synchronous send then it works fine. Is asynchronous sending really a problem with Conquer?
02/13/2013 15:29 CptSky#2
Quote:
Originally Posted by Super Aids View Post
Can BeginSend really be a devil when working with conquer?

Just wondering since I am having random disconnections at times when using BeginSend.

This is the debug error from the client:


As you can see it receives a packet on the size of 20k rofl.

However if I use a synchronous send then it works fine. Is asynchronous sending really a problem with Conquer?
Maybe you can change the Socket.SendBufferSize so it won't send a 20k block ? I've never had the problem...
02/13/2013 16:11 Super Aids#3
My buffersize is set to max 1024.

Also another thing I've found strange which makes me think it's my mistake.
It only happens with drop (as far as I'm aware.)
My drop handler:
Code:
using System;

namespace ProjectX_V3_Game.Packets.Item
{
	/// <summary>
	/// Subtype: 37
	/// </summary>
	public class Drop
	{
		/// <summary>
		/// Handling the Drop action from the ItemPacket.
		/// </summary>
		/// <param name="client">The client.</param>
		/// <param name="item">The item packet.</param>
		public static void Handle(Entities.GameClient client, ItemPacket packet)
		{
			if (client.Inventory.ContainsByUID(packet.UID))
			{
				Maps.MapPoint Location = client.Map.CreateAvailableLocation<Data.GroundItem>(client.X, client.Y, 3);
				if (Location != null)
				{
					Data.ItemInfo dropitem = client.Inventory.RemoveItemByUID(packet.UID);
					
					if (dropitem != null)
					{
						Data.GroundItem ground = new Data.GroundItem(dropitem);
						ground.DropType = Enums.DropItemType.Item;
						ground.X = Location.X;
						ground.Y = Location.Y;
						Location.Map.EnterMap(ground);
						ground.TaskID = ProjectX_V3_Lib.Threading.DelayedTask.StartDelayedTask(
							() => {
								Location.Map.LeaveMap(ground);
								ground.Screen.ClearScreen();
							},
							Core.TimeIntervals.DroppedItemRemove);
						ground.Screen.UpdateScreen(null);
					}
				}
			}
		}
	}
}
Nothing that really can disconnect there. There is none of those calls that disconnects.
Since the issue seem to be a buffer issue then this is how I am sending my packets.
Code:
		/// <summary>
		/// Sends data to the client.
		/// </summary>
		/// <param name="buffer">The buffer to send.</param>
		public void Send(DataPacket buffer)
		{
			bool PacketSend = false;

			try
			{
				if (buffer.BufferLength > 1024)
				{
					Disconnect("Too big packet...");
					return;
				}
				
				byte[] Buffer = buffer.Copy();
				
				if (Crypto != null)
				{
					lock (Crypto)
						Crypto.Encrypt(Buffer);
				}
				
				if (PacketSend = Monitor.TryEnter(this, 50))
				{
					if (clientSocket.Connected)
					{
						 clientSocket.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(Send_Callback), Buffer);
					}
					else
						Disconnect("Not Connected.");
				}
			}
			finally
			{
				if (!PacketSend)
					Disconnect("Lag."); // lag
				else
					Monitor.Exit(this);
			}
		}

		/// <summary>
		/// The callback from Send().
		/// </summary>
		/// <param name="asyncResult">The async result.</param>
		private void Send_Callback(IAsyncResult asyncResult)
		{
			try
			{
				int send = clientSocket.EndSend(asyncResult);
				if (send < 4)
					Disconnect("Did not send proper packet header.");
				
				if (asyncResult.AsyncState != null && send > 0)
				{
					Array.Clear(((byte[])asyncResult.AsyncState), 0, send);
				}
			}
			catch
			{
			}
		}
As you can see I am not allowing any packets above the size of 1024 bytes to be send.

Although what I should look for is not things that will let the server disconnect the client as it's the client that disconnects.

I'm totally lost whether it's my mistake or a mistake with the conquer client.

#edit noticed you said Socket.SendBufferSize. Will try now.

#edit 2 setting the sendbuffersize didn't work either. Still getting the error.
Quote:
ReleaseVer:F:\CQ2ClientRelease-42.0.1 MsgVer:124, FileTime:2011/07/21,16:24==ERROR: Receive package len[20820] > _MAX_MSGSIZE at ..\3DRole/Network/socket.h, 504 -- Wed Feb 13 16:54:38 2013
[R,cq2clientrelease-42.0.1,5517,English][Win6.2/47M/3658M/1633M/55][18791s/19898s/0s/0s/20050s/20053s/20053s][51814ms/2449=21.16ms] -- Wed Feb 13 16:54:38 2013
#edit 3 also found out it does happen with regular send as well, so the problem doesn't exactly lie in BeginSend...
02/13/2013 17:43 nTL3fTy#4
Looks like an encryption/decryption problem to me.
02/13/2013 17:47 Super Aids#5
However if it was a crypto problem wouldn't it happen on random packets and not on the drop packet to be specific?

Tried checking the buffer size and it clearly wasn't the problem.
[Only registered and activated users can see links. Click Here To Register...]

Also it should be noticed it is not the one who drops the items that disconnects, but the ones around. Although the one who drops the item does not send or does anything regarding the drop. Only thing that happens is the item being removed from the inventory. The way the ground item is spawned is through its screenhandler which obviously does not have an "item owner".

Perhaps I am blind? If anyone can spot my error they're godlike.

THOUGH THIS WAS FIXING IT: Seems like it's fixed now thanks to Lat.

Was a locking problem after all, so perhaps it was a crypto problem xD

HOWEVER:
Was not the problem c_c
02/14/2013 16:49 KraHen#6
See if the size in your packet header is always correct, it could be the client checking the header and automatically assuming that it`s going to get a ton of data because of a typo.
02/14/2013 18:54 Super Aids#7
Virtual size is the size written in the packet (referring to the screenshot)

Oh and I though this was fixed by the help I had by Lat. Although it wasn't. I'm totally stuck on what the issue could be.

Even had my send method changed to lock a specific object on send from after the buffer copy and till the end (removing all other locks in the method) and it obviously didn't help either.

Could've been a race condition with BeginSend, although with just Send it also happens.

If it was a cryptography problem why only the grounditempacket (haven't experienced it from anything else.)

The drop handler does not disconnect and I do not disconnect anywhere in the actual source that could be just the slightest related to it and the dc is not from the server either, but from the client (Hence the error), so where the exactly problem happens mind fucks me.

I appreciate all the help so far though :)
02/15/2013 08:29 { Angelius }#8
If you setup a temp socket to listen to the game port and connect to it instead of connecting to the client itself and the try to receive just like the client wold you wold understand what went wrong...

And to make the task easier for you download olly/CE and attach it to a running client then break point at 0x6D78C9...

Assume that the packet length which is a ushort value = 32
In hex mode: 0x0020
PHP Code:
CPU Disasm
006D78C9  
|MOVZX EDI,BYTE PTR DS:[ESI+ECX+200C]//Moves the first byte of the length value into EDI: 0x00
006D78D1  |SHL EDI,8//Left Shift EDI by 8
006D78D4  |MOVZX EAX,BYTE PTR DS:[ESI+EAX+200C]//Moves the second byte of the length into EAX: 0x20
006D78DC  |ADD EDI,EAX//EDI += EAX
006D78DE  |MOV DWORD PTR SS:[LOCAL.2070],EDI//store it somewhere on the stack we don't care 
006D78E1  |LEA EAX,[EDI-1]//EAX = EDI -1
006D78E4  |CMP EAX,3FF//compare EAX against 0x3FF
006D78E9  |JA SHORT 006D7900//If EAX greater then 1023 throw a Receive package len error 
Now if you still don't understand whats going on or what i am talking about.. then let me sum it up for you..

One of the packets that are being sent to the client has a length of lets say 50 but the actual array of that packet is less then 50 bytes..

IE:
byte[] Array = new byte[40];
Array[0] = 50;
Client.Send(Array);

Now when the client gets the packet it'll be like ummm i can't read 50 bytes of that buffer because if i do i will end up reading from the next packet or of an incorrect memory address so i better not process that packet.. and there for you will be disconnected and greeted by that error message..
02/16/2013 05:45 Super Aids#9
Well after 3 days it's finally fixed. Well I assume since I have got no disconnections for the past 15 mins and it was used to happen like 1-3 mins within starting to drop items.

Thanks a lot everyone!

And I have no idea what exactly fixed it, just went through my whole source and changed some code here and there xD

Now I think I deserve some sleep, because I've only had 1 or 2 hours last days :D

Goodnight all!