void OnUPnPDeviceDisconnected(DeviceConnection connection) { IEnumerable <UPnPServiceProxyBase> servicesToDispose; lock (_networkTracker.SharedControlPointData.SyncObj) { _connection = null; _contentDirectoryService = null; _resourceInformationService = null; _serverControllerService = null; servicesToDispose = _additionalServices; _additionalServices.Clear(); } // Dispose all additional services if possible, to allow proper shutdown and cleanup foreach (UPnPServiceProxyBase service in servicesToDispose) { IDisposable disposable = service as IDisposable; if (disposable == null) { continue; } try { disposable.Dispose(); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("UPnPClientControlPoint: Error disposing additional service '{0}'", service, e); } } InvokeBackendServerDeviceDisconnected(connection); }
public void Stop() { _contentDirectoryService = null; _resourceInformationService = null; _serverControllerService = null; _networkTracker.Close(); _controlPoint.Close(); // Close the control point after the network tracker was closed. See docs of Close() method. }
public void DetachFromHomeServer() { ISettingsManager settingsManager = ServiceRegistration.Get<ISettingsManager>(); ServerConnectionSettings settings = settingsManager.Load<ServerConnectionSettings>(); ServiceRegistration.Get<ILogger>().Info("ServerConnectionManager: Detaching from home server '{0}'", settings.HomeServerSystemId); ServiceRegistration.Get<ILogger>().Debug("ServerConnectionManager: Clearing pending import jobs and suspending importer worker"); IImporterWorker importerWorker = ServiceRegistration.Get<IImporterWorker>(); importerWorker.Suspend(); importerWorker.CancelPendingJobs(); ServiceRegistration.Get<ILogger>().Debug("ServerConnectionManager: Notifying the MediaPortal server about the detachment"); UPnPServerControllerServiceProxy sc = ServerControllerServiceProxy; ISystemResolver systemResolver = ServiceRegistration.Get<ISystemResolver>(); if (sc != null) try { sc.DetachClient(systemResolver.LocalSystemId); sc.AttachedClientsChanged -= OnAttachedClientsChanged; sc.ConnectedClientsChanged -= OnConnectedClientsChanged; } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("ServerConnectionManager: Error detaching from home server '{0}'", e, HomeServerSystemId); } UPnPContentDirectoryServiceProxy cd = ContentDirectoryServiceProxy; if (cd != null) try { cd.PlaylistsChanged -= OnContentDirectoryPlaylistsChanged; cd.MIATypeRegistrationsChanged -= OnContentDirectoryMIATypeRegistrationsChanged; cd.RegisteredSharesChangeCounterChanged -= OnRegisteredSharesChangeCounterChanged; } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("ServerConnectionManager: Error unregistering from state variable change events", e); } ServiceRegistration.Get<ILogger>().Debug("ServerConnectionManager: Closing server connection"); UPnPClientControlPoint cp; lock (_syncObj) cp = _controlPoint; if (cp != null) cp.Stop(); // Must be outside the lock - sends messages lock (_syncObj) { settings.HomeServerSystemId = null; settings.LastHomeServerName = null; settings.LastHomeServerSystem = null; settingsManager.Save(settings); _controlPoint = null; } UpdateCurrentlyImportingShares(null); // Mark all shares as not being imported ServerConnectionMessaging.SendServerConnectionStateChangedMessage(ServerConnectionMessaging.MessageType.HomeServerDetached); ServiceRegistration.Get<ILogger>().Debug("ServerConnectionManager: Starting to watch for MediaPortal servers"); if (_serverWatcher == null) { lock (_syncObj) _serverWatcher = BuildServerWatcher(); _serverWatcher.Start(); // Outside the lock } }
/// <summary> /// Synchronously synchronizes all local shares and media item aspect types with the MediaPortal server. /// </summary> protected async Task CompleteServerConnectionAsync() { UPnPServerControllerServiceProxy sc = ServerControllerServiceProxy; ISystemResolver systemResolver = ServiceRegistration.Get<ISystemResolver>(); if (sc != null) { try { // Check if we're attached to the server. If the server lost its state, it might have forgotten us. if (!sc.GetAttachedClients().Select(clientMetadata => clientMetadata.SystemId).Contains(systemResolver.LocalSystemId)) sc.AttachClient(systemResolver.LocalSystemId); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("ServerConnectionManager: Error checking attachment state at home server '{0}'", e, HomeServerSystemId); return; // This is a real error case, we don't need to try any other service calls } // Register state variables change events sc.AttachedClientsChanged += OnAttachedClientsChanged; sc.ConnectedClientsChanged += OnConnectedClientsChanged; } IImporterWorker importerWorker = ServiceRegistration.Get<IImporterWorker>(); ICollection<Share> newShares = new List<Share>(); UPnPContentDirectoryServiceProxy cd = ContentDirectoryServiceProxy; if (cd != null) { // Update shares registration try { ISettingsManager settingsManager = ServiceRegistration.Get<ISettingsManager>(); ServerConnectionSettings settings = settingsManager.Load<ServerConnectionSettings>(); ServiceRegistration.Get<ILogger>().Info("ServerConnectionManager: Synchronizing shares with home server"); IDictionary<Guid, Share> serverShares = new Dictionary<Guid, Share>(); foreach (Share share in await cd.GetSharesAsync(systemResolver.LocalSystemId, SharesFilter.All)) serverShares.Add(share.ShareId, share); IDictionary<Guid, Share> localShares = ServiceRegistration.Get<ILocalSharesManagement>().Shares; // First remove shares - if the client lost its configuration and re-registers an already present share, the server's method will throw an exception foreach (Guid serverShareId in serverShares.Keys) if (!localShares.ContainsKey(serverShareId)) await cd.RemoveShareAsync(serverShareId); foreach (Share localShare in localShares.Values) { RelocationMode relocationMode; if (!serverShares.ContainsKey(localShare.ShareId)) { await cd.RegisterShareAsync(localShare); newShares.Add(localShare); } else if (settings.CachedSharesUpdates.TryGetValue(localShare.ShareId, out relocationMode)) { await cd.UpdateShareAsync(localShare.ShareId, localShare.BaseResourcePath, localShare.Name, localShare.UseShareWatcher, localShare.MediaCategories, relocationMode); switch (relocationMode) { case RelocationMode.ClearAndReImport: importerWorker.ScheduleImport(localShare.BaseResourcePath, localShare.MediaCategories, true); break; case RelocationMode.Relocate: importerWorker.ScheduleRefresh(localShare.BaseResourcePath, localShare.MediaCategories, true); break; } } } settings.CachedSharesUpdates.Clear(); settingsManager.Save(settings); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("ServerConnectionManager: Could not synchronize local shares with server", e); } // Update media item aspect type registration try { IMediaItemAspectTypeRegistration miatr = ServiceRegistration.Get<IMediaItemAspectTypeRegistration>(); ServiceRegistration.Get<ILogger>().Info("ServerConnectionManager: Checking for unregistered media item aspect types at home server"); ICollection<Guid> serverMIATypes = await cd.GetAllManagedMediaItemAspectTypesAsync(); foreach (KeyValuePair<Guid, MediaItemAspectMetadata> localMiaType in miatr.LocallyKnownMediaItemAspectTypes) if (!serverMIATypes.Contains(localMiaType.Key)) { ServiceRegistration.Get<ILogger>().Info("ServerConnectionManager: Adding unregistered media item aspect type '{0}' (ID '{1}') at home server", localMiaType.Value.Name, localMiaType.Key); await cd.AddMediaItemAspectStorageAsync(localMiaType.Value); } } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("ServerConnectionManager: Could not synchronize local media item aspect types with server", e); } // Register state variables change events cd.PlaylistsChanged += OnContentDirectoryPlaylistsChanged; cd.MIATypeRegistrationsChanged += OnContentDirectoryMIATypeRegistrationsChanged; cd.RegisteredSharesChangeCounterChanged += OnRegisteredSharesChangeCounterChanged; // Activate importer worker ServiceRegistration.Get<ILogger>().Debug("ServerConnectionManager: Activating importer worker"); ImporterCallback ic = new ImporterCallback(cd); importerWorker.Activate(ic, ic); foreach (Share share in newShares) importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true); } }
protected void TryConnect(RootDescriptor rootDescriptor) { DeviceConnection connection; string deviceUuid; lock (_networkTracker.SharedControlPointData.SyncObj) { if (_connection != null) { return; } DeviceDescriptor rootDeviceDescriptor = DeviceDescriptor.CreateRootDeviceDescriptor(rootDescriptor); DeviceDescriptor backendServerDescriptor = rootDeviceDescriptor.FindFirstDevice( UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); if (backendServerDescriptor == null) { return; } deviceUuid = backendServerDescriptor.DeviceUUID; string friendlyName = backendServerDescriptor.FriendlyName; SystemName system = new SystemName(new Uri(rootDescriptor.SSDPRootEntry.PreferredLink.DescriptionLocation).Host); if (deviceUuid == _homeServerSystemId) { ServiceRegistration.Get <ILogger>().Debug("UPnPClientControlPoint: Found MP 2 home server '{0}' (system ID '{1}') at host '{2}' (IP address: '{3}')", friendlyName, deviceUuid, system.HostName, system.Address); } else { ServiceRegistration.Get <ILogger>().Debug("UPnPClientControlPoint: Found foreign MP 2 server '{0}' (system ID '{1}') at host '{2}' (IP address: '{3}')", friendlyName, deviceUuid, system.HostName, system.Address); return; } try { connection = _connection = _controlPoint.Connect(rootDescriptor, deviceUuid, UPnPExtendedDataTypes.ResolveDataType); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("UPnPClientControlPoint: Error connecting to UPnP MP 2 backend server '{0}'", e, deviceUuid); return; } } connection.DeviceDisconnected += OnUPnPDeviceDisconnected; try { CpService cdsStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.CONTENT_DIRECTORY_SERVICE_ID); if (cdsStub == null) { throw new InvalidDataException("ContentDirectory service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); } CpService risStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.RESOURCE_INFORMATION_SERVICE_ID); if (risStub == null) { throw new InvalidDataException("ResourceAccess service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); } CpService scsStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.SERVER_CONTROLLER_SERVICE_ID); if (scsStub == null) { throw new InvalidDataException("ServerController service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); } CpService updmStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.USER_PROFILE_DATA_MANAGEMENT_SERVICE_ID); if (updmStub == null) { throw new InvalidDataException("UserProfileDataManagement service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); } lock (_networkTracker.SharedControlPointData.SyncObj) { _contentDirectoryService = new UPnPContentDirectoryServiceProxy(cdsStub); _resourceInformationService = new UPnPResourceInformationServiceProxy(risStub); _serverControllerService = new UPnPServerControllerServiceProxy(scsStub); _userProfileDataManagementService = new UPnPUserProfileDataManagementServiceProxy(updmStub); } ICollection <UPnPServiceProxyBase> additionalServices = new List <UPnPServiceProxyBase>(); foreach (AdditionalServiceRegisterDlgt additionalServiceRegistration in _additionalServiceRegistrations) { try { additionalServices.Add(additionalServiceRegistration(connection)); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("UPnPClientControlPoint: Error registering user service for UPnP MP 2 backend server '{0}'", e, deviceUuid); } } lock (_networkTracker.SharedControlPointData.SyncObj) _additionalServices = additionalServices; } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("UPnPClientControlPoint: Error connecting to services of UPnP MP 2 backend server '{0}'", e, deviceUuid); connection.DeviceDisconnected -= OnUPnPDeviceDisconnected; _controlPoint.Disconnect(deviceUuid); return; } InvokeBackendServerDeviceConnected(connection); }
void OnUPnPDeviceDisconnected(DeviceConnection connection) { IEnumerable<UPnPServiceProxyBase> servicesToDispose; lock (_networkTracker.SharedControlPointData.SyncObj) { _connection = null; _contentDirectoryService = null; _resourceInformationService = null; _serverControllerService = null; servicesToDispose = _additionalServices; _additionalServices.Clear(); } // Dispose all additional services if possible, to allow proper shutdown and cleanup foreach (UPnPServiceProxyBase service in servicesToDispose) { IDisposable disposable = service as IDisposable; if (disposable == null) continue; try { disposable.Dispose(); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("UPnPClientControlPoint: Error disposing additional service '{0}'", service, e); } } InvokeBackendServerDeviceDisconnected(connection); }
protected void TryConnect(RootDescriptor rootDescriptor) { DeviceConnection connection; string deviceUuid; lock (_networkTracker.SharedControlPointData.SyncObj) { if (_connection != null) return; DeviceDescriptor rootDeviceDescriptor = DeviceDescriptor.CreateRootDeviceDescriptor(rootDescriptor); DeviceDescriptor backendServerDescriptor = rootDeviceDescriptor.FindFirstDevice( UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); if (backendServerDescriptor == null) return; deviceUuid = backendServerDescriptor.DeviceUUID; string friendlyName = backendServerDescriptor.FriendlyName; SystemName system = new SystemName(new Uri(rootDescriptor.SSDPRootEntry.PreferredLink.DescriptionLocation).Host); if (deviceUuid == _homeServerSystemId) ServiceRegistration.Get<ILogger>().Debug("UPnPClientControlPoint: Found MP 2 home server '{0}' (system ID '{1}') at host '{2}' (IP address: '{3}')", friendlyName, deviceUuid, system.HostName, system.Address); else { ServiceRegistration.Get<ILogger>().Debug("UPnPClientControlPoint: Found foreign MP 2 server '{0}' (system ID '{1}') at host '{2}' (IP address: '{3}')", friendlyName, deviceUuid, system.HostName, system.Address); return; } try { connection = _connection = _controlPoint.Connect(rootDescriptor, deviceUuid, UPnPExtendedDataTypes.ResolveDataType); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("UPnPClientControlPoint: Error connecting to UPnP MP 2 backend server '{0}'", e, deviceUuid); return; } } connection.DeviceDisconnected += OnUPnPDeviceDisconnected; try { CpService cdsStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.CONTENT_DIRECTORY_SERVICE_ID); if (cdsStub == null) throw new InvalidDataException("ContentDirectory service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); CpService risStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.RESOURCE_INFORMATION_SERVICE_ID); if (risStub == null) throw new InvalidDataException("ResourceAccess service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); CpService scsStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.SERVER_CONTROLLER_SERVICE_ID); if (scsStub == null) throw new InvalidDataException("ServerController service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); CpService updmStub = connection.Device.FindServiceByServiceId(UPnPTypesAndIds.USER_PROFILE_DATA_MANAGEMENT_SERVICE_ID); if (updmStub == null) throw new InvalidDataException("UserProfileDataManagement service not found in device '{0}' of type '{1}:{2}'", deviceUuid, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE, UPnPTypesAndIds.BACKEND_SERVER_DEVICE_TYPE_VERSION); lock (_networkTracker.SharedControlPointData.SyncObj) { _contentDirectoryService = new UPnPContentDirectoryServiceProxy(cdsStub); _resourceInformationService = new UPnPResourceInformationServiceProxy(risStub); _serverControllerService = new UPnPServerControllerServiceProxy(scsStub); _userProfileDataManagementService = new UPnPUserProfileDataManagementServiceProxy(updmStub); } ICollection<UPnPServiceProxyBase> additionalServices = new List<UPnPServiceProxyBase>(); foreach (AdditionalServiceRegisterDlgt additionalServiceRegistration in _additionalServiceRegistrations) { try { additionalServices.Add(additionalServiceRegistration(connection)); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("UPnPClientControlPoint: Error registering user service for UPnP MP 2 backend server '{0}'", e, deviceUuid); } } lock (_networkTracker.SharedControlPointData.SyncObj) _additionalServices = additionalServices; } catch (Exception e) { ServiceRegistration.Get<ILogger>().Warn("UPnPClientControlPoint: Error connecting to services of UPnP MP 2 backend server '{0}'", e, deviceUuid); connection.DeviceDisconnected -= OnUPnPDeviceDisconnected; _controlPoint.Disconnect(deviceUuid); return; } InvokeBackendServerDeviceConnected(connection); }