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 async Task StartAsync(string port, RouteRepository routeRepository) { this.httpListener.Prefixes.Add(string.Format("http://localhost:{0}/", port)); try { this.httpListener.Start(); } catch (Exception e) { System.Net.HttpListenerException ex = (System.Net.HttpListenerException)e; } Console.WriteLine("Listening for requests on port {0}.", port); Request request = await GetNextRequestAsync(); while (request != null) { Console.WriteLine("{0}: {1} {2}", DateTime.Now, request.Method, request.Endpoint); if (!await TryRespondAsync(request, routeRepository)) { Console.WriteLine("HTTP 404 for {0}.", request.Endpoint); } request = await GetNextRequestAsync(); } }
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 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(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); }
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); }
public static Exception CreateCommunicationException(HttpListenerException listenerException) { switch (listenerException.NativeErrorCode) { case 0x40: return new CommunicationException(System.ServiceModel.SR.GetString("HttpNetnameDeleted", new object[] { listenerException.Message }), listenerException); case 0x494: return new CommunicationException(System.ServiceModel.SR.GetString("HttpNoTrackingService", new object[] { listenerException.Message }), listenerException); case 0x5aa: case 8: case 14: return new InsufficientMemoryException(System.ServiceModel.SR.GetString("InsufficentMemory"), listenerException); case 6: return new CommunicationObjectAbortedException(System.ServiceModel.SR.GetString("HttpResponseAborted"), listenerException); } return new CommunicationException(listenerException.Message, listenerException); }
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); }
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); }
private void SetUrlGroupProperty(Interop.HttpApi.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize) { uint statusCode = Interop.HttpApi.ERROR_SUCCESS; Debug.Assert(_urlGroupId != 0, "SetUrlGroupProperty called with invalid url group id"); Debug.Assert(info != IntPtr.Zero, "SetUrlGroupProperty called with invalid pointer"); // // Set the url group property using Http Api. // statusCode = Interop.HttpApi.HttpSetUrlGroupProperty( _urlGroupId, property, info, infosize); if (statusCode != Interop.HttpApi.ERROR_SUCCESS) { HttpListenerException exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"HttpSetUrlGroupProperty:: Property: {property} {exception}"); throw exception; } }
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", ""); } }
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; }
private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes) { object result = null; try { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"errorCode:[{errorCode}] numBytes:[{numBytes}]"); } if (errorCode != Interop.HttpApi.ERROR_SUCCESS && errorCode != Interop.HttpApi.ERROR_MORE_DATA) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener; if (errorCode == Interop.HttpApi.ERROR_SUCCESS) { // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob // points to it we need to hook up our authentication handling code here. bool stoleBlob = false; try { if (httpWebListener.ValidateRequest(asyncResult._requestContext)) { result = httpWebListener.HandleAuthentication(asyncResult._requestContext, out stoleBlob); } } finally { if (stoleBlob) { // The request has been handed to the user, which means this code can't reuse the blob. Reset it here. asyncResult._requestContext = result == null ? new AsyncRequestContext(httpWebListener.RequestQueueBoundHandle, asyncResult) : null; } else { asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, 0, 0); } } } else { asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, asyncResult._requestContext.RequestBlob->RequestId, numBytes); } // We need to issue a new request, either because auth failed, or because our buffer was too small the first time. if (result == null) { uint statusCode = asyncResult.QueueBeginGetContext(); if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { // someother bad error, possible return values are: // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED result = new HttpListenerException((int)statusCode); } } if (result == null) { return; } } // complete the async IO and invoke the callback if (NetEventSource.IsEnabled) { NetEventSource.Info(null, "Calling Complete()"); } } catch (Exception exception) when(!ExceptionCheck.IsFatal(exception)) { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"Caught exception: {exception}"); } result = exception; } asyncResult.InvokeCallback(result); }
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); } }
public override void Write(byte[] buffer, int offset, int size) { if (NetEventSource.IsEnabled) { NetEventSource.Enter(this); NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " 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)); } Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_closed || (size == 0 && _leftToWrite != 0)) { if (NetEventSource.IsEnabled) NetEventSource.Exit(this); 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 = new Interop.HttpApi.HTTP_DATA_CHUNK(); 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.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.IsEnabled) NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); if (_httpContext.Listener.IgnoreWriteExceptions) { if (NetEventSource.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.IsEnabled) NetEventSource.Error(this, exception.ToString()); _closed = true; _httpContext.Abort(); throw exception; } UpdateAfterWrite(dataToWrite); if (NetEventSource.IsEnabled) NetEventSource.DumpBuffer(this, buffer, offset, (int)dataToWrite); if (NetEventSource.IsEnabled) NetEventSource.Exit(this); }
private void SetUrlGroupProperty(UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize) { uint statusCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; GlobalLog.Assert(m_UrlGroupId != 0, "SetUrlGroupProperty called with invalid url group id"); GlobalLog.Assert(info != IntPtr.Zero, "SetUrlGroupProperty called with invalid pointer"); // // Set the url group property using Http Api. // statusCode = UnsafeNclNativeMethods.HttpApi.HttpSetUrlGroupProperty( m_UrlGroupId, property, info, infosize); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { HttpListenerException exception = new HttpListenerException((int)statusCode); if (Logging.On) Logging.Exception(Logging.HttpListener, this, "HttpSetUrlGroupProperty:: Property: " + property, exception); throw exception; } }
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); }
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; }
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 IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { uint num; 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, "BeginWrite", ""); } HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback(0); return(result); } if ((this.m_LeftToWrite >= 0L) && (size > this.m_LeftToWrite)) { throw new ProtocolViolationException(SR.GetString("net_entitytoobig")); } flags |= (this.m_LeftToWrite == size) ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = this.m_HttpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders); try { if (!sentHeaders) { num = this.m_HttpContext.Response.SendHeaders(null, asyncResult, flags); } else { this.m_HttpContext.EnsureBoundHandle(); num = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, null, SafeLocalFree.Zero, 0, asyncResult.m_pOverlapped, null); } } catch (Exception exception) { if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginWrite", exception); } asyncResult.InternalCleanup(); this.m_HttpContext.Abort(); throw; } switch (num) { case 0: case 0x3e5: break; default: asyncResult.InternalCleanup(); if (!this.m_HttpContext.Listener.IgnoreWriteExceptions || !sentHeaders) { Exception e = new HttpListenerException((int)num); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginWrite", e); } this.m_HttpContext.Abort(); throw e; } break; } if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "BeginWrite", ""); } return(asyncResult); }
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 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); }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " 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)); } Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_closed || (size == 0 && _leftToWrite != 0)) { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return(result); } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint bytesSent = 0; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = _httpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle); // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite. UpdateAfterWrite((uint)((_httpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size)); try { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, asyncResult, flags, false); } else { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, &bytesSent, SafeLocalAllocHandle.Zero, 0, asyncResult._pOverlapped, null); if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } } } catch (Exception e) { if (NetEventSource.IsEnabled) { NetEventSource.Error(this, e.ToString()); } asyncResult.InternalCleanup(); _closed = true; _httpContext.Abort(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (_httpContext.Listener.IgnoreWriteExceptions && sentHeaders) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "BeginWrite() Suppressing error"); } } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } _closed = true; _httpContext.Abort(); throw exception; } } if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesSent); } // Last write, cache it for special cancelation handling. if ((flags & Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0) { _lastWrite = asyncResult; } if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } return(asyncResult); }
private static bool IsDeadClient(HttpListenerException he) { return (he.ErrorCode == ERROR_NETNAME_DELETED || he.ErrorCode == ERROR_CONNECTION_INVALID); }
bool HandleHttpException(HttpListenerException e) { switch (e.ErrorCode) { case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: case UnsafeNativeMethods.ERROR_OUTOFMEMORY: case UnsafeNativeMethods.ERROR_NO_SYSTEM_RESOURCES: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InsufficientMemoryException(SR.GetString(SR.InsufficentMemory), e)); default: return ExceptionHandler.HandleTransportExceptionHelper(e); } }
protected override void Dispose(bool disposing) { if (NetEventSource.IsEnabled) NetEventSource.Enter(this); try { if (disposing) { if (NetEventSource.IsEnabled) NetEventSource.Info(this, "_closed:" + _closed); if (_closed) { if (NetEventSource.IsEnabled) NetEventSource.Exit(this); return; } _closed = true; Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_leftToWrite > 0 && !_inOpaqueMode) { throw new InvalidOperationException(SR.net_io_notenoughbyteswritten); } bool sentHeaders = _httpContext.Response.SentHeaders; if (sentHeaders && _leftToWrite == 0) { if (NetEventSource.IsEnabled) NetEventSource.Exit(this); return; } uint statusCode = 0; if ((_httpContext.Response.BoundaryType == BoundaryType.Chunked || _httpContext.Response.BoundaryType == BoundaryType.None) && (String.Compare(_httpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) != 0)) { if (_httpContext.Response.BoundaryType == BoundaryType.None) { flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } fixed (void* pBuffer = ChunkTerminator) { Interop.HttpApi.HTTP_DATA_CHUNK* pDataChunk = null; if (_httpContext.Response.BoundaryType == BoundaryType.Chunked) { Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = new Interop.HttpApi.HTTP_DATA_CHUNK(); dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte*)pBuffer; dataChunk.BufferLength = (uint)ChunkTerminator.Length; pDataChunk = &dataChunk; } if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(pDataChunk, null, flags, false); } else { if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, pDataChunk != null ? (ushort)1 : (ushort)0, pDataChunk, null, SafeLocalAllocHandle.Zero, 0, null, null); if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); if (_httpContext.Listener.IgnoreWriteExceptions) { if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Suppressing error"); statusCode = Interop.HttpApi.ERROR_SUCCESS; } } } } else { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, null, flags, false); } } 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()); _httpContext.Abort(); throw exception; } _leftToWrite = 0; } } finally { base.Dispose(disposing); } if (NetEventSource.IsEnabled) NetEventSource.Exit(this); }
private void SetUrlGroupProperty(UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize) { uint num = 0; num = UnsafeNclNativeMethods.HttpApi.HttpSetUrlGroupProperty(this.m_UrlGroupId, property, info, infosize); if (num != 0) { HttpListenerException e = new HttpListenerException((int) num); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "HttpSetUrlGroupProperty:: Property: " + property, e); } 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); }
private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) { ListenerAsyncResult asyncResult = (ListenerAsyncResult) Overlapped.Unpack(nativeOverlapped).AsyncResult; object result = null; try { if ((errorCode != 0) && (errorCode != 0xea)) { asyncResult.ErrorCode = (int) errorCode; result = new HttpListenerException((int) errorCode); } else { HttpListener asyncObject = asyncResult.AsyncObject as HttpListener; if (errorCode == 0) { bool stoleBlob = false; try { result = asyncObject.HandleAuthentication(asyncResult.m_RequestContext, out stoleBlob); } finally { if (stoleBlob) { asyncResult.m_RequestContext = (result == null) ? new AsyncRequestContext(asyncResult) : null; } else { asyncResult.m_RequestContext.Reset(0L, 0); } } } else { asyncResult.m_RequestContext.Reset(asyncResult.m_RequestContext.RequestBlob.RequestId, numBytes); } if (result == null) { uint num = asyncResult.QueueBeginGetContext(); if ((num != 0) && (num != 0x3e5)) { result = new HttpListenerException((int) num); } } if (result == null) { return; } } } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) { throw; } result = exception; } asyncResult.InvokeCallback(result); }
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; }
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 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); }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (NetEventSource.IsEnabled) NetEventSource.Enter(this); if (NetEventSource.IsEnabled) NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " 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); HttpRequestStreamAsyncResult result = new HttpRequestStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return result; } HttpRequestStreamAsyncResult asyncResult = null; 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) { asyncResult = new HttpRequestStreamAsyncResult(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, 0); asyncResult.InvokeCallback(dataRead); } } if (_dataChunkIndex == -1 && dataRead < size) { if (NetEventSource.IsEnabled) NetEventSource.Info(this, "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(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, dataRead); uint bytesReturned; try { 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, asyncResult._pPinnedBuffer, (uint)size, out bytesReturned, asyncResult._pOverlapped); if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } } catch (Exception e) { if (NetEventSource.IsEnabled) NetEventSource.Error(this, e.ToString()); asyncResult.InternalCleanup(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (statusCode == Interop.HttpApi.ERROR_HANDLE_EOF) { asyncResult = new HttpRequestStreamAsyncResult(this, state, callback, dataRead); asyncResult.InvokeCallback((uint)0); } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) NetEventSource.Error(this, exception.ToString()); asyncResult.InternalCleanup(); throw exception; } } else if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesReturned); } } if (NetEventSource.IsEnabled) NetEventSource.Exit(this); return asyncResult; }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() 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, "BeginWrite", ""); } HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return(result); } if (m_LeftToWrite >= 0 && size > m_LeftToWrite) { throw new ProtocolViolationException(SR.GetString(SR.net_entitytoobig)); } uint statusCode; uint bytesSent = 0; flags |= m_LeftToWrite == size ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = m_HttpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, m_HttpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders); // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite. UpdateAfterWrite((uint)((m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size)); try { if (!sentHeaders) { statusCode = m_HttpContext.Response.SendHeaders(null, asyncResult, flags, false); } else { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() calling UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody"); m_HttpContext.EnsureBoundHandle(); statusCode = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, &bytesSent, SafeLocalFree.Zero, 0, asyncResult.m_pOverlapped, null); GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() call to UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } } catch (Exception e) { if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginWrite", e); } asyncResult.InternalCleanup(); m_Closed = true; m_HttpContext.Abort(); throw; } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (m_HttpContext.Listener.IgnoreWriteExceptions && sentHeaders) { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() suppressing error"); } else { Exception exception = new HttpListenerException((int)statusCode); if (Logging.On) { Logging.Exception(Logging.HttpListener, this, "BeginWrite", exception); } m_Closed = true; m_HttpContext.Abort(); throw exception; } } if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesSent); } // Last write, cache it for special cancelation handling. if ((flags & UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0) { m_LastWrite = asyncResult; } if (Logging.On) { Logging.Exit(Logging.HttpListener, this, "BeginWrite", ""); } return(asyncResult); }
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); }
private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes) { object result = null; try { GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() errorCode:[" + errorCode.ToString() + "] numBytes:[" + numBytes.ToString() + "]"); if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener; if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob // points to it we need to hook up our authentication handling code here. bool stoleBlob = false; try { if (httpWebListener.ValidateRequest(asyncResult.m_RequestContext)) { result = httpWebListener.HandleAuthentication(asyncResult.m_RequestContext, out stoleBlob); } } finally { if (stoleBlob) { // The request has been handed to the user, which means this code can't reuse the blob. Reset it here. asyncResult.m_RequestContext = result == null ? new AsyncRequestContext(asyncResult) : null; } else { asyncResult.m_RequestContext.Reset(0, 0); } } } else { asyncResult.m_RequestContext.Reset(asyncResult.m_RequestContext.RequestBlob->RequestId, numBytes); } // We need to issue a new request, either because auth failed, or because our buffer was too small the first time. if (result == null) { uint statusCode = asyncResult.QueueBeginGetContext(); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { // someother bad error, possible(?) return values are: // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED result = new HttpListenerException((int)statusCode); } } if (result == null) { return; } } // complete the async IO and invoke the callback GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() calling Complete()"); } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) { throw; } GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() Caught exception:" + exception.ToString()); 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", ""); }
private static unsafe void IOCompleted(ListenerClientCertAsyncResult asyncResult, uint errorCode, uint numBytes) { HttpListenerRequest httpListenerRequest = (HttpListenerRequest) asyncResult.AsyncObject; object result = null; try { if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA) { //There is a bug that has existed in http.sys since w2k3. Bytesreceived will only //return the size of the inital cert structure. To get the full size, //we need to add the certificate encoding size as well. UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.RequestBlob; asyncResult.Reset(numBytes + pClientCertInfo->CertEncodedSize); uint bytesReceived = 0; errorCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate( httpListenerRequest.HttpListenerContext.RequestQueueHandle, httpListenerRequest.m_ConnectionId, (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE, asyncResult.m_MemoryBlob, asyncResult.m_Size, &bytesReceived, asyncResult.m_pOverlapped); if(errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING || (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && !HttpListener.SkipIOCPCallbackOnSuccess)) { return; } } if (errorCode!=UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.m_MemoryBlob; if (pClientCertInfo!=null) { GlobalLog.Print("HttpListenerRequest#" + ValidationHelper.HashString(httpListenerRequest) + "::ProcessClientCertificate() pClientCertInfo:" + ValidationHelper.ToString((IntPtr)pClientCertInfo) + " pClientCertInfo->CertFlags:" + ValidationHelper.ToString(pClientCertInfo->CertFlags) + " pClientCertInfo->CertEncodedSize:" + ValidationHelper.ToString(pClientCertInfo->CertEncodedSize) + " pClientCertInfo->pCertEncoded:" + ValidationHelper.ToString((IntPtr)pClientCertInfo->pCertEncoded) + " pClientCertInfo->Token:" + ValidationHelper.ToString((IntPtr)pClientCertInfo->Token) + " pClientCertInfo->CertDeniedByMapper:" + ValidationHelper.ToString(pClientCertInfo->CertDeniedByMapper)); if (pClientCertInfo->pCertEncoded!=null) { try { byte[] certEncoded = new byte[pClientCertInfo->CertEncodedSize]; Marshal.Copy((IntPtr)pClientCertInfo->pCertEncoded, certEncoded, 0, certEncoded.Length); result = httpListenerRequest.ClientCertificate = new X509Certificate2(certEncoded); } catch (CryptographicException exception) { GlobalLog.Print("HttpListenerRequest#" + ValidationHelper.HashString(httpListenerRequest) + "::ProcessClientCertificate() caught CryptographicException in X509Certificate2..ctor():" + ValidationHelper.ToString(exception)); result = exception; } catch (SecurityException exception) { GlobalLog.Print("HttpListenerRequest#" + ValidationHelper.HashString(httpListenerRequest) + "::ProcessClientCertificate() caught SecurityException in X509Certificate2..ctor():" + ValidationHelper.ToString(exception)); result = exception; } } httpListenerRequest.SetClientCertificateError((int)pClientCertInfo->CertFlags); } } // complete the async IO and invoke the callback GlobalLog.Print("ListenerClientCertAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() calling Complete()"); } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) throw; result = exception; } finally { if(errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING){ httpListenerRequest.ClientCertState = ListenerClientCertState.Completed; } } asyncResult.InvokeCallback(result); }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() 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, "BeginWrite", ""); HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback((uint) 0); return result; } if (m_LeftToWrite>=0 && size>m_LeftToWrite) { throw new ProtocolViolationException(SR.GetString(SR.net_entitytoobig)); } uint statusCode; uint bytesSent = 0; flags |= m_LeftToWrite==size ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = m_HttpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, m_HttpContext.Response.BoundaryType==BoundaryType.Chunked, sentHeaders); // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite. UpdateAfterWrite((uint)((m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size)); try { if (!sentHeaders) { statusCode = m_HttpContext.Response.SendHeaders(null, asyncResult, flags, false); } else { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() calling UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody"); m_HttpContext.EnsureBoundHandle(); statusCode = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody( m_HttpContext.RequestQueueHandle, m_HttpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, &bytesSent, SafeLocalFree.Zero, 0, asyncResult.m_pOverlapped, null); GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() call to UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } } catch (Exception e) { if (Logging.On) Logging.Exception(Logging.HttpListener, this, "BeginWrite", e); asyncResult.InternalCleanup(); m_Closed = true; m_HttpContext.Abort(); throw; } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (m_HttpContext.Listener.IgnoreWriteExceptions && sentHeaders) { GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() suppressing error"); } else { Exception exception = new HttpListenerException((int)statusCode); if (Logging.On) Logging.Exception(Logging.HttpListener, this, "BeginWrite", exception); m_Closed = true; m_HttpContext.Abort(); throw exception; } } if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesSent); } // Last write, cache it for special cancelation handling. if ((flags & UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0) { m_LastWrite = asyncResult; } if(Logging.On)Logging.Exit(Logging.HttpListener, this, "BeginWrite", ""); return asyncResult; }
private static bool CanStartHttpListener(int port, bool useSsl, out int errorCode, out HttpListenerException listenerException) { errorCode = 0; listenerException = null; try { var httpListener = new HttpListener(); httpListener.Prefixes.Add(string.Format("{0}+:{1}/", useSsl ? "https://" : "http://", port)); httpListener.Start(); httpListener.Stop(); return true; } catch (HttpListenerException e) { errorCode = e.ErrorCode; listenerException = e; } return false; }
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", ""); }
private void DisposeCore() { Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_leftToWrite > 0 && !_inOpaqueMode) { throw new InvalidOperationException(SR.net_io_notenoughbyteswritten); } bool sentHeaders = _httpContext.Response.SentHeaders; if (sentHeaders && _leftToWrite == 0) { return; } uint statusCode = 0; if ((_httpContext.Response.BoundaryType == BoundaryType.Chunked || _httpContext.Response.BoundaryType == BoundaryType.None) && !string.Equals(_httpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase)) { if (_httpContext.Response.BoundaryType == BoundaryType.None) { flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } fixed(void *pBuffer = &s_chunkTerminator[0]) { Interop.HttpApi.HTTP_DATA_CHUNK *pDataChunk = null; if (_httpContext.Response.BoundaryType == BoundaryType.Chunked) { Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = default; dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte *)pBuffer; dataChunk.BufferLength = (uint)s_chunkTerminator.Length; pDataChunk = &dataChunk; } if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(pDataChunk, 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, pDataChunk != null ? (ushort)1 : (ushort)0, pDataChunk, 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, "Suppressing error"); } statusCode = Interop.HttpApi.ERROR_SUCCESS; } } } } else { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, null, flags, false); } } 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()); } _httpContext.Abort(); throw exception; } _leftToWrite = 0; }
private static unsafe void IOCompleted(ListenerClientCertAsyncResult asyncResult, uint errorCode, uint numBytes) { HttpListenerRequest httpListenerRequest = (HttpListenerRequest)asyncResult.AsyncObject; object result = null; try { if (errorCode == Interop.HttpApi.ERROR_MORE_DATA) { //There is a bug that has existed in http.sys since w2k3. Bytesreceived will only //return the size of the inital cert structure. To get the full size, //we need to add the certificate encoding size as well. Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *pClientCertInfo = asyncResult.RequestBlob; asyncResult.Reset(numBytes + pClientCertInfo->CertEncodedSize); uint bytesReceived = 0; errorCode = Interop.HttpApi.HttpReceiveClientCertificate( httpListenerRequest.HttpListenerContext.RequestQueueHandle, httpListenerRequest._connectionId, (uint)Interop.HttpApi.HTTP_FLAGS.NONE, asyncResult._memoryBlob, asyncResult._size, &bytesReceived, asyncResult._pOverlapped); if (errorCode == Interop.HttpApi.ERROR_IO_PENDING || (errorCode == Interop.HttpApi.ERROR_SUCCESS && !HttpListener.SkipIOCPCallbackOnSuccess)) { return; } } if (errorCode != Interop.HttpApi.ERROR_SUCCESS) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *pClientCertInfo = asyncResult._memoryBlob; if (pClientCertInfo != null) { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"pClientCertInfo:{(IntPtr)pClientCertInfo} pClientCertInfo->CertFlags: {pClientCertInfo->CertFlags} pClientCertInfo->CertEncodedSize: {pClientCertInfo->CertEncodedSize} pClientCertInfo->pCertEncoded: {(IntPtr)pClientCertInfo->pCertEncoded} pClientCertInfo->Token: {(IntPtr)pClientCertInfo->Token} pClientCertInfo->CertDeniedByMapper: {pClientCertInfo->CertDeniedByMapper}"); } if (pClientCertInfo->pCertEncoded != null) { try { byte[] certEncoded = new byte[pClientCertInfo->CertEncodedSize]; Marshal.Copy((IntPtr)pClientCertInfo->pCertEncoded, certEncoded, 0, certEncoded.Length); result = httpListenerRequest.ClientCertificate = new X509Certificate2(certEncoded); } catch (CryptographicException exception) { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"HttpListenerRequest: {httpListenerRequest} caught CryptographicException: {exception}"); } result = exception; } catch (SecurityException exception) { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"HttpListenerRequest: {httpListenerRequest} caught SecurityException: {exception}"); } result = exception; } } httpListenerRequest.SetClientCertificateError((int)pClientCertInfo->CertFlags); } } // complete the async IO and invoke the callback if (NetEventSource.IsEnabled) { NetEventSource.Info(null, "Calling Complete()"); } } catch (Exception exception) when(!ExceptionCheck.IsFatal(exception)) { result = exception; } finally { if (errorCode != Interop.HttpApi.ERROR_IO_PENDING) { httpListenerRequest.ClientCertState = ListenerClientCertState.Completed; } } asyncResult.InvokeCallback(result); }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (NetEventSource.IsEnabled) NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " 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)); } Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_closed || (size == 0 && _leftToWrite != 0)) { if (NetEventSource.IsEnabled) NetEventSource.Exit(this); HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return result; } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint bytesSent = 0; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = _httpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle); // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite. UpdateAfterWrite((uint)((_httpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size)); try { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, asyncResult, flags, false); } else { if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, &bytesSent, SafeLocalAllocHandle.Zero, 0, asyncResult._pOverlapped, null); if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } } catch (Exception e) { if (NetEventSource.IsEnabled) NetEventSource.Error(this, e.ToString()); asyncResult.InternalCleanup(); _closed = true; _httpContext.Abort(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (_httpContext.Listener.IgnoreWriteExceptions && sentHeaders) { if (NetEventSource.IsEnabled) NetEventSource.Info(this, "BeginWrite() Suppressing error"); } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) NetEventSource.Error(this, exception.ToString()); _closed = true; _httpContext.Abort(); throw exception; } } if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesSent); } // Last write, cache it for special cancelation handling. if ((flags & Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0) { _lastWrite = asyncResult; } if (NetEventSource.IsEnabled) NetEventSource.Exit(this); return asyncResult; }
private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped) { ListenerAsyncResult asyncResult = (ListenerAsyncResult)Overlapped.Unpack(nativeOverlapped).AsyncResult; object result = null; try { if ((errorCode != 0) && (errorCode != 0xea)) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { HttpListener asyncObject = asyncResult.AsyncObject as HttpListener; if (errorCode == 0) { bool stoleBlob = false; try { result = asyncObject.HandleAuthentication(asyncResult.m_RequestContext, out stoleBlob); } finally { if (stoleBlob) { asyncResult.m_RequestContext = (result == null) ? new AsyncRequestContext(asyncResult) : null; } else { asyncResult.m_RequestContext.Reset(0L, 0); } } } else { asyncResult.m_RequestContext.Reset(asyncResult.m_RequestContext.RequestBlob.RequestId, numBytes); } if (result == null) { uint num = asyncResult.QueueBeginGetContext(); if ((num != 0) && (num != 0x3e5)) { result = new HttpListenerException((int)num); } } if (result == null) { return; } } } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) { throw; } result = exception; } asyncResult.InvokeCallback(result); }
private IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback?callback, object?state) { Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_closed || (size == 0 && _leftToWrite != 0)) { HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return(result); } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint bytesSent = 0; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = _httpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle); // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite. UpdateAfterWrite((uint)((_httpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size)); try { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, asyncResult, flags, false); } else { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, &bytesSent, SafeLocalAllocHandle.Zero, 0, asyncResult._pOverlapped, null); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } } } catch (Exception e) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(this, e.ToString()); } asyncResult.InternalCleanup(); _closed = true; _httpContext.Abort(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (_httpContext.Listener !.IgnoreWriteExceptions && sentHeaders) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "BeginWrite() Suppressing error"); } } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(this, exception.ToString()); } _closed = true; _httpContext.Abort(); throw exception; } }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (NetEventSource.IsEnabled) { NetEventSource.Enter(this); } if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " 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); } HttpRequestStreamAsyncResult result = new HttpRequestStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return(result); } HttpRequestStreamAsyncResult asyncResult = null; 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) { asyncResult = new HttpRequestStreamAsyncResult(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, 0); asyncResult.InvokeCallback(dataRead); } } if (_dataChunkIndex == -1 && dataRead < size) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "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(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, dataRead); uint bytesReturned; try { 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, asyncResult._pPinnedBuffer, (uint)size, out bytesReturned, asyncResult._pOverlapped); if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } } } catch (Exception e) { if (NetEventSource.IsEnabled) { NetEventSource.Error(this, e.ToString()); } asyncResult.InternalCleanup(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (statusCode == Interop.HttpApi.ERROR_HANDLE_EOF) { asyncResult = new HttpRequestStreamAsyncResult(this, state, callback, dataRead); asyncResult.InvokeCallback((uint)0); } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } asyncResult.InternalCleanup(); throw exception; } } else if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesReturned); } } if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } return(asyncResult); }
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); }
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 static Exception CreateCommunicationException(HttpListenerException listenerException) { switch (listenerException.NativeErrorCode) { case UnsafeNativeMethods.ERROR_NO_TRACKING_SERVICE: return new CommunicationException(SR.GetString(SR.HttpNoTrackingService, listenerException.Message), listenerException); case UnsafeNativeMethods.ERROR_NETNAME_DELETED: return new CommunicationException(SR.GetString(SR.HttpNetnameDeleted, listenerException.Message), listenerException); case UnsafeNativeMethods.ERROR_INVALID_HANDLE: return new CommunicationObjectAbortedException(SR.GetString(SR.HttpResponseAborted), listenerException); case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: case UnsafeNativeMethods.ERROR_OUTOFMEMORY: case UnsafeNativeMethods.ERROR_NO_SYSTEM_RESOURCES: return new InsufficientMemoryException(SR.GetString(SR.InsufficentMemory), listenerException); default: return new CommunicationException(listenerException.Message, listenerException); } }
private static unsafe void IOCompleted(ListenerClientCertAsyncResult asyncResult, uint errorCode, uint numBytes) { HttpListenerRequest httpListenerRequest = (HttpListenerRequest)asyncResult.AsyncObject; object result = null; try { if (errorCode == Interop.HttpApi.ERROR_MORE_DATA) { //There is a bug that has existed in http.sys since w2k3. Bytesreceived will only //return the size of the inital cert structure. To get the full size, //we need to add the certificate encoding size as well. Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.RequestBlob; asyncResult.Reset(numBytes + pClientCertInfo->CertEncodedSize); uint bytesReceived = 0; errorCode = Interop.HttpApi.HttpReceiveClientCertificate( httpListenerRequest.HttpListenerContext.RequestQueueHandle, httpListenerRequest._connectionId, (uint)Interop.HttpApi.HTTP_FLAGS.NONE, asyncResult._memoryBlob, asyncResult._size, &bytesReceived, asyncResult._pOverlapped); if (errorCode == Interop.HttpApi.ERROR_IO_PENDING || (errorCode == Interop.HttpApi.ERROR_SUCCESS && !HttpListener.SkipIOCPCallbackOnSuccess)) { return; } } if (errorCode != Interop.HttpApi.ERROR_SUCCESS) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult._memoryBlob; if (pClientCertInfo != null) { if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"pClientCertInfo:{(IntPtr)pClientCertInfo} pClientCertInfo->CertFlags: {pClientCertInfo->CertFlags} pClientCertInfo->CertEncodedSize: {pClientCertInfo->CertEncodedSize} pClientCertInfo->pCertEncoded: {(IntPtr)pClientCertInfo->pCertEncoded} pClientCertInfo->Token: {(IntPtr)pClientCertInfo->Token} pClientCertInfo->CertDeniedByMapper: {pClientCertInfo->CertDeniedByMapper}"); if (pClientCertInfo->pCertEncoded != null) { try { byte[] certEncoded = new byte[pClientCertInfo->CertEncodedSize]; Marshal.Copy((IntPtr)pClientCertInfo->pCertEncoded, certEncoded, 0, certEncoded.Length); result = httpListenerRequest.ClientCertificate = new X509Certificate2(certEncoded); } catch (CryptographicException exception) { if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"HttpListenerRequest: {httpListenerRequest} caught CryptographicException: {exception}"); result = exception; } catch (SecurityException exception) { if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"HttpListenerRequest: {httpListenerRequest} caught SecurityException: {exception}"); result = exception; } } httpListenerRequest.SetClientCertificateError((int)pClientCertInfo->CertFlags); } } // complete the async IO and invoke the callback if (NetEventSource.IsEnabled) NetEventSource.Info(null, "Calling Complete()"); } catch (Exception exception) when (!ExceptionCheck.IsFatal(exception)) { result = exception; } finally { if (errorCode != Interop.HttpApi.ERROR_IO_PENDING) { httpListenerRequest.ClientCertState = ListenerClientCertState.Completed; } } 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); }
public void SplashPresenter_StartApplication_Picks_Up_HttpListenerExceptions_When_Starting_WebServer() { var exception = new HttpListenerException(); _WebServer.SetupSet(s => s.Online = true).Callback(() => { throw exception; }); _WebServer.Setup(a => a.Port).Returns(123); _Presenter.Initialise(_View.Object); _Presenter.StartApplication(); _Log.Verify(g => g.WriteLine("Caught exception when starting web server: {0}", exception.ToString()), Times.Once()); _View.Verify(v => v.ReportProblem(String.Format(Strings.CannotStartWebServerFull, 123), Strings.CannotStartWebServerTitle, false), Times.Once()); _View.Verify(v => v.ReportProblem(Strings.SuggestUseDifferentPortFull, Strings.SuggestUseDifferentPortTitle, false), Times.Once()); }
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); }
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); }
private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes) { object result = null; try { GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() errorCode:[" + errorCode.ToString() + "] numBytes:[" + numBytes.ToString() + "]"); if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener; if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob // points to it we need to hook up our authentication handling code here. bool stoleBlob = false; try { if (httpWebListener.ValidateRequest(asyncResult.m_RequestContext)) { result = httpWebListener.HandleAuthentication(asyncResult.m_RequestContext, out stoleBlob); } } finally { if (stoleBlob) { // The request has been handed to the user, which means this code can't reuse the blob. Reset it here. asyncResult.m_RequestContext = result == null ? new AsyncRequestContext(asyncResult) : null; } else { asyncResult.m_RequestContext.Reset(0, 0); } } } else { asyncResult.m_RequestContext.Reset(asyncResult.m_RequestContext.RequestBlob->RequestId, numBytes); } // We need to issue a new request, either because auth failed, or because our buffer was too small the first time. if (result==null) { uint statusCode = asyncResult.QueueBeginGetContext(); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { // someother bad error, possible(?) return values are: // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED result = new HttpListenerException((int)statusCode); } } if (result==null) { return; } } // complete the async IO and invoke the callback GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() calling Complete()"); } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) throw; GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() Caught exception:" + exception.ToString()); result = exception; } asyncResult.InvokeCallback(result); }
private static unsafe void WaitCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped *nativeOverlapped) { ListenerClientCertAsyncResult asyncResult = (ListenerClientCertAsyncResult)Overlapped.Unpack(nativeOverlapped).AsyncResult; HttpListenerRequest asyncObject = (HttpListenerRequest)asyncResult.AsyncObject; object result = null; try { if (errorCode == 0xea) { UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *requestBlob = asyncResult.RequestBlob; asyncResult.Reset(numBytes + requestBlob->CertEncodedSize); uint pBytesReceived = 0; errorCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(asyncObject.HttpListenerContext.RequestQueueHandle, asyncObject.m_ConnectionId, 0, asyncResult.m_MemoryBlob, asyncResult.m_Size, &pBytesReceived, asyncResult.m_pOverlapped); if ((errorCode == 0x3e5) || (errorCode == 0)) { return; } } if (errorCode != 0) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *memoryBlob = asyncResult.m_MemoryBlob; if (memoryBlob != null) { if (memoryBlob->pCertEncoded != null) { try { byte[] destination = new byte[memoryBlob->CertEncodedSize]; Marshal.Copy((IntPtr)memoryBlob->pCertEncoded, destination, 0, destination.Length); result = asyncObject.ClientCertificate = new X509Certificate2(destination); } catch (CryptographicException exception) { result = exception; } catch (SecurityException exception2) { result = exception2; } } asyncObject.SetClientCertificateError((int)memoryBlob->CertFlags); } } } catch (Exception exception3) { if (NclUtilities.IsFatal(exception3)) { throw; } result = exception3; } finally { if (errorCode != 0x3e5) { asyncObject.ClientCertState = ListenerClientCertState.Completed; } } asyncResult.InvokeCallback(result); }