Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Discovery / System / ServiceModel / Channels / UdpUtility.cs / 1484997 / UdpUtility.cs
//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------- namespace System.ServiceModel.Channels { using System; using System.Collections.Generic; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime; using System.ServiceModel.Discovery; using System.Xml; static class UdpUtility { public static Uri AppendRelativePath(Uri basepath, string relativePath) { // Ensure that baseAddress Path does end with a slash if we have a relative address if (!string.IsNullOrEmpty(relativePath)) { if (!basepath.AbsolutePath.EndsWith("/", StringComparison.Ordinal)) { UriBuilder uriBuilder = new UriBuilder(basepath); uriBuilder.Path = uriBuilder.Path + "/"; basepath = uriBuilder.Uri; } basepath = new Uri(basepath, relativePath); } return basepath; } public static MessageEncoderFactory GetEncoder(BindingContext context) { MessageEncodingBindingElement messageEncoderBindingElement = context.BindingParameters.Remove(); MessageEncoderFactory factory = null; if (messageEncoderBindingElement != null) { factory = messageEncoderBindingElement.CreateMessageEncoderFactory(); } else { factory = UdpConstants.Defaults.MessageEncoderFactory; } if (factory.MessageVersion.Addressing == AddressingVersion.None) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.TransportRequiresAddressingOnEncoder(factory.MessageVersion.Addressing.ToString()))); } return factory; } public static void CheckSocketSupport(out bool ipV4Supported, out bool ipV6Supported) { ipV4Supported = Socket.OSSupportsIPv4; ipV6Supported = Socket.OSSupportsIPv6; ThrowIfNoSocketSupport(ipV4Supported, ipV6Supported); } public static int GetLoopbackInterfaceIndex(NetworkInterface adapter, bool ipv4) { Fx.Assert(adapter != null, "adapter can't be null"); Fx.Assert(adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback, "adapter type must be loopback adapter"); if (ipv4) { return NetworkInterface.LoopbackInterfaceIndex; } else { IPInterfaceProperties properties = adapter.GetIPProperties(); IPv6InterfaceProperties ipv6Properties = properties.GetIPv6Properties(); return ipv6Properties.Index; } } public static UdpSocket CreateUnicastListenSocket(IPAddress ipAddress, ref int port, int receiveBufferSize, int timeToLive) { return CreateListenSocket(ipAddress, ref port, receiveBufferSize, timeToLive, UdpConstants.Defaults.InterfaceIndex, false, false); } public static UdpSocket CreateListenSocket(IPAddress ipAddress, ref int port, int receiveBufferSize, int timeToLive, int interfaceIndex, bool allowMulticastLoopback, bool isLoopbackAdapter) { bool isIPv6 = (ipAddress.AddressFamily == AddressFamily.InterNetworkV6); Socket socket = null; bool listenMulticast = IsMulticastAddress(ipAddress); IPEndPoint localEndpoint; if (listenMulticast) { IPAddress bindAddress = (isIPv6 ? IPAddress.IPv6Any : IPAddress.Any); localEndpoint = new IPEndPoint(bindAddress, port); } else { localEndpoint = new IPEndPoint(ipAddress, port); } socket = new Socket(localEndpoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); SetPreBindSocketOptions(socket, listenMulticast, receiveBufferSize, (short)timeToLive, interfaceIndex, allowMulticastLoopback, isLoopbackAdapter); BindSocket(socket, localEndpoint); SetPostBindSocketOptions(socket, listenMulticast, ipAddress, interfaceIndex); if (port == 0) { //update the port to be the actual one the socket is bound to... port = ((IPEndPoint)socket.LocalEndPoint).Port; } return new UdpSocket(socket, interfaceIndex); } //returns the port number used... public static int CreateListenSocketsOnUniquePort(IPAddress ipv4Address, IPAddress ipv6Address, int receiveBufferSize, int timeToLive, out UdpSocket ipv4Socket, out UdpSocket ipv6Socket) { // We need both IPv4 and IPv6 on the same port. We can't atomicly 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; ipv4Socket = null; ipv6Socket = null; int[] portNumbers = new int[retries]; Random randomNumberGenerator = new Random(AppDomain.CurrentDomain.GetHashCode() | Environment.TickCount); for (int i = 0; i < retries; i++) { portNumbers[i] = randomNumberGenerator.Next(lowWatermark, highWatermark); } int port = -1; for (int i = 0; i < retries; i++) { port = portNumbers[i]; try { ipv4Socket = UdpUtility.CreateUnicastListenSocket(ipv4Address, ref port, receiveBufferSize, timeToLive); ipv6Socket = UdpUtility.CreateUnicastListenSocket(ipv6Address, ref port, receiveBufferSize, timeToLive); break; } catch (AddressAlreadyInUseException) { if (ipv4Socket != null) { ipv4Socket.Close(); ipv4Socket = null; } ipv6Socket = null; } catch (AddressAccessDeniedException) { if (ipv4Socket != null) { ipv4Socket.Close(); ipv4Socket = null; } ipv6Socket = null; } } if (ipv4Socket == null) { throw FxTrace.Exception.AsError(new AddressAlreadyInUseException(SR.UniquePortNotAvailable)); } Fx.Assert(ipv4Socket != null, "An exception should have been thrown if the ipv4Socket socket is null"); Fx.Assert(ipv6Socket != null, "An exception should have been thrown if the ipv6Socket socket is null"); Fx.Assert(port > 0, "The port number should have been greater than 0. Actual value was " + port); return port; } public static void ThrowIfNoSocketSupport() { ThrowIfNoSocketSupport(Socket.OSSupportsIPv4, Socket.OSSupportsIPv6); } static void ThrowIfNoSocketSupport(bool ipv4Supported, bool ipv6Supported) { if (!ipv4Supported && !ipv6Supported) { throw FxTrace.Exception.AsError(new NotSupportedException(SR.IPv4OrIPv6Required)); } } public static NetworkInterface[] GetMulticastInterfaces(string multicastInterfaceIdentifier) { NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); Fx.Assert(adapters != null, "NetworkInterface.GetAllNetworkInterfaces() should never return null"); NetworkInterface[] results = null; if (string.IsNullOrEmpty(multicastInterfaceIdentifier)) //find all supported NICs { List supportedAdapters = new List (); for (int i = 0; i < adapters.Length; i++) { NetworkInterface adapter = adapters[i]; if (IsSuitableForMulticast(adapter)) { supportedAdapters.Add(adapter); } } //OK to return an empty array in this case, the calling code will throw an exception //with better context information that what we have here... results = supportedAdapters.ToArray(); } else //Only looking for one interface... { for (int i = 0; i < adapters.Length; i++) { NetworkInterface adapter = adapters[i]; if (string.Equals(adapter.Id, multicastInterfaceIdentifier, StringComparison.OrdinalIgnoreCase)) { if (IsSuitableForMulticast(adapter)) { OperationalStatus status = adapter.OperationalStatus; if (status != OperationalStatus.Up) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.UdpAdapterSpecifiedNotConnected(multicastInterfaceIdentifier, status))); } results = new NetworkInterface[] { adapter }; break; } else { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.UdpAdapterSpecifiedNotSuitableForMulticast(multicastInterfaceIdentifier))); } } } if (results == null || results.Length == 0) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.UdpInterfaceIndexMatchNotFound(multicastInterfaceIdentifier))); } } Fx.Assert(results != null, "A null list of network adapters should never be returned. It should either be an empty list or an exception should have been thrown."); return results; } public static bool IsMulticastAddress(IPAddress address) { if (address.AddressFamily == AddressFamily.InterNetwork) { // 224.0.0.0 through 239.255.255.255 byte[] addressBytes = address.GetAddressBytes(); return ((addressBytes[0] & 0xE0) == 0xE0); } else { return address.IsIPv6Multicast; } } public static bool IsSuitableForMulticast(NetworkInterface networkInterface) { bool result = false; if (networkInterface.SupportsMulticast && !networkInterface.IsReceiveOnly && networkInterface.NetworkInterfaceType != NetworkInterfaceType.Tunnel && networkInterface.NetworkInterfaceType != NetworkInterfaceType.Unknown) { result = true; } return result; } public static bool IsSupportedHostNameType(UriHostNameType hostNameType) { return hostNameType == UriHostNameType.Dns || hostNameType == UriHostNameType.IPv4 || hostNameType == UriHostNameType.IPv6; } public static void ValidateBufferBounds(byte[] buffer, int offset, int size) { if (buffer == null) { throw FxTrace.Exception.ArgumentNull("buffer"); } ValidateBufferBounds(buffer.Length, offset, size); } public static void ValidateBufferBounds(int bufferSize, int offset, int size) { if (offset < 0) { throw FxTrace.Exception.ArgumentOutOfRange("offset", offset, SR.ValueMustBeNonNegative(offset)); } if (offset > bufferSize) { throw FxTrace.Exception.ArgumentOutOfRange("offset", offset, SR.OffsetExceedsBufferSize(bufferSize)); } if (size <= 0) { throw FxTrace.Exception.ArgumentOutOfRange("size", size, SR.ValueMustBePositive); } int remainingBufferSpace = bufferSize - offset; if (size > remainingBufferSpace) { throw FxTrace.Exception.ArgumentOutOfRange("size", size, SR.SizeExceedsRemainingBufferSpace(remainingBufferSpace)); } } public static Exception WrapAsyncException(Exception ex) { if (ex is TimeoutException) { return new TimeoutException(SR.AsynchronousExceptionOccurred, ex); } else if (ex is AddressAlreadyInUseException) { return new AddressAlreadyInUseException(SR.AsynchronousExceptionOccurred, ex); } else if (ex is AddressAccessDeniedException) { return new AddressAccessDeniedException(SR.AsynchronousExceptionOccurred, ex); } else if (ex is EndpointNotFoundException) { return new EndpointNotFoundException(SR.AsynchronousExceptionOccurred, ex); } else if (ex is XmlException) { return new XmlException(SR.AsynchronousExceptionOccurred, ex); } else if (ex is CommunicationException) { return new CommunicationException(SR.AsynchronousExceptionOccurred, ex); } else { return ex; } } static void BindSocket(Socket socket, IPEndPoint localEndpoint) { try { socket.Bind(localEndpoint); } catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.AddressAlreadyInUse) { throw FxTrace.Exception.AsError(new AddressAlreadyInUseException(SR.SocketAddressInUse(localEndpoint.ToString()), ex)); } else if (ex.SocketErrorCode == SocketError.AccessDenied) { throw FxTrace.Exception.AsError(new AddressAccessDeniedException(SR.SocketAddressAccessDenied(localEndpoint.ToString()), ex)); } else { throw; } } } static void SetPreBindSocketOptions(Socket socket, bool listenMulticast, int receiveBufferSize, short timeToLive, int interfaceIndex, bool allowMulticastLoopback, bool isLoopbackAdapter) { bool isIPv4 = socket.AddressFamily == AddressFamily.InterNetwork; SocketOptionLevel ipOptionLevel = (isIPv4 ? ipOptionLevel = SocketOptionLevel.IP: ipOptionLevel = SocketOptionLevel.IPv6); //sets only the unicast TTL socket.Ttl = timeToLive; //set send related multicast options even if not listening multicast, //we might be sending multicast (e.g. client side or due to manual addressing on server). socket.SetSocketOption(ipOptionLevel, SocketOptionName.MulticastTimeToLive, timeToLive); if (interfaceIndex != UdpConstants.Defaults.InterfaceIndex) { int index = (isIPv4 ? IPAddress.HostToNetworkOrder(interfaceIndex) : interfaceIndex); //sets the outbound interface index socket.SetSocketOption(ipOptionLevel, SocketOptionName.MulticastInterface, index); } if (listenMulticast) { //don't set this socket option if the socket is bound to the //loopback adapter because it will throw an argument exception. if (!isLoopbackAdapter) { socket.SetSocketOption(ipOptionLevel, SocketOptionName.MulticastLoopback, allowMulticastLoopback); } socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); } else { socket.ExclusiveAddressUse = true; } if (receiveBufferSize >= 0) { socket.ReceiveBufferSize = receiveBufferSize; } } static void SetPostBindSocketOptions(Socket socket, bool listenMulticast, IPAddress ipAddress, int interfaceIndex) { bool isIPv6 = socket.AddressFamily == AddressFamily.InterNetworkV6; if (listenMulticast) { //Win2k3 requires that the joining of the multicast group be after the socket is bound (not true on Vista). if (isIPv6) { IPv6MulticastOption multicastGroup = (interfaceIndex == UdpConstants.Defaults.InterfaceIndex ? new IPv6MulticastOption(ipAddress) : new IPv6MulticastOption(ipAddress, interfaceIndex)); socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, multicastGroup); } else { MulticastOption multicastGroup = (interfaceIndex == UdpConstants.Defaults.InterfaceIndex ? new MulticastOption(ipAddress) : new MulticastOption(ipAddress, interfaceIndex)); socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastGroup); } } } public static bool TryGetSocketError(Exception ex, out SocketError error) { error = SocketError.SocketError; while (ex != null) { SocketException socketException = ex as SocketException; if (socketException != null) { error = socketException.SocketErrorCode; return true; } ex = ex.InnerException; } return false; } public static Message DecodeMessage(DuplicateMessageDetector duplicateDetector, MessageEncoder encoder, BufferManager bufferManager, ArraySegment data, IPEndPoint remoteEndPoint, int interfaceIndex, bool ignoreSerializationException, out string messageHash) { Fx.Assert(data != null, "data can't be null"); Fx.Assert(remoteEndPoint != null, "remoteEndPoint can't be null"); Fx.Assert(encoder != null, "encoder can't be null"); Fx.Assert(bufferManager != null, "bufferManager can't be null"); Message message = null; messageHash = null; if (duplicateDetector == null || !duplicateDetector.IsDuplicate(data, out messageHash)) { try { message = encoder.ReadMessage(data, bufferManager); } catch (XmlException error) { // Don't throw serialization exceptions when the channel supports Multicast if (!ignoreSerializationException) { throw; } FxTrace.Exception.AsWarning(error); } if (message != null) { message.Properties.Add(RemoteEndpointMessageProperty.Name, new RemoteEndpointMessageProperty(remoteEndPoint.Address.ToString(), remoteEndPoint.Port)); UdpMessageProperty udpMessageProperty = new UdpMessageProperty(interfaceIndex); udpMessageProperty.AddTo(message); } } return message; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RichTextBoxAutomationPeer.cs
- Keywords.cs
- GenericTextProperties.cs
- CorrelationResolver.cs
- XmlImplementation.cs
- TypeConvertions.cs
- SystemUnicastIPAddressInformation.cs
- ClaimTypes.cs
- PointLight.cs
- PolyLineSegment.cs
- OptimizedTemplateContent.cs
- AssertSection.cs
- BlockingCollection.cs
- NonSerializedAttribute.cs
- Interlocked.cs
- SimpleRecyclingCache.cs
- DBConcurrencyException.cs
- Span.cs
- WebPartManager.cs
- FilterQueryOptionExpression.cs
- LinqDataSourceValidationException.cs
- XmlSignatureManifest.cs
- GrammarBuilderWildcard.cs
- PathData.cs
- SQLDecimal.cs
- RichTextBox.cs
- baseaxisquery.cs
- ComboBoxRenderer.cs
- OracleNumber.cs
- LayoutTable.cs
- FormViewDeleteEventArgs.cs
- Int16Storage.cs
- DataBoundControl.cs
- RtfControlWordInfo.cs
- PropertyPathConverter.cs
- SQLCharsStorage.cs
- RSAOAEPKeyExchangeFormatter.cs
- FontFamily.cs
- BamlTreeUpdater.cs
- HtmlMeta.cs
- DataGridViewElement.cs
- ListControl.cs
- StructuralCache.cs
- SoapCommonClasses.cs
- PlainXmlDeserializer.cs
- WebOperationContext.cs
- MailDefinition.cs
- PointHitTestParameters.cs
- ClientUtils.cs
- SqlGenericUtil.cs
- TextSelectionHighlightLayer.cs
- CookielessHelper.cs
- MissingFieldException.cs
- PropertyChangedEventManager.cs
- CurrencyManager.cs
- HttpResponseWrapper.cs
- SerTrace.cs
- CodeCatchClauseCollection.cs
- ImageClickEventArgs.cs
- ObjectQueryProvider.cs
- SafeSecurityHelper.cs
- ComponentGuaranteesAttribute.cs
- ListComponentEditor.cs
- QueryContext.cs
- XPathMessageFilterElementComparer.cs
- StrokeCollectionConverter.cs
- IPAddressCollection.cs
- ImportCatalogPart.cs
- ModuleConfigurationInfo.cs
- TableItemStyle.cs
- BufferedReadStream.cs
- AmbientLight.cs
- ObjectQuery_EntitySqlExtensions.cs
- ArraySortHelper.cs
- MarkupExtensionParser.cs
- CacheMemory.cs
- TextEditorSelection.cs
- UIPropertyMetadata.cs
- _UncName.cs
- LocationReferenceValue.cs
- FixedTextSelectionProcessor.cs
- Native.cs
- WindowsComboBox.cs
- IdentifierCollection.cs
- VisualProxy.cs
- QuaternionAnimation.cs
- PlatformCulture.cs
- LeftCellWrapper.cs
- NamespaceInfo.cs
- XPathDocumentIterator.cs
- Catch.cs
- DetailsViewUpdatedEventArgs.cs
- SQLDouble.cs
- StorageModelBuildProvider.cs
- DecimalMinMaxAggregationOperator.cs
- SpecularMaterial.cs
- ExpandCollapsePattern.cs
- versioninfo.cs
- TextContainerChangeEventArgs.cs
- RefType.cs