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
- EntityTemplateUserControl.cs
- XmlParserContext.cs
- ArcSegment.cs
- SqlDataSourceQuery.cs
- COAUTHIDENTITY.cs
- GlobalEventManager.cs
- NativeMethodsOther.cs
- Popup.cs
- FaultPropagationRecord.cs
- ContainsRowNumberChecker.cs
- InputBuffer.cs
- PropertyMapper.cs
- DecimalStorage.cs
- SingleObjectCollection.cs
- DesignRelation.cs
- DirectionalLight.cs
- ServerValidateEventArgs.cs
- SimpleTypeResolver.cs
- XmlSchemaAnnotated.cs
- StreamWithDictionary.cs
- FixedStringLookup.cs
- DynamicValidator.cs
- SubpageParagraph.cs
- SchemaDeclBase.cs
- WindowsListBox.cs
- DataSourceCache.cs
- Monitor.cs
- DbModificationCommandTree.cs
- SelectionRangeConverter.cs
- FlowLayoutSettings.cs
- Simplifier.cs
- XComponentModel.cs
- CancelEventArgs.cs
- ADConnectionHelper.cs
- StretchValidation.cs
- HtmlGenericControl.cs
- FontWeights.cs
- InputReport.cs
- ConfigurationConverterBase.cs
- Options.cs
- RelatedView.cs
- ErrorFormatterPage.cs
- Exception.cs
- EmptyCollection.cs
- XmlSchemaException.cs
- ToolStripItemClickedEventArgs.cs
- ColorMatrix.cs
- DisposableCollectionWrapper.cs
- RangeValidator.cs
- Typography.cs
- Util.cs
- ControlEvent.cs
- UserControlBuildProvider.cs
- DataServices.cs
- FixedSchema.cs
- FreezableCollection.cs
- CodeMemberProperty.cs
- ButtonChrome.cs
- BaseTemplateBuildProvider.cs
- CodeMethodMap.cs
- ArrangedElementCollection.cs
- XmlSchemaRedefine.cs
- keycontainerpermission.cs
- SqlProcedureAttribute.cs
- ContextMenu.cs
- DataGridCommandEventArgs.cs
- SmiContext.cs
- AdCreatedEventArgs.cs
- SymbolEqualComparer.cs
- util.cs
- DataRecordInternal.cs
- BuildManagerHost.cs
- Label.cs
- PreviewPageInfo.cs
- ExtensionFile.cs
- CombinedGeometry.cs
- ReceiveActivityDesignerTheme.cs
- HTTPNotFoundHandler.cs
- LinkLabel.cs
- DescendantBaseQuery.cs
- HwndProxyElementProvider.cs
- FormatSettings.cs
- CodeTypeReferenceCollection.cs
- SafeProcessHandle.cs
- RenderOptions.cs
- ArgumentException.cs
- CacheOutputQuery.cs
- FormsAuthenticationUserCollection.cs
- DefaultPropertyAttribute.cs
- RotationValidation.cs
- LongCountAggregationOperator.cs
- ImageIndexConverter.cs
- BuildManagerHost.cs
- AttachedAnnotationChangedEventArgs.cs
- Validator.cs
- DataGridViewCellValidatingEventArgs.cs
- LinearGradientBrush.cs
- CuspData.cs
- MSAANativeProvider.cs
- PageAsyncTaskManager.cs