aspnetcore/src/Kestrel.Transport.Abstractions/Internal/TransportConnection.Feature...

314 lines
10 KiB
C#

using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Net;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Protocols.Features;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{
public partial class TransportConnection : IFeatureCollection,
IHttpConnectionFeature,
IConnectionIdFeature,
IConnectionTransportFeature,
IMemoryPoolFeature,
IApplicationTransportFeature,
ITransportSchedulerFeature
{
private static readonly Type IHttpConnectionFeatureType = typeof(IHttpConnectionFeature);
private static readonly Type IConnectionIdFeatureType = typeof(IConnectionIdFeature);
private static readonly Type IConnectionTransportFeatureType = typeof(IConnectionTransportFeature);
private static readonly Type IMemoryPoolFeatureType = typeof(IMemoryPoolFeature);
private static readonly Type IApplicationTransportFeatureType = typeof(IApplicationTransportFeature);
private static readonly Type ITransportSchedulerFeatureType = typeof(ITransportSchedulerFeature);
private object _currentIHttpConnectionFeature;
private object _currentIConnectionIdFeature;
private object _currentIConnectionTransportFeature;
private object _currentIMemoryPoolFeature;
private object _currentIApplicationTransportFeature;
private object _currentITransportSchedulerFeature;
private int _featureRevision;
private List<KeyValuePair<Type, object>> MaybeExtra;
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<KeyValuePair<Type, object>>(2);
}
for (var i = 0; i < MaybeExtra.Count; i++)
{
if (MaybeExtra[i].Key == key)
{
MaybeExtra[i] = new KeyValuePair<Type, object>(key, value);
return;
}
}
MaybeExtra.Add(new KeyValuePair<Type, object>(key, value));
}
bool IFeatureCollection.IsReadOnly => false;
int IFeatureCollection.Revision => _featureRevision;
string IHttpConnectionFeature.ConnectionId
{
get => ConnectionId;
set => ConnectionId = value;
}
IPAddress IHttpConnectionFeature.RemoteIpAddress
{
get => RemoteAddress;
set => RemoteAddress = value;
}
IPAddress IHttpConnectionFeature.LocalIpAddress
{
get => LocalAddress;
set => LocalAddress = value;
}
int IHttpConnectionFeature.RemotePort
{
get => RemotePort;
set => RemotePort = value;
}
int IHttpConnectionFeature.LocalPort
{
get => LocalPort;
set => LocalPort = value;
}
MemoryPool<byte> IMemoryPoolFeature.MemoryPool => MemoryPool;
IDuplexPipe IConnectionTransportFeature.Transport
{
get => Transport;
set => Transport = value;
}
IDuplexPipe IApplicationTransportFeature.Application
{
get => Application;
set => Application = value;
}
PipeScheduler ITransportSchedulerFeature.InputWriterScheduler => InputWriterScheduler;
PipeScheduler ITransportSchedulerFeature.OutputReaderScheduler => OutputReaderScheduler;
object IFeatureCollection.this[Type key]
{
get
{
if (key == IHttpConnectionFeatureType)
{
return _currentIHttpConnectionFeature;
}
if (key == IConnectionIdFeatureType)
{
return _currentIConnectionIdFeature;
}
if (key == IConnectionTransportFeatureType)
{
return _currentIConnectionTransportFeature;
}
if (key == IMemoryPoolFeatureType)
{
return _currentIMemoryPoolFeature;
}
if (key == IApplicationTransportFeatureType)
{
return _currentIApplicationTransportFeature;
}
if (key == ITransportSchedulerFeatureType)
{
return _currentITransportSchedulerFeature;
}
if (MaybeExtra != null)
{
return ExtraFeatureGet(key);
}
return null;
}
set
{
_featureRevision++;
if (key == IHttpConnectionFeatureType)
{
_currentIHttpConnectionFeature = value;
}
else if (key == IConnectionIdFeatureType)
{
_currentIConnectionIdFeature = value;
}
else if (key == IConnectionTransportFeatureType)
{
_currentIConnectionTransportFeature = value;
}
else if (key == IMemoryPoolFeatureType)
{
_currentIMemoryPoolFeature = value;
}
else if (key == IApplicationTransportFeatureType)
{
_currentIApplicationTransportFeature = value;
}
else if (key == ITransportSchedulerFeatureType)
{
_currentITransportSchedulerFeature = value;
}
else
{
ExtraFeatureSet(key, value);
}
}
}
TFeature IFeatureCollection.Get<TFeature>()
{
if (typeof(TFeature) == IHttpConnectionFeatureType)
{
return (TFeature)_currentIHttpConnectionFeature;
}
else if (typeof(TFeature) == IConnectionIdFeatureType)
{
return (TFeature)_currentIConnectionIdFeature;
}
else if (typeof(TFeature) == IConnectionTransportFeatureType)
{
return (TFeature)_currentIConnectionTransportFeature;
}
else if (typeof(TFeature) == IMemoryPoolFeatureType)
{
return (TFeature)_currentIMemoryPoolFeature;
}
else if (typeof(TFeature) == IApplicationTransportFeatureType)
{
return (TFeature)_currentIApplicationTransportFeature;
}
else if (typeof(TFeature) == ITransportSchedulerFeatureType)
{
return (TFeature)_currentITransportSchedulerFeature;
}
else if (MaybeExtra != null)
{
return (TFeature)ExtraFeatureGet(typeof(TFeature));
}
return default;
}
void IFeatureCollection.Set<TFeature>(TFeature instance)
{
_featureRevision++;
if (typeof(TFeature) == IHttpConnectionFeatureType)
{
_currentIHttpConnectionFeature = instance;
}
else if (typeof(TFeature) == IConnectionIdFeatureType)
{
_currentIConnectionIdFeature = instance;
}
else if (typeof(TFeature) == IConnectionTransportFeatureType)
{
_currentIConnectionTransportFeature = instance;
}
else if (typeof(TFeature) == IMemoryPoolFeatureType)
{
_currentIMemoryPoolFeature = instance;
}
else if (typeof(TFeature) == IApplicationTransportFeatureType)
{
_currentIApplicationTransportFeature = instance;
}
else if (typeof(TFeature) == ITransportSchedulerFeatureType)
{
_currentITransportSchedulerFeature = instance;
}
else
{
ExtraFeatureSet(typeof(TFeature), instance);
}
}
IEnumerator<KeyValuePair<Type, object>> IEnumerable<KeyValuePair<Type, object>>.GetEnumerator() => FastEnumerable().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => FastEnumerable().GetEnumerator();
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
{
if (_currentIHttpConnectionFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpConnectionFeatureType, _currentIHttpConnectionFeature);
}
if (_currentIConnectionIdFeature != null)
{
yield return new KeyValuePair<Type, object>(IConnectionIdFeatureType, _currentIConnectionIdFeature);
}
if (_currentIConnectionTransportFeature != null)
{
yield return new KeyValuePair<Type, object>(IConnectionTransportFeatureType, _currentIConnectionTransportFeature);
}
if (_currentIMemoryPoolFeature != null)
{
yield return new KeyValuePair<Type, object>(IMemoryPoolFeatureType, _currentIMemoryPoolFeature);
}
if (_currentIApplicationTransportFeature != null)
{
yield return new KeyValuePair<Type, object>(IApplicationTransportFeatureType, _currentIApplicationTransportFeature);
}
if (_currentITransportSchedulerFeature != null)
{
yield return new KeyValuePair<Type, object>(ITransportSchedulerFeatureType, _currentITransportSchedulerFeature);
}
if (MaybeExtra != null)
{
foreach (var item in MaybeExtra)
{
yield return item;
}
}
}
}
}