aspnetcore/src/Microsoft.AspNetCore.Server.../KestrelEngine.cs

114 lines
3.5 KiB
C#

// 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<KestrelThread>();
}
public Libuv Libuv { get; private set; }
public List<KestrelThread> 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<IDisposable>();
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;
}
}
}
}