Beispiel #1
0
        public async Task DiscoveryJs()
        {
            var multicastService = new MulticastService();

            var serviceName = $"_{Guid.NewGuid()}._udp";

            serviceName = "_foo._udp";
            var peer1 = new Peer
            {
                Id        = "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
                Addresses = new MultiAddress[] { "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ" }
            };
            var peer2 = new Peer
            {
                Id        = "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuK",
                Addresses = new MultiAddress[] { "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuK" }
            };
            var done  = new ManualResetEvent(false);
            var mdns1 = new MdnsJs
            {
                MulticastService = multicastService,
                ServiceName      = serviceName,
                LocalPeer        = peer1
            };
            var mdns2 = new MdnsJs
            {
                MulticastService = multicastService,
                ServiceName      = serviceName,
                LocalPeer        = peer2
            };

            mdns1.PeerDiscovered += (s, e) =>
            {
                if (e.Address.PeerId == peer2.Id)
                {
                    done.Set();
                }
            };
            await mdns1.StartAsync();

            await mdns2.StartAsync();

            multicastService.Start();
            try
            {
                Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(2)), "timeout");
            }
            finally
            {
                await mdns1.StopAsync();

                await mdns2.StopAsync();

                multicastService.Stop();
            }
        }
        private void OnServiceAdded(object sender, ServiceAnnouncementEventArgs e)
        {
            var addresses = MulticastService.GetIPAddresses()
                            .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);

            if (!addresses.Contains(e.Announcement.Addresses?[0])) // Not a query from a local IP address
            {
                logger.Log($"Service added: {e.Announcement.Addresses?[0]} {e.Announcement.Txt.Where(x => x.StartsWith("fn=")).FirstOrDefault()?.ToString().Replace("fn=", "")} - {e.Announcement.Instance} {e.Announcement.Type}");
            }
        }
Beispiel #3
0
        static void Main(string[] args)
        {
            Console.WriteLine("Multicast DNS spike");

            // set logger factory
            var properties = new Common.Logging.Configuration.NameValueCollection
            {
                ["level"]          = "TRACE",
                ["showLogName"]    = "true",
                ["showDateTime"]   = "true",
                ["dateTimeFormat"] = "HH:mm:ss.fff"
            };

            LogManager.Adapter = new ConsoleOutLoggerFactoryAdapter(properties);

            var mdns = new MulticastService();

            foreach (var a in MulticastService.GetIPAddresses())
            {
                Console.WriteLine($"IP address {a}");
            }

            mdns.QueryReceived += (s, e) =>
            {
                var names = e.Message.Questions
                            .Select(q => q.Name + " " + q.Type);
                Console.WriteLine($"got a query for {String.Join(", ", names)}");
            };
            mdns.AnswerReceived += (s, e) =>
            {
                var names = e.Message.Answers
                            .Select(q => q.Name + " " + q.Type)
                            .Distinct();
                Console.WriteLine($"got answer for {String.Join(", ", names)}");
            };
            mdns.NetworkInterfaceDiscovered += (s, e) =>
            {
                foreach (var nic in e.NetworkInterfaces)
                {
                    Console.WriteLine($"discovered NIC '{nic.Name}'");
                }
            };

            var sd = new ServiceDiscovery(mdns);

            sd.Advertise(new ServiceProfile("x1", "_xservice._tcp", 5011));
            sd.Advertise(new ServiceProfile("x2", "_xservice._tcp", 666));
            var z1 = new ServiceProfile("z1", "_zservice.udp", 5012);

            z1.AddProperty("foo", "bar");
            sd.Advertise(z1);

            mdns.Start();
            Console.ReadKey();
        }
Beispiel #4
0
        public static void Main(string[] args)
        {
            var keyHandler = new KeyHandler();

            // todo: IOC
            var environmentService = SwimbaitModule.GetEnvironmentService();

            _multicastServer  = new MulticastServer(environmentService);
            _multicastService = new MulticastService(environmentService);
            var _musicCastHost = new MusicCastHost(environmentService);

            //Add command line configuration source to read command line parameters.
            var builder       = new ConfigurationBuilder();
            var portsToListen = new [] { 80, EnvironmentService.SwimbaitDlnaPort, 51100 };

            var urisToListen = portsToListen
                               .ToList()
                               .Select(p => $"http://{environmentService.IpAddress}:{p}");

            var uriToListenString = string.Join(";", urisToListen);

            var config = builder
                         .AddCommandLine(new[] { $"server.urls={uriToListenString}" })
                         .AddEnvironmentVariables()
                         .Build();

            _musicCastHost.RelayHost = IPAddress.Parse(config["Swimbait:RelayHost"]);

            // Dirty DI
            Startup._environmentService = environmentService;
            Startup._musicCastHost      = _musicCastHost;

            var host = new WebHostBuilder()
                       .UseConfiguration(config)
                       .UseKestrel()
                       .UseStartup <Startup>()
                       .Build();

            Console.WriteLine($"Starting the server. Listening on {uriToListenString}. Udp broadcasting to {environmentService.SubnetBroadcastIp}");
            host.Start();

            Console.WriteLine("Press 'Q' to stop the server");
            Console.WriteLine("Press 'M' to send SSDP Multicast discovery");
            Console.WriteLine("Press 'C' when ready to connect to the MusicCast app");

            _multicastServer.Start();

            keyHandler.KeyEvent += KeyHandler_KeyEvent;

            keyHandler.WaitForExit();

            host.Dispose();

            _multicastServer.Dispose();
        }
Beispiel #5
0
        static void Main(string[] args)
        {
            var mdns = new MulticastService();

            mdns.NetworkInterfaceDiscovered += (s, e)
                                               => mdns.SendQuery(ServiceDiscovery.ServiceName, type: DnsType.PTR);
            mdns.AnswerReceived   += OnGoodDnsMessage;
            mdns.QueryReceived    += OnGoodDnsMessage;
            mdns.MalformedMessage += OnBadDnsMessage;
            mdns.Start();
            Console.ReadKey();
        }
