public override unsafe IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (Logging.On) { Logging.Enter(Logging.HttpListener, this, "BeginRead", ""); } 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) || this.m_Closed) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "BeginRead", ""); } HttpRequestStreamAsyncResult result = new HttpRequestStreamAsyncResult(this, state, callback); result.InvokeCallback(0); return(result); } HttpRequestStreamAsyncResult result2 = null; uint num = 0; if (this.m_DataChunkIndex != -1) { num = UnsafeNclNativeMethods.HttpApi.GetChunks(this.m_HttpContext.Request.RequestBuffer, this.m_HttpContext.Request.OriginalBlobAddress, ref this.m_DataChunkIndex, ref this.m_DataChunkOffset, buffer, offset, size); if ((this.m_DataChunkIndex != -1) && (num == size)) { result2 = new HttpRequestStreamAsyncResult(this, state, callback, buffer, offset, (uint)size, 0); result2.InvokeCallback(num); } } if ((this.m_DataChunkIndex == -1) && (num < size)) { uint num2 = 0; offset += (int)num; size -= (int)num; if (size > 0x20000) { size = 0x20000; } result2 = new HttpRequestStreamAsyncResult(this, state, callback, buffer, offset, (uint)size, num); try { byte[] buffer2 = buffer; if (buffer2 != null) { int length = buffer2.Length; } this.m_HttpContext.EnsureBoundHandle(); num2 = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, 1, result2.m_pPinnedBuffer, (uint)size, null, result2.m_pOverlapped); } catch (Exception exception) { if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginRead", exception); } result2.InternalCleanup(); throw; } switch (num2) { case 0: case 0x3e5: goto Label_0217; } if (num2 == 0x26) { result2.m_pOverlapped.InternalLow = IntPtr.Zero; } result2.InternalCleanup(); if (num2 != 0x26) { Exception e = new HttpListenerException((int)num2); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginRead", e); } result2.InternalCleanup(); throw e; } result2 = new HttpRequestStreamAsyncResult(this, state, callback, num); result2.InvokeCallback(0); } Label_0217: if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "BeginRead", ""); } return(result2); }
// Create a WebRequest. // // This is the main creation routine. We take a Uri object, look // up the Uri in the prefix match table, and invoke the appropriate // handler to create the object. We also have a parameter that // tells us whether or not to use the whole Uri or just the // scheme portion of it. // // Input: // requestUri - Uri object for request. // useUriBase - True if we're only to look at the scheme portion of the Uri. // // Returns: // Newly created WebRequest. private static WebRequest Create(Uri requestUri, bool useUriBase) { if (Logging.On) { Logging.Enter(Logging.Web, "WebRequest", "Create", requestUri.ToString()); } string LookupUri; WebRequestPrefixElement Current = null; bool Found = false; if (!useUriBase) { LookupUri = requestUri.AbsoluteUri; } else { // schemes are registered as <schemeName>":", so add the separator // to the string returned from the Uri object LookupUri = requestUri.Scheme + ':'; } int LookupLength = LookupUri.Length; // Copy the prefix list so that if it is updated it will // not affect us on this thread. List <WebRequestPrefixElement> prefixList = PrefixList; // Look for the longest matching prefix. // Walk down the list of prefixes. The prefixes are kept longest // first. When we find a prefix that is shorter or the same size // as this Uri, we'll do a compare to see if they match. If they // do we'll break out of the loop and call the creator. for (int i = 0; i < prefixList.Count; i++) { Current = prefixList[i]; // See if this prefix is short enough. if (LookupLength >= Current.Prefix.Length) { // It is. See if these match. if (String.Compare(Current.Prefix, 0, LookupUri, 0, Current.Prefix.Length, StringComparison.OrdinalIgnoreCase) == 0) { // These match. Remember that we found it and break // out. Found = true; break; } } } WebRequest webRequest = null; if (Found) { // We found a match, so just call the creator and return what it does. webRequest = Current.Creator.Create(requestUri); if (Logging.On) { Logging.Exit(Logging.Web, "WebRequest", "Create", webRequest); } return(webRequest); } if (Logging.On) { Logging.Exit(Logging.Web, "WebRequest", "Create", null); } // Otherwise no match, throw an exception. throw new NotSupportedException(SR.net_unknown_prefix); }
public override unsafe void Write(byte[] buffer, int offset, int size) { if (Logging.On) { Logging.Enter(Logging.HttpListener, this, "Write", ""); } 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"); } UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = this.ComputeLeftToWrite(); if (this.m_Closed || ((size == 0) && (this.m_LeftToWrite != 0L))) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Write", ""); } } else { uint num; if ((this.m_LeftToWrite >= 0L) && (size > this.m_LeftToWrite)) { throw new ProtocolViolationException(SR.GetString("net_entitytoobig")); } uint dataWritten = (uint)size; SafeLocalFree free = null; IntPtr zero = IntPtr.Zero; bool sentHeaders = this.m_HttpContext.Response.SentHeaders; try { if (size == 0) { num = this.m_HttpContext.Response.SendHeaders(null, null, flags); } else { try { byte[] buffer2; if (((buffer2 = buffer) == null) || (buffer2.Length == 0)) { numRef = null; goto Label_0109; } fixed(byte *numRef = buffer2) { byte *numPtr; Label_0109: numPtr = numRef; if (this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) { string str = size.ToString("x", CultureInfo.InvariantCulture); dataWritten += (uint)(str.Length + 4); free = SafeLocalFree.LocalAlloc((int)dataWritten); zero = free.DangerousGetHandle(); for (int i = 0; i < str.Length; i++) { Marshal.WriteByte(zero, i, (byte)str[i]); } Marshal.WriteInt16(zero, str.Length, (short)0xa0d); Marshal.Copy(buffer, offset, IntPtrHelper.Add(zero, str.Length + 2), size); Marshal.WriteInt16(zero, ((int)dataWritten) - 2, (short)0xa0d); numPtr = (byte *)zero; offset = 0; } UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK pDataChunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK { DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory, pBuffer = numPtr + offset, BufferLength = dataWritten }; flags |= (this.m_LeftToWrite == size) ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; if (!sentHeaders) { num = this.m_HttpContext.Response.SendHeaders(&pDataChunk, null, flags); } else { num = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, (uint)flags, 1, &pDataChunk, null, SafeLocalFree.Zero, 0, null, null); if (this.m_HttpContext.Listener.IgnoreWriteExceptions) { num = 0; } } } } finally { numRef = null; } } } finally { if (free != null) { free.Close(); } } switch (num) { case 0: case 0x26: this.UpdateAfterWrite(dataWritten); if (Logging.On) { Logging.Dump(Logging.HttpListener, this, "Write", buffer, offset, (int)dataWritten); } if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Write", ""); } return; } Exception e = new HttpListenerException((int)num); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "Write", e); } this.m_HttpContext.Abort(); throw e; } }
public override unsafe int Read([In, Out] byte[] buffer, int offset, int size) { if (Logging.On) { Logging.Enter(Logging.HttpListener, this, "Read", ""); } 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) || this.m_Closed) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Read", "dataRead:0"); } return(0); } uint dataRead = 0; if (this.m_DataChunkIndex != -1) { dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(this.m_HttpContext.Request.RequestBuffer, this.m_HttpContext.Request.OriginalBlobAddress, ref this.m_DataChunkIndex, ref this.m_DataChunkOffset, buffer, offset, size); } if ((this.m_DataChunkIndex == -1) && (dataRead < size)) { uint statusCode = 0; uint pBytesReturned = 0; offset += (int)dataRead; size -= (int)dataRead; if (size > 0x20000) { size = 0x20000; } fixed(byte *numRef = buffer) { statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, 1, (void *)(numRef + offset), (uint)size, &pBytesReturned, null); dataRead += pBytesReturned; } switch (statusCode) { case 0: case 0x26: this.UpdateAfterRead(statusCode, dataRead); break; default: { Exception e = new HttpListenerException((int)statusCode); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "Read", e); } throw e; } } } if (Logging.On) { Logging.Dump(Logging.HttpListener, this, "Read", buffer, offset, (int)dataRead); } if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Read", "dataRead:" + dataRead); } return((int)dataRead); }
protected override unsafe void Dispose(bool disposing) { if (Logging.On) { Logging.Enter(Logging.HttpListener, this, "Close", ""); } try { if (!disposing) { goto Label_023F; } if (this.m_Closed) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Close", ""); } return; } this.m_Closed = true; UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = this.ComputeLeftToWrite(); if (this.m_LeftToWrite > 0L) { throw new InvalidOperationException(SR.GetString("net_io_notenoughbyteswritten")); } bool sentHeaders = this.m_HttpContext.Response.SentHeaders; if (sentHeaders && (this.m_LeftToWrite == 0L)) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Close", ""); } return; } uint num = 0; if (((this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) || (this.m_HttpContext.Response.BoundaryType == BoundaryType.None)) && (string.Compare(this.m_HttpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) != 0)) { if (this.m_HttpContext.Response.BoundaryType == BoundaryType.None) { flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_INITIALIZE_SERVER; } try { byte[] buffer; if (((buffer = NclConstants.ChunkTerminator) == null) || (buffer.Length == 0)) { ptrRef = null; goto Label_0132; } fixed(IntPtr *ptrRef = buffer) { UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK *http_data_chunkPtr; Label_0132: http_data_chunkPtr = null; if (this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) { UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK http_data_chunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK { DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory, pBuffer = (byte *)ptrRef, BufferLength = (uint)NclConstants.ChunkTerminator.Length }; http_data_chunkPtr = &http_data_chunk; } if (!sentHeaders) { num = this.m_HttpContext.Response.SendHeaders(http_data_chunkPtr, null, flags); } else { num = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, (uint)flags, (http_data_chunkPtr != null) ? ((ushort)1) : ((ushort)0), http_data_chunkPtr, null, SafeLocalFree.Zero, 0, null, null); if (this.m_HttpContext.Listener.IgnoreWriteExceptions) { num = 0; } } goto Label_01F6; } } finally { ptrRef = null; } } if (!sentHeaders) { num = this.m_HttpContext.Response.SendHeaders(null, null, flags); } Label_01F6: switch (num) { case 0: case 0x26: break; default: { Exception e = new HttpListenerException((int)num); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "Close", e); } this.m_HttpContext.Abort(); throw e; } } this.m_LeftToWrite = 0L; } finally { base.Dispose(disposing); } Label_023F: if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Dispose", ""); } }
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); uint bytesReturned; try { fixed(byte *pBuffer = buffer) { // issue unmanaged blocking call GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::BeginRead() calling UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody"); m_HttpContext.EnsureBoundHandle(); uint flags = 0; if (!m_InOpaqueMode) { flags = (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY; } statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, flags, asyncResult.m_pPinnedBuffer, (uint)size, out bytesReturned, asyncResult.m_pOverlapped); GlobalLog.Print("HttpRequestStream#" + ValidationHelper.HashString(this) + "::BeginRead() call to UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } } catch (Exception e) { if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginRead", e); } asyncResult.InternalCleanup(); throw; } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { asyncResult = new HttpRequestStreamAsyncResult(this, state, callback, dataRead); asyncResult.InvokeCallback((uint)0); } else { Exception exception = new HttpListenerException((int)statusCode); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginRead", exception); } asyncResult.InternalCleanup(); throw exception; } } else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesReturned); } } if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "BeginRead", ""); } return(asyncResult); }
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"); uint flags = 0; if (!m_InOpaqueMode) { flags = (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY; } statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, flags, (void *)(pBuffer + offset), (uint)size, out 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); }
protected override void Dispose(bool disposing) { if (Logging.On) { Logging.Enter(Logging.HttpListener, this, "Close", ""); } try { if (disposing) { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() m_Closed:" + m_Closed); if (m_Closed) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Close", ""); } return; } m_Closed = true; UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (m_LeftToWrite > 0 && !m_InOpaqueMode) { throw new InvalidOperationException(SR.GetString(SR.net_io_notenoughbyteswritten)); } bool sentHeaders = m_HttpContext.Response.SentHeaders; if (sentHeaders && m_LeftToWrite == 0) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Close", ""); } return; } uint statusCode = 0; if ((m_HttpContext.Response.BoundaryType == BoundaryType.Chunked || m_HttpContext.Response.BoundaryType == BoundaryType.None) && (String.Compare(m_HttpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) != 0)) { if (m_HttpContext.Response.BoundaryType == BoundaryType.None) { flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } fixed(void *pBuffer = NclConstants.ChunkTerminator) { UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK *pDataChunk = null; if (m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) { UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK dataChunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); dataChunk.DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte *)pBuffer; dataChunk.BufferLength = (uint)NclConstants.ChunkTerminator.Length; pDataChunk = &dataChunk; } if (!sentHeaders) { statusCode = m_HttpContext.Response.SendHeaders(pDataChunk, null, flags, false); } else { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() calling UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody"); statusCode = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, (uint)flags, pDataChunk != null ? (ushort)1 : (ushort)0, pDataChunk, null, SafeLocalFree.Zero, 0, null, null); GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() call to UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); if (m_HttpContext.Listener.IgnoreWriteExceptions) { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() suppressing error"); statusCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; } } } } else { if (!sentHeaders) { statusCode = m_HttpContext.Response.SendHeaders(null, null, flags, false); } } 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, "Close", exception); } m_HttpContext.Abort(); throw exception; } m_LeftToWrite = 0; } } finally { base.Dispose(disposing); } if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Dispose", ""); } }
public override void Write(byte[] buffer, int offset, int size) { if (Logging.On) { Logging.Enter(Logging.HttpListener, this, "Write", ""); } GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() 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"); } UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (m_Closed || (size == 0 && m_LeftToWrite != 0)) { if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Write", ""); } return; } if (m_LeftToWrite >= 0 && size > m_LeftToWrite) { throw new ProtocolViolationException(SR.GetString(SR.net_entitytoobig)); } uint statusCode; uint dataToWrite = (uint)size; SafeLocalFree bufferAsIntPtr = null; IntPtr pBufferAsIntPtr = IntPtr.Zero; bool sentHeaders = m_HttpContext.Response.SentHeaders; try { if (size == 0) { statusCode = m_HttpContext.Response.SendHeaders(null, null, flags, false); } else { fixed(byte *pDataBuffer = buffer) { byte *pBuffer = pDataBuffer; if (m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) { // string chunkHeader = size.ToString("x", CultureInfo.InvariantCulture); dataToWrite = dataToWrite + (uint)(chunkHeader.Length + 4); bufferAsIntPtr = SafeLocalFree.LocalAlloc((int)dataToWrite); pBufferAsIntPtr = bufferAsIntPtr.DangerousGetHandle(); for (int i = 0; i < chunkHeader.Length; i++) { Marshal.WriteByte(pBufferAsIntPtr, i, (byte)chunkHeader[i]); } Marshal.WriteInt16(pBufferAsIntPtr, chunkHeader.Length, 0x0A0D); Marshal.Copy(buffer, offset, IntPtrHelper.Add(pBufferAsIntPtr, chunkHeader.Length + 2), size); Marshal.WriteInt16(pBufferAsIntPtr, (int)(dataToWrite - 2), 0x0A0D); pBuffer = (byte *)pBufferAsIntPtr; offset = 0; } UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK dataChunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); dataChunk.DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte *)(pBuffer + offset); dataChunk.BufferLength = dataToWrite; flags |= m_LeftToWrite == size ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; if (!sentHeaders) { statusCode = m_HttpContext.Response.SendHeaders(&dataChunk, null, flags, false); } else { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() calling UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody"); statusCode = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, (uint)flags, 1, &dataChunk, null, SafeLocalFree.Zero, 0, null, null); GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() call to UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); if (m_HttpContext.Listener.IgnoreWriteExceptions) { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() suppressing error"); statusCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; } } } } } finally { if (bufferAsIntPtr != null) { // free unmanaged buffer bufferAsIntPtr.Close(); } } 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, "Write", exception); } m_Closed = true; m_HttpContext.Abort(); throw exception; } UpdateAfterWrite(dataToWrite); if (Logging.On) { Logging.Dump(Logging.HttpListener, this, "Write", buffer, offset, (int)dataToWrite); } if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "Write", ""); } }