internal static unsafe void CancelRequest(CriticalHandle requestQueueHandle, ulong requestId) { UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK http_data_chunk; http_data_chunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK { DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory, pBuffer = (byte*) &http_data_chunk }; UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(requestQueueHandle, requestId, 1, 1, &http_data_chunk, null, SafeLocalFree.Zero, 0, null, null); }
internal HttpResponseStreamAsyncResult(object asyncObject, object userState, AsyncCallback callback, byte[] buffer, int offset, int size, bool chunked, bool sentHeaders): base(asyncObject, userState, callback){ m_SentHeaders = sentHeaders; Overlapped overlapped = new Overlapped(); overlapped.AsyncResult = this; if (size == 0) { m_DataChunks = null; m_pOverlapped = overlapped.Pack(s_IOCallback, null); } else { m_DataChunks = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK[chunked ? 3 : 1]; GlobalLog.Print("HttpResponseStreamAsyncResult#" + ValidationHelper.HashString(this) + "::.ctor() m_pOverlapped:0x" + ((IntPtr)m_pOverlapped).ToString("x8")); object[] objectsToPin = new object[1 + m_DataChunks.Length]; objectsToPin[m_DataChunks.Length] = m_DataChunks; int chunkHeaderOffset = 0; byte[] chunkHeaderBuffer = null; if (chunked) { chunkHeaderBuffer = ConnectStream.GetChunkHeader(size, out chunkHeaderOffset); m_DataChunks[0] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[0].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[0].BufferLength = (uint)(chunkHeaderBuffer.Length - chunkHeaderOffset); objectsToPin[0] = chunkHeaderBuffer; m_DataChunks[1] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[1].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[1].BufferLength = (uint)size; objectsToPin[1] = buffer; m_DataChunks[2] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[2].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[2].BufferLength = (uint)NclConstants.CRLF.Length; objectsToPin[2] = NclConstants.CRLF; } else { m_DataChunks[0] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[0].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[0].BufferLength = (uint)size; objectsToPin[0] = buffer; } // This call will pin needed memory m_pOverlapped = overlapped.Pack(s_IOCallback, objectsToPin); if (chunked) { m_DataChunks[0].pBuffer = (byte*)(Marshal.UnsafeAddrOfPinnedArrayElement(chunkHeaderBuffer, chunkHeaderOffset)); m_DataChunks[1].pBuffer = (byte*)(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset)); m_DataChunks[2].pBuffer = (byte*)(Marshal.UnsafeAddrOfPinnedArrayElement(NclConstants.CRLF, 0)); } else { m_DataChunks[0].pBuffer = (byte*)(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset)); } } }
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", ""); }
private unsafe void UpdateDataChunk() { if (m_DataChunks == null) { m_DataChunks = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK[2]; m_DataChunksGCHandle = GCHandle.Alloc(m_DataChunks, GCHandleType.Pinned); m_DataChunks[0] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[0].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[1] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[1].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; } Contract.Assert(m_Buffer == null || m_BufferList == null, "Either 'm_Buffer' or 'm_BufferList' MUST be NULL."); Contract.Assert(m_ShouldCloseOutput || m_Buffer != null || m_BufferList != null, "Either 'm_Buffer' or 'm_BufferList' MUST NOT be NULL."); // The underlying byte[] m_Buffer or each m_BufferList[].Array are pinned already if (m_Buffer != null) { UpdateDataChunk(0, m_Buffer, m_Offset, m_Count); UpdateDataChunk(1, null, 0, 0); m_DataChunkCount = 1; } else if (m_BufferList != null) { Contract.Assert(m_BufferList != null && m_BufferList.Count == 2, "'m_BufferList' MUST NOT be NULL and have exactly '2' items at this point."); UpdateDataChunk(0, m_BufferList[0].Array, m_BufferList[0].Offset, m_BufferList[0].Count); UpdateDataChunk(1, m_BufferList[1].Array, m_BufferList[1].Offset, m_BufferList[1].Count); m_DataChunkCount = 2; } else { Contract.Assert(m_ShouldCloseOutput, "'m_ShouldCloseOutput' MUST be 'true' at this point."); m_DataChunks = null; } }
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; } }
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", ""); } }