Beispiel #6
0
        private static void RunServer()
        {
            var service = "_appletv.local.appletv._local.appletv.local.appletv.local";
            var mdns    = new MulticastService();

            mdns.QueryReceived += (s, e) =>
            {
                var msg = e.Message;
                if (msg.Questions.Any(q => q.Name == service))
                {
                    var res       = msg.CreateResponse();
                    var addresses = MulticastService.GetIPAddresses()
                                    .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);
                    foreach (var address in addresses)
                    {
                        var ar = new ARecord
                        {
                            Name    = service,
                            Address = address
                        };
                        var writer = new PresentationWriter(new StringWriter());
                        writer.WriteString("123qweq");
                        ar.WriteData(writer);
                        ar.Name = "qweqeqweq";
                        res.Answers.Add(ar);
                    }
                    mdns.SendAnswer(res);
                }
            };
            advertiseThread = new Thread(new ThreadStart(() =>
            {
                sd     = new ServiceDiscovery(mdns);
                var sp = new ServiceProfile("_itxpt_multicast._tcp.", "_itxpt._tcp", 5353, new List <IPAddress> {
                    IPAddress.Parse("192.168.88.239")
                });
                //sp.AddProperty("host", "192.168.88.239");
                //sp.AddProperty("port", "14005");
                sp.Resources.Add(new ARecord {
                    Name = "_itxpt_multicast._tcp.", Address = IPAddress.Parse("192.168.88.239"), Class = DnsClass.ANY
                });
                sp.Resources.Add(new SRVRecord {
                    Name = "_itxpt_multicast._tcp.", Port = 5353, Priority = 0, Weight = 0, Class = DnsClass.ANY
                });
                sp.Resources.Add(new PTRRecord {
                    Name = "_itxpt_multicast._tcp.", DomainName = "192.168.88.239"
                });
                sd.Advertise(sp);
            }));
            advertiseThread.Start();

            mdns.Start();
        }
Beispiel #7
0
        private void DoAnnounce(string deviceId, string modelName, DomainName domain, DomainName deviceDomain)
        {
            var res       = new Message();
            var addresses = MulticastService.GetIPAddresses()
                            .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);

            foreach (var address in addresses)
            {
                res.Answers.Add(new PTRRecord
                {
                    Name       = AtemDeviceInfo.ServiceName,
                    DomainName = domain
                });
                res.AdditionalRecords.Add(new TXTRecord
                {
                    Name    = domain,
                    Strings = new List <string>
                    {
                        "txtvers=1",
                        $"name=Blackmagic {modelName}",
                        "class=AtemSwitcher",
                        "protocol version=0.0",
                        "internal version=FAKE",
                        $"unique id={deviceId}"
                    }
                });
                res.AdditionalRecords.Add(new ARecord
                {
                    Address = address,
                    Name    = deviceDomain,
                });
                res.AdditionalRecords.Add(new SRVRecord
                {
                    Name     = domain,
                    Port     = 9910,
                    Priority = 0,
                    Target   = deviceDomain,
                    Weight   = 0
                });

                /*
                 * res.AdditionalRecords.Add(new NSECRecord
                 * {
                 *  Name = domain
                 * });*/
            }
            _mdns.SendAnswer(res);
        }
Beispiel #8
0
        private void Light(MulticastService arg1, MulticastMessage msg)
        {
            if (!Selbsttest && DeviceInfo.Name == msg.Sender)
            {
                return;
            }

            if (msg.Data == "On")
            {
                Flashlight.TurnOnAsync();
            }
            else
            {
                Flashlight.TurnOffAsync();
            }
        }
        private void Mdns_QueryReceived(object sender, MessageEventArgs e)
        {
            var addresses = MulticastService.GetIPAddresses()
                            .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);

            if (!addresses.Contains(e.RemoteEndPoint.Address)) // Not a query from a local IP address
            {
                var msg = e.Message;
                if (msg.Questions.Any(q => q.Name.ToString().Contains(serviceType)))
                {
                    SendAnswer(addresses, msg, serviceType);
                }
                else if (msg.Questions.Any(q => q.Name.ToString().Contains(serviceTypeEmbedded)))
                {
                    SendAnswer(addresses, msg, serviceTypeEmbedded);
                }
            }
        }
Beispiel #10
0
        public static async Task <SRVRecord> Resolve(DomainName server, CancellationToken token = default)
        {
            var query = new Message
            {
                Opcode = MessageOperation.Query,
                QR     = false
            };

            query.Questions.Add(new Question {
                Name = server, Type = DnsType.SRV
            });
            var mdns = new MulticastService();

            mdns.Start();
            var target = await mdns.ResolveAsync(query, token);

            mdns.Stop();
            return(target.Answers.OfType <SRVRecord>().First());
        }
Beispiel #11
0
        private void AdvertiseService(IApplicationBuilder app)
        {
            var mdns = new MulticastService();

            mdns.Start();

            var serverAddressesFeature = app.ServerFeatures.Get <IServerAddressesFeature>();

            foreach (var address in serverAddressesFeature.Addresses)
            {
                var    uri = new Uri(address);
                var    serviceDiscovery = new ServiceDiscovery(mdns);
                string serviceType      = "_" + uri.Scheme + "._tcp";
                var    service          = new ServiceProfile("TelekinesisServer", serviceType, (ushort)uri.Port);
                service.AddProperty("OSVersion", Environment.OSVersion.ToString());
                service.AddProperty("Platform", Environment.OSVersion.Platform.ToString());
                service.AddProperty("MachineName", Environment.MachineName);
                serviceDiscovery.Advertise(service);
            }
        }
Beispiel #12
0
        public DiscoveryClient(string serviceName, ushort port, string serviceType, IEnumerable <IPAddress> ipAddresses)
        {
            ServiceName = serviceName;
            ServiceType = serviceType;
            Port        = port;

            mdns        = new MulticastService();
            IPAddresses = ipAddresses ?? MulticastService.GetIPAddresses();

            logger.Info("Creating service profile with" +
                        "\tServiceName=" + serviceName +
                        "\tServiceType=" + serviceType +
                        "\tPort=" + port +
                        "\tIPAddresses=" + string.Join(";", IPAddresses));

            serviceProfile = new ServiceProfile(ServiceName, ServiceType, Port, IPAddresses);

            advertiseThread = new Thread(Advertise);
            IsRunning       = false;
        }
        public void Advertise()
        {
            mdns = new MulticastService();
            mdns.QueryReceived    += Mdns_QueryReceived;
            mdns.AnswerReceived   += Mdns_AnswerReceived;
            mdns.MalformedMessage += Mdns_MalformedMessage;
            mdns.Start();

            // For future use:
            serviceBrowser = new ServiceBrowser();
            serviceBrowser.ServiceAdded   += OnServiceAdded;
            serviceBrowser.ServiceRemoved += OnServiceRemoved;
            serviceBrowser.ServiceChanged += OnServiceChanged;
            serviceBrowser.StartBrowse(serviceType);

            serviceBrowserEmbedded = new ServiceBrowser();
            serviceBrowserEmbedded.ServiceAdded   += OnServiceAdded;
            serviceBrowserEmbedded.ServiceRemoved += OnServiceRemoved;
            serviceBrowserEmbedded.ServiceChanged += OnServiceChanged;
            serviceBrowserEmbedded.StartBrowse(serviceTypeEmbedded);
        }
