public IDisposable Start(IServerInformation serverInformation, Func<IFeatureCollection, Task> application) { var disposables = new List<IDisposable>(); var information = (ServerInformation)serverInformation; var engine = new KestrelEngine(_libraryManager, _appShutdownService); engine.Start(1); foreach (var address in information.Addresses) { disposables.Add(engine.CreateServer( address.Scheme, address.Host, address.Port, async frame => { var request = new ServerRequest(frame); await application.Invoke(request.Features); })); } disposables.Add(engine); return new Disposable(() => { foreach (var disposable in disposables) { disposable.Dispose(); } }); }
public KestrelThread(KestrelEngine engine) { _engine = engine; _loop = new UvLoopHandle(); _post = new UvAsyncHandle(); _thread = new Thread(ThreadStart); QueueCloseHandle = PostCloseHandle; }
public async Task ListenerCanCreateAndDispose() { var engine = new KestrelEngine(LibraryManager); engine.Start(1); var started = engine.CreateServer("http", "localhost", 54321, App); started.Dispose(); engine.Dispose(); }
public void Create(Func<IFeatureCollection, Task> app, ServiceContext context, string serverAddress) { _engine = new KestrelEngine(context); _engine.Start(1); _server = _engine.CreateServer( ServerAddress.FromUrl(serverAddress), app); }
public KestrelThread(KestrelEngine engine) { _engine = engine; _appShutdown = engine.AppShutdown; _log = engine.Log; _loop = new UvLoopHandle(_log); _post = new UvAsyncHandle(_log); _thread = new Thread(ThreadStart); QueueCloseHandle = PostCloseHandle; }
public void Create(Func<Frame, Task> app) { _engine = new KestrelEngine(LibraryManager); _engine.Start(1); _server = _engine.CreateServer( "http", "localhost", 54321, app); }
public void WritesDontCompleteImmediatelyWhenTooManyBytesAreAlreadyPreCompleted() { // This should match _maxBytesPreCompleted in SocketOutput var maxBytesPreCompleted = 65536; var completeQueue = new Queue<Action<int>>(); // Arrange var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { completeQueue.Enqueue(triggerCompleted); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext())) using (var memory = new MemoryPool2()) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace()); var trace = new KestrelTrace(new TestKestrelTrace()); var ltp = new LoggingThreadPool(trace); var socketOutput = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue<UvWriteReq>()); var bufferSize = maxBytesPreCompleted; var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize); var completedWh = new ManualResetEventSlim(); Action<Task> onCompleted = (Task t) => { Assert.Null(t.Exception); completedWh.Set(); }; // Act socketOutput.WriteAsync(buffer).ContinueWith(onCompleted); // Assert // The first write should pre-complete since it is <= _maxBytesPreCompleted. Assert.True(completedWh.Wait(1000)); // Arrange completedWh.Reset(); // Act socketOutput.WriteAsync(buffer).ContinueWith(onCompleted); // Assert // Too many bytes are already pre-completed for the second write to pre-complete. Assert.False(completedWh.Wait(1000)); // Act completeQueue.Dequeue()(0); // Assert // Finishing the first write should allow the second write to pre-complete. Assert.True(completedWh.Wait(1000)); } }
public void Create(RequestDelegate app, ServiceContext context, string serverAddress) { context.FrameFactory = (connectionContext, remoteEP, localEP, prepareRequest) => { return new Frame<HttpContext>(new DummyApplication(app), connectionContext, remoteEP, localEP, prepareRequest); }; _engine = new KestrelEngine(context); _engine.Start(1); _server = _engine.CreateServer( ServerAddress.FromUrl(serverAddress)); }
public KestrelThread(KestrelEngine engine) { _engine = engine; _appLifetime = engine.AppLifetime; _log = engine.Log; _threadPool = engine.ThreadPool; _loop = new UvLoopHandle(_log); _post = new UvAsyncHandle(_log); _thread = new Thread(ThreadStart); _thread.Name = "KestrelThread - libuv"; QueueCloseHandle = PostCloseHandle; }
public void WritesDontCompleteImmediatelyWhenTooManyBytesAreAlreadyPreCompleted() { // This should match _maxBytesPreCompleted in SocketOutput var maxBytesPreCompleted = 65536; var completeQueue = new Queue<Action<int>>(); // Arrange var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { completeQueue.Enqueue(triggerCompleted); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new ShutdownNotImplemented())) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId); var socketOutput = new SocketOutput(kestrelThread, socket); var bufferSize = maxBytesPreCompleted; var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize); var completedWh = new ManualResetEventSlim(); Action<Exception, object> onCompleted = (ex, state) => { Assert.Null(ex); Assert.Null(state); completedWh.Set(); }; // Act socketOutput.Write(buffer, onCompleted, null); // Assert // The first write should pre-complete since it is <= _maxBytesPreCompleted. Assert.True(completedWh.Wait(1000)); // Arrange completedWh.Reset(); // Act socketOutput.Write(buffer, onCompleted, null); // Assert // Too many bytes are already pre-completed for the second write to pre-complete. Assert.False(completedWh.Wait(1000)); // Act completeQueue.Dequeue()(0); // Assert // Finishing the first write should allow the second write to pre-complete. Assert.True(completedWh.Wait(1000)); } }
public void CanWrite1MB() { // This test was added because when initially implementing write-behind buffering in // SocketOutput, the write callback would never be invoked for writes larger than // _maxBytesPreCompleted even after the write actually completed. // Arrange var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { triggerCompleted(0); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext())) using (var memory = new MemoryPool2()) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace()); var trace = new KestrelTrace(new TestKestrelTrace()); var ltp = new LoggingThreadPool(trace); var socketOutput = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue<UvWriteReq>()); // I doubt _maxBytesPreCompleted will ever be over a MB. If it is, we should change this test. var bufferSize = 1048576; var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize); var completedWh = new ManualResetEventSlim(); // Act socketOutput.WriteAsync(buffer).ContinueWith( (t) => { Assert.Null(t.Exception); completedWh.Set(); } ); // Assert Assert.True(completedWh.Wait(1000)); } }
public void CanWrite1MB() { // This test was added because when initially implementing write-behind buffering in // SocketOutput, the write callback would never be invoked for writes larger than // _maxBytesPreCompleted even after the write actually completed. // Arrange var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { triggerCompleted(0); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext())) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId, new KestrelTrace(new TestKestrelTrace())); var trace = new KestrelTrace(new TestKestrelTrace()); var socketOutput = new SocketOutput(kestrelThread, socket, 0, trace); // I doubt _maxBytesPreCompleted will ever be over a MB. If it is, we should change this test. var bufferSize = 1048576; var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize); var completedWh = new ManualResetEventSlim(); Action<Exception, object, bool> onCompleted = (ex, state, calledInline) => { Assert.Null(ex); Assert.Null(state); completedWh.Set(); }; // Act socketOutput.Write(buffer, onCompleted, null); // Assert Assert.True(completedWh.Wait(1000)); } }
public void ConnectionCanReadAndWrite(ServiceContext testContext) { var engine = new KestrelEngine(testContext); engine.Start(1); var address = ServerAddress.FromUrl("http://localhost:54321/"); var started = engine.CreateServer(address, App); Console.WriteLine("Started"); var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(new IPEndPoint(IPAddress.Loopback, 54321)); socket.Send(Encoding.ASCII.GetBytes("POST / HTTP/1.0\r\n\r\nHello World")); socket.Shutdown(SocketShutdown.Send); var buffer = new byte[8192]; while (true) { var length = socket.Receive(buffer); if (length == 0) { break; } var text = Encoding.ASCII.GetString(buffer, 0, length); } started.Dispose(); engine.Dispose(); }
public NetworkingTests() { var engine = new KestrelEngine(LibraryManager, new ShutdownNotImplemented()); _uv = engine.Libuv; }
public async Task EngineCanStartAndStop() { var engine = new KestrelEngine(LibraryManager); engine.Start(1); engine.Dispose(); }
public void WritesDontGetCompletedTooQuickly() { // This should match _maxBytesPreCompleted in SocketOutput var maxBytesPreCompleted = 65536; var completeQueue = new Queue<Action<int>>(); var onWriteWh = new ManualResetEventSlim(); // Arrange var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { completeQueue.Enqueue(triggerCompleted); onWriteWh.Set(); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext())) using (var memory = new MemoryPool2()) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace()); var trace = new KestrelTrace(new TestKestrelTrace()); var ltp = new LoggingThreadPool(trace); var socketOutput = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue<UvWriteReq>()); var bufferSize = maxBytesPreCompleted; var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize); var completedWh = new ManualResetEventSlim(); Action<Task> onCompleted = (Task t) => { Assert.Null(t.Exception); completedWh.Set(); }; var completedWh2 = new ManualResetEventSlim(); Action<Task> onCompleted2 = (Task t) => { Assert.Null(t.Exception); completedWh2.Set(); }; // Act (Pre-complete the maximum number of bytes in preparation for the rest of the test) socketOutput.WriteAsync(buffer).ContinueWith(onCompleted); // Assert // The first write should pre-complete since it is <= _maxBytesPreCompleted. Assert.True(completedWh.Wait(1000)); Assert.True(onWriteWh.Wait(1000)); // Arrange completedWh.Reset(); onWriteWh.Reset(); // Act socketOutput.WriteAsync(buffer).ContinueWith(onCompleted); socketOutput.WriteAsync(buffer).ContinueWith(onCompleted2); Assert.True(onWriteWh.Wait(1000)); completeQueue.Dequeue()(0); // Assert // Too many bytes are already pre-completed for the third but not the second write to pre-complete. // https://github.com/aspnet/KestrelHttpServer/issues/356 Assert.True(completedWh.Wait(1000)); Assert.False(completedWh2.Wait(1000)); // Act completeQueue.Dequeue()(0); // Assert // Finishing the first write should allow the second write to pre-complete. Assert.True(completedWh2.Wait(1000)); } }
public void ListenerCanCreateAndDispose() { var engine = new KestrelEngine(LibraryManager, new ShutdownNotImplemented()); engine.Start(1); var started = engine.CreateServer("http", "localhost", 54321, App); started.Dispose(); engine.Dispose(); }
public void ConnectionCanReadAndWrite() { var engine = new KestrelEngine(LibraryManager, new ShutdownNotImplemented()); engine.Start(1); var started = engine.CreateServer("http", "localhost", 54321, App); Console.WriteLine("Started"); var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(new IPEndPoint(IPAddress.Loopback, 54321)); socket.Send(Encoding.ASCII.GetBytes("POST / HTTP/1.0\r\n\r\nHello World")); socket.Shutdown(SocketShutdown.Send); var buffer = new byte[8192]; for (; ;) { var length = socket.Receive(buffer); if (length == 0) { break; } var text = Encoding.ASCII.GetString(buffer, 0, length); } started.Dispose(); engine.Dispose(); }
public NetworkingTests() { var engine = new KestrelEngine(LibraryManager); _uv = engine.Libuv; }
public IDisposable Start(IFeatureCollection serverFeatures, Func<IFeatureCollection, Task> application) { var disposables = new Stack<IDisposable>(); var disposer = new Disposable(() => { foreach (var disposable in disposables) { disposable.Dispose(); } }); try { var information = (KestrelServerInformation)serverFeatures.Get<IKestrelServerInformation>(); var dateHeaderValueManager = new DateHeaderValueManager(); var engine = new KestrelEngine(_libraryManager, new ServiceContext { AppShutdown = _appShutdownService, Log = new KestrelTrace(_logger), DateHeaderValueManager = dateHeaderValueManager }); disposables.Push(engine); disposables.Push(dateHeaderValueManager); if (information.ThreadCount < 0) { throw new ArgumentOutOfRangeException(nameof(information.ThreadCount), information.ThreadCount, "ThreadCount cannot be negative"); } engine.Start(information.ThreadCount == 0 ? 1 : information.ThreadCount); bool atLeastOneListener = false; foreach (var address in information.Addresses) { var parsedAddress = ServerAddress.FromUrl(address); if (parsedAddress == null) { throw new FormatException("Unrecognized listening address: " + address); } else { atLeastOneListener = true; disposables.Push(engine.CreateServer( parsedAddress.Scheme, parsedAddress.Host, parsedAddress.Port, async frame => { var request = new ServerRequest(frame); await application.Invoke(request.Features).ConfigureAwait(false); })); } } if (!atLeastOneListener) { throw new InvalidOperationException("No recognized listening addresses were configured."); } return disposer; } catch { disposer.Dispose(); throw; } }
public void EngineCanStartAndStop() { var engine = new KestrelEngine(LibraryManager, new TestServiceContext()); engine.Start(1); engine.Dispose(); }
public void ListenerCanCreateAndDispose() { var engine = new KestrelEngine(LibraryManager, new TestServiceContext()); engine.Start(1); var started = engine.CreateServer("http", "localhost", 54321, App); started.Dispose(); engine.Dispose(); }
public void ProducingStartAndProducingCompleteCanBeUsedDirectly() { int nBuffers = 0; var nBufferWh = new ManualResetEventSlim(); var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { nBuffers = buffers; nBufferWh.Set(); triggerCompleted(0); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext())) using (var memory = new MemoryPool2()) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace()); var trace = new KestrelTrace(new TestKestrelTrace()); var ltp = new LoggingThreadPool(trace); var socketOutput = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue<UvWriteReq>()); // block 1 var start = socketOutput.ProducingStart(); start.Block.End = start.Block.Data.Offset + start.Block.Data.Count; // block 2 var block2 = memory.Lease(); block2.End = block2.Data.Offset + block2.Data.Count; start.Block.Next = block2; var end = new MemoryPoolIterator2(block2, block2.End); socketOutput.ProducingComplete(end); // A call to Write is required to ensure a write is scheduled socketOutput.WriteAsync(default(ArraySegment<byte>)); Assert.True(nBufferWh.Wait(1000)); Assert.Equal(2, nBuffers); } }
public void EngineCanStartAndStop(ServiceContext testContext) { var engine = new KestrelEngine(testContext); engine.Start(1); engine.Dispose(); }
public void ListenerCanCreateAndDispose(ServiceContext testContext) { var engine = new KestrelEngine(testContext); engine.Start(1); var address = ServerAddress.FromUrl("http://localhost:54321/"); var started = engine.CreateServer(address, App); started.Dispose(); engine.Dispose(); }
public IDisposable Start(IFeatureCollection serverFeatures, Func <IFeatureCollection, Task> application) { var disposables = new Stack <IDisposable>(); var disposer = new Disposable(() => { foreach (var disposable in disposables) { disposable.Dispose(); } }); try { var information = (KestrelServerInformation)serverFeatures.Get <IKestrelServerInformation>(); var dateHeaderValueManager = new DateHeaderValueManager(); var engine = new KestrelEngine(_libraryManager, new ServiceContext { AppShutdown = _appShutdownService, Log = new KestrelTrace(_logger), DateHeaderValueManager = dateHeaderValueManager }); disposables.Push(engine); disposables.Push(dateHeaderValueManager); if (information.ThreadCount < 0) { throw new ArgumentOutOfRangeException(nameof(information.ThreadCount), information.ThreadCount, "ThreadCount cannot be negative"); } engine.Start(information.ThreadCount == 0 ? 1 : information.ThreadCount); bool atLeastOneListener = false; foreach (var address in information.Addresses) { var parsedAddress = ServerAddress.FromUrl(address); if (parsedAddress == null) { throw new FormatException("Unrecognized listening address: " + address); } else { atLeastOneListener = true; disposables.Push(engine.CreateServer( parsedAddress.Scheme, parsedAddress.Host, parsedAddress.Port, async frame => { var request = new ServerRequest(frame); await application.Invoke(request.Features).ConfigureAwait(false); })); } } if (!atLeastOneListener) { throw new InvalidOperationException("No recognized listening addresses were configured."); } return(disposer); } catch { disposer.Dispose(); throw; } }
public void EngineCanStartAndStop() { var engine = new KestrelEngine(LibraryManager, new ShutdownNotImplemented()); engine.Start(1); engine.Dispose(); }
public NetworkingTests() { var engine = new KestrelEngine(new TestServiceContext()); _uv = engine.Libuv; _logger = engine.Log; }
public MultipleLoopTests() { var engine = new KestrelEngine(new TestServiceContext()); _uv = engine.Libuv; _logger = engine.Log; }
public MultipleLoopTests() { var engine = new KestrelEngine(LibraryManager, new ShutdownNotImplemented()); _uv = engine.Libuv; }