Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / _ListenerRequestStream.cs / 2 / _ListenerRequestStream.cs
// ------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // // ----------------------------------------------------------------------------- namespace System.Net { using System.IO; using System.Runtime.InteropServices; using System.ComponentModel; using System.Threading; using System.Collections; using System.Security.Permissions; unsafe class HttpRequestStream : Stream { private HttpListenerContext m_HttpContext; private uint m_DataChunkOffset; private int m_DataChunkIndex; private bool m_Closed; private const int MaxReadSize = 0x20000; //http.sys recommends we limit reads to 128k internal HttpRequestStream(HttpListenerContext httpContext) { GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::.ctor() HttpListenerContext#" + ValidationHelper.HashString(httpContext)); m_HttpContext = httpContext; } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return false; } } public override bool CanRead { get { return true; } } /* // Consider removing. public bool DataAvailable { get { return !m_Closed; } } */ public override void Flush() { } public override long Length { get { throw new NotSupportedException(SR.GetString(SR.net_noseek)); } } public override long Position { get { throw new NotSupportedException(SR.GetString(SR.net_noseek)); } set { throw new NotSupportedException(SR.GetString(SR.net_noseek)); } } public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(SR.GetString(SR.net_noseek)); } public override void SetLength(long value) { throw new NotSupportedException(SR.GetString(SR.net_noseek)); } public override int Read([In, Out] byte[] buffer, int offset, int size) { if(Logging.On)Logging.Enter(Logging.HttpListener, this, "Read", ""); GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::Read() size:" + size + " offset:" + offset); if (buffer==null) { throw new ArgumentNullException("buffer"); } if (offset<0 || offset>buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (size<0 || size>buffer.Length-offset) { throw new ArgumentOutOfRangeException("size"); } if (size==0 || m_Closed) { if(Logging.On)Logging.Exit(Logging.HttpListener, this, "Read", "dataRead:0"); return 0; } uint dataRead = 0; if (m_DataChunkIndex != -1) { dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(m_HttpContext.Request.RequestBuffer, m_HttpContext.Request.OriginalBlobAddress, ref m_DataChunkIndex, ref m_DataChunkOffset, buffer, offset, size); } if(m_DataChunkIndex == -1 && dataRead < size){ GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::Read() size:" + size + " offset:" + offset); uint statusCode = 0; uint extraDataRead = 0; offset+= (int) dataRead; size-=(int)dataRead; //the http.sys team recommends that we limit the size to 128kb if(size > MaxReadSize){ size = MaxReadSize; } fixed (byte *pBuffer = buffer) { // issue unmanaged blocking call GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::Read() calling UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody"); statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY, (void*)(pBuffer + offset), (uint)size, &extraDataRead, null); dataRead+=extraDataRead; GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::Read() call to UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if(Logging.On)Logging.Exception(Logging.HttpListener, this, "Read", exception); throw exception; } UpdateAfterRead(statusCode, dataRead); } if(Logging.On)Logging.Dump(Logging.HttpListener, this, "Read", buffer, offset, (int)dataRead); GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::Read() returning dataRead:" + dataRead); if(Logging.On)Logging.Exit(Logging.HttpListener, this, "Read", "dataRead:" + dataRead); return (int)dataRead; } void UpdateAfterRead(uint statusCode, uint dataRead) { GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::UpdateAfterRead() statusCode:" + statusCode + " m_Closed:" + m_Closed); if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF || dataRead == 0) { Close(); } GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::UpdateAfterRead() statusCode:" + statusCode + " m_Closed:" + m_Closed); } [HostProtection(ExternalThreading=true)] public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if(Logging.On)Logging.Enter(Logging.HttpListener, this, "BeginRead", ""); GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::BeginRead() buffer.Length:" + buffer.Length + " size:" + size + " offset:" + offset); if (buffer==null) { throw new ArgumentNullException("buffer"); } if (offset<0 || offset>buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (size<0 || size>buffer.Length-offset) { throw new ArgumentOutOfRangeException("size"); } if (size==0 || m_Closed) { if(Logging.On)Logging.Exit(Logging.HttpListener, this, "BeginRead", ""); HttpRequestStreamAsyncResult result = new HttpRequestStreamAsyncResult(this, state, callback); result.InvokeCallback((uint) 0); return result; } HttpRequestStreamAsyncResult asyncResult = null; uint dataRead = 0; if (m_DataChunkIndex != -1) { dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(m_HttpContext.Request.RequestBuffer, m_HttpContext.Request.OriginalBlobAddress, ref m_DataChunkIndex, ref m_DataChunkOffset, buffer, offset, size); if (m_DataChunkIndex != -1 && dataRead == size) { asyncResult = new HttpRequestStreamAsyncResult(this, state, callback, buffer, offset, (uint)size, 0); asyncResult.InvokeCallback(dataRead); } } if(m_DataChunkIndex == -1 && dataRead < size){ GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::BeginRead() size:" + size + " offset:" + offset); 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 HttpRequestStreamAsyncResult(this, state, callback, buffer, offset, (uint)size, dataRead); fixed (byte *pBuffer = buffer) { // issue unmanaged blocking call GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::BeginRead() calling UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody"); m_HttpContext.EnsureBoundHandle(); GlobalLog.Assert(asyncResult.m_pOverlapped->InternalLow != (IntPtr) 0x0103, "HttpRequestStream#{0}::BeginRead()|Overlapped structure STATUS_PENDING before use. 0x{1:x}", ValidationHelper.HashString(this), (IntPtr) asyncResult.m_pOverlapped); statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY, asyncResult.m_pPinnedBuffer, (uint)size, null, asyncResult.m_pOverlapped); GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::BeginRead() call to UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if(Logging.On)Logging.Exception(Logging.HttpListener, this, "BeginRead", exception); throw exception; } if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { // WORKAROUND: http.sys HttpReceiveRequestEntityBody has a bug where InternalLow gets set to STATUS_PENDING when it shouldn't. // This causes an MDA to fire in the CLR (as well as the assert in NclUtilities.OverlappedFree). // Explicitly reset InternalLow as if it hadn't been touched. asyncResult.m_pOverlapped->InternalLow = IntPtr.Zero; asyncResult.InternalCleanup(); asyncResult = new HttpRequestStreamAsyncResult(this, state, callback); asyncResult.InvokeCallback((uint)0); } } if(Logging.On)Logging.Exit(Logging.HttpListener, this, "BeginRead", ""); return asyncResult; } public override int EndRead(IAsyncResult asyncResult) { if(Logging.On)Logging.Enter(Logging.HttpListener, this, "EndRead", ""); GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::EndRead() asyncResult#" + ValidationHelper.HashString(asyncResult)); if (asyncResult==null) { throw new ArgumentNullException("asyncResult"); } HttpRequestStreamAsyncResult castedAsyncResult = asyncResult as HttpRequestStreamAsyncResult; if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) { throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult"); } if (castedAsyncResult.EndCalled) { throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndRead")); } castedAsyncResult.EndCalled = true; // wait & then check for errors object returnValue = castedAsyncResult.InternalWaitForCompletion(); Exception exception = returnValue as Exception; if (exception!=null) { GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::EndRead() rethrowing exception:" + exception); if(Logging.On)Logging.Exception(Logging.HttpListener, this, "EndRead", exception); throw exception; } // uint dataRead = (uint)returnValue; UpdateAfterRead((uint)castedAsyncResult.ErrorCode, dataRead); GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::EndRead() returning returnValue:" + ValidationHelper.ToString(returnValue)); if(Logging.On)Logging.Exit(Logging.HttpListener, this, "EndRead", ""); return (int)dataRead + (int)castedAsyncResult.m_dataAlreadyRead; } public override void Write(byte[] buffer, int offset, int size) { throw new InvalidOperationException(SR.GetString(SR.net_readonlystream)); } [HostProtection(ExternalThreading=true)] public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { throw new InvalidOperationException(SR.GetString(SR.net_readonlystream)); } public override void EndWrite(IAsyncResult asyncResult) { throw new InvalidOperationException(SR.GetString(SR.net_readonlystream)); } protected override void Dispose(bool disposing) { if(Logging.On)Logging.Enter(Logging.HttpListener, this, "Dispose", ""); try { GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::Dispose(bool) m_Closed:" + m_Closed); m_Closed = true; } finally { base.Dispose(disposing); } if(Logging.On)Logging.Exit(Logging.HttpListener, this, "Dispose", ""); } unsafe class HttpRequestStreamAsyncResult : LazyAsyncResult { internal NativeOverlapped* m_pOverlapped; internal void* m_pPinnedBuffer; internal uint m_dataAlreadyRead = 0; private static readonly IOCompletionCallback s_IOCallback = new IOCompletionCallback(Callback); internal HttpRequestStreamAsyncResult(object asyncObject, object userState, AsyncCallback callback) : base(asyncObject, userState, callback) { } internal HttpRequestStreamAsyncResult(object asyncObject, object userState, AsyncCallback callback, byte[] buffer, int offset, uint size, uint dataAlreadyRead): base(asyncObject, userState, callback) { m_dataAlreadyRead = dataAlreadyRead; Overlapped overlapped = new Overlapped(); overlapped.AsyncResult = this; m_pOverlapped = overlapped.Pack(s_IOCallback, buffer); m_pPinnedBuffer = (void*)(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset)); } private static unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) { Overlapped callbackOverlapped = Overlapped.Unpack(nativeOverlapped); HttpRequestStreamAsyncResult asyncResult = callbackOverlapped.AsyncResult as HttpRequestStreamAsyncResult; GlobalLog.Print("HttpRequestStreamAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::Callback() errorCode:0x" + errorCode.ToString("x8") + " numBytes:" + numBytes + " nativeOverlapped:0x" + ((IntPtr)nativeOverlapped).ToString("x8")); object result = null; try { if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { result = numBytes; if(Logging.On)Logging.Dump(Logging.HttpListener, asyncResult, "Callback", (IntPtr)asyncResult.m_pPinnedBuffer, (int)numBytes); } GlobalLog.Print("HttpRequestStreamAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::Callback() calling Complete()"); } catch (Exception e) { result = e; } asyncResult.InvokeCallback(result); } // Will be called from the base class upon InvokeCallback() protected override void Cleanup() { base.Cleanup(); if (m_pOverlapped != null) { Overlapped.Free(m_pOverlapped); } } } } }
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextSearch.cs
- DesignerInterfaces.cs
- InputLangChangeEvent.cs
- OrCondition.cs
- BuilderPropertyEntry.cs
- DefaultProfileManager.cs
- SqlCacheDependencyDatabase.cs
- Ipv6Element.cs
- EventData.cs
- LinearKeyFrames.cs
- FlatButtonAppearance.cs
- TableStyle.cs
- TransformCollection.cs
- SiteMapHierarchicalDataSourceView.cs
- TimeSpanSecondsConverter.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- Pen.cs
- WorkflowIdleElement.cs
- SwitchElementsCollection.cs
- Int64.cs
- FrameDimension.cs
- WebPartConnectionsCancelVerb.cs
- ObjectQuery.cs
- DetailsViewDeleteEventArgs.cs
- DataListComponentEditor.cs
- SamlConditions.cs
- WpfGeneratedKnownProperties.cs
- SafeRightsManagementPubHandle.cs
- ToolStripProgressBar.cs
- SpellerError.cs
- GridProviderWrapper.cs
- LongValidatorAttribute.cs
- HuffModule.cs
- TextBoxAutoCompleteSourceConverter.cs
- ValueConversionAttribute.cs
- DebugController.cs
- DropShadowEffect.cs
- LayoutManager.cs
- XmlResolver.cs
- XsltException.cs
- MessageSmuggler.cs
- WebResourceUtil.cs
- _SecureChannel.cs
- FamilyCollection.cs
- XmlDocument.cs
- MetafileHeaderWmf.cs
- EntityDataSource.cs
- XmlSchemaObject.cs
- ScaleTransform3D.cs
- ContentDefinition.cs
- Parser.cs
- rsa.cs
- COM2PropertyBuilderUITypeEditor.cs
- GC.cs
- ModulesEntry.cs
- ArrangedElementCollection.cs
- FocusWithinProperty.cs
- BadImageFormatException.cs
- SmiXetterAccessMap.cs
- ProfileGroupSettingsCollection.cs
- ComPlusSynchronizationContext.cs
- ToolStripItemImageRenderEventArgs.cs
- TrackPointCollection.cs
- StrokeRenderer.cs
- ReadWriteSpinLock.cs
- AmbientLight.cs
- BaseTemplatedMobileComponentEditor.cs
- RemotingConfigParser.cs
- DesigntimeLicenseContextSerializer.cs
- InputLanguageProfileNotifySink.cs
- OpacityConverter.cs
- HelpInfo.cs
- Point.cs
- TimeSpan.cs
- FixedSOMElement.cs
- SafeCoTaskMem.cs
- MimeMapping.cs
- GuidelineCollection.cs
- Executor.cs
- UpdatePanelTrigger.cs
- InputBindingCollection.cs
- EntityObject.cs
- XamlBrushSerializer.cs
- XdrBuilder.cs
- SmtpFailedRecipientException.cs
- UIElement3DAutomationPeer.cs
- HttpContext.cs
- CqlParser.cs
- XsltArgumentList.cs
- PeerToPeerException.cs
- EnumerableRowCollection.cs
- MarshalDirectiveException.cs
- ConfigurationElementProperty.cs
- Button.cs
- ArgIterator.cs
- ACE.cs
- ObjectStateFormatter.cs
- FontStyle.cs
- ZipIOFileItemStream.cs
- XpsFontSubsetter.cs