Beispiel #14
0
        /// <summary>
        /// Do a scan on the network.
        /// </summary>
        public void MdnsSearch()
        {
            ServiceBrowser serviceBrowser = new ServiceBrowser();

            serviceBrowser.ServiceAdded   += OnServiceAdded;
            serviceBrowser.ServiceRemoved += OnServiceRemoved;
            serviceBrowser.ServiceChanged += OnServiceChanged;
            serviceBrowser.StartBrowse(serviceType);

            ServiceBrowser serviceBrowserEmbedded = new ServiceBrowser();

            serviceBrowserEmbedded.ServiceAdded   += OnServiceAdded;
            serviceBrowserEmbedded.ServiceRemoved += OnServiceRemoved;
            serviceBrowserEmbedded.ServiceChanged += OnServiceChanged;
            serviceBrowserEmbedded.StartBrowse(serviceTypeEmbedded);

            var mdns = new MulticastService();

            mdns.AnswerReceived += Mdns_AnswerReceived;
            mdns.Start();
        }
Beispiel #15
0
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var mdns = new MulticastService();

            mdns.QueryReceived += (s, e) =>
            {
                Console.WriteLine("got a query");
            };
            mdns.AnswerReceived += (s, e) =>
            {
                Console.WriteLine("got an answer");
            };
            mdns.NetworkInterfaceDiscovered += (s, e) =>
            {
                mdns.SendQuery("ipfs.local");
            };
            mdns.Start();

            Console.ReadKey();
        }
Beispiel #16
0
        private async Task <Message> Lookup(string service)
        {
            try
            {
                var query = new Message();
                query.Questions.Add(new Question {
                    Name = service, Type = DnsType.ANY
                });
                var cancellation = new CancellationTokenSource(10000);

                using MulticastService mdns = new MulticastService();
                mdns.AnswerReceived        += Mdns_AnswerReceived;

                mdns.Start();
                Message response = await mdns.ResolveAsync(query, cancellation.Token).ConfigureAwait(false);

                mdns.Stop();
                return(response);
            }
            catch (Exception)
            {
                return(null);
            }
        }
Beispiel #17
0
        public void StartAnnounce(string modelName, string deviceId)
        {
            _mdns.UseIpv4 = true;
            _mdns.UseIpv6 = false;

            var safeModelName = modelName.Replace(' ', '-').ToUpper();

            var domain       = new DomainName($"Mock {modelName}.{AtemDeviceInfo.ServiceName}");
            var deviceDomain = new DomainName($"MOCK-{safeModelName}-{deviceId}.local");

            _mdns.QueryReceived += (s, e) =>
            {
                var msg = e.Message;
                if (msg.Questions.Any(q => q.Name == AtemDeviceInfo.ServiceName))
                {
                    var res       = msg.CreateResponse();
                    var addresses = MulticastService.GetIPAddresses()
                                    .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);
                    foreach (var address in addresses)
                    {
                        res.Answers.Add(new PTRRecord
                        {
                            Name       = AtemDeviceInfo.ServiceName,
                            DomainName = domain
                        });
                        res.AdditionalRecords.Add(new TXTRecord
                        {
                            Name    = domain,
                            Strings = new List <string>
                            {
                                "txtvers=1",
                                $"name=Mock Blackmagic {modelName}",
                                "class=AtemSwitcher",
                                "protocol version=0.0",
                                "internal version=FAKE",
                                $"unique id={deviceId}"
                            }
                        });
                        res.AdditionalRecords.Add(new ARecord
                        {
                            Address = address,
                            Name    = deviceDomain,
                        });
                        res.AdditionalRecords.Add(new SRVRecord
                        {
                            Name     = domain,
                            Port     = 9910,
                            Priority = 0,
                            Target   = deviceDomain,
                            Weight   = 0
                        });

                        /*
                         * res.AdditionalRecords.Add(new NSECRecord
                         * {
                         *  Name = domain
                         * });*/
                    }
                    _mdns.SendAnswer(res);
                }
            };
            _mdns.Start();
        }
