From 7729b92a9f66ef06bdb173bf913ab75abc95f0fe Mon Sep 17 00:00:00 2001 From: GitHubProUser67 <127040195+GitHubProUser67@users.noreply.github.com> Date: Wed, 17 Jul 2024 17:42:13 +0200 Subject: [PATCH 1/2] Adds Netstandard2.1 support. Adds Netstandard2.1 support. Allows a wider range of usage such as Unity 2018 and Xamarin projects. --- Common/src/System/HexConverter.cs | 2 +- src/SpaceWizards.HttpListener.csproj | 2 +- src/System/Net/HttpListenerException.cs | 4 +++ src/System/Net/Managed/HttpConnection.cs | 3 ++- .../HttpListenerTimeoutManager.Managed.cs | 27 +++++++++++++++++++ .../Net/Managed/HttpResponseStream.Managed.cs | 5 +++- src/System/Net/WebSockets/HttpWebSocket.cs | 17 +++++++++--- 7 files changed, 53 insertions(+), 7 deletions(-) diff --git a/Common/src/System/HexConverter.cs b/Common/src/System/HexConverter.cs index 7f24477..1646039 100644 --- a/Common/src/System/HexConverter.cs +++ b/Common/src/System/HexConverter.cs @@ -99,7 +99,7 @@ public static void EncodeToUtf16(ReadOnlySpan bytes, Span chars, Cas #endif public static unsafe string ToString(ReadOnlySpan bytes, Casing casing = Casing.Upper) { -#if NETFRAMEWORK || NETSTANDARD1_0 || NETSTANDARD1_3 || NETSTANDARD2_0 +#if NETFRAMEWORK || NETSTANDARD1_0 || NETSTANDARD1_3 || NETSTANDARD2_0 || NETSTANDARD2_1 Span result = stackalloc char[0]; if (bytes.Length > 16) { diff --git a/src/SpaceWizards.HttpListener.csproj b/src/SpaceWizards.HttpListener.csproj index 11fb420..024e6e3 100644 --- a/src/SpaceWizards.HttpListener.csproj +++ b/src/SpaceWizards.HttpListener.csproj @@ -2,7 +2,7 @@ true true - net6.0 + netstandard2.1;net6.0 enable ..\Common\src\ False diff --git a/src/System/Net/HttpListenerException.cs b/src/System/Net/HttpListenerException.cs index b07da22..58b0a6f 100644 --- a/src/System/Net/HttpListenerException.cs +++ b/src/System/Net/HttpListenerException.cs @@ -12,7 +12,11 @@ namespace SpaceWizards.HttpListener [Serializable] public class HttpListenerException : Win32Exception { +#if NET6_0_OR_GREATER public HttpListenerException() : base(Marshal.GetLastPInvokeError()) +#else + public HttpListenerException() : base(Marshal.GetLastWin32Error()) +#endif { if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{NativeErrorCode}:{Message}"); } diff --git a/src/System/Net/Managed/HttpConnection.cs b/src/System/Net/Managed/HttpConnection.cs index 0c34bd7..82eda0b 100644 --- a/src/System/Net/Managed/HttpConnection.cs +++ b/src/System/Net/Managed/HttpConnection.cs @@ -125,9 +125,10 @@ internal SslStream? SslStream { get { return _sslStream; } } - +#if NET5_0_OR_GREATER [MemberNotNull(nameof(_memoryStream))] [MemberNotNull(nameof(_context))] +#endif private void Init() { _contextBound = false; diff --git a/src/System/Net/Managed/HttpListenerTimeoutManager.Managed.cs b/src/System/Net/Managed/HttpListenerTimeoutManager.Managed.cs index a88c96f..b3261a1 100644 --- a/src/System/Net/Managed/HttpListenerTimeoutManager.Managed.cs +++ b/src/System/Net/Managed/HttpListenerTimeoutManager.Managed.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +#if NETCORE3_1_OR_LOWER +using System.Runtime.InteropServices; +#endif using System.Runtime.Versioning; namespace SpaceWizards.HttpListener @@ -40,9 +43,15 @@ public TimeSpan IdleConnection public TimeSpan EntityBody { get => TimeSpan.Zero; +#if NET5_0_OR_GREATER [SupportedOSPlatform("windows")] +#endif set { +#if NETCORE3_1_OR_LOWER + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return; +#endif ValidateTimeout(value); throw new PlatformNotSupportedException(); // low usage, not currently implemented } @@ -51,9 +60,15 @@ public TimeSpan EntityBody public TimeSpan HeaderWait { get => TimeSpan.Zero; +#if NET5_0_OR_GREATER [SupportedOSPlatform("windows")] +#endif set { +#if NETCORE3_1_OR_LOWER + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return; +#endif ValidateTimeout(value); throw new PlatformNotSupportedException(); // low usage, not currently implemented } @@ -62,9 +77,15 @@ public TimeSpan HeaderWait public long MinSendBytesPerSecond { get => 0; +#if NET5_0_OR_GREATER [SupportedOSPlatform("windows")] +#endif set { +#if NETCORE3_1_OR_LOWER + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return; +#endif if (value < 0 || value > uint.MaxValue) { throw new ArgumentOutOfRangeException(nameof(value)); @@ -76,9 +97,15 @@ public long MinSendBytesPerSecond public TimeSpan RequestQueue { get => TimeSpan.Zero; +#if NET5_0_OR_GREATER [SupportedOSPlatform("windows")] +#endif set { +#if NETCORE3_1_OR_LOWER + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return; +#endif ValidateTimeout(value); throw new PlatformNotSupportedException(); // low usage, not currently implemented } diff --git a/src/System/Net/Managed/HttpResponseStream.Managed.cs b/src/System/Net/Managed/HttpResponseStream.Managed.cs index dceaa7f..5a87000 100644 --- a/src/System/Net/Managed/HttpResponseStream.Managed.cs +++ b/src/System/Net/Managed/HttpResponseStream.Managed.cs @@ -280,8 +280,11 @@ private void EndWriteCore(IAsyncResult asyncResult) { if (_closed) return; - +#if NET5_0_OR_GREATER if (asyncResult is HttpStreamAsyncResult { _buffer: not null, _count: 0 }) +#else + if (asyncResult is HttpStreamAsyncResult result && result._buffer != null && result._count == 0) +#endif return; if (_ignore_errors) diff --git a/src/System/Net/WebSockets/HttpWebSocket.cs b/src/System/Net/WebSockets/HttpWebSocket.cs index 4376c56..f1d08cb 100644 --- a/src/System/Net/WebSockets/HttpWebSocket.cs +++ b/src/System/Net/WebSockets/HttpWebSocket.cs @@ -25,8 +25,10 @@ internal static string GetSecWebSocketAcceptString(string? secWebSocketKey) byte[] toHash = Encoding.UTF8.GetBytes(acceptString); // SHA1 used only for hashing purposes, not for crypto. Check here for FIPS compat. - byte[] hash = SHA1.HashData(toHash); - return Convert.ToBase64String(hash); + using (SHA1 sha1 = SHA1.Create()) + { + return Convert.ToBase64String(sha1.ComputeHash(toHash)); + } } // return value here signifies if a Sec-WebSocket-Protocol header should be returned by the server. @@ -58,8 +60,17 @@ internal static bool ProcessWebSocketProtocolHeader(string? clientSecWebSocketPr // here, we know that the client has specified something, it's not empty // and the server has specified exactly one protocol - +#if NET5_0_OR_GREATER string[] requestProtocols = clientSecWebSocketProtocol.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); +#else + string[] rawRequestProtocols = clientSecWebSocketProtocol.Split(',', StringSplitOptions.RemoveEmptyEntries); + string[] requestProtocols = new string[rawRequestProtocols.Length]; + + for (int i = 0; i < rawRequestProtocols.Length; i++) + { + requestProtocols[i] = rawRequestProtocols[i].Trim(); + } +#endif acceptProtocol = subProtocol; // client specified protocols, serverOptions has exactly 1 non-empty entry. Check that From b89cbea66ad122f354d8ce0475191c34118a8625 Mon Sep 17 00:00:00 2001 From: GitHubProUser67 <127040195+GitHubProUser67@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:30:15 +0200 Subject: [PATCH 2/2] Implement NetStandard 2.0 support. Implement NetStandard 2.0 support. Also compatible with NetFramework 4.6.1 and up (maybe lower too). --- Common/src/System/HexConverter.cs | 1 - Common/src/System/Net/CaseInsensitiveAscii.cs | 15 +- Common/src/System/Net/CookieParser.cs | 78 ++++--- .../src/System/Net/HttpStatusDescription.cs | 194 ++++++++++++------ Common/src/System/Net/LazyAsyncResult.cs | 47 +++-- .../Net/Logging/NetEventSource.Common.cs | 63 +++--- Common/src/System/Net/WebHeaderEncoding.cs | 37 ++++ .../Net/WebSockets/WebSocketValidate.cs | 4 +- .../src/System/Threading/Tasks/TaskToApm.cs | 17 +- src/SR.cs | 18 +- src/SpaceWizards.HttpListener.csproj | 6 +- src/System/Net/HttpListener.cs | 30 ++- src/System/Net/HttpListenerContext.cs | 15 +- src/System/Net/HttpListenerRequest.cs | 76 +++---- .../Net/HttpListenerRequestUriBuilder.cs | 26 +-- src/System/Net/HttpListenerResponse.cs | 24 +-- src/System/Net/HttpRequestStream.cs | 6 +- src/System/Net/HttpResponseStream.cs | 4 +- src/System/Net/Managed/ChunkStream.cs | 6 +- src/System/Net/Managed/ChunkedInputStream.cs | 10 +- src/System/Net/Managed/HttpConnection.cs | 83 ++++---- .../Net/Managed/HttpEndPointListener.cs | 40 ++-- src/System/Net/Managed/HttpEndPointManager.cs | 18 +- .../Net/Managed/HttpListener.Certificates.cs | 2 +- .../Net/Managed/HttpListener.Managed.cs | 12 +- .../Managed/HttpListenerContext.Managed.cs | 24 ++- .../Managed/HttpListenerRequest.Managed.cs | 42 ++-- .../Managed/HttpListenerResponse.Managed.cs | 20 +- .../Net/Managed/HttpRequestStream.Managed.cs | 6 +- .../Net/Managed/HttpResponseStream.Managed.cs | 26 ++- .../Net/Managed/HttpStreamAsyncResult.cs | 12 +- .../Managed/ListenerAsyncResult.Managed.cs | 36 ++-- src/System/Net/Managed/ListenerPrefix.cs | 32 ++- .../WebSockets/HttpWebSocket.Managed.cs | 31 +-- src/System/Net/ServiceNameStore.cs | 31 +-- .../HttpListenerWebSocketContext.cs | 4 +- src/System/Net/WebSockets/HttpWebSocket.cs | 31 ++- src/System/Net/Windows/CookieExtensions.cs | 28 ++- 38 files changed, 675 insertions(+), 480 deletions(-) diff --git a/Common/src/System/HexConverter.cs b/Common/src/System/HexConverter.cs index 1646039..53bb4fc 100644 --- a/Common/src/System/HexConverter.cs +++ b/Common/src/System/HexConverter.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable using System.Diagnostics; using System.Runtime.CompilerServices; diff --git a/Common/src/System/Net/CaseInsensitiveAscii.cs b/Common/src/System/Net/CaseInsensitiveAscii.cs index 3b83c8f..651e42a 100644 --- a/Common/src/System/Net/CaseInsensitiveAscii.cs +++ b/Common/src/System/Net/CaseInsensitiveAscii.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable using System.Collections; namespace System.Net @@ -42,7 +41,7 @@ internal class CaseInsensitiveAscii : IEqualityComparer, IComparer // ASCII string case insensitive hash function public int GetHashCode(object myObject) { - string? myString = myObject as string; + string myString = myObject as string; if (myString == null) { return 0; @@ -57,10 +56,10 @@ public int GetHashCode(object myObject) } // ASCII string case insensitive comparer - public int Compare(object? firstObject, object? secondObject) + public int Compare(object firstObject, object secondObject) { - string? firstString = firstObject as string; - string? secondString = secondObject as string; + string firstString = firstObject as string; + string secondString = secondObject as string; if (firstString == null) { return secondString == null ? 0 : -1; @@ -97,10 +96,10 @@ private int FastGetHashCode(string myString) } // ASCII string case insensitive comparer - public new bool Equals(object? firstObject, object? secondObject) + public new bool Equals(object firstObject, object secondObject) { - string? firstString = firstObject as string; - string? secondString = secondObject as string; + string firstString = firstObject as string; + string secondString = secondObject as string; if (firstString == null) { return secondString == null; diff --git a/Common/src/System/Net/CookieParser.cs b/Common/src/System/Net/CookieParser.cs index 34fcfa0..a63125a 100644 --- a/Common/src/System/Net/CookieParser.cs +++ b/Common/src/System/Net/CookieParser.cs @@ -1,11 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable using System.Diagnostics; using System.Globalization; using System.Reflection; -using System.Runtime.InteropServices; namespace System.Net { @@ -45,7 +43,7 @@ internal struct CookieTokenizer private bool _eofCookie; private int _index; private readonly int _length; - private string? _name; + private string _name; private bool _quoted; private int _start; private CookieToken _token; @@ -82,7 +80,7 @@ internal bool Eof } } - internal string? Name + internal string Name { get { @@ -450,7 +448,7 @@ internal CookieToken Token } } - internal bool IsEqualTo(string? value) + internal bool IsEqualTo(string value) { return string.Equals(_name, value, StringComparison.OrdinalIgnoreCase); } @@ -511,7 +509,7 @@ internal CookieToken TokenFromName(bool parseResponseCookies) internal struct CookieParser { private CookieTokenizer _tokenizer; - private Cookie? _savedCookie; + private Cookie _savedCookie; internal CookieParser(string cookieString) { @@ -525,8 +523,8 @@ private static bool InternalSetNameMethod(Cookie cookie, string? value) return cookie.InternalSetName(value); } #else - private static Func? s_internalSetNameMethod; - private static Func InternalSetNameMethod + private static Func s_internalSetNameMethod; + private static Func InternalSetNameMethod { get { @@ -536,9 +534,9 @@ private static bool InternalSetNameMethod(Cookie cookie, string? value) // We need to use Cookie.InternalSetName instead of the Cookie.set_Name wrapped in a try catch block, as // Cookie.set_Name keeps the original name if the string is empty or null. // Unfortunately this API is internal so we use reflection to access it. The method is cached for performance reasons. - MethodInfo? method = typeof(Cookie).GetMethod("InternalSetName", BindingFlags.Instance | BindingFlags.NonPublic); + MethodInfo method = typeof(Cookie).GetMethod("InternalSetName", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(method != null, "We need to use an internal method named InternalSetName that is declared on Cookie."); - s_internalSetNameMethod = (Func)Delegate.CreateDelegate(typeof(Func), method); + s_internalSetNameMethod = (Func)Delegate.CreateDelegate(typeof(Func), method); } return s_internalSetNameMethod; @@ -546,7 +544,7 @@ private static bool InternalSetNameMethod(Cookie cookie, string? value) } #endif - private static FieldInfo? s_isQuotedDomainField; + private static FieldInfo s_isQuotedDomainField; private static FieldInfo IsQuotedDomainField { get @@ -554,7 +552,7 @@ private static FieldInfo IsQuotedDomainField if (s_isQuotedDomainField == null) { // TODO https://github.com/dotnet/runtime/issues/19348: - FieldInfo? field = typeof(Cookie).GetField("IsQuotedDomain", BindingFlags.Instance | BindingFlags.NonPublic); + FieldInfo field = typeof(Cookie).GetField("IsQuotedDomain", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(field != null, "We need to use an internal field named IsQuotedDomain that is declared on Cookie."); s_isQuotedDomainField = field; } @@ -563,7 +561,7 @@ private static FieldInfo IsQuotedDomainField } } - private static FieldInfo? s_isQuotedVersionField; + private static FieldInfo s_isQuotedVersionField; private static FieldInfo IsQuotedVersionField { get @@ -571,7 +569,7 @@ private static FieldInfo IsQuotedVersionField if (s_isQuotedVersionField == null) { // TODO https://github.com/dotnet/runtime/issues/19348: - FieldInfo? field = typeof(Cookie).GetField("IsQuotedVersion", BindingFlags.Instance | BindingFlags.NonPublic); + FieldInfo field = typeof(Cookie).GetField("IsQuotedVersion", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(field != null, "We need to use an internal field named IsQuotedVersion that is declared on Cookie."); s_isQuotedVersionField = field; } @@ -583,9 +581,9 @@ private static FieldInfo IsQuotedVersionField // Get // // Gets the next cookie or null if there are no more cookies. - internal Cookie? Get() + internal Cookie Get() { - Cookie? cookie = null; + Cookie cookie = null; // Only the first occurrence of an attribute value must be counted. bool commentSet = false; @@ -618,7 +616,7 @@ private static FieldInfo IsQuotedVersionField if (!commentSet) { commentSet = true; - cookie!.Comment = _tokenizer.Value; + cookie.Comment = _tokenizer.Value; } break; @@ -626,9 +624,9 @@ private static FieldInfo IsQuotedVersionField if (!commentUriSet) { commentUriSet = true; - if (Uri.TryCreate(CheckQuoted(_tokenizer.Value), UriKind.Absolute, out Uri? parsed)) + if (Uri.TryCreate(CheckQuoted(_tokenizer.Value), UriKind.Absolute, out Uri parsed)) { - cookie!.CommentUri = parsed; + cookie.CommentUri = parsed; } } break; @@ -637,7 +635,7 @@ private static FieldInfo IsQuotedVersionField if (!domainSet) { domainSet = true; - cookie!.Domain = CheckQuoted(_tokenizer.Value); + cookie.Domain = CheckQuoted(_tokenizer.Value); IsQuotedDomainField.SetValue(cookie, _tokenizer.Quoted); } break; @@ -650,12 +648,12 @@ private static FieldInfo IsQuotedVersionField if (DateTime.TryParse(CheckQuoted(_tokenizer.Value), CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AdjustToUniversal, out DateTime expires)) { - cookie!.Expires = expires; + cookie.Expires = expires; } else { // This cookie will be rejected - InternalSetNameMethod(cookie!, string.Empty); + InternalSetNameMethod(cookie, string.Empty); } } break; @@ -666,12 +664,12 @@ private static FieldInfo IsQuotedVersionField expiresSet = true; if (int.TryParse(CheckQuoted(_tokenizer.Value), out int parsed)) { - cookie!.Expires = DateTime.Now.AddSeconds(parsed); + cookie.Expires = DateTime.Now.AddSeconds(parsed); } else { // This cookie will be rejected - InternalSetNameMethod(cookie!, string.Empty); + InternalSetNameMethod(cookie, string.Empty); } } break; @@ -680,7 +678,7 @@ private static FieldInfo IsQuotedVersionField if (!pathSet) { pathSet = true; - cookie!.Path = _tokenizer.Value; + cookie.Path = _tokenizer.Value; } break; @@ -690,12 +688,12 @@ private static FieldInfo IsQuotedVersionField portSet = true; try { - cookie!.Port = _tokenizer.Value; + cookie.Port = _tokenizer.Value; } catch { // This cookie will be rejected - InternalSetNameMethod(cookie!, string.Empty); + InternalSetNameMethod(cookie, string.Empty); } } break; @@ -707,13 +705,13 @@ private static FieldInfo IsQuotedVersionField int parsed; if (int.TryParse(CheckQuoted(_tokenizer.Value), out parsed)) { - cookie!.Version = parsed; + cookie.Version = parsed; IsQuotedVersionField.SetValue(cookie, _tokenizer.Quoted); } else { // This cookie will be rejected - InternalSetNameMethod(cookie!, string.Empty); + InternalSetNameMethod(cookie, string.Empty); } } break; @@ -727,7 +725,7 @@ private static FieldInfo IsQuotedVersionField if (!discardSet) { discardSet = true; - cookie!.Discard = true; + cookie.Discard = true; } break; @@ -735,19 +733,19 @@ private static FieldInfo IsQuotedVersionField if (!secureSet) { secureSet = true; - cookie!.Secure = true; + cookie.Secure = true; } break; case CookieToken.HttpOnly: - cookie!.HttpOnly = true; + cookie.HttpOnly = true; break; case CookieToken.Port: if (!portSet) { portSet = true; - cookie!.Port = string.Empty; + cookie.Port = string.Empty; } break; } @@ -759,9 +757,9 @@ private static FieldInfo IsQuotedVersionField return cookie; } - internal Cookie? GetServer() + internal Cookie GetServer() { - Cookie? cookie = _savedCookie; + Cookie cookie = _savedCookie; _savedCookie = null; // Only the first occurrence of an attribute value must be counted. @@ -794,7 +792,7 @@ private static FieldInfo IsQuotedVersionField if (!domainSet) { domainSet = true; - cookie!.Domain = CheckQuoted(_tokenizer.Value); + cookie.Domain = CheckQuoted(_tokenizer.Value); IsQuotedDomainField.SetValue(cookie, _tokenizer.Quoted); } break; @@ -803,7 +801,7 @@ private static FieldInfo IsQuotedVersionField if (!pathSet) { pathSet = true; - cookie!.Path = _tokenizer.Value; + cookie.Path = _tokenizer.Value; } break; @@ -813,12 +811,12 @@ private static FieldInfo IsQuotedVersionField portSet = true; try { - cookie!.Port = _tokenizer.Value; + cookie.Port = _tokenizer.Value; } catch (CookieException) { // This cookie will be rejected - InternalSetNameMethod(cookie!, string.Empty); + InternalSetNameMethod(cookie, string.Empty); } } break; @@ -845,7 +843,7 @@ private static FieldInfo IsQuotedVersionField if (_tokenizer.Token == CookieToken.Port && !portSet) { portSet = true; - cookie!.Port = string.Empty; + cookie.Port = string.Empty; } break; } diff --git a/Common/src/System/Net/HttpStatusDescription.cs b/Common/src/System/Net/HttpStatusDescription.cs index f08cc58..f2d8edc 100644 --- a/Common/src/System/Net/HttpStatusDescription.cs +++ b/Common/src/System/Net/HttpStatusDescription.cs @@ -1,83 +1,145 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable namespace System.Net { internal static class HttpStatusDescription { - internal static string? Get(HttpStatusCode code) => + internal static string Get(HttpStatusCode code) => Get((int)code); - internal static string? Get(int code) => - code switch + internal static string Get(int code) + { + switch (code) { - 100 => "Continue", - 101 => "Switching Protocols", - 102 => "Processing", - 103 => "Early Hints", + case 100: + return "Continue"; + case 101: + return "Switching Protocols"; + case 102: + return "Processing"; + case 103: + return "Early Hints"; - 200 => "OK", - 201 => "Created", - 202 => "Accepted", - 203 => "Non-Authoritative Information", - 204 => "No Content", - 205 => "Reset Content", - 206 => "Partial Content", - 207 => "Multi-Status", - 208 => "Already Reported", - 226 => "IM Used", + case 200: + return "OK"; + case 201: + return "Created"; + case 202: + return "Accepted"; + case 203: + return "Non-Authoritative Information"; + case 204: + return "No Content"; + case 205: + return "Reset Content"; + case 206: + return "Partial Content"; + case 207: + return "Multi-Status"; + case 208: + return "Already Reported"; + case 226: + return "IM Used"; - 300 => "Multiple Choices", - 301 => "Moved Permanently", - 302 => "Found", - 303 => "See Other", - 304 => "Not Modified", - 305 => "Use Proxy", - 307 => "Temporary Redirect", - 308 => "Permanent Redirect", + case 300: + return "Multiple Choices"; + case 301: + return "Moved Permanently"; + case 302: + return "Found"; + case 303: + return "See Other"; + case 304: + return "Not Modified"; + case 305: + return "Use Proxy"; + case 307: + return "Temporary Redirect"; + case 308: + return "Permanent Redirect"; - 400 => "Bad Request", - 401 => "Unauthorized", - 402 => "Payment Required", - 403 => "Forbidden", - 404 => "Not Found", - 405 => "Method Not Allowed", - 406 => "Not Acceptable", - 407 => "Proxy Authentication Required", - 408 => "Request Timeout", - 409 => "Conflict", - 410 => "Gone", - 411 => "Length Required", - 412 => "Precondition Failed", - 413 => "Request Entity Too Large", - 414 => "Request-Uri Too Long", - 415 => "Unsupported Media Type", - 416 => "Requested Range Not Satisfiable", - 417 => "Expectation Failed", - 421 => "Misdirected Request", - 422 => "Unprocessable Entity", - 423 => "Locked", - 424 => "Failed Dependency", - 426 => "Upgrade Required", // RFC 2817 - 428 => "Precondition Required", - 429 => "Too Many Requests", - 431 => "Request Header Fields Too Large", - 451 => "Unavailable For Legal Reasons", + case 400: + return "Bad Request"; + case 401: + return "Unauthorized"; + case 402: + return "Payment Required"; + case 403: + return "Forbidden"; + case 404: + return "Not Found"; + case 405: + return "Method Not Allowed"; + case 406: + return "Not Acceptable"; + case 407: + return "Proxy Authentication Required"; + case 408: + return "Request Timeout"; + case 409: + return "Conflict"; + case 410: + return "Gone"; + case 411: + return "Length Required"; + case 412: + return "Precondition Failed"; + case 413: + return "Request Entity Too Large"; + case 414: + return "Request-Uri Too Long"; + case 415: + return "Unsupported Media Type"; + case 416: + return "Requested Range Not Satisfiable"; + case 417: + return "Expectation Failed"; + case 421: + return "Misdirected Request"; + case 422: + return "Unprocessable Entity"; + case 423: + return "Locked"; + case 424: + return "Failed Dependency"; + case 426: + return "Upgrade Required"; // RFC 2817 + case 428: + return "Precondition Required"; + case 429: + return "Too Many Requests"; + case 431: + return "Request Header Fields Too Large"; + case 451: + return "Unavailable For Legal Reasons"; - 500 => "Internal Server Error", - 501 => "Not Implemented", - 502 => "Bad Gateway", - 503 => "Service Unavailable", - 504 => "Gateway Timeout", - 505 => "Http Version Not Supported", - 506 => "Variant Also Negotiates", - 507 => "Insufficient Storage", - 508 => "Loop Detected", - 510 => "Not Extended", - 511 => "Network Authentication Required", + case 500: + return "Internal Server Error"; + case 501: + return "Not Implemented"; + case 502: + return "Bad Gateway"; + case 503: + return "Service Unavailable"; + case 504: + return "Gateway Timeout"; + case 505: + return "Http Version Not Supported"; + case 506: + return "Variant Also Negotiates"; + case 507: + return "Insufficient Storage"; + case 508: + return "Loop Detected"; + case 510: + return "Not Extended"; + case 511: + return "Network Authentication Required"; - _ => null, - }; + default: + return null; + } + } } } diff --git a/Common/src/System/Net/LazyAsyncResult.cs b/Common/src/System/Net/LazyAsyncResult.cs index fbdfd38..f07f42f 100644 --- a/Common/src/System/Net/LazyAsyncResult.cs +++ b/Common/src/System/Net/LazyAsyncResult.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable using System.Diagnostics; using System.Threading; using System.Threading.Tasks; @@ -17,13 +16,13 @@ internal class LazyAsyncResult : IAsyncResult // This is to avoid user mistakes when they queue another async op from a callback the completes sync. [ThreadStatic] - private static ThreadContext? t_threadContext; + private static ThreadContext t_threadContext; private static ThreadContext CurrentThreadContext { get { - ThreadContext? threadContext = t_threadContext; + ThreadContext threadContext = t_threadContext; if (threadContext == null) { threadContext = new ThreadContext(); @@ -43,10 +42,10 @@ private class ThreadContext private bool _protectState; // Used by ContextAwareResult to prevent some calls. #endif - private readonly object? _asyncObject; // Caller's async object. - private readonly object? _asyncState; // Caller's state object. - private AsyncCallback? _asyncCallback; // Caller's callback method. - private object? _result; // Final IO result to be returned byt the End*() method. + private readonly object _asyncObject; // Caller's async object. + private readonly object _asyncState; // Caller's state object. + private AsyncCallback _asyncCallback; // Caller's callback method. + private object _result; // Final IO result to be returned byt the End*() method. private int _errorCode; // Win32 error code for Win32 IO async calls (that want to throw). private int _intCompleted; // Sign bit indicates synchronous completion if set. // Remaining bits count the number of InvokeCallbak() calls. @@ -54,9 +53,9 @@ private class ThreadContext private bool _endCalled; // True if the user called the End*() method. private bool _userEvent; // True if the event has been (or is about to be) handed to the user - private object? _event; // Lazy allocated event to be returned in the IAsyncResult for the client to wait on. + private object _event; // Lazy allocated event to be returned in the IAsyncResult for the client to wait on. - internal LazyAsyncResult(object? myObject, object? myState, AsyncCallback? myCallBack) + internal LazyAsyncResult(object myObject, object myState, AsyncCallback myCallBack) { _asyncObject = myObject; _asyncState = myState; @@ -66,7 +65,7 @@ internal LazyAsyncResult(object? myObject, object? myState, AsyncCallback? myCal } // Interface method to return the original async object. - internal object? AsyncObject + internal object AsyncObject { get { @@ -75,7 +74,7 @@ internal object? AsyncObject } // Interface method to return the caller's state object. - public object? AsyncState + public object AsyncState { get { @@ -83,7 +82,7 @@ public object? AsyncState } } - protected AsyncCallback? AsyncCallback + protected AsyncCallback AsyncCallback { get { @@ -127,7 +126,7 @@ public WaitHandle AsyncWaitHandle // possible for _event to become null immediately after being set, but only if // IsCompleted has become true. Therefore it's possible for this property // to give different (set) events to different callers when IsCompleted is true. - ManualResetEvent? asyncEvent = (ManualResetEvent?)_event; + ManualResetEvent asyncEvent = (ManualResetEvent)_event; while (asyncEvent == null) { LazilyCreateEvent(out asyncEvent); @@ -242,7 +241,7 @@ internal bool InternalPeekCompleted } // Internal property for setting the IO result. - internal object? Result + internal object Result { get { @@ -293,7 +292,7 @@ internal int ErrorCode // Used by derived classes to pass context into an overridden Complete(). Useful // for determining the 'winning' thread in case several may simultaneously call // the equivalent of InvokeCallback(). - protected void ProtectedInvokeCallback(object? result, IntPtr userToken) + protected void ProtectedInvokeCallback(object result, IntPtr userToken) { // Critical to disallow DBNull here - it could result in a stuck spinlock in WaitForCompletion. if (result == DBNull.Value) @@ -315,7 +314,7 @@ protected void ProtectedInvokeCallback(object? result, IntPtr userToken) _result = result; } - ManualResetEvent? asyncEvent = (ManualResetEvent?)_event; + ManualResetEvent asyncEvent = (ManualResetEvent)_event; if (asyncEvent != null) { try @@ -334,7 +333,7 @@ protected void ProtectedInvokeCallback(object? result, IntPtr userToken) } // Completes the IO with a result and invoking the user's callback. - internal void InvokeCallback(object? result) + internal void InvokeCallback(object result) { ProtectedInvokeCallback(result, IntPtr.Zero); } @@ -365,7 +364,7 @@ protected virtual void Complete(IntPtr userToken) if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "*** OFFLOADED the user callback ****"); Task.Factory.StartNew( - s => WorkerThreadComplete(s!), + s => WorkerThreadComplete(s), this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, @@ -403,7 +402,7 @@ private static void WorkerThreadComplete(object state) try { - thisPtr._asyncCallback!(thisPtr); + thisPtr._asyncCallback(thisPtr); } finally { @@ -418,21 +417,21 @@ protected virtual void Cleanup() { } - internal object? InternalWaitForCompletion() + internal object InternalWaitForCompletion() { return WaitForCompletion(true); } - private object? WaitForCompletion(bool snap) + private object WaitForCompletion(bool snap) { - ManualResetEvent? waitHandle = null; + ManualResetEvent waitHandle = null; bool createdByMe = false; bool complete = snap ? IsCompleted : InternalPeekCompleted; if (!complete) { // Not done yet, so wait: - waitHandle = (ManualResetEvent?)_event; + waitHandle = (ManualResetEvent)_event; if (waitHandle == null) { createdByMe = LazilyCreateEvent(out waitHandle); @@ -458,7 +457,7 @@ protected virtual void Cleanup() { // Does _userEvent need to be volatile (or _event set via Interlocked) in order // to avoid giving a user a disposed event? - ManualResetEvent? oldEvent = (ManualResetEvent?)_event; + ManualResetEvent oldEvent = (ManualResetEvent)_event; _event = null; if (!_userEvent) { diff --git a/Common/src/System/Net/Logging/NetEventSource.Common.cs b/Common/src/System/Net/Logging/NetEventSource.Common.cs index fb10011..5294d0d 100644 --- a/Common/src/System/Net/Logging/NetEventSource.Common.cs +++ b/Common/src/System/Net/Logging/NetEventSource.Common.cs @@ -7,7 +7,6 @@ //#define DEBUG_NETEVENTSOURCE_MISUSE #endif -#nullable enable using System.Collections; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -95,7 +94,7 @@ public class Keywords /// The message to be logged. /// The calling member. [NonEvent] - public static void Info(object? thisOrContextObject, FormattableString? formattableString = null, [CallerMemberName] string? memberName = null) + public static void Info(object thisOrContextObject, FormattableString formattableString = null, [CallerMemberName] string memberName = null) { DebugValidateArg(thisOrContextObject); DebugValidateArg(formattableString); @@ -107,7 +106,7 @@ public static void Info(object? thisOrContextObject, FormattableString? formatta /// The message to be logged. /// The calling member. [NonEvent] - public static void Info(object? thisOrContextObject, object? message, [CallerMemberName] string? memberName = null) + public static void Info(object thisOrContextObject, object message, [CallerMemberName] string memberName = null) { DebugValidateArg(thisOrContextObject); DebugValidateArg(message); @@ -115,7 +114,7 @@ public static void Info(object? thisOrContextObject, object? message, [CallerMem } [Event(InfoEventId, Level = EventLevel.Informational, Keywords = Keywords.Default)] - private void Info(string thisOrContextObject, string? memberName, string? message) => + private void Info(string thisOrContextObject, string memberName, string message) => WriteEvent(InfoEventId, thisOrContextObject, memberName ?? MissingMember, message); #endregion @@ -125,7 +124,7 @@ private void Info(string thisOrContextObject, string? memberName, string? messag /// The message to be logged. /// The calling member. [NonEvent] - public static void Error(object? thisOrContextObject, FormattableString formattableString, [CallerMemberName] string? memberName = null) + public static void Error(object thisOrContextObject, FormattableString formattableString, [CallerMemberName] string memberName = null) { DebugValidateArg(thisOrContextObject); DebugValidateArg(formattableString); @@ -137,7 +136,7 @@ public static void Error(object? thisOrContextObject, FormattableString formatta /// The message to be logged. /// The calling member. [NonEvent] - public static void Error(object? thisOrContextObject, object message, [CallerMemberName] string? memberName = null) + public static void Error(object thisOrContextObject, object message, [CallerMemberName] string memberName = null) { DebugValidateArg(thisOrContextObject); DebugValidateArg(message); @@ -145,7 +144,7 @@ public static void Error(object? thisOrContextObject, object message, [CallerMem } [Event(ErrorEventId, Level = EventLevel.Error, Keywords = Keywords.Default)] - private void ErrorMessage(string thisOrContextObject, string? memberName, string? message) => + private void ErrorMessage(string thisOrContextObject, string memberName, string message) => WriteEvent(ErrorEventId, thisOrContextObject, memberName ?? MissingMember, message); #endregion @@ -155,7 +154,7 @@ private void ErrorMessage(string thisOrContextObject, string? memberName, string /// The message to be logged. /// The calling member. [NonEvent] - public static void Verbose(object? thisOrContextObject, FormattableString formattableString, [CallerMemberName] string? memberName = null) + public static void Verbose(object thisOrContextObject, FormattableString formattableString, [CallerMemberName] string memberName = null) { DebugValidateArg(thisOrContextObject); DebugValidateArg(formattableString); @@ -167,7 +166,7 @@ public static void Verbose(object? thisOrContextObject, FormattableString format /// The message to be logged. /// The calling member. [NonEvent] - public static void Verbose(object? thisOrContextObject, object message, [CallerMemberName] string? memberName = null) + public static void Verbose(object thisOrContextObject, object message, [CallerMemberName] string memberName = null) { DebugValidateArg(thisOrContextObject); DebugValidateArg(message); @@ -175,7 +174,7 @@ public static void Verbose(object? thisOrContextObject, object message, [CallerM } [Event(ErrorEventId, Level = EventLevel.Verbose, Keywords = Keywords.Default)] - private void VerboseMessage(string thisOrContextObject, string? memberName, string? message) => + private void VerboseMessage(string thisOrContextObject, string memberName, string message) => WriteEvent(ErrorEventId, thisOrContextObject, memberName ?? MissingMember, message); #endregion @@ -185,7 +184,7 @@ private void VerboseMessage(string thisOrContextObject, string? memberName, stri /// The buffer to be logged. /// The calling member. [NonEvent] - public static void DumpBuffer(object? thisOrContextObject, byte[] buffer, [CallerMemberName] string? memberName = null) + public static void DumpBuffer(object thisOrContextObject, byte[] buffer, [CallerMemberName] string memberName = null) { DumpBuffer(thisOrContextObject, buffer, 0, buffer.Length, memberName); } @@ -197,7 +196,7 @@ public static void DumpBuffer(object? thisOrContextObject, byte[] buffer, [Calle /// The number of bytes to log. /// The calling member. [NonEvent] - public static void DumpBuffer(object? thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string? memberName = null) + public static void DumpBuffer(object thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string memberName = null) { if (IsEnabled && offset >= 0 && offset <= buffer.Length - count) { @@ -220,7 +219,7 @@ public static void DumpBuffer(object? thisOrContextObject, byte[] buffer, int of /// The number of bytes to log. /// The calling member. [NonEvent] - public static unsafe void DumpBuffer(object? thisOrContextObject, IntPtr bufferPtr, int count, [CallerMemberName] string? memberName = null) + public static unsafe void DumpBuffer(object thisOrContextObject, IntPtr bufferPtr, int count, [CallerMemberName] string memberName = null) { Debug.Assert(bufferPtr != IntPtr.Zero); Debug.Assert(count >= 0); @@ -237,7 +236,7 @@ public static unsafe void DumpBuffer(object? thisOrContextObject, IntPtr bufferP } [Event(DumpArrayEventId, Level = EventLevel.Verbose, Keywords = Keywords.Debug)] - private void DumpBuffer(string thisOrContextObject, string? memberName, byte[] buffer) => + private void DumpBuffer(string thisOrContextObject, string memberName, byte[] buffer) => WriteEvent(DumpArrayEventId, thisOrContextObject, memberName ?? MissingMember, buffer); #endregion @@ -247,7 +246,7 @@ private void DumpBuffer(string thisOrContextObject, string? memberName, byte[] b /// The second object. /// The calling member. [NonEvent] - public static void Associate(object first, object second, [CallerMemberName] string? memberName = null) + public static void Associate(object first, object second, [CallerMemberName] string memberName = null) { DebugValidateArg(first); DebugValidateArg(second); @@ -260,7 +259,7 @@ public static void Associate(object first, object second, [CallerMemberName] str /// The second object. /// The calling member. [NonEvent] - public static void Associate(object? thisOrContextObject, object first, object second, [CallerMemberName] string? memberName = null) + public static void Associate(object thisOrContextObject, object first, object second, [CallerMemberName] string memberName = null) { DebugValidateArg(thisOrContextObject); DebugValidateArg(first); @@ -269,14 +268,14 @@ public static void Associate(object? thisOrContextObject, object first, object s } [Event(AssociateEventId, Level = EventLevel.Informational, Keywords = Keywords.Default, Message = "[{2}]<-->[{3}]")] - private void Associate(string thisOrContextObject, string? memberName, string first, string second) => + private void Associate(string thisOrContextObject, string memberName, string first, string second) => WriteEvent(AssociateEventId, thisOrContextObject, memberName ?? MissingMember, first, second); #endregion #endregion #region Helpers [Conditional("DEBUG_NETEVENTSOURCE_MISUSE")] - private static void DebugValidateArg(object? arg) + private static void DebugValidateArg(object arg) { if (!IsEnabled) { @@ -286,7 +285,7 @@ private static void DebugValidateArg(object? arg) } [Conditional("DEBUG_NETEVENTSOURCE_MISUSE")] - private static void DebugValidateArg(FormattableString? arg) + private static void DebugValidateArg(FormattableString arg) { Debug.Assert(IsEnabled || arg == null, $"Should not be formatting FormattableString \"{arg}\" if tracing isn't enabled"); } @@ -295,13 +294,13 @@ private static void DebugValidateArg(FormattableString? arg) Log.IsEnabled(); [NonEvent] - public static string IdOf(object? value) => value != null ? value.GetType().Name + "#" + GetHashCode(value) : NullInstance; + public static string IdOf(object value) => value != null ? value.GetType().Name + "#" + GetHashCode(value) : NullInstance; [NonEvent] - public static int GetHashCode(object? value) => value?.GetHashCode() ?? 0; + public static int GetHashCode(object value) => value?.GetHashCode() ?? 0; [NonEvent] - public static object Format(object? value) + public static object Format(object value) { // If it's null, return a known string for null values if (value == null) @@ -310,7 +309,7 @@ public static object Format(object? value) } // Give another partial implementation a chance to provide its own string representation - string? result = null; + string result = null; AdditionalCustomizedToString(value, ref result); if (result != null) { @@ -343,7 +342,7 @@ public static object Format(object? value) // If the string representation of the instance would just be its type name, // use its id instead. - string? toString = value.ToString(); + string toString = value.ToString(); if (toString == null || toString == value.GetType().FullName) { return IdOf(value); @@ -363,7 +362,7 @@ private static string Format(FormattableString s) case 2: return string.Format(s.Format, Format(s.GetArgument(0)), Format(s.GetArgument(1))); case 3: return string.Format(s.Format, Format(s.GetArgument(0)), Format(s.GetArgument(1)), Format(s.GetArgument(2))); default: - object?[] args = s.GetArguments(); + object[] args = s.GetArguments(); object[] formattedArgs = new object[args.Length]; for (int i = 0; i < args.Length; i++) { @@ -373,13 +372,13 @@ private static string Format(FormattableString s) } } - static partial void AdditionalCustomizedToString(T value, ref string? result); + static partial void AdditionalCustomizedToString(T value, ref string result); #endregion #region Custom WriteEvent overloads [NonEvent] - private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, string? arg3, string? arg4) + private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, string arg4) { if (IsEnabled()) { @@ -423,7 +422,7 @@ private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, string? } [NonEvent] - private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, byte[]? arg3) + private unsafe void WriteEvent(int eventId, string arg1, string arg2, byte[] arg3) { if (IsEnabled()) { @@ -466,7 +465,7 @@ private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, byte[]? } [NonEvent] - private unsafe void WriteEvent(int eventId, string? arg1, int arg2, int arg3, int arg4) + private unsafe void WriteEvent(int eventId, string arg1, int arg2, int arg3, int arg4) { if (IsEnabled()) { @@ -504,7 +503,7 @@ private unsafe void WriteEvent(int eventId, string? arg1, int arg2, int arg3, in } [NonEvent] - private unsafe void WriteEvent(int eventId, string? arg1, int arg2, string? arg3) + private unsafe void WriteEvent(int eventId, string arg1, int arg2, string arg3) { if (IsEnabled()) { @@ -539,7 +538,7 @@ private unsafe void WriteEvent(int eventId, string? arg1, int arg2, string? arg3 } [NonEvent] - private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, int arg3) + private unsafe void WriteEvent(int eventId, string arg1, string arg2, int arg3) { if (IsEnabled()) { @@ -574,7 +573,7 @@ private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, int arg3 } [NonEvent] - private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, string? arg3, int arg4) + private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, int arg4) { if (IsEnabled()) { diff --git a/Common/src/System/Net/WebHeaderEncoding.cs b/Common/src/System/Net/WebHeaderEncoding.cs index b654e07..04b3235 100644 --- a/Common/src/System/Net/WebHeaderEncoding.cs +++ b/Common/src/System/Net/WebHeaderEncoding.cs @@ -22,6 +22,7 @@ internal static unsafe string GetString(byte[] bytes, int byteIndex, int byteCou Debug.Assert(bytes != null && (uint)byteIndex <= (uint)bytes.Length && (uint)(byteIndex + byteCount) <= (uint)bytes.Length); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER return string.Create(byteCount, (bytes, byteIndex), (buffer, state) => { fixed (byte* pByt = &state.bytes[state.byteIndex]) @@ -51,6 +52,42 @@ internal static unsafe string GetString(byte[] bytes, int byteIndex, int byteCou } } }); +#else + // Allocate a string with the desired length + string result = new string('\0', byteCount); + + fixed (byte* pBytes = &bytes[byteIndex]) + fixed (char* pStr = result) + { + byte* pSource = pBytes; + char* pDest = pStr; + int remaining = byteCount; + + // Copy 8 bytes at a time for efficiency + while (remaining >= 8) + { + pDest[0] = (char)pSource[0]; + pDest[1] = (char)pSource[1]; + pDest[2] = (char)pSource[2]; + pDest[3] = (char)pSource[3]; + pDest[4] = (char)pSource[4]; + pDest[5] = (char)pSource[5]; + pDest[6] = (char)pSource[6]; + pDest[7] = (char)pSource[7]; + pSource += 8; + pDest += 8; + remaining -= 8; + } + + // Copy the remaining bytes one by one + for (int i = 0; i < remaining; i++) + { + pDest[i] = (char)pSource[i]; + } + } + + return result; +#endif } internal static int GetByteCount(string myString) => myString.Length; diff --git a/Common/src/System/Net/WebSockets/WebSocketValidate.cs b/Common/src/System/Net/WebSockets/WebSocketValidate.cs index 729f826..4bce6cf 100644 --- a/Common/src/System/Net/WebSockets/WebSocketValidate.cs +++ b/Common/src/System/Net/WebSockets/WebSocketValidate.cs @@ -51,7 +51,7 @@ internal static void ValidateSubprotocol(string subProtocol) throw new ArgumentException(SR.net_WebSockets_InvalidEmptySubProtocol, nameof(subProtocol)); } - string? invalidChar = null; + string invalidChar = null; int i = 0; while (i < subProtocol.Length) { @@ -80,7 +80,7 @@ internal static void ValidateSubprotocol(string subProtocol) } } - internal static void ValidateCloseStatus(WebSocketCloseStatus closeStatus, string? statusDescription) + internal static void ValidateCloseStatus(WebSocketCloseStatus closeStatus, string statusDescription) { if (closeStatus == WebSocketCloseStatus.Empty && !string.IsNullOrEmpty(statusDescription)) { diff --git a/Common/src/System/Threading/Tasks/TaskToApm.cs b/Common/src/System/Threading/Tasks/TaskToApm.cs index 7dc13d0..e3b8b40 100644 --- a/Common/src/System/Threading/Tasks/TaskToApm.cs +++ b/Common/src/System/Threading/Tasks/TaskToApm.cs @@ -11,9 +11,10 @@ // public int EndFoo(IAsyncResult asyncResult) => // TaskToApm.End(asyncResult); -#nullable enable using System.Diagnostics; +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER using System.Diagnostics.CodeAnalysis; +#endif namespace System.Threading.Tasks { @@ -30,7 +31,7 @@ internal static class TaskToApm /// The callback to be invoked upon completion. /// The state to be stored in the IAsyncResult. /// An IAsyncResult to represent the task's asynchronous operation. - public static IAsyncResult Begin(Task task, AsyncCallback? callback, object? state) => + public static IAsyncResult Begin(Task task, AsyncCallback callback, object state) => new TaskAsyncResult(task, state, callback); /// Processes an IAsyncResult returned by Begin. @@ -56,14 +57,16 @@ public static TResult End(IAsyncResult asyncResult) } ThrowArgumentException(asyncResult); - return default!; // unreachable + return default; // unreachable } /// Gets the task represented by the IAsyncResult. - public static Task? GetTask(IAsyncResult asyncResult) => (asyncResult as TaskAsyncResult)?._task; + public static Task GetTask(IAsyncResult asyncResult) => (asyncResult as TaskAsyncResult)?._task; /// Throws an argument exception for the invalid . +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER [DoesNotReturn] +#endif private static void ThrowArgumentException(IAsyncResult asyncResult) => throw (asyncResult is null ? new ArgumentNullException(nameof(asyncResult)) : @@ -80,13 +83,13 @@ internal sealed class TaskAsyncResult : IAsyncResult /// The wrapped Task. internal readonly Task _task; /// Callback to invoke when the wrapped task completes. - private readonly AsyncCallback? _callback; + private readonly AsyncCallback _callback; /// Initializes the IAsyncResult with the Task to wrap and the associated object state. /// The Task to wrap. /// The new AsyncState value. /// Callback to invoke when the wrapped task completes. - internal TaskAsyncResult(Task task, object? state, AsyncCallback? callback) + internal TaskAsyncResult(Task task, object state, AsyncCallback callback) { Debug.Assert(task != null); _task = task; @@ -119,7 +122,7 @@ private void InvokeCallback() } /// Gets a user-defined object that qualifies or contains information about an asynchronous operation. - public object? AsyncState { get; } + public object AsyncState { get; } /// Gets a value that indicates whether the asynchronous operation completed synchronously. /// This is set lazily based on whether the has completed by the time this object is created. public bool CompletedSynchronously { get; } diff --git a/src/SR.cs b/src/SR.cs index 2d2473d..00e8df5 100644 --- a/src/SR.cs +++ b/src/SR.cs @@ -2,22 +2,22 @@ { internal static class SR { - internal static string Format(string resourceFormat, object? p1) + internal static string Format(string resourceFormat, object p1) { return string.Format(resourceFormat, p1); } - internal static string Format(string resourceFormat, object? p1, object? p2) + internal static string Format(string resourceFormat, object p1, object p2) { return string.Format(resourceFormat, p1, p2); } - internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) + internal static string Format(string resourceFormat, object p1, object p2, object p3) { return string.Format(resourceFormat, p1, p2, p3); } - internal static string Format(string resourceFormat, params object?[]? args) + internal static string Format(string resourceFormat, params object[] args) { if (args != null) { @@ -27,23 +27,23 @@ internal static string Format(string resourceFormat, params object?[]? args) return resourceFormat; } - internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) + internal static string Format(IFormatProvider provider, string resourceFormat, object p1) { return string.Format(provider, resourceFormat, p1); } - internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) + internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2) { return string.Format(provider, resourceFormat, p1, p2); } - internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, - object? p3) + internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2, + object p3) { return string.Format(provider, resourceFormat, p1, p2, p3); } - internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) + internal static string Format(IFormatProvider provider, string resourceFormat, params object[] args) { if (args != null) { diff --git a/src/SpaceWizards.HttpListener.csproj b/src/SpaceWizards.HttpListener.csproj index 024e6e3..bb97859 100644 --- a/src/SpaceWizards.HttpListener.csproj +++ b/src/SpaceWizards.HttpListener.csproj @@ -2,8 +2,7 @@ true true - netstandard2.1;net6.0 - enable + net461;netstandard2.0;netstandard2.1;net6.0 ..\Common\src\ False SpaceWizards.HttpListener @@ -25,6 +24,9 @@ + + + diff --git a/src/System/Net/HttpListener.cs b/src/System/Net/HttpListener.cs index b6737fe..01ba4b8 100644 --- a/src/System/Net/HttpListener.cs +++ b/src/System/Net/HttpListener.cs @@ -3,7 +3,9 @@ using System; using System.Collections; +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER using System.Diagnostics.CodeAnalysis; +#endif using System.Net; using System.Security.Authentication.ExtendedProtection; using System.Security.Cryptography.X509Certificates; @@ -24,11 +26,11 @@ public sealed unsafe partial class HttpListener : IDisposable private readonly ServiceNameStore _defaultServiceNames; private readonly HttpListenerTimeoutManager _timeoutManager; private ExtendedProtectionPolicy _extendedProtectionPolicy; - private AuthenticationSchemeSelector? _authenticationDelegate; + private AuthenticationSchemeSelector _authenticationDelegate; private AuthenticationSchemes _authenticationScheme = AuthenticationSchemes.Anonymous; - private ExtendedProtectionSelector? _extendedProtectionSelectorDelegate; - private string? _realm; - private X509Certificate2? _certificate; + private ExtendedProtectionSelector _extendedProtectionSelectorDelegate; + private string _realm; + private X509Certificate2 _certificate; internal ICollection PrefixCollection => _uriPrefixes.Keys; @@ -46,7 +48,7 @@ public HttpListener() _extendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never); } - public AuthenticationSchemeSelector? AuthenticationSchemeSelectorDelegate + public AuthenticationSchemeSelector AuthenticationSchemeSelectorDelegate { get => _authenticationDelegate; set @@ -56,8 +58,10 @@ public AuthenticationSchemeSelector? AuthenticationSchemeSelectorDelegate } } +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER [DisallowNull] - public ExtendedProtectionSelector? ExtendedProtectionSelectorDelegate +#endif + public ExtendedProtectionSelector ExtendedProtectionSelectorDelegate { get => _extendedProtectionSelectorDelegate; set @@ -114,7 +118,7 @@ public HttpListenerPrefixCollection Prefixes internal void AddPrefix(string uriPrefix) { - string? registeredPrefix = null; + string registeredPrefix = null; try { if (uriPrefix == null) @@ -136,7 +140,11 @@ internal void AddPrefix(string uriPrefix) throw new ArgumentException(SR.net_listener_scheme, nameof(uriPrefix)); } +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER int j = ServiceNameStore.FindEndOfHostname(uriPrefix, i); +#else + int j = ServiceNameStore.FindEndOfHostname(uriPrefix.AsSpan(), i); +#endif if (i == j) { throw new ArgumentException(SR.net_listener_host, nameof(uriPrefix)); @@ -196,7 +204,7 @@ internal bool RemovePrefix(string uriPrefix) if (_state == State.Started) { - RemovePrefixCore((string)_uriPrefixes[uriPrefix]!); + RemovePrefixCore((string)_uriPrefixes[uriPrefix]); } _uriPrefixes.Remove(uriPrefix); @@ -232,7 +240,7 @@ internal void RemoveAll(bool clear) } } - public string? Realm + public string Realm { get => _realm; set @@ -257,8 +265,8 @@ public bool IgnoreWriteExceptions public Task GetContextAsync() { return Task.Factory.FromAsync( - (callback, state) => ((HttpListener)state!).BeginGetContext(callback, state), - iar => ((HttpListener)iar!.AsyncState!).EndGetContext(iar), + (callback, state) => ((HttpListener)state).BeginGetContext(callback, state), + iar => ((HttpListener)iar.AsyncState).EndGetContext(iar), this); } diff --git a/src/System/Net/HttpListenerContext.cs b/src/System/Net/HttpListenerContext.cs index fb8cd0a..ce39ec7 100644 --- a/src/System/Net/HttpListenerContext.cs +++ b/src/System/Net/HttpListenerContext.cs @@ -7,19 +7,18 @@ using System.Security.Principal; using System.Threading.Tasks; using SpaceWizards.HttpListener.WebSockets; -using HttpListenerWebSocketContext = SpaceWizards.HttpListener.WebSockets.HttpListenerWebSocketContext; namespace SpaceWizards.HttpListener { public sealed unsafe partial class HttpListenerContext { - internal HttpListener? _listener; - private HttpListenerResponse? _response; - private IPrincipal? _user; + internal HttpListener _listener; + private HttpListenerResponse _response; + private IPrincipal _user; public HttpListenerRequest Request { get; } - public IPrincipal? User => _user; + public IPrincipal User => _user; // This can be used to cache the results of HttpListener.AuthenticationSchemeSelectorDelegate. internal AuthenticationSchemes AuthenticationSchemes { get; set; } @@ -37,14 +36,16 @@ public HttpListenerResponse Response } } - public Task AcceptWebSocketAsync(string? subProtocol) +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER + public Task AcceptWebSocketAsync(string subProtocol) { return AcceptWebSocketAsync(subProtocol, HttpWebSocket.DefaultReceiveBufferSize, WebSocket.DefaultKeepAliveInterval); } - public Task AcceptWebSocketAsync(string? subProtocol, TimeSpan keepAliveInterval) + public Task AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval) { return AcceptWebSocketAsync(subProtocol, HttpWebSocket.DefaultReceiveBufferSize, keepAliveInterval); } +#endif } } diff --git a/src/System/Net/HttpListenerRequest.cs b/src/System/Net/HttpListenerRequest.cs index 2fe5134..4f1349d 100644 --- a/src/System/Net/HttpListenerRequest.cs +++ b/src/System/Net/HttpListenerRequest.cs @@ -18,24 +18,24 @@ namespace SpaceWizards.HttpListener { public sealed unsafe partial class HttpListenerRequest { - private CookieCollection? _cookies; + private CookieCollection _cookies; private bool? _keepAlive; - private string? _rawUrl; - private Uri? _requestUri; + private string _rawUrl; + private Uri _requestUri; private Version _version; - public string[]? AcceptTypes => Helpers.ParseMultivalueHeader(Headers[HttpKnownHeaderNames.Accept]!); + public string[] AcceptTypes => Helpers.ParseMultivalueHeader(Headers[HttpKnownHeaderNames.Accept]); - public string[]? UserLanguages => Helpers.ParseMultivalueHeader(Headers[HttpKnownHeaderNames.AcceptLanguage]!); + public string[] UserLanguages => Helpers.ParseMultivalueHeader(Headers[HttpKnownHeaderNames.AcceptLanguage]); - private CookieCollection ParseCookies(Uri? uri, string setCookieHeader) + private CookieCollection ParseCookies(Uri uri, string setCookieHeader) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "uri:" + uri + " setCookieHeader:" + setCookieHeader); CookieCollection cookies = new CookieCollection(); CookieParser parser = new CookieParser(setCookieHeader); while (true) { - Cookie? cookie = parser.GetServer(); + Cookie cookie = parser.GetServer(); if (cookie == null) { // EOF, done. @@ -58,7 +58,7 @@ public CookieCollection Cookies { if (_cookies == null) { - string? cookieString = Headers[HttpKnownHeaderNames.Cookie]; + string cookieString = Headers[HttpKnownHeaderNames.Cookie]; if (!string.IsNullOrEmpty(cookieString)) { _cookies = ParseCookies(RequestUri, cookieString); @@ -78,7 +78,7 @@ public Encoding ContentEncoding { if (UserAgent != null && CultureInfo.InvariantCulture.CompareInfo.IsPrefix(UserAgent, "UP")) { - string? postDataCharset = Headers["x-up-devcap-post-charset"]; + string postDataCharset = Headers["x-up-devcap-post-charset"]; if (postDataCharset != null && postDataCharset.Length > 0) { try @@ -94,7 +94,7 @@ public Encoding ContentEncoding { if (ContentType != null) { - string? charSet = Helpers.GetCharSetValueFromHeader(ContentType); + string charSet = Helpers.GetCharSetValueFromHeader(ContentType); if (charSet != null) { try @@ -111,9 +111,9 @@ public Encoding ContentEncoding } } - public string? ContentType => Headers[HttpKnownHeaderNames.ContentType]; + public string ContentType => Headers[HttpKnownHeaderNames.ContentType]; - public bool IsLocal => LocalEndPoint!.Address.Equals(RemoteEndPoint!.Address); + public bool IsLocal => LocalEndPoint.Address.Equals(RemoteEndPoint.Address); public bool IsWebSocketRequest { @@ -130,7 +130,7 @@ public bool IsWebSocketRequest return false; } - foreach (string connection in Headers.GetValues(HttpKnownHeaderNames.Connection)!) + foreach (string connection in Headers.GetValues(HttpKnownHeaderNames.Connection)) { if (string.Equals(connection, HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase)) { @@ -144,7 +144,7 @@ public bool IsWebSocketRequest return false; } - foreach (string upgrade in Headers.GetValues(HttpKnownHeaderNames.Upgrade)!) + foreach (string upgrade in Headers.GetValues(HttpKnownHeaderNames.Upgrade)) { if (string.Equals(upgrade, HttpWebSocket.WebSocketUpgradeToken, StringComparison.OrdinalIgnoreCase)) { @@ -162,7 +162,7 @@ public bool KeepAlive { if (!_keepAlive.HasValue) { - string? header = Headers[HttpKnownHeaderNames.ProxyConnection]; + string header = Headers[HttpKnownHeaderNames.ProxyConnection]; if (string.IsNullOrEmpty(header)) { header = Headers[HttpKnownHeaderNames.Connection]; @@ -184,7 +184,7 @@ public bool KeepAlive header = header.ToLowerInvariant(); _keepAlive = header.IndexOf("close", StringComparison.OrdinalIgnoreCase) < 0 || - header.Contains("keep-alive", StringComparison.OrdinalIgnoreCase); + header.IndexOf("keep-alive", StringComparison.OrdinalIgnoreCase) >= 0; } } @@ -198,41 +198,41 @@ public NameValueCollection QueryString get { NameValueCollection queryString = new NameValueCollection(); - Helpers.FillFromString(queryString, Url!.Query, true, ContentEncoding); + Helpers.FillFromString(queryString, Url.Query, true, ContentEncoding); return queryString; } } - public string? RawUrl => _rawUrl; + public string RawUrl => _rawUrl; private string RequestScheme => IsSecureConnection ? UriScheme.Https : UriScheme.Http; - public string UserAgent => Headers[HttpKnownHeaderNames.UserAgent]!; + public string UserAgent => Headers[HttpKnownHeaderNames.UserAgent]; - public string UserHostAddress => LocalEndPoint!.ToString(); + public string UserHostAddress => LocalEndPoint.ToString(); - public string UserHostName => Headers[HttpKnownHeaderNames.Host]!; + public string UserHostName => Headers[HttpKnownHeaderNames.Host]; - public Uri? UrlReferrer + public Uri UrlReferrer { get { - string? referrer = Headers[HttpKnownHeaderNames.Referer]; + string referrer = Headers[HttpKnownHeaderNames.Referer]; if (referrer == null) { return null; } - bool success = Uri.TryCreate(referrer, UriKind.RelativeOrAbsolute, out Uri? urlReferrer); + bool success = Uri.TryCreate(referrer, UriKind.RelativeOrAbsolute, out Uri urlReferrer); return success ? urlReferrer : null; } } - public Uri? Url => RequestUri; + public Uri Url => RequestUri; public Version ProtocolVersion => _version; - public X509Certificate2? GetClientCertificate() + public X509Certificate2 GetClientCertificate() { if (ClientCertState == ListenerClientCertState.InProgress) throw new InvalidOperationException(SR.Format(SR.net_listener_callinprogress, $"{nameof(GetClientCertificate)}()/{nameof(BeginGetClientCertificate)}()")); @@ -246,7 +246,7 @@ public Uri? UrlReferrer return ClientCertificate; } - public IAsyncResult BeginGetClientCertificate(AsyncCallback? requestCallback, object? state) + public IAsyncResult BeginGetClientCertificate(AsyncCallback requestCallback, object state) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this); if (ClientCertState == ListenerClientCertState.InProgress) @@ -256,16 +256,16 @@ public IAsyncResult BeginGetClientCertificate(AsyncCallback? requestCallback, ob return BeginGetClientCertificateCore(requestCallback, state); } - public Task GetClientCertificateAsync() + public Task GetClientCertificateAsync() { return Task.Factory.FromAsync( - (callback, state) => ((HttpListenerRequest)state!).BeginGetClientCertificate(callback, state), - iar => ((HttpListenerRequest)iar.AsyncState!).EndGetClientCertificate(iar), + (callback, state) => ((HttpListenerRequest)state).BeginGetClientCertificate(callback, state), + iar => ((HttpListenerRequest)iar.AsyncState).EndGetClientCertificate(iar), this); } internal ListenerClientCertState ClientCertState { get; set; } = ListenerClientCertState.NotInitialized; - internal X509Certificate2? ClientCertificate { get; set; } + internal X509Certificate2 ClientCertificate { get; set; } public int ClientCertificateError { @@ -285,7 +285,7 @@ private static class Helpers // // Get attribute off header value // - internal static string? GetCharSetValueFromHeader(string headerValue) + internal static string GetCharSetValueFromHeader(string headerValue) { const string AttrName = "charset"; @@ -330,7 +330,7 @@ private static class Helpers return null; // parse the value - string? attrValue = null; + string attrValue = null; int j; @@ -361,7 +361,7 @@ private static class Helpers return attrValue; } - internal static string[]? ParseMultivalueHeader(string s) + internal static string[] ParseMultivalueHeader(string s) { if (s == null) return null; @@ -484,7 +484,7 @@ private sealed class UrlDecoder // Accumulate bytes for decoding into characters in a special array private int _numBytes; - private byte[]? _byteBuffer; + private byte[] _byteBuffer; // Encoding to convert chars to bytes private readonly Encoding _encoding; @@ -493,7 +493,7 @@ private void FlushBytes() { if (_numBytes > 0) { - _numChars += _encoding.GetChars(_byteBuffer!, 0, _numBytes, _charBuffer, _numChars); + _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars); _numBytes = 0; } } @@ -569,8 +569,8 @@ internal static void FillFromString(NameValueCollection nvc, string s, bool urle // extract the name / value pair - string? name = null; - string? value = null; + string name = null; + string value = null; if (ti >= 0) { diff --git a/src/System/Net/HttpListenerRequestUriBuilder.cs b/src/System/Net/HttpListenerRequestUriBuilder.cs index e5a5e88..6cb0601 100644 --- a/src/System/Net/HttpListenerRequestUriBuilder.cs +++ b/src/System/Net/HttpListenerRequestUriBuilder.cs @@ -27,7 +27,7 @@ internal sealed class HttpListenerRequestUriBuilder private readonly string _cookedUriQuery; // This field is used to build the final request Uri string from the Uri parts passed to the ctor. - private StringBuilder? _requestUriString; + private StringBuilder _requestUriString; // The raw path is parsed by looping through all characters from left to right. 'rawOctets' // is used to store consecutive percent encoded octets as actual byte values: e.g. for path /pa%C3%84th%2F/ @@ -39,11 +39,11 @@ internal sealed class HttpListenerRequestUriBuilder // we reach 't', the content of rawOctets { 0xC4 } will be fed into the ANSI encoding. The resulting // string '\u00C4' will be percent encoded into UTF-8 octets and appended to requestUriString. The final // path will be '/pa%C3%84th/', where '%C3%84' is the UTF-8 percent encoded character. - private List? _rawOctets; - private string? _rawPath; + private List _rawOctets; + private string _rawPath; // Holds the final request Uri. - private Uri? _requestUri; + private Uri _requestUri; private HttpListenerRequestUriBuilder(string rawUri, string cookedUriScheme, string cookedUriHost, string cookedUriPath, string cookedUriQuery) @@ -78,7 +78,7 @@ private Uri Build() BuildRequestUriUsingCookedPath(); } - return _requestUri!; + return _requestUri; } private void BuildRequestUriUsingCookedPath() @@ -224,7 +224,7 @@ private ParsingResult ParseRawPath(Encoding encoding) } // Append the current character to the result. Debug.Assert(_requestUriString != null); - _requestUriString!.Append(current); + _requestUriString.Append(current); index++; } } @@ -251,11 +251,11 @@ private bool AppendUnicodeCodePointValuePercentEncoded(string codePoint) return false; } - string? unicodeString = null; + string unicodeString = null; try { unicodeString = char.ConvertFromUtf32(codePointValue); - AppendOctetsPercentEncoded(_requestUriString!, s_utf8Encoding.GetBytes(unicodeString)); + AppendOctetsPercentEncoded(_requestUriString, s_utf8Encoding.GetBytes(unicodeString)); return true; } @@ -283,19 +283,19 @@ private bool AddPercentEncodedOctetToRawOctetsList(Encoding encoding, string esc } Debug.Assert(_rawOctets != null); - _rawOctets!.Add(encodedValue); + _rawOctets.Add(encodedValue); return true; } private bool EmptyDecodeAndAppendRawOctetsList(Encoding encoding) { - if (_rawOctets!.Count == 0) + if (_rawOctets.Count == 0) { return true; } - string? decodedString = null; + string decodedString = null; try { // If the encoding can get a string out of the byte array, this is a valid string in the @@ -304,11 +304,11 @@ private bool EmptyDecodeAndAppendRawOctetsList(Encoding encoding) if (encoding == s_utf8Encoding) { - AppendOctetsPercentEncoded(_requestUriString!, _rawOctets.ToArray()); + AppendOctetsPercentEncoded(_requestUriString, _rawOctets.ToArray()); } else { - AppendOctetsPercentEncoded(_requestUriString!, s_utf8Encoding.GetBytes(decodedString)); + AppendOctetsPercentEncoded(_requestUriString, s_utf8Encoding.GetBytes(decodedString)); } _rawOctets.Clear(); diff --git a/src/System/Net/HttpListenerResponse.cs b/src/System/Net/HttpListenerResponse.cs index acf24e1..e3826be 100644 --- a/src/System/Net/HttpListenerResponse.cs +++ b/src/System/Net/HttpListenerResponse.cs @@ -12,11 +12,11 @@ namespace SpaceWizards.HttpListener public sealed unsafe partial class HttpListenerResponse : IDisposable { private BoundaryType _boundaryType = BoundaryType.None; - private CookieCollection? _cookies; - private readonly HttpListenerContext? _httpContext; + private CookieCollection _cookies; + private readonly HttpListenerContext _httpContext; private bool _keepAlive = true; - private HttpResponseStream? _responseStream; - private string? _statusDescription; + private HttpResponseStream _responseStream; + private string _statusDescription; private WebHeaderCollection _webHeaders = new WebHeaderCollection(); public WebHeaderCollection Headers @@ -32,9 +32,9 @@ public WebHeaderCollection Headers } } - public Encoding? ContentEncoding { get; set; } + public Encoding ContentEncoding { get; set; } - public string? ContentType + public string ContentType { get => Headers[HttpKnownHeaderNames.ContentType]; set @@ -51,9 +51,9 @@ public string? ContentType } } - private HttpListenerContext HttpListenerContext => _httpContext!; + private HttpListenerContext HttpListenerContext => _httpContext; - private HttpListenerRequest HttpListenerRequest => HttpListenerContext!.Request; + private HttpListenerRequest HttpListenerRequest => HttpListenerContext.Request; internal EntitySendFormat EntitySendFormat { @@ -136,11 +136,11 @@ public Stream OutputStream { CheckDisposed(); EnsureResponseStream(); - return _responseStream!; + return _responseStream; } } - public string? RedirectLocation + public string RedirectLocation { get => Headers[HttpResponseHeader.Location]; set @@ -226,7 +226,7 @@ private void ComputeCookies() if (_cookies != null) { // now go through the collection, and concatenate all the cookies in per-variant strings - string? setCookie2 = null, setCookie = null; + string setCookie2 = null, setCookie = null; for (int index = 0; index < _cookies.Count; index++) { Cookie cookie = _cookies[index]; @@ -273,7 +273,7 @@ public void Redirect(string url) if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"url={url}"); Headers[HttpResponseHeader.Location] = url; StatusCode = (int)HttpStatusCode.Redirect; - StatusDescription = HttpStatusDescription.Get(StatusCode)!; + StatusDescription = HttpStatusDescription.Get(StatusCode); } public void SetCookie(Cookie cookie) diff --git a/src/System/Net/HttpRequestStream.cs b/src/System/Net/HttpRequestStream.cs index 86ffe2b..81a88e7 100644 --- a/src/System/Net/HttpRequestStream.cs +++ b/src/System/Net/HttpRequestStream.cs @@ -29,13 +29,13 @@ public override int Read(byte[] buffer, int offset, int count) return ReadCore(buffer, offset, count); } - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " count:" + count + " offset:" + offset); StreamHelper.ValidateBufferArguments(buffer, offset, count); - return BeginReadCore(buffer, offset, count, callback, state)!; + return BeginReadCore(buffer, offset, count, callback, state); } public override void Flush() { } @@ -55,7 +55,7 @@ public override long Position public override void Write(byte[] buffer, int offset, int count) => throw new InvalidOperationException(SR.net_readonlystream); - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { throw new InvalidOperationException(SR.net_readonlystream); } diff --git a/src/System/Net/HttpResponseStream.cs b/src/System/Net/HttpResponseStream.cs index ab86f91..5160876 100644 --- a/src/System/Net/HttpResponseStream.cs +++ b/src/System/Net/HttpResponseStream.cs @@ -35,7 +35,7 @@ public override long Position public override int Read(byte[] buffer, int offset, int size) => throw new InvalidOperationException(SR.net_writeonlystream); - public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback? callback, object? state) + public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { throw new InvalidOperationException(SR.net_writeonlystream); } @@ -56,7 +56,7 @@ public override void Write(byte[] buffer, int offset, int count) WriteCore(buffer, offset, count); } - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { StreamHelper.ValidateBufferArguments(buffer, offset, count); diff --git a/src/System/Net/Managed/ChunkStream.cs b/src/System/Net/Managed/ChunkStream.cs index f8b4f1a..b38b4c7 100644 --- a/src/System/Net/Managed/ChunkStream.cs +++ b/src/System/Net/Managed/ChunkStream.cs @@ -367,7 +367,11 @@ private State ReadTrailer(byte[] buffer, ref int offset, int size) if (st > 0) { +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER _saved.Append(stString.AsSpan(0, _saved.Length == 0 ? st - 2 : st)); +#else + _saved.Append(stString.AsSpan(0, _saved.Length == 0 ? st - 2 : st).ToString()); +#endif st = 0; if (_saved.Length > 4196) ThrowProtocolViolation("Error reading trailer (too long)."); @@ -384,7 +388,7 @@ private State ReadTrailer(byte[] buffer, ref int offset, int size) } StringReader reader = new StringReader(_saved.ToString()); - string? line; + string line; while ((line = reader.ReadLine()) != null && line != "") _headers.Add(line); diff --git a/src/System/Net/Managed/ChunkedInputStream.cs b/src/System/Net/Managed/ChunkedInputStream.cs index 9af6285..425ea4c 100644 --- a/src/System/Net/Managed/ChunkedInputStream.cs +++ b/src/System/Net/Managed/ChunkedInputStream.cs @@ -78,7 +78,7 @@ protected override int ReadCore(byte[] buffer, int offset, int count) return EndRead(ares); } - protected override IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback? cback, object? state) + protected override IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback cback, object state) { HttpStreamAsyncResult ares = new HttpStreamAsyncResult(this); ares._callback = cback; @@ -116,7 +116,7 @@ protected override IAsyncResult BeginReadCore(byte[] buffer, int offset, int siz private void OnRead(IAsyncResult base_ares) { - ReadBufferState rb = (ReadBufferState)base_ares.AsyncState!; + ReadBufferState rb = (ReadBufferState)base_ares.AsyncState; HttpStreamAsyncResult ares = rb.Ares; try { @@ -129,7 +129,7 @@ private void OnRead(IAsyncResult base_ares) return; } - _decoder.Write(ares._buffer!, ares._offset, nread); + _decoder.Write(ares._buffer, ares._offset, nread); nread = _decoder.Read(rb.Buffer, rb.Offset, rb.Count); rb.Offset += nread; rb.Count -= nread; @@ -142,7 +142,7 @@ private void OnRead(IAsyncResult base_ares) } ares._offset = 0; ares._count = Math.Min(8192, _decoder.ChunkLeft + 6); - base.BeginReadCore(ares._buffer!, ares._offset, ares._count, OnRead, rb); + base.BeginReadCore(ares._buffer, ares._offset, ares._count, OnRead, rb); } catch (Exception e) { @@ -156,7 +156,7 @@ public override int EndRead(IAsyncResult asyncResult) if (asyncResult == null) throw new ArgumentNullException(nameof(asyncResult)); - HttpStreamAsyncResult? ares = asyncResult as HttpStreamAsyncResult; + HttpStreamAsyncResult ares = asyncResult as HttpStreamAsyncResult; if (ares == null || !ReferenceEquals(this, ares._parent)) { throw new ArgumentException(SR.net_io_invalidasyncresult, nameof(asyncResult)); diff --git a/src/System/Net/Managed/HttpConnection.cs b/src/System/Net/Managed/HttpConnection.cs index 82eda0b..abdb84b 100644 --- a/src/System/Net/Managed/HttpConnection.cs +++ b/src/System/Net/Managed/HttpConnection.cs @@ -46,18 +46,18 @@ namespace SpaceWizards.HttpListener { internal sealed class HttpConnection { - private static readonly Action, object?> s_onreadCallback = OnRead; + private static readonly Action, object> s_onreadCallback = OnRead; private const int BufferSize = 8192; - private Socket? _socket; + private Socket _socket; private Stream _stream; private HttpEndPointListener _epl; - private MemoryStream? _memoryStream; - private byte[]? _buffer; + private MemoryStream _memoryStream; + private byte[] _buffer; private HttpListenerContext _context; - private StringBuilder? _currentLine; - private ListenerPrefix? _prefix; - private HttpRequestStream? _requestStream; - private HttpResponseStream? _responseStream; + private StringBuilder _currentLine; + private ListenerPrefix _prefix; + private HttpRequestStream _requestStream; + private HttpResponseStream _responseStream; private bool _chunked; private int _reuses; private bool _contextBound; @@ -65,11 +65,11 @@ internal sealed class HttpConnection private X509Certificate _cert; private int _timeout = 90000; // 90k ms for first request, 15k ms from then on private Timer _timer; - private IPEndPoint? _localEndPoint; - private HttpListener? _lastListener; - private int[]? _clientCertErrors; - private X509Certificate2? _clientCert; - private SslStream? _sslStream; + private IPEndPoint _localEndPoint; + private HttpListener _lastListener; + private int[] _clientCertErrors; + private X509Certificate2 _clientCert; + private SslStream _sslStream; private InputState _inputState = InputState.RequestLine; private LineState _lineState = LineState.None; private int _position; @@ -94,8 +94,11 @@ public HttpConnection(Socket sock, HttpEndPointListener epl, bool secure, X509Ce return true; } - X509Certificate2? c2 = c as X509Certificate2; - c2 ??= new X509Certificate2(c.GetRawCertData()); + X509Certificate2 c2 = c as X509Certificate2; + if (c2 == null) + { + c2 = new X509Certificate2(c.GetRawCertData()); + } _clientCert = c2; _clientCertErrors = new int[] { (int)e }; @@ -111,17 +114,17 @@ public HttpConnection(Socket sock, HttpEndPointListener epl, bool secure, X509Ce Init(); } - internal int[]? ClientCertificateErrors + internal int[] ClientCertificateErrors { get { return _clientCertErrors; } } - internal X509Certificate2? ClientCertificate + internal X509Certificate2 ClientCertificate { get { return _clientCert; } } - internal SslStream? SslStream + internal SslStream SslStream { get { return _sslStream; } } @@ -155,21 +158,21 @@ public int Reuses get { return _reuses; } } - public IPEndPoint? LocalEndPoint + public IPEndPoint LocalEndPoint { get { if (_localEndPoint != null) return _localEndPoint; - _localEndPoint = (IPEndPoint?)_socket!.LocalEndPoint; + _localEndPoint = (IPEndPoint)_socket.LocalEndPoint; return _localEndPoint; } } - public IPEndPoint? RemoteEndPoint + public IPEndPoint RemoteEndPoint { - get { return (IPEndPoint?)_socket!.RemoteEndPoint; } + get { return (IPEndPoint)_socket.RemoteEndPoint; } } public bool IsSecure @@ -177,13 +180,13 @@ public bool IsSecure get { return _secure; } } - public ListenerPrefix? Prefix + public ListenerPrefix Prefix { get { return _prefix; } set { _prefix = value; } } - private void OnTimeout(object? unused) + private void OnTimeout(object unused) { CloseSocket(); Unbind(); @@ -212,8 +215,8 @@ public HttpRequestStream GetRequestStream(bool chunked, long contentlength) { if (_requestStream == null) { - byte[] buffer = _memoryStream!.GetBuffer(); - int length = (int)_memoryStream!.Length; + byte[] buffer = _memoryStream.GetBuffer(); + int length = (int)_memoryStream.Length; _memoryStream = null; if (chunked) { @@ -233,7 +236,7 @@ public HttpResponseStream GetResponseStream() { if (_responseStream == null) { - HttpListener? listener = _context._listener; + HttpListener listener = _context._listener; if (listener == null) return new HttpResponseStream(_stream, _context.Response, true); @@ -243,9 +246,9 @@ public HttpResponseStream GetResponseStream() return _responseStream; } - private static void OnRead(Task task, object? state) + private static void OnRead(Task task, object state) { - HttpConnection cnc = (HttpConnection)state!; + HttpConnection cnc = (HttpConnection)state; cnc.OnReadInternal(task); } @@ -256,7 +259,7 @@ private void OnReadInternal(Task ares) try { nread = ares.Result; - _memoryStream!.Write(_buffer!, 0, nread); + _memoryStream.Write(_buffer, 0, nread); if (_memoryStream.Length > 32768) { SendError(HttpStatusDescription.Get(400), 400); @@ -302,7 +305,7 @@ private void OnReadInternal(Task ares) Close(true); return; } - HttpListener listener = _context._listener!; + HttpListener listener = _context._listener; if (_lastListener != listener) { RemoveConnection(); @@ -315,7 +318,7 @@ private void OnReadInternal(Task ares) return; } - _stream.ReadAsync(_buffer!, 0, BufferSize).ContinueWith(s_onreadCallback, this); + _stream.ReadAsync(_buffer, 0, BufferSize).ContinueWith(s_onreadCallback, this); } private void RemoveConnection() @@ -346,7 +349,7 @@ private bool ProcessInput(MemoryStream ms) byte[] buffer = ms.GetBuffer(); int len = (int)ms.Length; int used = 0; - string? line; + string line; while (true) { @@ -363,7 +366,7 @@ private bool ProcessInput(MemoryStream ms) } catch { - _context.ErrorMessage = HttpStatusDescription.Get(400)!; + _context.ErrorMessage = HttpStatusDescription.Get(400); _context.ErrorStatus = 400; return true; } @@ -376,7 +379,7 @@ private bool ProcessInput(MemoryStream ms) if (_inputState == InputState.RequestLine) continue; _currentLine = null; - ms = null!; + ms = null; return true; } @@ -408,7 +411,7 @@ private bool ProcessInput(MemoryStream ms) return false; } - private string? ReadLine(byte[] buffer, int offset, int len, ref int used) + private string ReadLine(byte[] buffer, int offset, int len, ref int used) { if (_currentLine == null) _currentLine = new StringBuilder(128); @@ -432,7 +435,7 @@ private bool ProcessInput(MemoryStream ms) } } - string? result = null; + string result = null; if (_lineState == LineState.LF) { _lineState = LineState.None; @@ -443,15 +446,15 @@ private bool ProcessInput(MemoryStream ms) return result; } - public void SendError(string? msg, int status) + public void SendError(string msg, int status) { try { HttpListenerResponse response = _context.Response; response.StatusCode = status; response.ContentType = "text/html"; - string? description = HttpStatusDescription.Get(status); - var str = !string.IsNullOrEmpty(msg) ? + string description = HttpStatusDescription.Get(status); + string str = !string.IsNullOrEmpty(msg) ? $"

{description} ({msg})

" : $"

{description}

"; diff --git a/src/System/Net/Managed/HttpEndPointListener.cs b/src/System/Net/Managed/HttpEndPointListener.cs index 4705e7e..90d85b1 100644 --- a/src/System/Net/Managed/HttpEndPointListener.cs +++ b/src/System/Net/Managed/HttpEndPointListener.cs @@ -46,9 +46,9 @@ internal sealed class HttpEndPointListener private readonly Socket _socket; private readonly Dictionary _unregisteredConnections; private Dictionary _prefixes; - private List? _unhandledPrefixes; // host = '*' - private List? _allPrefixes; // host = '+' - private X509Certificate? _cert; + private List _unhandledPrefixes; // host = '*' + private List _allPrefixes; // host = '+' + private X509Certificate _cert; private bool _secure; public HttpEndPointListener(HttpListener listener, IPAddress addr, int port, bool secure) @@ -105,9 +105,9 @@ private void Accept(SocketAsyncEventArgs e) private static void ProcessAccept(SocketAsyncEventArgs args) { - HttpEndPointListener epl = (HttpEndPointListener)args.UserToken!; + HttpEndPointListener epl = (HttpEndPointListener)args.UserToken; - Socket? accepted = args.SocketError == SocketError.Success ? args.AcceptSocket : null; + Socket accepted = args.SocketError == SocketError.Success ? args.AcceptSocket : null; epl.Accept(args); if (accepted == null) @@ -122,7 +122,7 @@ private static void ProcessAccept(SocketAsyncEventArgs args) HttpConnection conn; try { - conn = new HttpConnection(accepted, epl, epl._secure, epl._cert!); + conn = new HttpConnection(accepted, epl, epl._secure, epl._cert); } catch { @@ -137,7 +137,7 @@ private static void ProcessAccept(SocketAsyncEventArgs args) conn.BeginReadRequest(); } - private static void OnAccept(object? sender, SocketAsyncEventArgs e) + private static void OnAccept(object sender, SocketAsyncEventArgs e) { ProcessAccept(e); } @@ -153,8 +153,8 @@ internal void RemoveConnection(HttpConnection conn) public bool BindContext(HttpListenerContext context) { HttpListenerRequest req = context.Request; - ListenerPrefix? prefix; - HttpListener? listener = SearchListener(req.Url, out prefix); + ListenerPrefix prefix; + HttpListener listener = SearchListener(req.Url, out prefix); if (listener == null) return false; @@ -168,10 +168,10 @@ public void UnbindContext(HttpListenerContext context) if (context == null || context.Request == null) return; - context._listener!.UnregisterContext(context); + context._listener.UnregisterContext(context); } - private HttpListener? SearchListener(Uri? uri, out ListenerPrefix? prefix) + private HttpListener SearchListener(Uri uri, out ListenerPrefix prefix) { prefix = null; if (uri == null) @@ -182,7 +182,7 @@ public void UnbindContext(HttpListenerContext context) string path = WebUtility.UrlDecode(uri.AbsolutePath); string pathSlash = path[path.Length - 1] == '/' ? path : path + "/"; - HttpListener? bestMatch = null; + HttpListener bestMatch = null; int bestLength = -1; if (host != null && host != "") @@ -190,7 +190,7 @@ public void UnbindContext(HttpListenerContext context) Dictionary localPrefixes = _prefixes; foreach (ListenerPrefix p in localPrefixes.Keys) { - string ppath = p.Path!; + string ppath = p.Path; if (ppath.Length < bestLength) continue; @@ -208,7 +208,7 @@ public void UnbindContext(HttpListenerContext context) return bestMatch; } - List? list = _unhandledPrefixes; + List list = _unhandledPrefixes; bestMatch = MatchFromList(host, path, list, out prefix); if (path != pathSlash && bestMatch == null) @@ -229,18 +229,18 @@ public void UnbindContext(HttpListenerContext context) return null; } - private HttpListener? MatchFromList(string? host, string path, List? list, out ListenerPrefix? prefix) + private HttpListener MatchFromList(string host, string path, List list, out ListenerPrefix prefix) { prefix = null; if (list == null) return null; - HttpListener? bestMatch = null; + HttpListener bestMatch = null; int bestLength = -1; foreach (ListenerPrefix p in list) { - string ppath = p.Path!; + string ppath = p.Path; if (ppath.Length < bestLength) continue; @@ -291,7 +291,7 @@ private void CheckIfRemove() if (_prefixes.Count > 0) return; - List? list = _unhandledPrefixes; + List list = _unhandledPrefixes; if (list != null && list.Count > 0) return; @@ -318,7 +318,7 @@ public void Close() public void AddPrefix(ListenerPrefix prefix, HttpListener listener) { - List? current; + List current; List future; if (prefix.Host == "*") { @@ -359,7 +359,7 @@ public void AddPrefix(ListenerPrefix prefix, HttpListener listener) public void RemovePrefix(ListenerPrefix prefix, HttpListener listener) { - List? current; + List current; List future; if (prefix.Host == "*") { diff --git a/src/System/Net/Managed/HttpEndPointManager.cs b/src/System/Net/Managed/HttpEndPointManager.cs index add1ad1..13de081 100644 --- a/src/System/Net/Managed/HttpEndPointManager.cs +++ b/src/System/Net/Managed/HttpEndPointManager.cs @@ -87,14 +87,14 @@ private static void AddPrefixInternal(string p, HttpListener listener) if (lp.Port <= 0 || lp.Port >= 65536) throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.net_invalid_port); - if (lp.Path!.Contains('%')) + if (lp.Path.Contains('%')) throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.net_invalid_path); if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1) throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.net_invalid_path); // listens on all the interfaces if host name cannot be parsed by IPAddress. - foreach (HttpEndPointListener epl in GetEPListener(lp.Host!, lp.Port, listener, lp.Secure)) + foreach (HttpEndPointListener epl in GetEPListener(lp.Host, lp.Port, listener, lp.Secure)) { epl.AddPrefix(lp, listener); } @@ -109,8 +109,8 @@ private static IEnumerable GetEPListener(string host, int } else { - if (host.StartsWith('[') && host.EndsWith(']')) - host = host[1..^1]; + if (host.StartsWith("[") && host.EndsWith("]")) + host = host.Substring(1, host.Length - 2); const int NotSupportedErrorCode = 50; try @@ -132,7 +132,7 @@ private static IEnumerable GetEPListener(string host, int foreach (var addr in addresses) { - Dictionary? p = null; + Dictionary p = null; if (s_ipEndPoints.ContainsKey(addr)) { p = s_ipEndPoints[addr]; @@ -143,7 +143,7 @@ private static IEnumerable GetEPListener(string host, int s_ipEndPoints[addr] = p; } - HttpEndPointListener? epl = null; + HttpEndPointListener epl = null; if (p.ContainsKey(port)) { epl = p[port]; @@ -169,7 +169,7 @@ public static void RemoveEndPoint(HttpEndPointListener epl, IPEndPoint ep) { lock ((s_ipEndPoints as ICollection).SyncRoot) { - Dictionary? p = null; + Dictionary p = null; p = s_ipEndPoints[ep.Address]; p.Remove(ep.Port); if (p.Count == 0) @@ -202,13 +202,13 @@ public static void RemovePrefix(string prefix, HttpListener listener) private static void RemovePrefixInternal(string prefix, HttpListener listener) { ListenerPrefix lp = new ListenerPrefix(prefix); - if (lp.Path!.Contains('%')) + if (lp.Path.Contains('%')) return; if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1) return; - foreach (HttpEndPointListener epl in GetEPListener(lp.Host!, lp.Port, listener, lp.Secure)) + foreach (HttpEndPointListener epl in GetEPListener(lp.Host, lp.Port, listener, lp.Secure)) { epl.RemovePrefix(lp, listener); } diff --git a/src/System/Net/Managed/HttpListener.Certificates.cs b/src/System/Net/Managed/HttpListener.Certificates.cs index fa1dc31..25f74b1 100644 --- a/src/System/Net/Managed/HttpListener.Certificates.cs +++ b/src/System/Net/Managed/HttpListener.Certificates.cs @@ -17,7 +17,7 @@ internal SslStream CreateSslStream(Stream innerStream, bool ownsStream, RemoteCe return new SslStream(innerStream, ownsStream, callback); } - internal X509Certificate? LoadCertificateAndKey(IPAddress addr, int port) + internal X509Certificate LoadCertificateAndKey(IPAddress addr, int port) { return _certificate; } diff --git a/src/System/Net/Managed/HttpListener.Managed.cs b/src/System/Net/Managed/HttpListener.Managed.cs index 2cd7de6..7049fc7 100644 --- a/src/System/Net/Managed/HttpListener.Managed.cs +++ b/src/System/Net/Managed/HttpListener.Managed.cs @@ -194,7 +194,7 @@ internal void RegisterContext(HttpListenerContext context) _listenerContexts[context] = context; } - ListenerAsyncResult? ares = null; + ListenerAsyncResult ares = null; lock ((_asyncWaitQueue as ICollection).SyncRoot) { if (_asyncWaitQueue.Count == 0) @@ -259,7 +259,7 @@ private void Cleanup(bool close_existing) } } - private HttpListenerContext? GetContextFromQueue() + private HttpListenerContext GetContextFromQueue() { lock ((_contextQueue as ICollection).SyncRoot) { @@ -275,7 +275,7 @@ private void Cleanup(bool close_existing) } } - public IAsyncResult BeginGetContext(AsyncCallback? callback, object? state) + public IAsyncResult BeginGetContext(AsyncCallback callback, object state) { CheckDisposed(); if (_state != State.Started) @@ -290,7 +290,7 @@ public IAsyncResult BeginGetContext(AsyncCallback? callback, object? state) { lock ((_contextQueue as ICollection).SyncRoot) { - HttpListenerContext? ctx = GetContextFromQueue(); + HttpListenerContext ctx = GetContextFromQueue(); if (ctx != null) { ares.Complete(ctx, true); @@ -312,7 +312,7 @@ public HttpListenerContext EndGetContext(IAsyncResult asyncResult) throw new ArgumentNullException(nameof(asyncResult)); } - ListenerAsyncResult? ares = asyncResult as ListenerAsyncResult; + ListenerAsyncResult ares = asyncResult as ListenerAsyncResult; if (ares == null || !ReferenceEquals(this, ares._parent)) { throw new ArgumentException(SR.net_io_invalidasyncresult, nameof(asyncResult)); @@ -334,7 +334,7 @@ public HttpListenerContext EndGetContext(IAsyncResult asyncResult) _asyncWaitQueue.RemoveAt(idx); } - HttpListenerContext context = ares.GetContext()!; + HttpListenerContext context = ares.GetContext(); context.ParseAuthentication(context.AuthenticationSchemes); return context; } diff --git a/src/System/Net/Managed/HttpListenerContext.Managed.cs b/src/System/Net/Managed/HttpListenerContext.Managed.cs index 267d912..b737ae8 100644 --- a/src/System/Net/Managed/HttpListenerContext.Managed.cs +++ b/src/System/Net/Managed/HttpListenerContext.Managed.cs @@ -3,14 +3,14 @@ using System; using System.ComponentModel; +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER using System.Diagnostics.CodeAnalysis; +#endif using System.Net; using System.Net.WebSockets; using System.Security.Principal; using System.Text; using System.Threading.Tasks; -using SpaceWizards.HttpListener.WebSockets; -using HttpListenerWebSocketContext = SpaceWizards.HttpListener.WebSockets.HttpListenerWebSocketContext; using HttpWebSocket = SpaceWizards.HttpListener.WebSockets.HttpWebSocket; namespace SpaceWizards.HttpListener @@ -29,7 +29,7 @@ internal HttpListenerContext(HttpConnection connection) internal int ErrorStatus { get; set; } - internal string? ErrorMessage { get; set; } + internal string ErrorMessage { get; set; } internal bool HaveError => ErrorMessage != null; @@ -40,7 +40,7 @@ internal void ParseAuthentication(AuthenticationSchemes expectedSchemes) if (expectedSchemes == AuthenticationSchemes.Anonymous) return; - string? header = Request.Headers[HttpKnownHeaderNames.Authorization]; + string header = Request.Headers[HttpKnownHeaderNames.Authorization]; if (string.IsNullOrEmpty(header)) return; @@ -50,8 +50,8 @@ internal void ParseAuthentication(AuthenticationSchemes expectedSchemes) } } - internal IPrincipal? ParseBasicAuthentication(string authData) => - TryParseBasicAuth(authData, out HttpStatusCode errorCode, out string? username, out string? password) ? + internal IPrincipal ParseBasicAuthentication(string authData) => + TryParseBasicAuth(authData, out HttpStatusCode errorCode, out string username, out string password) ? new GenericPrincipal(new HttpListenerBasicIdentity(username, password), Array.Empty()) : null; @@ -60,7 +60,11 @@ internal static bool IsBasicHeader(string header) => header[5] == ' ' && string.Compare(header, 0, AuthenticationTypes.Basic, 0, 5, StringComparison.OrdinalIgnoreCase) == 0; - internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, [NotNullWhen(true)] out string? username, [NotNullWhen(true)] out string? password) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER + internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, [NotNullWhen(true)] out string username, [NotNullWhen(true)] out string password) +#else + internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, out string username, out string password) +#endif { errorCode = HttpStatusCode.OK; username = password = null; @@ -91,17 +95,19 @@ internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode er } } - public Task AcceptWebSocketAsync(string? subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval) +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER + public Task AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval) { return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval); } [EditorBrowsable(EditorBrowsableState.Never)] - public Task AcceptWebSocketAsync(string? subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment internalBuffer) + public Task AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment internalBuffer) { WebSocketValidate.ValidateArraySegment(internalBuffer, nameof(internalBuffer)); HttpWebSocket.ValidateOptions(subProtocol, receiveBufferSize, HttpWebSocket.MinSendBufferSize, keepAliveInterval); return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer); } +#endif } } diff --git a/src/System/Net/Managed/HttpListenerRequest.Managed.cs b/src/System/Net/Managed/HttpListenerRequest.Managed.cs index 606e227..c96edc8 100644 --- a/src/System/Net/Managed/HttpListenerRequest.Managed.cs +++ b/src/System/Net/Managed/HttpListenerRequest.Managed.cs @@ -47,7 +47,7 @@ public sealed partial class HttpListenerRequest { private sealed class Context : TransportContext { - public override ChannelBinding? GetChannelBinding(ChannelBindingKind kind) + public override ChannelBinding GetChannelBinding(ChannelBindingKind kind) { if (kind != ChannelBindingKind.Endpoint) { @@ -61,8 +61,8 @@ private sealed class Context : TransportContext private long _contentLength; private bool _clSet; private WebHeaderCollection _headers; - private string? _method; - private Stream? _inputStream; + private string _method; + private Stream _inputStream; private HttpListenerContext _context; private bool _isChunked; @@ -180,9 +180,9 @@ internal void FinishInitialization() } string path; - Uri? raw_uri = null; + Uri raw_uri = null; Debug.Assert(_rawUrl != null); - if (MaybeUri(_rawUrl!.ToLowerInvariant()) && Uri.TryCreate(_rawUrl, UriKind.Absolute, out raw_uri)) + if (MaybeUri(_rawUrl.ToLowerInvariant()) && Uri.TryCreate(_rawUrl, UriKind.Absolute, out raw_uri)) path = raw_uri.PathAndQuery; else path = _rawUrl; @@ -193,9 +193,13 @@ internal void FinishInitialization() if (raw_uri != null) host = raw_uri.Host; +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER host = host.Substring(0, ServiceNameStore.FindEndOfHostname(host, 0)); +#else + host = host.Substring(0, ServiceNameStore.FindEndOfHostname(host.AsSpan(), 0)); +#endif - string base_uri = $"{RequestScheme}://{host}:{LocalEndPoint!.Port}"; + string base_uri = $"{RequestScheme}://{host}:{LocalEndPoint.Port}"; if (!Uri.TryCreate(base_uri + path, UriKind.Absolute, out _requestUri)) { @@ -208,7 +212,7 @@ internal void FinishInitialization() if (_version >= HttpVersion.Version11) { - string? t_encoding = Headers[HttpKnownHeaderNames.TransferEncoding]; + string t_encoding = Headers[HttpKnownHeaderNames.TransferEncoding]; _isChunked = (t_encoding != null && string.Equals(t_encoding, "chunked", StringComparison.OrdinalIgnoreCase)); // 'identity' is not valid! if (t_encoding != null && !_isChunked) @@ -329,14 +333,14 @@ internal bool FlushInput() } } - private X509Certificate2? GetClientCertificateCore() => ClientCertificate = _context.Connection.ClientCertificate; + private X509Certificate2 GetClientCertificateCore() => ClientCertificate = _context.Connection.ClientCertificate; private int GetClientCertificateErrorCore() { HttpConnection cnc = _context.Connection; if (cnc.ClientCertificate == null) return 0; - int[]? errors = cnc.ClientCertificateErrors; + int[] errors = cnc.ClientCertificateErrors; if (errors != null && errors.Length > 0) return errors[0]; return 0; @@ -357,7 +361,7 @@ public long ContentLength64 public NameValueCollection Headers => _headers; - public string? HttpMethod => _method; + public string HttpMethod => _method; public Stream InputStream { @@ -379,13 +383,13 @@ public Stream InputStream public bool IsSecureConnection => _context.Connection.IsSecure; - public IPEndPoint? LocalEndPoint => _context.Connection.LocalEndPoint; + public IPEndPoint LocalEndPoint => _context.Connection.LocalEndPoint; - public IPEndPoint? RemoteEndPoint => _context.Connection.RemoteEndPoint; + public IPEndPoint RemoteEndPoint => _context.Connection.RemoteEndPoint; public Guid RequestTraceIdentifier { get; } = Guid.NewGuid(); - private IAsyncResult BeginGetClientCertificateCore(AsyncCallback? requestCallback, object? state) + private IAsyncResult BeginGetClientCertificateCore(AsyncCallback requestCallback, object state) { var asyncResult = new GetClientCertificateAsyncResult(this, state, requestCallback); @@ -397,12 +401,12 @@ private IAsyncResult BeginGetClientCertificateCore(AsyncCallback? requestCallbac return asyncResult; } - public X509Certificate2? EndGetClientCertificate(IAsyncResult asyncResult) + public X509Certificate2 EndGetClientCertificate(IAsyncResult asyncResult) { if (asyncResult == null) throw new ArgumentNullException(nameof(asyncResult)); - GetClientCertificateAsyncResult? clientCertAsyncResult = asyncResult as GetClientCertificateAsyncResult; + GetClientCertificateAsyncResult clientCertAsyncResult = asyncResult as GetClientCertificateAsyncResult; if (clientCertAsyncResult == null || clientCertAsyncResult.AsyncObject != this) { throw new ArgumentException(SR.net_io_invalidasyncresult, nameof(asyncResult)); @@ -413,19 +417,19 @@ private IAsyncResult BeginGetClientCertificateCore(AsyncCallback? requestCallbac } clientCertAsyncResult.EndCalled = true; - return (X509Certificate2?)clientCertAsyncResult.Result; + return (X509Certificate2)clientCertAsyncResult.Result; } - public string? ServiceName => null; + public string ServiceName => null; public TransportContext TransportContext => new Context(); - private Uri? RequestUri => _requestUri; + private Uri RequestUri => _requestUri; private bool SupportsWebSockets => true; private sealed class GetClientCertificateAsyncResult : LazyAsyncResult { - public GetClientCertificateAsyncResult(object myObject, object? myState, AsyncCallback? myCallBack) : base(myObject, myState, myCallBack) { } + public GetClientCertificateAsyncResult(object myObject, object myState, AsyncCallback myCallBack) : base(myObject, myState, myCallBack) { } } } } diff --git a/src/System/Net/Managed/HttpListenerResponse.Managed.cs b/src/System/Net/Managed/HttpListenerResponse.Managed.cs index a818047..319a24e 100644 --- a/src/System/Net/Managed/HttpListenerResponse.Managed.cs +++ b/src/System/Net/Managed/HttpListenerResponse.Managed.cs @@ -56,7 +56,7 @@ private void EnsureResponseStream() { if (_responseStream == null) { - _responseStream = _httpContext!.Connection.GetResponseStream(); + _responseStream = _httpContext.Connection.GetResponseStream(); } } @@ -114,7 +114,7 @@ public void Abort() private void Close(bool force) { Disposed = true; - _httpContext!.Connection.Close(force); + _httpContext.Connection.Close(force); } public void Close(byte[] responseEntity, bool willBlock) @@ -146,7 +146,7 @@ public void Close(byte[] responseEntity, bool willBlock) { OutputStream.BeginWrite(responseEntity, 0, responseEntity.Length, iar => { - var thisRef = (HttpListenerResponse)iar.AsyncState!; + var thisRef = (HttpListenerResponse)iar.AsyncState; try { thisRef.OutputStream.EndWrite(iar); @@ -195,7 +195,7 @@ internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandsha _boundaryType = BoundaryType.Chunked; } - if (CanSendResponseBody(_httpContext!.Response.StatusCode)) + if (CanSendResponseBody(_httpContext.Response.StatusCode)) { _contentLength = -1; } @@ -210,7 +210,7 @@ internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandsha { if (_boundaryType != BoundaryType.ContentLength && closing) { - _contentLength = CanSendResponseBody(_httpContext!.Response.StatusCode) ? -1 : 0; + _contentLength = CanSendResponseBody(_httpContext.Response.StatusCode) ? -1 : 0; } if (_boundaryType == BoundaryType.ContentLength) @@ -235,7 +235,7 @@ internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandsha if (!conn_close) { - conn_close = !_httpContext!.Request.KeepAlive; + conn_close = !_httpContext.Request.KeepAlive; } // They sent both KeepAlive: true and Connection: close @@ -250,7 +250,7 @@ internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandsha _webHeaders.Set(HttpKnownHeaderNames.TransferEncoding, HttpHeaderStrings.Chunked); } - int reuses = _httpContext!.Connection.Reuses; + int reuses = _httpContext.Connection.Reuses; if (reuses >= 100) { _forceCloseChunked = true; @@ -287,7 +287,11 @@ internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandsha writer.Write(FormatHeaders(_webHeaders)); writer.Flush(); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER int preamble = encoding.Preamble.Length; +#else + int preamble = encoding.GetPreamble().Length; +#endif EnsureResponseStream(); /* Assumes that the ms was at position 0 */ @@ -305,7 +309,7 @@ private static string FormatHeaders(WebHeaderCollection headers) for (int i = 0; i < headers.Count; i++) { string key = headers.GetKey(i); - string[] values = headers.GetValues(i)!; + string[] values = headers.GetValues(i); int startingLength = sb.Length; diff --git a/src/System/Net/Managed/HttpRequestStream.Managed.cs b/src/System/Net/Managed/HttpRequestStream.Managed.cs index a033307..f20709a 100644 --- a/src/System/Net/Managed/HttpRequestStream.Managed.cs +++ b/src/System/Net/Managed/HttpRequestStream.Managed.cs @@ -128,7 +128,7 @@ protected virtual int ReadCore(byte[] buffer, int offset, int size) return nread; } - protected virtual IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback? cback, object? state) + protected virtual IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback cback, object state) { if (size == 0 || _closed) { @@ -198,7 +198,11 @@ public override int EndRead(IAsyncResult asyncResult) } catch (IOException e) when (e.InnerException is ArgumentException || e.InnerException is InvalidOperationException) { +#if NET462_OR_GREATER || NETCORE1_0_OR_GREATER ExceptionDispatchInfo.Throw(e.InnerException); +#else + throw e.InnerException; +#endif } if (_remainingBody > 0) diff --git a/src/System/Net/Managed/HttpResponseStream.Managed.cs b/src/System/Net/Managed/HttpResponseStream.Managed.cs index 5a87000..ac311d5 100644 --- a/src/System/Net/Managed/HttpResponseStream.Managed.cs +++ b/src/System/Net/Managed/HttpResponseStream.Managed.cs @@ -57,8 +57,8 @@ internal HttpResponseStream(Stream stream, HttpListenerResponse response, bool i private void DisposeCore() { - byte[]? bytes = null; - MemoryStream? ms = GetHeaders(true); + byte[] bytes = null; + MemoryStream ms = GetHeaders(true); bool chunked = _response.SendChunked; if (_stream.CanWrite) { @@ -98,7 +98,7 @@ internal async Task WriteWebSocketHandshakeHeadersAsync() if (_stream.CanWrite) { - MemoryStream ms = GetHeaders(closing: false, isWebSocketHandshake: true)!; + MemoryStream ms = GetHeaders(closing: false, isWebSocketHandshake: true); bool chunked = _response.SendChunked; long start = ms.Position; @@ -114,7 +114,7 @@ internal async Task WriteWebSocketHandshakeHeadersAsync() } } - private MemoryStream? GetHeaders(bool closing, bool isWebSocketHandshake = false) + private MemoryStream GetHeaders(bool closing, bool isWebSocketHandshake = false) { // SendHeaders works on shared headers lock (_response._headersLock) @@ -167,7 +167,11 @@ internal Task InternalWriteAsync(byte[] buffer, int offset, int count) => private async Task InternalWriteIgnoreErrorsAsync(byte[] buffer, int offset, int count) { +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER try { await _stream.WriteAsync(buffer.AsMemory(offset, count)).ConfigureAwait(false); } +#else + try { await _stream.WriteAsync(buffer, offset, count).ConfigureAwait(false); } +#endif catch { } } @@ -176,8 +180,8 @@ private void WriteCore(byte[] buffer, int offset, int size) if (size == 0) return; - byte[]? bytes = null; - MemoryStream? ms = GetHeaders(false); + byte[] bytes = null; + MemoryStream ms = GetHeaders(false); bool chunked = _response.SendChunked; if (ms != null) { @@ -209,7 +213,7 @@ private void WriteCore(byte[] buffer, int offset, int size) InternalWrite(s_crlf, 0, 2); } - private IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback? cback, object? state) + private IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback cback, object state) { if (_closed) { @@ -232,8 +236,8 @@ private IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCa return ares; } - byte[]? bytes = null; - MemoryStream? ms = GetHeaders(false); + byte[] bytes = null; + MemoryStream ms = GetHeaders(false); bool chunked = _response.SendChunked; if (ms != null) { @@ -312,7 +316,11 @@ private void EndWriteCore(IAsyncResult asyncResult) // wrap the whole thing in an HttpListenerException. This is all to match Windows behavior. if (ex.InnerException is ArgumentException || ex.InnerException is InvalidOperationException) { +#if NET462_OR_GREATER || NETCORE1_0_OR_GREATER ExceptionDispatchInfo.Throw(ex.InnerException); +#else + throw ex.InnerException; +#endif } throw new HttpListenerException(ex.HResult, ex.Message); diff --git a/src/System/Net/Managed/HttpStreamAsyncResult.cs b/src/System/Net/Managed/HttpStreamAsyncResult.cs index b2d2664..f8db458 100644 --- a/src/System/Net/Managed/HttpStreamAsyncResult.cs +++ b/src/System/Net/Managed/HttpStreamAsyncResult.cs @@ -38,17 +38,17 @@ namespace SpaceWizards.HttpListener internal sealed class HttpStreamAsyncResult : IAsyncResult { private object _locker = new object(); - private ManualResetEvent? _handle; + private ManualResetEvent _handle; private bool _completed; internal readonly object _parent; - internal byte[]? _buffer; + internal byte[] _buffer; internal int _offset; internal int _count; - internal AsyncCallback? _callback; - internal object? _state; + internal AsyncCallback _callback; + internal object _state; internal int _synchRead; - internal Exception? _error; + internal Exception _error; internal bool _endCalled; internal HttpStreamAsyncResult(object parent) @@ -78,7 +78,7 @@ public void Complete() } } - public object? AsyncState + public object AsyncState { get { return _state; } } diff --git a/src/System/Net/Managed/ListenerAsyncResult.Managed.cs b/src/System/Net/Managed/ListenerAsyncResult.Managed.cs index 468118d..d1763c9 100644 --- a/src/System/Net/Managed/ListenerAsyncResult.Managed.cs +++ b/src/System/Net/Managed/ListenerAsyncResult.Managed.cs @@ -40,20 +40,20 @@ namespace SpaceWizards.HttpListener { internal sealed class ListenerAsyncResult : IAsyncResult { - private ManualResetEvent? _handle; + private ManualResetEvent _handle; private bool _synch; private bool _completed; - private AsyncCallback? _cb; - private object? _state; - private Exception? _exception; - private HttpListenerContext? _context; + private AsyncCallback _cb; + private object _state; + private Exception _exception; + private HttpListenerContext _context; private object _locker = new object(); - private ListenerAsyncResult? _forward; + private ListenerAsyncResult _forward; internal readonly HttpListener _parent; internal bool _endCalled; internal bool _inGet; - public ListenerAsyncResult(HttpListener parent, AsyncCallback? cb, object? state) + public ListenerAsyncResult(HttpListener parent, AsyncCallback cb, object state) { _parent = parent; _cb = cb; @@ -81,10 +81,10 @@ internal void Complete(Exception exc) } } - private static WaitCallback s_invokeCB = new WaitCallback(InvokeCallback!); + private static WaitCallback s_invokeCB = new WaitCallback(InvokeCallback); private static void InvokeCallback(object o) { - ListenerAsyncResult ares = (ListenerAsyncResult)o!; + ListenerAsyncResult ares = (ListenerAsyncResult)o; if (ares._forward != null) { InvokeCallback(ares._forward); @@ -92,7 +92,7 @@ private static void InvokeCallback(object o) } try { - ares._cb!(ares); + ares._cb(ares); } catch { @@ -118,7 +118,7 @@ internal void Complete(HttpListenerContext context, bool synch) bool authFailure = false; try { - context.AuthenticationSchemes = context._listener!.SelectAuthenticationScheme(context); + context.AuthenticationSchemes = context._listener.SelectAuthenticationScheme(context); } catch (OutOfMemoryException oom) { @@ -141,7 +141,7 @@ internal void Complete(HttpListenerContext context, bool synch) else if (context.AuthenticationSchemes == AuthenticationSchemes.Basic) { HttpStatusCode errorCode = HttpStatusCode.Unauthorized; - string? authHeader = context.Request.Headers["Authorization"]; + string authHeader = context.Request.Headers["Authorization"]; if (authHeader == null || !HttpListenerContext.IsBasicHeader(authHeader) || authHeader.Length < AuthenticationTypes.Basic.Length + 2 || @@ -151,7 +151,7 @@ internal void Complete(HttpListenerContext context, bool synch) context.Response.StatusCode = (int)errorCode; if (errorCode == HttpStatusCode.Unauthorized) { - context.Response.Headers["WWW-Authenticate"] = context.AuthenticationSchemes + " realm=\"" + context._listener!.Realm + "\""; + context.Response.Headers["WWW-Authenticate"] = context.AuthenticationSchemes + " realm=\"" + context._listener.Realm + "\""; } } } @@ -159,7 +159,7 @@ internal void Complete(HttpListenerContext context, bool synch) if (authFailure) { context.Response.OutputStream.Close(); - IAsyncResult ares = context._listener!.BeginGetContext(_cb, _state); + IAsyncResult ares = context._listener.BeginGetContext(_cb, _state); _forward = (ListenerAsyncResult)ares; lock (_forward._locker) { @@ -188,7 +188,7 @@ internal void Complete(HttpListenerContext context, bool synch) } } - internal HttpListenerContext? GetContext() + internal HttpListenerContext GetContext() { if (_forward != null) { @@ -197,13 +197,17 @@ internal void Complete(HttpListenerContext context, bool synch) if (_exception != null) { +#if NET462_OR_GREATER || NETCORE1_0_OR_GREATER ExceptionDispatchInfo.Throw(_exception); +#else + throw _exception; +#endif } return _context; } - public object? AsyncState + public object AsyncState { get { diff --git a/src/System/Net/Managed/ListenerPrefix.cs b/src/System/Net/Managed/ListenerPrefix.cs index e2a8c8b..eea5a56 100644 --- a/src/System/Net/Managed/ListenerPrefix.cs +++ b/src/System/Net/Managed/ListenerPrefix.cs @@ -31,7 +31,9 @@ // using System; +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER using System.Diagnostics.CodeAnalysis; +#endif using System.Net; namespace SpaceWizards.HttpListener @@ -39,12 +41,12 @@ namespace SpaceWizards.HttpListener internal sealed class ListenerPrefix { private string _original; - private string? _host; + private string _host; private ushort _port; - private string? _path; + private string _path; private bool _secure; - private IPAddress[]? _addresses; - internal HttpListener? _listener; + private IPAddress[] _addresses; + internal HttpListener _listener; public ListenerPrefix(string prefix) { @@ -57,7 +59,7 @@ public override string ToString() return _original; } - public IPAddress[]? Addresses + public IPAddress[] Addresses { get { return _addresses; } set { _addresses = value; } @@ -67,7 +69,7 @@ public bool Secure get { return _secure; } } - public string? Host + public string Host { get { return _host; } } @@ -77,15 +79,19 @@ public int Port get { return _port; } } - public string? Path + public string Path { get { return _path; } } // Equals and GetHashCode are required to detect duplicates in HttpListenerPrefixCollection. - public override bool Equals([NotNullWhen(true)] object? o) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER + public override bool Equals([NotNullWhen(true)] object o) +#else + public override bool Equals(object o) +#endif { - ListenerPrefix? other = o as ListenerPrefix; + ListenerPrefix other = o as ListenerPrefix; if (other == null) return false; @@ -111,13 +117,21 @@ private void Parse(string uri) if (start_host >= length) throw new ArgumentException(SR.net_listener_host); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER int end_host = ServiceNameStore.FindEndOfHostname(uri, start_host); +#else + int end_host = ServiceNameStore.FindEndOfHostname(uri.AsSpan(), start_host); +#endif int root; if (uri[end_host] == ':') { _host = uri.Substring(start_host, end_host - start_host); root = uri.IndexOf('/', end_host, length - end_host); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER _port = (ushort)int.Parse(uri.AsSpan(end_host + 1, root - end_host - 1)); +#else + _port = (ushort)int.Parse(uri.AsSpan(end_host + 1, root - end_host - 1).ToString()); +#endif _path = uri.Substring(root); } else diff --git a/src/System/Net/Managed/WebSockets/HttpWebSocket.Managed.cs b/src/System/Net/Managed/WebSockets/HttpWebSocket.Managed.cs index 18db7a1..eb2b9cb 100644 --- a/src/System/Net/Managed/WebSockets/HttpWebSocket.Managed.cs +++ b/src/System/Net/Managed/WebSockets/HttpWebSocket.Managed.cs @@ -1,6 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER using System; using System.Net; using System.Net.WebSockets; @@ -13,7 +13,7 @@ internal static partial class HttpWebSocket private const string SupportedVersion = "13"; internal static async Task AcceptWebSocketAsyncCore(HttpListenerContext context, - string? subProtocol, + string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment? internalBuffer = null) @@ -25,12 +25,12 @@ internal static async Task AcceptWebSocketAsyncCor HttpListenerRequest request = context.Request; ValidateWebSocketHeaders(context); - string? secWebSocketVersion = request.Headers[HttpKnownHeaderNames.SecWebSocketVersion]; + string secWebSocketVersion = request.Headers[HttpKnownHeaderNames.SecWebSocketVersion]; // Optional for non-browser client - string? origin = request.Headers[HttpKnownHeaderNames.Origin]; + string origin = request.Headers[HttpKnownHeaderNames.Origin]; - string[]? secWebSocketProtocols = null; + string[] secWebSocketProtocols = null; string outgoingSecWebSocketProtocolString; bool shouldSendSecWebSocketProtocolHeader = ProcessWebSocketProtocolHeader( @@ -45,35 +45,35 @@ internal static async Task AcceptWebSocketAsyncCor } // negotiate the websocket key return value - string? secWebSocketKey = request.Headers[HttpKnownHeaderNames.SecWebSocketKey]; - string secWebSocketAccept = HttpWebSocket.GetSecWebSocketAcceptString(secWebSocketKey); + string secWebSocketKey = request.Headers[HttpKnownHeaderNames.SecWebSocketKey]; + string secWebSocketAccept = GetSecWebSocketAcceptString(secWebSocketKey); response.Headers.Add(HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade); response.Headers.Add(HttpKnownHeaderNames.Upgrade, WebSocketUpgradeToken); response.Headers.Add(HttpKnownHeaderNames.SecWebSocketAccept, secWebSocketAccept); response.StatusCode = (int)HttpStatusCode.SwitchingProtocols; // HTTP 101 - response.StatusDescription = HttpStatusDescription.Get(HttpStatusCode.SwitchingProtocols)!; + response.StatusDescription = HttpStatusDescription.Get(HttpStatusCode.SwitchingProtocols); - HttpResponseStream responseStream = (response.OutputStream as HttpResponseStream)!; + HttpResponseStream responseStream = (response.OutputStream as HttpResponseStream); // Send websocket handshake headers await responseStream.WriteWebSocketHandshakeHeadersAsync().ConfigureAwait(false); - WebSocket webSocket = WebSocket.CreateFromStream(context.Connection.ConnectedStream, isServer:true, subProtocol, keepAliveInterval); + WebSocket webSocket = WebSocket.CreateFromStream(context.Connection.ConnectedStream, isServer: true, subProtocol, keepAliveInterval); HttpListenerWebSocketContext webSocketContext = new HttpListenerWebSocketContext( - request.Url!, + request.Url, request.Headers, request.Cookies, - context.User!, + context.User, request.IsAuthenticated, request.IsLocal, request.IsSecureConnection, - origin!, + origin, secWebSocketProtocols != null ? secWebSocketProtocols : Array.Empty(), - secWebSocketVersion!, - secWebSocketKey!, + secWebSocketVersion, + secWebSocketKey, webSocket); return webSocketContext; @@ -82,3 +82,4 @@ internal static async Task AcceptWebSocketAsyncCor private const bool WebSocketsSupported = true; } } +#endif \ No newline at end of file diff --git a/src/System/Net/ServiceNameStore.cs b/src/System/Net/ServiceNameStore.cs index d3e1a43..66b0f88 100644 --- a/src/System/Net/ServiceNameStore.cs +++ b/src/System/Net/ServiceNameStore.cs @@ -13,7 +13,7 @@ namespace SpaceWizards.HttpListener internal sealed class ServiceNameStore { private readonly List _serviceNames; - private ServiceNameCollection? _serviceNameCollection; + private ServiceNameCollection _serviceNameCollection; public ServiceNameCollection ServiceNames { @@ -33,7 +33,7 @@ public ServiceNameStore() _serviceNameCollection = null; // set only when needed (due to expensive item-by-item copy) } - private static string? NormalizeServiceName(string? inputServiceName) + private static string NormalizeServiceName(string inputServiceName) { if (string.IsNullOrWhiteSpace(inputServiceName)) { @@ -109,7 +109,7 @@ public ServiceNameStore() // Now we have a valid DNS host, normalize it. - Uri? constructedUri; + Uri constructedUri; // This shouldn't fail, but we need to avoid any unexpected exceptions on this code path. if (!Uri.TryCreate(Uri.UriSchemeHttp + Uri.SchemeDelimiter + host, UriKind.Absolute, out constructedUri)) { @@ -132,7 +132,7 @@ public ServiceNameStore() private bool AddSingleServiceName(string spn) { - spn = NormalizeServiceName(spn)!; + spn = NormalizeServiceName(spn); if (Contains(spn)) { return false; @@ -177,13 +177,13 @@ public bool Remove(string uriPrefix) { Debug.Assert(!string.IsNullOrEmpty(uriPrefix)); - string? newServiceName = BuildSimpleServiceName(uriPrefix); + string newServiceName = BuildSimpleServiceName(uriPrefix); newServiceName = NormalizeServiceName(newServiceName); bool needToRemove = Contains(newServiceName); if (needToRemove) { - _serviceNames.Remove(newServiceName!); + _serviceNames.Remove(newServiceName); _serviceNameCollection = null; //invalidate (readonly) ServiceNameCollection } @@ -203,7 +203,7 @@ public bool Remove(string uriPrefix) } // Assumes already normalized - private bool Contains(string? newServiceName) + private bool Contains(string newServiceName) { if (newServiceName == null) { @@ -227,7 +227,7 @@ public void Clear() _serviceNameCollection = null; //invalidate (readonly) ServiceNameCollection } - private string? ExtractHostname(string uriPrefix, bool allowInvalidUriStrings) + private string ExtractHostname(string uriPrefix, bool allowInvalidUriStrings) { if (Uri.IsWellFormedUriString(uriPrefix, UriKind.Absolute)) { @@ -237,7 +237,12 @@ public void Clear() else if (allowInvalidUriStrings) { int i = uriPrefix.IndexOf("://", StringComparison.Ordinal) + 3; + +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER int j = FindEndOfHostname(uriPrefix, i); +#else + int j = FindEndOfHostname(uriPrefix.AsSpan(), i); +#endif return uriPrefix.Substring(i, j - i); } @@ -271,9 +276,9 @@ internal static int FindEndOfHostname(ReadOnlySpan uriPrefix, int i) return j; } - public string? BuildSimpleServiceName(string uriPrefix) + public string BuildSimpleServiceName(string uriPrefix) { - string? hostname = ExtractHostname(uriPrefix, false); + string hostname = ExtractHostname(uriPrefix, false); if (hostname != null) { @@ -287,9 +292,9 @@ internal static int FindEndOfHostname(ReadOnlySpan uriPrefix, int i) public string[] BuildServiceNames(string uriPrefix) { - string hostname = ExtractHostname(uriPrefix, true)!; + string hostname = ExtractHostname(uriPrefix, true); - IPAddress? ipAddress = null; + IPAddress ipAddress = null; if (string.Equals(hostname, "*", StringComparison.OrdinalIgnoreCase) || string.Equals(hostname, "+", StringComparison.OrdinalIgnoreCase) || IPAddress.TryParse(hostname, out ipAddress)) @@ -310,7 +315,7 @@ public string[] BuildServiceNames(string uriPrefix) return Array.Empty(); } } - else if (!hostname.Contains('.')) + else if (!hostname.Contains(".")) { // for a dotless name, try to resolve the FQDN. If the caller doesn't have DNS permission // or the query fails for some reason, add only the dotless name. diff --git a/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs b/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs index d08b824..6440447 100644 --- a/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs +++ b/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs @@ -52,7 +52,7 @@ internal HttpListenerWebSocketContext( _cookieCollection.Add(cookieCollection); _headers = new NameValueCollection(headers); - _user = CopyPrincipal(user)!; + _user = CopyPrincipal(user); _requestUri = requestUri; _isAuthenticated = isAuthenticated; @@ -89,7 +89,7 @@ internal HttpListenerWebSocketContext( public override WebSocket WebSocket => _webSocket; - private static IPrincipal? CopyPrincipal(IPrincipal user) + private static IPrincipal CopyPrincipal(IPrincipal user) { if (user != null) { diff --git a/src/System/Net/WebSockets/HttpWebSocket.cs b/src/System/Net/WebSockets/HttpWebSocket.cs index f1d08cb..f44c381 100644 --- a/src/System/Net/WebSockets/HttpWebSocket.cs +++ b/src/System/Net/WebSockets/HttpWebSocket.cs @@ -2,8 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +#if !NET5_0_OR_GREATER +using System.Collections.Generic; +#endif using System.Diagnostics.CodeAnalysis; +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER using System.Net; +#endif using System.Net.WebSockets; using System.Security.Cryptography; using System.Text; @@ -19,7 +24,7 @@ internal static partial class HttpWebSocket internal const int DefaultClientSendBufferSize = 16 * 1024; [SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 used only for hashing purposes, not for crypto.")] - internal static string GetSecWebSocketAcceptString(string? secWebSocketKey) + internal static string GetSecWebSocketAcceptString(string secWebSocketKey) { string acceptString = string.Concat(secWebSocketKey, HttpWebSocket.SecWebSocketKeyGuid); byte[] toHash = Encoding.UTF8.GetBytes(acceptString); @@ -32,8 +37,8 @@ internal static string GetSecWebSocketAcceptString(string? secWebSocketKey) } // return value here signifies if a Sec-WebSocket-Protocol header should be returned by the server. - internal static bool ProcessWebSocketProtocolHeader(string? clientSecWebSocketProtocol, - string? subProtocol, + internal static bool ProcessWebSocketProtocolHeader(string clientSecWebSocketProtocol, + string subProtocol, out string acceptProtocol) { acceptProtocol = string.Empty; @@ -62,7 +67,7 @@ internal static bool ProcessWebSocketProtocolHeader(string? clientSecWebSocketPr // and the server has specified exactly one protocol #if NET5_0_OR_GREATER string[] requestProtocols = clientSecWebSocketProtocol.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); -#else +#elif NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER string[] rawRequestProtocols = clientSecWebSocketProtocol.Split(',', StringSplitOptions.RemoveEmptyEntries); string[] requestProtocols = new string[rawRequestProtocols.Length]; @@ -70,6 +75,18 @@ internal static bool ProcessWebSocketProtocolHeader(string? clientSecWebSocketPr { requestProtocols[i] = rawRequestProtocols[i].Trim(); } +#else + string[] rawRequestProtocols = clientSecWebSocketProtocol.Split(','); + List requestProtocolsList = new List(); + foreach (string protocol in rawRequestProtocols) + { + string trimmedProtocol = protocol.Trim(); + if (!string.IsNullOrEmpty(trimmedProtocol)) + { + requestProtocolsList.Add(trimmedProtocol); + } + } + string[] requestProtocols = requestProtocolsList.ToArray(); #endif acceptProtocol = subProtocol; @@ -90,7 +107,7 @@ internal static bool ProcessWebSocketProtocolHeader(string? clientSecWebSocketPr subProtocol)); } - internal static void ValidateOptions(string? subProtocol, int receiveBufferSize, int sendBufferSize, TimeSpan keepAliveInterval) + internal static void ValidateOptions(string subProtocol, int receiveBufferSize, int sendBufferSize, TimeSpan keepAliveInterval) { if (subProtocol != null) { @@ -138,6 +155,7 @@ internal static void ValidateOptions(string? subProtocol, int receiveBufferSize, internal const int MinReceiveBufferSize = 256; internal const int MaxBufferSize = 64 * 1024; +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER private static void ValidateWebSocketHeaders(HttpListenerContext context) { if (!WebSocketsSupported) @@ -152,7 +170,7 @@ private static void ValidateWebSocketHeaders(HttpListenerContext context) nameof(ValidateWebSocketHeaders), HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade, - HttpWebSocket.WebSocketUpgradeToken, + WebSocketUpgradeToken, context.Request.Headers[HttpKnownHeaderNames.Upgrade])); } @@ -196,5 +214,6 @@ private static void ValidateWebSocketHeaders(HttpListenerContext context) HttpKnownHeaderNames.SecWebSocketKey)); } } +#endif } } diff --git a/src/System/Net/Windows/CookieExtensions.cs b/src/System/Net/Windows/CookieExtensions.cs index 9af2442..ee71d65 100644 --- a/src/System/Net/Windows/CookieExtensions.cs +++ b/src/System/Net/Windows/CookieExtensions.cs @@ -12,20 +12,26 @@ namespace SpaceWizards.HttpListener // TODO https://github.com/dotnet/runtime/issues/19348 internal static class CookieExtensions { - private static Func? s_toServerStringFunc; + private static Func s_toServerStringFunc; public static string ToServerString(this Cookie cookie) { - s_toServerStringFunc ??= (Func)typeof(Cookie).GetMethod("ToServerString", BindingFlags.Instance | BindingFlags.NonPublic)!.CreateDelegate(typeof(Func)); + if (s_toServerStringFunc == null) + { + s_toServerStringFunc = (Func)typeof(Cookie).GetMethod("ToServerString", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(Func)); + } Debug.Assert(s_toServerStringFunc != null, "Reflection failed for Cookie.ToServerString()."); return s_toServerStringFunc(cookie); } - private static Func? s_cloneFunc; + private static Func s_cloneFunc; public static Cookie Clone(this Cookie cookie) { - s_cloneFunc ??= (Func)typeof(Cookie).GetMethod("Clone", BindingFlags.Instance | BindingFlags.NonPublic)!.CreateDelegate(typeof(Func)); + if (s_cloneFunc == null) + { + s_cloneFunc = (Func)typeof(Cookie).GetMethod("Clone", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(Func)); + } Debug.Assert(s_cloneFunc != null, "Reflection failed for Cookie.Clone()."); return s_cloneFunc(cookie); } @@ -39,11 +45,14 @@ private enum CookieVariant Default = Rfc2109 } - private static Func? s_getVariantFunc; + private static Func s_getVariantFunc; public static bool IsRfc2965Variant(this Cookie cookie) { - s_getVariantFunc ??= (Func)typeof(Cookie).GetProperty("Variant", BindingFlags.Instance | BindingFlags.NonPublic)!.GetGetMethod(true)!.CreateDelegate(typeof(Func)); + if (s_getVariantFunc == null) + { + s_getVariantFunc = (Func)typeof(Cookie).GetProperty("Variant", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true).CreateDelegate(typeof(Func)); + } Debug.Assert(s_getVariantFunc != null, "Reflection failed for Cookie.Variant."); return s_getVariantFunc(cookie) == CookieVariant.Rfc2965; } @@ -51,11 +60,14 @@ public static bool IsRfc2965Variant(this Cookie cookie) internal static class CookieCollectionExtensions { - private static Func? s_internalAddFunc; + private static Func s_internalAddFunc; public static int InternalAdd(this CookieCollection cookieCollection, Cookie cookie, bool isStrict) { - s_internalAddFunc ??= (Func)typeof(CookieCollection).GetMethod("InternalAdd", BindingFlags.Instance | BindingFlags.NonPublic)!.CreateDelegate(typeof(Func)); + if (s_internalAddFunc == null) + { + s_internalAddFunc = (Func)typeof(CookieCollection).GetMethod("InternalAdd", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(Func)); + } Debug.Assert(s_internalAddFunc != null, "Reflection failed for CookieCollection.InternalAdd()."); return s_internalAddFunc(cookieCollection, cookie, isStrict); }