From 361caff1adf2301bcadc1de5bd1d709720a6c7c2 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 3 May 2018 17:18:33 -0700 Subject: [PATCH 1/2] Remove managed InProcess code (#809) --- samples/NativeIISSample/Startup.cs | 21 - .../IISHttpContextExtensions.cs | 38 -- .../IServerVariablesFeature.cs | 24 - .../NativeMethods.cs | 254 --------- .../Server/DuplexStream.cs | 69 --- .../Server/IISAwaitable.cs | 119 ---- .../Server/IISConfigurationData.cs | 19 - .../IISHttpContext.FeatureCollection.cs | 276 ---------- .../Server/IISHttpContext.Features.cs | 336 ------------ .../IISHttpContext.IHttpConnectionFeature.cs | 100 ---- ...tpContext.IHttpRequestIdentifierFeature.cs | 38 -- .../Server/IISHttpContext.ReadWrite.cs | 475 ---------------- .../Server/IISHttpContext.Websockets.cs | 225 -------- .../Server/IISHttpContext.cs | 514 ------------------ .../Server/IISHttpContextOfT.cs | 99 ---- .../Server/IISHttpRequestBody.cs | 62 --- .../Server/IISHttpResponseBody.cs | 65 --- .../Server/IISHttpServer.cs | 229 -------- .../Server/IISServerAuthenticationHandler.cs | 58 -- .../Server/IISServerConstants.cs | 10 - .../Server/IISServerSetupFilter.cs | 36 -- .../Server/OutputProducer.cs | 149 ----- .../WebHostBuilderIISExtensions.cs | 25 - .../Inprocess/AuthenticationTests.cs | 67 --- .../Inprocess/EnvironmentVariableTests.cs | 51 -- .../Inprocess/FeatureCollectionTests.cs | 30 - .../Inprocess/HelloWorldTests.cs | 31 -- .../InvalidReadWriteOperationTests.cs | 84 --- .../Inprocess/LargeResponseBodyTests.cs | 36 -- .../Inprocess/ResponseHeaderTests.cs | 64 --- .../Inprocess/ResponseInvalidOrderingTests.cs | 28 - .../Inprocess/ServerVariablesTest.cs | 40 -- .../Inprocess/StartupTests.cs | 234 -------- .../Inprocess/SynchronousReadAndWriteTests.cs | 125 ----- .../UpgradeFeatureDetectionTests.cs | 22 +- 35 files changed, 1 insertion(+), 4052 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/IISHttpContextExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/IServerVariablesFeature.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/DuplexStream.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISAwaitable.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISConfigurationData.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.FeatureCollection.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Features.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpConnectionFeature.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpRequestIdentifierFeature.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.ReadWrite.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Websockets.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContextOfT.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpRequestBody.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpResponseBody.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpServer.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerAuthenticationHandler.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerConstants.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerSetupFilter.cs delete mode 100644 src/Microsoft.AspNetCore.Server.IISIntegration/Server/OutputProducer.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/AuthenticationTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/EnvironmentVariableTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/FeatureCollectionTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/HelloWorldTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/LargeResponseBodyTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/ResponseHeaderTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/ServerVariablesTest.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs delete mode 100644 test/IISIntegration.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs diff --git a/samples/NativeIISSample/Startup.cs b/samples/NativeIISSample/Startup.cs index 1a41f5a848..d36f26908d 100644 --- a/samples/NativeIISSample/Startup.cs +++ b/samples/NativeIISSample/Startup.cs @@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Server.IIS; using Microsoft.AspNetCore.Server.IISIntegration; namespace NativeIISSample @@ -66,12 +65,6 @@ namespace NativeIISSample // accessing IIS server variables await context.Response.WriteAsync("Server Variables:" + Environment.NewLine); - foreach (var varName in IISServerVarNames) - { - await context.Response.WriteAsync(varName + ": " + context.GetIISServerVariable(varName) + Environment.NewLine); - } - - await context.Response.WriteAsync(Environment.NewLine); if (context.Features.Get() != null) { await context.Response.WriteAsync("Websocket feature is enabled."); @@ -82,20 +75,6 @@ namespace NativeIISSample } }); } - - private static readonly string[] IISServerVarNames = - { - "AUTH_TYPE", - "AUTH_USER", - "CONTENT_TYPE", - "HTTP_HOST", - "HTTPS", - "REMOTE_PORT", - "REMOTE_USER", - "REQUEST_METHOD", - "WEBSOCKET_VERSION" - }; - public static void Main(string[] args) { var host = new WebHostBuilder() diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/IISHttpContextExtensions.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/IISHttpContextExtensions.cs deleted file mode 100644 index fd72e9d00f..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/IISHttpContextExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; - -namespace Microsoft.AspNetCore.Server.IIS -{ - /// - /// Extensions to that enable access to IIS features. - /// - public static class IISHttpContextExtensions - { - /// - /// Gets the value of a server variable for the current request. - /// - /// The http context for the request. - /// The name of the variable. - /// - /// null if the feature does not support the feature. - /// May return null or empty if the variable does not exist or is not set. - /// - /// - /// For a list of common server variables available in IIS, see http://go.microsoft.com/fwlink/?LinkId=52471. - /// - public static string GetIISServerVariable(this HttpContext context, string variableName) - { - var feature = context.Features.Get(); - - if (feature == null) - { - return null; - } - - return feature[variableName]; - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/IServerVariablesFeature.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/IServerVariablesFeature.cs deleted file mode 100644 index 3b54733a03..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/IServerVariablesFeature.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Http.Features -{ - /// - /// This feature provides access to request server variables set. - /// - /// This feature is only available when hosting ASP.NET Core in-process with IIS or IIS Express. - /// - /// - /// - /// For a list of common server variables available in IIS, see http://go.microsoft.com/fwlink/?LinkId=52471. - /// - public interface IServerVariablesFeature - { - /// - /// Gets the value of a server variable for the current request. - /// - /// The variable name - /// May return null or empty if the variable does not exist or is not set. - string this[string variableName] { get; } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/NativeMethods.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/NativeMethods.cs index eef84d69b8..4ecb5018a2 100644 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/NativeMethods.cs +++ b/src/Microsoft.AspNetCore.Server.IISIntegration/NativeMethods.cs @@ -9,264 +9,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration { internal static class NativeMethods { - private const int HR_NOT_FOUND = unchecked((int)0x80070490); - private const int HR_OK = 0; - private const string KERNEL32 = "kernel32.dll"; - private const string AspNetCoreModuleDll = "aspnetcorerh.dll"; - [DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)] public static extern bool CloseHandle(IntPtr handle); - - - [DllImport("kernel32.dll")] - private static extern IntPtr GetModuleHandle(string lpModuleName); - - public static bool IsAspNetCoreModuleLoaded() - { - return GetModuleHandle(AspNetCoreModuleDll) != IntPtr.Zero; - } - - public enum REQUEST_NOTIFICATION_STATUS - { - RQ_NOTIFICATION_CONTINUE, - RQ_NOTIFICATION_PENDING, - RQ_NOTIFICATION_FINISH_REQUEST - } - - public delegate REQUEST_NOTIFICATION_STATUS PFN_REQUEST_HANDLER(IntPtr pInProcessHandler, IntPtr pvRequestContext); - public delegate bool PFN_SHUTDOWN_HANDLER(IntPtr pvRequestContext); - public delegate REQUEST_NOTIFICATION_STATUS PFN_ASYNC_COMPLETION(IntPtr pvManagedHttpContext, int hr, int bytes); - public delegate REQUEST_NOTIFICATION_STATUS PFN_WEBSOCKET_ASYNC_COMPLETION(IntPtr pInProcessHandler, IntPtr completionInfo, IntPtr pvCompletionContext); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_post_completion(IntPtr pInProcessHandler, int cbBytes); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_set_completion_status(IntPtr pInProcessHandler, REQUEST_NOTIFICATION_STATUS rquestNotificationStatus); - - [DllImport(AspNetCoreModuleDll)] - private static extern void http_indicate_completion(IntPtr pInProcessHandler, REQUEST_NOTIFICATION_STATUS notificationStatus); - - [DllImport(AspNetCoreModuleDll)] - private static extern void register_callbacks(PFN_REQUEST_HANDLER request_callback, PFN_SHUTDOWN_HANDLER shutdown_callback, PFN_ASYNC_COMPLETION managed_context_handler, IntPtr pvRequestContext, IntPtr pvShutdownContext); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe int http_write_response_bytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_flush_response_bytes(IntPtr pInProcessHandler, out bool fCompletionExpected); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe HttpApiTypes.HTTP_REQUEST_V2* http_get_raw_request(IntPtr pInProcessHandler); - - [DllImport(AspNetCoreModuleDll)] - private static extern void http_stop_calls_into_managed(); - - [DllImport(AspNetCoreModuleDll)] - private static extern void http_stop_incoming_requests(); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe HttpApiTypes.HTTP_RESPONSE_V2* http_get_raw_response(IntPtr pInProcessHandler); - - [DllImport(AspNetCoreModuleDll, CharSet = CharSet.Ansi)] - private static extern int http_set_response_status_code(IntPtr pInProcessHandler, ushort statusCode, string pszReason); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe int http_read_request_bytes(IntPtr pInProcessHandler, byte* pvBuffer, int cbBuffer, out int dwBytesReceived, out bool fCompletionExpected); - - [DllImport(AspNetCoreModuleDll)] - private static extern void http_get_completion_info(IntPtr pCompletionInfo, out int cbBytes, out int hr); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_set_managed_context(IntPtr pInProcessHandler, IntPtr pvManagedContext); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_get_server_variable( - IntPtr pInProcessHandler, - [MarshalAs(UnmanagedType.LPStr)] string variableName, - [MarshalAs(UnmanagedType.BStr)] out string value); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe int http_websockets_read_bytes( - IntPtr pInProcessHandler, - byte* pvBuffer, - int cbBuffer, - PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback, - IntPtr pvCompletionContext, - out int dwBytesReceived, - out bool fCompletionExpected); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe int http_websockets_write_bytes( - IntPtr pInProcessHandler, - HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, - int nChunks, - PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback, - IntPtr pvCompletionContext, - out bool fCompletionExpected); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_enable_websockets(IntPtr pInProcessHandler); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_cancel_io(IntPtr pInProcessHandler); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe int http_response_set_unknown_header(IntPtr pInProcessHandler, byte* pszHeaderName, byte* pszHeaderValue, ushort usHeaderValueLength, bool fReplace); - - [DllImport(AspNetCoreModuleDll)] - private static extern unsafe int http_response_set_known_header(IntPtr pInProcessHandler, int headerId, byte* pHeaderValue, ushort length, bool fReplace); - - [DllImport(AspNetCoreModuleDll)] - private static extern int http_get_authentication_information(IntPtr pInProcessHandler, [MarshalAs(UnmanagedType.BStr)] out string authType, out IntPtr token); - - public static void HttpPostCompletion(IntPtr pInProcessHandler, int cbBytes) - { - Validate(http_post_completion(pInProcessHandler, cbBytes)); - } - - public static void HttpSetCompletionStatus(IntPtr pInProcessHandler, REQUEST_NOTIFICATION_STATUS rquestNotificationStatus) - { - Validate(http_set_completion_status(pInProcessHandler, rquestNotificationStatus)); - } - - public static void HttpIndicateCompletion(IntPtr pInProcessHandler, REQUEST_NOTIFICATION_STATUS notificationStatus) - { - http_indicate_completion(pInProcessHandler, notificationStatus); - } - public static void HttpRegisterCallbacks(PFN_REQUEST_HANDLER request_callback, PFN_SHUTDOWN_HANDLER shutdown_callback, PFN_ASYNC_COMPLETION managed_context_handler, IntPtr pvRequestContext, IntPtr pvShutdownContext) - { - register_callbacks(request_callback, shutdown_callback, managed_context_handler, pvRequestContext, pvShutdownContext); - } - - public static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected) - { - return http_write_response_bytes(pInProcessHandler, pDataChunks, nChunks, out fCompletionExpected); - } - - public static int HttpFlushResponseBytes(IntPtr pInProcessHandler, out bool fCompletionExpected) - { - return http_flush_response_bytes(pInProcessHandler, out fCompletionExpected); - } - public static unsafe HttpApiTypes.HTTP_REQUEST_V2* HttpGetRawRequest(IntPtr pInProcessHandler) - { - return http_get_raw_request(pInProcessHandler); - } - - public static void HttpStopCallsIntoManaged() - { - http_stop_calls_into_managed(); - } - - public static void HttpStopIncomingRequests() - { - http_stop_incoming_requests(); - } - - public static unsafe HttpApiTypes.HTTP_RESPONSE_V2* HttpGetRawResponse(IntPtr pInProcessHandler) - { - return http_get_raw_response(pInProcessHandler); - } - - public static void HttpSetResponseStatusCode(IntPtr pInProcessHandler, ushort statusCode, string pszReason) - { - Validate(http_set_response_status_code(pInProcessHandler, statusCode, pszReason)); - } - - public static unsafe int HttpReadRequestBytes(IntPtr pInProcessHandler, byte* pvBuffer, int cbBuffer, out int dwBytesReceived, out bool fCompletionExpected) - { - return http_read_request_bytes(pInProcessHandler, pvBuffer, cbBuffer, out dwBytesReceived, out fCompletionExpected); - } - - public static void HttpGetCompletionInfo(IntPtr pCompletionInfo, out int cbBytes, out int hr) - { - http_get_completion_info(pCompletionInfo, out cbBytes, out hr); - } - - public static void HttpSetManagedContext(IntPtr pInProcessHandler, IntPtr pvManagedContext) - { - Validate(http_set_managed_context(pInProcessHandler, pvManagedContext)); - } - - public static IISConfigurationData HttpGetApplicationProperties() - { - var iisConfigurationData = new IISConfigurationData(); - Validate(http_get_application_properties(ref iisConfigurationData)); - return iisConfigurationData; - } - - public static bool HttpTryGetServerVariable(IntPtr pInProcessHandler, string variableName, out string value) - { - return http_get_server_variable(pInProcessHandler, variableName, out value) == 0; - } - - public static unsafe int HttpWebsocketsReadBytes( - IntPtr pInProcessHandler, - byte* pvBuffer, - int cbBuffer, - PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback, - IntPtr pvCompletionContext, out int dwBytesReceived, - out bool fCompletionExpected) - { - return http_websockets_read_bytes(pInProcessHandler, pvBuffer, cbBuffer, pfnCompletionCallback, pvCompletionContext, out dwBytesReceived, out fCompletionExpected); - } - - public static unsafe int HttpWebsocketsWriteBytes( - IntPtr pInProcessHandler, - HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, - int nChunks, - PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback, - IntPtr pvCompletionContext, - out bool fCompletionExpected) - { - return http_websockets_write_bytes(pInProcessHandler, pDataChunks, nChunks, pfnCompletionCallback, pvCompletionContext, out fCompletionExpected); - } - - public static void HttpEnableWebsockets(IntPtr pInProcessHandler) - { - Validate(http_enable_websockets(pInProcessHandler)); - } - - public static bool HttpTryCancelIO(IntPtr pInProcessHandler) - { - var hr = http_cancel_io(pInProcessHandler); - // Async operation finished - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363792(v=vs.85).aspx - if (hr == HR_NOT_FOUND) - { - return false; - } - Validate(hr); - return true; - } - - public static unsafe void HttpResponseSetUnknownHeader(IntPtr pInProcessHandler, byte* pszHeaderName, byte* pszHeaderValue, ushort usHeaderValueLength, bool fReplace) - { - Validate(http_response_set_unknown_header(pInProcessHandler, pszHeaderName, pszHeaderValue, usHeaderValueLength, fReplace)); - } - - public static unsafe void HttpResponseSetKnownHeader(IntPtr pInProcessHandler, int headerId, byte* pHeaderValue, ushort length, bool fReplace) - { - Validate(http_response_set_known_header(pInProcessHandler, headerId, pHeaderValue, length, fReplace)); - } - - public static void HttpGetAuthenticationInformation(IntPtr pInProcessHandler, out string authType, out IntPtr token) - { - Validate(http_get_authentication_information(pInProcessHandler, out authType, out token)); - } - - private static void Validate(int hr) - { - if (hr != HR_OK) - { - throw Marshal.GetExceptionForHR(hr); - } - } } } diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/DuplexStream.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/DuplexStream.cs deleted file mode 100644 index f8ebd8d792..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/DuplexStream.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - // TODO redudant file, remove - // See https://github.com/aspnet/IISIntegration/issues/426 - internal class DuplexStream : Stream - { - private Stream _requestBody; - private Stream _responseBody; - - public DuplexStream(Stream requestBody, Stream responseBody) - { - _requestBody = requestBody; - _responseBody = responseBody; - } - - public override bool CanRead => true; - - public override bool CanSeek => false; - - public override bool CanWrite => true; - - public override long Length => throw new NotSupportedException(); - - public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } - - public override void Flush() - { - _responseBody.Flush(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - return _requestBody.Read(buffer, offset, count); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - _responseBody.Write(buffer, offset, count); - } - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - return _requestBody.ReadAsync(buffer, offset, count, cancellationToken); - } - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - return _responseBody.WriteAsync(buffer, offset, count, cancellationToken); - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISAwaitable.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISAwaitable.cs deleted file mode 100644 index a24586b137..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISAwaitable.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - // Primarily copied from https://github.com/aspnet/KestrelHttpServer/blob/dev/src/Kestrel.Transport.Libuv/Internal/LibuvAwaitable.cs - internal class IISAwaitable : ICriticalNotifyCompletion - { - private readonly static Action _callbackCompleted = () => { }; - - private Action _callback; - - private Exception _exception; - private int _cbBytes; - private int _hr; - - public static readonly NativeMethods.PFN_WEBSOCKET_ASYNC_COMPLETION ReadCallback = (IntPtr pHttpContext, IntPtr pCompletionInfo, IntPtr pvCompletionContext) => - { - var context = (IISHttpContext)GCHandle.FromIntPtr(pvCompletionContext).Target; - - NativeMethods.HttpGetCompletionInfo(pCompletionInfo, out int cbBytes, out int hr); - - context.CompleteReadWebSockets(hr, cbBytes); - - return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING; - }; - - public static readonly NativeMethods.PFN_WEBSOCKET_ASYNC_COMPLETION WriteCallback = (IntPtr pHttpContext, IntPtr pCompletionInfo, IntPtr pvCompletionContext) => - { - var context = (IISHttpContext)GCHandle.FromIntPtr(pvCompletionContext).Target; - - NativeMethods.HttpGetCompletionInfo(pCompletionInfo, out int cbBytes, out int hr); - - context.CompleteWriteWebSockets(hr, cbBytes); - - return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING; - }; - - public IISAwaitable GetAwaiter() => this; - public bool IsCompleted => _callback == _callbackCompleted; - - public bool HasContinuation => _callback != null && !IsCompleted; - - public int GetResult() - { - var exception = _exception; - var cbBytes = _cbBytes; - var hr = _hr; - - // Reset the awaitable state - _exception = null; - _cbBytes = 0; - _callback = null; - _hr = 0; - - if (exception != null) - { - // If the exception was an aborted read operation, - // return -1 to notify NativeReadAsync that the write was cancelled. - // E_OPERATIONABORTED == 0x800703e3 == -2147023901 - // We also don't throw the exception here as this is expected behavior - // and can negatively impact perf if we catch an exception for each - // cann - if (hr != IISServerConstants.HResultCancelIO) - { - throw exception; - } - else - { - cbBytes = -1; - } - } - - return cbBytes; - } - - public void OnCompleted(Action continuation) - { - // There should never be a race between IsCompleted and OnCompleted since both operations - // should always be on the libuv thread - - if (_callback == _callbackCompleted || - Interlocked.CompareExchange(ref _callback, continuation, null) == _callbackCompleted) - { - // Just run it inline - Task.Run(continuation); - } - } - - public void UnsafeOnCompleted(Action continuation) - { - OnCompleted(continuation); - } - - public void Complete(int hr, int cbBytes) - { - _hr = hr; - _exception = Marshal.GetExceptionForHR(hr); - _cbBytes = cbBytes; - var continuation = Interlocked.Exchange(ref _callback, _callbackCompleted); - continuation?.Invoke(); - } - - public Action GetCompletion(int hr, int cbBytes) - { - _hr = hr; - _exception = Marshal.GetExceptionForHR(hr); - _cbBytes = cbBytes; - - return Interlocked.Exchange(ref _callback, _callbackCompleted); - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISConfigurationData.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISConfigurationData.cs deleted file mode 100644 index 76910ca9d3..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISConfigurationData.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.InteropServices; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - [StructLayout(LayoutKind.Sequential)] - internal unsafe struct IISConfigurationData - { - [MarshalAs(UnmanagedType.BStr)] - public string pwzFullApplicationPath; - [MarshalAs(UnmanagedType.BStr)] - public string pwzVirtualApplicationPath; - public bool fWindowsAuthEnabled; - public bool fBasicAuthEnabled; - public bool fAnonymousAuthEnable; - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.FeatureCollection.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.FeatureCollection.cs deleted file mode 100644 index 0acf621bb0..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.FeatureCollection.cs +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Security.Claims; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Http.Features.Authentication; -using Microsoft.AspNetCore.WebUtilities; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal partial class IISHttpContext : IFeatureCollection, - IHttpRequestFeature, - IHttpResponseFeature, - IHttpUpgradeFeature, - IHttpRequestLifetimeFeature, - IHttpAuthenticationFeature, - IServerVariablesFeature - { - // NOTE: When feature interfaces are added to or removed from this HttpProtocol implementation, - // then the list of `implementedFeatures` in the generated code project MUST also be updated. - - private int _featureRevision; - private string _httpProtocolVersion = null; - - private List> MaybeExtra; - public void ResetFeatureCollection() - { - Initialize(); - MaybeExtra?.Clear(); - _featureRevision++; - } - - private object ExtraFeatureGet(Type key) - { - if (MaybeExtra == null) - { - return null; - } - for (var i = 0; i < MaybeExtra.Count; i++) - { - var kv = MaybeExtra[i]; - if (kv.Key == key) - { - return kv.Value; - } - } - return null; - } - - private void ExtraFeatureSet(Type key, object value) - { - if (MaybeExtra == null) - { - MaybeExtra = new List>(2); - } - - for (var i = 0; i < MaybeExtra.Count; i++) - { - if (MaybeExtra[i].Key == key) - { - MaybeExtra[i] = new KeyValuePair(key, value); - return; - } - } - MaybeExtra.Add(new KeyValuePair(key, value)); - } - - string IHttpRequestFeature.Protocol - { - get - { - if (_httpProtocolVersion == null) - { - var protocol = HttpVersion; - if (protocol.Major == 1 && protocol.Minor == 1) - { - _httpProtocolVersion = "HTTP/1.1"; - } - else if (protocol.Major == 1 && protocol.Minor == 0) - { - _httpProtocolVersion = "HTTP/1.0"; - } - else - { - _httpProtocolVersion = "HTTP/" + protocol.ToString(2); - } - } - return _httpProtocolVersion; - } - set - { - _httpProtocolVersion = value; - } - } - - string IHttpRequestFeature.Scheme - { - get => Scheme; - set => Scheme = value; - } - - string IHttpRequestFeature.Method - { - get => Method; - set => Method = value; - } - - string IHttpRequestFeature.PathBase - { - get => PathBase; - set => PathBase = value; - } - - string IHttpRequestFeature.Path - { - get => Path; - set => Path = value; - } - - string IHttpRequestFeature.QueryString - { - get => QueryString; - set => QueryString = value; - } - - string IHttpRequestFeature.RawTarget - { - get => RawTarget; - set => RawTarget = value; - } - - IHeaderDictionary IHttpRequestFeature.Headers - { - get => RequestHeaders; - set => RequestHeaders = value; - } - - Stream IHttpRequestFeature.Body - { - get => RequestBody; - set => RequestBody = value; - } - - int IHttpResponseFeature.StatusCode - { - get => StatusCode; - set => StatusCode = value; - } - - string IHttpResponseFeature.ReasonPhrase - { - get => ReasonPhrase; - set => ReasonPhrase = value; - } - - IHeaderDictionary IHttpResponseFeature.Headers - { - get => ResponseHeaders; - set => ResponseHeaders = value; - } - - Stream IHttpResponseFeature.Body - { - get => ResponseBody; - set => ResponseBody = value; - } - - CancellationToken IHttpRequestLifetimeFeature.RequestAborted - { - get => RequestAborted; - set => RequestAborted = value; - } - - bool IHttpResponseFeature.HasStarted => HasResponseStarted; - - bool IHttpUpgradeFeature.IsUpgradableRequest => _server.IsWebSocketAvailible(_pInProcessHandler); - - bool IFeatureCollection.IsReadOnly => false; - - int IFeatureCollection.Revision => _featureRevision; - - ClaimsPrincipal IHttpAuthenticationFeature.User - { - get => User; - set => User = value; - } - - public IAuthenticationHandler Handler { get; set; } - - string IServerVariablesFeature.this[string variableName] - { - get - { - if (string.IsNullOrEmpty(variableName)) - { - return null; - } - - return NativeMethods.HttpTryGetServerVariable(_pInProcessHandler, variableName, out var value) ? value : null; - } - } - - object IFeatureCollection.this[Type key] - { - get => FastFeatureGet(key); - set => FastFeatureSet(key, value); - } - - TFeature IFeatureCollection.Get() - { - return (TFeature)FastFeatureGet(typeof(TFeature)); - } - - void IFeatureCollection.Set(TFeature instance) - { - FastFeatureSet(typeof(TFeature), instance); - } - - void IHttpResponseFeature.OnStarting(Func callback, object state) - { - OnStarting(callback, state); - } - - void IHttpResponseFeature.OnCompleted(Func callback, object state) - { - OnCompleted(callback, state); - } - - async Task IHttpUpgradeFeature.UpgradeAsync() - { - // TODO fix these exceptions strings - if (!((IHttpUpgradeFeature)this).IsUpgradableRequest) - { - throw new InvalidOperationException("CoreStrings.CannotUpgradeNonUpgradableRequest"); - } - - if (_wasUpgraded) - { - throw new InvalidOperationException("CoreStrings.UpgradeCannotBeCalledMultipleTimes"); - } - if (HasResponseStarted) - { - throw new InvalidOperationException("CoreStrings.UpgradeCannotBeCalledMultipleTimes"); - } - _wasUpgraded = true; - - StatusCode = StatusCodes.Status101SwitchingProtocols; - ReasonPhrase = ReasonPhrases.GetReasonPhrase(StatusCodes.Status101SwitchingProtocols); - _readWebSocketsOperation = new IISAwaitable(); - _writeWebSocketsOperation = new IISAwaitable(); - NativeMethods.HttpEnableWebsockets(_pInProcessHandler); - - // Upgrade async will cause the stream processing to go into duplex mode - await UpgradeAsync(); - - return new DuplexStream(RequestBody, ResponseBody); - } - - IEnumerator> IEnumerable>.GetEnumerator() => FastEnumerable().GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => FastEnumerable().GetEnumerator(); - - void IHttpRequestLifetimeFeature.Abort() - { - Abort(); - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Features.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Features.cs deleted file mode 100644 index 6733ba74c5..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Features.cs +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal partial class IISHttpContext - { - private static readonly Type IHttpRequestFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestFeature); - private static readonly Type IHttpResponseFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResponseFeature); - private static readonly Type IHttpRequestIdentifierFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestIdentifierFeature); - private static readonly Type IServiceProvidersFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IServiceProvidersFeature); - private static readonly Type IHttpRequestLifetimeFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestLifetimeFeature); - private static readonly Type IHttpConnectionFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature); - private static readonly Type IHttpAuthenticationFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.Authentication.IHttpAuthenticationFeature); - private static readonly Type IQueryFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IQueryFeature); - private static readonly Type IFormFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IFormFeature); - private static readonly Type IHttpUpgradeFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpUpgradeFeature); - private static readonly Type IResponseCookiesFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IResponseCookiesFeature); - private static readonly Type IItemsFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IItemsFeature); - private static readonly Type ITlsConnectionFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.ITlsConnectionFeature); - private static readonly Type IHttpWebSocketFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpWebSocketFeature); - private static readonly Type ISessionFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.ISessionFeature); - private static readonly Type IHttpBodyControlFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature); - private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature); - private static readonly Type IISHttpContextType = typeof(IISHttpContext); - private static readonly Type IServerVariablesFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IServerVariablesFeature); - - private object _currentIHttpRequestFeature; - private object _currentIHttpResponseFeature; - private object _currentIHttpRequestIdentifierFeature; - private object _currentIServiceProvidersFeature; - private object _currentIHttpRequestLifetimeFeature; - private object _currentIHttpConnectionFeature; - private object _currentIHttpAuthenticationFeature; - private object _currentIQueryFeature; - private object _currentIFormFeature; - private object _currentIHttpUpgradeFeature; - private object _currentIResponseCookiesFeature; - private object _currentIItemsFeature; - private object _currentITlsConnectionFeature; - private object _currentIHttpMaxRequestBodySizeFeature; - private object _currentIHttpMinRequestBodyDataRateFeature; - private object _currentIHttpMinResponseDataRateFeature; - private object _currentIHttpWebSocketFeature; - private object _currentISessionFeature; - private object _currentIHttpBodyControlFeature; - private object _currentIHttpSendFileFeature; - private object _currentIServerVariablesFeature; - - private void Initialize() - { - _currentIHttpRequestFeature = this; - _currentIHttpResponseFeature = this; - _currentIHttpUpgradeFeature = this; - _currentIHttpRequestIdentifierFeature = this; - _currentIHttpRequestLifetimeFeature = this; - _currentIHttpConnectionFeature = this; - _currentIHttpMaxRequestBodySizeFeature = this; - _currentIHttpMinRequestBodyDataRateFeature = this; - _currentIHttpMinResponseDataRateFeature = this; - _currentIHttpBodyControlFeature = this; - _currentIHttpAuthenticationFeature = this; - _currentIServerVariablesFeature = this; - } - - internal object FastFeatureGet(Type key) - { - if (key == IHttpRequestFeatureType) - { - return _currentIHttpRequestFeature; - } - if (key == IHttpResponseFeatureType) - { - return _currentIHttpResponseFeature; - } - if (key == IHttpRequestIdentifierFeatureType) - { - return _currentIHttpRequestIdentifierFeature; - } - if (key == IServiceProvidersFeatureType) - { - return _currentIServiceProvidersFeature; - } - if (key == IHttpRequestLifetimeFeatureType) - { - return _currentIHttpRequestLifetimeFeature; - } - if (key == IHttpConnectionFeatureType) - { - return _currentIHttpConnectionFeature; - } - if (key == IHttpAuthenticationFeatureType) - { - return _currentIHttpAuthenticationFeature; - } - if (key == IQueryFeatureType) - { - return _currentIQueryFeature; - } - if (key == IFormFeatureType) - { - return _currentIFormFeature; - } - if (key == IHttpUpgradeFeatureType) - { - return _currentIHttpUpgradeFeature; - } - if (key == IResponseCookiesFeatureType) - { - return _currentIResponseCookiesFeature; - } - if (key == IItemsFeatureType) - { - return _currentIItemsFeature; - } - if (key == ITlsConnectionFeatureType) - { - return _currentITlsConnectionFeature; - } - if (key == IHttpWebSocketFeatureType) - { - return _currentIHttpWebSocketFeature; - } - if (key == ISessionFeatureType) - { - return _currentISessionFeature; - } - if (key == IHttpBodyControlFeatureType) - { - return _currentIHttpBodyControlFeature; - } - if (key == IHttpSendFileFeatureType) - { - return _currentIHttpSendFileFeature; - } - if (key == IISHttpContextType) - { - return this; - } - if (key == IServerVariablesFeature) - { - return this; - } - - return ExtraFeatureGet(key); - } - - internal void FastFeatureSet(Type key, object feature) - { - _featureRevision++; - - if (key == IHttpRequestFeatureType) - { - _currentIHttpRequestFeature = feature; - return; - } - if (key == IHttpResponseFeatureType) - { - _currentIHttpResponseFeature = feature; - return; - } - if (key == IHttpRequestIdentifierFeatureType) - { - _currentIHttpRequestIdentifierFeature = feature; - return; - } - if (key == IServiceProvidersFeatureType) - { - _currentIServiceProvidersFeature = feature; - return; - } - if (key == IHttpRequestLifetimeFeatureType) - { - _currentIHttpRequestLifetimeFeature = feature; - return; - } - if (key == IHttpConnectionFeatureType) - { - _currentIHttpConnectionFeature = feature; - return; - } - if (key == IHttpAuthenticationFeatureType) - { - _currentIHttpAuthenticationFeature = feature; - return; - } - if (key == IQueryFeatureType) - { - _currentIQueryFeature = feature; - return; - } - if (key == IFormFeatureType) - { - _currentIFormFeature = feature; - return; - } - if (key == IHttpUpgradeFeatureType) - { - _currentIHttpUpgradeFeature = feature; - return; - } - if (key == IResponseCookiesFeatureType) - { - _currentIResponseCookiesFeature = feature; - return; - } - if (key == IItemsFeatureType) - { - _currentIItemsFeature = feature; - return; - } - if (key == ITlsConnectionFeatureType) - { - _currentITlsConnectionFeature = feature; - return; - } - if (key == IHttpWebSocketFeatureType) - { - _currentIHttpWebSocketFeature = feature; - return; - } - if (key == ISessionFeatureType) - { - _currentISessionFeature = feature; - return; - } - if (key == IHttpBodyControlFeatureType) - { - _currentIHttpBodyControlFeature = feature; - return; - } - if (key == IHttpSendFileFeatureType) - { - _currentIHttpSendFileFeature = feature; - return; - } - if (key == IServerVariablesFeature) - { - _currentIServerVariablesFeature = feature; - return; - } - if (key == IISHttpContextType) - { - throw new InvalidOperationException("Cannot set IISHttpContext in feature collection"); - }; - ExtraFeatureSet(key, feature); - } - - private IEnumerable> FastEnumerable() - { - if (_currentIHttpRequestFeature != null) - { - yield return new KeyValuePair(IHttpRequestFeatureType, _currentIHttpRequestFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestFeature); - } - if (_currentIHttpResponseFeature != null) - { - yield return new KeyValuePair(IHttpResponseFeatureType, _currentIHttpResponseFeature as global::Microsoft.AspNetCore.Http.Features.IHttpResponseFeature); - } - if (_currentIHttpRequestIdentifierFeature != null) - { - yield return new KeyValuePair(IHttpRequestIdentifierFeatureType, _currentIHttpRequestIdentifierFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestIdentifierFeature); - } - if (_currentIServiceProvidersFeature != null) - { - yield return new KeyValuePair(IServiceProvidersFeatureType, _currentIServiceProvidersFeature as global::Microsoft.AspNetCore.Http.Features.IServiceProvidersFeature); - } - if (_currentIHttpRequestLifetimeFeature != null) - { - yield return new KeyValuePair(IHttpRequestLifetimeFeatureType, _currentIHttpRequestLifetimeFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestLifetimeFeature); - } - if (_currentIHttpConnectionFeature != null) - { - yield return new KeyValuePair(IHttpConnectionFeatureType, _currentIHttpConnectionFeature as global::Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature); - } - if (_currentIHttpAuthenticationFeature != null) - { - yield return new KeyValuePair(IHttpAuthenticationFeatureType, _currentIHttpAuthenticationFeature as global::Microsoft.AspNetCore.Http.Features.Authentication.IHttpAuthenticationFeature); - } - if (_currentIQueryFeature != null) - { - yield return new KeyValuePair(IQueryFeatureType, _currentIQueryFeature as global::Microsoft.AspNetCore.Http.Features.IQueryFeature); - } - if (_currentIFormFeature != null) - { - yield return new KeyValuePair(IFormFeatureType, _currentIFormFeature as global::Microsoft.AspNetCore.Http.Features.IFormFeature); - } - if (_currentIHttpUpgradeFeature != null) - { - yield return new KeyValuePair(IHttpUpgradeFeatureType, _currentIHttpUpgradeFeature as global::Microsoft.AspNetCore.Http.Features.IHttpUpgradeFeature); - } - if (_currentIResponseCookiesFeature != null) - { - yield return new KeyValuePair(IResponseCookiesFeatureType, _currentIResponseCookiesFeature as global::Microsoft.AspNetCore.Http.Features.IResponseCookiesFeature); - } - if (_currentIItemsFeature != null) - { - yield return new KeyValuePair(IItemsFeatureType, _currentIItemsFeature as global::Microsoft.AspNetCore.Http.Features.IItemsFeature); - } - if (_currentITlsConnectionFeature != null) - { - yield return new KeyValuePair(ITlsConnectionFeatureType, _currentITlsConnectionFeature as global::Microsoft.AspNetCore.Http.Features.ITlsConnectionFeature); - } - if (_currentIHttpWebSocketFeature != null) - { - yield return new KeyValuePair(IHttpWebSocketFeatureType, _currentIHttpWebSocketFeature as global::Microsoft.AspNetCore.Http.Features.IHttpWebSocketFeature); - } - if (_currentISessionFeature != null) - { - yield return new KeyValuePair(ISessionFeatureType, _currentISessionFeature as global::Microsoft.AspNetCore.Http.Features.ISessionFeature); - } - if (_currentIHttpBodyControlFeature != null) - { - yield return new KeyValuePair(IHttpBodyControlFeatureType, _currentIHttpBodyControlFeature as global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature); - } - if (_currentIHttpSendFileFeature != null) - { - yield return new KeyValuePair(IHttpSendFileFeatureType, _currentIHttpSendFileFeature as global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature); - } - if (_currentIServerVariablesFeature != null) - { - yield return new KeyValuePair(IServerVariablesFeature, _currentIServerVariablesFeature as global::Microsoft.AspNetCore.Http.Features.IServerVariablesFeature); - } - - if (MaybeExtra != null) - { - foreach (var item in MaybeExtra) - { - yield return item; - } - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpConnectionFeature.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpConnectionFeature.cs deleted file mode 100644 index d5a72cf013..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpConnectionFeature.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Globalization; -using System.Net; -using Microsoft.AspNetCore.Http.Features; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal partial class IISHttpContext : IHttpConnectionFeature - { - IPAddress IHttpConnectionFeature.RemoteIpAddress - { - get - { - if (RemoteIpAddress == null) - { - InitializeRemoteEndpoint(); - } - - return RemoteIpAddress; - } - set => RemoteIpAddress = value; - } - - IPAddress IHttpConnectionFeature.LocalIpAddress - { - get - { - if (LocalIpAddress == null) - { - InitializeLocalEndpoint(); - } - return LocalIpAddress; - } - set => LocalIpAddress = value; - } - - int IHttpConnectionFeature.RemotePort - { - get - { - if (RemoteIpAddress == null) - { - InitializeRemoteEndpoint(); - } - - return RemotePort; - } - set => RemotePort = value; - } - - int IHttpConnectionFeature.LocalPort - { - get - { - if (LocalIpAddress == null) - { - InitializeLocalEndpoint(); - } - - return LocalPort; - } - set => LocalPort = value; - } - - string IHttpConnectionFeature.ConnectionId - { - get - { - if (RequestConnectionId == null) - { - InitializeConnectionId(); - } - - return RequestConnectionId; - } - set => RequestConnectionId = value; - } - - private void InitializeLocalEndpoint() - { - var localEndPoint = GetLocalEndPoint(); - LocalIpAddress = localEndPoint.GetIPAddress(); - LocalPort = localEndPoint.GetPort(); - } - - private void InitializeRemoteEndpoint() - { - var remoteEndPoint = GetRemoteEndPoint(); - RemoteIpAddress = remoteEndPoint.GetIPAddress(); - RemotePort = remoteEndPoint.GetPort(); - } - - private void InitializeConnectionId() - { - RequestConnectionId = ConnectionId.ToString(CultureInfo.InvariantCulture); - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpRequestIdentifierFeature.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpRequestIdentifierFeature.cs deleted file mode 100644 index 68112f607c..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.IHttpRequestIdentifierFeature.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Http.Features; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal partial class IISHttpContext : IHttpRequestIdentifierFeature - { - string IHttpRequestIdentifierFeature.TraceIdentifier - { - get - { - if (TraceIdentifier == null) - { - InitializeHttpRequestIdentifierFeature(); - } - - return TraceIdentifier; - } - set => TraceIdentifier = value; - } - - private unsafe void InitializeHttpRequestIdentifierFeature() - { - // Copied from WebListener - // This is the base GUID used by HTTP.SYS for generating the activity ID. - // HTTP.SYS overwrites the first 8 bytes of the base GUID with RequestId to generate ETW activity ID. - // The requestId should be set by the NativeRequestContext - var guid = new Guid(0xffcb4c93, 0xa57f, 0x453c, 0xb6, 0x3f, 0x84, 0x71, 0xc, 0x79, 0x67, 0xbb); - *((ulong*)&guid) = RequestId; - - // TODO: Also make this not slow - TraceIdentifier = guid.ToString(); - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.ReadWrite.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.ReadWrite.cs deleted file mode 100644 index d6480cde9a..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.ReadWrite.cs +++ /dev/null @@ -1,475 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Buffers; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.HttpSys.Internal; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal partial class IISHttpContext - { - private const int HttpDataChunkStackLimit = 128; // 16 bytes per HTTP_DATA_CHUNK - - /// - /// Reads data from the Input pipe to the user. - /// - /// - /// - /// - internal async Task ReadAsync(Memory memory, CancellationToken cancellationToken) - { - StartProcessingRequestAndResponseBody(); - - while (true) - { - var result = await Input.Reader.ReadAsync(); - var readableBuffer = result.Buffer; - try - { - if (!readableBuffer.IsEmpty) - { - var actual = Math.Min(readableBuffer.Length, memory.Length); - readableBuffer = readableBuffer.Slice(0, actual); - readableBuffer.CopyTo(memory.Span); - return (int)actual; - } - else if (result.IsCompleted) - { - return 0; - } - } - finally - { - Input.Reader.AdvanceTo(readableBuffer.End, readableBuffer.End); - } - } - } - - /// - /// Writes data to the output pipe. - /// - /// - /// - /// - internal Task WriteAsync(ReadOnlyMemory memory, CancellationToken cancellationToken = default(CancellationToken)) - { - - // Want to keep exceptions consistent, - if (!_hasResponseStarted) - { - return WriteAsyncAwaited(memory, cancellationToken); - } - - lock (_stateSync) - { - DisableReads(); - return Output.WriteAsync(memory, cancellationToken); - } - } - - /// - /// Flushes the data in the output pipe - /// - /// - /// - internal Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - if (!_hasResponseStarted) - { - return FlushAsyncAwaited(cancellationToken); - } - lock (_stateSync) - { - DisableReads(); - return Output.FlushAsync(cancellationToken); - } - } - - private void StartProcessingRequestAndResponseBody() - { - if (_processBodiesTask == null) - { - lock (_createReadWriteBodySync) - { - if (_processBodiesTask == null) - { - _processBodiesTask = ConsumeAsync(); - } - } - } - } - - private async Task FlushAsyncAwaited(CancellationToken cancellationToken) - { - await InitializeResponseAwaited(); - - Task flushTask; - lock (_stateSync) - { - DisableReads(); - - // Want to guarantee that data has been written to the pipe before releasing the lock. - flushTask = Output.FlushAsync(cancellationToken: cancellationToken); - } - await flushTask; - } - - private async Task WriteAsyncAwaited(ReadOnlyMemory data, CancellationToken cancellationToken) - { - // WriteAsyncAwaited is only called for the first write to the body. - // Ensure headers are flushed if Write(Chunked)Async isn't called. - await InitializeResponseAwaited(); - - Task writeTask; - lock (_stateSync) - { - DisableReads(); - - // Want to guarantee that data has been written to the pipe before releasing the lock. - writeTask = Output.WriteAsync(data, cancellationToken: cancellationToken); - } - await writeTask; - } - - // ConsumeAsync is called when either the first read or first write is done. - // There are two modes for reading and writing to the request/response bodies without upgrade. - // 1. Await all reads and try to read from the Output pipe - // 2. Done reading and await all writes. - // If the request is upgraded, we will start bidirectional streams for the input and output. - private async Task ConsumeAsync() - { - await ReadAndWriteLoopAsync(); - - // The ReadAndWriteLoop can return due to being upgraded. Check if _wasUpgraded is true to determine - // whether we go to a bidirectional stream or only write. - if (_wasUpgraded) - { - await StartBidirectionalStream(); - } - } - - private unsafe IISAwaitable ReadFromIISAsync(int length) - { - Action completion = null; - lock (_stateSync) - { - // We don't want to read if there is data available in the output pipe - // Therefore, we mark the current operation as cancelled to allow for the read - // to be requeued. - if (Output.Reader.TryRead(out var result)) - { - // If the buffer is empty, it is considered a write of zero. - // we still want to cancel and allow the write to occur. - completion = _operation.GetCompletion(hr: IISServerConstants.HResultCancelIO, cbBytes: 0); - Output.Reader.AdvanceTo(result.Buffer.Start); - } - else - { - var hr = NativeMethods.HttpReadRequestBytes( - _pInProcessHandler, - (byte*)_inputHandle.Pointer, - length, - out var dwReceivedBytes, - out bool fCompletionExpected); - // if we complete the read synchronously, there is no need to set the reading flag - // as there is no cancelable operation. - if (!fCompletionExpected) - { - completion = _operation.GetCompletion(hr, dwReceivedBytes); - } - else - { - _reading = true; - } - } - } - - // Invoke the completion outside of the lock if the reead finished synchronously. - completion?.Invoke(); - - return _operation; - } - - private unsafe IISAwaitable WriteToIISAsync(ReadOnlySequence buffer) - { - var fCompletionExpected = false; - var hr = 0; - var nChunks = 0; - - // Count the number of chunks in memory. - if (buffer.IsSingleSegment) - { - nChunks = 1; - } - else - { - foreach (var memory in buffer) - { - nChunks++; - } - } - - if (nChunks == 1) - { - // If there is only a single chunk, use fixed to get a pointer to the buffer - var pDataChunks = stackalloc HttpApiTypes.HTTP_DATA_CHUNK[1]; - - fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer.First.Span)) - { - ref var chunk = ref pDataChunks[0]; - - chunk.DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; - chunk.fromMemory.pBuffer = (IntPtr)pBuffer; - chunk.fromMemory.BufferLength = (uint)buffer.Length; - hr = NativeMethods.HttpWriteResponseBytes(_pInProcessHandler, pDataChunks, nChunks, out fCompletionExpected); - } - } - else if (nChunks < HttpDataChunkStackLimit) - { - // To avoid stackoverflows, we will only stackalloc if the write size is less than the StackChunkLimit - // The stack size is IIS is by default 128/256 KB, so we are generous with this threshold. - var pDataChunks = stackalloc HttpApiTypes.HTTP_DATA_CHUNK[nChunks]; - hr = WriteSequenceToIIS(nChunks, buffer, pDataChunks, out fCompletionExpected); - } - else - { - // Otherwise allocate the chunks on the heap. - var chunks = new HttpApiTypes.HTTP_DATA_CHUNK[nChunks]; - fixed (HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks = chunks) - { - hr = WriteSequenceToIIS(nChunks, buffer, pDataChunks, out fCompletionExpected); - } - } - - if (!fCompletionExpected) - { - _operation.Complete(hr, 0); - } - return _operation; - } - - private unsafe int WriteSequenceToIIS(int nChunks, ReadOnlySequence buffer, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, out bool fCompletionExpected) - { - var currentChunk = 0; - var hr = 0; - - // REVIEW: We don't really need this list since the memory is already pinned with the default pool, - // but shouldn't assume the pool implementation right now. Unfortunately, this causes a heap allocation... - var handles = new MemoryHandle[nChunks]; - - foreach (var b in buffer) - { - ref var handle = ref handles[currentChunk]; - ref var chunk = ref pDataChunks[currentChunk]; - handle = b.Pin(); - - chunk.DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; - chunk.fromMemory.BufferLength = (uint)b.Length; - chunk.fromMemory.pBuffer = (IntPtr)handle.Pointer; - - currentChunk++; - } - - hr = NativeMethods.HttpWriteResponseBytes(_pInProcessHandler, pDataChunks, nChunks, out fCompletionExpected); - - // Free the handles - foreach (var handle in handles) - { - handle.Dispose(); - } - - return hr; - } - - private unsafe IISAwaitable FlushToIISAsync() - { - // Calls flush - var hr = 0; - hr = NativeMethods.HttpFlushResponseBytes(_pInProcessHandler, out var fCompletionExpected); - if (!fCompletionExpected) - { - _operation.Complete(hr, 0); - } - - return _operation; - } - - /// - /// Main function for control flow with IIS. - /// Uses two Pipes (Input and Output) between application calls to Read/Write/FlushAsync - /// Control Flow: - /// Try to see if there is data written by the application code (using TryRead) - /// and write it to IIS. - /// Check if the connection has been upgraded and call StartBidirectionalStreams - /// if it has. - /// Await reading from IIS, which will be cancelled if application code calls Write/FlushAsync. - /// - /// The Reading and Writing task. - private async Task ReadAndWriteLoopAsync() - { - try - { - while (true) - { - // First we check if there is anything to write from the Output pipe - // If there is, we call WriteToIISAsync - // Check if Output pipe has anything to write to IIS. - if (Output.Reader.TryRead(out var readResult)) - { - var buffer = readResult.Buffer; - - try - { - if (!buffer.IsEmpty) - { - // Write to IIS buffers - // Guaranteed to write the entire buffer to IIS - await WriteToIISAsync(buffer); - } - else if (readResult.IsCompleted) - { - break; - } - else - { - // Flush of zero bytes - await FlushToIISAsync(); - } - } - finally - { - // Always Advance the data pointer to the end of the buffer. - Output.Reader.AdvanceTo(buffer.End); - } - } - - // Check if there was an upgrade. If there is, we will replace the request and response bodies with - // two seperate loops. These will still be using the same Input and Output pipes here. - if (_upgradeTcs?.TrySetResult(null) == true) - { - // _wasUpgraded will be set at this point, exit the loop and we will check if we upgraded or not - // when going to next read/write type. - return; - } - - // Now we handle the read. - var memory = Input.Writer.GetMemory(); - _inputHandle = memory.Pin(); - - try - { - // Lock around invoking ReadFromIISAsync as we don't want to call CancelIo - // when calling read - var read = await ReadFromIISAsync(memory.Length); - - // read value of 0 == done reading - // read value of -1 == read cancelled, still allowed to read but we - // need a write to occur first. - if (read == 0) - { - break; - } - else if (read == -1) - { - continue; - } - Input.Writer.Advance(read); - } - finally - { - // Always commit any changes to the Input pipe - _inputHandle.Dispose(); - } - - // Flush the read data for the Input Pipe writer - var flushResult = await Input.Writer.FlushAsync(); - - // If the pipe was closed, we are done reading, - if (flushResult.IsCompleted || flushResult.IsCanceled) - { - break; - } - } - - // Complete the input writer as we are done reading the request body. - Input.Writer.Complete(); - } - catch (Exception ex) - { - Input.Writer.Complete(ex); - } - - await WriteLoopAsync(); - } - - /// - /// Secondary function for control flow with IIS. This is only called once we are done - /// reading the request body. We now await reading from the Output pipe. - /// - /// - private async Task WriteLoopAsync() - { - try - { - while (true) - { - // Reading is done, so we will await all reads from the output pipe - var readResult = await Output.Reader.ReadAsync(); - - // Get data from pipe - var buffer = readResult.Buffer; - - try - { - if (!buffer.IsEmpty) - { - // Write to IIS buffers - // Guaranteed to write the entire buffer to IIS - await WriteToIISAsync(buffer); - } - else if (readResult.IsCompleted) - { - break; - } - else - { - // Flush of zero bytes will - await FlushToIISAsync(); - } - } - finally - { - // Always Advance the data pointer to the end of the buffer. - Output.Reader.AdvanceTo(buffer.End); - } - } - - // Close the output pipe as we are done reading from it. - Output.Reader.Complete(); - } - catch (Exception ex) - { - Output.Reader.Complete(ex); - } - } - - // Always called from within a lock - private void DisableReads() - { - // To avoid concurrent reading and writing, if we have a pending read, - // we must cancel it. - // _reading will always be false if we upgrade to websockets, so we don't need to check wasUpgrade - // Also, we set _reading to false after cancelling to detect redundant calls - if (_reading) - { - _reading = false; - // Calls IHttpContext->CancelIo(), which will cause the OnAsyncCompletion handler to fire. - NativeMethods.HttpTryCancelIO(_pInProcessHandler); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Websockets.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Websockets.cs deleted file mode 100644 index 75a1efba1e..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.Websockets.cs +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Buffers; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using Microsoft.AspNetCore.HttpSys.Internal; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - /// - /// Represents the websocket portion of the - /// - internal partial class IISHttpContext - { - private bool _wasUpgraded; // Used for detecting repeated upgrades in IISHttpContext - - private IISAwaitable _readWebSocketsOperation; - private IISAwaitable _writeWebSocketsOperation; - private TaskCompletionSource _upgradeTcs; - - private Task StartBidirectionalStream() - { - // IIS allows for websocket support and duplex channels only on Win8 and above - // This allows us to have two tasks for reading the request and writing the response - var readWebsocketTask = ReadWebSockets(); - var writeWebsocketTask = WriteWebSockets(); - return Task.WhenAll(readWebsocketTask, writeWebsocketTask); - } - - public async Task UpgradeAsync() - { - if (_upgradeTcs == null) - { - _upgradeTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - // Flush any contents of the OutputPipe before upgrading to websockets. - await FlushAsync(); - await _upgradeTcs.Task; - } - } - - private unsafe IISAwaitable ReadWebSocketsFromIISAsync(int length) - { - var hr = 0; - int dwReceivedBytes; - bool fCompletionExpected; - - // For websocket calls, we can directly provide a callback function to be called once the websocket operation completes. - hr = NativeMethods.HttpWebsocketsReadBytes( - _pInProcessHandler, - (byte*)_inputHandle.Pointer, - length, - IISAwaitable.ReadCallback, - (IntPtr)_thisHandle, - out dwReceivedBytes, - out fCompletionExpected); - if (!fCompletionExpected) - { - CompleteReadWebSockets(hr, dwReceivedBytes); - } - - return _readWebSocketsOperation; - } - - private unsafe IISAwaitable WriteWebSocketsFromIISAsync(ReadOnlySequence buffer) - { - var fCompletionExpected = false; - var hr = 0; - var nChunks = 0; - - if (buffer.IsSingleSegment) - { - nChunks = 1; - } - else - { - foreach (var memory in buffer) - { - nChunks++; - } - } - - if (buffer.IsSingleSegment) - { - var pDataChunks = stackalloc HttpApiTypes.HTTP_DATA_CHUNK[1]; - - fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer.First.Span)) - { - ref var chunk = ref pDataChunks[0]; - - chunk.DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; - chunk.fromMemory.pBuffer = (IntPtr)pBuffer; - chunk.fromMemory.BufferLength = (uint)buffer.Length; - hr = NativeMethods.HttpWebsocketsWriteBytes(_pInProcessHandler, pDataChunks, nChunks, IISAwaitable.WriteCallback, (IntPtr)_thisHandle, out fCompletionExpected); - } - } - else - { - // REVIEW: Do we need to guard against this getting too big? It seems unlikely that we'd have more than say 10 chunks in real life - var pDataChunks = stackalloc HttpApiTypes.HTTP_DATA_CHUNK[nChunks]; - var currentChunk = 0; - - // REVIEW: We don't really need this list since the memory is already pinned with the default pool, - // but shouldn't assume the pool implementation right now. Unfortunately, this causes a heap allocation... - var handles = new MemoryHandle[nChunks]; - - foreach (var b in buffer) - { - ref var handle = ref handles[currentChunk]; - ref var chunk = ref pDataChunks[currentChunk]; - - handle = b.Pin(); - - chunk.DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; - chunk.fromMemory.BufferLength = (uint)b.Length; - chunk.fromMemory.pBuffer = (IntPtr)handle.Pointer; - - currentChunk++; - } - - hr = NativeMethods.HttpWebsocketsWriteBytes(_pInProcessHandler, pDataChunks, nChunks, IISAwaitable.WriteCallback, (IntPtr)_thisHandle, out fCompletionExpected); - - foreach (var handle in handles) - { - handle.Dispose(); - } - } - - if (!fCompletionExpected) - { - CompleteWriteWebSockets(hr, 0); - } - - return _writeWebSocketsOperation; - } - - internal void CompleteWriteWebSockets(int hr, int cbBytes) - { - _writeWebSocketsOperation.Complete(hr, cbBytes); - } - - internal void CompleteReadWebSockets(int hr, int cbBytes) - { - _readWebSocketsOperation.Complete(hr, cbBytes); - } - - private async Task ReadWebSockets() - { - try - { - while (true) - { - var memory = Input.Writer.GetMemory(); - _inputHandle = memory.Pin(); - - try - { - int read = 0; - read = await ReadWebSocketsFromIISAsync(memory.Length); - - if (read == 0) - { - break; - } - - Input.Writer.Advance(read); - } - finally - { - _inputHandle.Dispose(); - } - - var result = await Input.Writer.FlushAsync(); - - if (result.IsCompleted || result.IsCanceled) - { - break; - } - } - Input.Writer.Complete(); - } - catch (Exception ex) - { - Input.Writer.Complete(ex); - } - } - - private async Task WriteWebSockets() - { - try - { - while (true) - { - var result = await Output.Reader.ReadAsync(); - - var buffer = result.Buffer; - var consumed = buffer.End; - - try - { - if (!buffer.IsEmpty) - { - await WriteWebSocketsFromIISAsync(buffer); - } - else if (result.IsCompleted) - { - break; - } - } - finally - { - Output.Reader.AdvanceTo(consumed); - } - } - - Output.Reader.Complete(); - } - catch (Exception ex) - { - Output.Reader.Complete(ex); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.cs deleted file mode 100644 index fa04d66e6c..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContext.cs +++ /dev/null @@ -1,514 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.IO.Pipelines; -using System.Net; -using System.Runtime.InteropServices; -using System.Security.Claims; -using System.Security.Principal; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.HttpSys.Internal; -using Microsoft.AspNetCore.WebUtilities; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal abstract partial class IISHttpContext : NativeRequestContext, IDisposable - { - private const int MinAllocBufferSize = 2048; - private const int PauseWriterThreshold = 65536; - private const int ResumeWriterTheshold = PauseWriterThreshold / 2; - - - protected readonly IntPtr _pInProcessHandler; - - private readonly IISOptions _options; - - private bool _reading; // To know whether we are currently in a read operation. - private volatile bool _hasResponseStarted; - - private int _statusCode; - private string _reasonPhrase; - private readonly object _onStartingSync = new object(); - private readonly object _onCompletedSync = new object(); - private readonly object _stateSync = new object(); - protected readonly object _createReadWriteBodySync = new object(); - - protected Stack, object>> _onStarting; - protected Stack, object>> _onCompleted; - - protected Exception _applicationException; - private readonly MemoryPool _memoryPool; - private readonly IISHttpServer _server; - - private GCHandle _thisHandle; - private MemoryHandle _inputHandle; - private IISAwaitable _operation = new IISAwaitable(); - protected Task _processBodiesTask; - - protected int _requestAborted; - - private const string NtlmString = "NTLM"; - private const string NegotiateString = "Negotiate"; - private const string BasicString = "Basic"; - - internal unsafe IISHttpContext(MemoryPool memoryPool, IntPtr pInProcessHandler, IISOptions options, IISHttpServer server) - : base((HttpApiTypes.HTTP_REQUEST*)NativeMethods.HttpGetRawRequest(pInProcessHandler)) - { - _memoryPool = memoryPool; - _pInProcessHandler = pInProcessHandler; - _options = options; - _server = server; - } - - public Version HttpVersion { get; set; } - public string Scheme { get; set; } - public string Method { get; set; } - public string PathBase { get; set; } - public string Path { get; set; } - public string QueryString { get; set; } - public string RawTarget { get; set; } - public CancellationToken RequestAborted { get; set; } - public bool HasResponseStarted => _hasResponseStarted; - public IPAddress RemoteIpAddress { get; set; } - public int RemotePort { get; set; } - public IPAddress LocalIpAddress { get; set; } - public int LocalPort { get; set; } - public string RequestConnectionId { get; set; } - public string TraceIdentifier { get; set; } - public ClaimsPrincipal User { get; set; } - internal WindowsPrincipal WindowsUser { get; set; } - public Stream RequestBody { get; set; } - public Stream ResponseBody { get; set; } - public Pipe Input { get; set; } - public OutputProducer Output { get; set; } - - public IHeaderDictionary RequestHeaders { get; set; } - public IHeaderDictionary ResponseHeaders { get; set; } - private HeaderCollection HttpResponseHeaders { get; set; } - internal HttpApiTypes.HTTP_VERB KnownMethod { get; private set; } - - protected void InitializeContext() - { - _thisHandle = GCHandle.Alloc(this); - - NativeMethods.HttpSetManagedContext(_pInProcessHandler, (IntPtr)_thisHandle); - - Method = GetVerb(); - - RawTarget = GetRawUrl(); - // TODO version is slow. - HttpVersion = GetVersion(); - Scheme = SslStatus != SslStatus.Insecure ? Constants.HttpsScheme : Constants.HttpScheme; - KnownMethod = VerbId; - StatusCode = 200; - - var originalPath = RequestUriBuilder.DecodeAndUnescapePath(GetRawUrlInBytes()); - - if (KnownMethod == HttpApiTypes.HTTP_VERB.HttpVerbOPTIONS && string.Equals(RawTarget, "*", StringComparison.Ordinal)) - { - PathBase = string.Empty; - Path = string.Empty; - } - else - { - // Path and pathbase are unescaped by RequestUriBuilder - // The UsePathBase middleware will modify the pathbase and path correctly - PathBase = string.Empty; - Path = originalPath; - } - - var cookedUrl = GetCookedUrl(); - QueryString = cookedUrl.GetQueryString() ?? string.Empty; - - RequestHeaders = new RequestHeaders(this); - HttpResponseHeaders = new HeaderCollection(); - ResponseHeaders = HttpResponseHeaders; - - if (_options.ForwardWindowsAuthentication) - { - WindowsUser = GetWindowsPrincipal(); - if (_options.AutomaticAuthentication) - { - User = WindowsUser; - } - } - - ResetFeatureCollection(); - - if (!_server.IsWebSocketAvailible(_pInProcessHandler)) - { - _currentIHttpUpgradeFeature = null; - } - - RequestBody = new IISHttpRequestBody(this); - ResponseBody = new IISHttpResponseBody(this); - - Input = new Pipe(new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.ThreadPool, minimumSegmentSize: MinAllocBufferSize)); - var pipe = new Pipe( - new PipeOptions( - _memoryPool, - readerScheduler: PipeScheduler.ThreadPool, - pauseWriterThreshold: PauseWriterThreshold, - resumeWriterThreshold: ResumeWriterTheshold, - minimumSegmentSize: MinAllocBufferSize)); - Output = new OutputProducer(pipe); - } - - public int StatusCode - { - get { return _statusCode; } - set - { - if (_hasResponseStarted) - { - ThrowResponseAlreadyStartedException(nameof(StatusCode)); - } - _statusCode = (ushort)value; - } - } - - public string ReasonPhrase - { - get { return _reasonPhrase; } - set - { - if (_hasResponseStarted) - { - ThrowResponseAlreadyStartedException(nameof(ReasonPhrase)); - } - _reasonPhrase = value; - } - } - - internal IISHttpServer Server - { - get { return _server; } - } - - private async Task InitializeResponseAwaited() - { - await FireOnStarting(); - - if (_applicationException != null) - { - ThrowResponseAbortedException(); - } - - await ProduceStart(appCompleted: false); - } - - private void ThrowResponseAbortedException() - { - throw new ObjectDisposedException("Unhandled application exception", _applicationException); - } - - private async Task ProduceStart(bool appCompleted) - { - if (_hasResponseStarted) - { - return; - } - - _hasResponseStarted = true; - - SendResponseHeaders(appCompleted); - - // On first flush for websockets, we need to flush the headers such that - // IIS will know that an upgrade occured. - // If we don't have anything on the Output pipe, the TryRead in ReadAndWriteLoopAsync - // will fail and we will signal the upgradeTcs that we are upgrading. However, we still - // didn't flush. To fix this, we flush 0 bytes right after writing the headers. - Task flushTask; - lock (_stateSync) - { - DisableReads(); - flushTask = Output.FlushAsync(); - } - await flushTask; - - StartProcessingRequestAndResponseBody(); - } - - protected Task ProduceEnd() - { - if (_applicationException != null) - { - if (_hasResponseStarted) - { - // We can no longer change the response, so we simply close the connection. - return Task.CompletedTask; - } - - // If the request was rejected, the error state has already been set by SetBadRequestState and - // that should take precedence. - else - { - // 500 Internal Server Error - SetErrorResponseHeaders(statusCode: StatusCodes.Status500InternalServerError); - } - } - - if (!_hasResponseStarted) - { - return ProduceEndAwaited(); - } - - return Task.CompletedTask; - } - - private void SetErrorResponseHeaders(int statusCode) - { - StatusCode = statusCode; - ReasonPhrase = string.Empty; - HttpResponseHeaders.Clear(); - } - - private async Task ProduceEndAwaited() - { - if (_hasResponseStarted) - { - return; - } - - _hasResponseStarted = true; - - SendResponseHeaders(appCompleted: true); - StartProcessingRequestAndResponseBody(); - - Task flushAsync; - - lock (_stateSync) - { - DisableReads(); - flushAsync = Output.FlushAsync(); - } - await flushAsync; - } - - public unsafe void SendResponseHeaders(bool appCompleted) - { - // Verifies we have sent the statuscode before writing a header - var reasonPhrase = string.IsNullOrEmpty(ReasonPhrase) ? ReasonPhrases.GetReasonPhrase(StatusCode) : ReasonPhrase; - - // This copies data into the underlying buffer - NativeMethods.HttpSetResponseStatusCode(_pInProcessHandler, (ushort)StatusCode, reasonPhrase); - - HttpResponseHeaders.IsReadOnly = true; - foreach (var headerPair in HttpResponseHeaders) - { - var headerValues = headerPair.Value; - var knownHeaderIndex = HttpApiTypes.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerPair.Key); - if (knownHeaderIndex == -1) - { - var headerNameBytes = Encoding.UTF8.GetBytes(headerPair.Key); - for (var i = 0; i < headerValues.Count; i++) - { - var headerValueBytes = Encoding.UTF8.GetBytes(headerValues[i]); - fixed (byte* pHeaderName = headerNameBytes) - { - fixed (byte* pHeaderValue = headerValueBytes) - { - NativeMethods.HttpResponseSetUnknownHeader(_pInProcessHandler, pHeaderName, pHeaderValue, (ushort)headerValueBytes.Length, fReplace: false); - } - } - } - } - else - { - for (var i = 0; i < headerValues.Count; i++) - { - var headerValueBytes = Encoding.UTF8.GetBytes(headerValues[i]); - fixed (byte* pHeaderValue = headerValueBytes) - { - NativeMethods.HttpResponseSetKnownHeader(_pInProcessHandler, knownHeaderIndex, pHeaderValue, (ushort)headerValueBytes.Length, fReplace: false); - } - } - } - } - } - - public void Abort() - { - // TODO - } - - public abstract Task ProcessRequestAsync(); - - public void OnStarting(Func callback, object state) - { - lock (_onStartingSync) - { - if (_hasResponseStarted) - { - throw new InvalidOperationException("Response already started"); - } - - if (_onStarting == null) - { - _onStarting = new Stack, object>>(); - } - _onStarting.Push(new KeyValuePair, object>(callback, state)); - } - } - - public void OnCompleted(Func callback, object state) - { - lock (_onCompletedSync) - { - if (_onCompleted == null) - { - _onCompleted = new Stack, object>>(); - } - _onCompleted.Push(new KeyValuePair, object>(callback, state)); - } - } - - protected async Task FireOnStarting() - { - Stack, object>> onStarting = null; - lock (_onStartingSync) - { - onStarting = _onStarting; - _onStarting = null; - } - if (onStarting != null) - { - try - { - foreach (var entry in onStarting) - { - await entry.Key.Invoke(entry.Value); - } - } - catch (Exception ex) - { - ReportApplicationError(ex); - } - } - } - - protected async Task FireOnCompleted() - { - Stack, object>> onCompleted = null; - lock (_onCompletedSync) - { - onCompleted = _onCompleted; - _onCompleted = null; - } - if (onCompleted != null) - { - foreach (var entry in onCompleted) - { - try - { - await entry.Key.Invoke(entry.Value); - } - catch (Exception ex) - { - ReportApplicationError(ex); - } - } - } - } - - protected void ReportApplicationError(Exception ex) - { - if (_applicationException == null) - { - _applicationException = ex; - } - else if (_applicationException is AggregateException) - { - _applicationException = new AggregateException(_applicationException, ex).Flatten(); - } - else - { - _applicationException = new AggregateException(_applicationException, ex); - } - } - - public void PostCompletion(NativeMethods.REQUEST_NOTIFICATION_STATUS requestNotificationStatus) - { - Debug.Assert(!_operation.HasContinuation, "Pending async operation!"); - - NativeMethods.HttpSetCompletionStatus(_pInProcessHandler, requestNotificationStatus); - NativeMethods.HttpPostCompletion(_pInProcessHandler, 0); - } - - public void IndicateCompletion(NativeMethods.REQUEST_NOTIFICATION_STATUS notificationStatus) - { - NativeMethods.HttpIndicateCompletion(_pInProcessHandler, notificationStatus); - } - - internal void OnAsyncCompletion(int hr, int cbBytes) - { - // Must acquire the _stateSync here as anytime we call complete, we need to hold the lock - // to avoid races with cancellation. - Action continuation; - lock (_stateSync) - { - _reading = false; - continuation = _operation.GetCompletion(hr, cbBytes); - } - - continuation?.Invoke(); - } - - private bool disposedValue = false; // To detect redundant calls - - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - // TODO: dispose managed state (managed objects). - _thisHandle.Free(); - } - if (WindowsUser?.Identity is WindowsIdentity wi) - { - wi.Dispose(); - } - disposedValue = true; - } - } - - // This code added to correctly implement the disposable pattern. - public override void Dispose() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(disposing: true); - } - - private void ThrowResponseAlreadyStartedException(string value) - { - throw new InvalidOperationException("Response already started"); - } - - private WindowsPrincipal GetWindowsPrincipal() - { - NativeMethods.HttpGetAuthenticationInformation(_pInProcessHandler, out var authenticationType, out var token); - - if (token != IntPtr.Zero && authenticationType != null) - { - if ((authenticationType.Equals(NtlmString, StringComparison.OrdinalIgnoreCase) - || authenticationType.Equals(NegotiateString, StringComparison.OrdinalIgnoreCase) - || authenticationType.Equals(BasicString, StringComparison.OrdinalIgnoreCase))) - { - return new WindowsPrincipal(new WindowsIdentity(token, authenticationType)); - } - } - return null; - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContextOfT.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContextOfT.cs deleted file mode 100644 index 0867c3dd06..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpContextOfT.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Buffers; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting.Server; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal class IISHttpContextOfT : IISHttpContext - { - private readonly IHttpApplication _application; - - public IISHttpContextOfT(MemoryPool memoryPool, IHttpApplication application, IntPtr pInProcessHandler, IISOptions options, IISHttpServer server) - : base(memoryPool, pInProcessHandler, options, server) - { - _application = application; - } - - public override async Task ProcessRequestAsync() - { - InitializeContext(); - - var context = default(TContext); - var success = true; - - try - { - context = _application.CreateContext(this); - await _application.ProcessRequestAsync(context); - // TODO Verification of Response - //if (Volatile.Read(ref _requestAborted) == 0) - //{ - // VerifyResponseContentLength(); - //} - } - catch (Exception ex) - { - ReportApplicationError(ex); - success = false; - } - finally - { - if (!HasResponseStarted && _applicationException == null && _onStarting != null) - { - await FireOnStarting(); - // Dispose - } - - if (_onCompleted != null) - { - await FireOnCompleted(); - } - } - - if (Volatile.Read(ref _requestAborted) == 0) - { - await ProduceEnd(); - } - else if (!HasResponseStarted) - { - // If the request was aborted and no response was sent, there's no - // meaningful status code to log. - StatusCode = 0; - success = false; - } - - try - { - _application.DisposeContext(context, _applicationException); - } - catch (Exception ex) - { - // TODO Log this - _applicationException = _applicationException ?? ex; - success = false; - } - finally - { - // The app is finished and there should be nobody writing to the response pipe - Output.Dispose(); - - // The app is finished and there should be nobody reading from the request pipe - Input.Reader.Complete(); - - Task processBodiesTask; - lock (_createReadWriteBodySync) - { - processBodiesTask = _processBodiesTask; - } - await processBodiesTask; - } - return success; - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpRequestBody.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpRequestBody.cs deleted file mode 100644 index be5746c0d3..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpRequestBody.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal class IISHttpRequestBody : Stream - { - private readonly IISHttpContext _httpContext; - - public IISHttpRequestBody(IISHttpContext httpContext) - { - _httpContext = httpContext; - } - - public override bool CanRead => true; - - public override bool CanSeek => false; - - public override bool CanWrite => false; - - public override long Length => throw new NotSupportedException(); - - public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } - - public override void Flush() - { - throw new NotSupportedException(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - return ReadAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult(); - } - - public override unsafe Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - var memory = new Memory(buffer, offset, count); - - return _httpContext.ReadAsync(memory, cancellationToken); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public unsafe override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpResponseBody.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpResponseBody.cs deleted file mode 100644 index f850994a4a..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpResponseBody.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal class IISHttpResponseBody : Stream - { - private readonly IISHttpContext _httpContext; - - public IISHttpResponseBody(IISHttpContext httpContext) - { - _httpContext = httpContext; - } - - public override bool CanRead => false; - - public override bool CanSeek => false; - - public override bool CanWrite => true; - - public override long Length => throw new NotSupportedException(); - - public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } - - public override void Flush() - { - FlushAsync(CancellationToken.None).GetAwaiter().GetResult(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public unsafe override void Write(byte[] buffer, int offset, int count) - { - WriteAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult(); - } - - public override unsafe Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - return _httpContext.WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken); - } - - public override Task FlushAsync(CancellationToken cancellationToken) - { - return _httpContext.FlushAsync(cancellationToken); - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpServer.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpServer.cs deleted file mode 100644 index 49518926ce..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISHttpServer.cs +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Buffers; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.Server; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal class IISHttpServer : IServer - { - private const string WebSocketVersionString = "WEBSOCKET_VERSION"; - - private static NativeMethods.PFN_REQUEST_HANDLER _requestHandler = HandleRequest; - private static NativeMethods.PFN_SHUTDOWN_HANDLER _shutdownHandler = HandleShutdown; - private static NativeMethods.PFN_ASYNC_COMPLETION _onAsyncCompletion = OnAsyncCompletion; - - private IISContextFactory _iisContextFactory; - private readonly MemoryPool _memoryPool = new SlabMemoryPool(); - private GCHandle _httpServerHandle; - private readonly IApplicationLifetime _applicationLifetime; - private readonly IAuthenticationSchemeProvider _authentication; - private readonly IISOptions _options; - - private volatile int _stopping; - private bool Stopping => _stopping == 1; - private int _outstandingRequests; - private readonly TaskCompletionSource _shutdownSignal = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - private bool? _websocketAvailable; - - public IFeatureCollection Features { get; } = new FeatureCollection(); - - // TODO: Remove pInProcessHandler argument - public bool IsWebSocketAvailible(IntPtr pInProcessHandler) - { - // Check if the Http upgrade feature is available in IIS. - // To check this, we can look at the server variable WEBSOCKET_VERSION - // And see if there is a version. Same check that Katana did: - // https://github.com/aspnet/AspNetKatana/blob/9f6e09af6bf203744feb5347121fe25f6eec06d8/src/Microsoft.Owin.Host.SystemWeb/OwinAppContext.cs#L125 - // Actively not locking here as acquiring a lock on every request will hurt perf more than checking the - // server variables a few extra times if a bunch of requests hit the server at the same time. - if (!_websocketAvailable.HasValue) - { - _websocketAvailable = NativeMethods.HttpTryGetServerVariable(pInProcessHandler, WebSocketVersionString, out var webSocketsSupported) - && !string.IsNullOrEmpty(webSocketsSupported); - } - - return _websocketAvailable.Value; - } - - public IISHttpServer(IApplicationLifetime applicationLifetime, IAuthenticationSchemeProvider authentication, IOptions options) - { - _applicationLifetime = applicationLifetime; - _authentication = authentication; - _options = options.Value; - - if (_options.ForwardWindowsAuthentication) - { - authentication.AddScheme(new AuthenticationScheme(IISDefaults.AuthenticationScheme, _options.AuthenticationDisplayName, typeof(IISServerAuthenticationHandler))); - } - } - - public Task StartAsync(IHttpApplication application, CancellationToken cancellationToken) - { - _httpServerHandle = GCHandle.Alloc(this); - - _iisContextFactory = new IISContextFactory(_memoryPool, application, _options, this); - - // Start the server by registering the callback - NativeMethods.HttpRegisterCallbacks(_requestHandler, _shutdownHandler, _onAsyncCompletion, (IntPtr)_httpServerHandle, (IntPtr)_httpServerHandle); - - return Task.CompletedTask; - } - - public Task StopAsync(CancellationToken cancellationToken) - { - void RegisterCancelation() - { - cancellationToken.Register(() => - { - NativeMethods.HttpStopCallsIntoManaged(); - _shutdownSignal.TrySetResult(null); - }); - } - if (Interlocked.Exchange(ref _stopping, 1) == 1) - { - RegisterCancelation(); - - return _shutdownSignal.Task; - } - - // First call back into native saying "DON'T SEND ME ANY MORE REQUESTS" - NativeMethods.HttpStopIncomingRequests(); - - try - { - // Wait for active requests to drain - if (_outstandingRequests > 0) - { - RegisterCancelation(); - } - else - { - // We have drained all requests. Block any callbacks into managed at this point. - NativeMethods.HttpStopCallsIntoManaged(); - _shutdownSignal.TrySetResult(null); - } - } - catch (Exception ex) - { - _shutdownSignal.TrySetException(ex); - } - - return _shutdownSignal.Task; - } - - public void Dispose() - { - _stopping = 1; - - // Block any more calls into managed from native as we are unloading. - NativeMethods.HttpStopCallsIntoManaged(); - _shutdownSignal.TrySetResult(null); - - if (_httpServerHandle.IsAllocated) - { - _httpServerHandle.Free(); - } - - _memoryPool.Dispose(); - } - - private static NativeMethods.REQUEST_NOTIFICATION_STATUS HandleRequest(IntPtr pInProcessHandler, IntPtr pvRequestContext) - { - // Unwrap the server so we can create an http context and process the request - var server = (IISHttpServer)GCHandle.FromIntPtr(pvRequestContext).Target; - Interlocked.Increment(ref server._outstandingRequests); - - var context = server._iisContextFactory.CreateHttpContext(pInProcessHandler); - - ThreadPool.QueueUserWorkItem(state => _ = HandleRequest((IISHttpContext)state), context); - - return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING; - } - - private static async Task HandleRequest(IISHttpContext context) - { - var result = await context.ProcessRequestAsync(); - CompleteRequest(context, result); - } - - private static bool HandleShutdown(IntPtr pvRequestContext) - { - var server = (IISHttpServer)GCHandle.FromIntPtr(pvRequestContext).Target; - server._applicationLifetime.StopApplication(); - return true; - } - - private static NativeMethods.REQUEST_NOTIFICATION_STATUS OnAsyncCompletion(IntPtr pvManagedHttpContext, int hr, int bytes) - { - var context = (IISHttpContext)GCHandle.FromIntPtr(pvManagedHttpContext).Target; - context.OnAsyncCompletion(hr, bytes); - return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING; - } - - private static void CompleteRequest(IISHttpContext context, bool result) - { - // Post completion after completing the request to resume the state machine - context.PostCompletion(ConvertRequestCompletionResults(result)); - - if (Interlocked.Decrement(ref context.Server._outstandingRequests) == 0 && context.Server.Stopping) - { - // All requests have been drained. - NativeMethods.HttpStopCallsIntoManaged(); - context.Server._shutdownSignal.TrySetResult(null); - } - - // Dispose the context - context.Dispose(); - } - - private static NativeMethods.REQUEST_NOTIFICATION_STATUS ConvertRequestCompletionResults(bool success) - { - return success ? NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_CONTINUE - : NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_FINISH_REQUEST; - } - - private class IISContextFactory : IISContextFactory - { - private readonly IHttpApplication _application; - private readonly MemoryPool _memoryPool; - private readonly IISOptions _options; - private readonly IISHttpServer _server; - - public IISContextFactory(MemoryPool memoryPool, IHttpApplication application, IISOptions options, IISHttpServer server) - { - _application = application; - _memoryPool = memoryPool; - _options = options; - _server = server; - } - - public IISHttpContext CreateHttpContext(IntPtr pInProcessHandler) - { - return new IISHttpContextOfT(_memoryPool, _application, pInProcessHandler, _options, _server); - } - } - - ~IISHttpServer() - { - // If this finalize is invoked, try our best to block all calls into managed. - NativeMethods.HttpStopCallsIntoManaged(); - } - } - - // Over engineering to avoid allocations... - internal interface IISContextFactory - { - IISHttpContext CreateHttpContext(IntPtr pInProcessHandler); - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerAuthenticationHandler.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerAuthenticationHandler.cs deleted file mode 100644 index 587490bf50..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerAuthenticationHandler.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Http; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - public class IISServerAuthenticationHandler : IAuthenticationHandler - { - private HttpContext _context; - private IISHttpContext _iisHttpContext; - - internal AuthenticationScheme Scheme { get; private set; } - - public Task AuthenticateAsync() - { - var user = _iisHttpContext.WindowsUser; - if (user != null && user.Identity != null && user.Identity.IsAuthenticated) - { - return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(user, Scheme.Name))); - } - else - { - return Task.FromResult(AuthenticateResult.NoResult()); - } - } - - public Task ChallengeAsync(AuthenticationProperties properties) - { - // We would normally set the www-authenticate header here, but IIS does that for us. - _context.Response.StatusCode = 401; - return Task.CompletedTask; - } - - public Task ForbidAsync(AuthenticationProperties properties) - { - _context.Response.StatusCode = 403; - return Task.CompletedTask; - } - - public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) - { - _iisHttpContext = context.Features.Get(); - if (_iisHttpContext == null) - { - throw new InvalidOperationException("No IISHttpContext found."); - } - - Scheme = scheme; - _context = context; - - return Task.CompletedTask; - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerConstants.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerConstants.cs deleted file mode 100644 index fc137bd159..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerConstants.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal static class IISServerConstants - { - internal const int HResultCancelIO = -2147023901; - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerSetupFilter.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerSetupFilter.cs deleted file mode 100644 index 787c979c96..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/IISServerSetupFilter.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.Server; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal class IISServerSetupFilter : IStartupFilter - { - private string _virtualPath; - - public IISServerSetupFilter(string virtualPath) - { - _virtualPath = virtualPath; - } - - public Action Configure(Action next) - { - return app => - { - var server = app.ApplicationServices.GetService(); - if (server?.GetType() != typeof(IISHttpServer)) - { - throw new InvalidOperationException("Application is running inside IIS process but is not configured to use IIS server."); - } - - app.UsePathBase(_virtualPath); - next(app); - }; - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/OutputProducer.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/Server/OutputProducer.cs deleted file mode 100644 index fddd9db00a..0000000000 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/Server/OutputProducer.cs +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Buffers; -using System.IO.Pipelines; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - internal class OutputProducer - { - private static readonly ArraySegment _emptyData = new ArraySegment(new byte[0]); - - // This locks access to to all of the below fields - private readonly object _contextLock = new object(); - - private ValueTask _flushTask; - private bool _completed = false; - - private readonly Pipe _pipe; - - // https://github.com/dotnet/corefxlab/issues/1334 - // Pipelines don't support multiple awaiters on flush - // this is temporary until it does - private TaskCompletionSource _flushTcs; - private readonly object _flushLock = new object(); - private Action _flushCompleted; - - public OutputProducer(Pipe pipe) - { - _pipe = pipe; - _flushCompleted = OnFlushCompleted; - } - - public PipeReader Reader => _pipe.Reader; - - public Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - return WriteAsync(_emptyData, cancellationToken); - } - - public void Dispose() - { - lock (_contextLock) - { - if (_completed) - { - return; - } - - _completed = true; - _pipe.Writer.Complete(); - } - } - - public void Abort(Exception error) - { - lock (_contextLock) - { - if (_completed) - { - return; - } - - _completed = true; - - _pipe.Reader.CancelPendingRead(); - _pipe.Writer.Complete(error); - } - } - - public Task WriteAsync( - ReadOnlyMemory buffer, - CancellationToken cancellationToken) - { - lock (_contextLock) - { - if (_completed) - { - throw new ObjectDisposedException("Response is already completed"); - } - - _pipe.Writer.Write(buffer.Span); - } - - return FlushAsync(_pipe.Writer, cancellationToken); - } - - private Task FlushAsync(PipeWriter pipeWriter, - CancellationToken cancellationToken) - { - var awaitable = pipeWriter.FlushAsync(cancellationToken); - if (awaitable.IsCompleted) - { - // The flush task can't fail today - return Task.CompletedTask; - } - return FlushAsyncAwaited(awaitable, cancellationToken); - } - - private async Task FlushAsyncAwaited(ValueTask awaitable, CancellationToken cancellationToken) - { - // https://github.com/dotnet/corefxlab/issues/1334 - // Since the flush awaitable doesn't currently support multiple awaiters - // we need to use a task to track the callbacks. - // All awaiters get the same task - lock (_flushLock) - { - _flushTask = awaitable; - if (_flushTcs == null || _flushTcs.Task.IsCompleted) - { - _flushTcs = new TaskCompletionSource(); - - _flushTask.GetAwaiter().OnCompleted(_flushCompleted); - } - } - - try - { - await _flushTcs.Task; - cancellationToken.ThrowIfCancellationRequested(); - } - catch (OperationCanceledException) - { - _completed = true; - throw; - } - } - - private void OnFlushCompleted() - { - try - { - _flushTask.GetAwaiter().GetResult(); - _flushTcs.TrySetResult(null); - } - catch (Exception exception) - { - _flushTcs.TrySetResult(exception); - } - finally - { - _flushTask = default; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs index c236c7eac4..b57ad38b00 100644 --- a/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs +++ b/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs @@ -40,13 +40,6 @@ namespace Microsoft.AspNetCore.Hosting return hostBuilder; } - // Check if in process - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && NativeMethods.IsAspNetCoreModuleLoaded()) - { - - return SetupInProcessServer(hostBuilder); - } - var port = hostBuilder.GetSetting(ServerPort) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{ServerPort}"); var path = hostBuilder.GetSetting(ServerPath) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{ServerPath}"); var pairingToken = hostBuilder.GetSetting(PairingToken) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{PairingToken}"); @@ -107,23 +100,5 @@ namespace Microsoft.AspNetCore.Hosting return hostBuilder; } - - private static IWebHostBuilder SetupInProcessServer(IWebHostBuilder hostBuilder) - { - hostBuilder.UseSetting(nameof(UseIISIntegration), "true"); - hostBuilder.CaptureStartupErrors(true); - - var iisConfigData = NativeMethods.HttpGetApplicationProperties(); - hostBuilder.UseContentRoot(iisConfigData.pwzFullApplicationPath); - return hostBuilder.ConfigureServices( - services => { - services.AddSingleton(); - services.AddSingleton(new IISServerSetupFilter(iisConfigData.pwzVirtualApplicationPath)); - services.AddAuthenticationCore(); - services.Configure( - options => { options.ForwardWindowsAuthentication = iisConfigData.fWindowsAuthEnabled || iisConfigData.fBasicAuthEnabled; } - ); - }); - } } } diff --git a/test/IISIntegration.FunctionalTests/Inprocess/AuthenticationTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/AuthenticationTests.cs deleted file mode 100644 index 4370014007..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/AuthenticationTests.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#if NET461 - -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class AuthenticationTests - { - private readonly IISTestSiteFixture _fixture; - public AuthenticationTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task Authentication_InProcess_IISExpressAsync() - { - var response = await _fixture.Client.GetAsync("/AuthenticationAnonymous"); - - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Anonymous?True", responseText); - - response = await _fixture.Client.GetAsync("/AuthenticationRestricted"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString()); - Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); - - response = await _fixture.Client.GetAsync("/AuthenticationRestrictedNTLM"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString()); - // Note we can't restrict a challenge to a specific auth type, the native auth modules always add themselves. - Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); - - response = await _fixture.Client.GetAsync("/AuthenticationForbidden"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); - - var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - var httpClient = _fixture.DeploymentResult.CreateHttpClient(httpClientHandler); - - response = await httpClient.GetAsync("/AuthenticationAnonymous"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Anonymous?True", responseText); - - response = await httpClient.GetAsync("/AuthenticationRestricted"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotEmpty(responseText); - } - } -} -#elif NETCOREAPP2_0 || NETCOREAPP2_1 -#else -#error Target frameworks need to be updated -#endif diff --git a/test/IISIntegration.FunctionalTests/Inprocess/EnvironmentVariableTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/EnvironmentVariableTests.cs deleted file mode 100644 index 413aa4c35f..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/EnvironmentVariableTests.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class EnvironmentVariableTests - { - private readonly IISTestSiteFixture _fixture; - - public EnvironmentVariableTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task GetUniqueEnvironmentVariable() - { - Assert.Equal("foobar", await _fixture.Client.GetStringAsync("/CheckEnvironmentVariable")); - } - - [ConditionalFact] - public async Task GetLongEnvironmentVariable() - { - Assert.Equal( - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative", - await _fixture.Client.GetStringAsync("/CheckEnvironmentLongValueVariable")); - } - - [ConditionalFact] - public async Task GetExistingEnvironmentVariable() - { - Assert.Contains(";foobarbaz", await _fixture.Client.GetStringAsync("/CheckAppendedEnvironmentVariable")); - } - - [ConditionalFact] - public async Task AuthHeaderEnvironmentVariableRemoved() - { - Assert.DoesNotContain("shouldberemoved", await _fixture.Client.GetStringAsync("/CheckRemoveAuthEnvironmentVariable")); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/FeatureCollectionTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/FeatureCollectionTests.cs deleted file mode 100644 index 8aa54716e3..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/FeatureCollectionTests.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class FeatureCollectionTest - { - private readonly IISTestSiteFixture _fixture; - - public FeatureCollectionTest(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData("FeatureCollectionSetRequestFeatures")] - [InlineData("FeatureCollectionSetResponseFeatures")] - [InlineData("FeatureCollectionSetConnectionFeatures")] - public async Task FeatureCollectionTest_SetHttpContextFeatures(string path) - { - Assert.Equal("Success", await _fixture.Client.GetStringAsync(path + "/path" + "?query")); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/HelloWorldTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/HelloWorldTests.cs deleted file mode 100644 index ce569acfe7..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/HelloWorldTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class HelloWorldInProcessTests - { - private readonly IISTestSiteFixture _fixture; - - public HelloWorldInProcessTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task HelloWorld_InProcess_IISExpress_CoreClr_X64_Portable() - { - Assert.Equal("Hello World", await _fixture.Client.GetStringAsync("/HelloWorld")); - - Assert.Equal("/Path??", await _fixture.Client.GetStringAsync("/HelloWorld/Path%3F%3F?query")); - - Assert.Equal("?query", await _fixture.Client.GetStringAsync("/HelloWorld/Query%3F%3F?query")); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs deleted file mode 100644 index 95c05308bd..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class InvalidReadWriteOperationTests - { - private readonly IISTestSiteFixture _fixture; - - public InvalidReadWriteOperationTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task TestReadOffsetWorks() - { - var result = await _fixture.Client.PostAsync($"/TestReadOffsetWorks", new StringContent("Hello World")); - Assert.Equal("Hello World", await result.Content.ReadAsStringAsync()); - } - - [ConditionalTheory] - [InlineData("/InvalidOffsetSmall")] - [InlineData("/InvalidOffsetLarge")] - [InlineData("/InvalidCountSmall")] - [InlineData("/InvalidCountLarge")] - [InlineData("/InvalidCountWithOffset")] - public async Task TestInvalidReadOperations(string operation) - { - var result = await _fixture.Client.GetStringAsync($"/TestInvalidReadOperations{operation}"); - Assert.Equal("Success", result); - } - - [ConditionalTheory] - [InlineData("/NullBuffer")] - [InlineData("/InvalidCountZeroRead")] - public async Task TestValidReadOperations(string operation) - { - var result = await _fixture.Client.GetStringAsync($"/TestValidReadOperations{operation}"); - Assert.Equal("Success", result); - } - - [ConditionalTheory] - [InlineData("/NullBufferPost")] - [InlineData("/InvalidCountZeroReadPost")] - public async Task TestValidReadOperationsPost(string operation) - { - var result = await _fixture.Client.PostAsync($"/TestValidReadOperations{operation}", new StringContent("hello")); - Assert.Equal("Success", await result.Content.ReadAsStringAsync()); - } - - [ConditionalTheory] - [InlineData("/InvalidOffsetSmall")] - [InlineData("/InvalidOffsetLarge")] - [InlineData("/InvalidCountSmall")] - [InlineData("/InvalidCountLarge")] - [InlineData("/InvalidCountWithOffset")] - public async Task TestInvalidWriteOperations(string operation) - { - var result = await _fixture.Client.GetStringAsync($"/TestInvalidWriteOperations{operation}"); - Assert.Equal("Success", result); - } - - [ConditionalFact] - public async Task TestValidWriteOperations() - { - var result = await _fixture.Client.GetStringAsync($"/TestValidWriteOperations/NullBuffer"); - Assert.Equal("Success", result); - } - - [ConditionalFact] - public async Task TestValidWriteOperationsPost() - { - var result = await _fixture.Client.PostAsync($"/TestValidWriteOperations/NullBufferPost", new StringContent("hello")); - Assert.Equal("Success", await result.Content.ReadAsStringAsync()); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/LargeResponseBodyTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/LargeResponseBodyTests.cs deleted file mode 100644 index 40db2cfdb8..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/LargeResponseBodyTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class LargeResponseBodyTests - { - private readonly IISTestSiteFixture _fixture; - - public LargeResponseBodyTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData(65000)] - [InlineData(1000000)] - [InlineData(10000000)] - [InlineData(100000000)] - public async Task LargeResponseBodyTest_CheckAllResponseBodyBytesWritten(int query) - { - Assert.Equal(new string('a', query), await _fixture.Client.GetStringAsync($"/LargeResponseBody?length={query}")); - } - - [ConditionalFact] - public async Task LargeResponseBodyFromFile_CheckAllResponseBodyBytesWritten() - { - Assert.Equal(200000000, (await _fixture.Client.GetStringAsync($"/LargeResponseFile")).Length); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/ResponseHeaderTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/ResponseHeaderTests.cs deleted file mode 100644 index 47ca0dc808..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/ResponseHeaderTests.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Net.Http.Headers; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - - public class ResponseHeaders - { - private readonly IISTestSiteFixture _fixture; - - public ResponseHeaders(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task AddResponseHeaders_HeaderValuesAreSetCorrectly() - { - var response = await _fixture.Client.GetAsync("ResponseHeaders"); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Request Complete", responseText); - - Assert.True(response.Headers.TryGetValues("UnknownHeader", out var headerValues)); - Assert.Equal("test123=foo", headerValues.First()); - - Assert.True(response.Content.Headers.TryGetValues(HeaderNames.ContentType, out headerValues)); - Assert.Equal("text/plain", headerValues.First()); - - Assert.True(response.Headers.TryGetValues("MultiHeader", out headerValues)); - Assert.Equal(2, headerValues.Count()); - Assert.Equal("1", headerValues.First()); - Assert.Equal("2", headerValues.Last()); - } - - [ConditionalFact] - public async Task ErrorCodeIsSetForExceptionDuringRequest() - { - var response = await _fixture.Client.GetAsync("Throw"); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - Assert.Equal("Internal Server Error", response.ReasonPhrase); - } - - [ConditionalTheory] - [InlineData(200, "custom", "custom")] - [InlineData(500, "", "Internal Server Error")] - [InlineData(999, "", "")] - public async Task CustomErrorCodeWorks(int code, string reason, string expectedReason) - { - var response = await _fixture.Client.GetAsync($"SetCustomErorCode?code={code}&reason={reason}"); - Assert.Equal((HttpStatusCode)code, response.StatusCode); - Assert.Equal(expectedReason, response.ReasonPhrase); - Assert.Equal("Body", await response.Content.ReadAsStringAsync()); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs deleted file mode 100644 index 2e484724e6..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class ResponseInvalidOrderingTest - { - private readonly IISTestSiteFixture _fixture; - - public ResponseInvalidOrderingTest(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData("SetStatusCodeAfterWrite")] - [InlineData("SetHeaderAfterWrite")] - public async Task ResponseInvalidOrderingTests_ExpectFailure(string path) - { - Assert.Equal($"Started_{path}Threw_Finished", await _fixture.Client.GetStringAsync("/ResponseInvalidOrdering/" + path)); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/ServerVariablesTest.cs b/test/IISIntegration.FunctionalTests/Inprocess/ServerVariablesTest.cs deleted file mode 100644 index d6fd676346..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/ServerVariablesTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class ServerVariablesTest - { - private readonly IISTestSiteFixture _fixture; - - public ServerVariablesTest(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ProvidesAccessToServerVariables() - { - var port = _fixture.Client.BaseAddress.Port; - Assert.Equal("SERVER_PORT: " + port, await _fixture.Client.GetStringAsync("/ServerVariable?q=SERVER_PORT")); - Assert.Equal("QUERY_STRING: q=QUERY_STRING", await _fixture.Client.GetStringAsync("/ServerVariable?q=QUERY_STRING")); - } - - [ConditionalFact] - public async Task ReturnsNullForUndefinedServerVariable() - { - Assert.Equal("THIS_VAR_IS_UNDEFINED: (null)", await _fixture.Client.GetStringAsync("/ServerVariable?q=THIS_VAR_IS_UNDEFINED")); - } - - [ConditionalFact] - public async Task BasePathIsNotPrefixedBySlashSlashQuestionMark() - { - Assert.DoesNotContain(@"\\?\", await _fixture.Client.GetStringAsync("/BasePath")); - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs deleted file mode 100644 index 890bd248d3..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs +++ /dev/null @@ -1,234 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; -using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; - - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class StartupTests : LoggedTest - { - public StartupTests(ITestOutputHelper output) : base(output) - { - - } - - [Fact] - public async Task ExpandEnvironmentVariableInWebConfig() - { - var architecture = RuntimeArchitecture.x64; - var dotnetLocation = $"%USERPROFILE%\\.dotnet\\{architecture.ToString()}\\dotnet.exe"; - using (StartLog(out var loggerFactory)) - { - var logger = loggerFactory.CreateLogger("HelloWorldTest"); - - var deploymentParameters = GetBaseDeploymentParameters(); - - // Point to dotnet installed in user profile. - deploymentParameters.EnvironmentVariables["DotnetPath"] = Environment.ExpandEnvironmentVariables(dotnetLocation); // Path to dotnet. - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - - Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%"); - - // Request to base address and check if various parts of the body are rendered & measure the cold startup time. - var response = await RetryHelper.RetryRequest(() => - { - return deploymentResult.HttpClient.GetAsync("HelloWorld"); - }, logger, deploymentResult.HostShutdownToken, retryCount: 30); - - var responseText = await response.Content.ReadAsStringAsync(); - try - { - Assert.Equal("Hello World", responseText); - } - catch (XunitException) - { - logger.LogWarning(response.ToString()); - logger.LogWarning(responseText); - throw; - } - } - } - } - - [Fact] - public async Task InvalidProcessPath_ExpectServerError() - { - var dotnetLocation = "bogus"; - using (StartLog(out var loggerFactory)) - { - var logger = loggerFactory.CreateLogger("HelloWorldTest"); - var deploymentParameters = GetBaseDeploymentParameters(); - - // Point to dotnet installed in user profile. - deploymentParameters.EnvironmentVariables["DotnetPath"] = Environment.ExpandEnvironmentVariables(dotnetLocation); // Path to dotnet. - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - - Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%"); - - // Request to base address and check if various parts of the body are rendered & measure the cold startup time. - var response = await RetryHelper.RetryRequest(() => - { - return deploymentResult.HttpClient.GetAsync("HelloWorld"); - }, logger, deploymentResult.HostShutdownToken, retryCount: 30); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - } - } - } - -#if NETCOREAPP2_0 || NETCOREAPP2_1 - - [Fact] // Consistently fails on CI for net461 - public async Task StandaloneApplication_ExpectCorrectPublish() - { - using (StartLog(out var loggerFactory)) - { - var logger = loggerFactory.CreateLogger("HelloWorldTest"); - - var deploymentParameters = GetBaseDeploymentParameters(); - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - deploymentParameters.ApplicationType = ApplicationType.Standalone; - - // Request to base address and check if various parts of the body are rendered & measure the cold startup time. - var response = await RetryHelper.RetryRequest(() => - { - return deploymentResult.HttpClient.GetAsync("HelloWorld"); - }, logger, deploymentResult.HostShutdownToken, retryCount: 30); - - var responseText = await response.Content.ReadAsStringAsync(); - try - { - Assert.Equal("Hello World", responseText); - } - catch (XunitException) - { - logger.LogWarning(response.ToString()); - logger.LogWarning(responseText); - throw; - } - } - } - } - - [Fact] // Consistently fails on CI for net461 - public async Task StandaloneApplication_AbsolutePathToExe_ExpectCorrectPublish() - { - using (StartLog(out var loggerFactory)) - { - var logger = loggerFactory.CreateLogger("HelloWorldTest"); - - var deploymentParameters = GetBaseDeploymentParameters(); - deploymentParameters.ApplicationType = ApplicationType.Standalone; - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - - Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", $"{deploymentResult.ContentRoot}\\InProcessWebSite.exe"); - - // Request to base address and check if various parts of the body are rendered & measure the cold startup time. - var response = await RetryHelper.RetryRequest(() => - { - return deploymentResult.HttpClient.GetAsync("HelloWorld"); - }, logger, deploymentResult.HostShutdownToken, retryCount: 30); - - var responseText = await response.Content.ReadAsStringAsync(); - try - { - Assert.Equal("Hello World", responseText); - } - catch (XunitException) - { - logger.LogWarning(response.ToString()); - logger.LogWarning(responseText); - throw; - } - } - } - } - -#elif NET461 -#else -#error Target frameworks need to be updated -#endif - - [Fact] - public async Task DetectsOveriddenServer() - { - var testSink = new TestSink(); - using (StartLog(out var loggerFactory)) - { - var testLoggerFactory = new TestLoggerFactory(testSink, true); - loggerFactory.AddProvider(new TestLoggerProvider(testLoggerFactory)); - - using (var deployer = ApplicationDeployerFactory.Create(GetBaseDeploymentParameters("OverriddenServerWebSite"), loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - var response = await deploymentResult.HttpClient.GetAsync("/"); - Assert.False(response.IsSuccessStatusCode); - } - } - Assert.Contains(testSink.Writes, context => context.State.ToString().Contains("Application is running inside IIS process but is not configured to use IIS server")); - } - - private DeploymentParameters GetBaseDeploymentParameters(string site = null) - { - return new DeploymentParameters(Helpers.GetTestWebSitePath(site ?? "InProcessWebSite"), ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64) - { - ServerConfigTemplateContent = File.ReadAllText("AppHostConfig/Http.config"), - SiteName = "HttpTestSite", // This is configured in the Http.config - TargetFramework = "netcoreapp2.1", - ApplicationType = ApplicationType.Portable, - Configuration = GetCurrentConfiguration() - }; - } - - private static string GetCurrentConfiguration() - { -#if DEBUG - return "Debug"; -#else - return "Release"; -#endif - } - - private class TestLoggerProvider : ILoggerProvider - { - private readonly TestLoggerFactory _loggerFactory; - - public TestLoggerProvider(TestLoggerFactory loggerFactory) - { - _loggerFactory = loggerFactory; - } - - public void Dispose() - { - } - - public ILogger CreateLogger(string categoryName) - { - return _loggerFactory.CreateLogger(categoryName); - } - } - } -} diff --git a/test/IISIntegration.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs deleted file mode 100644 index c79c8a462c..0000000000 --- a/test/IISIntegration.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net; -using System.Net.Http; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class SynchronousReadAndWriteTests - { - private readonly IISTestSiteFixture _fixture; - - public SynchronousReadAndWriteTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ReadAndWriteSynchronously() - { - for (int i = 0; i < 100; i++) - { - var content = new StringContent(new string('a', 100000)); - var response = await _fixture.Client.PostAsync("ReadAndWriteSynchronously", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(expected: 110000, actual: responseText.Length); - } - } - - [ConditionalFact] - public async Task ReadAndWriteEcho() - { - var body = new string('a', 100000); - var content = new StringContent(body); - var response = await _fixture.Client.PostAsync("ReadAndWriteEcho", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(body, responseText); - } - - [ConditionalFact] - public async Task ReadAndWriteCopyToAsync() - { - var body = new string('a', 100000); - var content = new StringContent(body); - var response = await _fixture.Client.PostAsync("ReadAndWriteCopyToAsync", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(body, responseText); - } - - [ConditionalFact] - public async Task ReadAndWriteEchoTwice() - { - var requestBody = new string('a', 10000); - var content = new StringContent(requestBody); - var response = await _fixture.Client.PostAsync("ReadAndWriteEchoTwice", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(requestBody.Length * 2, responseText.Length); - } - - [ConditionalFact] - public void ReadAndWriteSlowConnection() - { - var ipHostEntry = Dns.GetHostEntry(_fixture.Client.BaseAddress.Host); - - using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) - { - foreach (var hostEntry in ipHostEntry.AddressList) - { - try - { - socket.Connect(hostEntry, _fixture.Client.BaseAddress.Port); - break; - } - catch (Exception) - { - // Exceptions can be thrown based on ipv6 support - } - } - - Assert.True(socket.Connected); - - var testString = "hello world"; - var request = $"POST /ReadAndWriteSlowConnection HTTP/1.0\r\n" + - $"Content-Length: {testString.Length}\r\n" + - "Host: " + "localhost\r\n" + - "\r\n"; - var bytes = 0; - var requestStringBytes = Encoding.ASCII.GetBytes(request); - var testStringBytes = Encoding.ASCII.GetBytes(testString); - - while ((bytes += socket.Send(requestStringBytes, bytes, 1, SocketFlags.None)) < requestStringBytes.Length) - { - } - - bytes = 0; - while ((bytes += socket.Send(testStringBytes, bytes, 1, SocketFlags.None)) < testStringBytes.Length) - { - Thread.Sleep(100); - } - - var stringBuilder = new StringBuilder(); - var buffer = new byte[4096]; - int size; - while ((size = socket.Receive(buffer, buffer.Length, SocketFlags.None)) != 0) - { - stringBuilder.Append(Encoding.ASCII.GetString(buffer, 0, size)); - } - - Assert.Contains(new StringBuilder().Insert(0, "hello world", 100).ToString(), stringBuilder.ToString()); - } - } - } -} diff --git a/test/IISIntegration.FunctionalTests/UpgradeFeatureDetectionTests.cs b/test/IISIntegration.FunctionalTests/UpgradeFeatureDetectionTests.cs index c8c7a8aefd..8627334de7 100644 --- a/test/IISIntegration.FunctionalTests/UpgradeFeatureDetectionTests.cs +++ b/test/IISIntegration.FunctionalTests/UpgradeFeatureDetectionTests.cs @@ -22,26 +22,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests { } - [Fact] - public Task UpgradeFeatureDetectionEnabled_InProcess_IISExpress_CoreClr_x64_Portable() - { - return UpgradeFeatureDetectionDeployer(RuntimeFlavor.CoreClr, - ApplicationType.Portable, - "AppHostConfig/WebsocketsNotSupported.config", - Helpers.GetInProcessTestSitesPath(), - "Disabled"); - } - - [Fact] - public Task UpgradeFeatureDetectionDisabled_InProcess_IISExpress_CoreClr_x64_Portable() - { - return UpgradeFeatureDetectionDeployer(RuntimeFlavor.CoreClr, - ApplicationType.Portable, - "AppHostConfig/Http.config", - Helpers.GetInProcessTestSitesPath(), - _isWebsocketsSupported); - } - [Fact] public Task UpgradeFeatureDetectionEnabled_OutOfProcess_IISExpress_CoreClr_x64_Portable() { @@ -75,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests { var logger = loggerFactory.CreateLogger("HelloWorldTest"); - var deploymentParameters = new DeploymentParameters(Helpers.GetInProcessTestSitesPath(), serverType, runtimeFlavor, architecture) + var deploymentParameters = new DeploymentParameters(sitePath, serverType, runtimeFlavor, architecture) { EnvironmentName = "UpgradeFeatureDetection", // Will pick the Start class named 'StartupHelloWorld', ServerConfigTemplateContent = (serverType == ServerType.IISExpress) ? File.ReadAllText(configPath) : null, From cfde418a3c6356cff77f06eea6acc0f85b10e380 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 4 May 2018 07:37:44 -0700 Subject: [PATCH 2/2] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 68 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6d392beab8..bd99a3b640 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,44 +3,44 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 0.5.0-preview2-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 + 2.1.0-rtm-15783 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 0.5.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 15.6.82 15.6.82 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 2.0.0 - 2.1.0-rc1-26419-02 - 2.1.0-rc1-30613 + 2.1.0-rtm-26502-02 + 2.1.0-rtm-30721 15.6.1 - 2.0.1 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 + 2.0.3 + 4.5.0-rtm-26502-02 + 4.5.0-rtm-26502-02 + 4.5.0-rtm-26502-02 + 4.5.0-rtm-26502-02 + 4.5.0-rtm-26502-02 + 4.5.0-rtm-26502-02 + 4.5.0-rtm-26502-02 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index d35f5d62cf..27e94579a9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rc1-15774 -commithash:ed5ca9de3c652347dbb0158a9a65eff3471d2114 +version:2.1.0-rtm-15783 +commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774