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
- DataGridViewDataErrorEventArgs.cs
- FixedTextContainer.cs
- Point3DAnimation.cs
- SchemaImporter.cs
- SchemaElementLookUpTableEnumerator.cs
- CollectionMarkupSerializer.cs
- HttpModuleAction.cs
- GridProviderWrapper.cs
- XmlBinaryReader.cs
- MILUtilities.cs
- ContractMapping.cs
- ToolboxCategoryItems.cs
- Exceptions.cs
- StatusStrip.cs
- Compiler.cs
- TemplateKey.cs
- Block.cs
- GenerateTemporaryTargetAssembly.cs
- designeractionlistschangedeventargs.cs
- DocobjHost.cs
- CategoryValueConverter.cs
- NominalTypeEliminator.cs
- Pts.cs
- SessionParameter.cs
- MissingSatelliteAssemblyException.cs
- SqlDataSourceQueryEditorForm.cs
- ClientFormsAuthenticationCredentials.cs
- CodeDomLoader.cs
- PersonalizationDictionary.cs
- KeyBinding.cs
- ListViewPagedDataSource.cs
- InlineCollection.cs
- Queue.cs
- SafeCryptoHandles.cs
- CodeObject.cs
- SamlAuthenticationClaimResource.cs
- LayoutDump.cs
- DynamicValidatorEventArgs.cs
- PerformanceCountersElement.cs
- SByteConverter.cs
- PagesSection.cs
- HtmlTableRow.cs
- ServiceRouteHandler.cs
- WindowsListViewItem.cs
- RawTextInputReport.cs
- SystemUnicastIPAddressInformation.cs
- MergeLocalizationDirectives.cs
- BindingCollection.cs
- Tokenizer.cs
- Tablet.cs
- DataBindEngine.cs
- ResourceKey.cs
- SecurityContext.cs
- TemplateKeyConverter.cs
- CodeArrayIndexerExpression.cs
- OdbcDataReader.cs
- EtwTrace.cs
- FrameworkName.cs
- PassportAuthenticationModule.cs
- WindowsRichEditRange.cs
- DirectionalLight.cs
- IBuiltInEvidence.cs
- ObjectDisposedException.cs
- HttpApplicationStateBase.cs
- WindowsGraphicsCacheManager.cs
- SimpleExpression.cs
- GenericsInstances.cs
- AncillaryOps.cs
- CompositeFontFamily.cs
- PrinterUnitConvert.cs
- IResourceProvider.cs
- BindMarkupExtensionSerializer.cs
- XmlSchemaType.cs
- externdll.cs
- ObjectManager.cs
- errorpatternmatcher.cs
- IPCCacheManager.cs
- ContentType.cs
- CodePropertyReferenceExpression.cs
- LayoutSettings.cs
- ZipIOCentralDirectoryFileHeader.cs
- DbConnectionPoolOptions.cs
- Size3DConverter.cs
- XpsFilter.cs
- RotateTransform.cs
- CookieProtection.cs
- ToolStripSeparatorRenderEventArgs.cs
- TemplateBindingExtension.cs
- MachinePropertyVariants.cs
- Substitution.cs
- InstanceLockTracking.cs
- DataGridRowHeaderAutomationPeer.cs
- KeyValueConfigurationCollection.cs
- ProfileProvider.cs
- X509CertificateStore.cs
- ModelTreeManager.cs
- MetadataPropertyCollection.cs
- RawStylusInput.cs
- DragStartedEventArgs.cs
- DBAsyncResult.cs