Beispiel #18
0
        public Task StartMdnsAsync()
        {
            if (string.IsNullOrWhiteSpace(_deviceId))
            {
                throw new ArgumentNullException(_deviceId);
            }

            var rDeviceId = new Regex("^(([0-9a-fA-F][0-9a-fA-F]):){5}([0-9a-fA-F][0-9a-fA-F])$");
            var mDeviceId = rDeviceId.Match(_deviceId);

            if (!mDeviceId.Success)
            {
                throw new ArgumentException("Device id must be a mac address", _deviceId);
            }

            var deviceIdInstance = string.Join(string.Empty, mDeviceId.Groups[2].Captures) + mDeviceId.Groups[3].Value;

            _mdns = new MulticastService();
            var sd = new ServiceDiscovery(_mdns);

            foreach (var ip in MulticastService.GetIPAddresses())
            {
                Console.WriteLine($"IP address {ip}");
            }

            _mdns.NetworkInterfaceDiscovered += (s, e) =>
            {
                foreach (var nic in e.NetworkInterfaces)
                {
                    Console.WriteLine($"NIC '{nic.Name}'");
                }
            };

            // Internally 'ServiceProfile' create the SRV record
            var airTunes = new ServiceProfile($"{deviceIdInstance}@{_instance}", AirTunesType, _airTunesPort);

            airTunes.AddProperty("ch", "2");
            airTunes.AddProperty("cn", "2,3");
            airTunes.AddProperty("et", "0,3,5");
            airTunes.AddProperty("md", "0,1,2");
            airTunes.AddProperty("sr", "44100");
            airTunes.AddProperty("ss", "16");
            airTunes.AddProperty("da", "true");
            airTunes.AddProperty("sv", "false");
            airTunes.AddProperty("ft", "0x5A7FFFF7,0x1E"); // 0x4A7FFFF7, 0xE
            airTunes.AddProperty("am", "AppleTV5,3");
            airTunes.AddProperty("pk", "29fbb183a58b466e05b9ab667b3c429d18a6b785637333d3f0f3a34baa89f45e");
            airTunes.AddProperty("sf", "0x4");
            airTunes.AddProperty("tp", "UDP");
            airTunes.AddProperty("vn", "65537");
            airTunes.AddProperty("vs", "220.68");
            airTunes.AddProperty("vv", "2");

            /*
             * ch	2	audio channels: stereo
             * cn	0,1,2,3	audio codecs
             * et	0,3,5	supported encryption types
             * md	0,1,2	supported metadata types
             * pw	false	does the speaker require a password?
             * sr	44100	audio sample rate: 44100 Hz
             * ss	16	audio sample size: 16-bit
             */

            // Internally 'ServiceProfile' create the SRV record
            var airPlay = new ServiceProfile(_instance, AirPlayType, _airPlayPort);

            airPlay.AddProperty("deviceid", _deviceId);
            airPlay.AddProperty("features", "0x5A7FFFF7,0x1E"); // 0x4A7FFFF7
            airPlay.AddProperty("flags", "0x4");
            airPlay.AddProperty("model", "AppleTV5,3");
            airPlay.AddProperty("pk", "29fbb183a58b466e05b9ab667b3c429d18a6b785637333d3f0f3a34baa89f45e");
            airPlay.AddProperty("pi", "aa072a95-0318-4ec3-b042-4992495877d3");
            airPlay.AddProperty("srcvers", "220.68");
            airPlay.AddProperty("vv", "2");

            sd.Advertise(airTunes);
            sd.Advertise(airPlay);

            _mdns.Start();

            return(Task.CompletedTask);
        }
Beispiel #19
0
        public Client(string clientIp)
        {
            _clientIp = clientIp;
            mdns      = new MulticastService();
            var domainName = "_itxpt_multicast._tcp";

            servicename = "gnsslocation";
            mdns.NetworkInterfaceDiscovered += (s, e) => mdns.SendQuery(domainName);

            mdns.AnswerReceived += (s, e) =>
            {
                Console.WriteLine($"GET response from server {e.RemoteEndPoint.Address}:{e.RemoteEndPoint.Port}. Message: {e.Message.Answers.FirstOrDefault()}");
                List <ResourceRecord> answers = e.Message.Answers;
                this.ParseRecords(answers);

                Func <IPEndPoint, bool> predicate = null;
                foreach (ResourceRecord record in answers)
                {
                    if ((record is TXTRecord) && this.ForMe)
                    {
                        foreach (string str in ((TXTRecord)record).Strings)
                        {
                            char[]   separator = new char[] { '=' };
                            string[] strArray  = str.Split(separator);
                            if (strArray.Length == 2)
                            {
                                if (strArray[0] == "address")
                                {
                                    string text1 = strArray[1];
                                }
                                if (strArray[0] == "multicast")
                                {
                                    this.multicastIp = strArray[1];
                                }
                            }
                        }
                    }
                }
                answers = e.Message.AdditionalRecords;
                foreach (ResourceRecord record in answers)
                {
                    if ((record is TXTRecord) && this.ForMe)
                    {
                        foreach (string str in ((TXTRecord)record).Strings)
                        {
                            char[]   separator = new char[] { '=' };
                            string[] strArray  = str.Split(separator);
                            if (strArray.Length == 2)
                            {
                                if (strArray[0] == "address")
                                {
                                    string text1 = strArray[1];
                                }
                                if (strArray[0] == "multicast")
                                {
                                    this.multicastIp = strArray[1];
                                }
                            }
                        }
                    }
                }

                if ((this.srvRec != null) && (this.ForMe && ((this.srvRec.Port != 0) && (!string.IsNullOrEmpty(this.multicastIp) && (this.udpClient == null)))))
                {
                    if (predicate == null)
                    {
                        predicate = p => p.Port == this.srvRec.Port;
                    }
                    if (Enumerable.Any <IPEndPoint>(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners(), predicate))
                    {
                        Console.WriteLine(string.Format("{0}:{1} already in use. Try again later", this.multicastIp, this.srvRec.Port));
                    }
                    else
                    {
                        Console.WriteLine("FeedbackType.Client: " + string.Format("JoinMulticastGroup {0}:{1}", this.multicastIp, this.srvRec.Port));
                        udpClient = new UdpClient(this.srvRec.Port);
                        udpClient.JoinMulticastGroup(IPAddress.Parse(this.multicastIp), 50);
                        receiveThread = new Thread(new ThreadStart(this.Receive));
                        receiveThread.Start();
                    }
                }
            };

            advertiseThread = new Thread(new ThreadStart(() =>
            {
                sd     = new ServiceDiscovery(mdns);
                var sp = new ServiceProfile(servicename, domainName, 14005);
                sp.AddProperty("host", "192.168.88.239");
                sp.AddProperty("port", "14005");
                sp.Resources.Add(new ARecord {
                    Name = "_itxpt_multicast._tcp", Address = IPAddress.Parse("192.168.88.239"), Class = DnsClass.IN
                });
                sp.Resources.Add(new SRVRecord {
                    Name = "_itxpt_multicast._tcp", Port = 14005, Priority = 0, Weight = 0, Class = DnsClass.IN
                });
                sd.Advertise(sp);
            }));

            advertiseThread.Start();

            mdns.Start();
        }
