Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AsyncCodeActivityContext.cs
- ProfileGroupSettings.cs
- FastPropertyAccessor.cs
- WindowsIdentity.cs
- ScriptManager.cs
- StylusLogic.cs
- BooleanConverter.cs
- indexingfiltermarshaler.cs
- SplayTreeNode.cs
- XmlTextAttribute.cs
- TraceLog.cs
- WinInetCache.cs
- RMPermissions.cs
- XmlMessageFormatter.cs
- WeakRefEnumerator.cs
- SynchronizedCollection.cs
- LayoutTableCell.cs
- Vars.cs
- Brush.cs
- CqlIdentifiers.cs
- SizeFConverter.cs
- RtfControls.cs
- AuthenticationManager.cs
- Duration.cs
- EventData.cs
- QueryCursorEventArgs.cs
- ConnectionStringsExpressionBuilder.cs
- ClaimSet.cs
- LogStore.cs
- AssemblyAttributesGoHere.cs
- PasswordPropertyTextAttribute.cs
- NameValuePair.cs
- QilNode.cs
- SafeFindHandle.cs
- SoapFault.cs
- SqlConnectionFactory.cs
- SiteMapDataSource.cs
- Propagator.ExtentPlaceholderCreator.cs
- StringAnimationBase.cs
- SHA384.cs
- DataPagerFieldCommandEventArgs.cs
- DelegatingTypeDescriptionProvider.cs
- DoubleAnimation.cs
- ReadOnlyTernaryTree.cs
- AnimationTimeline.cs
- ScriptingSectionGroup.cs
- UpdateEventArgs.cs
- ErrorFormatterPage.cs
- WorkflowServiceHostFactory.cs
- KeySpline.cs
- FormParameter.cs
- DecoderReplacementFallback.cs
- LoginNameDesigner.cs
- SmiMetaDataProperty.cs
- ExpressionParser.cs
- XNodeSchemaApplier.cs
- XmlSerializationReader.cs
- InvokeProviderWrapper.cs
- latinshape.cs
- ListViewItem.cs
- ScriptMethodAttribute.cs
- PowerModeChangedEventArgs.cs
- ScriptRegistrationManager.cs
- ImpersonateTokenRef.cs
- WindowInteractionStateTracker.cs
- MenuCommandsChangedEventArgs.cs
- WebPartEventArgs.cs
- CompressedStack.cs
- GC.cs
- PhysicalOps.cs
- AttributeProviderAttribute.cs
- PublisherMembershipCondition.cs
- RoleGroupCollection.cs
- ValidationErrorCollection.cs
- ProcessHostMapPath.cs
- UnknownWrapper.cs
- TransportConfigurationTypeElementCollection.cs
- DesignerRegionCollection.cs
- UserPersonalizationStateInfo.cs
- EventMemberCodeDomSerializer.cs
- ButtonDesigner.cs
- SchemaHelper.cs
- oledbmetadatacolumnnames.cs
- Tokenizer.cs
- GraphicsPath.cs
- InProcStateClientManager.cs
- MenuItemBindingCollection.cs
- LayoutEditorPart.cs
- ObjectStateFormatter.cs
- SqlException.cs
- RootContext.cs
- MobileControlDesigner.cs
- FileEnumerator.cs
- Misc.cs
- SettingsPropertyCollection.cs
- Brushes.cs
- CapiSafeHandles.cs
- NameScope.cs
- EncryptedType.cs
- DataGridViewAdvancedBorderStyle.cs