public override int EndRead(IAsyncResult asyncResult) #endif { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } RequestStreamAsyncResult castedAsyncResult = asyncResult as RequestStreamAsyncResult; if (castedAsyncResult == null || castedAsyncResult.RequestStream != this) { throw new ArgumentException(Resources.Exception_WrongIAsyncResult, "asyncResult"); } if (castedAsyncResult.EndCalled) { throw new InvalidOperationException(Resources.Exception_EndCalledMultipleTimes); } castedAsyncResult.EndCalled = true; // wait & then check for errors // Throws on failure int dataRead = castedAsyncResult.Task.Result; // TODO: Verbose log #dataRead. return(dataRead); }
private static void IOCompleted(RequestStreamAsyncResult asyncResult, uint errorCode, uint numBytes) { try { if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { asyncResult.Fail(new IOException(string.Empty, new WebListenerException((int)errorCode))); } else { // TODO: Verbose log dump data read asyncResult.Complete((int)numBytes, errorCode); } } catch (Exception e) { asyncResult.Fail(e); } }
public override unsafe Task <int> ReadAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken) { ValidateReadBuffer(buffer, offset, size); if (_closed) { return(Task.FromResult <int>(0)); } if (cancellationToken.IsCancellationRequested) { return(Helpers.CanceledTask <int>()); } // TODO: Verbose log parameters RequestStreamAsyncResult asyncResult = null; uint dataRead = 0; if (_dataChunkIndex != -1) { dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); if (_dataChunkIndex != -1 && dataRead == size) { UpdateAfterRead(UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS, dataRead); // TODO: Verbose log #dataRead return(Task.FromResult <int>((int)dataRead)); } } if (_dataChunkIndex == -1 && dataRead < size) { uint statusCode = 0; offset += (int)dataRead; size -= (int)dataRead; // the http.sys team recommends that we limit the size to 128kb if (size > MaxReadSize) { size = MaxReadSize; } var cancellationRegistration = default(CancellationTokenRegistration); if (cancellationToken.CanBeCanceled) { cancellationRegistration = cancellationToken.Register(RequestContext.AbortDelegate, _requestContext); } asyncResult = new RequestStreamAsyncResult(this, null, null, buffer, offset, dataRead, cancellationRegistration); uint bytesReturned; try { uint flags = 0; statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( _requestContext.RequestQueueHandle, _requestContext.RequestId, flags, asyncResult.PinnedBuffer, (uint)size, out bytesReturned, asyncResult.NativeOverlapped); } catch (Exception e) { asyncResult.Dispose(); Abort(); LogHelper.LogException(_requestContext.Logger, "ReadAsync", e); throw; } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { asyncResult.Dispose(); if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { uint totalRead = dataRead + bytesReturned; UpdateAfterRead(statusCode, totalRead); // TODO: Verbose log totalRead return(Task.FromResult <int>((int)totalRead)); } else { Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode)); LogHelper.LogException(_requestContext.Logger, "ReadAsync", exception); Abort(); throw exception; } } else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && WebListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.Dispose(); uint totalRead = dataRead + bytesReturned; UpdateAfterRead(statusCode, totalRead); // TODO: Verbose log return(Task.FromResult <int>((int)totalRead)); } } return(asyncResult.Task); }
public override unsafe IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state) #endif { ValidateReadBuffer(buffer, offset, size); if (_closed) { RequestStreamAsyncResult result = new RequestStreamAsyncResult(this, state, callback); result.Complete(0); return(result); } // TODO: Verbose log parameters RequestStreamAsyncResult asyncResult = null; uint dataRead = 0; if (_dataChunkIndex != -1) { dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); if (_dataChunkIndex != -1 && dataRead == size) { asyncResult = new RequestStreamAsyncResult(this, state, callback, buffer, offset, 0); asyncResult.Complete((int)dataRead); } } if (_dataChunkIndex == -1 && dataRead < size) { uint statusCode = 0; offset += (int)dataRead; size -= (int)dataRead; // the http.sys team recommends that we limit the size to 128kb if (size > MaxReadSize) { size = MaxReadSize; } asyncResult = new RequestStreamAsyncResult(this, state, callback, buffer, offset, dataRead); uint bytesReturned; try { uint flags = 0; statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( _requestContext.RequestQueueHandle, _requestContext.RequestId, flags, asyncResult.PinnedBuffer, (uint)size, out bytesReturned, asyncResult.NativeOverlapped); } catch (Exception e) { LogHelper.LogException(_requestContext.Logger, "BeginRead", e); asyncResult.Dispose(); throw; } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { asyncResult.Dispose(); if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { asyncResult = new RequestStreamAsyncResult(this, state, callback, dataRead); asyncResult.Complete((int)bytesReturned); } else { Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode)); LogHelper.LogException(_requestContext.Logger, "BeginRead", exception); Abort(); throw exception; } } else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && WebListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesReturned); } } return(asyncResult); }