private static void IOCompleted(HttpRequestStreamAsyncResult asyncResult, uint errorCode, uint numBytes)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, $"asyncResult: {asyncResult} errorCode:0x {errorCode.ToString("x8")} numBytes: {numBytes}");
                }
                object result = null;

                try
                {
                    if (errorCode != Interop.HttpApi.ERROR_SUCCESS && errorCode != Interop.HttpApi.ERROR_HANDLE_EOF)
                    {
                        asyncResult.ErrorCode = (int)errorCode;
                        result = new HttpListenerException((int)errorCode);
                    }
                    else
                    {
                        result = numBytes;
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.DumpBuffer(asyncResult, (IntPtr)asyncResult._pPinnedBuffer, (int)numBytes);
                        }
                    }
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(null, $"asyncResult: {asyncResult} calling Complete()");
                    }
                }
                catch (Exception e)
                {
                    result = e;
                }
                asyncResult.InvokeCallback(result);
            }
        public static void DumpBuffer(object?thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string?memberName = null)
        {
            if (Log.IsEnabled() && offset >= 0 && offset <= buffer.Length - count)
            {
                count = Math.Min(count, MaxDumpSize);

                byte[] slice = buffer;
                if (offset != 0 || count != buffer.Length)
                {
                    slice = new byte[count];
                    Buffer.BlockCopy(buffer, offset, slice, 0, count);
                }

                Log.DumpBuffer(IdOf(thisOrContextObject), memberName, slice);
            }
        }
Exemple #3
0
        public static void DumpBuffer(object thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string memberName = null)
        {
            if (IsEnabled)
            {
                if (offset < 0 || offset > buffer.Length - count)
                {
                    Fail(thisOrContextObject, $"Invalid {nameof(DumpBuffer)} Args. Length={buffer.Length}, Offset={offset}, Count={count}", memberName);
                    return;
                }

                count = Math.Min(count, MaxDumpSize);

                byte[] slice = buffer;
                if (offset != 0 || count != buffer.Length)
                {
                    slice = new byte[count];
                    Buffer.BlockCopy(buffer, offset, slice, 0, count);
                }

                Log.DumpBuffer(IdOf(thisOrContextObject), memberName, slice);
            }
        }
        private static void IOCompleted(HttpResponseStreamAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            if (NetEventSource.Log.IsEnabled())
            {
                NetEventSource.Info(null, $"errorCode:0x{errorCode:x8} numBytes: {numBytes}");
            }
            object?result;

            try
            {
                if (errorCode != Interop.HttpApi.ERROR_SUCCESS && errorCode != Interop.HttpApi.ERROR_HANDLE_EOF)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    // if we sent headers and body together, numBytes will be the total, but we need to only account for the data
                    if (asyncResult._dataChunks == null)
                    {
                        result = (uint)0;
                        if (NetEventSource.Log.IsEnabled())
                        {
                            NetEventSource.DumpBuffer(null, IntPtr.Zero, 0);
                        }
                    }
                    else
                    {
                        result = asyncResult._dataChunks.Length == 1 ? asyncResult._dataChunks[0].BufferLength : 0;
                        if (NetEventSource.Log.IsEnabled())
                        {
                            for (int i = 0; i < asyncResult._dataChunks.Length; i++)
                            {
                                NetEventSource.DumpBuffer(null, (IntPtr)asyncResult._dataChunks[0].pBuffer, (int)asyncResult._dataChunks[0].BufferLength);
                            }
                        }
                    }
                }
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, "Calling Complete()");
                }
            }
            catch (Exception e)
            {
                result = e;
            }
            asyncResult.InvokeCallback(result);
        }
        public override int Read([In, Out] byte[] buffer, int offset, int size)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this);
                NetEventSource.Info(this, "size:" + size + " offset:" + offset);
            }
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }
            if (size == 0 || _closed)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this, "dataRead:0");
                }
                return(0);
            }

            uint dataRead = 0;

            if (_dataChunkIndex != -1)
            {
                dataRead = Interop.HttpApi.GetChunks(_httpContext.Request.RequestBuffer, _httpContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
            }

            if (_dataChunkIndex == -1 && dataRead < size)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, "size:" + size + " offset:" + offset);
                }
                uint statusCode    = 0;
                uint extraDataRead = 0;
                offset += (int)dataRead;
                size   -= (int)dataRead;

                //the http.sys team recommends that we limit the size to 128kb
                if (size > MaxReadSize)
                {
                    size = MaxReadSize;
                }

                fixed(byte *pBuffer = buffer)
                {
                    // issue unmanaged blocking call
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "Calling Interop.HttpApi.HttpReceiveRequestEntityBody");
                    }

                    uint flags = 0;

                    if (!_inOpaqueMode)
                    {
                        flags = (uint)Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY;
                    }

                    statusCode =
                        Interop.HttpApi.HttpReceiveRequestEntityBody(
                            _httpContext.RequestQueueHandle,
                            _httpContext.RequestId,
                            flags,
                            (void *)(pBuffer + offset),
                            (uint)size,
                            out extraDataRead,
                            null);

                    dataRead += extraDataRead;
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead);
                    }
                }

                if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF)
                {
                    Exception exception = new HttpListenerException((int)statusCode);
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Error(this, exception.ToString());
                    }
                    throw exception;
                }
                UpdateAfterRead(statusCode, dataRead);
            }
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.DumpBuffer(this, buffer, offset, (int)dataRead);
                NetEventSource.Info(this, "returning dataRead:" + dataRead);
                NetEventSource.Exit(this, "dataRead:" + dataRead);
            }
            return((int)dataRead);
        }
Exemple #6
0
        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);
            }
        }