Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / SharedHttpTransportManager.cs / 1 / SharedHttpTransportManager.cs
//---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Diagnostics; using System.ServiceModel; using System.Net; using System.ServiceModel.Diagnostics; using System.ServiceModel.Dispatcher; using System.Threading; using System.Security.Principal; class SharedHttpTransportManager : HttpTransportManager { const int maxPendingGetContexts = 10; #if DEBUG // add performance counter instead in v.Next - see MessageBus bug #54117 int currentPendingGetContexts; #endif HttpListener listener; ManualResetEvent listenStartedEvent; Exception listenStartedException; AsyncCallback onGetContext; ItemDequeuedCallback onMessageDequeued; WaitCallback onCompleteGetContextLater; bool unsafeConnectionNtlmAuthentication; internal SharedHttpTransportManager(Uri listenUri, HttpChannelListener channelListener) : base(listenUri, channelListener.HostNameComparisonMode, channelListener.Realm) { this.onGetContext = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnGetContext)); this.onMessageDequeued = new ItemDequeuedCallback(OnMessageDequeued); this.unsafeConnectionNtlmAuthentication = channelListener.UnsafeConnectionNtlmAuthentication; } internal override bool IsCompatible(HttpChannelListener channelListener) { if (channelListener.InheritBaseAddressSettings) return true; if (!channelListener.IsScopeIdCompatible(HostNameComparisonMode, this.ListenUri)) { return false; } return channelListener.UnsafeConnectionNtlmAuthentication == this.unsafeConnectionNtlmAuthentication && base.IsCompatible(channelListener); } internal override void OnClose() { try { listener.Stop(); } finally { try { listener.Close(); } finally { base.OnClose(); } } listener = null; } IAsyncResult BeginGetContext(AsyncCallback callback, object state, bool startListening) { while (true) { Exception unexpectedException = null; try { try { if (ExecutionContext.IsFlowSuppressed()) { return listener.BeginGetContext(callback, state); } else { using (ExecutionContext.SuppressFlow()) { return listener.BeginGetContext(callback, state); } } } catch (HttpListenerException e) { switch (e.ErrorCode) { case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: case UnsafeNativeMethods.ERROR_OUTOFMEMORY: case UnsafeNativeMethods.ERROR_NO_SYSTEM_RESOURCES: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InsufficientMemoryException(SR.GetString(SR.InsufficentMemory), e)); default: if (!ExceptionHandler.HandleTransportExceptionHelper(e)) throw; break; } } } catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { throw; } if (startListening) { // Since we're under a call to StartListening(), just throw the exception up the stack. throw; } unexpectedException = e; } if (unexpectedException != null) { this.Fault(unexpectedException); return null; } } } void OnGetContext(IAsyncResult result) { if (result.CompletedSynchronously) { return; } OnGetContextCore(result); } void OnGetContextCore(IAsyncResult result) { bool enqueued = false; while (!enqueued) { Exception unexpectedException = null; try { try { HttpListenerContext listenerContext = null; lock (base.ThisLock) { if (listener == null) // we've been closed return; listenerContext = listener.EndGetContext(result); DiagnosticUtility.DebugAssert(listenerContext != null && listenerContext.Request != null, ""); } HttpChannelListener channelListener = null; // Grab the activity from the context and set that as the surrounding activity. // If a message appears, we will transfer to the message's activity next using (DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.BoundOperation(this.Activity) : null) { using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivityWithTransferInOnly(listenerContext.Request.RequestTraceIdentifier) : null) { if (activity != null && DiagnosticUtility.ShouldUseActivity) { ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityReceiveBytes, listenerContext.Request.Url.ToString()), ActivityType.ReceiveBytes); } if (DiagnosticUtility.ShouldTraceInformation) { TraceUtility.TraceHttpConnectionInformation(listenerContext.Request.LocalEndPoint.ToString(), listenerContext.Request.RemoteEndPoint.ToString(), this); } if (base.TryLookupUri(listenerContext.Request.Url, listenerContext.Request.HttpMethod, this.HostNameComparisonMode, out channelListener)) { enqueued = channelListener.HttpContextReceived( HttpRequestContext.CreateContext(channelListener, listenerContext), onMessageDequeued); #if DEBUG // add performance counter instead in v.Next - see MessageBus bug #54117 if (enqueued) { bool traceLimit = false; lock (ThisLock) { currentPendingGetContexts++; if (currentPendingGetContexts >= maxPendingGetContexts) { traceLimit = true; } } if (traceLimit) { if (DiagnosticUtility.ShouldTraceWarning) { DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Warning, TraceCode.HttpChannelConcurrentReceiveQuotaReached, SR.GetString(SR.HttpConcurrentReceiveQuotaReached, maxPendingGetContexts)); } } } #endif } else { if (DiagnosticUtility.ShouldTraceWarning) { TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.HttpChannelMessageReceiveFailed, null); } // no match -- 405 or 404 if (string.Compare(listenerContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) != 0) { listenerContext.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; listenerContext.Response.Headers.Add(HttpResponseHeader.Allow, "POST"); } else { listenerContext.Response.StatusCode = (int)HttpStatusCode.NotFound; } listenerContext.Response.ContentLength64 = 0; listenerContext.Response.Close(); } } } } catch (HttpListenerException e) { switch (e.ErrorCode) { case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: case UnsafeNativeMethods.ERROR_OUTOFMEMORY: case UnsafeNativeMethods.ERROR_NO_SYSTEM_RESOURCES: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InsufficientMemoryException(SR.GetString(SR.InsufficentMemory), e)); default: if (!ExceptionHandler.HandleTransportExceptionHelper(e)) throw; break; } } } catch (Exception exception) { if (DiagnosticUtility.IsFatal(exception)) { throw; } unexpectedException = exception; } if (unexpectedException != null) { this.Fault(unexpectedException); } if (!enqueued) // onMessageDequeued will handle this in the enqueued case { lock (base.ThisLock) { if (listener != null) { result = BeginGetContext(onGetContext, null, false); if ((result == null) || !result.CompletedSynchronously) { return; } } } } } } void OnCompleteGetContextLater(object state) { OnGetContextCore((IAsyncResult)state); } void StartListening() { for (int i = 0; i < maxPendingGetContexts; i++) { IAsyncResult result = BeginGetContext(onGetContext, null, true); if (result.CompletedSynchronously) { if (onCompleteGetContextLater == null) { onCompleteGetContextLater = new WaitCallback(OnCompleteGetContextLater); } IOThreadScheduler.ScheduleCallback(onCompleteGetContextLater, result); } } } void OnListening(object state) { try { StartListening(); } catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { throw; } listenStartedException = e; } finally { listenStartedEvent.Set(); } } void OnMessageDequeued() { ThreadTrace.Trace("message dequeued"); IAsyncResult result = null; lock (base.ThisLock) { if (listener != null) { #if DEBUG // add performance counter instead in v.Next - see MessageBus bug #54117 currentPendingGetContexts--; #endif result = BeginGetContext(onGetContext, null, false); } } if (result != null && result.CompletedSynchronously) { if (onCompleteGetContextLater == null) { onCompleteGetContextLater = new WaitCallback(OnCompleteGetContextLater); } IOThreadScheduler.ScheduleCallback(onCompleteGetContextLater, result); } } internal override void OnOpen() { listener = new HttpListener(); string host; switch (HostNameComparisonMode) { case HostNameComparisonMode.Exact: // Uri.DnsSafeHost strips the [], but preserves the scopeid for IPV6 addresses. if (ListenUri.HostNameType == UriHostNameType.IPv6) { host = string.Concat("[", ListenUri.DnsSafeHost, "]"); } else { host = ListenUri.DnsSafeHost; } break; case HostNameComparisonMode.StrongWildcard: host = "+"; break; case HostNameComparisonMode.WeakWildcard: host = "*"; break; default: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnrecognizedHostNameComparisonMode, HostNameComparisonMode.ToString()))); } string path = ListenUri.GetComponents(UriComponents.Path, UriFormat.Unescaped); if (!path.StartsWith("/", StringComparison.Ordinal)) path = "/" + path; if (!path.EndsWith("/", StringComparison.Ordinal)) path = path + "/"; string httpListenUrl = string.Concat(Scheme, "://", host, ":", ListenUri.Port, path); listener.UnsafeConnectionNtlmAuthentication = this.unsafeConnectionNtlmAuthentication; listener.AuthenticationSchemeSelectorDelegate = new AuthenticationSchemeSelector(SelectAuthenticationScheme); if (this.Realm != null) { listener.Realm = this.Realm; } bool success = false; try { listener.Prefixes.Add(httpListenUrl); listener.Start(); bool startedListening = false; try { if (Thread.CurrentThread.IsThreadPoolThread) { StartListening(); } else { // If we're not on a threadpool thread, then we need to post a callback to start our accepting loop // Otherwise if the calling thread aborts then the async I/O will get inadvertantly cancelled listenStartedEvent = new ManualResetEvent(false); IOThreadScheduler.ScheduleCallback(OnListening, null); listenStartedEvent.WaitOne(); listenStartedEvent.Close(); listenStartedEvent = null; if (listenStartedException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(listenStartedException); } } startedListening = true; } finally { if (!startedListening) { listener.Stop(); } } success = true; } catch (HttpListenerException listenerException) { switch (listenerException.NativeErrorCode) { case UnsafeNativeMethods.ERROR_ALREADY_EXISTS: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAlreadyInUseException(SR.GetString(SR.HttpRegistrationAlreadyExists, httpListenUrl), listenerException)); case UnsafeNativeMethods.ERROR_SHARING_VIOLATION: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAlreadyInUseException(SR.GetString(SR.HttpRegistrationPortInUse, httpListenUrl, ListenUri.Port), listenerException)); case UnsafeNativeMethods.ERROR_ACCESS_DENIED: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAccessDeniedException(SR.GetString(SR.HttpRegistrationAccessDenied, httpListenUrl), listenerException)); case UnsafeNativeMethods.ERROR_ALLOTTED_SPACE_EXCEEDED: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.HttpRegistrationLimitExceeded, httpListenUrl), listenerException)); case UnsafeNativeMethods.ERROR_INVALID_PARAMETER: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.HttpInvalidListenURI, ListenUri.OriginalString), listenerException)); default: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( HttpChannelUtilities.CreateCommunicationException(listenerException)); } } finally { if (!success) { listener.Abort(); } } } AuthenticationSchemes SelectAuthenticationScheme(HttpListenerRequest request) { try { AuthenticationSchemes result; HttpChannelListener channelListener; if (base.TryLookupUri(request.Url, request.HttpMethod, this.HostNameComparisonMode, out channelListener)) { result = channelListener.AuthenticationScheme; } else { // if we don't match a listener factory, we want to "fall through" the // auth delegate code and run through our normal OnGetContext codepath. // System.Net treats "None" as Access Denied, which is not our intent here. // In most cases this will just fall through to the code that returns a "404 Not Found" result = AuthenticationSchemes.Anonymous; } return result; } catch (Exception e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ValueProviderWrapper.cs
- DataGridRelationshipRow.cs
- Exception.cs
- Stopwatch.cs
- ReflectionPermission.cs
- OracleMonthSpan.cs
- SqlCacheDependency.cs
- SafeCryptoHandles.cs
- ItemContainerProviderWrapper.cs
- GACMembershipCondition.cs
- CurrentTimeZone.cs
- IndentTextWriter.cs
- FontUnit.cs
- SessionStateItemCollection.cs
- AsymmetricSignatureFormatter.cs
- AutomationPropertyInfo.cs
- XmlExceptionHelper.cs
- OdbcRowUpdatingEvent.cs
- XmlnsDefinitionAttribute.cs
- Rect.cs
- PerfCounters.cs
- PenContexts.cs
- ChildTable.cs
- CompareValidator.cs
- ScrollProperties.cs
- HttpCachePolicy.cs
- SecurityContext.cs
- brushes.cs
- PrintControllerWithStatusDialog.cs
- CellParaClient.cs
- _KerberosClient.cs
- DataConnectionHelper.cs
- WindowsEditBox.cs
- ByteStreamMessageUtility.cs
- SchemaEntity.cs
- ByteStorage.cs
- RichTextBoxConstants.cs
- SqlDesignerDataSourceView.cs
- ResourceExpressionBuilder.cs
- SplineKeyFrames.cs
- TextSelectionHelper.cs
- SHA384.cs
- HiddenFieldPageStatePersister.cs
- VisualBrush.cs
- LinkLabelLinkClickedEvent.cs
- SqlNotificationRequest.cs
- LoginDesigner.cs
- Compiler.cs
- DrawItemEvent.cs
- CacheEntry.cs
- DataGridViewCellStyleChangedEventArgs.cs
- WebPartDeleteVerb.cs
- FixedElement.cs
- RayMeshGeometry3DHitTestResult.cs
- VBCodeProvider.cs
- WebContext.cs
- VisualStyleRenderer.cs
- ProviderSettingsCollection.cs
- PagedDataSource.cs
- AndMessageFilterTable.cs
- IssuedTokenClientBehaviorsElement.cs
- CngAlgorithm.cs
- TransformerInfo.cs
- PanelStyle.cs
- DataError.cs
- ServiceNameElement.cs
- ToggleButton.cs
- XmlSequenceWriter.cs
- ImageField.cs
- smtpconnection.cs
- ZoomPercentageConverter.cs
- XmlAnyElementAttribute.cs
- VSWCFServiceContractGenerator.cs
- ErrorTableItemStyle.cs
- newinstructionaction.cs
- PageRequestManager.cs
- StylusPoint.cs
- CTreeGenerator.cs
- followingsibling.cs
- Ticks.cs
- HttpBrowserCapabilitiesBase.cs
- WorkflowServiceBehavior.cs
- UntrustedRecipientException.cs
- followingquery.cs
- OverflowException.cs
- CounterNameConverter.cs
- DesignerTransaction.cs
- PreProcessor.cs
- DataSourceHelper.cs
- AlphabetConverter.cs
- DbExpressionBuilder.cs
- ServiceModelTimeSpanValidator.cs
- UnicastIPAddressInformationCollection.cs
- SplitContainerDesigner.cs
- TextLineBreak.cs
- DispatcherExceptionFilterEventArgs.cs
- SignedXml.cs
- AuthorizationSection.cs
- UInt32Storage.cs
- XmlComplianceUtil.cs