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);
public LocalMulticast(int port, Action <TMessage> handler = null, string name = null) { _handler = handler; _name = name ?? String.Empty; var msgSize = TypeHelper <TMessage> .FixedSize; if (msgSize <= 0) { throw new ArgumentException($"Type {typeof(TMessage).Name} must be a blittable struct"); } _bufferLength = msgSize; _sendArgsPool = new ObjectPool <SocketAsyncEventArgs>(SendArgsFactory, Environment.ProcessorCount * 4); var multicastAddress = IPAddress.Parse("239.199.99.9"); _mcEndPoint = new CachedEndPoint(new IPEndPoint(multicastAddress, port)); _inEndPoint = new CachedEndPoint(new IPEndPoint(IPAddress.Loopback, port)); _socket = new Socket(_inEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); _socket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.NoChecksum, 1); _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2); _socket.ExclusiveAddressUse = false; _socket.Blocking = true; _socket.EnableBroadcast = true; // Maybe a fluke, bit perf drops and definitely not improves with this: _socket.UseOnlyOverlappedIO = true; _socket.Bind(_inEndPoint); // If you are using a connectionless protocol such as UDP, // you do not have to call Connect before sending and // receiving data. You can use SendTo and ReceiveFrom to // synchronously communicate with a remote host. // If you do call Connect, any datagrams that arrive from // an address other than the specified default will be discarded. // _socket.Connect(_mcEndPoint); _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true); // join on loopback interface var mcastOption = new MulticastOption(multicastAddress, NetworkInterface.LoopbackInterfaceIndex); _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption); _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, #pragma warning disable 618 (int)IPAddress.Loopback.Address); #pragma warning restore 618 // see https://github.com/dotnet/corefx/issues/25699 if there are issues on non-Windows // IPAddress.HostToNetworkOrder(NetworkInterface.LoopbackInterfaceIndex)); // Another option to limit source to loopback //byte[] membershipAddresses = new byte[12]; // 3 IPs * 4 bytes (IPv4) //Buffer.BlockCopy(multicastAddress.GetAddressBytes(), 0, membershipAddresses, 0, 4); //Buffer.BlockCopy(IPAddress.Loopback.GetAddressBytes(), 0, membershipAddresses, 4, 4); //Buffer.BlockCopy(IPAddress.Loopback.GetAddressBytes(), 0, membershipAddresses, 8, 4); //_socket.SetSocketOption(SocketOptionLevel.IP, // SocketOptionName.AddSourceMembership, // membershipAddresses); StartReceive(); #if NETCOREAPP3_0 try { _handle = _socket.SafeHandle; var address = _mcEndPoint.Serialize(); _mcAddressSize = address.Size; _mcAddressBuffer = new byte[_mcAddressSize]; for (int i = 0; i < _mcAddressSize; i++) { _mcAddressBuffer[i] = address[i]; } var assembly = typeof(Socket).Assembly; var socketPalType = assembly.GetTypes().FirstOrDefault(x => x.Name == "SocketPal"); var method = socketPalType?.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) .FirstOrDefault(m => m.Name == "SendTo"); _sendToDelegate = Delegate.CreateDelegate(typeof(SendToDelegate), method) as SendToDelegate; } catch { Trace.TraceInformation("Cannot get SocketPal.SendTo method"); } #endif }
public async Task NetworkRequestAsync(byte[] requestBytes, TimeSpan scanTime, int retries, int retryDelayMilliseconds, Action <string, byte[]> onResponse, CancellationToken cancellationToken) { using (var client = new UdpClient()) { for (var i = 0; i < retries; i++) { #if ANDROID var mlock = wifi.CreateMulticastLock("Zeroconf lock"); #endif try { #if ANDROID mlock.Acquire(); #endif var localEp = new IPEndPoint(IPAddress.Any, 5353); // There could be multiple adapters, get the default one uint index = 0; #if XAMARIN const int ifaceIndex = 0; #else GetBestInterface(0, out index); var ifaceIndex = (int)index; #endif client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(ifaceIndex)); client.ExclusiveAddressUse = false; client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, scanTime.Milliseconds); client.ExclusiveAddressUse = false; client.Client.Bind(localEp); var multicastAddress = IPAddress.Parse("224.0.0.251"); var multOpt = new MulticastOption(multicastAddress, ifaceIndex); client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multOpt); Debug.WriteLine("Bound to multicast address"); // Start a receive loop var shouldCancel = false; var recTask = Task.Run(async () => { try { while (!shouldCancel) { var res = await client.ReceiveAsync() .ConfigureAwait(false); onResponse(res.RemoteEndPoint.Address.ToString(), res.Buffer); } } catch (ObjectDisposedException) { } }, cancellationToken); var broadcastEp = new IPEndPoint(IPAddress.Parse("224.0.0.251"), 5353); await client.SendAsync(requestBytes, requestBytes.Length, broadcastEp) .ConfigureAwait(false); Debug.WriteLine("Sent mDNS query"); // wait for responses await Task.Delay(scanTime, cancellationToken) .ConfigureAwait(false); shouldCancel = true; client.Close(); Debug.WriteLine("Done Scanning"); await recTask.ConfigureAwait(false); return; } catch (Exception e) { Debug.WriteLine("Execption: ", e); if (i + 1 >= retries) // last one, pass underlying out { throw; } } finally { #if ANDROID mlock.Release(); #endif } await Task.Delay(retryDelayMilliseconds, cancellationToken).ConfigureAwait(false); } } }
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, _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 adapter.GetIPProperties().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); } catch (SocketException e) { #if LOG_UDP_CHANNEL _Log.Info( m => m( $"Start Multicast: Address {info._localEP.Address} had an exception ${e.ToString()}")); #endif } break; } } } } } catch (SocketException e) { #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, _port)); 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 adapter.GetIPProperties().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); } } } } } catch (SocketException e) { #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); }
/// <summary> /// Gets socket option value. /// </summary> /// <param name="option">Option to get.</param> /// <returns></returns> public dynamic GetOption( MulticastOption option ) { switch( option ) { case MulticastOption.DataRate: case MulticastOption.RecoveryInterval: case MulticastOption.RecoveryIntervalMS: case MulticastOption.Loopback: return GetOptionInt64( (int)option ); default: throw new NotImplementedException( "Unknown option: " + option ); } }
public static void Main(String[] args) { // Initialize the multicast address group and multicast port. // Both address and port are selected from the allowed sets as // defined in the related RFC documents. These are the same // as the values used by the sender. mcastAddress = IPAddress.Parse("230.0.0.1"); mcastPort = 11000; try { mcastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPAddress localIP = IPAddress.Any; EndPoint localEP = (EndPoint)new IPEndPoint(localIP, mcastPort); mcastSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); mcastSocket.Bind(localEP); // Define a MulticastOption object specifying the multicast group // address and the local IPAddress. // The multicast group address is the same as the address used by the server. mcastOption = new MulticastOption(mcastAddress, localIP); // Become a member of the multicast IP address mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption); bool done = false; byte[] bytes = new Byte[100]; IPEndPoint groupEP = new IPEndPoint(mcastAddress, mcastPort); EndPoint remoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0); while (!done) { Console.WriteLine("Waiting for multicast packets......."); Console.WriteLine("Enter ^C to terminate."); mcastSocket.ReceiveFrom(bytes, ref remoteEP); Console.WriteLine("Received broadcast from {0} :\n {1}\n", remoteEP.ToString(), Encoding.ASCII.GetString(bytes, 0, bytes.Length)); Array.Clear(bytes, 0, 99); } mcastSocket.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } }
/// <include file='doc\UDPClient.uex' path='docs/doc[@for="UdpClient.DropMulticastGroup"]/*' /> /// <devdoc> /// <para> /// Leaves a multicast address group. /// </para> /// </devdoc> public void DropMulticastGroup(IPAddress multicastAddr) { // // parameter validation // if (m_CleanedUp){ throw new ObjectDisposedException(this.GetType().FullName); } if (multicastAddr==null){ throw new ArgumentNullException("multicastAddr"); } MulticastOption mcOpt = new MulticastOption(multicastAddr); Client.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.DropMembership, mcOpt ); }
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(); }
protected virtual void CreateSocket(string mcastserverPRI, int mcastportPRI, string mcastserverSEC, int mcastportSEC) { try { bKeepRunning = true; logger.Info("Criando socket para host:porta [" + mcastserverPRI + ":" + mcastportPRI + "]"); //Using UDP sockets clientSocketPRI = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); clientSocketPRI.ReceiveBufferSize = 1024 * 1024 * 16; clientSocketPRI.UseOnlyOverlappedIO = true; //IP address of the server machine ipAddressPRI = IPAddress.Parse(mcastserverPRI); IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, mcastportPRI); clientSocketPRI.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); clientSocketPRI.ExclusiveAddressUse = false; clientSocketPRI.Bind(localEndPoint); if (!String.IsNullOrEmpty(localInterfaceAddress) && !localInterfaceAddress.ToLowerInvariant().Equals("any")) { logger.Info("Binding PRI local interface: [" + localInterfaceAddress + "]"); mcoPRI = new MulticastOption(ipAddressPRI, IPAddress.Parse(localInterfaceAddress)); } else { logger.Info("Binding PRI all interfaces"); mcoPRI = new MulticastOption(ipAddressPRI, IPAddress.Any); } clientSocketPRI.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcoPRI); clientSocketPRI.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 200); IPEndPoint serverEndPoint = new IPEndPoint(ipAddressPRI, mcastportPRI); epServerPRI = (EndPoint)serverEndPoint; logger.Debug("Joining primary group..."); byteDataPRI = new byte[BUFFER_SIZE]; logger.Info("Start primary receiving"); clientSocketPRI.BeginReceiveFrom(byteDataPRI, 0, byteDataPRI.Length, SocketFlags.None, ref epServerPRI, new AsyncCallback(this.OnReceivePRI), null); if (!String.IsNullOrEmpty(mcastserverSEC)) { logger.Info("Criando socket para host:porta [" + mcastserverSEC + ":" + mcastportSEC + "]"); //Using UDP sockets clientSocketSEC = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); clientSocketSEC.ReceiveBufferSize = 1024 * 1024 * 16; clientSocketSEC.UseOnlyOverlappedIO = true; //IP address of the server machine ipAddressSEC = IPAddress.Parse(mcastserverSEC); localEndPoint = new IPEndPoint(IPAddress.Any, mcastportSEC); clientSocketSEC.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); clientSocketSEC.ExclusiveAddressUse = false; clientSocketSEC.Bind(localEndPoint); if (!String.IsNullOrEmpty(localInterfaceAddress) && !localInterfaceAddress.ToLowerInvariant().Equals("any")) { logger.Info("Binding SEC local interface: [" + localInterfaceAddress + "]"); mcoSEC = new MulticastOption(ipAddressSEC, IPAddress.Parse(localInterfaceAddress)); } else { logger.Info("Binding SEC all interfaces"); mcoSEC = new MulticastOption(ipAddressSEC, IPAddress.Any); } clientSocketSEC.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcoSEC); clientSocketSEC.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 200); serverEndPoint = new IPEndPoint(ipAddressSEC, mcastportSEC); epServerSEC = (EndPoint)serverEndPoint; logger.Debug("Joining secondary group..."); byteDataSEC = new byte[BUFFER_SIZE]; logger.Debug("Start secondary receiving"); clientSocketSEC.BeginReceiveFrom(byteDataSEC, 0, byteDataSEC.Length, SocketFlags.None, ref epServerSEC, new AsyncCallback(this.OnReceiveSEC), null); } } catch (Exception ex) { logger.Error("CreateSocket(): " + ex.Message, ex); bKeepRunning = false; } }
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); }
internal static extern unsafe Error GetIPv6MulticastOption(int socket, MulticastOption multicastOption, IPv6MulticastOption *option);
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); }
/// <summary> /// Starts listening to the specified end point and accepting incoming connections. /// </summary> /// <param name="endPoint">The end point.</param> public override void StartListening(object endPoint) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; this._closing = false; // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "UdpConnectionManager.StartListening", LogMessageType.ConnectionParameters, null, null, this.ITransportContext.IParameterProvider, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this.DbgConnectionId, "UDP socket is being associated with the end point: {0}.", endPoint.ToString()); } // get the ip end point IPEndPoint ipEndPoint = null; int port; string url; try { url = (string)endPoint; url = GenuineUtility.SplitToHostAndPort(url, out port); ipEndPoint = new IPEndPoint(GenuineUtility.ResolveIPAddress(url), port); } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.Connection, "UdpConnectionManager.StartListening", LogMessageType.ListeningStarted, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, this.DbgConnectionId, 0, 0, 0, null, null, null, null, "The listening socket cannot be associated with the {0} local end point.", endPoint.ToString()); } throw GenuineExceptions.Get_Server_IncorrectAddressToListen(endPoint as string); } lock (this) { if (this._socket != null) { throw GenuineExceptions.Get_Server_EndPointIsAlreadyBeingListenedTo(this._socket.LocalEndPoint.ToString()); } // initialize the socket this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); if (this.ITransportContext.IParameterProvider[GenuineParameter.UdpTtl] != null) { this._socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, (int)this.ITransportContext.IParameterProvider[GenuineParameter.UdpTtl]); } // Receive buffer size this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, (int)this.ITransportContext.IParameterProvider[GenuineParameter.UdpReceiveBuffer]); this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); this._socket.Bind(ipEndPoint); // if it's an IP multicast sender if (this.ITransportContext.IParameterProvider[GenuineParameter.UdpMulticastTo] != null) { try { url = (string)this.ITransportContext.IParameterProvider[GenuineParameter.UdpMulticastTo]; url = GenuineUtility.SplitToHostAndPort(url, out port); this._multicastTo = new IPEndPoint(GenuineUtility.ResolveIPAddress(url), port); this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); if (this.ITransportContext.IParameterProvider[GenuineParameter.UdpTtl] != null) { this._socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, (int)this.ITransportContext.IParameterProvider[GenuineParameter.UdpTtl]); } } catch (Exception) { throw GenuineExceptions.Get_Channel_InvalidParameter("UdpMulticastTo"); } } // and join to the specified broadcast network if (this.ITransportContext.IParameterProvider[GenuineParameter.UdpJoinTo] != null) { string joinTo = (string)this.ITransportContext.IParameterProvider[GenuineParameter.UdpJoinTo]; this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); IPAddress ipAddressToJoinTo = GenuineUtility.ResolveIPAddress(joinTo); MulticastOption multicastOption = new MulticastOption(ipAddressToJoinTo, ipEndPoint.Address); this._socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOption); } // initiate receiving Thread receivingThread = new Thread(new ThreadStart(this.ReceiveSynchronously)); receivingThread.IsBackground = true; receivingThread.Start(); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.Connection, "UdpConnectionManager.StartListening", LogMessageType.ConnectionEstablished, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, this.DbgConnectionId, (int)GenuineConnectionType.Invocation, 0, 0, this.GetType().Name, this._socket.LocalEndPoint.ToString(), null, null, "The UDP socket is ready for action."); } } }
internal static extern unsafe Error SetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption *option);
/// <summary> /// Sets multicast socket options. /// </summary> /// <param name="option">Option to set.</param> /// <param name="value">Value to set the option to.</param> public void SetOption( MulticastOption option, long value ) { Contract.Requires( !Disposed ); Contract.Requires( option == MulticastOption.DataRate || option == MulticastOption.RecoveryInterval || option == MulticastOption.RecoveryIntervalMS || option == MulticastOption.Loopback ); if( C.zmq_setsockopt( m_sock, (int)option, ref value, new C.size_t( Marshal.SizeOf( value ) ) ) != 0 ) { throw ZeroMQException.CurrentError(); } }
/// <summary> /// Start listening for incoming messages on the specified port and network interface. /// </summary> public bool Start(int port, IPAddress ni) { Stop(); mPort = port; mSocket = new Socket(ni.AddressFamily, SocketType.Dgram, ProtocolType.Udp); #if !UNITY_WEBPLAYER // Web player doesn't seem to support broadcasts mSocket.MulticastLoopback = true; mMulticast = useMulticasting; try { if (useMulticasting) { List <IPAddress> ips = Tools.localAddresses; foreach (IPAddress ip in ips) { MulticastOption opt = new MulticastOption(multicastIP, ip); mSocket.SetSocketOption(ni.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP, SocketOptionName.AddMembership, opt); } } else { mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); } } catch (System.Exception) { } #endif // Port zero means we will be able to send, but not receive if (mPort == 0) { return(true); } try { // Use the default network interface if one wasn't explicitly chosen #if (UNITY_IPHONE && !UNITY_EDITOR) //|| UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX IPAddress networkInterface = useMulticasting ? multicastIP : ni; #else IPAddress networkInterface = ni; #endif mEndPoint = new IPEndPoint(networkInterface, 0); mDefaultEndPoint = new IPEndPoint(networkInterface, 0); // Bind the socket to the specific network interface and start listening for incoming packets mSocket.Bind(new IPEndPoint(networkInterface, mPort)); mSocket.BeginReceiveFrom(mTemp, 0, mTemp.Length, SocketFlags.None, ref mEndPoint, OnReceive, null); } #if UNITY_EDITOR catch (System.Exception ex) { UnityEngine.Debug.LogError("[TNet] Udp.Start: " + ex.Message); Stop(); return(false); } #elif DEBUG catch (System.Exception ex) { Tools.Print("Udp.Start: " + ex.Message); Stop(); return(false); } #else catch (System.Exception) { Stop(); return(false); } #endif return(true); }
internal static extern unsafe Error GetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption* option);
Task ListenForAnnouncementsAsync(System.Net.NetworkInformation.NetworkInterface adapter, Action <AdapterInformation, string, byte[]> callback, CancellationToken cancellationToken) { return(Task.Factory.StartNew(async() => { var ipv4Address = adapter.GetIPProperties().UnicastAddresses .First(ua => ua.Address.AddressFamily == AddressFamily.InterNetwork)?.Address; if (ipv4Address == null) { return; } var ifaceIndex = adapter.GetIPProperties().GetIPv4Properties()?.Index; if (ifaceIndex == null) { return; } Debug.WriteLine($"Scanning on iface {adapter.Name}, idx {ifaceIndex}, IP: {ipv4Address}"); using (var client = new UdpClient()) { var socket = client.Client; socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, IPAddress.HostToNetworkOrder(ifaceIndex.Value)); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); client.ExclusiveAddressUse = false; var localEp = new IPEndPoint(IPAddress.Any, 5353); socket.Bind(localEp); var multicastAddress = IPAddress.Parse("224.0.0.251"); var multOpt = new MulticastOption(multicastAddress, ifaceIndex.Value); socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multOpt); cancellationToken.Register((() => { ((IDisposable)client).Dispose(); })); while (!cancellationToken.IsCancellationRequested) { try { var packet = await client.ReceiveAsync() .ConfigureAwait(false); try { callback(new AdapterInformation(ipv4Address.ToString(), adapter.Name), packet.RemoteEndPoint.Address.ToString(), packet.Buffer); } catch (Exception ex) { Debug.WriteLine($"Callback threw an exception: {ex}"); } } catch when(cancellationToken.IsCancellationRequested) { // eat any exceptions if we've been cancelled } } Debug.WriteLine($"Done listening for mDNS packets on {adapter.Name}, idx {ifaceIndex}, IP: {ipv4Address}."); cancellationToken.ThrowIfCancellationRequested(); } }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap()); }
internal static extern unsafe Error SetIPv6MulticastOption(int socket, MulticastOption multicastOption, IPv6MulticastOption* option);
async Task NetworkRequestAsync(byte[] requestBytes, TimeSpan scanTime, int retries, int retryDelayMilliseconds, Action <IPAddress, byte[]> onResponse, System.Net.NetworkInformation.NetworkInterface adapter, CancellationToken cancellationToken) { // http://stackoverflow.com/questions/2192548/specifying-what-network-interface-an-udp-multicast-should-go-to-in-net // Xamarin doesn't support this //if (!adapter.GetIPProperties().MulticastAddresses.Any()) // return; // most of VPN adapters will be skipped if (!adapter.SupportsMulticast) { return; // multicast is meaningless for this type of connection } if (OperationalStatus.Up != adapter.OperationalStatus) { return; // this adapter is off or not connected } if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback) { return; // strip out loopback addresses } var p = adapter.GetIPProperties().GetIPv4Properties(); if (null == p) { return; // IPv4 is not configured on this adapter } var ipv4Address = adapter.GetIPProperties().UnicastAddresses .FirstOrDefault(ua => ua.Address.AddressFamily == AddressFamily.InterNetwork)?.Address; if (ipv4Address == null) { return; // could not find an IPv4 address for this adapter } var ifaceIndex = p.Index; Debug.WriteLine($"Scanning on iface {adapter.Name}, idx {ifaceIndex}, IP: {ipv4Address}"); using (var client = new UdpClient()) { for (var i = 0; i < retries; i++) { try { var socket = client.Client; if (socket.IsBound) { continue; } socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, IPAddress.HostToNetworkOrder(ifaceIndex)); client.ExclusiveAddressUse = false; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, (int)scanTime.TotalMilliseconds); client.ExclusiveAddressUse = false; var multicastAddress = IPAddress.Parse("224.0.0.251"); var multOpt = new MulticastOption(multicastAddress, ifaceIndex); socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multOpt); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { var localEp = new IPEndPoint(IPAddress.Any, 5353); Debug.WriteLine($"Attempting to bind to {localEp} on adapter {adapter.Name}"); socket.Bind(localEp); Debug.WriteLine($"Bound to {localEp}"); Debug.WriteLine("Bound to multicast address"); } // Start a receive loop var shouldCancel = false; var recTask = Task.Run(async () => { try { while (!Volatile.Read(ref shouldCancel)) { var res = await client.ReceiveAsync() .ConfigureAwait(false); if (res.RemoteEndPoint != null && res.Buffer != null && res.RemoteEndPoint.Port == 5353) { onResponse(res.RemoteEndPoint.Address, res.Buffer); } } } catch when(Volatile.Read(ref shouldCancel)) { // If we're canceling, eat any exceptions that come from here } }, cancellationToken); var broadcastEp = new IPEndPoint(IPAddress.Parse("224.0.0.251"), 5353); Debug.WriteLine($"About to send on iface {adapter.Name}"); await client.SendAsync(requestBytes, requestBytes.Length, broadcastEp) .ConfigureAwait(false); Debug.WriteLine($"Sent mDNS query on iface {adapter.Name}"); // wait for responses await Task.Delay(scanTime, cancellationToken) .ConfigureAwait(false); Volatile.Write(ref shouldCancel, true); ((IDisposable)client).Dispose(); Debug.WriteLine("Done Scanning"); await recTask.ConfigureAwait(false); return; } catch (Exception e) { Debug.WriteLine($"Execption with network request, IP {ipv4Address}\n: {e}"); if (i + 1 >= retries) // last one, pass underlying out { // Ensure all inner info is captured ExceptionDispatchInfo.Capture(e).Throw(); throw; } } await Task.Delay(retryDelayMilliseconds, cancellationToken).ConfigureAwait(false); } } }
private static extern unsafe Error DangerousSetIPv6MulticastOption(int socket, MulticastOption multicastOption, IPv6MulticastOption* option);
// This thread handles incoming NatNet packets. private void ThreadRun() { stopReceive = false; Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); ipEndPoint = new IPEndPoint(IPAddress.Any, BLACK_BOX_CLIENT_PORT); //Debug.Log("prebind"); socket.Bind(ipEndPoint); //Debug.Log("bind"); MulticastOption mo = new MulticastOption(IPAddress.Parse("224.1.1.1")); socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mo); nBytesReceived = 0; lastLoadedBuffer = b1; lastLoadedBufferMS = b1ms; lastLoadedFrame = 0; byte[] newPacketBuffer = b2; MemoryStream newPacketBufferMS = b2ms; long newPacketFrame = 0; byte[] tempBuffer; MemoryStream tempBufferMS; while (true) { //Debug.Log("preRECV"); nBytesReceived = socket.Receive(newPacketBuffer); //Debug.Log("RECV"); nPackets++; newPacketBufferMS.Position = 0; update_protocol_v3.Update update = Serializer.Deserialize <update_protocol_v3.Update>(new MemoryStream(newPacketBuffer, 0, nBytesReceived)); //Debug.Log ("received update of type " + update.id); newPacketFrame = update.mod_version; if (newPacketFrame > lastLoadedFrame) { // Swap the buffers and reset the positions. lastLoadedBufferMS.Position = 0; newPacketBufferMS.Position = 0; tempBuffer = lastLoadedBuffer; tempBufferMS = lastLoadedBufferMS; lastLoadedBuffer = newPacketBuffer; lastLoadedBufferMS = newPacketBufferMS; newPacketBuffer = tempBuffer; newPacketBufferMS = tempBufferMS; lastLoadedFrame = newPacketFrame; for (int j = 0; j < update.live_objects.Count; j++) { LiveObject or = update.live_objects[j]; string label = or.label; LiveObjectStorage ow; lock (lock_object) { if (!labelToLiveObject.TryGetValue(label, out ow)) { ow = new LiveObjectStorage(); labelToLiveObject[label] = ow; } else { ow = labelToLiveObject[label]; } if (update.lhs_frame) { ow.pos = new Vector3(-(float)or.x, (float)or.y, (float)or.z); ow.rot = new Quaternion(-(float)or.qx, (float)or.qy, (float)or.qz, -(float)or.qw); } else { ow.pos = new Vector3((float)or.x, (float)or.y, (float)or.z); ow.rot = new Quaternion((float)or.qx, (float)or.qy, (float)or.qz, (float)or.qw); } //Debug.Log (label + " positon: " + ow.pos); //Debug.Log (label + " rotation: " + ow.rot); if (or.button_bits > 0) { ow.button_bits = or.button_bits; } } } } if (stopReceive) { break; } } }