Beispiel #20
0
        /// <summary>
        /// Discover devices connected to your local network or link-local devices, such as UsbNCM.
        /// By default looks for devices running Factory Orchestrator with network access enabled.
        /// </summary>
        /// <param name="linkLocalOnly">Only look for link-local devices, such as UsbNCM devices Default: false</param>
        /// <param name="displayHostname">Display the device hostname Default: true</param>
        /// <param name="displayIPv4">Display the device IPv4 address Default: true</param>
        /// <param name="displayIPv6">Display the device IPv6 address Default: false</param>
        /// <param name="displayPort">Display the port the service is discovered on Default: false</param>
        /// <param name="timeout">The amount of time in milliseconds to wait for responses (use greater than 2000 ms for WiFi). Default: Infinite</param>
        /// <param name="queryInterval">The amount of time in milliseconds to wait between queries. Default: 1000ms</param>
        /// <param name="service">The DNS-SD service string used for discovery Default: _factorch._tcp.local</param>
        ///
        static async Task Main(bool linkLocalOnly   = false,
                               bool displayHostname = true,
                               bool displayIPv4     = true,
                               bool displayIPv6     = false,
                               bool displayPort     = false,
                               int timeout          = -1,
                               int queryInterval    = 1000,
                               string service       = "_factorch._tcp.local"
                               )
        {
            if (!displayHostname && !displayIPv4 && !displayIPv6)
            {
                Console.Error.WriteLine("Error: at least one display method must be used!");
            }

            if ((queryInterval < 500))
            {
                Console.WriteLine("Warning: a query interval below 500ms may result in 'erroneous' data, as ip address can change on first enumeration.");
            }

            if (linkLocalOnly)
            {
                Console.WriteLine($"Looking for {service} devices connected via link-local network interfaces such as USBNCM...");
            }
            else
            {
                Console.WriteLine($"Looking for {service} devices connected to any network interface...");
            }
            Console.WriteLine();

            // Setup global variables
            TimeSinceReCheck = 0;
            QueryInterval    = queryInterval;
            ServiceToQuery   = service;
            LinkLocalOnly    = linkLocalOnly;
            DisplayHostname  = displayHostname;
            DisplayIPv4      = displayIPv4;
            DisplayIPv6      = displayIPv6;
            DisplayPort      = displayPort;
            DeviceList       = new ConcurrentDictionary <string, bool>();
            PrintQueue       = new ConcurrentQueue <string>();
            MDns             = new MulticastService();

            // Send the first DNS-SD query
            MDns.AnswerReceived += MDns_AnswerReceived;
            MDns.Start();
            MDns.SendQuery(ServiceToQuery);

            // Set a timer to continuously query for new devices
            // Also set the interval that we wish to recheck for devices
            ReCheckInterval     = Math.Max(2000, queryInterval * 2);
            QueryTimer          = new System.Timers.Timer(QueryInterval);
            QueryTimer.Elapsed += FindDeviceTimer_Elapsed;
            QueryTimer.Start();
            PrintTimer          = new System.Timers.Timer(200);
            PrintTimer.Elapsed += PrintTimer_Elapsed;
            PrintTimer.Start();

            if (timeout == -1)
            {
                Console.WriteLine("Press any key to exit.");
                Console.WriteLine();
                Console.ReadLine();
            }
            else
            {
                await Task.Delay(timeout);
            }

            MDns.Stop();
            QueryTimer.Stop();

            Console.WriteLine($"Done looking for devices, exiting.");
        }
Beispiel #21
0
        public static async Task <List <NanoData> > Discover(int timeout = 5)
        {
            var output = new List <NanoData>();
            var mDns   = new MulticastService();
            var sd     = new ServiceDiscovery(mDns);

            mDns.NetworkInterfaceDiscovered += (s, e) => {
                // Ask for the name of all services.
                sd.QueryServiceInstances("_nanoleafapi._tcp");
            };

            sd.ServiceDiscovered += (s, serviceName) => { mDns.SendQuery(serviceName, type: DnsType.PTR); };

            sd.ServiceInstanceDiscovered += (s, e) => {
                var name  = e.ServiceInstanceName.ToString();
                var nData = new NanoData {
                    IpAddress = string.Empty
                };
                if (!name.Contains("nanoleafapi", StringComparison.InvariantCulture))
                {
                    return;
                }
                foreach (var msg in e.Message.AdditionalRecords)
                {
                    switch (msg.Type)
                    {
                    case DnsType.A:
                        var aString = msg.ToString();
                        var aValues = aString.Split(" ");
                        nData.IpAddress = aValues[4];
                        nData.Name      = aValues[0].Split(".")[0];
                        break;

                    case DnsType.TXT:
                        var txtString = msg.ToString();
                        var txtValues = txtString.Split(" ");
                        nData.Version = txtValues[5]
                                        .Replace("srcvers=", string.Empty, StringComparison.InvariantCulture);
                        nData.Type = txtValues[4].Replace("md=", string.Empty, StringComparison.InvariantCulture);
                        nData.Id   = txtValues[3].Replace("id=", string.Empty, StringComparison.InvariantCulture);
                        break;

                    case DnsType.AAAA:
                        var mString = msg.ToString();
                        var mValues = mString.Split(" ");
                        nData.IpV6Address = mValues[4];
                        // Remove rest of FQDN
                        nData.Name = mValues[0].Split(".")[0];
                        break;

                    case DnsType.SRV:
                        var sString = msg.ToString();
                        var sValues = sString.Split(" ");
                        nData.Port     = int.Parse(sValues[6], CultureInfo.InvariantCulture);
                        nData.Hostname = sValues[7];
                        break;
                    }
                }

                if (string.IsNullOrEmpty(nData.IpAddress) && !string.IsNullOrEmpty(nData.Hostname))
                {
                    nData.IpAddress = nData.Hostname;
                }

                if (!string.IsNullOrEmpty(nData.IpAddress) && !string.IsNullOrEmpty(nData.Id))
                {
                    output.Add(nData);
                }
            };

            mDns.Start();
            LogUtil.Write("Nano: Discovery Started.");
            await Task.Delay(timeout * 1000).ConfigureAwait(false);

            mDns.Stop();
            sd.Dispose();
            mDns.Dispose();
            LogUtil.Write($"Nano: Discovery complete, found {output.Count} devices.");
            return(output);
        }
        public MDNSServicePublisher()
        {
            Task.Run(() => {
                var mdns     = new MulticastService();
                mdns.UseIpv6 = false;
                foreach (var a in MulticastService.GetIPAddresses())
                {
                    Debug.WriteLine($"IP address {a}");
                }

                mdns.QueryReceived += (s, e) =>
                {
                    var names = e.Message.Questions
                                .Select(q => q.Name + " " + q.Type);
                    Debug.WriteLine($"got a query for {String.Join(", ", names)}");
                };
                mdns.AnswerReceived += (s, e) =>
                {
                    var names = e.Message.Answers
                                .Select(q => q.Name + " " + q.Type)
                                .Distinct();
                    Debug.WriteLine($"got answer for {String.Join(", ", names)}");
                };
                mdns.NetworkInterfaceDiscovered += (s, e) =>
                {
                    foreach (var nic in e.NetworkInterfaces)
                    {
                        Debug.WriteLine($"discovered NIC '{nic.Name}'");
                    }
                };

                var sd = new ServiceDiscovery(mdns);

                var address = new List <IPAddress>();
                address.Add(IPAddress.Parse("10.113.81.192"));

                var s1 = new ServiceProfile("JOSHMobile", "_airplay._tcp.", 7000, address);
                s1.AddProperty("deviceid", "00:05:A6:16:45:8F");
                s1.AddProperty("features", "0xA7FFFF7,0xE");
                s1.AddProperty("flags", "0x4");
                s1.AddProperty("model", "AppleTV5,3");
                s1.AddProperty("pi", "6b448552-85ce-4143-a896-e28d12e8a0ab");
                s1.AddProperty("pk", "F381DC574DEAF9C70B75297755BC7C7C35BB1D0DB500258F3AB46B5FE7C7355B");
                s1.AddProperty("srcvers", "220.68");
                s1.AddProperty("vv", "2");



                var s2 = new ServiceProfile("0005A616458F@JOSHMobile", "_raop._tcp.", 7000, address);
                s2.AddProperty("am", "AppleTV5,3");
                s2.AddProperty("ch", "2");
                s2.AddProperty("cn", "0,1,2,3");
                s2.AddProperty("da", "true");
                s2.AddProperty("ek", "1");
                s2.AddProperty("et", "0,3,5");
                s2.AddProperty("md", "0,1,2");
                s2.AddProperty("pw", "false");
                s2.AddProperty("sm", "false");
                s2.AddProperty("sr", "44100");
                s2.AddProperty("ss", "16");
                s2.AddProperty("sv", "false");
                s2.AddProperty("tp", "UDP");
                s2.AddProperty("txvers", "1");
                s2.AddProperty("vn", "65537");
                s2.AddProperty("vs", "220.68");
                s2.AddProperty("sf", "0x4");
                s2.AddProperty("ft", "0xA7FFFF7,0xE");
                s2.AddProperty("pk", "F381DC574DEAF9C70B75297755BC7C7C35BB1D0DB500258F3AB46B5FE7C7355B");
                s2.AddProperty("vv", "2");

                sd.Advertise(s2);
                sd.Advertise(s1);
                mdns.Start();
            }
                     );
        }
