private static unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped) { HttpRequestStream.HttpRequestStreamAsyncResult asyncResult = Overlapped.Unpack(nativeOverlapped).AsyncResult as HttpRequestStream.HttpRequestStreamAsyncResult; object result = null; try { if ((errorCode != 0) && (errorCode != 0x26)) { 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); } } } catch (Exception exception) { result = exception; } asyncResult.InvokeCallback(result); }
private static void IOCompleted(HttpRequestStreamAsyncResult asyncResult, uint errorCode, uint numBytes) { GlobalLog.Print("HttpRequestStreamAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::Callback() errorCode:0x" + errorCode.ToString("x8") + " numBytes:" + numBytes); 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); }
private static void IOCompleted(HttpResponseStreamAsyncResult asyncResult, uint errorCode, uint numBytes) { GlobalLog.Print("HttpResponseStreamAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::Callback() errorCode:0x" + errorCode.ToString("x8") + " numBytes:" + numBytes); 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 { // if we sent headers and body together, numBytes will be the total, but we need to only account for the data // result = numBytes; if (asyncResult.m_DataChunks == null) { result = (uint)0; if (Logging.On) { Logging.Dump(Logging.HttpListener, asyncResult, "Callback", IntPtr.Zero, 0); } } else { result = asyncResult.m_DataChunks.Length == 1 ? asyncResult.m_DataChunks[0].BufferLength : 0; if (Logging.On) { for (int i = 0; i < asyncResult.m_DataChunks.Length; i++) { Logging.Dump(Logging.HttpListener, asyncResult, "Callback", (IntPtr)asyncResult.m_DataChunks[0].pBuffer, (int)asyncResult.m_DataChunks[0].BufferLength); } } } } GlobalLog.Print("HttpResponseStreamAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::Callback() calling Complete()"); } catch (Exception e) { result = e; } asyncResult.InvokeCallback(result); }
private static unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped) { HttpResponseStreamAsyncResult asyncResult = Overlapped.Unpack(nativeOverlapped).AsyncResult as HttpResponseStreamAsyncResult; object result = null; try { if ((errorCode != 0) && (errorCode != 0x26)) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else if (asyncResult.m_DataChunks == null) { result = 0; if (Logging.On) { Logging.Dump(Logging.HttpListener, asyncResult, "Callback", IntPtr.Zero, 0); } } else { result = (asyncResult.m_DataChunks.Length == 1) ? ((object)asyncResult.m_DataChunks[0].BufferLength) : ((object)0); if (Logging.On) { for (int i = 0; i < asyncResult.m_DataChunks.Length; i++) { Logging.Dump(Logging.HttpListener, asyncResult, "Callback", (IntPtr)asyncResult.m_DataChunks[0].pBuffer, (int)asyncResult.m_DataChunks[0].BufferLength); } } } } catch (Exception exception) { result = exception; } asyncResult.InvokeCallback(result); }
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", ""); } }
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); }
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 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); }