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; }
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; }