Beispiel #23
0
        /// <summary>
        ///   Starts the network services.
        /// </summary>
        /// <returns>
        ///   A task that represents the asynchronous operation.
        /// </returns>
        /// <remarks>
        ///   Starts the various IPFS and PeerTalk network services.  This should
        ///   be called after any configuration changes.
        /// </remarks>
        /// <exception cref="Exception">
        ///   When the engine is already started.
        /// </exception>
        public async Task StartAsync()
        {
            if (stopTasks.Count > 0)
            {
                throw new Exception("IPFS engine is already started.");
            }

            var localPeer = await LocalPeer;

            log.Debug("starting " + localPeer.Id);

            // Everybody needs the swarm.
            var swarm = await SwarmService;

            stopTasks.Add(async() => await swarm.StopAsync());
            await swarm.StartAsync();

            var multicast = new MulticastService();

#pragma warning disable CS1998
            stopTasks.Add(async() => multicast.Dispose());
#pragma warning restore CS1998

            var tasks = new List <Func <Task> >
            {
                async() =>
                {
                    var bootstrap = new PeerTalk.Discovery.Bootstrap
                    {
                        Addresses = await this.Bootstrap.ListAsync()
                    };
                    bootstrap.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await bootstrap.StopAsync());
                    await bootstrap.StartAsync();
                },
                async() =>
                {
                    var mdns = new PeerTalk.Discovery.MdnsNext
                    {
                        LocalPeer        = localPeer,
                        MulticastService = multicast
                    };
                    mdns.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await mdns.StopAsync());
                    await mdns.StartAsync();
                },
                async() =>
                {
                    var mdns = new PeerTalk.Discovery.MdnsJs
                    {
                        LocalPeer        = localPeer,
                        MulticastService = multicast
                    };
                    mdns.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await mdns.StopAsync());
                    await mdns.StartAsync();
                },
                async() =>
                {
                    var mdns = new PeerTalk.Discovery.MdnsGo
                    {
                        LocalPeer        = localPeer,
                        MulticastService = multicast
                    };
                    mdns.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await mdns.StopAsync());
                    await mdns.StartAsync();
                },
                async() =>
                {
                    var bitswap = await BitswapService;
                    stopTasks.Add(async() => await bitswap.StopAsync());
                    await bitswap.StartAsync();
                },
                async() =>
                {
                    var dht = await DhtService;
                    stopTasks.Add(async() => await dht.StopAsync());
                    await dht.StartAsync();
                },
            };

            log.Debug("waiting for services to start");
            await Task.WhenAll(tasks.Select(t => t()));

            // TODO: Would be nice to make this deterministic.
            //await Task.Delay(TimeSpan.FromMilliseconds(100));
            //log.Debug("all service started");

            // Starting listening to the swarm.
            var json = await Config.GetAsync("Addresses.Swarm");

            var numberListeners = 0;
            foreach (string a in json)
            {
                try
                {
                    await swarm.StartListeningAsync(a);

                    ++numberListeners;
                }
                catch (Exception e)
                {
                    log.Warn($"Listener failure for '{a}'", e);
                    // eat the exception
                }
            }
            if (numberListeners == 0)
            {
                log.Error("No listeners were created.");
            }

            // Now that the listener addresses are established, the mdns discovery can begin.
            // TODO: Maybe all discovery services should be start here.
            multicast.Start();

            log.Debug("started");
        }
