From d9a680703f1bc7aa895e9adf370a0e075eb0a5e4 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 24 Jul 2020 17:12:38 +0100 Subject: [PATCH] cosmetics on http server --- .../OSHttpServer/HttpClientContext.cs | 15 +- .../OSHttpServer/HttpRequestParser.cs | 178 ++++++++++-------- 2 files changed, 106 insertions(+), 87 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs index 617004079c..a1b6342c7a 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs @@ -364,20 +364,18 @@ namespace OSHttpServer continue; m_ReceiveBytesLeft += bytesRead; - if (m_ReceiveBytesLeft > m_ReceiveBuffer.Length) - throw new BadRequestException("HTTP header Too large: " + m_ReceiveBytesLeft); int offset = m_parser.Parse(m_ReceiveBuffer, 0, m_ReceiveBytesLeft); if (m_stream == null) return; // "Connection: Close" in effect. - // try again to see if we can parse another message (check parser to see if it is looking for a new message) - int nextOffset; - int nextBytesleft = m_ReceiveBytesLeft - offset; - - while (offset != 0 && nextBytesleft > 0) + while (offset != 0) { - nextOffset = m_parser.Parse(m_ReceiveBuffer, offset, nextBytesleft); + int nextBytesleft = m_ReceiveBytesLeft - offset; + if(nextBytesleft <= 0) + break; + + int nextOffset = m_parser.Parse(m_ReceiveBuffer, offset, nextBytesleft); if (m_stream == null) return; // "Connection: Close" in effect. @@ -386,7 +384,6 @@ namespace OSHttpServer break; offset = nextOffset; - nextBytesleft = m_ReceiveBytesLeft - offset; } // copy unused bytes to the beginning of the array diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs index 5868187b2c..bf2b3eca5e 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs @@ -224,21 +224,24 @@ namespace OSHttpServer.Parser m_log.Write(this, LogPrio.Warning, "HTTP Request is too large."); throw new BadRequestException("Too large request line."); } - if (char.IsLetterOrDigit(ch) && startPos == -1) - startPos = currentPos; - if (startPos == -1 && (ch != '\r' || nextCh != '\n')) + if (startPos == -1) { - m_log.Write(this, LogPrio.Warning, "Request line is not found."); - throw new BadRequestException("Invalid request line."); + if(char.IsLetterOrDigit(ch)) + startPos = currentPos; + else if (ch != '\r' || nextCh != '\n') + { + m_log.Write(this, LogPrio.Warning, "Request line is not found."); + throw new BadRequestException("Invalid request line."); + } } - if (startPos != -1 && (ch == '\r' || ch == '\n')) + else if(ch == '\r' || ch == '\n') { int size = GetLineBreakSize(buffer, currentPos); OnFirstLine(Encoding.UTF8.GetString(buffer, startPos, currentPos - startPos)); - CurrentState = CurrentState + 1; currentPos += size - 1; - handledBytes = currentPos + size - 1; + handledBytes = currentPos; startPos = -1; + CurrentState = RequestParserState.HeaderName; } break; case RequestParserState.HeaderName: @@ -273,19 +276,20 @@ namespace OSHttpServer.Parser } m_curHeaderName = Encoding.UTF8.GetString(buffer, startPos, currentPos - startPos); handledBytes = currentPos + 1; - startPos = -1; - CurrentState = CurrentState + 1; + startPos = handledBytes; if (ch == ':') - CurrentState = CurrentState + 1; + CurrentState = RequestParserState.Between; + else + CurrentState = RequestParserState.AfterName; } - else if (startPos == -1) - startPos = currentPos; else if (!char.IsLetterOrDigit(ch) && ch != '-') { m_log.Write(this, LogPrio.Warning, "Invalid character in header name on line " + currentLine); throw new BadRequestException("Invalid character in header name on line " + currentLine); } - if (startPos != -1 && currentPos - startPos > 200) + if (startPos == -1) + startPos = currentPos; + else if (currentPos - startPos > 200) { m_log.Write(this, LogPrio.Warning, "Invalid header name on line " + currentLine); throw new BadRequestException("Invalid header name on line " + currentLine); @@ -295,85 +299,103 @@ namespace OSHttpServer.Parser if (ch == ':') { handledBytes = currentPos + 1; - CurrentState = CurrentState + 1; + startPos = currentPos; + CurrentState = RequestParserState.Between; + } + else if(currentPos - startPos > 256) + { + m_log.Write(this, LogPrio.Warning, "missing header aftername ':' " + currentLine); + throw new BadRequestException("missing header aftername ':' " + currentLine); } break; case RequestParserState.Between: { if (ch == ' ' || ch == '\t') - continue; - int newLineSize = GetLineBreakSize(buffer, currentPos); - if (newLineSize > 0 && currentPos + newLineSize < endOfBufferPos && - char.IsWhiteSpace((char)buffer[currentPos + newLineSize])) { - ++currentPos; - continue; + if (currentPos - startPos > 256) + { + m_log.Write(this, LogPrio.Warning, "header value too far" + currentLine); + throw new BadRequestException("header value too far" + currentLine); + } } - startPos = currentPos; - CurrentState = CurrentState + 1; - handledBytes = currentPos; - continue; + else + { + int newLineSize = GetLineBreakSize(buffer, currentPos); + if (newLineSize > 0 && currentPos + newLineSize < endOfBufferPos && + char.IsWhiteSpace((char)buffer[currentPos + newLineSize])) + { + if (currentPos - startPos > 256) + { + m_log.Write(this, LogPrio.Warning, "header value too" + currentLine); + throw new BadRequestException("header value too far" + currentLine); + } + ++currentPos; + } + else + { + startPos = currentPos; + handledBytes = currentPos; + CurrentState = RequestParserState.HeaderValue; + } + } + break; } case RequestParserState.HeaderValue: { - if (ch != '\r' && ch != '\n') - continue; - int newLineSize = GetLineBreakSize(buffer, currentPos); - if (startPos == -1) - continue; // allow new lines before start of value - - if (m_curHeaderName == string.Empty) - throw new BadRequestException("Missing header on line " + currentLine); - if (startPos == -1) + if (ch == '\r' || ch == '\n') { - m_log.Write(this, LogPrio.Warning, "Missing header value for '" + m_curHeaderName); - throw new BadRequestException("Missing header value for '" + m_curHeaderName); - } - if (currentPos - startPos > 8190) - { - m_log.Write(this, LogPrio.Warning, "Too large header value on line " + currentLine); - throw new BadRequestException("Too large header value on line " + currentLine); - } + if (m_curHeaderName == string.Empty) + throw new BadRequestException("Missing header on line " + currentLine); + + if (currentPos - startPos > 8190) + { + m_log.Write(this, LogPrio.Warning, "Too large header value on line " + currentLine); + throw new BadRequestException("Too large header value on line " + currentLine); + } - // Header fields can be extended over multiple lines by preceding each extra line with at - // least one SP or HT. - if (endOfBufferPos > currentPos + newLineSize - && (buffer[currentPos + newLineSize] == ' ' || buffer[currentPos + newLineSize] == '\t')) - { - if (startPos != -1) - m_curHeaderValue = Encoding.UTF8.GetString(buffer, startPos, currentPos - startPos); + // Header fields can be extended over multiple lines by preceding each extra line with at + // least one SP or HT. + int newLineSize = GetLineBreakSize(buffer, currentPos); + if (endOfBufferPos > currentPos + newLineSize + && (buffer[currentPos + newLineSize] == ' ' || buffer[currentPos + newLineSize] == '\t')) + { + if (startPos != -1) + m_curHeaderValue += Encoding.UTF8.GetString(buffer, startPos, currentPos - startPos); - m_log.Write(this, LogPrio.Trace, "Header value is on multiple lines."); - CurrentState = RequestParserState.Between; - startPos = -1; - currentPos += newLineSize - 1; - handledBytes = currentPos + newLineSize - 1; - continue; - } + m_log.Write(this, LogPrio.Trace, "Header value is on multiple lines."); + CurrentState = RequestParserState.Between; + currentPos += newLineSize - 1; + startPos = currentPos; + handledBytes = currentPos; + } + else + { + m_curHeaderValue += Encoding.UTF8.GetString(buffer, startPos, currentPos - startPos); + m_log.Write(this, LogPrio.Trace, "Header [" + m_curHeaderName + ": " + m_curHeaderValue + "]"); + OnHeader(m_curHeaderName, m_curHeaderValue); - m_curHeaderValue += Encoding.UTF8.GetString(buffer, startPos, currentPos - startPos); - m_log.Write(this, LogPrio.Trace, "Header [" + m_curHeaderName + ": " + m_curHeaderValue + "]"); - OnHeader(m_curHeaderName, m_curHeaderValue); + startPos = -1; + CurrentState = RequestParserState.HeaderName; + m_curHeaderValue = string.Empty; + m_curHeaderName = string.Empty; + currentPos += newLineSize - 1; + handledBytes = currentPos; - startPos = -1; - CurrentState = RequestParserState.HeaderName; - m_curHeaderValue = string.Empty; - m_curHeaderName = string.Empty; - ++currentPos; - handledBytes = currentPos + 1; - - // Check if we got a colon so we can cut header name, or crlf for end of header. - bool canContinue = false; - for (int j = currentPos; j < endOfBufferPos; ++j) - { - if (buffer[j] != ':' && buffer[j] != '\r' && buffer[j] != '\n') continue; - canContinue = true; - break; - } - if (!canContinue) - { - m_log.Write(this, LogPrio.Trace, "Cant continue, no colon."); - return currentPos + 1; + // Check if we got a colon so we can cut header name, or crlf for end of header. + bool canContinue = false; + for (int j = currentPos; j < endOfBufferPos; ++j) + { + if (buffer[j] != ':' && buffer[j] != '\r' && buffer[j] != '\n') + continue; + canContinue = true; + break; + } + if (!canContinue) + { + m_log.Write(this, LogPrio.Trace, "Cant continue, no colon."); + return currentPos + 1; + } + } } } break;