HttpResponsetHeaders.cs

/*
 * All intellectual rights of this framework, including this source file belong to Appicacy, René Vaessen.
 * Customers of Appicacy, may copy and change it, as long as this header remains.
 *
 */
using System.Text;
using GenXdev.Configuration;
 
namespace GenXdev.AsyncSockets.Containers
{
    public unsafe class HttpResponseHeaders : IHttpResponseHeaders
    {
        public byte[] MemoryBuffer;
        int CharCount;
        int CharByteCount;
 
        UTF8Encoding UTF8Encoding;
 
        public Uri Location { get; private set; }
        public bool IsValidRequest { get; private set; }
        public void Dispose()
        {
            Dispose(true);
 
            GC.SuppressFinalize(this);
        }
 
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                MemoryBuffer = null;
                CharCount = 0;
                CharByteCount = 0;
            }
        }
 
        ~HttpResponseHeaders()
        {
            Dispose(false);
        }
 
        public HttpResponseHeaders(IMemoryManagerConfiguration Configuration, byte[] MemoryBuffer, byte[] RequestBuffer, int Length, UTF8Encoding UTF8Encoding)
        {
            // store references
            this.MemoryBuffer = MemoryBuffer;
            this.UTF8Encoding = UTF8Encoding;
            this.IsValidRequest = true;
 
            // only really unsafe if memorybuffer is not at least 2x RequestBuffer.length due to UTF8 -> Unicode chars translation
            unsafe
            {
                // get pointer to first byte element in requestbuffer
                fixed (byte* requestBufferBytePointer = &RequestBuffer[0])
                {
                    // get pointer to first byte element in memorybuffer
                    fixed (byte* memoryBufferBytePointer = &MemoryBuffer[0])
                    {
                        // convert byte pointer to char pointer
                        char* memoryBufferCharPointer = (char*)memoryBufferBytePointer;
 
                        // get the unicode chars and put them in the memory buffer
                        CharCount = UTF8Encoding.GetChars(requestBufferBytePointer, Length, memoryBufferCharPointer, Convert.ToInt32(Math.Floor(MemoryBuffer.Length / 2.0)));
                        CharByteCount = CharCount * 2;
                    }
                }
            }
        }
 
        // make sure HeaderName parameter is lowercase!
        public string this[string HeaderName]
        {
            get
            {
                int matchCount = 0;
                int cursorBytePosition = 0;
                int valueStart = 0;
                bool inValue = false;
                bool matched = false;
                var value = new StringBuilder(50);
                bool inHeaders = false;
 
                // loop
                while (cursorBytePosition < CharByteCount)
                {
                    // get pointer to character at cursor
                    fixed (byte* memoryBufferBytePointer = &MemoryBuffer[cursorBytePosition])
                    {
                        // get pointer to the character at the cursor position
                        char* c = (char*)memoryBufferBytePointer;
 
                        // are we matching a headername?
                        if ((inHeaders) && (!inValue) && (matchCount < HeaderName.Length) && (HeaderName[matchCount] == char.ToLower(*c)))
                        {
                            // increase nr of matched characters
                            matchCount++;
 
                            // have matched all characters of the requested headername?
                            if (matchCount == HeaderName.Length)
                            {
                                // set flag
                                matched = true;
                            }
                        }
                        else
                        {
                            // not reached the actual headers yet?
                            if (!inHeaders)
                            {
                                // maybe now?
                                if (*c == '\n')
                                {
                                    // set the flag
                                    inHeaders = true;
                                }
                            }
                            else
                                // have we encountered the headername/value seperator?
                                if ((!inValue) && (*c == ':'))
                            {
                                // toggle the inValue flag
                                inValue = true;
                                valueStart = cursorBytePosition + 2;
                            }
                            else
                                    // encountered a space at the beginning of a header value?
                                    if (inValue && (*c == ' ') && (valueStart == cursorBytePosition))
                            {
                                // trim!
                                valueStart = cursorBytePosition;
                            }
                            else
                                        // headername longer then requested headername?
                                        if (matched && !inValue)
                            {
                                // then we don't have a match!
                                matched = false;
                            }
                            else
                                            // append this character to the result if we are collecting the value of the requested headername
                                            if (matched && (*c != '\r')) value.Append(*c);
 
                            // end of value?
                            if (inValue && ((*c == '\r') || (cursorBytePosition == CharByteCount - 2)))
                            {
 
                                // toggle inValue flag
                                inValue = false;
 
                                // we were collecting the value, because this is the value of the requested headername?
                                if (matched)
                                {
                                    // return the results
                                    return value.ToString();
                                }
                            }
 
                            // reset the match count
                            matchCount = 0;
                        }
                    }
 
                    // move cursor to next unicode character
                    cursorBytePosition += 2;
                }
 
                return "";
            }
        }
    }
}