private void OnDataReceive(IAsyncResult result)
    {
        if (connection == null)
            return;

        lock (this)
        {
            int bytesRead = connection.EndReceive(result);

            if (bytesRead > 0)
            {
                this.circStream.Write(this.receiveBuffer, 0, bytesRead);

                byte[] buffer = new byte[ this.circStream.DataAvailable ];
                this.circStream.Read(buffer, 0, buffer.Length);

                // if we have enough to read in the header
                if (buffer.Length >= Message.HeaderLength)
                {
                    int bytesLeft = buffer.Length;
                    int arrayPosition = 0;
                    Message.MessageHeader header = new Message.MessageHeader();

                    do
                    {
                        // read in the header
                        if (bytesLeft >= Message.HeaderLength)
                        {
                            header.Set(buffer, arrayPosition);
                            bytesLeft -= Message.HeaderLength;
                        }
                        else
                        {
                            AddToLeftOvers(buffer, arrayPosition, bytesLeft);
                            break;
                        }

                        // if we have enough to read in the rest of the message,
                        // copy it into a new array and dispatch the message
                        if (bytesLeft >= header.Length)
                        {
                            byte[] message = new byte[ header.Length + Message.HeaderLength ];
                            Array.Copy(buffer, arrayPosition, message, 0, message.Length);
                            this.DispatchMessage(message);
                            bytesLeft -= header.Length;
                        }
                            // otherwise, we dont have enough data to contruct a full message.
                            // add the header and whatever else to the data "left overs" and go.
                        else
                        {
                            AddToLeftOvers(buffer, arrayPosition, bytesLeft + Message.HeaderLength);
                            break;
                        }

                        arrayPosition += Message.HeaderLength + header.Length;
                    }
                    while (bytesLeft > 0);
                }
                else
                {
                    // else we dont have enough data to even construct the message header.
                    // add it to the leftovers and forget about it.
                    AddToLeftOvers(this.receiveBuffer, 0, bytesRead);
                }

                try
                {
                    // restart async call
                    this.connection.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, new AsyncCallback(OnDataReceive), null);
                }
                catch
                {
                    this.onDisconnect(this, null, null);
                }
            }
            else if (!ExpectingDisconnection)
            {
                this.onDisconnect(this, null, null);
            }
        }
    }
    private void OnDataReceive(IAsyncResult result)
    {
        if (connection == null)
        {
            return;
        }

        lock (this)
        {
            int bytesRead = connection.EndReceive(result);

            if (bytesRead > 0)
            {
                this.circStream.Write(this.receiveBuffer, 0, bytesRead);

                byte[] buffer = new byte[this.circStream.DataAvailable];
                this.circStream.Read(buffer, 0, buffer.Length);

                // if we have enough to read in the header
                if (buffer.Length >= Message.HeaderLength)
                {
                    int bytesLeft                = buffer.Length;
                    int arrayPosition            = 0;
                    Message.MessageHeader header = new Message.MessageHeader();

                    do
                    {
                        // read in the header
                        if (bytesLeft >= Message.HeaderLength)
                        {
                            header.Set(buffer, arrayPosition);
                            bytesLeft -= Message.HeaderLength;
                        }
                        else
                        {
                            AddToLeftOvers(buffer, arrayPosition, bytesLeft);
                            break;
                        }

                        // if we have enough to read in the rest of the message,
                        // copy it into a new array and dispatch the message
                        if (bytesLeft >= header.Length)
                        {
                            byte[] message = new byte[header.Length + Message.HeaderLength];
                            Array.Copy(buffer, arrayPosition, message, 0, message.Length);
                            this.DispatchMessage(message);
                            bytesLeft -= header.Length;
                        }
                        // otherwise, we dont have enough data to contruct a full message.
                        // add the header and whatever else to the data "left overs" and go.
                        else
                        {
                            AddToLeftOvers(buffer, arrayPosition, bytesLeft + Message.HeaderLength);
                            break;
                        }

                        arrayPosition += Message.HeaderLength + header.Length;
                    }while (bytesLeft > 0);
                }
                else
                {
                    // else we dont have enough data to even construct the message header.
                    // add it to the leftovers and forget about it.
                    AddToLeftOvers(this.receiveBuffer, 0, bytesRead);
                }

                try
                {
                    // restart async call
                    this.connection.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, new AsyncCallback(OnDataReceive), null);
                }
                catch
                {
                    this.onDisconnect(this, null, null);
                }
            }
            else if (!ExpectingDisconnection)
            {
                this.onDisconnect(this, null, null);
            }
        }
    }