Beispiel #24
0
 public NanoleafDiscovery(ColorService cs) : base(cs)
 {
     _controlService = cs.ControlService;
     _mDns           = _controlService.MulticastService;
     _sd             = _controlService.ServiceDiscovery;
 }
 public MainWindow()
 {
     InitializeComponent();
     service = new MulticastService();
     service.StartService();
 }
Beispiel #26
0
        public static void Main(string[] args)
        {
            var mdns = new MulticastService();
            var sd   = new ServiceDiscovery(mdns);

            mdns.NetworkInterfaceDiscovered += (s, e) =>
            {
                foreach (var nic in e.NetworkInterfaces)
                {
                    Console.WriteLine($"NIC '{nic.Name}'");
                }

                // Ask for the name of all services.
                sd.QueryAllServices();
            };

            sd.ServiceDiscovered += (s, serviceName) =>
            {
                Console.WriteLine($"service '{serviceName}'");

                // Ask for the name of instances of the service.
                mdns.SendQuery(serviceName, type: DnsType.PTR);
            };

            mdns.AnswerReceived += (s, e) =>
            {
                // Is this an answer to a instances query?
                var pointers = e.Message.Answers.OfType <PTRRecord>().Where(p => p.Name != ServiceDiscovery.ServiceName);
                foreach (var pointer in pointers)
                {
                    Console.WriteLine($"service instance '{pointer.DomainName}'");

                    // Ask for the service instance details.
                    mdns.SendQuery(pointer.DomainName, type: DnsType.SRV);
                }

                // Is this an answer to a service instance details?
                var servers = e.Message.Answers.OfType <SRVRecord>();
                foreach (var server in servers)
                {
                    Console.WriteLine($"host '{server.Target}' for '{server.Name}'");

                    // Ask for the host IP addresses.
                    mdns.SendQuery(server.Target, type: DnsType.A);
                    mdns.SendQuery(server.Target, type: DnsType.AAAA);
                }

                // Is this an answer to host addresses?
                var addresses = e.Message.Answers.OfType <AddressRecord>();
                foreach (var address in addresses)
                {
                    Console.WriteLine($"host '{address.Name}' at {address.Address}");
                }
            };

            try
            {
                mdns.Start();
                Console.ReadKey();
            }
            finally
            {
                sd.Dispose();
                mdns.Stop();
            }
        }
 private void LogMessage(MulticastService arg1, MulticastMessage arg2)
 {
     Log.Add(arg2);
 }
Beispiel #28
0
        /// <summary>
        ///   Starts the network services.
        /// </summary>
        /// <returns>
        ///   A task that represents the asynchronous operation.
        /// </returns>
        /// <remarks>
        ///   Starts the various IPFS and PeerTalk network services.  This should
        ///   be called after any configuration changes.
        /// </remarks>
        /// <exception cref="Exception">
        ///   When the engine is already started.
        /// </exception>
        public async Task StartAsync()
        {
            if (stopTasks.Count > 0)
            {
                throw new Exception("IPFS engine is already started.");
            }

            var localPeer = await LocalPeer.ConfigureAwait(false);

            log.Debug("starting " + localPeer.Id);

            // Everybody needs the swarm.
            var swarm = await SwarmService.ConfigureAwait(false);

            stopTasks.Add(async() =>
            {
                await swarm.StopAsync().ConfigureAwait(false);
            });
            await swarm.StartAsync().ConfigureAwait(false);

            // Start the primary services.
            var tasks = new List <Func <Task> >
            {
                async() =>
                {
                    var bitswap = await BitswapService.ConfigureAwait(false);

                    stopTasks.Add(async() => await bitswap.StopAsync().ConfigureAwait(false));
                    await bitswap.StartAsync().ConfigureAwait(false);
                },
                async() =>
                {
                    var dht = await DhtService.ConfigureAwait(false);

                    stopTasks.Add(async() => await dht.StopAsync().ConfigureAwait(false));
                    await dht.StartAsync().ConfigureAwait(false);
                },
                async() =>
                {
                    var pubsub = await PubSubService.ConfigureAwait(false);

                    stopTasks.Add(async() => await pubsub.StopAsync().ConfigureAwait(false));
                    await pubsub.StartAsync().ConfigureAwait(false);
                },
            };

            log.Debug("waiting for services to start");
            await Task.WhenAll(tasks.Select(t => t())).ConfigureAwait(false);

            // Starting listening to the swarm.
            var json = await Config.GetAsync("Addresses.Swarm").ConfigureAwait(false);

            var numberListeners = 0;

            foreach (string a in json)
            {
                try
                {
                    await swarm.StartListeningAsync(a).ConfigureAwait(false);

                    ++numberListeners;
                }
                catch (Exception e)
                {
                    log.Warn($"Listener failure for '{a}'", e);
                    // eat the exception
                }
            }
            if (numberListeners == 0)
            {
                log.Error("No listeners were created.");
            }

            // Now that the listener addresses are established, the discovery
            // services can begin.
            MulticastService multicast = null;

            if (!Options.Discovery.DisableMdns)
            {
                multicast = new MulticastService();
#pragma warning disable CS1998
                stopTasks.Add(async() => multicast.Dispose());
#pragma warning restore CS1998
            }

            var autodialer = new AutoDialer(swarm)
            {
                MinConnections = Options.Swarm.MinConnections
            };
#pragma warning disable CS1998
            stopTasks.Add(async() => autodialer.Dispose());
#pragma warning restore CS1998

            tasks = new List <Func <Task> >
            {
                // Bootstrap discovery
                async() =>
                {
                    var bootstrap = new PeerTalk.Discovery.Bootstrap
                    {
                        Addresses = await this.Bootstrap.ListAsync()
                    };
                    bootstrap.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await bootstrap.StopAsync().ConfigureAwait(false));
                    await bootstrap.StartAsync().ConfigureAwait(false);
                },
                // New multicast DNS discovery
                async() =>
                {
                    if (Options.Discovery.DisableMdns)
                    {
                        return;
                    }
                    var mdns = new PeerTalk.Discovery.MdnsNext
                    {
                        LocalPeer        = localPeer,
                        MulticastService = multicast
                    };
                    if (Options.Swarm.PrivateNetworkKey != null)
                    {
                        mdns.ServiceName = $"_p2p-{Options.Swarm.PrivateNetworkKey.Fingerprint().ToHexString()}._udp";
                    }
                    mdns.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await mdns.StopAsync().ConfigureAwait(false));
                    await mdns.StartAsync().ConfigureAwait(false);
                },
                // Old style JS multicast DNS discovery
                async() =>
                {
                    if (Options.Discovery.DisableMdns || Options.Swarm.PrivateNetworkKey != null)
                    {
                        return;
                    }
                    var mdns = new PeerTalk.Discovery.MdnsJs
                    {
                        LocalPeer        = localPeer,
                        MulticastService = multicast
                    };
                    mdns.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await mdns.StopAsync().ConfigureAwait(false));
                    await mdns.StartAsync().ConfigureAwait(false);
                },
                // Old style GO multicast DNS discovery
                async() =>
                {
                    if (Options.Discovery.DisableMdns || Options.Swarm.PrivateNetworkKey != null)
                    {
                        return;
                    }
                    var mdns = new PeerTalk.Discovery.MdnsGo
                    {
                        LocalPeer        = localPeer,
                        MulticastService = multicast
                    };
                    mdns.PeerDiscovered += OnPeerDiscovered;
                    stopTasks.Add(async() => await mdns.StopAsync().ConfigureAwait(false));
                    await mdns.StartAsync().ConfigureAwait(false);
                },
                async() =>
                {
                    if (Options.Discovery.DisableRandomWalk)
                    {
                        return;
                    }
                    var randomWalk = new RandomWalk {
                        Dht = Dht
                    };
                    stopTasks.Add(async() => await randomWalk.StopAsync().ConfigureAwait(false));
                    await randomWalk.StartAsync().ConfigureAwait(false);
                }
            };
            log.Debug("waiting for discovery services to start");
            await Task.WhenAll(tasks.Select(t => t())).ConfigureAwait(false);

            multicast?.Start();

            log.Debug("started");
        }
