private void SetupSessions() { const int SIO_UDP_CONNRESET = -1744830452; byte[] inValue = new byte[] { 0, 0, 0, 0 }; // == false byte[] outValue = new byte[] { 0, 0, 0, 0 }; // initialize to 0 IPAddress[] ips = NetInfo.GetLocalAddresses(); foreach (IPAddress addr in ips) { if (addr.AddressFamily == AddressFamily.InterNetwork || addr.ScopeId != 0) { if (sessions.ContainsKey(addr) == false) { try { if (addr.AddressFamily == AddressFamily.InterNetwork) { UdpClient session = new UdpClient(AddressFamily.InterNetwork); try { session.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); } try { session.ExclusiveAddressUse = false; } catch (SocketException ex) { session.Client.Close(); OpenSource.Utilities.EventLogger.Log(ex); } if (!Utils.IsMono()) { session.Client.Bind(new IPEndPoint(addr, 1900)); } else { session.Client.Bind(new IPEndPoint(IPAddress.Any, 1900)); } session.EnableBroadcast = true; session.JoinMulticastGroup(Utils.UpnpMulticastV4Addr, addr); try { session.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue); } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); // session.Client.Close(); } session.BeginReceive(new AsyncCallback(OnReceiveSink), new object[2] { session, new IPEndPoint(addr, ((IPEndPoint)session.Client.LocalEndPoint).Port) }); sessions[addr] = session; UdpClient usession = new UdpClient(AddressFamily.InterNetwork); usession.Client.Bind(new IPEndPoint(addr, 0)); try { usession.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue); } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); // usession.Client.Close(); } usession.BeginReceive(new AsyncCallback(OnReceiveSink), new object[2] { usession, new IPEndPoint(addr, ((IPEndPoint)session.Client.LocalEndPoint).Port) }); usessions[addr] = usession; } if (addr.AddressFamily == AddressFamily.InterNetworkV6) { UdpClient session = new UdpClient(AddressFamily.InterNetworkV6); try { session.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); } try { session.ExclusiveAddressUse = false; } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); } if (!Utils.IsMono()) { session.Client.Bind(new IPEndPoint(addr, 1900)); } else { session.Client.Bind(new IPEndPoint(IPAddress.IPv6Any, 1900)); } session.EnableBroadcast = true; if (addr.IsIPv6LinkLocal) { session.JoinMulticastGroup((int)addr.ScopeId, Utils.UpnpMulticastV6Addr2); } else { session.JoinMulticastGroup((int)addr.ScopeId, Utils.UpnpMulticastV6Addr1); } try { session.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue); } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); // session.Close(); } session.BeginReceive(new AsyncCallback(OnReceiveSink), new object[2] { session, new IPEndPoint(addr, ((IPEndPoint)session.Client.LocalEndPoint).Port) }); sessions[addr] = session; UdpClient usession = new UdpClient(AddressFamily.InterNetworkV6); usession.Client.Bind(new IPEndPoint(addr, 0)); try { usession.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue); } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); // usession.Close(); } usession.BeginReceive(new AsyncCallback(OnReceiveSink), new object[2] { usession, new IPEndPoint(addr, ((IPEndPoint)session.Client.LocalEndPoint).Port) }); usessions[addr] = usession; } } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); } // Sometimes the bind will thru an exception. In this case, we want to skip that interface and move on. } } } }
/// <summary> /// Searches for a SearchTarget Asynchronously /// </summary> /// <param name="SearchTarget">The Target</param> public void FindDeviceAsync(String SearchTarget, IPEndPoint RemoteEP) { HTTPMessage request = new HTTPMessage(); request.Directive = "M-SEARCH"; request.DirectiveObj = "*"; request.AddTag("ST", SearchTarget); request.AddTag("MX", MX.ToString()); request.AddTag("MAN", "\"ssdp:discover\""); if (RemoteEP.AddressFamily == AddressFamily.InterNetwork) { request.AddTag("HOST", RemoteEP.ToString()); // "239.255.255.250:1900" } if (RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) { request.AddTag("HOST", string.Format("[{0}]:{1}", RemoteEP.Address.ToString(), RemoteEP.Port)); // "[FF05::C]:1900" } byte[] buffer = UTF8Encoding.UTF8.GetBytes(request.StringPacket); IPAddress[] LocalAddresses = NetInfo.GetLocalAddresses(); foreach (IPAddress localaddr in LocalAddresses) { try { UdpClient session = (UdpClient)SSDPSessions[localaddr]; if (session == null) { session = new UdpClient(new IPEndPoint(localaddr, 0)); session.EnableBroadcast = true; session.BeginReceive(new AsyncCallback(OnReceiveSink), session); SSDPSessions[localaddr] = session; } if (RemoteEP.AddressFamily != session.Client.AddressFamily) { continue; } if ((RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) && ((IPEndPoint)session.Client.LocalEndPoint).Address.IsIPv6LinkLocal == true && RemoteEP != Utils.UpnpMulticastV6EndPoint2) { continue; } if ((RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) && ((IPEndPoint)session.Client.LocalEndPoint).Address.IsIPv6LinkLocal == false && RemoteEP != Utils.UpnpMulticastV6EndPoint1) { continue; } IPEndPoint lep = (IPEndPoint)session.Client.LocalEndPoint; if (session.Client.AddressFamily == AddressFamily.InterNetwork) { session.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, localaddr.GetAddressBytes()); } else if (session.Client.AddressFamily == AddressFamily.InterNetworkV6) { session.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface, BitConverter.GetBytes((int)localaddr.ScopeId)); } session.Send(buffer, buffer.Length, RemoteEP); session.Send(buffer, buffer.Length, RemoteEP); } catch (Exception ex) { OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "CP Failure: " + localaddr.ToString()); OpenSource.Utilities.EventLogger.Log(ex); } } }