#43 Honor CancellationTokens in GetClientCertificateAsync.

This commit is contained in:
Chris R 2015-08-07 16:01:36 -07:00
parent a24fd18dc0
commit 28d3b18686
2 changed files with 14 additions and 6 deletions

View File

@ -50,14 +50,20 @@ namespace Microsoft.Net.Http.Server
private int _clientCertError; private int _clientCertError;
private X509Certificate2 _clientCert; private X509Certificate2 _clientCert;
private Exception _clientCertException; private Exception _clientCertException;
private CancellationTokenRegistration _cancellationRegistration;
internal ClientCertLoader(RequestContext requestContext) internal ClientCertLoader(RequestContext requestContext, CancellationToken cancellationToken)
{ {
_requestContext = requestContext; _requestContext = requestContext;
_tcs = new TaskCompletionSource<object>(); _tcs = new TaskCompletionSource<object>();
// we will use this overlapped structure to issue async IO to ul // we will use this overlapped structure to issue async IO to ul
// the event handle will be put in by the BeginHttpApi2.ERROR_SUCCESS() method // the event handle will be put in by the BeginHttpApi2.ERROR_SUCCESS() method
Reset(CertBoblSize); Reset(CertBoblSize);
if (cancellationToken.CanBeCanceled)
{
_cancellationRegistration = cancellationToken.Register(RequestContext.AbortDelegate, _requestContext);
}
} }
internal X509Certificate2 ClientCert internal X509Certificate2 ClientCert
@ -162,9 +168,8 @@ namespace Microsoft.Net.Http.Server
// ERROR_NOT_FOUND - which means the client did not provide the cert // ERROR_NOT_FOUND - which means the client did not provide the cert
// If this is important, the server should respond with 403 forbidden // If this is important, the server should respond with 403 forbidden
// HTTP.SYS will not do this for you automatically // HTTP.SYS will not do this for you automatically
internal Task LoadClientCertificateAsync(CancellationToken cancellationToken) internal Task LoadClientCertificateAsync()
{ {
// TODO: cancellation support? Abort the request?
uint size = CertBoblSize; uint size = CertBoblSize;
bool retry; bool retry;
do do
@ -218,14 +223,15 @@ namespace Microsoft.Net.Http.Server
// May be null // May be null
_clientCert = cert; _clientCert = cert;
_clientCertError = certErrors; _clientCertError = certErrors;
_tcs.TrySetResult(null);
Dispose(); Dispose();
_tcs.TrySetResult(null);
} }
private void Fail(Exception ex) private void Fail(Exception ex)
{ {
// TODO: Log // TODO: Log
_clientCertException = ex; _clientCertException = ex;
Dispose();
_tcs.TrySetResult(null); _tcs.TrySetResult(null);
} }
@ -328,6 +334,7 @@ namespace Microsoft.Net.Http.Server
{ {
if (disposing) if (disposing)
{ {
_cancellationRegistration.Dispose();
if (_overlapped != null) if (_overlapped != null)
{ {
_memoryBlob = null; _memoryBlob = null;

View File

@ -451,11 +451,12 @@ namespace Microsoft.Net.Http.Server
{ {
return _clientCert; return _clientCert;
} }
cancellationToken.ThrowIfCancellationRequested();
ClientCertLoader certLoader = new ClientCertLoader(RequestContext); ClientCertLoader certLoader = new ClientCertLoader(RequestContext, cancellationToken);
try try
{ {
await certLoader.LoadClientCertificateAsync(cancellationToken).SupressContext(); await certLoader.LoadClientCertificateAsync().SupressContext();
// Populate the environment. // Populate the environment.
if (certLoader.ClientCert != null) if (certLoader.ClientCert != null)
{ {