private void OnReadCompleted(object sender, SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred == 0 ||
                e.SocketError != SocketError.Success)
            {
                HandleDisconnect(e.SocketError);
                return;
            }

            if (BufferPreProcessor != null)
            {
                var read = BufferPreProcessor(this, _readArgsWrapper);
                if (read > 0)
                {
                    var newCount  = _readArgsWrapper.BytesTransferred - read;
                    var newOffset = _readArgsWrapper.Offset + read;
                    _readArgsWrapper.SetBuffer(newOffset, newCount);
                    _readArgsWrapper.BytesTransferred -= read;
                }
            }

            try {
                // pre processor can have read everything
                if (_readArgsWrapper.BytesTransferred > 0)
                {
                    _decoder.ProcessReadBytes(_readArgsWrapper);
                }
            }
            catch (Exception exception) {
                Console.WriteLine(exception);
                ChannelFailure(this, exception);

                // event handler closed the socket.
                if (!_socket.Connected)
                {
                    return;
                }
            }

            ReadAsync();
        }