internal static unsafe Error GetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption* option) { bool release = false; try { socket.DangerousAddRef(ref release); return DangerousGetIPv6MulticastOption((int)socket.DangerousGetHandle(), multicastOption, option); } finally { if (release) { socket.DangerousRelease(); } } }
private static extern unsafe Error DangerousSetIPv6MulticastOption(int socket, MulticastOption multicastOption, IPv6MulticastOption* option);
internal static extern unsafe Error GetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption* option);
internal static extern unsafe Error SetIPv6MulticastOption(int socket, MulticastOption multicastOption, IPv6MulticastOption* option);
private void StartMulticastSocket(SocketSet info) { if (info.LocalEP.Address.IsIPv6Multicast) { try { info._socket = SetupUDPSocket(AddressFamily.InterNetworkV6, ReceivePacketSize + 1); info._socket.Socket.Bind(new IPEndPoint(IPAddress.IPv6Any, info.LocalEP.Port)); NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); foreach (NetworkInterface adapter in nics) { if (!adapter.SupportsMulticast) { continue; } if (adapter.OperationalStatus != OperationalStatus.Up) { continue; } if (adapter.Supports(NetworkInterfaceComponent.IPv6)) { IPInterfaceProperties properties = adapter.GetIPProperties(); foreach (UnicastIPAddressInformation ip in properties.UnicastAddresses) { if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { IPv6InterfaceProperties v6Ip = adapter.GetIPProperties().GetIPv6Properties(); IPv6MulticastOption mc = new IPv6MulticastOption(info.LocalEP.Address, v6Ip.Index); try { info._socket.Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mc); } #pragma warning disable 168 catch (SocketException e) { #pragma warning restore 168 #if LOG_UDP_CHANNEL _Log.Info( m => m( $"Start Multicast: Address {info._localEP.Address} had an exception ${e.ToString()}")); #endif } break; } } } } } #pragma warning disable 168 catch (SocketException e) { #pragma warning restore 168 #if LOG_UDP_CHANNEL _Log.Info( m => m($"Start Multicast: Address {info._localEP.Address} had an exception ${e.ToString()}")); throw; #endif } } else { try { info._socket = SetupUDPSocket(AddressFamily.InterNetwork, ReceivePacketSize + 1); info._socket.Socket.Bind(new IPEndPoint(IPAddress.Any, info.LocalEP.Port)); info._socket.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true); NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); foreach (NetworkInterface adapter in nics) { if (!adapter.SupportsMulticast) { continue; } if (adapter.OperationalStatus != OperationalStatus.Up) { continue; } if (adapter.Supports(NetworkInterfaceComponent.IPv4)) { IPInterfaceProperties properties = adapter.GetIPProperties(); foreach (UnicastIPAddressInformation ip in properties.UnicastAddresses) { if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { MulticastOption mc = new MulticastOption(info.LocalEP.Address, ip.Address); info._socket.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mc); } } } } } #pragma warning disable 168 catch (SocketException e) { #pragma warning restore 168 #if LOG_UDP_CHANNEL _Log.Info(m => m($"Start Multicast: Address {info._localEP.Address} had an exception ${e.ToString()}")); #endif throw; } } if (ReceiveBufferSize > 0) { info._socket.Socket.ReceiveBufferSize = ReceiveBufferSize; if (info._socketBackup != null) { info._socketBackup.Socket.ReceiveBufferSize = ReceiveBufferSize; } } if (SendBufferSize > 0) { info._socket.Socket.SendBufferSize = SendBufferSize; if (info._socketBackup != null) { info._socketBackup.Socket.SendBufferSize = SendBufferSize; } } BeginReceive(info); }
private void DoJoin(IPEndPoint multicastAddr) { if (multicastAddr.Address.IsIPv6Multicast) { try { NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); foreach (NetworkInterface adapter in nics) { if (!adapter.SupportsMulticast) { continue; } if (adapter.OperationalStatus != OperationalStatus.Up) { continue; } if (adapter.Supports(NetworkInterfaceComponent.IPv6)) { IPInterfaceProperties properties = adapter.GetIPProperties(); foreach (UnicastIPAddressInformation ip in properties.UnicastAddresses) { if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { IPv6InterfaceProperties v6Ip = adapter.GetIPProperties().GetIPv6Properties(); IPv6MulticastOption mc = new IPv6MulticastOption(multicastAddr.Address, v6Ip.Index); try { #if LOG_UDP_CHANNEL _Log.Debug(m => m($"Join: {multicastAddr.Address} to {v6Ip.Index}")); #endif _socket.Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mc); } #pragma warning disable 168 catch (SocketException e) { #pragma warning restore 168 #if LOG_UDP_CHANNEL _Log.Info( m => m( $"Start Multicast: Address {LocalEP.Address} had an exception ${e.ToString()}")); #endif } break; } } } } } #pragma warning disable 168 catch (SocketException e) { #pragma warning restore 168 #if LOG_UDP_CHANNEL _Log.Info( m => m($"Start Multicast: Address {LocalEP.Address} had an exception ${e.ToString()}")); throw; #endif } } else { try { NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); foreach (NetworkInterface adapter in nics) { if (!adapter.SupportsMulticast) { continue; } if (adapter.OperationalStatus != OperationalStatus.Up) { continue; } if (adapter.Supports(NetworkInterfaceComponent.IPv4)) { IPInterfaceProperties properties = adapter.GetIPProperties(); foreach (UnicastIPAddressInformation ip in properties.UnicastAddresses) { if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { MulticastOption mc = new MulticastOption(multicastAddr.Address, ip.Address); if (_socketBackup != null) { #if LOG_UDP_CHANNEL _Log.Debug(m => m($"Join: (backup) {multicastAddr.Address} to {ip.Address}")); #endif _socketBackup.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mc); } else { #if LOG_UDP_CHANNEL _Log.Debug(m => m($"Join: {multicastAddr.Address} to {ip.Address}")); #endif _socket.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mc); } } } } } } #pragma warning disable 168 catch (SocketException e) { #pragma warning restore 168 #if LOG_UDP_CHANNEL _Log.Info(m => m($"Start Multicast: Address {LocalEP.Address} had an exception ${e.ToString()}")); #endif throw; } } }
// The ConnectOriginatorAndTarget method connects the // ClientOriginator with the ClientTarget. // It performs the following main tasks: // 1)Creates a UDP client to receive data on a specific port // using IPv6 addresses. // 2)Joins or create a multicast group at the specified address. // 3)Defines the endpoint port to send data to on the ClientTarget. // 4)Starts the ClientTarget thread that also creates the ClientTarget object. // Note this method is the counterpart of the // ClientTarget.StartMulticastConversation(). public static bool ConnectOriginatorAndTarget() { try { // <Snippet3> // Bind and listen on port 2000. This constructor creates a socket // and binds it to the port on which to receive data. The family // parameter specifies that this connection uses an IPv6 address. clientOriginator = new UdpClient(2000, AddressFamily.InterNetworkV6); // Join or create a multicast group. The multicast address ranges // to use are specified in RFC#2375. You are free to use // different addresses. // Transform the string address into the internal format. m_GrpAddr = IPAddress.Parse("FF01::1"); // Display the multicast address used. Console.WriteLine("Multicast Address: [" + m_GrpAddr.ToString() + "]"); // <Snippet4> // Exercise the use of the IPv6MulticastOption. Console.WriteLine("Instantiate IPv6MulticastOption(IPAddress)"); // Instantiate IPv6MulticastOption using one of the // overloaded constructors. IPv6MulticastOption ipv6MulticastOption = new IPv6MulticastOption(m_GrpAddr); // Store the IPAdress multicast options. IPAddress group = ipv6MulticastOption.Group; long interfaceIndex = ipv6MulticastOption.InterfaceIndex; // Display IPv6MulticastOption properties. Console.WriteLine("IPv6MulticastOption.Group: [" + group + "]"); Console.WriteLine("IPv6MulticastOption.InterfaceIndex: [" + interfaceIndex + "]"); // </Snippet4> // <Snippet5> // Instantiate IPv6MulticastOption using another // overloaded constructor. IPv6MulticastOption ipv6MulticastOption2 = new IPv6MulticastOption(group, interfaceIndex); // Store the IPAdress multicast options. group = ipv6MulticastOption2.Group; interfaceIndex = ipv6MulticastOption2.InterfaceIndex; // Display the IPv6MulticastOption2 properties. Console.WriteLine("IPv6MulticastOption.Group: [" + group + "]"); Console.WriteLine("IPv6MulticastOption.InterfaceIndex: [" + interfaceIndex + "]"); // Join the specified multicast group using one of the // JoinMulticastGroup overloaded methods. clientOriginator.JoinMulticastGroup((int)interfaceIndex, group); // </Snippet5> // Define the endpoint data port. Note that this port number // must match the ClientTarget UDP port number which is the // port on which the ClientTarget is receiving data. m_ClientTargetdest = new IPEndPoint(m_GrpAddr, 1000); // </Snippet3> // Start the ClientTarget thread so it is ready to receive. m_t = new Thread(new ThreadStart(ClientTarget.StartMulticastConversation)); m_t.Start(); // Make sure that the thread has started. Thread.Sleep(2000); return(true); } catch (Exception e) { Console.WriteLine("[ClientOriginator.ConnectClients] Exception: " + e.ToString()); return(false); } }
void FindNetworkInterfaces() { var nics = GetNetworkInterfaces() .Where(nic => !knownNics.Any(k => k.Id == nic.Id)) .ToArray(); foreach (var nic in nics) { lock (socketLock) { if (socket == null) { return; } IPInterfaceProperties properties = nic.GetIPProperties(); if (ip6) { var ipProperties = properties.GetIPv6Properties(); var interfaceIndex = ipProperties.Index; var mopt = new IPv6MulticastOption(MulticastAddressIp6, interfaceIndex); socket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mopt); if (ipProperties.Mtu > packetOverhead) { // Only change maxPacketSize if Mtu is available (and it that is not the case on MacOS) maxPacketSize = Math.Min(maxPacketSize, ipProperties.Mtu - packetOverhead); } } else { var ipProperties = properties.GetIPv4Properties(); var interfaceIndex = ipProperties.Index; var mopt = new MulticastOption(MulticastAddressIp4, interfaceIndex); socket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.AddMembership, mopt); if (ipProperties.Mtu > packetOverhead) { // Only change maxPacketSize if Mtu is available (and it that is not the case on MacOS) maxPacketSize = Math.Min(maxPacketSize, ipProperties.Mtu - packetOverhead); } } knownNics.Add(nic); } } // Tell others. if (nics.Length > 0) { lock (socketLock) { if (socket == null) { return; } NetworkInterfaceDiscovered?.Invoke(this, new NetworkInterfaceEventArgs { NetworkInterfaces = nics }); } } }
public void JoinASM(IPAddress groupIp, int port, EMulticastInterface iface, IPAddress specificIface = null) { ValidateASM(groupIp, port); if (_udpClient != null) { return; // already started. } _udpClient = new UdpClient(groupIp.AddressFamily); Socket socket = _udpClient.Client; socket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true ); var bindInterface = specificIface; if (iface != EMulticastInterface.Specific) { bindInterface = (socket.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any); } socket.Bind(new IPEndPoint(bindInterface, port)); var joinInterfaces = new List <int>(); if (iface == EMulticastInterface.All) { foreach (var ni in NetworkUtils.GetActiveInterfaces()) { joinInterfaces.Add(socket.AddressFamily == AddressFamily.InterNetworkV6 ? ni.IPv6.Index : ni.IPv4.Index); } } else if (iface == EMulticastInterface.Specific) { int best = NetworkUtils.GetBestMulticastInterfaceIndex(specificIface); if (best == -1) { best = 0; } joinInterfaces.Add(best); } else if (iface == EMulticastInterface.Default) { joinInterfaces.Add(0); // 0 = default. } foreach (int ifaceIndex in joinInterfaces) { if (socket.AddressFamily == AddressFamily.InterNetwork) { MulticastOption opt = new MulticastOption( groupIp, ifaceIndex); socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, opt); } else if (socket.AddressFamily == AddressFamily.InterNetworkV6) { IPv6MulticastOption optv6 = new IPv6MulticastOption( groupIp, ifaceIndex); socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, optv6); } } StatusChanged?.Invoke(this, new UdpMulticastClientStatusEventArgs(true) { MulticastGroup = new IPEndPoint(groupIp, port), MulticastInterface = iface, SpecificInterface = specificIface } ); StartReceive(); }
public void Start() { if (socket_ != null) { throw new InvalidOperationException("Network is already running"); } socket_ = new Socket(broadcastEndpoint_.AddressFamily, SocketType.Dgram, ProtocolType.Udp); // Bind to the broadcast port. socket_.Bind(new IPEndPoint(localAddress_, broadcastEndpoint_.Port)); // Optionally join a multicast group if (IsMulticast(broadcastEndpoint_.Address)) { if (broadcastEndpoint_.AddressFamily == AddressFamily.InterNetwork) { MulticastOption mcastOption; mcastOption = new MulticastOption(broadcastEndpoint_.Address, localAddress_); socket_.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption); } else if (broadcastEndpoint_.AddressFamily == AddressFamily.InterNetworkV6) { IPv6MulticastOption mcastOption; if (localAddress_ != IPAddress.IPv6Any) { var ifaceIdx = GetIfaceIdxFromAddress(localAddress_); mcastOption = new IPv6MulticastOption(broadcastEndpoint_.Address, ifaceIdx); } else { mcastOption = new IPv6MulticastOption(broadcastEndpoint_.Address); } socket_.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption); } else { // Should never happen throw new NotSupportedException($"Invalid address family: {broadcastEndpoint_.AddressFamily}"); } } else { // Assume this is a broadcast address. socket_.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); } // Start the cleanup thread. deleteExpiredCts_ = new CancellationTokenSource(); var token = deleteExpiredCts_.Token; deleteExpiredTask_ = Task.Run(() => CleanupExpired(token), token); // Start the receiving thread. recvTask_ = Task.Run(ReceiveLoop); Started?.Invoke(this); }
protected override void OnOpen() { System.Diagnostics.Debug.Assert(_socket == null); System.Diagnostics.Debug.Assert(_remoteEp != null); System.Diagnostics.Debug.Assert(_localIp != null); System.Diagnostics.Debug.Assert(_iface != null); try { IPEndPoint ep = _remoteEp as IPEndPoint; ep.Port = Port; _socket = OpenSocket(ep); _multicast = ep.Address.IsMulticast(); if (_multicast) { if (Platform.GetOS() == Platform.OS.Windows) { // Multicast needs to bind to INADDR_ANY on windows if (ep.AddressFamily == AddressFamily.InterNetwork) { _socket.Bind(new IPEndPoint(IPAddress.Any, SrcPort)); } else { _socket.Bind(new IPEndPoint(IPAddress.IPv6Any, SrcPort)); } } else if (ep.Address.AddressFamily == AddressFamily.InterNetwork) { // Multicast needs to bind to the group on *nix _socket.Bind(new IPEndPoint(ep.Address, SrcPort)); } else { _socket.Bind(new IPEndPoint(IPAddress.IPv6Any, SrcPort)); } SocketOptionLevel level = SocketOptionLevel.IPv6; object opt = null; if (_localIp.AddressFamily == AddressFamily.InterNetwork) { level = SocketOptionLevel.IP; opt = new MulticastOption(ep.Address, _localIp); } else if (Platform.GetOS() == Platform.OS.OSX) { if (_iface == null) { throw new PeachException("Error, could not resolve local interface name for local IP '{0}'.".Fmt(_localIp)); } uint ifindex = if_nametoindex(_iface); if (ifindex == 0) { throw new PeachException("Error, could not resolve interface index for interface name '{0}'.".Fmt(_iface)); } JoinGroupV6(ep.Address, ifindex); } else if (_localIp != IPAddress.IPv6Any) { level = SocketOptionLevel.IPv6; opt = new IPv6MulticastOption(ep.Address, _localIp.ScopeId); } else { level = SocketOptionLevel.IPv6; opt = new IPv6MulticastOption(ep.Address); } if (opt != null) { _socket.SetSocketOption(level, SocketOptionName.AddMembership, opt); } if (_localIp != IPAddress.Any && _localIp != IPAddress.IPv6Any) { Logger.Trace("Setting multicast interface for {0} socket to {1}.", _type, _localIp); if (level == SocketOptionLevel.IP) { _socket.SetSocketOption(level, SocketOptionName.MulticastInterface, _localIp.GetAddressBytes()); } else if (Platform.GetOS() != Platform.OS.OSX) { _socket.SetSocketOption(level, SocketOptionName.MulticastInterface, (int)_localIp.ScopeId); } } else if (Platform.GetOS() == Platform.OS.OSX) { throw new PeachException(string.Format("Error, the value for parameter 'Interface' can not be '{0}' when the 'Host' parameter is multicast.", Interface == null ? "<null>" : Interface.ToString())); } } else { _socket.Bind(new IPEndPoint(_localIp, SrcPort)); } } catch (Exception ex) { if (_socket != null) { _socket.Close(); _socket = null; } SocketException se = ex as SocketException; if (se != null && se.SocketErrorCode == SocketError.AccessDenied) { throw new PeachException(string.Format("Access denied when trying open a {0} socket. Ensure the user has the appropriate permissions.", _type), ex); } Logger.Error("Unable to open {0} socket to {1}:{2}. {3}.", _type, Host, Port, ex.Message); throw new SoftException(ex); } _socket.ReceiveBufferSize = MaxSendSize; _socket.SendBufferSize = MaxSendSize; if (_recvBuffer == null || _recvBuffer.Capacity < _socket.ReceiveBufferSize) { _recvBuffer = new MemoryStream(MaxSendSize); } _localEp = _socket.LocalEndPoint; Logger.Trace("Opened {0} socket, Local: {1}, Remote: {2}", _type, _localEp, _remoteEp); }