< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.HttpInput
Assembly: CoreWCF.Http
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Http/src/CoreWCF/Channels/HttpChannelHelpers.cs
Line coverage
72%
Covered lines: 132
Uncovered lines: 50
Coverable lines: 182
Total lines: 2034
Line coverage: 72.5%
Branch coverage
79%
Covered branches: 75
Total branches: 94
Branch coverage: 79.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Http/src/CoreWCF/Channels/HttpChannelHelpers.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Diagnostics;
 6using System.Globalization;
 7using System.IO;
 8using System.Net;
 9using System.Net.Mime;
 10using System.Security.Authentication.ExtendedProtection;
 11using System.Text;
 12using System.Threading;
 13using System.Threading.Tasks;
 14using System.Xml;
 15using CoreWCF.Runtime;
 16using Microsoft.AspNetCore.Http;
 17using Microsoft.AspNetCore.Http.Features;
 18using Microsoft.Extensions.Primitives;
 19
 20namespace CoreWCF.Channels
 21{
 22    // abstract out the common functionality of an "HttpInput"
 23    internal abstract class HttpInput
 24    {
 25        private const string multipartRelatedMediaType = "multipart/related";
 26        private const string startInfoHeaderParam = "start-info";
 27        private const string defaultContentType = "application/octet-stream";
 28        private readonly BufferManager _bufferManager;
 29        private readonly bool _isRequest;
 30        private readonly MessageEncoder _messageEncoder;
 31        private readonly IHttpTransportFactorySettings _settings;
 32        private readonly bool _streamed;
 33        private Stream _inputStream;
 34        private readonly bool _enableChannelBinding;
 35        private bool _errorGettingInputStream;
 36
 65037        protected HttpInput(IHttpTransportFactorySettings settings, bool isRequest, bool enableChannelBinding)
 38        {
 65039            _settings = settings;
 65040            _bufferManager = settings.BufferManager;
 65041            _messageEncoder = settings.MessageEncoderFactory.Encoder;
 65042            WebException = null;
 65043            _isRequest = isRequest;
 65044            _inputStream = null;
 65045            _enableChannelBinding = enableChannelBinding;
 46
 65047            if (isRequest)
 48            {
 65049                _streamed = TransferModeHelper.IsRequestStreamed(settings.TransferMode);
 50            }
 51            else
 52            {
 053                _streamed = TransferModeHelper.IsResponseStreamed(settings.TransferMode);
 54            }
 055        }
 56
 65157        internal WebException WebException { get; set; }
 58
 59        // Note: This method will return null in the case where throwOnError is false, and a non-fatal error occurs.
 60        // Please exercise caution when passing in throwOnError = false.  This should basically only be done in error
 61        // code paths, or code paths where there is very good reason that you would not want this method to throw.
 62        // When passing in throwOnError = false, please handle the case where this method returns null.
 63        public Stream GetInputStream(bool throwOnError)
 64        {
 62165            if (_inputStream == null && (throwOnError || !_errorGettingInputStream))
 66            {
 67                try
 68                {
 62169                    _inputStream = GetInputStream();
 62170                    _errorGettingInputStream = false;
 62171                }
 072                catch (Exception e)
 73                {
 074                    _errorGettingInputStream = true;
 075                    if (throwOnError || Fx.IsFatal(e))
 76                    {
 077                        throw;
 78                    }
 79
 080                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
 081                }
 82            }
 83
 62184            return _inputStream;
 85        }
 86
 87        // -1 if chunked
 88        public abstract long ContentLength { get; }
 89        protected abstract string ContentTypeCore { get; }
 90        protected abstract bool HasContent { get; }
 91        protected abstract string SoapActionHeader { get; }
 92        protected abstract Stream GetInputStream();
 093        protected virtual ChannelBinding ChannelBinding { get { return null; } }
 94
 95        protected string ContentType
 96        {
 97            get
 98            {
 210799                string contentType = ContentTypeCore;
 100
 2107101                if (string.IsNullOrEmpty(contentType))
 102                {
 3103                    return defaultContentType;
 104                }
 105
 2104106                return contentType;
 107            }
 108        }
 109
 110        private void ThrowMaxReceivedMessageSizeExceeded()
 111        {
 0112            if (_isRequest)
 113            {
 0114                ThrowHttpProtocolException(SR.Format(SR.MaxReceivedMessageSizeExceeded, _settings.MaxReceivedMessageSize
 115            }
 116            else
 117            {
 0118                string message = SR.Format(SR.MaxReceivedMessageSizeExceeded, _settings.MaxReceivedMessageSize);
 0119                Exception inner = new QuotaExceededException(message);
 0120                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(message, inner));
 121            }
 122        }
 123
 124        private async Task<Message> DecodeBufferedMessageAsync(ArraySegment<byte> buffer, Stream inputStream)
 125        {
 126            try
 127            {
 128                // if we're chunked, make sure we've consumed the whole body
 602129                if (ContentLength == -1 && buffer.Count == _settings.MaxReceivedMessageSize)
 130                {
 0131                    byte[] extraBuffer = new byte[1];
 0132                    int extraReceived = await inputStream.ReadAsync(extraBuffer, 0, 1);
 0133                    if (extraReceived > 0)
 134                    {
 0135                        ThrowMaxReceivedMessageSizeExceeded();
 136                    }
 137                }
 138
 139                try
 140                {
 602141                    return _messageEncoder.ReadMessage(buffer, _bufferManager, ContentType);
 142                }
 0143                catch (XmlException xmlException)
 144                {
 0145                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0146                        new ProtocolException(SR.MessageXmlProtocolError, xmlException));
 147                }
 148            }
 149            finally
 150            {
 602151                inputStream.Close();
 152            }
 602153        }
 154
 155        private async Task<Message> ReadBufferedMessageAsync(Stream inputStream)
 156        {
 602157            ArraySegment<byte> messageBuffer = GetMessageBuffer();
 602158            byte[] buffer = messageBuffer.Array;
 602159            int offset = 0;
 602160            int count = messageBuffer.Count;
 161
 3750162            while (count > 0)
 163            {
 3148164                int bytesRead = await inputStream.ReadAsync(buffer, offset, count);
 3148165                if (bytesRead == 0) // EOF
 166                {
 0167                    if (ContentLength != -1)
 168                    {
 0169                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0170                            new ProtocolException(SR.HttpContentLengthIncorrect));
 171                    }
 172
 173                    break;
 174                }
 3148175                count -= bytesRead;
 3148176                offset += bytesRead;
 177            }
 178
 602179            return await DecodeBufferedMessageAsync(new ArraySegment<byte>(buffer, 0, offset), inputStream);
 602180        }
 181
 182        private async Task<Message> ReadChunkedBufferedMessageAsync(Stream inputStream)
 183        {
 184            try
 185            {
 9186                return _messageEncoder.ReadMessage(await BufferMessageStreamAsync(inputStream, _bufferManager, _settings
 187            }
 0188            catch (XmlException xmlException)
 189            {
 0190                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0191                    new ProtocolException(SR.MessageXmlProtocolError, xmlException));
 192            }
 9193        }
 194
 195        private async Task<Message> ReadStreamedMessageAsync(Stream inputStream)
 196        {
 10197            MaxMessageSizeStream maxMessageSizeStream = new MaxMessageSizeStream(inputStream, _settings.MaxReceivedMessa
 198
 199            try
 200            {
 10201                return await _messageEncoder.ReadMessageAsync(maxMessageSizeStream, _settings.MaxBufferSize, ContentType
 202            }
 0203            catch (XmlException xmlException)
 204            {
 0205                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0206                    new ProtocolException(SR.MessageXmlProtocolError, xmlException));
 207            }
 10208        }
 209
 210        // used for buffered streaming
 211        internal async Task<ArraySegment<byte>> BufferMessageStreamAsync(Stream stream, BufferManager bufferManager, int
 212        {
 9213            byte[] buffer = bufferManager.TakeBuffer(ConnectionOrientedTransportDefaults.ConnectionBufferSize);
 9214            int offset = 0;
 9215            int currentBufferSize = Math.Min(buffer.Length, maxBufferSize);
 216
 3347217            while (offset < currentBufferSize)
 218            {
 3347219                int count = await stream.ReadAsync(buffer, offset, currentBufferSize - offset);
 3347220                if (count == 0)
 221                {
 9222                    stream.Dispose();
 9223                    break;
 224                }
 225
 3338226                offset += count;
 3338227                if (offset == currentBufferSize)
 228                {
 19229                    if (currentBufferSize >= maxBufferSize)
 230                    {
 0231                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(MaxMessageSizeStream.CreateMaxReceived
 232                    }
 233
 19234                    currentBufferSize = Math.Min(currentBufferSize * 2, maxBufferSize);
 19235                    byte[] temp = bufferManager.TakeBuffer(currentBufferSize);
 19236                    Buffer.BlockCopy(buffer, 0, temp, 0, offset);
 19237                    bufferManager.ReturnBuffer(buffer);
 19238                    buffer = temp;
 239                }
 240            }
 241
 9242            return new ArraySegment<byte>(buffer, 0, offset);
 9243        }
 244
 245        protected abstract void AddProperties(Message message);
 246
 247        private void ApplyChannelBinding(Message message)
 248        {
 648249            if (_enableChannelBinding)
 250            {
 0251                ChannelBindingUtility.TryAddToMessage(ChannelBinding, message, true);
 252            }
 648253        }
 254
 255        protected abstract Task CheckForContentAsync();
 256
 257        // makes sure that appropriate HTTP level headers are included in the received Message
 258        private Exception ProcessHttpAddressing(Message message)
 259        {
 648260            Exception result = null;
 648261            AddProperties(message);
 262
 263            // check if user is receiving WS-1 messages
 648264            if (message.Version.Addressing == AddressingVersion.None)
 265            {
 526266                bool actionAbsent = false;
 267                try
 268                {
 526269                    actionAbsent = (message.Headers.Action == null);
 526270                }
 271                catch (XmlException e)
 272                {
 0273                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 0274                }
 275                catch (CommunicationException e)
 276                {
 0277                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 0278                }
 279
 526280                if (!actionAbsent)
 281                {
 0282                    result = new ProtocolException(SR.Format(SR.HttpAddressingNoneHeaderOnWire, "Action"));
 283                }
 284
 526285                bool toAbsent = false;
 286                try
 287                {
 526288                    toAbsent = (message.Headers.To == null);
 526289                }
 290                catch (XmlException e)
 291                {
 0292                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 0293                }
 294                catch (CommunicationException e)
 295                {
 0296                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 0297                }
 298
 526299                if (!toAbsent)
 300                {
 0301                    result = new ProtocolException(SR.Format(SR.HttpAddressingNoneHeaderOnWire, "To"));
 302                }
 526303                message.Headers.To = message.Properties.Via;
 304            }
 305
 648306            if (_isRequest)
 307            {
 648308                string action = null;
 309
 648310                if (message.Version.Envelope == EnvelopeVersion.Soap11)
 311                {
 493312                    action = SoapActionHeader;
 313                }
 155314                else if (message.Version.Envelope == EnvelopeVersion.Soap12 && !string.IsNullOrEmpty(ContentType))
 315                {
 120316                    ContentType parsedContentType = new ContentType(ContentType);
 317
 120318                    if (parsedContentType.MediaType == multipartRelatedMediaType && parsedContentType.Parameters.Contain
 319                    {
 320                        // fix to grab action from start-info as stated in RFC2387
 6321                        action = new ContentType(parsedContentType.Parameters[startInfoHeaderParam]).Parameters["action"
 322                    }
 120323                    if (action == null)
 324                    {
 325                        // only if we can't find an action inside start-info
 120326                        action = parsedContentType.Parameters["action"];
 327                    }
 328                }
 329
 648330                if (action != null)
 331                {
 494332                    action = UrlUtility.UrlDecode(action, Encoding.UTF8);
 333
 494334                    if (action.Length >= 2 && action[0] == '"' && action[action.Length - 1] == '"')
 335                    {
 493336                        action = action.Substring(1, action.Length - 2);
 337                    }
 338
 494339                    if (message.Version.Addressing == AddressingVersion.None)
 340                    {
 491341                        message.Headers.Action = action;
 342                    }
 343
 344                    try
 345                    {
 494346                        if (action.Length > 0 && string.Compare(message.Headers.Action, action, StringComparison.Ordinal
 347                        {
 1348                            result = new ActionMismatchAddressingException(SR.Format(SR.HttpSoapActionMismatchFault,
 1349                                message.Headers.Action, action), message.Headers.Action, action);
 350                        }
 494351                    }
 352                    catch (XmlException e)
 353                    {
 0354                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 0355                    }
 356                    catch (CommunicationException e)
 357                    {
 0358                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 0359                    }
 360                }
 361            }
 362
 648363            ApplyChannelBinding(message);
 364
 648365            return result;
 366        }
 367
 368        private void ValidateContentType()
 369        {
 650370            if (!HasContent)
 371            {
 28372                return;
 373            }
 374
 622375            if (string.IsNullOrEmpty(ContentType))
 376            {
 0377                ThrowHttpProtocolException(SR.HttpContentTypeHeaderRequired, HttpStatusCode.UnsupportedMediaType, HttpCh
 378            }
 622379            if (!_messageEncoder.IsContentTypeSupported(ContentType))
 380            {
 1381                string statusDescription = string.Format(CultureInfo.InvariantCulture, HttpChannelUtilities.StatusDescri
 1382                ThrowHttpProtocolException(SR.Format(SR.ContentTypeMismatch, ContentType, _messageEncoder.ContentType), 
 383            }
 621384        }
 385
 386        public async Task<(Message message, Exception requestException)> ParseIncomingMessageAsync()
 387        {
 650388            Exception requestException = null;
 650389            bool throwing = true;
 390            try
 391            {
 650392                await CheckForContentAsync();
 650393                ValidateContentType();
 394
 395                Message message;
 649396                if (!HasContent)
 397                {
 28398                    if (_messageEncoder.MessageVersion == MessageVersion.None)
 399                    {
 27400                        message = new NullMessage();
 401                    }
 402                    else
 403                    {
 1404                        return (null, requestException);
 405                    }
 406                }
 407                else
 408                {
 621409                    Stream stream = GetInputStream(true);
 621410                    if (_streamed)
 411                    {
 10412                        message = await ReadStreamedMessageAsync(stream);
 413                    }
 611414                    else if (ContentLength == -1)
 415                    {
 9416                        message = await ReadChunkedBufferedMessageAsync(stream);
 417                    }
 418                    else
 419                    {
 602420                        message = await ReadBufferedMessageAsync(stream);
 421                    }
 422                }
 423
 648424                requestException = ProcessHttpAddressing(message);
 425
 648426                throwing = false;
 648427                return (message, requestException);
 428            }
 429            finally
 430            {
 650431                if (throwing)
 432                {
 2433                    Close();
 434                }
 435            }
 649436        }
 437
 438        private void ThrowHttpProtocolException(string message, HttpStatusCode statusCode)
 439        {
 0440            ThrowHttpProtocolException(message, statusCode, null);
 0441        }
 442
 443        private void ThrowHttpProtocolException(string message, HttpStatusCode statusCode, string statusDescription)
 444        {
 1445            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateHttpProtocolException(message, statusCode, s
 446        }
 447
 448        internal static ProtocolException CreateHttpProtocolException(string message, HttpStatusCode statusCode, string 
 449        {
 1450            ProtocolException exception = new ProtocolException(message, innerException);
 1451            exception.Data.Add(HttpChannelUtilities.HttpStatusCodeExceptionKey, statusCode);
 1452            if (statusDescription != null && statusDescription.Length > 0)
 453            {
 1454                exception.Data.Add(HttpChannelUtilities.HttpStatusDescriptionExceptionKey, statusDescription);
 455            }
 456
 1457            return exception;
 458        }
 459
 460        protected virtual void Close()
 461        {
 2462        }
 463
 464        private ArraySegment<byte> GetMessageBuffer()
 465        {
 602466            long count = ContentLength;
 467            int bufferSize;
 468
 602469            if (count > _settings.MaxReceivedMessageSize)
 470            {
 0471                ThrowMaxReceivedMessageSizeExceeded();
 472            }
 473
 602474            bufferSize = (int)count;
 475
 602476            return new ArraySegment<byte>(_bufferManager.TakeBuffer(bufferSize), 0, bufferSize);
 477        }
 478    }
 479
 480    // abstract out the common functionality of an "HttpOutput"
 481    internal abstract class HttpOutput
 482    {
 483        private HttpAbortReason _abortReason;
 484        private bool _isDisposed;
 485        private readonly bool _isRequest;
 486        private readonly Message _message;
 487        private readonly IHttpTransportFactorySettings _settings;
 488        private byte[] _bufferToRecycle;
 489        private readonly BufferManager _bufferManager;
 490        private readonly MessageEncoder _messageEncoder;
 491        private readonly bool _streamed;
 492        private static Action<object> s_onStreamSendTimeout;
 493        private Stream _outputStream;
 494
 495        protected HttpOutput(IHttpTransportFactorySettings settings, Message message, bool isRequest)
 496        {
 497            _settings = settings;
 498            _message = message;
 499            _isRequest = isRequest;
 500            _bufferManager = settings.BufferManager;
 501            _messageEncoder = settings.MessageEncoderFactory.Encoder;
 502            CanSendCompressedResponses = _messageEncoder is ICompressedMessageEncoder compressedMessageEncoder && compre
 503            if (isRequest)
 504            {
 505                _streamed = TransferModeHelper.IsRequestStreamed(settings.TransferMode);
 506            }
 507            else
 508            {
 509                _streamed = TransferModeHelper.IsResponseStreamed(settings.TransferMode);
 510            }
 511        }
 512
 513        protected virtual bool IsChannelBindingSupportEnabled { get { return false; } }
 514        protected virtual ChannelBinding ChannelBinding { get { return null; } }
 515
 516        protected void Abort()
 517        {
 518            Abort(HttpAbortReason.Aborted);
 519        }
 520
 521        public virtual void Abort(HttpAbortReason reason)
 522        {
 523            if (_isDisposed)
 524            {
 525                return;
 526            }
 527
 528            _abortReason = reason;
 529
 530            CleanupBuffer();
 531        }
 532
 533        public Task CloseAsync()
 534        {
 535            if (_isDisposed)
 536            {
 537                return Task.CompletedTask;
 538            }
 539
 540            try
 541            {
 542                if (_outputStream != null)
 543                {
 544                    _outputStream.Close();
 545                }
 546            }
 547            finally
 548            {
 549                CleanupBuffer();
 550            }
 551
 552            return Task.CompletedTask;
 553        }
 554
 555        private void CleanupBuffer()
 556        {
 557            byte[] bufferToRecycleSnapshot = Interlocked.Exchange<byte[]>(ref _bufferToRecycle, null);
 558            if (bufferToRecycleSnapshot != null)
 559            {
 560                _bufferManager.ReturnBuffer(bufferToRecycleSnapshot);
 561            }
 562
 563            _isDisposed = true;
 564        }
 565
 566        protected abstract void AddMimeVersion(string version);
 567        protected abstract void AddHeader(string name, string value);
 568        protected abstract void SetContentType(string contentType);
 569        protected abstract void SetContentEncoding(string contentEncoding);
 570        protected abstract void SetStatusCode(HttpStatusCode statusCode);
 571        protected abstract void SetStatusDescription(string statusDescription);
 572        protected virtual bool CleanupChannelBinding { get { return true; } }
 573        protected virtual void SetContentLength(int contentLength)
 574        {
 575        }
 576
 577        protected virtual string HttpMethod { get { return null; } }
 578
 579        public virtual ChannelBinding TakeChannelBinding()
 580        {
 581            return null;
 582        }
 583
 584        private void ApplyChannelBinding()
 585        {
 586            if (IsChannelBindingSupportEnabled)
 587            {
 588                ChannelBindingUtility.TryAddToMessage(ChannelBinding, _message, CleanupChannelBinding);
 589            }
 590        }
 591
 592        protected abstract Stream GetOutputStream();
 593
 594        protected virtual bool WillGetOutputStreamCompleteSynchronously
 595        {
 596            get { return true; }
 597        }
 598
 599        protected bool CanSendCompressedResponses { get; }
 600
 601        protected virtual bool PrepareHttpSend(Message message)
 602        {
 603            string action = message.Headers.Action;
 604
 605            if (message.Version.Addressing == AddressingVersion.None)
 606            {
 607                message.Headers.Action = null;
 608                message.Headers.To = null;
 609            }
 610
 611            string contentType = null;
 612
 613            if (message.Version == MessageVersion.None)
 614            {
 615                if (message.Properties.TryGetValue(HttpResponseMessageProperty.Name, out object property))
 616                {
 617                    HttpResponseMessageProperty responseProperty = (HttpResponseMessageProperty)property;
 618                    if (!string.IsNullOrEmpty(responseProperty.Headers[HttpResponseHeader.ContentType]))
 619                    {
 620                        contentType = responseProperty.Headers[HttpResponseHeader.ContentType];
 621                        if (!_messageEncoder.IsContentTypeSupported(contentType))
 622                        {
 623                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 624                                new ProtocolException(SR.Format(SR.ResponseContentTypeNotSupported,
 625                                contentType)));
 626                        }
 627                    }
 628                }
 629            }
 630
 631            if (string.IsNullOrEmpty(contentType))
 632            {
 633                //MtomMessageEncoder mtomMessageEncoder = messageEncoder as MtomMessageEncoder;
 634                //if (mtomMessageEncoder == null)
 635                //{
 636                contentType = _messageEncoder.ContentType;
 637                //}
 638                //else
 639                //{
 640                //    contentType = mtomMessageEncoder.GetContentType(out this.mtomBoundary);
 641                //    // For MTOM messages, add a MIME version header
 642                //    AddMimeVersion("1.0");
 643                //}
 644            }
 645
 646            SetContentType(contentType);
 647            return message is NullMessage;
 648        }
 649
 650        private ArraySegment<byte> SerializeBufferedMessage(Message message)
 651        {
 652            // by default, the HttpOutput should own the buffer and clean it up
 653            return SerializeBufferedMessage(message, true);
 654        }
 655
 656        private ArraySegment<byte> SerializeBufferedMessage(Message message, bool shouldRecycleBuffer)
 657        {
 658            ArraySegment<byte> result;
 659
 660            //MtomMessageEncoder mtomMessageEncoder = messageEncoder as MtomMessageEncoder;
 661            //if (mtomMessageEncoder == null)
 662            //{
 663            result = _messageEncoder.WriteMessage(message, int.MaxValue, _bufferManager);
 664            //}
 665            //else
 666            //{
 667            //    result = mtomMessageEncoder.WriteMessage(message, int.MaxValue, bufferManager, 0, this.mtomBoundary);
 668            //}
 669
 670            if (shouldRecycleBuffer)
 671            {
 672                // Only set this.bufferToRecycle if the HttpOutput owns the buffer, we will clean it up upon httpOutput.
 673                // Otherwise, caller of SerializeBufferedMessage assumes responsibility for returning the buffer to the 
 674                _bufferToRecycle = result.Array;
 675            }
 676            return result;
 677        }
 678
 679        private Stream GetWrappedOutputStream()
 680        {
 681            const int ChunkSize = 32768;    // buffer size used for synchronous writes
 682            // const int BufferSize = 16384;   // buffer size used for asynchronous writes
 683            // const int BufferCount = 4;      // buffer count used for asynchronous writes
 684
 685            // Writing an HTTP request chunk has a high fixed cost, so use BufferedStream to avoid writing
 686            // small ones.
 687            // TODO: Evaluate whether we need to buffer the output stream and if concurrent io is supported
 688            //return supportsConcurrentIO ? (Stream)new BufferedOutputAsyncStream(outputStream, BufferSize, BufferCount)
 689            //return this.supportsConcurrentIO ? (Stream)new BufferedOutputAsyncStream(this.outputStream, BufferSize, Bu
 690            return new BufferedStream(_outputStream, ChunkSize);
 691        }
 692
 693        private async Task WriteStreamedMessageAsync(CancellationToken token)
 694        {
 695            _outputStream = GetWrappedOutputStream();
 696
 697            // Since HTTP streams don't support timeouts, we can't just use TimeoutStream here.
 698            // Rather, we need to run a timer to bound the overall operation
 699            if (s_onStreamSendTimeout == null)
 700            {
 701                s_onStreamSendTimeout = OnStreamSendTimeout;
 702            }
 703
 704            // TODO: Verify that the cancellation token is honored for timeout
 705            //IOThreadTimer sendTimer = new IOThreadTimer(onStreamSendTimeout, this, true);
 706            //sendTimer.Set(timeout);
 707
 708            try
 709            {
 710                //MtomMessageEncoder mtomMessageEncoder = messageEncoder as MtomMessageEncoder;
 711                //if (mtomMessageEncoder == null)
 712                //{
 713                await _messageEncoder.WriteMessageAsync(_message, _outputStream);
 714                //}
 715                //else
 716                //{
 717                //    mtomMessageEncoder.WriteMessage(this.message, this.outputStream, this.mtomBoundary);
 718                //}
 719
 720                //if (this.supportsConcurrentIO)
 721                //{
 722                //    this.outputStream.Close();
 723                //}
 724            }
 725            finally
 726            {
 727                //sendTimer.Cancel();
 728            }
 729        }
 730
 731        private static void OnStreamSendTimeout(object state)
 732        {
 733            HttpOutput thisPtr = (HttpOutput)state;
 734            thisPtr.Abort(HttpAbortReason.TimedOut);
 735        }
 736
 737        public async Task SendAsync(CancellationToken token)
 738        {
 739            bool suppressEntityBody = PrepareHttpSend(_message);
 740
 741            if (suppressEntityBody)
 742            {
 743                // requests can't always support an output stream (for GET, etc)
 744                if (!_isRequest)
 745                {
 746                    _outputStream = GetOutputStream();
 747                }
 748                else
 749                {
 750                    SetContentLength(0);
 751                }
 752            }
 753            else if (_streamed)
 754            {
 755                _outputStream = GetOutputStream();
 756                ApplyChannelBinding();
 757                await WriteStreamedMessageAsync(token);
 758            }
 759            else
 760            {
 761                if (IsChannelBindingSupportEnabled)
 762                {
 763                    //need to get the Channel binding token (CBT), apply channel binding info to the message and then wr
 764                    //CBT is only enabled when message security is in the stack, which also requires an HTTP entity body
 765                    //should be safe to always get the stream.
 766                    _outputStream = GetOutputStream();
 767
 768                    ApplyChannelBinding();
 769
 770                    ArraySegment<byte> buffer = SerializeBufferedMessage(_message);
 771
 772                    Fx.Assert(buffer.Count != 0, "We should always have an entity body in this case...");
 773                    await _outputStream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count);
 774                }
 775                else
 776                {
 777                    ArraySegment<byte> buffer = SerializeBufferedMessage(_message);
 778                    SetContentLength(buffer.Count);
 779
 780                    // requests can't always support an output stream (for GET, etc)
 781                    if (!_isRequest || buffer.Count > 0)
 782                    {
 783                        _outputStream = GetOutputStream();
 784                        await _outputStream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count);
 785                    }
 786                }
 787            }
 788        }
 789
 790        internal static HttpOutput CreateHttpOutput(HttpContext httpContext, IHttpTransportFactorySettings settings, Mes
 791        {
 792            return new AspNetCoreHttpOutput(httpContext, settings, message, httpMethod);
 793        }
 794
 795        private class AspNetCoreHttpOutput : HttpOutput
 796        {
 797            private readonly HttpResponse _httpResponse;
 798            private readonly HttpContext _httpContext;
 799            private readonly string _httpMethod;
 800
 801            public AspNetCoreHttpOutput(HttpContext httpContext, IHttpTransportFactorySettings settings, Message message
 802                : base(settings, message, false)
 803            {
 804                _httpResponse = httpContext.Response;
 805                _httpContext = httpContext;
 806                _httpMethod = httpMethod;
 807
 808                if (message.IsFault)
 809                {
 810                    SetStatusCode(HttpStatusCode.InternalServerError);
 811                }
 812                else
 813                {
 814                    SetStatusCode(HttpStatusCode.OK);
 815                }
 816            }
 817
 818            protected override string HttpMethod => _httpMethod;
 819
 820            public override void Abort(HttpAbortReason abortReason)
 821            {
 822                _httpContext.Abort();
 823                base.Abort(abortReason);
 824            }
 825
 826            protected override void AddMimeVersion(string version)
 827            {
 828                _httpResponse.Headers[HttpChannelUtilities.MIMEVersionHeader] = version;
 829            }
 830
 831            protected override bool PrepareHttpSend(Message message)
 832            {
 833                bool result = base.PrepareHttpSend(message);
 834
 835                if (CanSendCompressedResponses)
 836                {
 837                    string contentType = _httpResponse.ContentType;
 838                    if (HttpChannelUtilities.GetHttpResponseTypeAndEncodingForCompression(ref contentType, out string co
 839                    {
 840                        if (contentType != _httpResponse.ContentType)
 841                        {
 842                            SetContentType(contentType);
 843                        }
 844                        SetContentEncoding(contentEncoding);
 845                    }
 846                }
 847
 848                message.Properties.TryGetValue(HttpResponseMessageProperty.Name, out object responsePropertyObj);
 849                HttpResponseMessageProperty responseProperty = (HttpResponseMessageProperty)responsePropertyObj;
 850                bool httpResponseMessagePropertyFound = responseProperty != null;
 851                bool httpMethodIsHead = string.Compare(_httpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) == 0;
 852
 853                if (httpMethodIsHead ||
 854                    httpResponseMessagePropertyFound && responseProperty.SuppressEntityBody)
 855                {
 856                    result = true;
 857                    SetContentLength(0);
 858                    SetContentType(null);
 859                }
 860
 861                if (httpResponseMessagePropertyFound)
 862                {
 863                    SetStatusCode(responseProperty.StatusCode);
 864                    if (responseProperty.StatusDescription != null)
 865                    {
 866                        SetStatusDescription(responseProperty.StatusDescription);
 867                    }
 868
 869                    WebHeaderCollection responseHeaders = responseProperty.Headers;
 870                    for (int i = 0; i < responseHeaders.Count; i++)
 871                    {
 872                        string name = responseHeaders.Keys[i];
 873                        string value = responseHeaders[i];
 874                        if (string.Compare(name, "content-length", StringComparison.OrdinalIgnoreCase) == 0)
 875                        {
 876                            if (httpMethodIsHead &&
 877                                int.TryParse(value, out int contentLength))
 878                            {
 879                                SetContentLength(contentLength);
 880                            }
 881                        }
 882                        else if (string.Compare(name, "content-type", StringComparison.OrdinalIgnoreCase) == 0)
 883                        {
 884                            if (httpMethodIsHead ||
 885                                !responseProperty.SuppressEntityBody)
 886                            {
 887                                SetContentType(value);
 888                            }
 889                        }
 890                        else if (string.Compare(name, "connection", StringComparison.OrdinalIgnoreCase) == 0)
 891                        {
 892                            SetConnection(value);
 893                        }
 894                        else
 895                        {
 896                            AddHeader(name, value);
 897                        }
 898                    }
 899                }
 900
 901                if (_httpResponse.ContentType != null && _httpResponse.ContentType.StartsWith(@"multipart/related; type=
 902                {
 903                    // For MTOM messages, add a MIME version header
 904                    AddMimeVersion("1.0");
 905                    message.Properties.Add("CoreWCF.Channel.MtomMessageEncoder.WriteMessageHeaders", false);
 906                }
 907
 908                return result;
 909            }
 910
 911            protected override void AddHeader(string name, string value)
 912            {
 913                if (string.Compare(name, "WWW-Authenticate", StringComparison.OrdinalIgnoreCase) == 0)
 914                {
 915                    _httpResponse.Headers[name] = value;
 916                }
 917                else
 918                {
 919                    if (_httpResponse.Headers.ContainsKey(name))
 920                    {
 921                        StringValues previousValues = _httpResponse.Headers[name];
 922                        _httpResponse.Headers[name] = StringValues.Concat(previousValues, value);
 923                    }
 924                    else
 925                    {
 926                        _httpResponse.Headers[name] = value;
 927                    }
 928                }
 929            }
 930
 931            private void SetConnection(string connectionValue)
 932            {
 933                if ((connectionValue.Equals("keep-alive", StringComparison.OrdinalIgnoreCase) ||
 934                    connectionValue.Equals("close", StringComparison.OrdinalIgnoreCase)) &&
 935                    _httpResponse.Headers.ContainsKey("Connection"))
 936                {
 937                    // Need to remove existing keep-alive and/or close values
 938                    StringValues connectionHeaderValue;
 939                    StringValues previousValues = _httpResponse.Headers["Connection"];
 940                    for (int i = 0; i < previousValues.Count; i++)
 941                    {
 942                        if (previousValues[i].Equals("keep-alive", StringComparison.OrdinalIgnoreCase) ||
 943                            previousValues[i].Equals("close", StringComparison.OrdinalIgnoreCase))
 944                        {
 945                            continue; // Don't add to new connectionHeaderValue as it will conflict with new value
 946                        }
 947
 948                        connectionHeaderValue = StringValues.Concat(connectionHeaderValue, previousValues[i]);
 949                    }
 950
 951                    connectionHeaderValue = StringValues.Concat(connectionHeaderValue, connectionValue);
 952                    _httpResponse.Headers["Connection"] = connectionHeaderValue;
 953                }
 954                else
 955                {
 956                    AddHeader("Connection", connectionValue);
 957                }
 958            }
 959
 960            protected override void SetContentType(string contentType)
 961            {
 962                _httpResponse.ContentType = contentType;
 963            }
 964
 965            protected override void SetContentEncoding(string contentEncoding)
 966            {
 967                _httpResponse.Headers[HttpChannelUtilities.ContentEncodingHeader] = contentEncoding;
 968            }
 969
 970            protected override void SetContentLength(int contentLength)
 971            {
 972                _httpResponse.ContentLength = contentLength;
 973            }
 974
 975            protected override void SetStatusCode(HttpStatusCode statusCode)
 976            {
 977                _httpResponse.StatusCode = (int)statusCode;
 978            }
 979
 980            protected override void SetStatusDescription(string statusDescription)
 981            {
 982                _httpResponse.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = statusDescription;
 983            }
 984
 985            protected override Stream GetOutputStream()
 986            {
 987                return _httpResponse.Body;
 988            }
 989        }
 990    }
 991
 992    internal enum HttpAbortReason
 993    {
 994        None,
 995        Aborted,
 996        TimedOut
 997    }
 998
 999    internal static class HttpChannelUtilities
 1000    {
 1001        internal static class StatusDescriptionStrings
 1002        {
 1003            internal const string HttpContentTypeMissing = "Missing Content Type";
 1004            internal const string HttpContentTypeMismatch = "Cannot process the message because the content type '{0}' w
 1005        }
 1006
 1007        internal const string HttpStatusCodeKey = "HttpStatusCode";
 1008        internal const string HttpStatusCodeExceptionKey = "CoreWCF.Channels.HttpInput.HttpStatusCode";
 1009        internal const string HttpStatusDescriptionExceptionKey = "CoreWCF.Channels.HttpInput.HttpStatusDescription";
 1010
 1011        internal const string MIMEVersionHeader = "MIME-Version";
 1012
 1013        internal const string ContentEncodingHeader = "Content-Encoding";
 1014        internal const string AcceptEncodingHeader = "Accept-Encoding";
 1015
 1016        public static Exception CreateCommunicationException(Exception exception)
 1017        {
 1018            return new CommunicationException(exception.Message, exception);
 1019        }
 1020
 1021        //    public static void EnsureHttpRequestMessageContentNotNull(HttpRequestMessage httpRequestMessage)
 1022        //    {
 1023        //        if (httpRequestMessage.Content == null)
 1024        //        {
 1025        //            httpRequestMessage.Content = new ByteArrayContent(EmptyArray<byte>.Instance);
 1026        //        }
 1027        //    }
 1028
 1029        //    public static void EnsureHttpResponseMessageContentNotNull(HttpResponseMessage httpResponseMessage)
 1030        //    {
 1031        //        if (httpResponseMessage.Content == null)
 1032        //        {
 1033        //            httpResponseMessage.Content = new ByteArrayContent(EmptyArray<byte>.Instance);
 1034        //        }
 1035        //    }
 1036
 1037        //    public static bool IsEmpty(HttpResponseMessage httpResponseMessage)
 1038        //    {
 1039        //        return httpResponseMessage.Content == null
 1040        //           || (httpResponseMessage.Content.Headers.ContentLength.HasValue && httpResponseMessage.Content.Heade
 1041        //    }
 1042
 1043        //    internal static void HandleContinueWithTask(Task task)
 1044        //    {
 1045        //        HandleContinueWithTask(task, null);
 1046        //    }
 1047
 1048        //    internal static void HandleContinueWithTask(Task task, Action<Exception> exceptionHandler)
 1049        //    {
 1050        //        if (task.IsFaulted)
 1051        //        {
 1052        //            if (exceptionHandler == null)
 1053        //            {
 1054        //                throw FxTrace.Exception.AsError<FaultException>(task.Exception);
 1055        //            }
 1056        //            else
 1057        //            {
 1058        //                exceptionHandler.Invoke(task.Exception);
 1059        //            }
 1060        //        }
 1061        //        else if (task.IsCanceled)
 1062        //        {
 1063        //            throw FxTrace.Exception.AsError(new TimeoutException(SR.GetString(SR.TaskCancelledError)));
 1064        //        }
 1065        //    }
 1066
 1067        //    public static void AbortRequest(HttpWebRequest request)
 1068        //    {
 1069        //        request.Abort();
 1070        //    }
 1071
 1072        //    public static void SetRequestTimeout(HttpWebRequest request, TimeSpan timeout)
 1073        //    {
 1074        //        int millisecondsTimeout = TimeoutHelper.ToMilliseconds(timeout);
 1075        //        if (millisecondsTimeout == 0)
 1076        //        {
 1077        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(SR.GetString(
 1078        //                SR.HttpRequestTimedOut, request.RequestUri, timeout)));
 1079        //        }
 1080        //        request.Timeout = millisecondsTimeout;
 1081        //        request.ReadWriteTimeout = millisecondsTimeout;
 1082        //    }
 1083
 1084        //    public static void AddReplySecurityProperty(HttpChannelFactory<IRequestChannel> factory, HttpWebRequest we
 1085        //        HttpWebResponse webResponse, Message replyMessage)
 1086        //    {
 1087        //        SecurityMessageProperty securityProperty = factory.CreateReplySecurityProperty(webRequest, webResponse
 1088        //        if (securityProperty != null)
 1089        //        {
 1090        //            replyMessage.Properties.Security = securityProperty;
 1091        //        }
 1092        //    }
 1093
 1094        //    public static void CopyHeaders(HttpRequestMessage request, AddHeaderDelegate addHeader)
 1095        //    {
 1096        //        HttpChannelUtilities.CopyHeaders(request.Headers, addHeader);
 1097        //        if (request.Content != null)
 1098        //        {
 1099        //            HttpChannelUtilities.CopyHeaders(request.Content.Headers, addHeader);
 1100        //        }
 1101        //    }
 1102
 1103        //    public static void CopyHeaders(HttpResponseMessage response, AddHeaderDelegate addHeader)
 1104        //    {
 1105        //        HttpChannelUtilities.CopyHeaders(response.Headers, addHeader);
 1106        //        if (response.Content != null)
 1107        //        {
 1108        //            HttpChannelUtilities.CopyHeaders(response.Content.Headers, addHeader);
 1109        //        }
 1110        //    }
 1111
 1112        //    static void CopyHeaders(HttpHeaders headers, AddHeaderDelegate addHeader)
 1113        //    {
 1114        //        foreach (KeyValuePair<string, IEnumerable<string>> header in headers)
 1115        //        {
 1116        //            foreach (string value in header.Value)
 1117        //            {
 1118        //                TryAddToCollection(addHeader, header.Key, value);
 1119        //            }
 1120        //        }
 1121        //    }
 1122
 1123        //    public static void CopyHeaders(NameValueCollection headers, AddHeaderDelegate addHeader)
 1124        //    {
 1125        //        //this nested loop logic was copied from NameValueCollection.Add(NameValueCollection)
 1126        //        int count = headers.Count;
 1127        //        for (int i = 0; i < count; i++)
 1128        //        {
 1129        //            string key = headers.GetKey(i);
 1130
 1131        //            string[] values = headers.GetValues(i);
 1132        //            if (values != null)
 1133        //            {
 1134        //                for (int j = 0; j < values.Length; j++)
 1135        //                {
 1136        //                    TryAddToCollection(addHeader, key, values[j]);
 1137        //                }
 1138        //            }
 1139        //            else
 1140        //            {
 1141        //                addHeader(key, null);
 1142        //            }
 1143        //        }
 1144        //    }
 1145
 1146        //    public static void CopyHeadersToNameValueCollection(NameValueCollection headers, NameValueCollection desti
 1147        //    {
 1148        //        CopyHeaders(headers, destination.Add);
 1149        //    }
 1150
 1151        //    [System.Diagnostics.CodeAnalysis.SuppressMessage(FxCop.Category.ReliabilityBasic, "Reliability104",
 1152        //                        Justification = "The exceptions are traced already.")]
 1153        //    static void TryAddToCollection(AddHeaderDelegate addHeader, string headerName, string value)
 1154        //    {
 1155        //        try
 1156        //        {
 1157        //            addHeader(headerName, value);
 1158        //        }
 1159        //        catch (ArgumentException ex)
 1160        //        {
 1161        //            string encodedValue = null;
 1162        //            if (TryEncodeHeaderValueAsUri(headerName, value, out encodedValue))
 1163        //            {
 1164        //                //note: if the hosthame of a referer header contains illegal chars, we will still throw from h
 1165        //                //because Uri will not fix this up for us, which is ok. The request will get rejected in the e
 1166        //                addHeader(headerName, encodedValue);
 1167        //            }
 1168        //            else
 1169        //            {
 1170        //                // In self-hosted scenarios, some of the headers like Content-Length cannot be added directly.
 1171        //                // It will throw ArgumentException instead.
 1172        //                FxTrace.Exception.AsInformation(ex);
 1173        //            }
 1174        //        }
 1175        //    }
 1176
 1177        //    static bool TryEncodeHeaderValueAsUri(string headerName, string value, out string result)
 1178        //    {
 1179        //        result = null;
 1180        //        //Internet Explorer will send the referrer header on the wire in unicode without encoding it
 1181        //        //this will cause errors when added to a WebHeaderCollection.  This is a workaround for sharepoint,
 1182        //        //but will only work for WebHosted Scenarios.
 1183        //        if (String.Compare(headerName, "Referer", StringComparison.OrdinalIgnoreCase) == 0)
 1184        //        {
 1185        //            Uri uri;
 1186        //            if (Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out uri))
 1187        //            {
 1188        //                if (uri.IsAbsoluteUri)
 1189        //                {
 1190        //                    result = uri.AbsoluteUri;
 1191        //                }
 1192        //                else
 1193        //                {
 1194        //                    result = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
 1195        //                }
 1196        //                return true;
 1197        //            }
 1198        //        }
 1199        //        return false;
 1200        //    }
 1201
 1202        //    //TODO, weixi, CSDMain 231775: Refactor the code for GetType logic in System.ServiceModel.dll and System.S
 1203        //    internal static Type GetTypeFromAssembliesInCurrentDomain(string typeString)
 1204        //    {
 1205        //        Type type = Type.GetType(typeString, false);
 1206        //        if (null == type)
 1207        //        {
 1208        //            if (!allReferencedAssembliesLoaded)
 1209        //            {
 1210        //                allReferencedAssembliesLoaded = true;
 1211        //                AspNetEnvironment.Current.EnsureAllReferencedAssemblyLoaded();
 1212        //            }
 1213
 1214        //            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
 1215        //            for (int i = 0; i < assemblies.Length; i++)
 1216        //            {
 1217        //                type = assemblies[i].GetType(typeString, false);
 1218        //                if (null != type)
 1219        //                {
 1220        //                    break;
 1221        //                }
 1222        //            }
 1223        //        }
 1224
 1225        //        return type;
 1226        //    }
 1227
 1228        //    public static NetworkCredential GetCredential(AuthenticationSchemes authenticationScheme,
 1229        //        SecurityTokenProviderContainer credentialProvider, TimeSpan timeout,
 1230        //        out TokenImpersonationLevel impersonationLevel, out AuthenticationLevel authenticationLevel)
 1231        //    {
 1232        //        impersonationLevel = TokenImpersonationLevel.None;
 1233        //        authenticationLevel = AuthenticationLevel.None;
 1234
 1235        //        NetworkCredential result = null;
 1236
 1237        //        if (authenticationScheme != AuthenticationSchemes.Anonymous)
 1238        //        {
 1239        //            result = GetCredentialCore(authenticationScheme, credentialProvider, timeout, out impersonationLev
 1240        //        }
 1241
 1242        //        return result;
 1243        //    }
 1244
 1245        //    [MethodImpl(MethodImplOptions.NoInlining)]
 1246        //    static NetworkCredential GetCredentialCore(AuthenticationSchemes authenticationScheme,
 1247        //        SecurityTokenProviderContainer credentialProvider, TimeSpan timeout,
 1248        //        out TokenImpersonationLevel impersonationLevel, out AuthenticationLevel authenticationLevel)
 1249        //    {
 1250        //        impersonationLevel = TokenImpersonationLevel.None;
 1251        //        authenticationLevel = AuthenticationLevel.None;
 1252
 1253        //        NetworkCredential result = null;
 1254
 1255        //        switch (authenticationScheme)
 1256        //        {
 1257        //            case AuthenticationSchemes.Basic:
 1258        //                result = TransportSecurityHelpers.GetUserNameCredential(credentialProvider, timeout);
 1259        //                impersonationLevel = TokenImpersonationLevel.Delegation;
 1260        //                break;
 1261
 1262        //            case AuthenticationSchemes.Digest:
 1263        //                result = TransportSecurityHelpers.GetSspiCredential(credentialProvider, timeout,
 1264        //                    out impersonationLevel, out authenticationLevel);
 1265
 1266        //                HttpChannelUtilities.ValidateDigestCredential(ref result, impersonationLevel);
 1267        //                break;
 1268
 1269        //            case AuthenticationSchemes.Negotiate:
 1270        //                result = TransportSecurityHelpers.GetSspiCredential(credentialProvider, timeout,
 1271        //                    out impersonationLevel, out authenticationLevel);
 1272        //                break;
 1273
 1274        //            case AuthenticationSchemes.Ntlm:
 1275        //                result = TransportSecurityHelpers.GetSspiCredential(credentialProvider, timeout,
 1276        //                    out impersonationLevel, out authenticationLevel);
 1277        //                if (authenticationLevel == AuthenticationLevel.MutualAuthRequired)
 1278        //                {
 1279        //                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1280        //                        new InvalidOperationException(SR.GetString(SR.CredentialDisallowsNtlm)));
 1281        //                }
 1282        //                break;
 1283
 1284        //            default:
 1285        //                // The setter for this property should prevent this.
 1286        //                throw Fx.AssertAndThrow("GetCredential: Invalid authentication scheme");
 1287        //        }
 1288
 1289        //        return result;
 1290        //    }
 1291
 1292
 1293        //    public static HttpWebResponse ProcessGetResponseWebException(WebException webException, HttpWebRequest req
 1294        //    {
 1295        //        HttpWebResponse response = null;
 1296
 1297        //        if (webException.Status == WebExceptionStatus.Success ||
 1298        //            webException.Status == WebExceptionStatus.ProtocolError)
 1299        //        {
 1300        //            response = (HttpWebResponse)webException.Response;
 1301        //        }
 1302
 1303        //        if (response == null)
 1304        //        {
 1305        //            Exception convertedException = ConvertWebException(webException, request, abortReason);
 1306
 1307        //            if (convertedException != null)
 1308        //            {
 1309        //                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(convertedException);
 1310        //            }
 1311
 1312        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(webException.
 1313        //                webException));
 1314        //        }
 1315
 1316        //        if (response.StatusCode == HttpStatusCode.NotFound)
 1317        //        {
 1318        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new EndpointNotFoundException(SR.GetStri
 1319        //        }
 1320
 1321        //        if (response.StatusCode == HttpStatusCode.ServiceUnavailable)
 1322        //        {
 1323        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ServerTooBusyException(SR.GetString(
 1324        //        }
 1325
 1326        //        if (response.StatusCode == HttpStatusCode.UnsupportedMediaType)
 1327        //        {
 1328        //            string statusDescription = response.StatusDescription;
 1329        //            if (!string.IsNullOrEmpty(statusDescription))
 1330        //            {
 1331        //                if (string.Compare(statusDescription, HttpChannelUtilities.StatusDescriptionStrings.HttpConten
 1332        //                {
 1333        //                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetStri
 1334        //                }
 1335        //            }
 1336        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.Fr
 1337        //        }
 1338
 1339        //        if (response.StatusCode == HttpStatusCode.GatewayTimeout)
 1340        //        {
 1341        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(webException.Messag
 1342        //        }
 1343
 1344        //        // if http.sys has a request queue on the TCP port, then if the path fails to match it will send
 1345        //        // back "<h1>Bad Request (Invalid Hostname)</h1>" in the body of a 400 response.
 1346        //        // See code at \\index1\sddnsrv\net\http\sys\httprcv.c for details
 1347        //        if (response.StatusCode == HttpStatusCode.BadRequest)
 1348        //        {
 1349        //            const string httpSysRequestQueueNotFound = "<h1>Bad Request (Invalid Hostname)</h1>";
 1350        //            const string httpSysRequestQueueNotFoundVista = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN
 1351        //            string notFoundTestString = null;
 1352
 1353        //            if (response.ContentLength == httpSysRequestQueueNotFound.Length)
 1354        //            {
 1355        //                notFoundTestString = httpSysRequestQueueNotFound;
 1356        //            }
 1357        //            else if (response.ContentLength == httpSysRequestQueueNotFoundVista.Length)
 1358        //            {
 1359        //                notFoundTestString = httpSysRequestQueueNotFoundVista;
 1360        //            }
 1361
 1362        //            if (notFoundTestString != null)
 1363        //            {
 1364        //                Stream responseStream = response.GetResponseStream();
 1365        //                byte[] responseBytes = new byte[notFoundTestString.Length];
 1366        //                int bytesRead = responseStream.Read(responseBytes, 0, responseBytes.Length);
 1367
 1368        //                // since the response is buffered by System.Net (it's an error response), we should have read
 1369        //                // the amount we were expecting
 1370        //                if (bytesRead == notFoundTestString.Length
 1371        //                    && notFoundTestString == UTF8Encoding.ASCII.GetString(responseBytes))
 1372        //                {
 1373        //                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new EndpointNotFoundException(SR
 1374        //                }
 1375        //            }
 1376        //        }
 1377
 1378        //        return response;
 1379        //    }
 1380
 1381        //    public static Exception ConvertWebException(WebException webException, HttpWebRequest request, HttpAbortRe
 1382        //    {
 1383        //        switch (webException.Status)
 1384        //        {
 1385        //            case WebExceptionStatus.ConnectFailure:
 1386        //            case WebExceptionStatus.NameResolutionFailure:
 1387        //            case WebExceptionStatus.ProxyNameResolutionFailure:
 1388        //                return new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, request.RequestUri.Abso
 1389        //            case WebExceptionStatus.SecureChannelFailure:
 1390        //                return new SecurityNegotiationException(SR.GetString(SR.SecureChannelFailure, request.RequestU
 1391        //            case WebExceptionStatus.TrustFailure:
 1392        //                return new SecurityNegotiationException(SR.GetString(SR.TrustFailure, request.RequestUri.Autho
 1393        //            case WebExceptionStatus.Timeout:
 1394        //                return new TimeoutException(CreateRequestTimedOutMessage(request), webException);
 1395        //            case WebExceptionStatus.ReceiveFailure:
 1396        //                return new CommunicationException(SR.GetString(SR.HttpReceiveFailure, request.RequestUri), web
 1397        //            case WebExceptionStatus.SendFailure:
 1398        //                return new CommunicationException(SR.GetString(SR.HttpSendFailure, request.RequestUri), webExc
 1399        //            case WebExceptionStatus.RequestCanceled:
 1400        //                return CreateRequestCanceledException(webException, request, abortReason);
 1401        //            case WebExceptionStatus.ProtocolError:
 1402        //                HttpWebResponse response = (HttpWebResponse)webException.Response;
 1403        //                Fx.Assert(response != null, "'response' MUST NOT be NULL for WebExceptionStatus=='ProtocolErro
 1404        //                if (response.StatusCode == HttpStatusCode.InternalServerError &&
 1405        //                    string.Compare(response.StatusDescription, HttpChannelUtilities.StatusDescriptionStrings.H
 1406        //                {
 1407        //                    return new ServiceActivationException(SR.GetString(SR.Hosting_ServiceActivationFailed, req
 1408        //                }
 1409        //                else
 1410        //                {
 1411        //                    return null;
 1412        //                }
 1413        //            default:
 1414        //                return null;
 1415        //        }
 1416        //    }
 1417
 1418        //    public static Exception CreateResponseIOException(IOException ioException, TimeSpan receiveTimeout)
 1419        //    {
 1420        //        if (ioException.InnerException is SocketException)
 1421        //        {
 1422        //            return SocketConnection.ConvertTransferException((SocketException)ioException.InnerException, rece
 1423        //        }
 1424
 1425        //        return new CommunicationException(SR.GetString(SR.HttpTransferError, ioException.Message), ioException
 1426        //    }
 1427
 1428        //    public static Exception CreateResponseWebException(WebException webException, HttpWebResponse response)
 1429        //    {
 1430        //        switch (webException.Status)
 1431        //        {
 1432        //            case WebExceptionStatus.RequestCanceled:
 1433        //                return TraceResponseException(new CommunicationObjectAbortedException(SR.GetString(SR.HttpRequ
 1434        //            case WebExceptionStatus.ConnectionClosed:
 1435        //                return TraceResponseException(new CommunicationException(webException.Message, webException));
 1436        //            case WebExceptionStatus.Timeout:
 1437        //                return TraceResponseException(new TimeoutException(SR.GetString(SR.HttpResponseTimedOut, respo
 1438        //                    TimeSpan.FromMilliseconds(response.GetResponseStream().ReadTimeout)), webException));
 1439        //            default:
 1440        //                return CreateUnexpectedResponseException(webException, response);
 1441        //        }
 1442        //    }
 1443
 1444        //    public static Exception CreateRequestCanceledException(Exception webException, HttpWebRequest request, Htt
 1445        //    {
 1446        //        switch (abortReason)
 1447        //        {
 1448        //            case HttpAbortReason.Aborted:
 1449        //                return new CommunicationObjectAbortedException(SR.GetString(SR.HttpRequestAborted, request.Req
 1450        //            case HttpAbortReason.TimedOut:
 1451        //                return new TimeoutException(CreateRequestTimedOutMessage(request), webException);
 1452        //            default:
 1453        //                return new CommunicationException(SR.GetString(SR.HttpTransferError, webException.Message), we
 1454        //        }
 1455        //    }
 1456
 1457        //    public static Exception CreateRequestIOException(IOException ioException, HttpWebRequest request)
 1458        //    {
 1459        //        return CreateRequestIOException(ioException, request, null);
 1460        //    }
 1461
 1462        //    public static Exception CreateRequestIOException(IOException ioException, HttpWebRequest request, Exceptio
 1463        //    {
 1464        //        Exception exception = originalException == null ? ioException : originalException;
 1465
 1466        //        if (ioException.InnerException is SocketException)
 1467        //        {
 1468        //            return SocketConnection.ConvertTransferException((SocketException)ioException.InnerException, Time
 1469        //        }
 1470
 1471        //        return new CommunicationException(SR.GetString(SR.HttpTransferError, exception.Message), exception);
 1472        //    }
 1473
 1474        //    static string CreateRequestTimedOutMessage(HttpWebRequest request)
 1475        //    {
 1476        //        return SR.GetString(SR.HttpRequestTimedOut, request.RequestUri, TimeSpan.FromMilliseconds(request.Time
 1477        //    }
 1478
 1479        //    public static Exception CreateRequestWebException(WebException webException, HttpWebRequest request, HttpA
 1480        //    {
 1481        //        Exception convertedException = ConvertWebException(webException, request, abortReason);
 1482
 1483        //        if (webException.Response != null)
 1484        //        {
 1485        //            //free the connection for use by another request
 1486        //            webException.Response.Close();
 1487        //        }
 1488
 1489        //        if (convertedException != null)
 1490        //        {
 1491        //            return convertedException;
 1492        //        }
 1493
 1494        //        if (webException.InnerException is IOException)
 1495        //        {
 1496        //            return CreateRequestIOException((IOException)webException.InnerException, request, webException);
 1497        //        }
 1498
 1499        //        if (webException.InnerException is SocketException)
 1500        //        {
 1501        //            return SocketConnectionInitiator.ConvertConnectException((SocketException)webException.InnerExcept
 1502        //        }
 1503
 1504        //        return new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, request.RequestUri.AbsoluteUri)
 1505        //    }
 1506
 1507        //    static Exception CreateUnexpectedResponseException(WebException responseException, HttpWebResponse respons
 1508        //    {
 1509        //        string statusDescription = response.StatusDescription;
 1510        //        if (string.IsNullOrEmpty(statusDescription))
 1511        //            statusDescription = response.StatusCode.ToString();
 1512
 1513        //        return TraceResponseException(
 1514        //            new ProtocolException(SR.GetString(SR.UnexpectedHttpResponseCode,
 1515        //            (int)response.StatusCode, statusDescription), responseException));
 1516        //    }
 1517
 1518        //    public static Exception CreateNullReferenceResponseException(NullReferenceException nullReferenceException
 1519        //    {
 1520        //        return TraceResponseException(
 1521        //            new ProtocolException(SR.GetString(SR.NullReferenceOnHttpResponse), nullReferenceException));
 1522        //    }
 1523
 1524        //    static string GetResponseStreamString(HttpWebResponse webResponse, out int bytesRead)
 1525        //    {
 1526        //        Stream responseStream = webResponse.GetResponseStream();
 1527
 1528        //        long bufferSize = webResponse.ContentLength;
 1529
 1530        //        if (bufferSize < 0 || bufferSize > ResponseStreamExcerptSize)
 1531        //        {
 1532        //            bufferSize = ResponseStreamExcerptSize;
 1533        //        }
 1534
 1535        //        byte[] responseBuffer = DiagnosticUtility.Utility.AllocateByteArray(checked((int)bufferSize));
 1536        //        bytesRead = responseStream.Read(responseBuffer, 0, (int)bufferSize);
 1537        //        responseStream.Close();
 1538
 1539        //        return System.Text.Encoding.UTF8.GetString(responseBuffer, 0, bytesRead);
 1540        //    }
 1541
 1542        //    static Exception TraceResponseException(Exception exception)
 1543        //    {
 1544        //        if (DiagnosticUtility.ShouldTraceError)
 1545        //        {
 1546        //            TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.HttpChannelUnexpectedResponse, SR.GetStrin
 1547        //        }
 1548
 1549        //        return exception;
 1550        //    }
 1551
 1552        //    static bool ValidateEmptyContent(HttpWebResponse response)
 1553        //    {
 1554        //        bool responseIsEmpty = true;
 1555
 1556        //        if (response.ContentLength > 0)
 1557        //        {
 1558        //            responseIsEmpty = false;
 1559        //        }
 1560        //        else if (response.ContentLength == -1) // chunked
 1561        //        {
 1562        //            Stream responseStream = response.GetResponseStream();
 1563        //            byte[] testBuffer = new byte[1];
 1564        //            responseIsEmpty = (responseStream.Read(testBuffer, 0, 1) != 1);
 1565        //        }
 1566
 1567        //        return responseIsEmpty;
 1568        //    }
 1569
 1570        //    static void ValidateAuthentication(HttpWebRequest request, HttpWebResponse response,
 1571        //        WebException responseException, HttpChannelFactory<IRequestChannel> factory)
 1572        //    {
 1573        //        if (response.StatusCode == HttpStatusCode.Unauthorized)
 1574        //        {
 1575        //            string message = SR.GetString(SR.HttpAuthorizationFailed, factory.AuthenticationScheme,
 1576        //                response.Headers[HttpResponseHeader.WwwAuthenticate]);
 1577        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1578        //                TraceResponseException(new MessageSecurityException(message, responseException)));
 1579        //        }
 1580
 1581        //        if (response.StatusCode == HttpStatusCode.Forbidden)
 1582        //        {
 1583        //            string message = SR.GetString(SR.HttpAuthorizationForbidden, factory.AuthenticationScheme);
 1584        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1585        //                TraceResponseException(new MessageSecurityException(message, responseException)));
 1586        //        }
 1587
 1588        //        if ((request.AuthenticationLevel == AuthenticationLevel.MutualAuthRequired) &&
 1589        //            !response.IsMutuallyAuthenticated)
 1590        //        {
 1591        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1592        //                TraceResponseException(new SecurityNegotiationException(SR.GetString(SR.HttpMutualAuthNotSatis
 1593        //                responseException)));
 1594        //        }
 1595        //    }
 1596
 1597        //    public static void ValidateDigestCredential(ref NetworkCredential credential, TokenImpersonationLevel impe
 1598        //    {
 1599        //        // this is a work-around to VSWhidbey#470545 (Since the service always uses Impersonation,
 1600        //        // we mitigate EOP by preemptively not allowing Identification)
 1601        //        if (!SecurityUtils.IsDefaultNetworkCredential(credential))
 1602        //        {
 1603        //            // With a non-default credential, Digest will not honor a client impersonation constraint of
 1604        //            // TokenImpersonationLevel.Identification.
 1605        //            if (!TokenImpersonationLevelHelper.IsGreaterOrEqual(impersonationLevel,
 1606        //                TokenImpersonationLevel.Impersonation))
 1607        //            {
 1608        //                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Get
 1609        //                    SR.DigestExplicitCredsImpersonationLevel, impersonationLevel)));
 1610        //            }
 1611        //        }
 1612        //    }
 1613
 1614        //    // only valid response codes are 500 (if it's a fault) or 200 (iff it's a response message)
 1615        //    public static HttpInput ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response,
 1616        //        HttpChannelFactory<IRequestChannel> factory, WebException responseException, ChannelBinding channelBin
 1617        //    {
 1618        //        ValidateAuthentication(request, response, responseException, factory);
 1619
 1620        //        HttpInput httpInput = null;
 1621
 1622        //        // We will close the HttpWebResponse if we got an error code betwen 200 and 300 and
 1623        //        // 1) an exception was thrown out or
 1624        //        // 2) it's an empty message and we are using SOAP.
 1625        //        // For responses with status code above 300, System.Net will close the underlying connection so we don
 1626        //        if ((200 <= (int)response.StatusCode && (int)response.StatusCode < 300) || response.StatusCode == Http
 1627        //        {
 1628        //            if (response.StatusCode == HttpStatusCode.InternalServerError
 1629        //                && string.Compare(response.StatusDescription, HttpChannelUtilities.StatusDescriptionStrings.Ht
 1630        //            {
 1631        //                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ServiceActivationException(SR.Ge
 1632        //            }
 1633        //            else
 1634        //            {
 1635        //                bool throwing = true;
 1636        //                try
 1637        //                {
 1638        //                    if (string.IsNullOrEmpty(response.ContentType))
 1639        //                    {
 1640        //                        if (!ValidateEmptyContent(response))
 1641        //                        {
 1642        //                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TraceResponseException(
 1643        //                                new ProtocolException(
 1644        //                                    SR.GetString(SR.HttpContentTypeHeaderRequired),
 1645        //                                    responseException)));
 1646        //                        }
 1647        //                    }
 1648        //                    else if (response.ContentLength != 0)
 1649        //                    {
 1650        //                        MessageEncoder encoder = factory.MessageEncoderFactory.Encoder;
 1651        //                        if (!encoder.IsContentTypeSupported(response.ContentType))
 1652        //                        {
 1653        //                            int bytesRead;
 1654        //                            String responseExcerpt = GetResponseStreamString(response, out bytesRead);
 1655
 1656        //                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TraceResponseException(
 1657        //                                new ProtocolException(
 1658        //                                    SR.GetString(
 1659        //                                        SR.ResponseContentTypeMismatch,
 1660        //                                        response.ContentType,
 1661        //                                        encoder.ContentType,
 1662        //                                        bytesRead,
 1663        //                                        responseExcerpt), responseException)));
 1664
 1665        //                        }
 1666
 1667        //                        httpInput = HttpInput.CreateHttpInput(response, factory, channelBinding);
 1668        //                        httpInput.WebException = responseException;
 1669        //                    }
 1670
 1671        //                    throwing = false;
 1672        //                }
 1673        //                finally
 1674        //                {
 1675        //                    if (throwing)
 1676        //                    {
 1677        //                        response.Close();
 1678        //                    }
 1679        //                }
 1680        //            }
 1681
 1682        //            if (httpInput == null)
 1683        //            {
 1684        //                if (factory.MessageEncoderFactory.MessageVersion == MessageVersion.None)
 1685        //                {
 1686        //                    httpInput = HttpInput.CreateHttpInput(response, factory, channelBinding);
 1687        //                    httpInput.WebException = responseException;
 1688        //                }
 1689        //                else
 1690        //                {
 1691        //                    // In this case, we got a response with
 1692        //                    // 1) status code between 200 and 300
 1693        //                    // 2) Non-empty Content Type string
 1694        //                    // 3) Zero content length
 1695        //                    // Since we are trying to use SOAP here, the message seems to be malicious and we should
 1696        //                    // just close the response directly.
 1697        //                    response.Close();
 1698        //                }
 1699        //            }
 1700        //        }
 1701        //        else
 1702        //        {
 1703        //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedResponseException(respon
 1704        //        }
 1705
 1706        //        return httpInput;
 1707        //    }
 1708
 1709        public static bool GetHttpResponseTypeAndEncodingForCompression(ref string contentType, out string contentEncodi
 1710        {
 1711            contentEncoding = null;
 1712            bool isSession = false;
 1713            bool isDeflate = false;
 1714
 1715            if (string.Equals(BinaryVersion.GZipVersion1.ContentType, contentType, StringComparison.OrdinalIgnoreCase) |
 1716                (isSession = string.Equals(BinaryVersion.GZipVersion1.SessionContentType, contentType, StringComparison.
 1717                (isDeflate = (string.Equals(BinaryVersion.DeflateVersion1.ContentType, contentType, StringComparison.Ord
 1718                (isSession = string.Equals(BinaryVersion.DeflateVersion1.SessionContentType, contentType, StringComparis
 1719            {
 1720                contentType = isSession ? BinaryVersion.Version1.SessionContentType : BinaryVersion.Version1.ContentType
 1721                contentEncoding = isDeflate ? MessageEncoderCompressionHandler.DeflateContentEncoding : MessageEncoderCo
 1722                return true;
 1723            }
 1724            return false;
 1725        }
 1726    }
 1727
 1728    //abstract class HttpDelayedAcceptStream : DetectEofStream
 1729    //{
 1730    //    HttpOutput httpOutput;
 1731    //    bool isHttpOutputClosed;
 1732
 1733    //    /// <summary>
 1734    //    /// Indicates whether the HttpOutput should be closed when this stream is closed. In the streamed case,
 1735    //    /// we�ll leave the HttpOutput opened (and it will be closed by the HttpRequestContext, so we won't leak it).
 1736    //    /// </summary>
 1737    //    bool closeHttpOutput;
 1738
 1739    //    // sometimes we can't flush the HTTP output until we're done reading the end of the
 1740    //    // incoming stream of the HTTP input
 1741    //    protected HttpDelayedAcceptStream(Stream stream)
 1742    //        : base(stream)
 1743    //    {
 1744    //    }
 1745
 1746    //    public bool EnableDelayedAccept(HttpOutput output, bool closeHttpOutput)
 1747    //    {
 1748    //        if (IsAtEof)
 1749    //        {
 1750    //            return false;
 1751    //        }
 1752
 1753    //        this.closeHttpOutput = closeHttpOutput;
 1754    //        this.httpOutput = output;
 1755    //        return true;
 1756    //    }
 1757
 1758    //    protected override void OnReceivedEof()
 1759    //    {
 1760    //        if (this.closeHttpOutput)
 1761    //        {
 1762    //            CloseHttpOutput();
 1763    //        }
 1764    //    }
 1765
 1766    //    public override void Close()
 1767    //    {
 1768    //        if (this.closeHttpOutput)
 1769    //        {
 1770    //            CloseHttpOutput();
 1771    //        }
 1772
 1773    //        base.Close();
 1774    //    }
 1775
 1776    //    void CloseHttpOutput()
 1777    //    {
 1778    //        if (this.httpOutput != null && !this.isHttpOutputClosed)
 1779    //        {
 1780    //            this.httpOutput.Close();
 1781    //            this.isHttpOutputClosed = true;
 1782    //        }
 1783    //    }
 1784    //}
 1785
 1786    //abstract class BytesReadPositionStream : DelegatingStream
 1787    //{
 1788    //    int bytesSent = 0;
 1789
 1790    //    protected BytesReadPositionStream(Stream stream)
 1791    //        : base(stream)
 1792    //    {
 1793    //    }
 1794
 1795    //    public override long Position
 1796    //    {
 1797    //        get
 1798    //        {
 1799    //            return bytesSent;
 1800    //        }
 1801    //        set
 1802    //        {
 1803    //            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.Se
 1804    //        }
 1805    //    }
 1806
 1807    //    public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object s
 1808    //    {
 1809    //        this.bytesSent += count;
 1810    //        return BaseStream.BeginWrite(buffer, offset, count, callback, state);
 1811    //    }
 1812
 1813    //    public override void Write(byte[] buffer, int offset, int count)
 1814    //    {
 1815    //        BaseStream.Write(buffer, offset, count);
 1816    //        this.bytesSent += count;
 1817    //    }
 1818
 1819    //    public override void WriteByte(byte value)
 1820    //    {
 1821    //        BaseStream.WriteByte(value);
 1822    //        this.bytesSent++;
 1823    //    }
 1824    //}
 1825
 1826    internal class PreReadStream : DelegatingStream
 1827    {
 1828        private byte[] _preReadBuffer;
 1829
 1830        public PreReadStream(Stream stream, byte[] preReadBuffer)
 1831            : base(stream)
 1832        {
 1833            _preReadBuffer = preReadBuffer;
 1834        }
 1835
 1836        private bool ReadFromBuffer(byte[] buffer, int offset, int count, out int bytesRead)
 1837        {
 1838            if (_preReadBuffer != null)
 1839            {
 1840                if (buffer == null)
 1841                {
 1842                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(buffer));
 1843                }
 1844
 1845                if (offset >= buffer.Length)
 1846                {
 1847                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(off
 1848                        SR.Format(SR.OffsetExceedsBufferBound, buffer.Length - 1)));
 1849                }
 1850
 1851                if (count < 0)
 1852                {
 1853                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(cou
 1854                        SRCommon.ValueMustBeNonNegative));
 1855                }
 1856
 1857                if (count == 0)
 1858                {
 1859                    bytesRead = 0;
 1860                }
 1861                else
 1862                {
 1863                    buffer[offset] = _preReadBuffer[0];
 1864                    _preReadBuffer = null;
 1865                    bytesRead = 1;
 1866                }
 1867
 1868                return true;
 1869            }
 1870
 1871            bytesRead = -1;
 1872            return false;
 1873        }
 1874
 1875        public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 1876        {
 1877            if (ReadFromBuffer(buffer, offset, count, out int bytesRead))
 1878            {
 1879                return Task.FromResult(bytesRead);
 1880            }
 1881
 1882            return base.ReadAsync(buffer, offset, count, cancellationToken);
 1883        }
 1884
 1885        public override int Read(byte[] buffer, int offset, int count)
 1886        {
 1887            if (ReadFromBuffer(buffer, offset, count, out int bytesRead))
 1888            {
 1889                return bytesRead;
 1890            }
 1891
 1892            return base.Read(buffer, offset, count);
 1893        }
 1894
 1895        public override int ReadByte()
 1896        {
 1897            if (_preReadBuffer != null)
 1898            {
 1899                byte[] tempBuffer = new byte[1];
 1900                if (ReadFromBuffer(tempBuffer, 0, 1, out _))
 1901                {
 1902                    return tempBuffer[0];
 1903                }
 1904            }
 1905
 1906            return base.ReadByte();
 1907        }
 1908    }
 1909
 1910    //class HttpRequestMessageHttpInput : HttpInput, HttpRequestMessageProperty.IHttpHeaderProvider
 1911    //{
 1912    //    const string SoapAction = "SOAPAction";
 1913    //    HttpRequestMessage httpRequestMessage;
 1914    //    ChannelBinding channelBinding;
 1915
 1916    //    public HttpRequestMessageHttpInput(HttpRequestMessage httpRequestMessage, IHttpTransportFactorySettings settin
 1917    //        : base(settings, true, enableChannelBinding)
 1918    //    {
 1919    //        this.httpRequestMessage = httpRequestMessage;
 1920    //        this.channelBinding = channelBinding;
 1921    //    }
 1922
 1923    //    public override long ContentLength
 1924    //    {
 1925    //        get
 1926    //        {
 1927    //            if (this.httpRequestMessage.Content.Headers.ContentLength == null)
 1928    //            {
 1929    //                // Chunked transfer mode
 1930    //                return -1;
 1931    //            }
 1932
 1933    //            return this.httpRequestMessage.Content.Headers.ContentLength.Value;
 1934    //        }
 1935    //    }
 1936
 1937    //    protected override ChannelBinding ChannelBinding
 1938    //    {
 1939    //        get
 1940    //        {
 1941    //            return this.channelBinding;
 1942    //        }
 1943    //    }
 1944
 1945    //    public HttpRequestMessage HttpRequestMessage
 1946    //    {
 1947    //        get { return this.httpRequestMessage; }
 1948    //    }
 1949
 1950    //    protected override bool HasContent
 1951    //    {
 1952    //        get
 1953    //        {
 1954    //            // In Chunked transfer mode, the ContentLength header is null
 1955    //            // Otherwise we just rely on the ContentLength header
 1956    //            return this.httpRequestMessage.Content.Headers.ContentLength == null || this.httpRequestMessage.Conten
 1957    //        }
 1958    //    }
 1959
 1960    //    protected override string ContentTypeCore
 1961    //    {
 1962    //        get
 1963    //        {
 1964    //            if (!this.HasContent)
 1965    //            {
 1966    //                return null;
 1967    //            }
 1968
 1969    //            return this.httpRequestMessage.Content.Headers.ContentType == null ? null : this.httpRequestMessage.Co
 1970    //        }
 1971    //    }
 1972
 1973    //    public override void ConfigureHttpRequestMessage(HttpRequestMessage message)
 1974    //    {
 1975    //        throw FxTrace.Exception.AsError(new InvalidOperationException());
 1976    //    }
 1977
 1978    //    protected override Stream GetInputStream()
 1979    //    {
 1980    //        if (this.httpRequestMessage.Content == null)
 1981    //        {
 1982    //            return Stream.Null;
 1983    //        }
 1984
 1985    //        return this.httpRequestMessage.Content.ReadAsStreamAsync().Result;
 1986    //    }
 1987
 1988    //    protected override void AddProperties(Message message)
 1989    //    {
 1990    //        HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(this.httpRequestMessage);
 1991    //        message.Properties.Add(HttpRequestMessageProperty.Name, requestProperty);
 1992    //        message.Properties.Via = this.httpRequestMessage.RequestUri;
 1993
 1994    //        foreach (KeyValuePair<string, object> property in this.httpRequestMessage.Properties)
 1995    //        {
 1996    //            message.Properties.Add(property.Key, property.Value);
 1997    //        }
 1998
 1999    //        this.httpRequestMessage.Properties.Clear();
 2000    //    }
 2001
 2002    //    protected override string SoapActionHeader
 2003    //    {
 2004    //        get
 2005    //        {
 2006    //            IEnumerable<string> values;
 2007    //            if (this.httpRequestMessage.Headers.TryGetValues(SoapAction, out values))
 2008    //            {
 2009    //                foreach (string headerValue in values)
 2010    //                {
 2011    //                    return headerValue;
 2012    //                }
 2013    //            }
 2014
 2015    //            return null;
 2016    //        }
 2017    //    }
 2018
 2019    //    public void CopyHeaders(WebHeaderCollection headers)
 2020    //    {
 2021    //        // No special-casing for the "WWW-Authenticate" header required here,
 2022    //        // because this method is only called for the incoming request
 2023    //        // and the WWW-Authenticate header is a header only applied to responses.
 2024    //        HttpChannelUtilities.CopyHeaders(this.httpRequestMessage, headers.Add);
 2025    //    }
 2026
 2027    //    internal void SetHttpRequestMessage(HttpRequestMessage httpRequestMessage)
 2028    //    {
 2029    //        Fx.Assert(httpRequestMessage != null, "httpRequestMessage should not be null.");
 2030    //        this.httpRequestMessage = httpRequestMessage;
 2031    //    }
 2032    //}
 2033}
 2034