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
- MemberDescriptor.cs
- IndicCharClassifier.cs
- NamedPipeHostedTransportConfiguration.cs
- CodeStatementCollection.cs
- ProgressBar.cs
- DateBoldEvent.cs
- XmlAggregates.cs
- VirtualDirectoryMappingCollection.cs
- OracleInfoMessageEventArgs.cs
- ValidationManager.cs
- DynamicControl.cs
- indexingfiltermarshaler.cs
- UrlPath.cs
- UserInitiatedNavigationPermission.cs
- XmlFormatWriterGenerator.cs
- ListCollectionView.cs
- safemediahandle.cs
- DecoderFallback.cs
- MainMenu.cs
- SecurityContextTokenCache.cs
- XmlSerializer.cs
- SkinIDTypeConverter.cs
- TextRangeEditTables.cs
- ArgumentException.cs
- Button.cs
- ConnectivityStatus.cs
- SelectorItemAutomationPeer.cs
- Operator.cs
- NoneExcludedImageIndexConverter.cs
- IntegerValidator.cs
- ExtensionFile.cs
- CodeCompileUnit.cs
- PeerObject.cs
- AssertFilter.cs
- ProfileService.cs
- BackStopAuthenticationModule.cs
- XmlRawWriter.cs
- ConnectionPoolManager.cs
- SspiSecurityToken.cs
- StorageMappingItemLoader.cs
- ClaimTypes.cs
- MeasurementDCInfo.cs
- AutomationElementCollection.cs
- HMACSHA512.cs
- LinqDataSourceEditData.cs
- Timeline.cs
- GetUserPreferenceRequest.cs
- ExtendedPropertyInfo.cs
- ImageAutomationPeer.cs
- XmlSchemaAttribute.cs
- SeekStoryboard.cs
- ServiceActivationException.cs
- FormViewPageEventArgs.cs
- TextStore.cs
- TransactionsSectionGroup.cs
- selecteditemcollection.cs
- Rules.cs
- cache.cs
- MatrixAnimationUsingKeyFrames.cs
- UIElementHelper.cs
- ButtonDesigner.cs
- SmtpReplyReader.cs
- XslNumber.cs
- SqlProviderManifest.cs
- Viewport2DVisual3D.cs
- ImageAttributes.cs
- DrawItemEvent.cs
- TextPenaltyModule.cs
- RsaEndpointIdentity.cs
- AvtEvent.cs
- ColumnPropertiesGroup.cs
- TableNameAttribute.cs
- InkCanvasFeedbackAdorner.cs
- CatalogZone.cs
- XdrBuilder.cs
- WebBrowser.cs
- NextPreviousPagerField.cs
- CacheMemory.cs
- Context.cs
- ListViewCommandEventArgs.cs
- XmlSerializerAssemblyAttribute.cs
- DbParameterCollection.cs
- IntSecurity.cs
- FormViewInsertEventArgs.cs
- StorageSetMapping.cs
- QuarticEase.cs
- GPPOINT.cs
- UrlAuthorizationModule.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- DataGridViewRow.cs
- ImageAttributes.cs
- NetworkInterface.cs
- ChildChangedEventArgs.cs
- ProtocolsConfigurationEntry.cs
- TextFindEngine.cs
- SharedDp.cs
- SqlDataSourceCache.cs
- LoginUtil.cs
- ViewCellRelation.cs
- SQLBoolean.cs