private void onServiceTimer(object source, ElapsedEventArgs e) { List <Tuple <string, string> > removed = new List <Tuple <string, string> >(); lock (_locker) { Parallel.ForEach(foundServices, (service) => { foreach (var location in service.Value) { if (location.Value < DateTimeOffset.UtcNow.ToUnixTimeSeconds() - TIMEOUT_SEC) { if (service.Value.TryRemove(location.Key, out var val)) { removed.Add(new Tuple <string, string>(service.Key, location.Key)); } } } }); } if (removed.Count > 0) { foreach (var removedUrl in removed) { ServiceLost?.Invoke(removedUrl.Item1, removedUrl.Item2); } } }
private void DiscoverThread() { while (IsStarted) { var devices = BluetoothAdapter.DiscoverDevices(); if (!IsStarted) { return; } //Remove lost devices. foreach (var device in _discoveredServices.ToList()) { if (!devices.Exists(x => x.Address == device.DiscoveryInfo.Address && x.Name == device.DiscoveryInfo.Name)) { _discoveredServices.Remove(device); ServiceLost?.Invoke(this, new ResonanceDiscoveredServiceEventArgs <ResonanceBluetoothDiscoveredDevice, BluetoothDevice>(device)); } } //Add new devices. foreach (var device in devices) { if (!_discoveredServices.Exists(x => x.DiscoveryInfo.Address == device.Address && x.DiscoveryInfo.Name == device.Name)) { var newDevice = new ResonanceBluetoothDiscoveredDevice(device); _discoveredServices.Add(newDevice); ServiceDiscovered?.Invoke(this, new ResonanceDiscoveredServiceEventArgs <ResonanceBluetoothDiscoveredDevice, BluetoothDevice>(newDevice)); } } } }
/// <summary> /// Called when a service has been lost. /// </summary> /// <param name="discoveryInfo">The discovery information.</param> protected virtual void OnServiceUnregistered(TReportedServiceInformation discoveryInfo) { var existingService = _discoveredServices.FirstOrDefault(x => x.DiscoveryInfo.ServiceId == discoveryInfo.ServiceId); if (existingService != null) { _discoveredServices.Remove(existingService); ServiceLost?.Invoke(this, new ResonanceDiscoveredServiceEventArgs <ResonanceSignalRDiscoveredService <TReportedServiceInformation>, TReportedServiceInformation>(existingService)); } }
#pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void void OnResolved(IReadOnlyList <IZeroconfHost> hosts) { lock (discoveredHosts) { var newHosts = new HashSet <Tuple <string, string> >(discoveredHosts); var remainingHosts = new HashSet <Tuple <string, string> >(discoveredHosts); foreach (var host in hosts) { foreach (var service in host.Services) { var keyValue = new Tuple <string, string>(host.DisplayName, service.Value.Name); if (discoveredHosts.Contains(keyValue)) { remainingHosts.Remove(keyValue); } else { ServiceFound?.Invoke(this, host); newHosts.Add(keyValue); } if (toRemove.ContainsKey(keyValue)) { toRemove.Remove(keyValue); } } } foreach (var service in remainingHosts) { if (toRemove.ContainsKey(service)) { //zeroconf sometimes reports missing hosts incorrectly. //after pingsUntilRemove missing hosts reports, we'll remove the service from the list. if (++toRemove[service] > pingsUntilRemove) { toRemove.Remove(service); newHosts.Remove(service); ServiceLost?.Invoke(this, new ZeroconfHost { DisplayName = service.Item1, Id = service.Item2 }); } } else { toRemove.Add(service, 0); } } discoveredHosts = newHosts; } }
private void ReceiveThreadMethod() { while (IsStarted) { try { var clientEndPoint = new IPEndPoint(IPAddress.Any, Port); var data = _udpClient.Receive(ref clientEndPoint); Logger.LogDebug($"Data received ({data.ToFriendlyByteSize()}), decoding discovery information..."); TDiscoveryInfo discoveryInfo = Decoder.Decode <TDiscoveryInfo>(data); Logger.LogDebug($"Discovery information decoded:\n{discoveryInfo.ToJsonString()}"); string address = clientEndPoint.Address.ToString(); Logger.LogDebug($"Service host address: {address}."); ResonanceUdpDiscoveredService <TDiscoveryInfo> discoveredService = new ResonanceUdpDiscoveredService <TDiscoveryInfo>(discoveryInfo, address); //validate service existence using TCP connection. if (EnableTcpValidation) { Logger.LogDebug($"Validating service existence using TCP..."); try { TcpClient client = new TcpClient(); client.Connect(address, Port); client.Dispose(); Logger.LogDebug("Service validated."); } catch { var missingService = _discoveredServices.ToList().FirstOrDefault(existingService => _discoveredServiceCompareFunc(existingService, discoveredService)); if (missingService != null) { Logger.LogDebug("Service TCP validation failed. Reporting service lost..."); _discoveredServices.Remove(missingService); Logger.LogDebug($"Total discovered services: {_discoveredServices.Count}."); ServiceLost?.Invoke(this, new ResonanceDiscoveredServiceEventArgs <ResonanceUdpDiscoveredService <TDiscoveryInfo>, TDiscoveryInfo>(missingService)); } else { Logger.LogDebug("Service TCP validation failed."); } continue; } } if (!_discoveredServices.ToList().Exists(existingService => _discoveredServiceCompareFunc(existingService, discoveredService))) { Logger.LogInformation("New service discovered on address {Address}. Reporting service discovered...", discoveredService.Address); _discoveredServices.Add(discoveredService); Logger.LogDebug($"Total discovered services: {_discoveredServices.Count}."); ServiceDiscovered?.Invoke(this, new ResonanceDiscoveredServiceEventArgs <ResonanceUdpDiscoveredService <TDiscoveryInfo>, TDiscoveryInfo>(discoveredService)); } else { Logger.LogDebug("Service was already discovered."); } } catch (Exception ex) { if (ex.Message != "A blocking operation was interrupted by a call to WSACancelBlockingCall") { Logger.LogError(ex, "Error occurred on discovery method."); } } } }