void ReceiveCallback(IAsyncResult ar)
        {
            PacketState state = null;

            try
            {
                int bytesreceived = rconSocket.EndReceive(ar);
                state             = (PacketState)ar.AsyncState;
                state.BytesSoFar += bytesreceived;

#if DEBUG
                Console.WriteLine("Receive Callback. Packet: {0} First packet: {1}, Bytes so far: {2}",
                                  state.PacketCount, state.IsPacketLength, state.BytesSoFar);
#endif

                // Spin the processing of this data off into another thread.
                ThreadPool.QueueUserWorkItem((object pool_state) =>
                {
                    ProcessIncomingData(state);
                });
            }
            catch (SocketException se)
            {
                OnError(MessageCode.ConnectionClosed, se.Message);
                Disconnect();
            }
            catch (ObjectDisposedException ode)
            {
                OnError(MessageCode.AlreadyDisposed, ode.Message);
            }
        }
        void GetNewPacketFromServer()
        {
            // Prepare the state information for a new packet.
            PacketState state = new PacketState();

            state.IsPacketLength = true;
            state.Data           = new byte[4];
            state.PacketCount    = PacketCount;
            PacketCount++;

            // If we're debugging, log the packetstate.
            // Can use this to trace the packets later.
            #if DEBUG
            TempPackets.Add(state);
            #endif

            try
            {
                rconSocket.BeginReceive(state.Data, 0, 4, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
            }
            catch (SocketException se)
            {
                OnError(MessageCode.ConnectionFailed, se.Message);
                Disconnect();
            }
        }
 void StartToReceive(PacketState state)
 {
     try
     {
         rconSocket.BeginReceive(state.Data, state.BytesSoFar, state.PacketLength - state.BytesSoFar, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
     }
     catch (SocketException se)
     {
         OnError(MessageCode.ConnectionClosed, se.Message);
         Disconnect();
     }
 }
        void ProcessIncomingData(PacketState state)
        {
            if (state.IsPacketLength)
            {
                // First 4 bytes of a new packet.
                state.PacketLength = BitConverter.ToInt32(state.Data, 0);

                state.IsPacketLength = false;
                state.BytesSoFar     = 0;
                state.Data           = new byte[state.PacketLength];

                if (state.PacketLength > 0)
                {
                    StartToReceive(state);
                }
                else
                {
                    OnError(MessageCode.EmptyPacket, null);
                    // Treat as a fatal error?
                    Disconnect();
                }
            }
            else
            {
                // This is a fragment of a complete packet.
                if (state.BytesSoFar < state.PacketLength)
                {
                    // We don't have all the data, ask the network for the rest.
                    StartToReceive(state);
                }
                else
                {
                    // This is the whole packet, so we can go ahead and pack it up into a structure and then punt it upstairs.
                    #if DEBUG
                    Console.WriteLine("Complete packet.");
                    #endif

                    RCONPacket ReturnedPacket = new RCONPacket();
                    ReturnedPacket.ParseFromBytes(state.Data, this);

                    ThreadPool.QueueUserWorkItem((object pool_state) =>
                    {
                        ProcessResponse(ReturnedPacket);
                    });

                    // Wait for new packet.
                    GetNewPacketFromServer();
                }
            }
        }