Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / ConnectionDemuxer.cs / 1 / ConnectionDemuxer.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Diagnostics; using System.ServiceModel; using System.ServiceModel.Activation; using System.ServiceModel.Dispatcher; using System.IO; using System.Threading; using System.Collections.Generic; using System.Globalization; using System.ServiceModel.Diagnostics; sealed class ConnectionDemuxer : IDisposable { ConnectionAcceptor acceptor; // we use this list to track readers that don't have a clear owner (so they don't get GC'ed) ListconnectionReaders; bool isDisposed; ConnectionModeCallback onConnectionModeKnown; ConnectionModeCallback onCachedConnectionModeKnown; ConnectionClosedCallback onConnectionClosed; ServerSessionPreambleCallback onSessionPreambleKnown; ServerSingletonPreambleCallback onSingletonPreambleKnown; WaitCallback reuseConnectionCallback; ServerSessionPreambleDemuxCallback serverSessionPreambleCallback; SingletonPreambleDemuxCallback singletonPreambleCallback; TransportSettingsCallback transportSettingsCallback; ItemDequeuedCallback pooledConnectionDequeuedCallback; OnViaDelegate viaDelegate; TimeSpan channelInitializationTimeout; TimeSpan idleTimeout; int maxPooledConnections; int pooledConnectionCount; public ConnectionDemuxer(IConnectionListener listener, int maxAccepts, int maxPendingConnections, TimeSpan channelInitializationTimeout, TimeSpan idleTimeout, int maxPooledConnections, TransportSettingsCallback transportSettingsCallback, SingletonPreambleDemuxCallback singletonPreambleCallback, ServerSessionPreambleDemuxCallback serverSessionPreambleCallback, ErrorCallback errorCallback) { this.connectionReaders = new List (); this.acceptor = new ConnectionAcceptor(listener, maxAccepts, maxPendingConnections, OnConnectionAvailable, errorCallback); this.channelInitializationTimeout = channelInitializationTimeout; this.idleTimeout = idleTimeout; this.maxPooledConnections = maxPooledConnections; this.onConnectionClosed = new ConnectionClosedCallback(OnConnectionClosed); this.transportSettingsCallback = transportSettingsCallback; this.singletonPreambleCallback = singletonPreambleCallback; this.serverSessionPreambleCallback = serverSessionPreambleCallback; } object ThisLock { get { return this; } } public void Dispose() { lock (ThisLock) { if (isDisposed) return; isDisposed = true; } for (int i = 0; i < connectionReaders.Count; i++) { connectionReaders[i].Dispose(); } connectionReaders.Clear(); acceptor.Dispose(); } ConnectionModeReader SetupModeReader(IConnection connection, bool isCached) { ConnectionModeReader modeReader; if (isCached) { if (onCachedConnectionModeKnown == null) { onCachedConnectionModeKnown = new ConnectionModeCallback(OnCachedConnectionModeKnown); } modeReader = new ConnectionModeReader(connection, onCachedConnectionModeKnown, onConnectionClosed); } else { if (onConnectionModeKnown == null) { onConnectionModeKnown = new ConnectionModeCallback(OnConnectionModeKnown); } modeReader = new ConnectionModeReader(connection, onConnectionModeKnown, onConnectionClosed); } lock (ThisLock) { if (isDisposed) { modeReader.Dispose(); return null; } connectionReaders.Add(modeReader); return modeReader; } } public void ReuseConnection(IConnection connection, TimeSpan closeTimeout) { connection.ExceptionEventType = TraceEventType.Information; ConnectionModeReader modeReader = SetupModeReader(connection, true); if (modeReader != null) { if (reuseConnectionCallback == null) { reuseConnectionCallback = new WaitCallback(ReuseConnectionCallback); } IOThreadScheduler.ScheduleCallback(reuseConnectionCallback, new ReuseConnectionState(modeReader, closeTimeout)); } } void ReuseConnectionCallback(object state) { ReuseConnectionState connectionState = (ReuseConnectionState)state; bool closeReader = false; lock (ThisLock) { if (this.pooledConnectionCount >= this.maxPooledConnections) { closeReader = true; } else { this.pooledConnectionCount++; } } if (closeReader) { if (DiagnosticUtility.ShouldTraceWarning) { DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Warning, TraceCode.ServerMaxPooledConnectionsQuotaReached, SR.GetString(SR.TraceCodeServerMaxPooledConnectionsQuotaReached, maxPooledConnections), new StringTraceRecord("MaxOutboundConnectionsPerEndpoint", maxPooledConnections.ToString(CultureInfo.InvariantCulture)), null, this); } connectionState.ModeReader.CloseFromPool(connectionState.CloseTimeout); } else { if (this.pooledConnectionDequeuedCallback == null) { this.pooledConnectionDequeuedCallback = new ItemDequeuedCallback(PooledConnectionDequeuedCallback); } connectionState.ModeReader.StartReading(this.idleTimeout, this.pooledConnectionDequeuedCallback); } } void PooledConnectionDequeuedCallback() { lock (ThisLock) { this.pooledConnectionCount--; DiagnosticUtility.DebugAssert(this.pooledConnectionCount >= 0, "Connection Throttle should never be negative"); } } void OnConnectionAvailable(IConnection connection, ItemDequeuedCallback connectionDequeuedCallback) { ConnectionModeReader modeReader = SetupModeReader(connection, false); if (modeReader != null) { // StartReading() will never throw non-fatal exceptions; // it propagates all exceptions into the onConnectionModeKnown callback, // which is where we need our robust handling modeReader.StartReading(this.channelInitializationTimeout, connectionDequeuedCallback); } else { connectionDequeuedCallback(); } } void OnCachedConnectionModeKnown(ConnectionModeReader modeReader) { OnConnectionModeKnownCore(modeReader, true); } void OnConnectionModeKnown(ConnectionModeReader modeReader) { OnConnectionModeKnownCore(modeReader, false); } void OnConnectionModeKnownCore(ConnectionModeReader modeReader, bool isCached) { lock (ThisLock) { if (isDisposed) return; this.connectionReaders.Remove(modeReader); } bool closeReader = true; try { FramingMode framingMode; try { framingMode = modeReader.GetConnectionMode(); } catch (CommunicationException exception) { TraceEventType eventType = modeReader.Connection.ExceptionEventType; if (DiagnosticUtility.ShouldTrace(eventType)) { DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, eventType); } return; } catch (TimeoutException exception) { if (!isCached) { exception = new TimeoutException(SR.GetString(SR.ChannelInitializationTimeout, this.channelInitializationTimeout), exception); System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(exception); } TraceEventType eventType = modeReader.Connection.ExceptionEventType; if (DiagnosticUtility.ShouldTrace(eventType)) { DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, eventType); } return; } switch (framingMode) { case FramingMode.Duplex: OnDuplexConnection(modeReader.Connection, modeReader.ConnectionDequeuedCallback, modeReader.StreamPosition, modeReader.BufferOffset, modeReader.BufferSize, modeReader.GetRemainingTimeout()); break; case FramingMode.Singleton: OnSingletonConnection(modeReader.Connection, modeReader.ConnectionDequeuedCallback, modeReader.StreamPosition, modeReader.BufferOffset, modeReader.BufferSize, modeReader.GetRemainingTimeout()); break; default: { Exception inner = new InvalidDataException(SR.GetString( SR.FramingModeNotSupported, framingMode)); Exception exception = new ProtocolException(inner.Message, inner); FramingEncodingString.AddFaultString(exception, FramingEncodingString.UnsupportedModeFault); System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(exception); return; } } closeReader = false; } catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { throw; } if (!ExceptionHandler.HandleTransportExceptionHelper(e)) { throw; } // containment -- the reader is aborted, no need for additional containment } finally { if (closeReader) { modeReader.Dispose(); } } } void OnConnectionClosed(InitialServerConnectionReader connectionReader) { lock (ThisLock) { if (isDisposed) return; connectionReaders.Remove(connectionReader); } } void OnSingletonConnection(IConnection connection, ItemDequeuedCallback connectionDequeuedCallback, long streamPosition, int offset, int size, TimeSpan timeout) { if (onSingletonPreambleKnown == null) { onSingletonPreambleKnown = OnSingletonPreambleKnown; } ServerSingletonPreambleConnectionReader singletonPreambleReader = new ServerSingletonPreambleConnectionReader(connection, connectionDequeuedCallback, streamPosition, offset, size, transportSettingsCallback, onConnectionClosed, onSingletonPreambleKnown); lock (ThisLock) { if (isDisposed) { singletonPreambleReader.Dispose(); return; } connectionReaders.Add(singletonPreambleReader); } singletonPreambleReader.StartReading(viaDelegate, timeout); } void OnSingletonPreambleKnown(ServerSingletonPreambleConnectionReader serverSingletonPreambleReader) { lock (ThisLock) { if (isDisposed) { return; } connectionReaders.Remove(serverSingletonPreambleReader); } ISingletonChannelListener singletonChannelListener = singletonPreambleCallback(serverSingletonPreambleReader); DiagnosticUtility.DebugAssert(singletonChannelListener != null, "singletonPreambleCallback must return a listener or send a Fault/throw"); // transfer ownership of the connection from the preamble reader to the message handler TimeoutHelper timeoutHelper = new TimeoutHelper(singletonChannelListener.ReceiveTimeout); IConnection upgradedConnection = serverSingletonPreambleReader.CompletePreamble(timeoutHelper.RemainingTime()); ServerSingletonConnectionReader singletonReader = new ServerSingletonConnectionReader(serverSingletonPreambleReader, upgradedConnection, this); RequestContext requestContext = singletonReader.ReceiveRequest(timeoutHelper.RemainingTime()); singletonChannelListener.ReceiveRequest(requestContext, serverSingletonPreambleReader.ConnectionDequeuedCallback, true); } void OnSessionPreambleKnown(ServerSessionPreambleConnectionReader serverSessionPreambleReader) { lock (ThisLock) { if (isDisposed) { return; } connectionReaders.Remove(serverSessionPreambleReader); } serverSessionPreambleCallback(serverSessionPreambleReader, this); } void OnDuplexConnection(IConnection connection, ItemDequeuedCallback connectionDequeuedCallback, long streamPosition, int offset, int size, TimeSpan timeout) { if (onSessionPreambleKnown == null) { onSessionPreambleKnown = OnSessionPreambleKnown; } ServerSessionPreambleConnectionReader sessionPreambleReader = new ServerSessionPreambleConnectionReader( connection, connectionDequeuedCallback, streamPosition, offset, size, transportSettingsCallback, onConnectionClosed, onSessionPreambleKnown); lock (ThisLock) { if (isDisposed) { sessionPreambleReader.Dispose(); return; } connectionReaders.Add(sessionPreambleReader); } sessionPreambleReader.StartReading(viaDelegate, timeout); } public void StartDemuxing() { StartDemuxing(null); } public void StartDemuxing(OnViaDelegate viaDelegate) { this.viaDelegate = viaDelegate; acceptor.StartAccepting(); } class ReuseConnectionState { ConnectionModeReader modeReader; TimeSpan closeTimeout; public ReuseConnectionState(ConnectionModeReader modeReader, TimeSpan closeTimeout) { this.modeReader = modeReader; this.closeTimeout = closeTimeout; } public ConnectionModeReader ModeReader { get { return this.modeReader; } } public TimeSpan CloseTimeout { get { return this.closeTimeout; } } } } } // 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
- ActivationService.cs
- EditorZone.cs
- XmlAttributes.cs
- QuaternionRotation3D.cs
- EdmScalarPropertyAttribute.cs
- SchemaObjectWriter.cs
- DSACryptoServiceProvider.cs
- PointCollectionConverter.cs
- ControlCollection.cs
- DBPropSet.cs
- NotifyCollectionChangedEventArgs.cs
- SafeWaitHandle.cs
- MDIWindowDialog.cs
- DoubleAnimationBase.cs
- WebConfigurationHostFileChange.cs
- SafeRegistryKey.cs
- HtmlShimManager.cs
- ConversionContext.cs
- ContextMarshalException.cs
- RefreshEventArgs.cs
- NamedElement.cs
- EntityContainerEmitter.cs
- ExtendedProtectionPolicyTypeConverter.cs
- XPathNodeInfoAtom.cs
- XmlSchemaProviderAttribute.cs
- NextPreviousPagerField.cs
- RuntimeHandles.cs
- TextCompositionManager.cs
- BoundField.cs
- SqlInfoMessageEvent.cs
- PersistChildrenAttribute.cs
- RenderTargetBitmap.cs
- ApplicationProxyInternal.cs
- RadialGradientBrush.cs
- Matrix.cs
- SolidBrush.cs
- StrokeDescriptor.cs
- ProcessRequestArgs.cs
- PropertyRef.cs
- StylusButton.cs
- ScrollChrome.cs
- SafeNativeMethods.cs
- DelayLoadType.cs
- DataBindingCollectionEditor.cs
- ForEachDesigner.xaml.cs
- TextBoxAutomationPeer.cs
- ConnectionStringsSection.cs
- SqlFactory.cs
- FormViewRow.cs
- FieldInfo.cs
- SchemaMapping.cs
- IImplicitResourceProvider.cs
- RegionData.cs
- StandardToolWindows.cs
- PolicyDesigner.cs
- ScriptMethodAttribute.cs
- serverconfig.cs
- SeekStoryboard.cs
- ActivityDesignerResources.cs
- ProfileManager.cs
- Receive.cs
- _CookieModule.cs
- WebPartTransformerCollection.cs
- FlowDocument.cs
- ConsoleCancelEventArgs.cs
- ExpressionConverter.cs
- QueryMath.cs
- CompilationUnit.cs
- SqlConnectionPoolProviderInfo.cs
- CalendarDataBindingHandler.cs
- XmlReflectionMember.cs
- SqlDataSource.cs
- DataGridViewRowsRemovedEventArgs.cs
- ValidationService.cs
- TriState.cs
- ApplicationServicesHostFactory.cs
- Viewport3DAutomationPeer.cs
- NodeInfo.cs
- SystemIcmpV4Statistics.cs
- ProfileGroupSettings.cs
- DSACryptoServiceProvider.cs
- SAPICategories.cs
- FileDialogCustomPlacesCollection.cs
- SqlColumnizer.cs
- CellRelation.cs
- ActiveXContainer.cs
- StyleSheetDesigner.cs
- SkewTransform.cs
- PartialList.cs
- Vector3DConverter.cs
- loginstatus.cs
- TextRenderer.cs
- LayoutEditorPart.cs
- GenericUI.cs
- SqlDataReader.cs
- Function.cs
- httpserverutility.cs
- EditorBrowsableAttribute.cs
- Pkcs7Recipient.cs
- DynamicRouteExpression.cs