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
- ByteRangeDownloader.cs
- SocketPermission.cs
- SubMenuStyle.cs
- DataGridViewCellValidatingEventArgs.cs
- DbConnectionPoolGroup.cs
- TextDecorationCollection.cs
- OracleBinary.cs
- InstancePersistenceCommandException.cs
- SimpleType.cs
- MarginCollapsingState.cs
- SelectionChangedEventArgs.cs
- httpstaticobjectscollection.cs
- TraceData.cs
- Win32.cs
- SimpleType.cs
- IntAverageAggregationOperator.cs
- UIElement3DAutomationPeer.cs
- DeobfuscatingStream.cs
- ResumeStoryboard.cs
- SecurityElementBase.cs
- DoubleAnimation.cs
- SqlConnectionPoolGroupProviderInfo.cs
- Point3DAnimationBase.cs
- CheckBoxRenderer.cs
- ObjectListCommandEventArgs.cs
- CompiledAction.cs
- HttpRawResponse.cs
- AspNetPartialTrustHelpers.cs
- MimeImporter.cs
- GatewayDefinition.cs
- XmlNamespaceDeclarationsAttribute.cs
- ListParagraph.cs
- TriState.cs
- GeneralTransform3DGroup.cs
- ParameterCollection.cs
- EnlistmentTraceIdentifier.cs
- CaseExpr.cs
- WindowsFormsLinkLabel.cs
- Msec.cs
- MethodCallExpression.cs
- ContextStaticAttribute.cs
- FieldNameLookup.cs
- AssociationTypeEmitter.cs
- COSERVERINFO.cs
- DataListGeneralPage.cs
- MethodBody.cs
- WindowsFormsHost.cs
- DeflateStreamAsyncResult.cs
- IndicCharClassifier.cs
- MdImport.cs
- PolicyChain.cs
- AutomationPeer.cs
- Sql8ConformanceChecker.cs
- XPathDocumentNavigator.cs
- RequestNavigateEventArgs.cs
- Int32.cs
- ExtensibleClassFactory.cs
- XmlEventCache.cs
- PeerMessageDispatcher.cs
- SamlSerializer.cs
- FixedSOMFixedBlock.cs
- EditingCoordinator.cs
- Deserializer.cs
- BidPrivateBase.cs
- GridViewRowEventArgs.cs
- GenerateDerivedKeyRequest.cs
- GestureRecognizer.cs
- InfoCardXmlSerializer.cs
- SecurityResources.cs
- ExpressionServices.cs
- StorageMappingItemLoader.cs
- UnsafeMethods.cs
- IndicCharClassifier.cs
- ListBoxDesigner.cs
- HitTestWithGeometryDrawingContextWalker.cs
- LayoutManager.cs
- TagPrefixCollection.cs
- GridView.cs
- UIHelper.cs
- DataFormats.cs
- ImageSourceValueSerializer.cs
- Int16.cs
- GacUtil.cs
- ScrollableControl.cs
- NetworkInformationPermission.cs
- SmiEventSink_DeferedProcessing.cs
- DbBuffer.cs
- PipeSecurity.cs
- CommonProperties.cs
- ToolStripPanelCell.cs
- AsymmetricSignatureDeformatter.cs
- DataTableClearEvent.cs
- TreeViewItemAutomationPeer.cs
- ShaperBuffers.cs
- AddInServer.cs
- BezierSegment.cs
- StrokeNodeData.cs
- ProfilePropertySettingsCollection.cs
- WebPartMenu.cs
- XmlDataDocument.cs