internal Connection(ConnectionGroup connectionGroup) : base(null) {
            //
            // add this Connection to the pool in the connection group,
            //  keep a weak reference to it
            //
            m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength;
            if(m_MaximumUnauthorizedUploadLength > 0){
                m_MaximumUnauthorizedUploadLength*=1024;
            }
            m_ResponseData = new CoreResponseData();
            m_ConnectionGroup = connectionGroup;
            m_ReadBuffer = new byte[4096];    // Using a fixed 4k read buffer.
            m_ReadState = ReadState.Start;
            m_WaitList = new List<WaitListItem>();
            m_WriteList = new ArrayList();
            m_AbortDelegate = new HttpAbortDelegate(AbortOrDisassociate);
            m_ConnectionUnlock = new UnlockConnectionDelegate(UnlockRequest);

            // for status line parsing
            m_StatusLineValues = new StatusLineValues();
            m_RecycleTimer = ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
            // the following line must be the last line of the constructor
            ConnectionGroup.Associate(this);
            m_ReadDone = true;
            m_WriteDone = true;
            m_Error = WebExceptionStatus.Success;
        }
        //
        // Updated version of ParseStatusLine() - secure and fast
        //
        private static unsafe DataParseStatus ParseStatusLineStrict(
                byte[] statusLine,
                int statusLineLength,
                ref int bytesParsed,
                ref int statusState,
                StatusLineValues statusLineValues,
                int maximumHeaderLength,
                ref int totalBytesParsed,
                ref WebParseError parseError)
        {
            GlobalLog.Enter("Connection::ParseStatusLineStrict", statusLineLength.ToString(NumberFormatInfo.InvariantInfo) + ", " + bytesParsed.ToString(NumberFormatInfo.InvariantInfo) + ", " + statusState.ToString(NumberFormatInfo.InvariantInfo));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection::ParseStatusLineStrict");
            GlobalLog.Assert((statusLineLength - bytesParsed) >= 0, "Connection::ParseStatusLineStrict()|(statusLineLength - bytesParsed) < 0");
            GlobalLog.Assert(maximumHeaderLength <= 0 || totalBytesParsed <= maximumHeaderLength, "Connection::ParseStatusLineStrict()|Headers already read exceeds limit.");

            // Remember where we started.
            int initialBytesParsed = bytesParsed;

            // Set up parsing status with what will happen if we exceed the buffer.
            DataParseStatus parseStatus = DataParseStatus.DataTooBig;
            int effectiveMax = maximumHeaderLength <= 0 ? int.MaxValue : (maximumHeaderLength - totalBytesParsed + bytesParsed);
            if (statusLineLength < effectiveMax)
            {
                parseStatus = DataParseStatus.NeedMoreData;
                effectiveMax = statusLineLength;
            }

            // sanity check
            if (bytesParsed >= effectiveMax)
                goto quit;

            fixed (byte* byteBuffer = statusLine)
            {
                // Use this switch to jump midway into the action.  They all fall through until the end of the buffer is reached or
                // the status line is fully parsed.
                switch (statusState)
                {
                    case BeforeVersionNumbers:
                        // This takes advantage of the fact that this token must be the very first thing in the response.
                        while (totalBytesParsed - initialBytesParsed + bytesParsed < BeforeVersionNumberBytes.Length)
                        {
                            if ((byte)BeforeVersionNumberBytes[totalBytesParsed - initialBytesParsed + bytesParsed] != byteBuffer[bytesParsed])
                            {
                                parseStatus = DataParseStatus.Invalid;
                                goto quit;
                            }

                            if(++bytesParsed == effectiveMax)
                                goto quit;
                        }

                        // When entering the MajorVersionNumber phase, make sure at least one digit is present.
                        if (byteBuffer[bytesParsed] == '.')
                        {
                            parseStatus = DataParseStatus.Invalid;
                            goto quit;
                        }

                        statusState = MajorVersionNumber;
                        goto case MajorVersionNumber;

                    case MajorVersionNumber:
                        while (byteBuffer[bytesParsed] != '.')
                        {
                            if (byteBuffer[bytesParsed] < '0' || byteBuffer[bytesParsed] > '9')
                            {
                                parseStatus = DataParseStatus.Invalid;
                                goto quit;
                            }

                            statusLineValues.MajorVersion = statusLineValues.MajorVersion * 10 + byteBuffer[bytesParsed] - '0';

                            if (++bytesParsed == effectiveMax)
                                goto quit;
                        }

                        // Need visibility past the dot.
                        if (bytesParsed + 1 == effectiveMax)
                            goto quit;
                        bytesParsed++;

                        // When entering the MinorVersionNumber phase, make sure at least one digit is present.
                        if (byteBuffer[bytesParsed] == ' ')
                        {
                            parseStatus = DataParseStatus.Invalid;
                            goto quit;
                        }

                        statusState = MinorVersionNumber;
                        goto case MinorVersionNumber;

                    case MinorVersionNumber:
                        // Only a single SP character is allowed to delimit fields in the status line.
                        while (byteBuffer[bytesParsed] != ' ')
                        {
                            if (byteBuffer[bytesParsed] < '0' || byteBuffer[bytesParsed] > '9')
                            {
                                parseStatus = DataParseStatus.Invalid;
                                goto quit;
                            }

                            statusLineValues.MinorVersion = statusLineValues.MinorVersion * 10 + byteBuffer[bytesParsed] - '0';

                            if (++bytesParsed == effectiveMax)
                                goto quit;
                        }

                        statusState = StatusCodeNumber;

                        // Start the status code out as "1".  This will effectively add 1000 to the code.  It's used to count
                        // the number of digits to make sure it's three.  At the end, subtract 1000.
                        statusLineValues.StatusCode = 1;

                        // Move past the space.
                        if (++bytesParsed == effectiveMax)
                            goto quit;

                        goto case StatusCodeNumber;

                    case StatusCodeNumber:
                        // RFC2616 says codes with an unrecognized first digit
                        // should be rejected.  We're allowing the application to define their own "understanding" of
                        // 0, 6, 7, 8, and 9xx codes.
                        while (byteBuffer[bytesParsed] >= '0' && byteBuffer[bytesParsed] <= '9')
                        {
                            // Make sure it isn't too big.  The leading '1' will be removed after three digits are read.
                            if (statusLineValues.StatusCode >= 1000)
                            {
                                parseStatus = DataParseStatus.Invalid;
                                goto quit;
                            }

                            statusLineValues.StatusCode = statusLineValues.StatusCode * 10 + byteBuffer[bytesParsed] - '0';

                            if (++bytesParsed == effectiveMax)
                                goto quit;
                        }

                        // Make sure there was enough, and exactly one space.
                        if (byteBuffer[bytesParsed] != ' ' || statusLineValues.StatusCode < 1000)
                        {
                            if(byteBuffer[bytesParsed] == '\r' && statusLineValues.StatusCode >= 1000){
                                statusLineValues.StatusCode -= 1000;
                                statusState = AfterCarriageReturn;
                                if (++bytesParsed == effectiveMax)
                                    goto quit;
                                goto case AfterCarriageReturn;
                            }
                            parseStatus = DataParseStatus.Invalid;
                            goto quit;
                        }

                        // Remove the extra leading 1.
                        statusLineValues.StatusCode -= 1000;

                        statusState = AfterStatusCode;

                        // Move past the space.
                        if (++bytesParsed == effectiveMax)
                            goto quit;

                        goto case AfterStatusCode;

                    case AfterStatusCode:
                    {
                        // Check for shortcuts.
                        if (statusLineValues.StatusDescription == null)
                        {
                            foreach (string s in s_ShortcutStatusDescriptions)
                            {
                                if (bytesParsed < effectiveMax - s.Length && byteBuffer[bytesParsed] == (byte) s[0])
                                {
                                    int i;
                                    byte *pBuffer = byteBuffer + bytesParsed + 1;
                                    for(i = 1; i < s.Length; i++)
                                        if (*(pBuffer++) != (byte) s[i])
                                            break;
                                    if (i == s.Length)
                                    {
                                        statusLineValues.StatusDescription = s;
                                        bytesParsed += s.Length;
                                    }
                                    break;
                                }
                            }
                        }

                        int beginning = bytesParsed;

                        while (byteBuffer[bytesParsed] != '\r')
                        {
                            if (byteBuffer[bytesParsed] < ' ' || byteBuffer[bytesParsed] == 127)
                            {
                                parseStatus = DataParseStatus.Invalid;
                                goto quit;
                            }

                            if (++bytesParsed == effectiveMax)
                            {
                                string s = WebHeaderCollection.HeaderEncoding.GetString(byteBuffer + beginning, bytesParsed - beginning);
                                if (statusLineValues.StatusDescription == null)
                                    statusLineValues.StatusDescription = s;
                                else
                                    statusLineValues.StatusDescription += s;

                                goto quit;
                            }
                        }

                        if (bytesParsed > beginning)
                        {
                            string s = WebHeaderCollection.HeaderEncoding.GetString(byteBuffer + beginning, bytesParsed - beginning);
                            if (statusLineValues.StatusDescription == null)
                                statusLineValues.StatusDescription = s;
                            else
                                statusLineValues.StatusDescription += s;
                        }
                        else if (statusLineValues.StatusDescription == null)
                        {
                            statusLineValues.StatusDescription = "";
                        }

                        statusState = AfterCarriageReturn;

                        // Move past the CR.
                        if (++bytesParsed == effectiveMax)
                            goto quit;

                        goto case AfterCarriageReturn;
                    }

                    case AfterCarriageReturn:
                        if (byteBuffer[bytesParsed] != '\n')
                        {
                            parseStatus = DataParseStatus.Invalid;
                            goto quit;
                        }

                        parseStatus = DataParseStatus.Done;
                        bytesParsed++;
                        break;
                }
            }

quit:
            totalBytesParsed += bytesParsed - initialBytesParsed;

            GlobalLog.Print("Connection::ParseStatusLineStrict() StatusCode:" + statusLineValues.StatusCode + " MajorVersionNumber:" + statusLineValues.MajorVersion + " MinorVersionNumber:" + statusLineValues.MinorVersion + " StatusDescription:" + ValidationHelper.ToString(statusLineValues.StatusDescription));
            GlobalLog.Leave("Connection::ParseStatusLineStrict", parseStatus.ToString());

            if (parseStatus == DataParseStatus.Invalid) {
                parseError.Section = WebParseErrorSection.ResponseStatusLine;
                parseError.Code = WebParseErrorCode.Generic;
            }

            return parseStatus;
        }
        private static unsafe DataParseStatus ParseStatusLineStrict(byte[] statusLine, int statusLineLength, ref int bytesParsed, ref int statusState, StatusLineValues statusLineValues, int maximumHeaderLength, ref int totalBytesParsed, ref WebParseError parseError)
        {
            int num = bytesParsed;
            DataParseStatus dataTooBig = DataParseStatus.DataTooBig;
            int num2 = (maximumHeaderLength <= 0) ? 0x7fffffff : ((maximumHeaderLength - totalBytesParsed) + bytesParsed);
            if (statusLineLength < num2)
            {
                dataTooBig = DataParseStatus.NeedMoreData;
                num2 = statusLineLength;
            }
            if (bytesParsed < num2)
            {
                try
                {
                    fixed (byte* numRef = statusLine)
                    {
                        switch (statusState)
                        {
                            case 0:
                                goto Label_00A2;

                            case 1:
                                goto Label_0115;

                            case 2:
                                goto Label_0190;

                            case 3:
                                goto Label_01FB;

                            case 4:
                                goto Label_029B;

                            case 5:
                                goto Label_0423;

                            default:
                                goto Label_043F;
                        }
                    Label_006D:
                        if (((byte) "HTTP/"[(totalBytesParsed - num) + bytesParsed]) != numRef[bytesParsed])
                        {
                            dataTooBig = DataParseStatus.Invalid;
                            goto Label_043F;
                        }
                        if (++bytesParsed == num2)
                        {
                            goto Label_043F;
                        }
                    Label_00A2:
                        if (((totalBytesParsed - num) + bytesParsed) < "HTTP/".Length)
                        {
                            goto Label_006D;
                        }
                        if (numRef[bytesParsed] == 0x2e)
                        {
                            dataTooBig = DataParseStatus.Invalid;
                            goto Label_043F;
                        }
                        statusState = 1;
                    Label_0115:
                        while (numRef[bytesParsed] != 0x2e)
                        {
                            if ((numRef[bytesParsed] < 0x30) || (numRef[bytesParsed] > 0x39))
                            {
                                dataTooBig = DataParseStatus.Invalid;
                                goto Label_043F;
                            }
                            statusLineValues.MajorVersion = ((statusLineValues.MajorVersion * 10) + numRef[bytesParsed]) - 0x30;
                            if (++bytesParsed == num2)
                            {
                                goto Label_043F;
                            }
                        }
                        if ((bytesParsed + 1) == num2)
                        {
                            goto Label_043F;
                        }
                        bytesParsed++;
                        if (numRef[bytesParsed] == 0x20)
                        {
                            dataTooBig = DataParseStatus.Invalid;
                            goto Label_043F;
                        }
                        statusState = 2;
                    Label_0190:
                        while (numRef[bytesParsed] != 0x20)
                        {
                            if ((numRef[bytesParsed] < 0x30) || (numRef[bytesParsed] > 0x39))
                            {
                                dataTooBig = DataParseStatus.Invalid;
                                goto Label_043F;
                            }
                            statusLineValues.MinorVersion = ((statusLineValues.MinorVersion * 10) + numRef[bytesParsed]) - 0x30;
                            if (++bytesParsed == num2)
                            {
                                goto Label_043F;
                            }
                        }
                        statusState = 3;
                        statusLineValues.StatusCode = 1;
                        if (++bytesParsed != num2)
                        {
                            goto Label_01FB;
                        }
                        goto Label_043F;
                    Label_01B8:
                        if (statusLineValues.StatusCode >= 0x3e8)
                        {
                            dataTooBig = DataParseStatus.Invalid;
                            goto Label_043F;
                        }
                        statusLineValues.StatusCode = ((statusLineValues.StatusCode * 10) + numRef[bytesParsed]) - 0x30;
                        if (++bytesParsed == num2)
                        {
                            goto Label_043F;
                        }
                    Label_01FB:
                        if ((numRef[bytesParsed] >= 0x30) && (numRef[bytesParsed] <= 0x39))
                        {
                            goto Label_01B8;
                        }
                        if ((numRef[bytesParsed] != 0x20) || (statusLineValues.StatusCode < 0x3e8))
                        {
                            if ((numRef[bytesParsed] == 13) && (statusLineValues.StatusCode >= 0x3e8))
                            {
                                statusLineValues.StatusCode -= 0x3e8;
                                statusState = 5;
                                if (++bytesParsed != num2)
                                {
                                    goto Label_0423;
                                }
                            }
                            else
                            {
                                dataTooBig = DataParseStatus.Invalid;
                            }
                            goto Label_043F;
                        }
                        statusLineValues.StatusCode -= 0x3e8;
                        statusState = 4;
                        if (++bytesParsed == num2)
                        {
                            goto Label_043F;
                        }
                    Label_029B:
                        if (statusLineValues.StatusDescription == null)
                        {
                            foreach (string str in s_ShortcutStatusDescriptions)
                            {
                                if ((bytesParsed >= (num2 - str.Length)) || (numRef[bytesParsed] != ((byte) str[0])))
                                {
                                    continue;
                                }
                                byte* numPtr = (numRef + bytesParsed) + 1;
                                int num3 = 1;
                                while (num3 < str.Length)
                                {
                                    numPtr++;
                                    if (numPtr[0] != ((byte) str[num3]))
                                    {
                                        break;
                                    }
                                    num3++;
                                }
                                if (num3 == str.Length)
                                {
                                    statusLineValues.StatusDescription = str;
                                    bytesParsed += str.Length;
                                }
                                break;
                            }
                        }
                        int num4 = bytesParsed;
                        while (numRef[bytesParsed] != 13)
                        {
                            if ((numRef[bytesParsed] < 0x20) || (numRef[bytesParsed] == 0x7f))
                            {
                                dataTooBig = DataParseStatus.Invalid;
                                goto Label_043F;
                            }
                            if (++bytesParsed == num2)
                            {
                                string str2 = WebHeaderCollection.HeaderEncoding.GetString(numRef + num4, bytesParsed - num4);
                                if (statusLineValues.StatusDescription == null)
                                {
                                    statusLineValues.StatusDescription = str2;
                                }
                                else
                                {
                                    statusLineValues.StatusDescription = statusLineValues.StatusDescription + str2;
                                }
                                goto Label_043F;
                            }
                        }
                        if (bytesParsed > num4)
                        {
                            string str3 = WebHeaderCollection.HeaderEncoding.GetString(numRef + num4, bytesParsed - num4);
                            if (statusLineValues.StatusDescription == null)
                            {
                                statusLineValues.StatusDescription = str3;
                            }
                            else
                            {
                                statusLineValues.StatusDescription = statusLineValues.StatusDescription + str3;
                            }
                        }
                        else if (statusLineValues.StatusDescription == null)
                        {
                            statusLineValues.StatusDescription = "";
                        }
                        statusState = 5;
                        if (++bytesParsed == num2)
                        {
                            goto Label_043F;
                        }
                    Label_0423:
                        if (numRef[bytesParsed] != 10)
                        {
                            dataTooBig = DataParseStatus.Invalid;
                        }
                        else
                        {
                            dataTooBig = DataParseStatus.Done;
                            bytesParsed++;
                        }
                    }
                }
                finally
                {
                    numRef = null;
                }
            }
        Label_043F:
            totalBytesParsed += bytesParsed - num;
            if (dataTooBig == DataParseStatus.Invalid)
            {
                parseError.Section = WebParseErrorSection.ResponseStatusLine;
                parseError.Code = WebParseErrorCode.Generic;
            }
            return dataTooBig;
        }