Beispiel #29
0
 protected override void OnStart()
 {
     service = new MulticastService();
     service.StartService();
 }
Beispiel #30
0
        /// <summary>
        ///     Starts the network services.
        /// </summary>
        /// <returns>
        ///     A task that represents the asynchronous operation.
        /// </returns>
        /// <remarks>
        ///     Starts the various IPFS and Lib.P2P network services.  This should
        ///     be called after any configuration changes.
        /// </remarks>
        /// <exception cref="Exception">
        ///     When the engine is already started.
        /// </exception>
        public async Task StartAsync()
        {
            _dfsState.IsStarted = true;
            if (_stopTasks.Count > 0)
            {
                throw new Exception("IPFS engine is already started.");
            }

            // Repository must be at the correct version.
            await MigrationManager.MirgrateToVersionAsync(MigrationManager.LatestVersion).ConfigureAwait(false);

            Log.Debug("starting " + LocalPeer.Id);

            // Everybody needs the swarm.
            _stopTasks.Add(async() => { await SwarmService.StopAsync().ConfigureAwait(false); });
            await SwarmService.StartAsync().ConfigureAwait(false);

            var peerManager = new PeerManager
            {
                SwarmService = SwarmService
            };
            await peerManager.StartAsync().ConfigureAwait(false);

            _stopTasks.Add(async() => { await peerManager.StopAsync().ConfigureAwait(false); });

            // Start the primary services.
            var tasks = new List <Func <Task> >
            {
                async() =>
                {
                    _stopTasks.Add(async() => await BitSwapService.StopAsync().ConfigureAwait(false));
                    await BitSwapService.StartAsync().ConfigureAwait(false);
                },
                async() =>
                {
                    _stopTasks.Add(async() => await DhtService.StopAsync().ConfigureAwait(false));
                    await DhtService.StartAsync().ConfigureAwait(false);
                },
                async() =>
                {
                    _stopTasks.Add(async() => await PingService.StopAsync().ConfigureAwait(false));
                    await PingService.StartAsync().ConfigureAwait(false);
                },
                async() =>
                {
                    _stopTasks.Add(async() => await PubSubService.StopAsync().ConfigureAwait(false));
                    await PubSubService.StartAsync().ConfigureAwait(false);
                }
            };

            Log.Debug("waiting for services to start");
            await Task.WhenAll(tasks.Select(t => t())).ConfigureAwait(false);

            // Starting listening to the swarm.
            var json = await ConfigApi.GetAsync("Addresses.Swarm").ConfigureAwait(false);

            var numberListeners = 0;

            foreach (string a in json)
            {
                try
                {
                    await SwarmService.StartListeningAsync(a).ConfigureAwait(false);

                    ++numberListeners;
                }
                catch (Exception e)
                {
                    Log.Warning($"Listener failure for '{a}'", e);
                }
            }

            if (numberListeners == 0)
            {
                Log.Error("No listeners were created.");
            }

            // Now that the listener addresses are established, the discovery
            // services can begin.
            MulticastService multicast = null;

            if (!Options.Discovery.DisableMdns)
            {
                multicast = new MulticastService();
#pragma warning disable CS1998
                _stopTasks.Add(async() => multicast.Dispose());
#pragma warning restore CS1998
            }

            var autodialer = new AutoDialer(SwarmService)
            {
                MinConnections = Options.Swarm.MinConnections
            };
#pragma warning disable CS1998
            _stopTasks.Add(async() => autodialer.Dispose());
#pragma warning restore CS1998

            tasks = new List <Func <Task> >
            {
                // Bootstrap discovery
                async() =>
                {
                    var bootstrap = new Bootstrap
                    {
                        Addresses = await BootstrapApi.ListAsync()
                    };
                    bootstrap.PeerDiscovered += OnPeerDiscovered;
                    _stopTasks.Add(async() => await bootstrap.StopAsync().ConfigureAwait(false));
                    await bootstrap.StartAsync().ConfigureAwait(false);
                },

                async() =>
                {
                    if (Options.Discovery.DisableRandomWalk)
                    {
                        return;
                    }
                    var randomWalk = new RandomWalk {
                        Dht = DhtApi
                    };
                    _stopTasks.Add(async() => await randomWalk.StopAsync().ConfigureAwait(false));
                    await randomWalk.StartAsync().ConfigureAwait(false);
                }
            };
            Log.Debug("waiting for discovery services to start");
            await Task.WhenAll(tasks.Select(t => t())).ConfigureAwait(false);

            multicast?.Start();

            Log.Debug("started");
        }