@@ -23,7 +23,7 @@ internal unsafe class AsyncAcceptContext : IValueTaskSource<RequestContext>, IDi
23
23
RunContinuationsAsynchronously = false
24
24
} ;
25
25
26
- private NativeRequestContext _nativeRequestContext ;
26
+ private RequestContext _requestContext ;
27
27
28
28
internal AsyncAcceptContext ( HttpSysListener server )
29
29
{
@@ -53,14 +53,18 @@ internal ValueTask<RequestContext> AcceptAsync()
53
53
54
54
private static void IOCompleted ( AsyncAcceptContext asyncContext , uint errorCode , uint numBytes )
55
55
{
56
- bool complete = false ;
56
+ var complete = false ;
57
+ // This is important to stash a ref to as it's a mutable struct
58
+ ref var mrvts = ref asyncContext . _mrvts ;
59
+ var requestContext = asyncContext . _requestContext ;
60
+ var requestId = requestContext . RequestId ;
57
61
58
62
try
59
63
{
60
64
if ( errorCode != UnsafeNclNativeMethods . ErrorCodes . ERROR_SUCCESS &&
61
65
errorCode != UnsafeNclNativeMethods . ErrorCodes . ERROR_MORE_DATA )
62
66
{
63
- asyncContext . _mrvts . SetException ( new HttpSysException ( ( int ) errorCode ) ) ;
67
+ mrvts . SetException ( new HttpSysException ( ( int ) errorCode ) ) ;
64
68
return ;
65
69
}
66
70
@@ -71,37 +75,39 @@ private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode,
71
75
// points to it we need to hook up our authentication handling code here.
72
76
try
73
77
{
74
- var nativeContext = asyncContext . _nativeRequestContext ;
75
-
76
- if ( server . ValidateRequest ( nativeContext ) && server . ValidateAuth ( nativeContext ) )
78
+ if ( server . ValidateRequest ( requestContext ) && server . ValidateAuth ( requestContext ) )
77
79
{
78
- // It's important that we clear the native request context before we set the result
79
- // we want to reuse this object for future accepts.
80
- asyncContext . _nativeRequestContext = null ;
80
+ // It's important that we clear the request context before we set the result
81
+ // we want to reuse the acceptContext object for future accepts.
82
+ asyncContext . _requestContext = null ;
83
+
84
+ // Initialize features here once we're successfully validated the request
85
+ // TODO: In the future defer this work to the thread pool so we can get off the IO thread
86
+ // as quickly as possible
87
+ requestContext . InitializeFeatures ( ) ;
81
88
82
- var requestContext = new RequestContext ( server , nativeContext ) ;
83
- asyncContext . _mrvts . SetResult ( requestContext ) ;
89
+ mrvts . SetResult ( requestContext ) ;
84
90
85
91
complete = true ;
86
92
}
87
93
}
88
94
catch ( Exception ex )
89
95
{
90
- server . SendError ( asyncContext . _nativeRequestContext . RequestId , StatusCodes . Status400BadRequest ) ;
91
- asyncContext . _mrvts . SetException ( ex ) ;
96
+ server . SendError ( requestId , StatusCodes . Status400BadRequest ) ;
97
+ mrvts . SetException ( ex ) ;
92
98
}
93
99
finally
94
100
{
95
101
if ( ! complete )
96
102
{
97
- asyncContext . AllocateNativeRequest ( size : asyncContext . _nativeRequestContext . Size ) ;
103
+ asyncContext . AllocateNativeRequest ( size : requestContext . Size ) ;
98
104
}
99
105
}
100
106
}
101
107
else
102
108
{
103
109
// (uint)backingBuffer.Length - AlignmentPadding
104
- asyncContext . AllocateNativeRequest ( numBytes , asyncContext . _nativeRequestContext . RequestId ) ;
110
+ asyncContext . AllocateNativeRequest ( numBytes , requestId ) ;
105
111
}
106
112
107
113
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
@@ -114,20 +120,20 @@ private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode,
114
120
{
115
121
// someother bad error, possible(?) return values are:
116
122
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
117
- asyncContext . _mrvts . SetException ( new HttpSysException ( ( int ) statusCode ) ) ;
123
+ mrvts . SetException ( new HttpSysException ( ( int ) statusCode ) ) ;
118
124
}
119
125
}
120
126
}
121
127
catch ( Exception exception )
122
128
{
123
- asyncContext . _mrvts . SetException ( exception ) ;
129
+ mrvts . SetException ( exception ) ;
124
130
}
125
131
}
126
132
127
133
private static unsafe void IOWaitCallback ( uint errorCode , uint numBytes , NativeOverlapped * nativeOverlapped )
128
134
{
129
- var asyncResult = ( AsyncAcceptContext ) ThreadPoolBoundHandle . GetNativeOverlappedState ( nativeOverlapped ) ;
130
- IOCompleted ( asyncResult , errorCode , numBytes ) ;
135
+ var acceptContext = ( AsyncAcceptContext ) ThreadPoolBoundHandle . GetNativeOverlappedState ( nativeOverlapped ) ;
136
+ IOCompleted ( acceptContext , errorCode , numBytes ) ;
131
137
}
132
138
133
139
private uint QueueBeginGetContext ( )
@@ -140,21 +146,21 @@ private uint QueueBeginGetContext()
140
146
uint bytesTransferred = 0 ;
141
147
statusCode = HttpApi . HttpReceiveHttpRequest (
142
148
Server . RequestQueue . Handle ,
143
- _nativeRequestContext . RequestId ,
149
+ _requestContext . RequestId ,
144
150
// Small perf impact by not using HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
145
151
// if the request sends header+body in a single TCP packet
146
152
( uint ) HttpApiTypes . HTTP_FLAGS . NONE ,
147
- _nativeRequestContext . NativeRequest ,
148
- _nativeRequestContext . Size ,
153
+ _requestContext . NativeRequest ,
154
+ _requestContext . Size ,
149
155
& bytesTransferred ,
150
156
_overlapped ) ;
151
157
152
- if ( statusCode == UnsafeNclNativeMethods . ErrorCodes . ERROR_INVALID_PARAMETER && _nativeRequestContext . RequestId != 0 )
158
+ if ( statusCode == UnsafeNclNativeMethods . ErrorCodes . ERROR_INVALID_PARAMETER && _requestContext . RequestId != 0 )
153
159
{
154
160
// we might get this if somebody stole our RequestId,
155
161
// set RequestId to 0 and start all over again with the buffer we just allocated
156
162
// BUGBUG: how can someone steal our request ID? seems really bad and in need of fix.
157
- _nativeRequestContext . RequestId = 0 ;
163
+ _requestContext . RequestId = 0 ;
158
164
retry = true ;
159
165
}
160
166
else if ( statusCode == UnsafeNclNativeMethods . ErrorCodes . ERROR_MORE_DATA )
@@ -178,17 +184,16 @@ private uint QueueBeginGetContext()
178
184
179
185
private void AllocateNativeRequest ( uint ? size = null , ulong requestId = 0 )
180
186
{
181
- _nativeRequestContext ? . ReleasePins ( ) ;
182
- _nativeRequestContext ? . Dispose ( ) ;
187
+ _requestContext ? . ReleasePins ( ) ;
188
+ _requestContext ? . Dispose ( ) ;
183
189
184
190
var boundHandle = Server . RequestQueue . BoundHandle ;
185
-
186
191
if ( _overlapped != null )
187
192
{
188
193
boundHandle . FreeNativeOverlapped ( _overlapped ) ;
189
194
}
190
195
191
- _nativeRequestContext = new NativeRequestContext ( Server . MemoryPool , size , requestId ) ;
196
+ _requestContext = new RequestContext ( Server , size , requestId ) ;
192
197
_overlapped = boundHandle . AllocateNativeOverlapped ( _preallocatedOverlapped ) ;
193
198
}
194
199
@@ -201,11 +206,11 @@ protected virtual void Dispose(bool disposing)
201
206
{
202
207
if ( disposing )
203
208
{
204
- if ( _nativeRequestContext != null )
209
+ if ( _requestContext != null )
205
210
{
206
- _nativeRequestContext . ReleasePins ( ) ;
207
- _nativeRequestContext . Dispose ( ) ;
208
- _nativeRequestContext = null ;
211
+ _requestContext . ReleasePins ( ) ;
212
+ _requestContext . Dispose ( ) ;
213
+ _requestContext = null ;
209
214
210
215
var boundHandle = Server . RequestQueue . BoundHandle ;
211
216
0 commit comments