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
- CursorConverter.cs
- TransactionTable.cs
- CodeExpressionRuleDeclaration.cs
- ElapsedEventArgs.cs
- FunctionNode.cs
- EventWaitHandleSecurity.cs
- DbDataReader.cs
- Decoder.cs
- ProviderIncompatibleException.cs
- KeyPressEvent.cs
- BlurEffect.cs
- SafeCertificateContext.cs
- OpacityConverter.cs
- AuthorizationBehavior.cs
- SessionStateSection.cs
- LinkLabel.cs
- TableCell.cs
- FontStyleConverter.cs
- XmlSecureResolver.cs
- ObjectHelper.cs
- ListComponentEditorPage.cs
- MimeTextImporter.cs
- Transform.cs
- While.cs
- PassportIdentity.cs
- ComponentCollection.cs
- StatusBarItemAutomationPeer.cs
- RegisteredScript.cs
- CompiledAction.cs
- DropDownHolder.cs
- DataBoundControlAdapter.cs
- UxThemeWrapper.cs
- WebPartEditorCancelVerb.cs
- UnsafeNativeMethodsTablet.cs
- __Filters.cs
- GridViewHeaderRowPresenter.cs
- MatrixAnimationBase.cs
- MetabaseSettings.cs
- MailSettingsSection.cs
- EntityContainerEntitySet.cs
- FormsIdentity.cs
- ClientTargetCollection.cs
- SplayTreeNode.cs
- FieldNameLookup.cs
- WinEventQueueItem.cs
- ActiveXMessageFormatter.cs
- CompressedStack.cs
- OleDbError.cs
- LongValidatorAttribute.cs
- CallTemplateAction.cs
- LineServices.cs
- IndentedTextWriter.cs
- WebHttpSecurity.cs
- LessThanOrEqual.cs
- Evidence.cs
- WorkflowRuntimeServiceElement.cs
- EqualityComparer.cs
- HorizontalAlignConverter.cs
- SqlFactory.cs
- DataRow.cs
- MsmqMessage.cs
- WebControlAdapter.cs
- DrawingServices.cs
- Literal.cs
- XsdDateTime.cs
- SafeFileMappingHandle.cs
- Base64Stream.cs
- WebPartConnectionCollection.cs
- TemplateEditingVerb.cs
- SpStreamWrapper.cs
- RequestCacheValidator.cs
- Tokenizer.cs
- BinHexEncoder.cs
- MasterPageParser.cs
- PathGradientBrush.cs
- LinkedResource.cs
- TextElementEnumerator.cs
- ListItem.cs
- WebPartConnectionsCancelEventArgs.cs
- _AcceptOverlappedAsyncResult.cs
- PagerSettings.cs
- EdmToObjectNamespaceMap.cs
- TaskCanceledException.cs
- OdbcException.cs
- KnownColorTable.cs
- XsltException.cs
- CompositeFontFamily.cs
- GraphicsState.cs
- DelimitedListTraceListener.cs
- DataGridBeginningEditEventArgs.cs
- MonthCalendar.cs
- EntityCollection.cs
- xml.cs
- Merger.cs
- BasicAsyncResult.cs
- BypassElementCollection.cs
- NamespaceInfo.cs
- DataBoundLiteralControl.cs
- SystemInformation.cs
- TraceFilter.cs