Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / TcpChannelListener.cs / 1 / TcpChannelListener.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.ServiceModel; using System.Diagnostics; using System.IO; using System.Net; using System.Net.Sockets; using System.Runtime.Serialization; using System.ServiceModel.Diagnostics; using System.Text; using System.Threading; using System.ServiceModel.Description; static class TcpUri { public const int DefaultPort = 808; } abstract class TcpChannelListener: TcpChannelListener, IChannelListener where TChannel : class, IChannel where TChannelAcceptor : ChannelAcceptor { protected TcpChannelListener(TcpTransportBindingElement bindingElement, BindingContext context) : base(bindingElement, context) { } protected abstract TChannelAcceptor ChannelAcceptor { get; } protected override void OnOpen(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); base.OnOpen(timeoutHelper.RemainingTime()); ChannelAcceptor.Open(timeoutHelper.RemainingTime()); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { return new ChainedOpenAsyncResult(timeout, callback, state, base.OnBeginOpen, base.OnEndOpen, ChannelAcceptor); } protected override void OnEndOpen(IAsyncResult result) { ChainedOpenAsyncResult.End(result); } protected override void OnClose(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); ChannelAcceptor.Close(timeoutHelper.RemainingTime()); base.OnClose(timeoutHelper.RemainingTime()); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { return new ChainedCloseAsyncResult(timeout, callback, state, base.OnBeginClose, base.OnEndClose, ChannelAcceptor); } protected override void OnEndClose(IAsyncResult result) { ChainedCloseAsyncResult.End(result); } protected override void OnAbort() { this.ChannelAcceptor.Abort(); base.OnAbort(); } public TChannel AcceptChannel() { return this.AcceptChannel(this.DefaultReceiveTimeout); } public IAsyncResult BeginAcceptChannel(AsyncCallback callback, object state) { return this.BeginAcceptChannel(this.DefaultReceiveTimeout, callback, state); } public TChannel AcceptChannel(TimeSpan timeout) { base.ThrowIfNotOpened(); return ChannelAcceptor.AcceptChannel(timeout); } public IAsyncResult BeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state) { base.ThrowIfNotOpened(); return ChannelAcceptor.BeginAcceptChannel(timeout, callback, state); } public TChannel EndAcceptChannel(IAsyncResult result) { base.ThrowPending(); return ChannelAcceptor.EndAcceptChannel(result); } protected override bool OnWaitForChannel(TimeSpan timeout) { return ChannelAcceptor.WaitForChannel(timeout); } protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state) { return ChannelAcceptor.BeginWaitForChannel(timeout, callback, state); } protected override bool OnEndWaitForChannel(IAsyncResult result) { return ChannelAcceptor.EndWaitForChannel(result); } } class TcpReplyChannelListener : TcpChannelListener , ISingletonChannelListener { ReplyChannelAcceptor replyAcceptor; public TcpReplyChannelListener(TcpTransportBindingElement bindingElement, BindingContext context) : base(bindingElement, context) { this.replyAcceptor = new ConnectionOrientedTransportReplyChannelAcceptor(this); } protected override ReplyChannelAcceptor ChannelAcceptor { get { return this.replyAcceptor; } } TimeSpan ISingletonChannelListener.ReceiveTimeout { get { return this.InternalReceiveTimeout; } } void ISingletonChannelListener.ReceiveRequest(RequestContext requestContext, ItemDequeuedCallback callback, bool canDispatchOnThisThread) { if (DiagnosticUtility.ShouldTraceVerbose) { TraceUtility.TraceEvent(TraceEventType.Verbose, MessageReceivedTraceCode, requestContext.RequestMessage); } replyAcceptor.Enqueue(requestContext, callback, canDispatchOnThisThread); } } class TcpDuplexChannelListener : TcpChannelListener > , ISessionPreambleHandler { InputQueueChannelAcceptor duplexAcceptor; public TcpDuplexChannelListener(TcpTransportBindingElement bindingElement, BindingContext context) : base(bindingElement, context) { this.duplexAcceptor = new InputQueueChannelAcceptor (this); } protected override InputQueueChannelAcceptor ChannelAcceptor { get { return this.duplexAcceptor; } } void ISessionPreambleHandler.HandleServerSessionPreamble(ServerSessionPreambleConnectionReader preambleReader, ConnectionDemuxer connectionDemuxer) { IDuplexSessionChannel channel = preambleReader.CreateDuplexSessionChannel( this, new EndpointAddress(this.Uri), ExposeConnectionProperty, connectionDemuxer); duplexAcceptor.EnqueueAndDispatch(channel, preambleReader.ConnectionDequeuedCallback); } } abstract class TcpChannelListener : ConnectionOrientedTransportChannelListener { bool teredoEnabled; int listenBacklog; bool portSharingEnabled; // "port 0" support Socket ipv4ListenSocket; Socket ipv6ListenSocket; static Random randomPortGenerator = new Random(AppDomain.CurrentDomain.GetHashCode() | Environment.TickCount); static UriPrefixTable transportManagerTable = new UriPrefixTable (true); protected TcpChannelListener(TcpTransportBindingElement bindingElement, BindingContext context) : base(bindingElement, context) { this.listenBacklog = bindingElement.ListenBacklog; this.portSharingEnabled = bindingElement.PortSharingEnabled; this.teredoEnabled = bindingElement.TeredoEnabled; SetIdleTimeout(bindingElement.ConnectionPoolSettings.IdleTimeout); SetMaxPooledConnections(bindingElement.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint); // for exclusive mode, we have "port 0" functionality if (!bindingElement.PortSharingEnabled && context.ListenUriMode == ListenUriMode.Unique) { SetupUniquePort(context); } } public bool PortSharingEnabled { get { return this.portSharingEnabled; } } public bool TeredoEnabled { get { return this.teredoEnabled; } } public int ListenBacklog { get { return this.listenBacklog; } } internal Socket GetListenSocket(UriHostNameType ipHostNameType) { if (ipHostNameType == UriHostNameType.IPv4) { Socket result = this.ipv4ListenSocket; this.ipv4ListenSocket = null; return result; } else // UriHostNameType.IPv6 { Socket result = this.ipv6ListenSocket; this.ipv6ListenSocket = null; return result; } } public override string Scheme { get { return Uri.UriSchemeNetTcp; } } internal override TraceCode MessageReceivedTraceCode { get { return TraceCode.TcpChannelMessageReceived; } } internal override TraceCode MessageReceiveFailedTraceCode { get { return TraceCode.TcpChannelMessageReceiveFailed; } } internal static UriPrefixTable StaticTransportManagerTable { get { return transportManagerTable; } } internal override UriPrefixTable TransportManagerTable { get { return transportManagerTable; } } internal static void FixIpv6Hostname(UriBuilder uriBuilder, Uri originalUri) { if (originalUri.HostNameType == UriHostNameType.IPv6) { string ipv6Host = originalUri.DnsSafeHost; uriBuilder.Host = string.Concat("[", ipv6Host, "]"); } } internal override ITransportManagerRegistration CreateTransportManagerRegistration() { Uri listenUri = this.BaseUri; if (!this.PortSharingEnabled) { UriBuilder builder = new UriBuilder(listenUri.Scheme, listenUri.Host, listenUri.Port); TcpChannelListener.FixIpv6Hostname(builder, listenUri); listenUri = builder.Uri; } return this.CreateTransportManagerRegistration(listenUri); } internal override ITransportManagerRegistration CreateTransportManagerRegistration(Uri listenUri) { if (this.PortSharingEnabled) { return new SharedTcpTransportManager(listenUri, this); } else { return new ExclusiveTcpTransportManagerRegistration(listenUri, this); } } Socket ListenAndBind(IPEndPoint localEndpoint) { Socket result = new Socket(localEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { result.Bind(localEndpoint); } catch (SocketException socketException) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( SocketConnectionListener.ConvertListenException(socketException, localEndpoint)); } return result; } void SetupUniquePort(BindingContext context) { IPAddress ipv4Address = IPAddress.Any; IPAddress ipv6Address = IPAddress.IPv6Any; bool useIPv4 = Socket.SupportsIPv4; bool useIPv6 = Socket.OSSupportsIPv6; if (this.Uri.HostNameType == UriHostNameType.IPv6) { useIPv4 = false; ipv6Address = IPAddress.Parse(this.Uri.DnsSafeHost); } else if (this.Uri.HostNameType == UriHostNameType.IPv4) { useIPv6 = false; ipv4Address = IPAddress.Parse(this.Uri.DnsSafeHost); } if (!useIPv4 && !useIPv6) { if (this.Uri.HostNameType == UriHostNameType.IPv6) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument( "context", SR.GetString(SR.TcpV6AddressInvalid, this.Uri)); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument( "context", SR.GetString(SR.TcpV4AddressInvalid, this.Uri)); } } UriBuilder uriBuilder = new UriBuilder(context.ListenUriBaseAddress); int port = -1; if (!useIPv6) // we just want IPv4 { this.ipv4ListenSocket = ListenAndBind(new IPEndPoint(ipv4Address, 0)); port = ((IPEndPoint)this.ipv4ListenSocket.LocalEndPoint).Port; } else if (!useIPv4) // or just IPv6 { this.ipv6ListenSocket = ListenAndBind(new IPEndPoint(ipv6Address, 0)); port = ((IPEndPoint)this.ipv6ListenSocket.LocalEndPoint).Port; } else { // We need both IPv4 and IPv6 on the same port. We can't atomically bind for IPv4 and IPv6, // so we try 10 times, which even with a 50% failure rate will statistically succeed 99.9% of the time. // // We look in the range of 49152-65534 for Vista default behavior parity. // http://www.iana.org/assignments/port-numbers // // We also grab the 10 random numbers in a row to reduce collisions between multiple people somehow // colliding on the same seed. const int retries = 10; const int lowWatermark = 49152; const int highWatermark = 65535; int[] portNumbers = new int[retries]; lock (randomPortGenerator) { for (int i = 0; i < retries; i++) { portNumbers[i] = randomPortGenerator.Next(lowWatermark, highWatermark); } } for (int i = 0; i < retries; i++) { port = portNumbers[i]; try { this.ipv4ListenSocket = ListenAndBind(new IPEndPoint(ipv4Address, port)); this.ipv6ListenSocket = ListenAndBind(new IPEndPoint(ipv6Address, port)); break; } catch (AddressAlreadyInUseException e) { if (DiagnosticUtility.ShouldTraceInformation) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } if (this.ipv4ListenSocket != null) { this.ipv4ListenSocket.Close(); this.ipv4ListenSocket = null; } this.ipv6ListenSocket = null; } } if (ipv4ListenSocket == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new AddressAlreadyInUseException(SR.GetString(SR.UniquePortNotAvailable))); } } uriBuilder.Port = port; base.SetUri(uriBuilder.Uri, context.ListenUriRelativeAddress); } } } // 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
- CommaDelimitedStringAttributeCollectionConverter.cs
- OleDbCommandBuilder.cs
- SQLInt32.cs
- ChainOfResponsibility.cs
- ClientConfigurationSystem.cs
- SizeAnimation.cs
- HtmlTableRow.cs
- Freezable.cs
- XmlKeywords.cs
- EdmComplexPropertyAttribute.cs
- MailMessageEventArgs.cs
- SpotLight.cs
- CommandEventArgs.cs
- TimeoutException.cs
- PublisherMembershipCondition.cs
- OracleParameterBinding.cs
- AutoGeneratedField.cs
- ExtendedProtectionPolicyElement.cs
- BooleanStorage.cs
- StrongName.cs
- CustomValidator.cs
- DragDeltaEventArgs.cs
- EdmFunctionAttribute.cs
- hebrewshape.cs
- DXD.cs
- UriTemplateVariablePathSegment.cs
- Normalization.cs
- ProcessHostFactoryHelper.cs
- MaskedTextBox.cs
- BulletedListEventArgs.cs
- safelink.cs
- TransformCryptoHandle.cs
- XmlCDATASection.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- DataPagerCommandEventArgs.cs
- PropertyConverter.cs
- QEncodedStream.cs
- SQLDoubleStorage.cs
- OdbcDataAdapter.cs
- WpfSharedBamlSchemaContext.cs
- DbTypeMap.cs
- SqlSelectStatement.cs
- ProxyManager.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- RemotingException.cs
- _UncName.cs
- FrameworkElementFactory.cs
- GradientBrush.cs
- ContentPlaceHolder.cs
- HelpKeywordAttribute.cs
- PriorityQueue.cs
- PiiTraceSource.cs
- HtmlUtf8RawTextWriter.cs
- Triplet.cs
- SystemShuttingDownException.cs
- OracleString.cs
- ListViewItem.cs
- Identity.cs
- PointHitTestParameters.cs
- ContextStack.cs
- JpegBitmapEncoder.cs
- SerialPort.cs
- MenuItemBinding.cs
- WebPartRestoreVerb.cs
- DataContractJsonSerializerOperationBehavior.cs
- HttpCacheVaryByContentEncodings.cs
- DrawingGroup.cs
- BitmapEffectGroup.cs
- ThreadStaticAttribute.cs
- NullableConverter.cs
- XmlDataCollection.cs
- StaticTextPointer.cs
- BehaviorEditorPart.cs
- MethodRental.cs
- MultiPropertyDescriptorGridEntry.cs
- ThrowHelper.cs
- TcpTransportSecurity.cs
- HtmlImage.cs
- StateItem.cs
- HtmlElementErrorEventArgs.cs
- RelationshipNavigation.cs
- SecurityUtils.cs
- ErrorStyle.cs
- AppDomainManager.cs
- PolicyException.cs
- ActivityCodeDomSerializationManager.cs
- CatalogZoneDesigner.cs
- TimeoutConverter.cs
- RequestCachingSection.cs
- WindowsListViewSubItem.cs
- XPathDocumentIterator.cs
- Walker.cs
- CounterSample.cs
- ItemMap.cs
- CounterCreationDataCollection.cs
- DataGridViewMethods.cs
- Soap.cs
- BaseCollection.cs
- CompoundFileStreamReference.cs
- TimeSpanSecondsOrInfiniteConverter.cs