Example #4
0
        internal Connection(ConnectionGroup connectionGroup) : base(null) {
            //
            // add this Connection to the pool in the connection group,
            //  keep a weak reference to it
            //
            m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength;
            if(m_MaximumUnauthorizedUploadLength > 0){
                m_MaximumUnauthorizedUploadLength*=1024;
            }
            m_ResponseData = new CoreResponseData();
            m_ConnectionGroup = connectionGroup;
            m_ReadBuffer = s_PinnableBufferCache.AllocateBuffer();
            m_ReadBufferFromPinnableCache = true;
            m_ReadState = ReadState.Start;
            m_WaitList = new List<WaitListItem>();
            m_WriteList = new ArrayList();
            m_AbortDelegate = new HttpAbortDelegate(AbortOrDisassociate);
            m_ConnectionUnlock = new UnlockConnectionDelegate(UnlockRequest);

            // for status line parsing
            m_StatusLineValues = new StatusLineValues();
            m_RecycleTimer = ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
            // the following line must be the last line of the constructor
            ConnectionGroup.Associate(this);
            m_ReadDone = true;
            m_WriteDone = true;
            m_Error = WebExceptionStatus.Success;
            if (PinnableBufferCacheEventSource.Log.IsEnabled())
            {
                PinnableBufferCacheEventSource.Log.DebugMessage1("CTOR: In System.Net.Connection.Connnection", this.GetHashCode());
            }
        }
 internal Connection(System.Net.ConnectionGroup connectionGroup) : base(null)
 {
     this.m_IISVersion = -1;
     this.m_Free = true;
     this.m_Idle = true;
     this.m_KeepAlive = true;
     this.m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength;
     if (this.m_MaximumUnauthorizedUploadLength > 0L)
     {
         this.m_MaximumUnauthorizedUploadLength *= 0x400L;
     }
     this.m_ResponseData = new CoreResponseData();
     this.m_ConnectionGroup = connectionGroup;
     this.m_ReadBuffer = new byte[0x1000];
     this.m_ReadState = ReadState.Start;
     this.m_WaitList = new List<WaitListItem>();
     this.m_WriteList = new ArrayList();
     this.m_AbortDelegate = new HttpAbortDelegate(this.AbortOrDisassociate);
     this.m_ConnectionUnlock = new UnlockConnectionDelegate(this.UnlockRequest);
     this.m_StatusLineValues = new StatusLineValues();
     this.m_RecycleTimer = this.ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
     this.ConnectionGroup.Associate(this);
     this.m_ReadDone = true;
     this.m_WriteDone = true;
     this.m_Error = WebExceptionStatus.Success;
 }