// Must return non-null/non-empty array unless exceptionToBeThrown is has been set protected override UdpSocket[] GetSendSockets(Message message, out IPEndPoint remoteEndPoint, out Exception exceptionToBeThrown) { Fx.Assert(message != null, "message can't be null"); UdpSocket[] socketList = null; exceptionToBeThrown = null; remoteEndPoint = null; Uri destination; bool isVia = false; if (message.Properties.Via != null) { destination = message.Properties.Via; isVia = true; } else if (message.Headers.To != null) { destination = message.Headers.To; } else { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ToOrViaRequired)); } this.ValidateDestinationUri(destination, isVia); if (destination.HostNameType == UriHostNameType.IPv4 || destination.HostNameType == UriHostNameType.IPv6) { remoteEndPoint = new IPEndPoint(IPAddress.Parse(destination.DnsSafeHost), destination.Port); if (this.IsMulticast) { UdpSocket socket = this.GetSendSocketUsingInterfaceIndex(message.Properties, out exceptionToBeThrown); if (socket != null) { if (socket.AddressFamily == remoteEndPoint.AddressFamily) { socketList = new UdpSocket[] { socket }; } else { exceptionToBeThrown = new InvalidOperationException(SR.RemoteAddressUnreachableDueToIPVersionMismatch(destination.DnsSafeHost)); } } } else { UdpSocket socket = this.GetSendSocket(remoteEndPoint.Address, destination, out exceptionToBeThrown); if (socket != null) { socketList = new UdpSocket[] { socket }; } } } else { IPAddress[] remoteAddresses = DnsCache.Resolve(destination).AddressList; if (this.IsMulticast) { UdpSocket socket = this.GetSendSocketUsingInterfaceIndex(message.Properties, out exceptionToBeThrown); if (socket != null) { socketList = new UdpSocket[] { socket }; for (int i = 0; i < remoteAddresses.Length; i++) { if (remoteAddresses[i].AddressFamily == socket.AddressFamily) { remoteEndPoint = new IPEndPoint(remoteAddresses[i], destination.Port); break; } } if (remoteEndPoint == null) { // for multicast, we only listen on either IPv4 or IPv6 (not both). // if we didn't find a matching remote endpoint, then it would indicate that // the remote host didn't resolve to an address we can use... exceptionToBeThrown = new InvalidOperationException(SR.RemoteAddressUnreachableDueToIPVersionMismatch(destination.DnsSafeHost)); } } } else { bool useIPv4 = true; bool useIPv6 = true; for (int i = 0; i < remoteAddresses.Length; i++) { IPAddress address = remoteAddresses[i]; if (address.AddressFamily == AddressFamily.InterNetwork && useIPv4) { UdpSocket socket = this.GetSendSocket(address, destination, out exceptionToBeThrown); if (socket == null) { if (this.State != CommunicationState.Opened) { // time to exit, the channel is closing down. break; } else { // no matching socket on IPv4, so ignore future IPv4 addresses // in the remoteAddresses list useIPv4 = false; } } else { remoteEndPoint = new IPEndPoint(address, destination.Port); socketList = new UdpSocket[] { socket }; break; } } else if (address.AddressFamily == AddressFamily.InterNetworkV6 && useIPv6) { UdpSocket socket = this.GetSendSocket(address, destination, out exceptionToBeThrown); if (socket == null) { if (this.State != CommunicationState.Opened) { // time to exit, the channel is closing down. break; } else { // no matching socket on IPv6, so ignore future IPv6 addresses // in the remoteAddresses list useIPv6 = false; } } else { remoteEndPoint = new IPEndPoint(address, destination.Port); socketList = new UdpSocket[] { socket }; break; } } } } } return(socketList); }