/// <summary> /// Receive Callback. Reads in incoming data, converting them to base packets. Base packets are sent to be parsed. If not enough data at the end to build a basepacket, move to the beginning and prepend. /// </summary> /// <param name="result"></param> private void ReceiveCallback(IAsyncResult result) { ZoneConnection conn = (ZoneConnection)result.AsyncState; //Check if disconnected if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0)) { mWorldConnection = null; Program.Log.Info("Disconnected from world server!"); } try { int bytesRead = conn.socket.EndReceive(result); bytesRead += conn.lastPartialSize; if (bytesRead >= 0) { int offset = 0; //Build packets until can no longer or out of data while (true) { SubPacket subPacket = SubPacket.CreatePacket(ref offset, conn.buffer, bytesRead); //If can't build packet, break, else process another if (subPacket == null) { break; } else { mProcessor.ProcessPacket(conn, subPacket); } } //Not all bytes consumed, transfer leftover to beginning if (offset < bytesRead) { Array.Copy(conn.buffer, offset, conn.buffer, 0, bytesRead - offset); } conn.lastPartialSize = bytesRead - offset; //Build any queued subpackets into basepackets and send conn.FlushQueuedSendPackets(); if (offset < bytesRead) { //Need offset since not all bytes consumed conn.socket.BeginReceive(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset), SocketFlags.None, new AsyncCallback(ReceiveCallback), conn); } else { //All bytes consumed, full buffer available conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn); } } else { mWorldConnection = null; Program.Log.Info("Disconnected from world server!"); } } catch (SocketException) { if (conn.socket != null) { mWorldConnection = null; Program.Log.Info("Disconnected from world server!"); } } }