/// <summary> /// Searches asynchronously. /// </summary> /// <param name="destinations">The destinations.</param> public void SearchAsync(params IPEndPoint[] destinations) { lock (this.SearchLock) { // If we're already searching then this is not allowed so throw an error if (this.IsSearching) { throw new InvalidOperationException("Search is already in progress."); } this.IsSearching = true; this.Server.DataReceived += OnServerDataReceived; // TODO: Come up with a good calculation for this // Just double our mx value for the timeout for now this.CreateSearchTimeout(TimeSpan.FromSeconds(this.Mx * 2)); } // If no destinations were specified then default to the IPv4 discovery if (destinations == null || destinations.Length == 0) { destinations = new IPEndPoint[] { Protocol.DiscoveryEndpoints.IPv4 } } ; // Start the server this.Server.StartListening(); // Do we really need to join the multicast group to send out multicast messages? Seems that way... foreach (IPEndPoint dest in destinations.Where(ep => IPAddressHelpers.IsMulticast(ep.Address))) { this.Server.JoinMulticastGroupAllInterfaces(dest); } // If we're sending out any searches to the broadcast address then be sure to enable broadcasts if (!this.Server.EnableBroadcast) { this.Server.EnableBroadcast = destinations.Any(ep => ep.Address.Equals(IPAddress.Broadcast)); } // Now send out our search data foreach (IPEndPoint dest in destinations) { // Make sure we respect our option as to whether we use the destination as the host value IPEndPoint host = (this.UseRemoteEndpointAsHost ? dest : this.HostEndpoint); string req = Protocol.CreateDiscoveryRequest(host, this.SearchType, this.Mx); byte[] bytes = Encoding.ASCII.GetBytes(req); // TODO: Should we make this configurable? // NOTE: It's recommended to send two searches this.Server.Send(bytes, bytes.Length, dest); this.Server.Send(bytes, bytes.Length, dest); } }