private static void IOCompleted(HttpRequestStreamAsyncResult asyncResult, uint errorCode, uint numBytes) { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"asyncResult: {asyncResult} errorCode:0x {errorCode.ToString("x8")} numBytes: {numBytes}"); } object result = null; try { if (errorCode != Interop.HttpApi.ERROR_SUCCESS && errorCode != Interop.HttpApi.ERROR_HANDLE_EOF) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { result = numBytes; if (NetEventSource.IsEnabled) { NetEventSource.DumpBuffer(asyncResult, (IntPtr)asyncResult._pPinnedBuffer, (int)numBytes); } } if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"asyncResult: {asyncResult} calling Complete()"); } } catch (Exception e) { result = e; } asyncResult.InvokeCallback(result); }
public static void DumpBuffer(object?thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string?memberName = null) { if (Log.IsEnabled() && offset >= 0 && offset <= buffer.Length - count) { count = Math.Min(count, MaxDumpSize); byte[] slice = buffer; if (offset != 0 || count != buffer.Length) { slice = new byte[count]; Buffer.BlockCopy(buffer, offset, slice, 0, count); } Log.DumpBuffer(IdOf(thisOrContextObject), memberName, slice); } }
public static void DumpBuffer(object thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string memberName = null) { if (IsEnabled) { if (offset < 0 || offset > buffer.Length - count) { Fail(thisOrContextObject, $"Invalid {nameof(DumpBuffer)} Args. Length={buffer.Length}, Offset={offset}, Count={count}", memberName); return; } count = Math.Min(count, MaxDumpSize); byte[] slice = buffer; if (offset != 0 || count != buffer.Length) { slice = new byte[count]; Buffer.BlockCopy(buffer, offset, slice, 0, count); } Log.DumpBuffer(IdOf(thisOrContextObject), memberName, slice); } }
private static void IOCompleted(HttpResponseStreamAsyncResult asyncResult, uint errorCode, uint numBytes) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(null, $"errorCode:0x{errorCode:x8} numBytes: {numBytes}"); } object?result; try { if (errorCode != Interop.HttpApi.ERROR_SUCCESS && errorCode != Interop.HttpApi.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 if (asyncResult._dataChunks == null) { result = (uint)0; if (NetEventSource.Log.IsEnabled()) { NetEventSource.DumpBuffer(null, IntPtr.Zero, 0); } } else { result = asyncResult._dataChunks.Length == 1 ? asyncResult._dataChunks[0].BufferLength : 0; if (NetEventSource.Log.IsEnabled()) { for (int i = 0; i < asyncResult._dataChunks.Length; i++) { NetEventSource.DumpBuffer(null, (IntPtr)asyncResult._dataChunks[0].pBuffer, (int)asyncResult._dataChunks[0].BufferLength); } } } } if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(null, "Calling Complete()"); } } catch (Exception e) { result = e; } asyncResult.InvokeCallback(result); }
public override int Read([In, Out] byte[] buffer, int offset, int size) { if (NetEventSource.IsEnabled) { NetEventSource.Enter(this); NetEventSource.Info(this, "size:" + size + " offset:" + offset); } if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (size < 0 || size > buffer.Length - offset) { throw new ArgumentOutOfRangeException(nameof(size)); } if (size == 0 || _closed) { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this, "dataRead:0"); } return(0); } uint dataRead = 0; if (_dataChunkIndex != -1) { dataRead = Interop.HttpApi.GetChunks(_httpContext.Request.RequestBuffer, _httpContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); } if (_dataChunkIndex == -1 && dataRead < size) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "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 if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpReceiveRequestEntityBody"); } uint flags = 0; if (!_inOpaqueMode) { flags = (uint)Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY; } statusCode = Interop.HttpApi.HttpReceiveRequestEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, flags, (void *)(pBuffer + offset), (uint)size, out extraDataRead, null); dataRead += extraDataRead; if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } throw exception; } UpdateAfterRead(statusCode, dataRead); } if (NetEventSource.IsEnabled) { NetEventSource.DumpBuffer(this, buffer, offset, (int)dataRead); NetEventSource.Info(this, "returning dataRead:" + dataRead); NetEventSource.Exit(this, "dataRead:" + dataRead); } return((int)dataRead); }
private void WriteCore(byte[] buffer, int offset, int size) { Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (size == 0 && _leftToWrite != 0) { return; } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint dataToWrite = (uint)size; SafeLocalAllocHandle?bufferAsIntPtr = null; IntPtr pBufferAsIntPtr = IntPtr.Zero; bool sentHeaders = _httpContext.Response.SentHeaders; try { if (size == 0) { statusCode = _httpContext.Response.SendHeaders(null, null, flags, false); } else { fixed(byte *pDataBuffer = buffer) { byte *pBuffer = pDataBuffer; if (_httpContext.Response.BoundaryType == BoundaryType.Chunked) { string chunkHeader = size.ToString("x", CultureInfo.InvariantCulture); dataToWrite = dataToWrite + (uint)(chunkHeader.Length + 4); bufferAsIntPtr = SafeLocalAllocHandle.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, pBufferAsIntPtr + chunkHeader.Length + 2, size); Marshal.WriteInt16(pBufferAsIntPtr, (int)(dataToWrite - 2), 0x0A0D); pBuffer = (byte *)pBufferAsIntPtr; offset = 0; } Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = default; dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte *)(pBuffer + offset); dataChunk.BufferLength = dataToWrite; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(&dataChunk, null, flags, false); } else { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, 1, &dataChunk, null, SafeLocalAllocHandle.Zero, 0, null, null); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } if (_httpContext.Listener !.IgnoreWriteExceptions) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Write() suppressing error"); } statusCode = Interop.HttpApi.ERROR_SUCCESS; } } } } } finally { // free unmanaged buffer bufferAsIntPtr?.Close(); } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(this, exception.ToString()); } _closed = true; _httpContext.Abort(); throw exception; } UpdateAfterWrite(dataToWrite); if (NetEventSource.Log.IsEnabled()) { NetEventSource.DumpBuffer(this, buffer, offset, (int)dataToWrite); } }