-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Initial commit to System.Net.HttpListener #13502
Conversation
{ | ||
internal unsafe static partial class HttpApi | ||
{ | ||
internal static readonly HTTPAPI_VERSION Version = new HTTPAPI_VERSION() { HttpApiMajorVersion = 2, HttpApiMinorVersion = 0 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s_version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
{ | ||
internal static readonly HTTPAPI_VERSION Version = new HTTPAPI_VERSION() { HttpApiMajorVersion = 2, HttpApiMinorVersion = 0 }; | ||
|
||
internal static readonly bool Supported = InitHttpApi(Version); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s_supported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
|
||
internal static partial class Interop | ||
{ | ||
internal unsafe static partial class HttpApi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we scope the unsafe to be only where it's needed, rather than the whole class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
internal struct HTTP_KNOWN_HEADER | ||
{ | ||
internal ushort RawValueLength; | ||
internal sbyte* pRawValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why sbyte rather than byte? (Same question for the other occurrences below.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as desktop code.
[DllImport(Libraries.HttpApi, SetLastError = true)] | ||
internal static extern uint HttpCloseServerSession(ulong serverSessionId); | ||
|
||
internal class SafeLocalFreeChannelBinding : ChannelBinding |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: sealed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
{ | ||
SafeLocalFreeChannelBinding result; | ||
|
||
result = LocalAllocChannelBinding(LMEM_FIXED, (UIntPtr)cb); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the declaration and initialization can be combined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
internal class SafeLocalFreeChannelBinding : ChannelBinding | ||
{ | ||
private const int LMEM_FIXED = 0; | ||
private int _size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type needs a parameterless ctor in order to work with the P/Invoke. The compiler is providing one by default, but it's public... consider adding an explicit one that's private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
} | ||
|
||
[DllImport(Interop.Libraries.Heap, EntryPoint = "LocalAlloc", SetLastError = true)] | ||
internal static extern SafeLocalFreeChannelBinding LocalAllocChannelBinding(int uFlags, UIntPtr sizetdwBytes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Why not just call the method LocalAlloc rather than calling it LocalAllocChannelBinding and using EntryPoint to change its name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah makes sense, it was copied from Desktop code.
"WWW-Authenticate", | ||
}; | ||
|
||
private static Dictionary<string, int> s_hashtable = CreateTable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: readonly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
//} | ||
|
||
//NetEventSource.Exit(null); | ||
//return endpoint; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the plan for all of this commented out code? Is there a TODO to follow-up on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, am working on it.
//} | ||
|
||
//NetEventSource.Exit(null); | ||
//return endpoint; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment/question
|
||
namespace System.Net.Security | ||
{ | ||
// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this SafeDeleteContext differ from the one we already have in the repo?
https://github.com/dotnet/corefx/blob/master/src/Common/src/System/Net/Security/Unix/SafeDeleteContext.cs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see, you just separated it out of SecuritySafeHandles.cs. Ok.
In reply to: 87213631 [](ancestors = 87213631)
@@ -43,7 +43,6 @@ private void Trace() | |||
|
|||
~DebugSafeHandle() | |||
{ | |||
DebugThreadTracking.SetThreadSource(ThreadKinds.Finalization); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this removed? I don't know what its purpose was, just wondering why it's going away.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @ericeil
|
||
namespace System.Net | ||
{ | ||
internal unsafe class AsyncRequestContext : RequestContextBase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: sealed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
{ | ||
private NativeOverlapped* _nativeOverlapped; | ||
private ThreadPoolBoundHandle _boundHandle; | ||
private ListenerAsyncResult _result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: readonly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
if (_nativeOverlapped != null) | ||
{ | ||
Debug.Assert(!disposing, "AsyncRequestContext::Dispose()|Must call ReleasePins() before calling Dispose()."); | ||
if (!Environment.HasShutdownStarted || disposing) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!Environment.HasShutdownStarted || [](start = 20, length = 35)
Do we know why this check is here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CIPop Any idea?
|
||
namespace System.Net | ||
{ | ||
internal class CaseInsensitiveAsciiComparer : IEqualityComparer, IComparer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this differ from the CaseInsensitiveAscii comparer already in the repo?
https://github.com/dotnet/corefx/blob/master/src/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs#L496
If possible, we should combine them to avoid duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, confirmed it's the same. Will reuse.
s_toServerStringFunc = (Func<Cookie, string>)typeof(Cookie).GetMethod("ToServerString").CreateDelegate(typeof(Func<Cookie, string>)); | ||
} | ||
return s_toServerStringFunc(cookie); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@weshaggard, FYI on another reflection case to access internals in another assembly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we add a TODO here?
This can be solved in other ways (e.g. factoring then importing the relevant code or exposing a public API, etc.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created issue #13607 to track.
//} | ||
finally | ||
{ | ||
//if (NetEventSource.IsEnabled) NetEventSource.Exit(NetEventSource.ComponentType.HttpListener, this, "Close", ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this tracing should be fixed and uncommented.
namespace System.Net | ||
{ | ||
public sealed unsafe partial class HttpListener | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a TODO comment for https://github.com/dotnet/corefx/issues/13187
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
|
||
private static bool InitHttpApi(HTTPAPI_VERSION version) | ||
{ | ||
uint statusCode = HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any platforms we need to run on where this function isn't exported? I'm wondering if we need a try/catch here to return false if this fails for any reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In .Net Desktop we check for Win7+ for this call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Priya91 To clarify: this is good as written and no more changes are required. CoreFX will only run on Win7 and above which support the above initialization code.
private string _realm; | ||
private SafeHandle _requestQueueHandle; | ||
private ThreadPoolBoundHandle _requestQueueBoundHandle; | ||
private volatile State _state; // m_State is set only within lock blocks, but often read outside locks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: wrong name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
private HttpListenerTimeoutManager _timeoutManager; | ||
private bool _V2Initialized; | ||
|
||
private Hashtable _disconnectResults; // ulong -> DisconnectAsyncResult |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hashtable _disconnectResults; // ulong -> DisconnectAsyncResult [](start = 16, length = 71)
Should this be a Dictionary<ulong, DisconnectAsyncResult>
then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
private Hashtable _disconnectResults; // ulong -> DisconnectAsyncResult | ||
private object _internalLock; | ||
|
||
internal Hashtable m_UriPrefixes = new Hashtable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_UriPrefixes [](start = 27, length = 13)
Nit: _uriPrefixes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
private bool _V2Initialized; | ||
|
||
private Hashtable _disconnectResults; // ulong -> DisconnectAsyncResult | ||
private object _internalLock; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
readonly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
CheckDisposed(); | ||
if (value == null) | ||
{ | ||
throw new ArgumentNullException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nameof(value)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
Big Plus for working on this! HttpListener must be treated as a key infrastructure component for productions systems from day one. It only stands to reason that this would ultimately be the underlying http server for ASP.Net Core (as in the case of Full FX ASP.NET self hosting ) and "Kestrel" would be a thing of the past... |
Thank you for the feedback, but no. The ASP.NET team (both at Microsoft and the community) has and continues to invest years and years of dev time into making that stack as efficient and programmable as possible, on both Windows and Unix, evolving it both in terms of implementation and API to do so. We do not plan to duplicate such efforts with HttpListener, nor are we able to take the API-level breaks necessary to bring it up to performance par. It is being exposed as part of corefx for compatibility, to enable code currently using it, but for production scenarios, I recommend using kestrel, ASP.NET, etc. |
@stephentoub The "ASP.NET" Stack has nothing to do with either HttpListener or "Kestrel" and if backward compatibility drives this effort then your duplicating efforts (and wasting time) as we speak... since nobody should care about the underlying HttpListener implementation (e.g Http.sys) but rather about the interface so for all intent and purposes "Kestrel" should expose HttpListener interface and get it over with. It's a simple interface and there is no reason it should not suit production scenarios regardless of the stack built on top of it. |
That is not the direction we are going. Thanks. |
dab4478
to
b70e653
Compare
@stephentoub @CIPop Addressed the PR feedback and filed issues on pending workitems. Plan to merge PR after CI passes, will continue watching the PR, and address additional comments in separate PR. This PR is getting too big to keep track of the work. cc @karelz |
Thanks, @Priya91. |
This gets @ericeil PR #13287 in. Fixed merged conflicts.
cc @stephentoub @davidsh @CIPop @geoffkizer @karelz