mirror of
https://github.com/opensim/opensim.git
synced 2026-08-04 16:22:50 +08:00
use some shared char arrays on string split
This commit is contained in:
@@ -14,7 +14,7 @@ namespace OSHttpServer
|
||||
private readonly X509Certificate m_certificate;
|
||||
private readonly IHttpContextFactory m_contextFactory;
|
||||
private readonly int m_port;
|
||||
private readonly ManualResetEvent m_shutdownEvent = new ManualResetEvent(false);
|
||||
private readonly ManualResetEvent m_shutdownEvent = new(false);
|
||||
private readonly SslProtocols m_sslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;
|
||||
|
||||
private TcpListener m_listener;
|
||||
@@ -64,8 +64,7 @@ namespace OSHttpServer
|
||||
/// <param name="factory">Factory used to create <see cref="IHttpClientContext"/>es.</param>
|
||||
/// <param name="certificate">Certificate to use</param>
|
||||
/// <param name="protocols">which HTTPS protocol to use, default is TLS.</param>
|
||||
protected OSHttpListener(IPAddress address, int port, X509Certificate certificate,
|
||||
SslProtocols protocols)
|
||||
protected OSHttpListener(IPAddress address, int port, X509Certificate certificate, SslProtocols protocols)
|
||||
: this(address, port)
|
||||
{
|
||||
m_certificate = certificate;
|
||||
@@ -109,11 +108,10 @@ namespace OSHttpServer
|
||||
set
|
||||
{
|
||||
m_logWriter = value ?? NullLogWriter.Instance;
|
||||
if (m_certificate != null)
|
||||
m_logWriter.Write(this, LogPrio.Info,
|
||||
"HTTPS(" + m_sslProtocols + ") listening on " + m_address + ":" + m_port);
|
||||
if (m_certificate is not null)
|
||||
m_logWriter.Write(this, LogPrio.Info, $"HTTPS({m_sslProtocols}) listening on {m_address}:{m_port}");
|
||||
else
|
||||
m_logWriter.Write(this, LogPrio.Info, "HTTP listening on " + m_address + ":" + m_port);
|
||||
m_logWriter.Write(this, LogPrio.Info, "$HTTP listening on {m_address}:{m_port}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,9 +155,9 @@ namespace OSHttpServer
|
||||
|
||||
if(socket.Connected)
|
||||
{
|
||||
m_logWriter.Write(this, LogPrio.Debug, "Accepted connection from: " + socket.RemoteEndPoint);
|
||||
m_logWriter.Write(this, LogPrio.Debug, $"Accepted connection from: {socket.RemoteEndPoint}");
|
||||
|
||||
if (m_certificate != null)
|
||||
if (m_certificate is not null)
|
||||
m_contextFactory.CreateSecureContext(socket, m_certificate, m_sslProtocols, m_clientCertValCallback);
|
||||
else
|
||||
m_contextFactory.CreateContext(socket);
|
||||
@@ -204,7 +202,7 @@ namespace OSHttpServer
|
||||
{
|
||||
if(Accepted!=null)
|
||||
{
|
||||
ClientAcceptedEventArgs args = new ClientAcceptedEventArgs(socket);
|
||||
ClientAcceptedEventArgs args = new(socket);
|
||||
Accepted?.Invoke(this, args);
|
||||
return !args.Revoked;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using OpenSim.Framework;
|
||||
using OSHttpServer.Exceptions;
|
||||
|
||||
|
||||
@@ -362,7 +363,7 @@ namespace OSHttpServer
|
||||
break;
|
||||
|
||||
case "forwarded":
|
||||
string[] parts = value.Split(new char[]{';'});
|
||||
string[] parts = value.Split(Util.SplitSemicolonArray);
|
||||
string addr = string.Empty;
|
||||
for(int i = 0; i < parts.Length; ++i)
|
||||
{
|
||||
@@ -386,7 +387,7 @@ namespace OSHttpServer
|
||||
case "x-forwarded-for":
|
||||
if (value.Length > 7)
|
||||
{
|
||||
string[] xparts = value.Split(new char[]{','});
|
||||
string[] xparts = value.Split(Util.SplitCommaArray);
|
||||
if(xparts.Length > 0)
|
||||
{
|
||||
string xs = xparts[0].Trim();
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace OSHttpServer.Parser
|
||||
public class HttpRequestParser : IHttpRequestParser
|
||||
{
|
||||
private ILogWriter m_log;
|
||||
private readonly HeaderEventArgs m_headerArgs = new HeaderEventArgs();
|
||||
private readonly BodyEventArgs m_bodyEventArgs = new BodyEventArgs();
|
||||
private readonly RequestLineEventArgs m_requestLineArgs = new RequestLineEventArgs();
|
||||
private osUTF8Slice m_curHeaderName = new osUTF8Slice();
|
||||
private osUTF8Slice m_curHeaderValue = new osUTF8Slice();
|
||||
private readonly HeaderEventArgs m_headerArgs = new();
|
||||
private readonly BodyEventArgs m_bodyEventArgs = new();
|
||||
private readonly RequestLineEventArgs m_requestLineArgs = new();
|
||||
private osUTF8Slice m_curHeaderName = new();
|
||||
private osUTF8Slice m_curHeaderValue = new();
|
||||
private int m_bodyBytesLeft;
|
||||
|
||||
/// <summary>
|
||||
@@ -68,7 +68,7 @@ namespace OSHttpServer.Parser
|
||||
if (m_bodyBytesLeft == 0)
|
||||
{
|
||||
// got a complete request.
|
||||
m_log.Write(this, LogPrio.Trace, "Request parsed successfully.");
|
||||
m_log.Write(this, LogPrio.Trace, "Request parsed successfully");
|
||||
OnRequestCompleted();
|
||||
Clear();
|
||||
}
|
||||
@@ -108,41 +108,42 @@ namespace OSHttpServer.Parser
|
||||
//todo: In the interest of robustness, servers SHOULD ignore any empty line(s) received where a Request-Line is expected.
|
||||
// In other words, if the server is reading the protocol stream at the beginning of a message and receives a CRLF first, it should ignore the CRLF.
|
||||
//
|
||||
m_log.Write(this, LogPrio.Debug, "Got request: " + value);
|
||||
m_log.Write(this, LogPrio.Debug, $"Got request: {value}");
|
||||
|
||||
//Request-Line = Method SP Request-URI SP HTTP-Version CRLF
|
||||
int pos = value.IndexOf(' ');
|
||||
if (pos == -1 || pos + 1 >= value.Length)
|
||||
int oldPos = pos + 1;
|
||||
if (pos == -1 || oldPos >= value.Length)
|
||||
{
|
||||
m_log.Write(this, LogPrio.Warning, "Invalid request line, missing Method. Line: " + value);
|
||||
throw new BadRequestException("Invalid request line, missing Method. Line: " + value);
|
||||
m_log.Write(this, LogPrio.Warning, $"Invalid request line, missing Method. Line: {value}");
|
||||
throw new BadRequestException($"Invalid request line, missing Method. Line: {value}");
|
||||
}
|
||||
|
||||
string method = value.Substring(0, pos).ToUpper();
|
||||
int oldPos = pos + 1;
|
||||
string method = value[..pos].ToUpper();
|
||||
pos = value.IndexOf(' ', oldPos);
|
||||
if (pos == -1)
|
||||
{
|
||||
m_log.Write(this, LogPrio.Warning, "Invalid request line, missing URI. Line: " + value);
|
||||
throw new BadRequestException("Invalid request line, missing URI. Line: " + value);
|
||||
}
|
||||
string path = value.Substring(oldPos, pos - oldPos);
|
||||
string path = value[oldPos..pos];
|
||||
if (path.Length > 4196)
|
||||
throw new BadRequestException("Too long URI.");
|
||||
if (path == "*")
|
||||
throw new BadRequestException("Not supported URI.");
|
||||
|
||||
if (pos + 1 >= value.Length)
|
||||
oldPos = pos + 1;
|
||||
if (oldPos >= value.Length)
|
||||
{
|
||||
m_log.Write(this, LogPrio.Warning, "Invalid request line, missing HTTP-Version. Line: " + value);
|
||||
throw new BadRequestException("Invalid request line, missing HTTP-Version. Line: " + value);
|
||||
m_log.Write(this, LogPrio.Warning, $"Invalid request line, missing HTTP-Version. Line: {value}");
|
||||
throw new BadRequestException($"Invalid request line, missing HTTP-Version. Line: {value}");
|
||||
}
|
||||
|
||||
string version = value.Substring(pos + 1);
|
||||
if (version.Length < 4 || string.Compare(version.Substring(0, 4), "HTTP", true) != 0)
|
||||
string version = value[oldPos..];
|
||||
if (version.Length < 4 || string.Compare(version[..4], "HTTP", true) != 0)
|
||||
{
|
||||
m_log.Write(this, LogPrio.Warning, "Invalid HTTP version in request line. Line: " + value);
|
||||
throw new BadRequestException("Invalid HTTP version in Request line. Line: " + value);
|
||||
m_log.Write(this, LogPrio.Warning, $"Invalid HTTP version in request line. Line: {value}");
|
||||
throw new BadRequestException($"Invalid HTTP version in Request line. Line: {value}");
|
||||
}
|
||||
|
||||
if(RequestLineReceived != null)
|
||||
@@ -269,7 +270,7 @@ namespace OSHttpServer.Parser
|
||||
if (m_bodyBytesLeft == 0)
|
||||
{
|
||||
CurrentState = RequestParserState.FirstLine;
|
||||
m_log.Write(this, LogPrio.Trace, "Request parsed successfully (no content).");
|
||||
m_log.Write(this, LogPrio.Trace, "Request parsed successfully (no content)");
|
||||
OnRequestCompleted();
|
||||
Clear();
|
||||
return currentPos;
|
||||
@@ -288,9 +289,8 @@ namespace OSHttpServer.Parser
|
||||
{
|
||||
if (startPos == -1)
|
||||
{
|
||||
m_log.Write(this, LogPrio.Warning,
|
||||
"Expected header name, got colon on line " + currentLine);
|
||||
throw new BadRequestException("Expected header name, got colon on line " + currentLine);
|
||||
m_log.Write(this, LogPrio.Warning, $"Expected header name, got colon on line {currentLine}");
|
||||
throw new BadRequestException($"Expected header name, got colon on line {currentLine}");
|
||||
}
|
||||
m_curHeaderName = new osUTF8Slice(buffer, startPos, currentPos - startPos);
|
||||
handledBytes = currentPos + 1;
|
||||
@@ -302,15 +302,15 @@ namespace OSHttpServer.Parser
|
||||
}
|
||||
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);
|
||||
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)
|
||||
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);
|
||||
m_log.Write(this, LogPrio.Warning, $"Invalid header name on line {currentLine}");
|
||||
throw new BadRequestException($"Invalid header name on line {currentLine}");
|
||||
}
|
||||
break;
|
||||
case RequestParserState.AfterName:
|
||||
@@ -332,21 +332,22 @@ namespace OSHttpServer.Parser
|
||||
{
|
||||
if (currentPos - startPos > 256)
|
||||
{
|
||||
m_log.Write(this, LogPrio.Warning, "header value too far" + currentLine);
|
||||
throw new BadRequestException("header value too far" + currentLine);
|
||||
m_log.Write(this, LogPrio.Warning, $"header value too far {currentLine}");
|
||||
throw new BadRequestException($"header value too far {currentLine}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int newLineSize = GetLineBreakSize(buffer, currentPos);
|
||||
if (newLineSize > 0 && currentPos + newLineSize < endOfBufferPos &&
|
||||
char.IsWhiteSpace((char)buffer[currentPos + newLineSize]))
|
||||
int tsize = currentPos + newLineSize;
|
||||
if (newLineSize > 0 && tsize < endOfBufferPos &&
|
||||
char.IsWhiteSpace((char)buffer[tsize]))
|
||||
{
|
||||
if (currentPos - startPos > 256)
|
||||
{
|
||||
m_log.Write(this, LogPrio.Warning, "header value too" + currentLine);
|
||||
throw new BadRequestException("header value too far" + currentLine);
|
||||
}
|
||||
m_log.Write(this, LogPrio.Warning, $"header value too far {currentLine}");
|
||||
throw new BadRequestException($"header value too far {currentLine}");
|
||||
}
|
||||
++currentPos;
|
||||
}
|
||||
else
|
||||
@@ -363,23 +364,23 @@ namespace OSHttpServer.Parser
|
||||
if (ch == '\r' || ch == '\n')
|
||||
{
|
||||
if (m_curHeaderName.Length == 0)
|
||||
throw new BadRequestException("Missing header on line " + currentLine);
|
||||
|
||||
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);
|
||||
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.
|
||||
int newLineSize = GetLineBreakSize(buffer, currentPos);
|
||||
if (endOfBufferPos > currentPos + newLineSize
|
||||
&& (buffer[currentPos + newLineSize] == ' ' || buffer[currentPos + newLineSize] == '\t'))
|
||||
int tnext = currentPos + newLineSize;
|
||||
if (endOfBufferPos > tnext && (buffer[tnext] == ' ' || buffer[tnext] == '\t'))
|
||||
{
|
||||
if (startPos != -1)
|
||||
{
|
||||
osUTF8Slice osUTF8SliceTmp = new osUTF8Slice(buffer, startPos, currentPos - startPos);
|
||||
osUTF8Slice osUTF8SliceTmp = new(buffer, startPos, currentPos - startPos);
|
||||
if (m_curHeaderValue.Length == 0)
|
||||
m_curHeaderValue = osUTF8SliceTmp.Clone();
|
||||
else
|
||||
@@ -393,13 +394,13 @@ namespace OSHttpServer.Parser
|
||||
}
|
||||
else
|
||||
{
|
||||
osUTF8Slice osUTF8SliceTmp = new osUTF8Slice(buffer, startPos, currentPos - startPos);
|
||||
osUTF8Slice osUTF8SliceTmp = new(buffer, startPos, currentPos - startPos);
|
||||
if (m_curHeaderValue.Length == 0)
|
||||
m_curHeaderValue = osUTF8SliceTmp.Clone();
|
||||
else
|
||||
m_curHeaderValue.Append(osUTF8SliceTmp);
|
||||
|
||||
m_log.Write(this, LogPrio.Trace, "Header [" + m_curHeaderName + ": " + m_curHeaderValue + "]");
|
||||
m_log.Write(this, LogPrio.Trace, $"Header [{m_curHeaderName}:{m_curHeaderValue}]");
|
||||
|
||||
OnHeader();
|
||||
|
||||
@@ -432,23 +433,23 @@ namespace OSHttpServer.Parser
|
||||
return handledBytes;
|
||||
}
|
||||
|
||||
int GetLineBreakSize(byte[] buffer, int offset)
|
||||
static int GetLineBreakSize(in byte[] buffer, int offset)
|
||||
{
|
||||
if (buffer[offset] == '\r')
|
||||
byte c = buffer[offset];
|
||||
if (c == '\r')
|
||||
{
|
||||
if (buffer.Length > offset + 1 && buffer[offset + 1] == '\n')
|
||||
++offset;
|
||||
if (buffer.Length > offset && buffer[offset] == '\n')
|
||||
return 2;
|
||||
else
|
||||
throw new BadRequestException("Got invalid linefeed.");
|
||||
}
|
||||
else if (buffer[offset] == '\n')
|
||||
else if (c == '\n')
|
||||
{
|
||||
if (buffer.Length == offset + 1)
|
||||
++offset;
|
||||
if (buffer.Length == offset)
|
||||
return 1; // linux line feed
|
||||
if (buffer[offset + 1] != '\r')
|
||||
return 1; // linux line feed
|
||||
else
|
||||
return 2; // win line feed
|
||||
return buffer[offset] == '\r' ? 2 : 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace OSHttpServer
|
||||
{
|
||||
@@ -68,7 +66,7 @@ namespace OSHttpServer
|
||||
/// <summary>
|
||||
/// The logging instance.
|
||||
/// </summary>
|
||||
public static readonly NullLogWriter Instance = new NullLogWriter();
|
||||
public static readonly NullLogWriter Instance = new();
|
||||
|
||||
/// <summary>
|
||||
/// Writes everything to null
|
||||
@@ -76,6 +74,7 @@ namespace OSHttpServer
|
||||
/// <param name="source">object that wrote the log entry.</param>
|
||||
/// <param name="prio">Importance of the log message</param>
|
||||
/// <param name="message">The message.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(object source, LogPrio prio, string message) {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user