public bool TryGetHeader(BufferValueReader reader, int remaining, ref MessageHeader header)
        {
            string callCategory = null;

                        #if TRACE
            int c = GetNextCallId();
            callCategory = String.Format("{0} {1}:TryGetHeader({2},{3})", this.connectionType, c, reader.Position, remaining);
                        #endif
            Trace.WriteLineIf(NTrace.TraceVerbose, String.Format("Entering {0}", (header == null) ? "without existing header" : "with existing header"), callCategory);

            int mlen; bool isContinued; Message msg = null; Protocol p;

            int headerLength = BaseHeaderLength;

            if (header == null)
            {
                header = new MessageHeader();
            }
            else if (header.State == HeaderState.Complete)
            {
                return(true);
            }
            else if (header.HeaderLength > 0)
            {
                headerLength = header.HeaderLength;
            }

            try
            {
                if (header.State >= HeaderState.Protocol)
                {
                    p = header.Protocol;
                }
                else
                {
                    byte pid = reader.ReadByte();

                    if (!this.protocols.TryGetValue(pid, out p))
                    {
                        Trace.WriteLineIf(NTrace.TraceWarning, "Exiting (Protocol " + pid + " not found)", callCategory);
                        return(true);
                    }

                    header.Protocol = p;
                    header.State    = HeaderState.Protocol;
                    if (this.serializationContext == null)
                    {
                        if (this.connection != null)
                        {
                            this.serializationContext = new SerializationContext(this.connection, this.protocols);
                        }
                        else
                        {
                            this.serializationContext = new SerializationContext(this.protocols);
                        }
                    }

                    header.SerializationContext = this.serializationContext;
                }

                if (header.State < HeaderState.CID)
                {
                    header.ConnectionId = reader.ReadInt32();
                    header.State        = HeaderState.CID;
                }

                if (header.State >= HeaderState.Type)
                {
                    msg = header.Message;
                }
                else
                {
                    ushort type = reader.ReadUInt16();

                    msg          = header.Message = p.Create(type);
                    header.State = HeaderState.Type;

                    if (msg == null)
                    {
                        Trace.WriteLineIf(NTrace.TraceWarning, "Exiting (Message " + type + " not found)", callCategory);
                        return(true);
                    }

                    msg.Header = header;

                    if (msg.Encrypted)
                    {
                        header.IsStillEncrypted = true;
                    }

                    Trace.WriteLineIf(NTrace.TraceVerbose, String.Format("Have " + msg.GetType().Name), callCategory);
                }

                if (header.State >= HeaderState.Length)
                {
                    mlen = header.MessageLength;
                }
                else
                {
                    mlen = reader.ReadInt32();

                    if (mlen <= 0)
                    {
                        Trace.WriteLineIf(NTrace.TraceWarning, "Exiting (length invalid)", callCategory);
                        return(true);
                    }

                    header.MessageLength = mlen;
                    header.State         = HeaderState.Length;

                    Trace.WriteLineIf(NTrace.TraceVerbose, String.Format("Have message of length: {0}", mlen), callCategory);
                }

                if (header.State == HeaderState.IV)
                {
                    if (header.IsStillEncrypted)
                    {
                        Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting (message not buffered)", callCategory);
                        return(!(remaining < mlen));
                    }
                    else if (header.Message.Encrypted)
                    {
                        reader.Position = 0;
                    }
                }
                else if (msg.Encrypted)                // && AES != null)
                {
                    int ivLength = reader.ReadInt32(); //AES.IV.Length;
                    headerLength += ivLength + sizeof(int);

                    if (remaining < headerLength)
                    {
                        reader.Position -= sizeof(int);
                        Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting (header not buffered (IV))", callCategory);
                        return(false);
                    }

                    byte[] iv = reader.ReadBytes(ivLength);

                    header.HeaderLength = headerLength;
                    header.State        = HeaderState.IV;
                    header.IV           = iv;

                    if (remaining < mlen)
                    {
                        Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting (message not buffered)", callCategory);
                        return(false);
                    }

                    Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting (need to decrypt)", callCategory);
                    return(true);
                }

                if (header.State < HeaderState.MessageId)
                {
                    int identV = reader.ReadInt32();
                    header.MessageId  = identV & ~ResponseFlag;
                    header.IsResponse = (identV & ResponseFlag) == ResponseFlag;

                    header.State = (header.IsResponse) ? HeaderState.MessageId : HeaderState.Complete;

                    Trace.WriteLineIf(NTrace.TraceVerbose, "Have message ID: " + header.MessageId, callCategory);
                }

                if (header.State < HeaderState.ResponseMessageId)
                {
                    header.ResponseMessageId = reader.ReadInt32();
                    header.State             = HeaderState.Complete;

                    Trace.WriteLineIf(NTrace.TraceVerbose, "Have message in resoponse to ID: " + header.ResponseMessageId);
                }

                Trace.WriteLineIf(NTrace.TraceVerbose, "Exiting", callCategory);
                return(true);
            }
            catch (Exception ex)
            {
                Trace.WriteLineIf(NTrace.TraceError, "Exiting (error): " + ex, callCategory);
                header = null;
                return(true);
            }
        }