HostedHttpContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / System.ServiceModel.Activation / System / ServiceModel / Activation / HostedHttpContext.cs / 1570162 / HostedHttpContext.cs

                            //---------------------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{ 
    using System.Diagnostics;
    using System.Globalization; 
    using System.IO; 
    using System.Net;
    using System.Runtime; 
    using System.Security;
    using System.Security.Authentication.ExtendedProtection;
    using System.ServiceModel;
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Security; 
    using System.Web; 

    class HostedHttpContext : HttpRequestContext 
    {
        HostedRequestContainer requestContainer;
        HostedHttpRequestAsyncResult result;
 
        public HostedHttpContext(HttpChannelListener listener, HostedHttpRequestAsyncResult result)
            : base(listener, null) 
        { 
            this.result = result;
        } 

        public override string HttpMethod
        {
            get 
            {
                return result.GetHttpMethod(); 
            } 
        }
 
        protected override SecurityMessageProperty OnProcessAuthentication()
        {
            return Listener.ProcessAuthentication(this.result);
        } 

        protected override HttpStatusCode ValidateAuthentication() 
        { 
            return Listener.ValidateAuthentication(this.result);
        } 

        // Accessing the headers of an already replied HttpRequest instance causes an Access Violation in hosted mode.
        // In one-way scenarios, reply happens before the user gets the message. That's why we are disabling all access
        // to HostedRequestContainer (CSDMain 34014). 
        void CloseHostedRequestContainer()
        { 
            // RequestContext.RequestMessage property can throw rather than create a message. 
            // This means we never created a message and never cached the IIS properties.
            // At this point the user may return a reply, so requestContainer is allowed to be null. 
            if (this.requestContainer != null)
            {
                this.requestContainer.Close();
                this.requestContainer = null; 
            }
        } 
 
        protected override void OnReply(Message message, TimeSpan timeout)
        { 
            this.CloseHostedRequestContainer();
            base.OnReply(message, timeout);
        }
 
        protected override IAsyncResult OnBeginReply(
            Message message, TimeSpan timeout, AsyncCallback callback, object state) 
        { 
            this.CloseHostedRequestContainer();
            return base.OnBeginReply(message, timeout, callback, state); 
        }

        protected override void OnAbort()
        { 
            base.OnAbort();
            result.Abort(); 
        } 

        protected override HttpInput GetHttpInput() 
        {
            return new HostedHttpInput(this);
        }
 
        protected override HttpOutput GetHttpOutput(Message message)
        { 
            // work around http.sys keep alive bug with chunked requests, see MB 49676, this is fixed in Vista 
            if ((this.HttpInput.ContentLength == -1 && !OSEnvironmentHelper.IsVistaOrGreater) || !this.KeepAliveEnabled)
            { 
                result.SetConnectionClose();
            }
            return new HostedRequestHttpOutput(result, Listener, message, this);
        } 

        protected override void OnClose(TimeSpan timeout) 
        { 
            base.OnClose(timeout);
            result.OnReplySent(); 
        }

        void SetRequestContainer(HostedRequestContainer requestContainer)
        { 
            this.requestContainer = requestContainer;
        } 
 
        class HostedHttpInput : HttpInput
        { 
            int contentLength;
            string contentType;
            HostedHttpContext hostedHttpContext;
            byte[] preReadBuffer; 

            public HostedHttpInput(HostedHttpContext hostedHttpContext) 
                : base(hostedHttpContext.Listener, true, hostedHttpContext.Listener.IsChannelBindingSupportEnabled) 
            {
                this.hostedHttpContext = hostedHttpContext; 

                EnvelopeVersion envelopeVersion = hostedHttpContext.Listener.MessageEncoderFactory.Encoder.MessageVersion.Envelope;

                // MB#29602, perf optimization 
                if (envelopeVersion == EnvelopeVersion.Soap11)
                { 
                    // For soap 1.1, use headers collection to get content-type since we need to pull in the headers 
                    // collection for SOAP-Action anyways
                    this.contentType = hostedHttpContext.result.GetContentType(); 
                }
                else
                {
                    // For soap 1.2, the we pull the action header from the content-type, so don't access the headers 
                    // and just use the typed property. For other versions, we shouldn't need the headers up front.
                    this.contentType = hostedHttpContext.result.GetContentTypeFast(); 
                } 

                this.contentLength = hostedHttpContext.result.GetContentLength(); 

                // MB#34947: System.Web signals chunked as 0 as well so the only way we can
                // differentiate is by reading ahead
                if (this.contentLength == 0) 
                {
                    preReadBuffer = hostedHttpContext.result.GetPrereadBuffer(ref this.contentLength); 
                } 
            }
 
            public override long ContentLength
            {
                get
                { 
                    return this.contentLength;
                } 
            } 

            protected override string ContentTypeCore 
            {
                get
                {
                    return this.contentType; 
                }
            } 
 
            protected override bool HasContent
            { 
                get { return (this.preReadBuffer != null || this.ContentLength > 0); }
            }

            protected override string SoapActionHeader 
            {
                get 
                { 
                    return hostedHttpContext.result.GetSoapAction();
                } 
            }

            protected override ChannelBinding ChannelBinding
            { 
                get
                { 
                    return ChannelBindingUtility.DuplicateToken(hostedHttpContext.result.GetChannelBinding()); 
                }
            } 

            protected override void AddProperties(Message message)
            {
                HostedRequestContainer requestContainer = new HostedRequestContainer(this.hostedHttpContext.result); 

                HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(requestContainer); 
 
                requestProperty.Method = this.hostedHttpContext.HttpMethod;
 
                // Uri.Query always includes the '?'
                if (this.hostedHttpContext.result.RequestUri.Query.Length > 1)
                {
                    requestProperty.QueryString = this.hostedHttpContext.result.RequestUri.Query.Substring(1); 
                }
 
                message.Properties.Add(HttpRequestMessageProperty.Name, requestProperty); 

                message.Properties.Add(HostingMessageProperty.Name, CreateMessagePropertyFromHostedResult(this.hostedHttpContext.result)); 
                message.Properties.Via = this.hostedHttpContext.result.RequestUri;

                RemoteEndpointMessageProperty remoteEndpointProperty = new RemoteEndpointMessageProperty(requestContainer);
                message.Properties.Add(RemoteEndpointMessageProperty.Name, remoteEndpointProperty); 

                this.hostedHttpContext.SetRequestContainer(requestContainer); 
            } 

            [Fx.Tag.SecurityNote(Critical = "Calls critical .ctor(HostedImpersonationContext)", 
                Safe = "Only accepts the incoming context from HostedHttpRequestAsyncResult which stores the context in a critical field")]
            [SecuritySafeCritical]
            static HostingMessageProperty CreateMessagePropertyFromHostedResult(HostedHttpRequestAsyncResult result)
            { 
                return new HostingMessageProperty(result);
            } 
 
            protected override Stream GetInputStream()
            { 
                if (this.preReadBuffer != null)
                {
                    return new HostedInputStream(this.hostedHttpContext, this.preReadBuffer); ;
                } 
                else
                { 
                    return new HostedInputStream(this.hostedHttpContext); 
                }
            } 

            class HostedInputStream : HttpDelayedAcceptStream
            {
                public HostedInputStream(HostedHttpContext hostedContext) 
                    : base(hostedContext.result.GetInputStream())
                { 
                } 

                public HostedInputStream(HostedHttpContext hostedContext, byte[] preReadBuffer) 
                    : base(new PreReadStream(hostedContext.result.GetInputStream(), preReadBuffer))
                {
                }
 
                public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
                { 
                    return base.BeginRead(buffer, offset, count, callback, state); 
                }
 
                public override int EndRead(IAsyncResult result)
                {
                    return base.EndRead(result);
                } 

                public override int Read(byte[] buffer, int offset, int count) 
                { 
                    return base.Read(buffer, offset, count);
                } 
            }
        }

        class HostedRequestHttpOutput : HttpOutput 
        {
            HostedHttpRequestAsyncResult result; 
            HostedHttpContext context; 
            string mimeVersion;
            string contentType; 
            int statusCode;

            public HostedRequestHttpOutput(HostedHttpRequestAsyncResult result, IHttpTransportFactorySettings settings,
                Message message, HostedHttpContext context) 
                : base(settings, message, false, false)
            { 
                this.result = result; 
                this.context = context;
 
                if (TransferModeHelper.IsResponseStreamed(settings.TransferMode))
                    result.SetTransferModeToStreaming();

                if (message.IsFault) 
                {
                    this.statusCode = (int)HttpStatusCode.InternalServerError; 
                } 
                else
                { 
                    this.statusCode = (int)HttpStatusCode.OK;
                }
            }
 
            protected override Stream GetOutputStream()
            { 
                return new HostedResponseOutputStream(this.result, this.context); 
            }
 
            protected override void AddMimeVersion(string version)
            {
                this.mimeVersion = version;
            } 

            protected override void SetContentType(string contentType) 
            { 
                this.contentType = contentType;
            } 

            protected override void SetContentLength(int contentLength)
            {
                result.AppendHeader("content-length", contentLength.ToString(CultureInfo.InvariantCulture)); 
            }
 
            protected override bool PrepareHttpSend(Message message) 
            {
                bool retValue = base.PrepareHttpSend(message); 
                object property;

                bool httpMethodIsHead = string.Compare(this.context.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) == 0;
                if (httpMethodIsHead) 
                {
                    retValue = true; 
                } 

                if (message.Properties.TryGetValue(HttpResponseMessageProperty.Name, out property)) 
                {
                    HttpResponseMessageProperty responseProperty = (HttpResponseMessageProperty)property;

                    if (responseProperty.SuppressPreamble) 
                    {
                        return retValue || responseProperty.SuppressEntityBody; 
                    } 

                    result.SetStatusCode((int)responseProperty.StatusCode); 
                    if (responseProperty.StatusDescription != null)
                    {
                        result.SetStatusDescription(responseProperty.StatusDescription);
                    } 

                    WebHeaderCollection responseHeaders = responseProperty.Headers; 
                    for (int i = 0; i < responseHeaders.Count; i++) 
                    {
                        string name = responseHeaders.Keys[i]; 
                        string value = responseHeaders[i];
                        if (string.Compare(name, "content-type", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            this.SetContentType(value); 
                        }
                        else if (string.Compare(name, HttpChannelUtilities.MIMEVersionHeader, StringComparison.OrdinalIgnoreCase) == 0) 
                        { 
                            this.mimeVersion = value;
                        } 
                        else if (string.Compare(name, "content-length", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            int contentLength = -1;
                            if (httpMethodIsHead && 
                                int.TryParse(value, out contentLength))
                            { 
                                this.SetContentLength(contentLength); 
                            }
                        } 
                        else
                        {
                            result.AppendHeader(name, value);
                        } 
                    }
                    if (responseProperty.SuppressEntityBody) 
                    { 
                        contentType = null;
                        retValue = true; 
                    }
                }

                else 
                {
                    result.SetStatusCode(statusCode); 
                } 

                if (contentType != null && contentType.Length != 0) 
                {
                    result.SetContentType(contentType);
                }
 
                if (this.mimeVersion != null)
                { 
                    result.AppendHeader(HttpChannelUtilities.MIMEVersionHeader, this.mimeVersion); 
                }
 
                return retValue;
            }

            class HostedResponseOutputStream : BytesReadPositionStream 
            {
                HostedHttpContext context; 
                HostedHttpRequestAsyncResult result; 

                public HostedResponseOutputStream(HostedHttpRequestAsyncResult result, HostedHttpContext context) 
                    : base(result.GetOutputStream())
                {
                    this.context = context;
                    this.result = result; 
                }
 
                public override void Close() 
                {
                    try 
                    {
                        base.Close();
                    }
                    catch (Exception e) 
                    {
                        CheckWrapThrow(e); 
                        throw; 
                    }
                    finally 
                    {
                        result.OnReplySent();
                    }
                } 

                public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) 
                { 
                    try
                    { 
                        return base.BeginWrite(buffer, offset, count, callback, state);
                    }
                    catch (Exception e)
                    { 
                        CheckWrapThrow(e);
                        throw; 
                    } 
                }
 
                public override void EndWrite(IAsyncResult result)
                {
                    try
                    { 
                        base.EndWrite(result);
                    } 
                    catch (Exception e) 
                    {
                        CheckWrapThrow(e); 
                        throw;
                    }
                }
 
                public override void Write(byte[] buffer, int offset, int count)
                { 
                    try 
                    {
                        base.Write(buffer, offset, count); 
                    }
                    catch (Exception e)
                    {
                        CheckWrapThrow(e); 
                        throw;
                    } 
                } 

                void CheckWrapThrow(Exception e) 
                {
                    if (!Fx.IsFatal(e))
                    {
                        if (e is HttpException) 
                        {
                            if (this.context.Aborted) 
                            { 
                                throw FxTrace.Exception.AsError(
                                    new CommunicationObjectAbortedException(SR.RequestContextAborted, e)); 
                            }
                            else
                            {
                                throw FxTrace.Exception.AsError(new CommunicationException(e.Message, e)); 
                            }
                        } 
                        else if (this.context.Aborted) 
                        {
                            // See VsWhidbey (594450) 
                            if (DiagnosticUtility.ShouldTraceError)
                            {
                                TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.RequestContextAbort, SR.TraceCodeRequestContextAbort, this, e);
                            } 

                            throw FxTrace.Exception.AsError(new CommunicationObjectAbortedException(SR.RequestContextAborted)); 
                        } 
                    }
                } 
            }
        }

        class HostedRequestContainer : RemoteEndpointMessageProperty.IRemoteEndpointProvider, HttpRequestMessageProperty.IHttpHeaderProvider 
        {
            bool isClosed; 
            HostedHttpRequestAsyncResult result; 
            object thisLock;
 
            public HostedRequestContainer(HostedHttpRequestAsyncResult result)
            {
                this.result = result;
                this.thisLock = new object(); 
            }
 
            object ThisLock 
            {
                get 
                {
                    return this.thisLock;
                }
            } 

            // IIS properties are not valid once the reply occurs. 
            // Close invalidates all access to these properties. 
            public void Close()
            { 
                lock (this.ThisLock)
                {
                    this.isClosed = true;
                } 
            }
 
 
            [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects",
                Safe = "Does not leak control or mutable/harmful data, no potential for harm")] 
            [SecuritySafeCritical]
            void HttpRequestMessageProperty.IHttpHeaderProvider.CopyHeaders(WebHeaderCollection headers)
            {
                if (!this.isClosed) 
                {
                    lock (this.ThisLock) 
                    { 
                        if (!this.isClosed)
                        { 
                            headers.Add(this.result.Application.Request.Headers);
                        }
                    }
                } 
            }
 
            [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects", 
                Safe = "Does not leak control or mutable/harmful data, no potential for harm")]
            [SecuritySafeCritical] 
            string RemoteEndpointMessageProperty.IRemoteEndpointProvider.GetAddress()
            {
                if (!this.isClosed)
                { 
                    lock (this.ThisLock)
                    { 
                        if (!this.isClosed) 
                        {
                            return this.result.Application.Request.UserHostAddress; 
                        }
                    }
                }
                return string.Empty; 
            }
 
 
            [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects",
                Safe = "Does not leak control or mutable/harmful data, no potential for harm")] 
            [SecuritySafeCritical]
            int RemoteEndpointMessageProperty.IRemoteEndpointProvider.GetPort()
            {
                int port = 0; 

                if (!this.isClosed) 
                { 
                    lock (this.ThisLock)
                    { 
                        if (!this.isClosed)
                        {
                            string remotePort = this.result.Application.Request.ServerVariables["REMOTE_PORT"];
                            if (string.IsNullOrEmpty(remotePort) || !int.TryParse(remotePort, out port)) 
                            {
                                port = 0; 
                            } 
                        }
                    } 
                }

                return port;
            } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{ 
    using System.Diagnostics;
    using System.Globalization; 
    using System.IO; 
    using System.Net;
    using System.Runtime; 
    using System.Security;
    using System.Security.Authentication.ExtendedProtection;
    using System.ServiceModel;
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Security; 
    using System.Web; 

    class HostedHttpContext : HttpRequestContext 
    {
        HostedRequestContainer requestContainer;
        HostedHttpRequestAsyncResult result;
 
        public HostedHttpContext(HttpChannelListener listener, HostedHttpRequestAsyncResult result)
            : base(listener, null) 
        { 
            this.result = result;
        } 

        public override string HttpMethod
        {
            get 
            {
                return result.GetHttpMethod(); 
            } 
        }
 
        protected override SecurityMessageProperty OnProcessAuthentication()
        {
            return Listener.ProcessAuthentication(this.result);
        } 

        protected override HttpStatusCode ValidateAuthentication() 
        { 
            return Listener.ValidateAuthentication(this.result);
        } 

        // Accessing the headers of an already replied HttpRequest instance causes an Access Violation in hosted mode.
        // In one-way scenarios, reply happens before the user gets the message. That's why we are disabling all access
        // to HostedRequestContainer (CSDMain 34014). 
        void CloseHostedRequestContainer()
        { 
            // RequestContext.RequestMessage property can throw rather than create a message. 
            // This means we never created a message and never cached the IIS properties.
            // At this point the user may return a reply, so requestContainer is allowed to be null. 
            if (this.requestContainer != null)
            {
                this.requestContainer.Close();
                this.requestContainer = null; 
            }
        } 
 
        protected override void OnReply(Message message, TimeSpan timeout)
        { 
            this.CloseHostedRequestContainer();
            base.OnReply(message, timeout);
        }
 
        protected override IAsyncResult OnBeginReply(
            Message message, TimeSpan timeout, AsyncCallback callback, object state) 
        { 
            this.CloseHostedRequestContainer();
            return base.OnBeginReply(message, timeout, callback, state); 
        }

        protected override void OnAbort()
        { 
            base.OnAbort();
            result.Abort(); 
        } 

        protected override HttpInput GetHttpInput() 
        {
            return new HostedHttpInput(this);
        }
 
        protected override HttpOutput GetHttpOutput(Message message)
        { 
            // work around http.sys keep alive bug with chunked requests, see MB 49676, this is fixed in Vista 
            if ((this.HttpInput.ContentLength == -1 && !OSEnvironmentHelper.IsVistaOrGreater) || !this.KeepAliveEnabled)
            { 
                result.SetConnectionClose();
            }
            return new HostedRequestHttpOutput(result, Listener, message, this);
        } 

        protected override void OnClose(TimeSpan timeout) 
        { 
            base.OnClose(timeout);
            result.OnReplySent(); 
        }

        void SetRequestContainer(HostedRequestContainer requestContainer)
        { 
            this.requestContainer = requestContainer;
        } 
 
        class HostedHttpInput : HttpInput
        { 
            int contentLength;
            string contentType;
            HostedHttpContext hostedHttpContext;
            byte[] preReadBuffer; 

            public HostedHttpInput(HostedHttpContext hostedHttpContext) 
                : base(hostedHttpContext.Listener, true, hostedHttpContext.Listener.IsChannelBindingSupportEnabled) 
            {
                this.hostedHttpContext = hostedHttpContext; 

                EnvelopeVersion envelopeVersion = hostedHttpContext.Listener.MessageEncoderFactory.Encoder.MessageVersion.Envelope;

                // MB#29602, perf optimization 
                if (envelopeVersion == EnvelopeVersion.Soap11)
                { 
                    // For soap 1.1, use headers collection to get content-type since we need to pull in the headers 
                    // collection for SOAP-Action anyways
                    this.contentType = hostedHttpContext.result.GetContentType(); 
                }
                else
                {
                    // For soap 1.2, the we pull the action header from the content-type, so don't access the headers 
                    // and just use the typed property. For other versions, we shouldn't need the headers up front.
                    this.contentType = hostedHttpContext.result.GetContentTypeFast(); 
                } 

                this.contentLength = hostedHttpContext.result.GetContentLength(); 

                // MB#34947: System.Web signals chunked as 0 as well so the only way we can
                // differentiate is by reading ahead
                if (this.contentLength == 0) 
                {
                    preReadBuffer = hostedHttpContext.result.GetPrereadBuffer(ref this.contentLength); 
                } 
            }
 
            public override long ContentLength
            {
                get
                { 
                    return this.contentLength;
                } 
            } 

            protected override string ContentTypeCore 
            {
                get
                {
                    return this.contentType; 
                }
            } 
 
            protected override bool HasContent
            { 
                get { return (this.preReadBuffer != null || this.ContentLength > 0); }
            }

            protected override string SoapActionHeader 
            {
                get 
                { 
                    return hostedHttpContext.result.GetSoapAction();
                } 
            }

            protected override ChannelBinding ChannelBinding
            { 
                get
                { 
                    return ChannelBindingUtility.DuplicateToken(hostedHttpContext.result.GetChannelBinding()); 
                }
            } 

            protected override void AddProperties(Message message)
            {
                HostedRequestContainer requestContainer = new HostedRequestContainer(this.hostedHttpContext.result); 

                HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(requestContainer); 
 
                requestProperty.Method = this.hostedHttpContext.HttpMethod;
 
                // Uri.Query always includes the '?'
                if (this.hostedHttpContext.result.RequestUri.Query.Length > 1)
                {
                    requestProperty.QueryString = this.hostedHttpContext.result.RequestUri.Query.Substring(1); 
                }
 
                message.Properties.Add(HttpRequestMessageProperty.Name, requestProperty); 

                message.Properties.Add(HostingMessageProperty.Name, CreateMessagePropertyFromHostedResult(this.hostedHttpContext.result)); 
                message.Properties.Via = this.hostedHttpContext.result.RequestUri;

                RemoteEndpointMessageProperty remoteEndpointProperty = new RemoteEndpointMessageProperty(requestContainer);
                message.Properties.Add(RemoteEndpointMessageProperty.Name, remoteEndpointProperty); 

                this.hostedHttpContext.SetRequestContainer(requestContainer); 
            } 

            [Fx.Tag.SecurityNote(Critical = "Calls critical .ctor(HostedImpersonationContext)", 
                Safe = "Only accepts the incoming context from HostedHttpRequestAsyncResult which stores the context in a critical field")]
            [SecuritySafeCritical]
            static HostingMessageProperty CreateMessagePropertyFromHostedResult(HostedHttpRequestAsyncResult result)
            { 
                return new HostingMessageProperty(result);
            } 
 
            protected override Stream GetInputStream()
            { 
                if (this.preReadBuffer != null)
                {
                    return new HostedInputStream(this.hostedHttpContext, this.preReadBuffer); ;
                } 
                else
                { 
                    return new HostedInputStream(this.hostedHttpContext); 
                }
            } 

            class HostedInputStream : HttpDelayedAcceptStream
            {
                public HostedInputStream(HostedHttpContext hostedContext) 
                    : base(hostedContext.result.GetInputStream())
                { 
                } 

                public HostedInputStream(HostedHttpContext hostedContext, byte[] preReadBuffer) 
                    : base(new PreReadStream(hostedContext.result.GetInputStream(), preReadBuffer))
                {
                }
 
                public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
                { 
                    return base.BeginRead(buffer, offset, count, callback, state); 
                }
 
                public override int EndRead(IAsyncResult result)
                {
                    return base.EndRead(result);
                } 

                public override int Read(byte[] buffer, int offset, int count) 
                { 
                    return base.Read(buffer, offset, count);
                } 
            }
        }

        class HostedRequestHttpOutput : HttpOutput 
        {
            HostedHttpRequestAsyncResult result; 
            HostedHttpContext context; 
            string mimeVersion;
            string contentType; 
            int statusCode;

            public HostedRequestHttpOutput(HostedHttpRequestAsyncResult result, IHttpTransportFactorySettings settings,
                Message message, HostedHttpContext context) 
                : base(settings, message, false, false)
            { 
                this.result = result; 
                this.context = context;
 
                if (TransferModeHelper.IsResponseStreamed(settings.TransferMode))
                    result.SetTransferModeToStreaming();

                if (message.IsFault) 
                {
                    this.statusCode = (int)HttpStatusCode.InternalServerError; 
                } 
                else
                { 
                    this.statusCode = (int)HttpStatusCode.OK;
                }
            }
 
            protected override Stream GetOutputStream()
            { 
                return new HostedResponseOutputStream(this.result, this.context); 
            }
 
            protected override void AddMimeVersion(string version)
            {
                this.mimeVersion = version;
            } 

            protected override void SetContentType(string contentType) 
            { 
                this.contentType = contentType;
            } 

            protected override void SetContentLength(int contentLength)
            {
                result.AppendHeader("content-length", contentLength.ToString(CultureInfo.InvariantCulture)); 
            }
 
            protected override bool PrepareHttpSend(Message message) 
            {
                bool retValue = base.PrepareHttpSend(message); 
                object property;

                bool httpMethodIsHead = string.Compare(this.context.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) == 0;
                if (httpMethodIsHead) 
                {
                    retValue = true; 
                } 

                if (message.Properties.TryGetValue(HttpResponseMessageProperty.Name, out property)) 
                {
                    HttpResponseMessageProperty responseProperty = (HttpResponseMessageProperty)property;

                    if (responseProperty.SuppressPreamble) 
                    {
                        return retValue || responseProperty.SuppressEntityBody; 
                    } 

                    result.SetStatusCode((int)responseProperty.StatusCode); 
                    if (responseProperty.StatusDescription != null)
                    {
                        result.SetStatusDescription(responseProperty.StatusDescription);
                    } 

                    WebHeaderCollection responseHeaders = responseProperty.Headers; 
                    for (int i = 0; i < responseHeaders.Count; i++) 
                    {
                        string name = responseHeaders.Keys[i]; 
                        string value = responseHeaders[i];
                        if (string.Compare(name, "content-type", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            this.SetContentType(value); 
                        }
                        else if (string.Compare(name, HttpChannelUtilities.MIMEVersionHeader, StringComparison.OrdinalIgnoreCase) == 0) 
                        { 
                            this.mimeVersion = value;
                        } 
                        else if (string.Compare(name, "content-length", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            int contentLength = -1;
                            if (httpMethodIsHead && 
                                int.TryParse(value, out contentLength))
                            { 
                                this.SetContentLength(contentLength); 
                            }
                        } 
                        else
                        {
                            result.AppendHeader(name, value);
                        } 
                    }
                    if (responseProperty.SuppressEntityBody) 
                    { 
                        contentType = null;
                        retValue = true; 
                    }
                }

                else 
                {
                    result.SetStatusCode(statusCode); 
                } 

                if (contentType != null && contentType.Length != 0) 
                {
                    result.SetContentType(contentType);
                }
 
                if (this.mimeVersion != null)
                { 
                    result.AppendHeader(HttpChannelUtilities.MIMEVersionHeader, this.mimeVersion); 
                }
 
                return retValue;
            }

            class HostedResponseOutputStream : BytesReadPositionStream 
            {
                HostedHttpContext context; 
                HostedHttpRequestAsyncResult result; 

                public HostedResponseOutputStream(HostedHttpRequestAsyncResult result, HostedHttpContext context) 
                    : base(result.GetOutputStream())
                {
                    this.context = context;
                    this.result = result; 
                }
 
                public override void Close() 
                {
                    try 
                    {
                        base.Close();
                    }
                    catch (Exception e) 
                    {
                        CheckWrapThrow(e); 
                        throw; 
                    }
                    finally 
                    {
                        result.OnReplySent();
                    }
                } 

                public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) 
                { 
                    try
                    { 
                        return base.BeginWrite(buffer, offset, count, callback, state);
                    }
                    catch (Exception e)
                    { 
                        CheckWrapThrow(e);
                        throw; 
                    } 
                }
 
                public override void EndWrite(IAsyncResult result)
                {
                    try
                    { 
                        base.EndWrite(result);
                    } 
                    catch (Exception e) 
                    {
                        CheckWrapThrow(e); 
                        throw;
                    }
                }
 
                public override void Write(byte[] buffer, int offset, int count)
                { 
                    try 
                    {
                        base.Write(buffer, offset, count); 
                    }
                    catch (Exception e)
                    {
                        CheckWrapThrow(e); 
                        throw;
                    } 
                } 

                void CheckWrapThrow(Exception e) 
                {
                    if (!Fx.IsFatal(e))
                    {
                        if (e is HttpException) 
                        {
                            if (this.context.Aborted) 
                            { 
                                throw FxTrace.Exception.AsError(
                                    new CommunicationObjectAbortedException(SR.RequestContextAborted, e)); 
                            }
                            else
                            {
                                throw FxTrace.Exception.AsError(new CommunicationException(e.Message, e)); 
                            }
                        } 
                        else if (this.context.Aborted) 
                        {
                            // See VsWhidbey (594450) 
                            if (DiagnosticUtility.ShouldTraceError)
                            {
                                TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.RequestContextAbort, SR.TraceCodeRequestContextAbort, this, e);
                            } 

                            throw FxTrace.Exception.AsError(new CommunicationObjectAbortedException(SR.RequestContextAborted)); 
                        } 
                    }
                } 
            }
        }

        class HostedRequestContainer : RemoteEndpointMessageProperty.IRemoteEndpointProvider, HttpRequestMessageProperty.IHttpHeaderProvider 
        {
            bool isClosed; 
            HostedHttpRequestAsyncResult result; 
            object thisLock;
 
            public HostedRequestContainer(HostedHttpRequestAsyncResult result)
            {
                this.result = result;
                this.thisLock = new object(); 
            }
 
            object ThisLock 
            {
                get 
                {
                    return this.thisLock;
                }
            } 

            // IIS properties are not valid once the reply occurs. 
            // Close invalidates all access to these properties. 
            public void Close()
            { 
                lock (this.ThisLock)
                {
                    this.isClosed = true;
                } 
            }
 
 
            [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects",
                Safe = "Does not leak control or mutable/harmful data, no potential for harm")] 
            [SecuritySafeCritical]
            void HttpRequestMessageProperty.IHttpHeaderProvider.CopyHeaders(WebHeaderCollection headers)
            {
                if (!this.isClosed) 
                {
                    lock (this.ThisLock) 
                    { 
                        if (!this.isClosed)
                        { 
                            headers.Add(this.result.Application.Request.Headers);
                        }
                    }
                } 
            }
 
            [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects", 
                Safe = "Does not leak control or mutable/harmful data, no potential for harm")]
            [SecuritySafeCritical] 
            string RemoteEndpointMessageProperty.IRemoteEndpointProvider.GetAddress()
            {
                if (!this.isClosed)
                { 
                    lock (this.ThisLock)
                    { 
                        if (!this.isClosed) 
                        {
                            return this.result.Application.Request.UserHostAddress; 
                        }
                    }
                }
                return string.Empty; 
            }
 
 
            [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects",
                Safe = "Does not leak control or mutable/harmful data, no potential for harm")] 
            [SecuritySafeCritical]
            int RemoteEndpointMessageProperty.IRemoteEndpointProvider.GetPort()
            {
                int port = 0; 

                if (!this.isClosed) 
                { 
                    lock (this.ThisLock)
                    { 
                        if (!this.isClosed)
                        {
                            string remotePort = this.result.Application.Request.ServerVariables["REMOTE_PORT"];
                            if (string.IsNullOrEmpty(remotePort) || !int.TryParse(remotePort, out port)) 
                            {
                                port = 0; 
                            } 
                        }
                    } 
                }

                return port;
            } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK