// 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; using Microsoft.AspNet.Http; using Microsoft.AspNet.Server.Kestrel.Http; using Microsoft.AspNet.Server.Kestrel.Networking; namespace Microsoft.AspNet.Server.Kestrel { public class KestrelEngine : ServiceContext, IDisposable { public KestrelEngine(ServiceContext context) : this(new Libuv(), context) { } // For testing internal KestrelEngine(Libuv uv, ServiceContext context) : base(context) { Libuv = uv; Threads = new List(); } public Libuv Libuv { get; private set; } public List Threads { get; private set; } public void Start(int count) { for (var index = 0; index < count; index++) { Threads.Add(new KestrelThread(this)); } foreach (var thread in Threads) { thread.StartAsync().Wait(); } } public void Dispose() { foreach (var thread in Threads) { thread.Stop(TimeSpan.FromSeconds(2.5)); } Threads.Clear(); } public IDisposable CreateServer(ServerAddress address) { var listeners = new List(); var usingPipes = address.IsUnixPipe; try { var pipeName = (Libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n"); var single = Threads.Count == 1; var first = true; foreach (var thread in Threads) { if (single) { var listener = usingPipes ? (Listener) new PipeListener(this) : new TcpListener(this); listeners.Add(listener); listener.StartAsync(address, thread).Wait(); } else if (first) { var listener = usingPipes ? (ListenerPrimary) new PipeListenerPrimary(this) : new TcpListenerPrimary(this); listeners.Add(listener); listener.StartAsync(pipeName, address, thread).Wait(); } else { var listener = usingPipes ? (ListenerSecondary) new PipeListenerSecondary(this) : new TcpListenerSecondary(this); listeners.Add(listener); listener.StartAsync(pipeName, address, thread).Wait(); } first = false; } return new Disposable(() => { foreach (var listener in listeners) { listener.Dispose(); } }); } catch { foreach (var listener in listeners) { listener.Dispose(); } throw; } } } }