예제 #1
0
        /// <summary>
        /// Opens the dashboard page.
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="appHost">The app host.</param>
        /// <param name="logger">The logger.</param>
        public static void OpenDashboardPage(string page, IServerApplicationHost appHost, ILogger logger)
        {
            var url = appHost.GetLocalApiUrl("localhost") + "/web/" + page;

            OpenUrl(url, logger);
        }
예제 #2
0
        public override async Task Open(CancellationToken openCancellationToken)
        {
            LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();

            var mediaSource = OriginalMediaSource;

            var url = mediaSource.Path;

            Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath));

            var typeName = GetType().Name;

            Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url);

            var httpRequestOptions = new HttpRequestOptions
            {
                Url = url,
                CancellationToken = CancellationToken.None,
                BufferContent     = false,

                // Increase a little bit
                TimeoutMs = 30000,

                EnableHttpCompression = false,

                LogResponse        = true,
                LogResponseHeaders = true
            };

            foreach (var header in mediaSource.RequiredHttpHeaders)
            {
                httpRequestOptions.RequestHeaders[header.Key] = header.Value;
            }

            var response = await _httpClient.SendAsync(httpRequestOptions, "GET").ConfigureAwait(false);

            var extension     = "ts";
            var requiresRemux = false;

            var contentType = response.ContentType ?? string.Empty;

            if (contentType.IndexOf("matroska", StringComparison.OrdinalIgnoreCase) != -1)
            {
                requiresRemux = true;
            }
            else if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 ||
                     contentType.IndexOf("dash", StringComparison.OrdinalIgnoreCase) != -1 ||
                     contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1 ||
                     contentType.IndexOf("text/", StringComparison.OrdinalIgnoreCase) != -1)
            {
                requiresRemux = true;
            }

            // Close the stream without any sharing features
            if (requiresRemux)
            {
                using (response)
                {
                    return;
                }
            }

            SetTempFilePath(extension);

            var taskCompletionSource = new TaskCompletionSource <bool>();

            var now = DateTime.UtcNow;

            var _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);

            //OpenedMediaSource.Protocol = MediaProtocol.File;
            //OpenedMediaSource.Path = tempFile;
            //OpenedMediaSource.ReadAtNativeFramerate = true;

            MediaSource.Path     = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
            MediaSource.Protocol = MediaProtocol.Http;

            //OpenedMediaSource.Path = TempFilePath;
            //OpenedMediaSource.Protocol = MediaProtocol.File;

            //OpenedMediaSource.Path = _tempFilePath;
            //OpenedMediaSource.Protocol = MediaProtocol.File;
            //OpenedMediaSource.SupportsDirectPlay = false;
            //OpenedMediaSource.SupportsDirectStream = true;
            //OpenedMediaSource.SupportsTranscoding = true;
            await taskCompletionSource.Task.ConfigureAwait(false);
        }
예제 #3
0
        private async Task AddDevice(UpnpDeviceInfo info, string location, CancellationToken cancellationToken)
        {
            var uri = info.Location;

            _logger.Debug("Attempting to create PlayToController from location {0}", location);
            var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory, cancellationToken).ConfigureAwait(false);

            _logger.Debug("Logging session activity from location {0}", location);
            var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null).ConfigureAwait(false);

            var controller = sessionInfo.SessionController as PlayToController;

            if (controller == null)
            {
                string serverAddress;
                if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Any))
                {
                    serverAddress = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    serverAddress = _appHost.GetLocalApiUrl(info.LocalIpAddress);
                }

                string accessToken = null;

                sessionInfo.SessionController = controller = new PlayToController(sessionInfo,
                                                                                  _sessionManager,
                                                                                  _libraryManager,
                                                                                  _logger,
                                                                                  _dlnaManager,
                                                                                  _userManager,
                                                                                  _imageProcessor,
                                                                                  serverAddress,
                                                                                  accessToken,
                                                                                  _deviceDiscovery,
                                                                                  _userDataManager,
                                                                                  _localization,
                                                                                  _mediaSourceManager,
                                                                                  _config,
                                                                                  _mediaEncoder);

                controller.Init(device);

                var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
                              _dlnaManager.GetDefaultProfile();

                _sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities
                {
                    PlayableMediaTypes = profile.GetSupportedMediaTypes(),

                    SupportedCommands = new string[]
                    {
                        GeneralCommandType.VolumeDown.ToString(),
                        GeneralCommandType.VolumeUp.ToString(),
                        GeneralCommandType.Mute.ToString(),
                        GeneralCommandType.Unmute.ToString(),
                        GeneralCommandType.ToggleMute.ToString(),
                        GeneralCommandType.SetVolume.ToString(),
                        GeneralCommandType.SetAudioStreamIndex.ToString(),
                        GeneralCommandType.SetSubtitleStreamIndex.ToString()
                    },

                    SupportsMediaControl = true,

                    // xbox one creates a new uuid everytime it restarts
                    SupportsPersistentIdentifier = (device.Properties.ModelName ?? string.Empty).IndexOf("xbox", StringComparison.OrdinalIgnoreCase) == -1
                });

                _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
            }
        }
예제 #4
0
        private async Task RegisterServerEndpoints()
        {
            if (!_config.GetDlnaConfiguration().BlastAliveMessages)
            {
                return;
            }

            var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds;

            _Publisher.SupportPnpRootDevice = false;

            var addresses = (await _appHost.GetLocalIpAddresses().ConfigureAwait(false)).ToList();

            var udn = CreateUuid(_appHost.SystemId);

            foreach (var address in addresses)
            {
                //if (IPAddress.IsLoopback(address))
                //{
                //    // Should we allow this?
                //    continue;
                //}

                var fullService = "urn:schemas-upnp-org:device:MediaServer:1";

                _logger.Info("Registering publisher for {0} on {1}", fullService, address.ToString());

                var descriptorUri = "/dlna/" + udn + "/description.xml";
                var uri           = new Uri(_appHost.GetLocalApiUrl(address) + descriptorUri);

                var device = new SsdpRootDevice
                {
                    CacheLifetime = TimeSpan.FromSeconds(cacheLength), //How long SSDP clients can cache this info.
                    Location      = uri,                               // Must point to the URL that serves your devices UPnP description document.
                    FriendlyName  = "Emby Server",
                    Manufacturer  = "Emby",
                    ModelName     = "Emby Server",
                    Uuid          = udn
                                    // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
                };

                SetProperies(device, fullService);
                _Publisher.AddDevice(device);

                var embeddedDevices = new List <string>
                {
                    "urn:schemas-upnp-org:service:ContentDirectory:1",
                    "urn:schemas-upnp-org:service:ConnectionManager:1",
                    //"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"
                };

                foreach (var subDevice in embeddedDevices)
                {
                    var embeddedDevice = new SsdpEmbeddedDevice
                    {
                        FriendlyName = device.FriendlyName,
                        Manufacturer = device.Manufacturer,
                        ModelName    = device.ModelName,
                        Uuid         = udn
                                       // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
                    };

                    SetProperies(embeddedDevice, subDevice);
                    device.AddDevice(embeddedDevice);
                }
            }
        }
예제 #5
0
        public override async Task Open(CancellationToken openCancellationToken)
        {
            LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();

            var mediaSource = OriginalMediaSource;

            var uri       = new Uri(mediaSource.Path);
            var localPort = _networkManager.GetRandomUnusedUdpPort();

            Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath));

            Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host);

            var       remoteAddress     = IPAddress.Parse(uri.Host);
            var       embyRemoteAddress = _networkManager.ParseIpAddress(uri.Host);
            IPAddress localAddress      = null;

            using (var tcpSocket = CreateSocket(remoteAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
            {
                try
                {
                    tcpSocket.Connect(new IPEndPoint(remoteAddress, HdHomerunManager.HdHomeRunPort));
                    localAddress = ((IPEndPoint)tcpSocket.LocalEndPoint).Address;
                    tcpSocket.Close();
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, "Unable to determine local ip address for Legacy HDHomerun stream.");
                    return;
                }
            }

            var udpClient        = _socketFactory.CreateUdpSocket(localPort);
            var hdHomerunManager = new HdHomerunManager(_socketFactory, Logger);

            try
            {
                // send url to start streaming
                await hdHomerunManager.StartStreaming(embyRemoteAddress, localAddress, localPort, _channelCommands, _numTuners, openCancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                using (udpClient)
                    using (hdHomerunManager)
                    {
                        if (!(ex is OperationCanceledException))
                        {
                            Logger.LogError(ex, "Error opening live stream:");
                        }
                        throw;
                    }
            }

            var taskCompletionSource = new TaskCompletionSource <bool>();

            await StartStreaming(udpClient, hdHomerunManager, remoteAddress, taskCompletionSource, LiveStreamCancellationTokenSource.Token);

            //OpenedMediaSource.Protocol = MediaProtocol.File;
            //OpenedMediaSource.Path = tempFile;
            //OpenedMediaSource.ReadAtNativeFramerate = true;

            MediaSource.Path     = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
            MediaSource.Protocol = MediaProtocol.Http;
            //OpenedMediaSource.SupportsDirectPlay = false;
            //OpenedMediaSource.SupportsDirectStream = true;
            //OpenedMediaSource.SupportsTranscoding = true;

            //await Task.Delay(5000).ConfigureAwait(false);
            await taskCompletionSource.Task.ConfigureAwait(false);
        }
예제 #6
0
        public override async Task Open(CancellationToken openCancellationToken)
        {
            LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();

            var mediaSource = OriginalMediaSource;

            var url = mediaSource.Path;

            FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath));

            var typeName = GetType().Name;

            Logger.Info("Opening " + typeName + " Live stream from {0}", url);

            var response = await _httpClient.SendAsync(new HttpRequestOptions
            {
                Url = url,
                CancellationToken = CancellationToken.None,
                BufferContent     = false,

                // Increase a little bit
                TimeoutMs = 30000,

                EnableHttpCompression = false,

                LogResponse        = true,
                LogResponseHeaders = true
            }, "GET").ConfigureAwait(false);

            var extension     = "ts";
            var requiresRemux = false;

            var contentType = response.ContentType ?? string.Empty;

            if (contentType.IndexOf("matroska", StringComparison.OrdinalIgnoreCase) != -1)
            {
                requiresRemux = true;
            }
            else if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 ||
                     contentType.IndexOf("dash", StringComparison.OrdinalIgnoreCase) != -1 ||
                     contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1 ||
                     contentType.IndexOf("text/", StringComparison.OrdinalIgnoreCase) != -1)
            {
                requiresRemux = true;
            }

            // Close the stream without any sharing features
            if (requiresRemux)
            {
                using (response)
                {
                    return;
                }
            }

            SetTempFilePath(extension);

            var taskCompletionSource = new TaskCompletionSource <bool>();

            var now = DateTime.UtcNow;

            StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);

            //OpenedMediaSource.Protocol = MediaProtocol.File;
            //OpenedMediaSource.Path = tempFile;
            //OpenedMediaSource.ReadAtNativeFramerate = true;

            OpenedMediaSource.Path     = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
            OpenedMediaSource.Protocol = MediaProtocol.Http;

            //OpenedMediaSource.Path = TempFilePath;
            //OpenedMediaSource.Protocol = MediaProtocol.File;

            //OpenedMediaSource.Path = _tempFilePath;
            //OpenedMediaSource.Protocol = MediaProtocol.File;
            //OpenedMediaSource.SupportsDirectPlay = false;
            //OpenedMediaSource.SupportsDirectStream = true;
            //OpenedMediaSource.SupportsTranscoding = true;
            await taskCompletionSource.Task.ConfigureAwait(false);

            if (OpenedMediaSource.SupportsProbing)
            {
                var elapsed = (DateTime.UtcNow - now).TotalMilliseconds;

                var delay = Convert.ToInt32(3000 - elapsed);

                if (delay > 0)
                {
                    Logger.Info("Delaying shared stream by {0}ms to allow the buffer to build.", delay);

                    await Task.Delay(delay).ConfigureAwait(false);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Opens the dashboard page.
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="appHost">The app host.</param>
        public static void OpenDashboardPage(string page, IServerApplicationHost appHost)
        {
            var url = appHost.GetLocalApiUrl("localhost") + "/web/" + page;

            OpenUrl(appHost, url);
        }
예제 #8
0
        private async Task AddDevice(UpnpDeviceInfo info, string location, CancellationToken cancellationToken)
        {
            var uri = info.Location;

            _logger.LogDebug("Attempting to create PlayToController from location {0}", location);

            _logger.LogDebug("Logging session activity from location {0}", location);
            if (info.Headers.TryGetValue("USN", out string uuid))
            {
                uuid = GetUuid(uuid);
            }
            else
            {
                uuid = location.GetMD5().ToString("N");
            }

            var sessionInfo = _sessionManager.LogSessionActivity("DLNA", _appHost.ApplicationVersion, uuid, null, uri.OriginalString, null);

            var controller = sessionInfo.SessionControllers.OfType <PlayToController>().FirstOrDefault();

            if (controller == null)
            {
                var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory, cancellationToken).ConfigureAwait(false);

                string deviceName = device.Properties.Name;

                _sessionManager.UpdateDeviceName(sessionInfo.Id, deviceName);

                string serverAddress;
                if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Any))
                {
                    serverAddress = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    serverAddress = _appHost.GetLocalApiUrl(info.LocalIpAddress);
                }

                controller = new PlayToController(sessionInfo,
                                                  _sessionManager,
                                                  _libraryManager,
                                                  _logger,
                                                  _dlnaManager,
                                                  _userManager,
                                                  _imageProcessor,
                                                  serverAddress,
                                                  null,
                                                  _deviceDiscovery,
                                                  _userDataManager,
                                                  _localization,
                                                  _mediaSourceManager,
                                                  _config,
                                                  _mediaEncoder);

                sessionInfo.AddController(controller);

                controller.Init(device);

                var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
                              _dlnaManager.GetDefaultProfile();

                _sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities
                {
                    PlayableMediaTypes = profile.GetSupportedMediaTypes(),

                    SupportedCommands = new string[]
                    {
                        GeneralCommandType.VolumeDown.ToString(),
                        GeneralCommandType.VolumeUp.ToString(),
                        GeneralCommandType.Mute.ToString(),
                        GeneralCommandType.Unmute.ToString(),
                        GeneralCommandType.ToggleMute.ToString(),
                        GeneralCommandType.SetVolume.ToString(),
                        GeneralCommandType.SetAudioStreamIndex.ToString(),
                        GeneralCommandType.SetSubtitleStreamIndex.ToString(),
                        GeneralCommandType.PlayMediaSource.ToString()
                    },

                    SupportsMediaControl = true
                });

                _logger.LogInformation("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
            }
        }
        private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs <UpnpDeviceInfo> e)
        {
            if (_disposed)
            {
                return;
            }

            var info = e.Argument;

            string usn;

            if (!info.Headers.TryGetValue("USN", out usn))
            {
                usn = string.Empty;
            }

            string nt;

            if (!info.Headers.TryGetValue("NT", out nt))
            {
                nt = string.Empty;
            }

            // Filter device type
            if (usn.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 &&
                nt.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 &&
                usn.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1 &&
                nt.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1)
            {
                return;
            }

            var identifier = string.IsNullOrWhiteSpace(usn) ? nt : usn;

            if (info.Location == null)
            {
                return;
            }

            lock (_usnsHandled)
            {
                if (_usnsHandled.Contains(identifier))
                {
                    return;
                }
                _usnsHandled.Add(identifier);
            }

            _logger.Debug("Found NAT device: " + identifier);

            IPAddress address;

            if (IPAddress.TryParse(info.Location.Host, out address))
            {
                // The Handle method doesn't need the port
                var endpoint = new IPEndPoint(address, info.Location.Port);

                IPAddress localAddress = null;

                try
                {
                    var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false);

                    Uri uri;
                    if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri))
                    {
                        localAddressString = uri.Host;

                        if (!IPAddress.TryParse(localAddressString, out localAddress))
                        {
                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    return;
                }

                if (_disposed)
                {
                    return;
                }

                _logger.Debug("Calling Nat.Handle on " + identifier);
                NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp);
            }
        }
예제 #10
0
 private string GetServerAddress(IPAddress localIp)
 {
     return(_appHost.GetLocalApiUrl(localIp.ToString()));
 }
예제 #11
0
        private async Task <IEnumerable <MediaSourceInfo> > GetMediaSourcesInternal(IHasMediaSources item, CancellationToken cancellationToken)
        {
            IEnumerable <MediaSourceInfo> sources;

            var forceRequireOpening = false;

            try
            {
                if (item is ILiveTvRecording)
                {
                    sources = await _liveTvManager.GetRecordingMediaSources(item.Id.ToString("N"), cancellationToken)
                              .ConfigureAwait(false);
                }
                else
                {
                    sources = await _liveTvManager.GetChannelMediaSources(item.Id.ToString("N"), cancellationToken)
                              .ConfigureAwait(false);
                }
            }
            catch (NotImplementedException)
            {
                var hasMediaSources = (IHasMediaSources)item;

                sources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false)
                          .ToList();

                forceRequireOpening = true;
            }

            var list      = sources.ToList();
            var serverUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false);

            foreach (var source in list)
            {
                source.Type     = MediaSourceType.Default;
                source.BufferMs = source.BufferMs ?? 1500;

                if (source.RequiresOpening || forceRequireOpening)
                {
                    source.RequiresOpening = true;
                }

                if (source.RequiresOpening)
                {
                    var openKeys = new List <string>();
                    openKeys.Add(item.GetType().Name);
                    openKeys.Add(item.Id.ToString("N"));
                    openKeys.Add(source.Id ?? string.Empty);
                    source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray());
                }

                // Dummy this up so that direct play checks can still run
                if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http)
                {
                    source.Path = serverUrl;
                }
            }

            _logger.Debug("MediaSources: {0}", _jsonSerializer.SerializeToString(list));

            return(list);
        }
예제 #12
0
        private async Task <IEnumerable <MediaSourceInfo> > GetMediaSourcesInternal(BaseItem item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
        {
            IEnumerable <MediaSourceInfo> sources;

            var forceRequireOpening = false;

            try
            {
                if (activeRecordingInfo != null)
                {
                    sources = await EmbyTV.EmbyTV.Current.GetRecordingStreamMediaSources(activeRecordingInfo, cancellationToken)
                              .ConfigureAwait(false);
                }
                else
                {
                    sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
                              .ConfigureAwait(false);
                }
            }
            catch (NotImplementedException)
            {
                sources = _mediaSourceManager.GetStaticMediaSources(item, false);

                forceRequireOpening = true;
            }

            var list      = sources.ToList();
            var serverUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);

            foreach (var source in list)
            {
                source.Type = MediaSourceType.Default;
                source.BufferMs ??= 1500;

                if (source.RequiresOpening || forceRequireOpening)
                {
                    source.RequiresOpening = true;
                }

                if (source.RequiresOpening)
                {
                    var openKeys = new List <string>
                    {
                        item.GetType().Name,
                        item.Id.ToString("N", CultureInfo.InvariantCulture),
                        source.Id ?? string.Empty
                    };

                    source.OpenToken = string.Join(StreamIdDelimiter, openKeys);
                }

                // Dummy this up so that direct play checks can still run
                if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http)
                {
                    source.Path = serverUrl;
                }
            }

            _logger.LogDebug("MediaSources: {@MediaSources}", list);

            return(list);
        }
예제 #13
0
        /// <summary>
        /// Opens the swagger.
        /// </summary>
        /// <param name="appHost">The app host.</param>
        /// <param name="logger">The logger.</param>
        public static void OpenSwagger(IServerApplicationHost appHost, ILogger logger)
        {
            var url = appHost.GetLocalApiUrl("localhost") + "/swagger-ui/index.html";

            OpenUrl(url, logger);
        }
예제 #14
0
        private async Task RegisterServerEndpoints()
        {
            var addresses = await _appHost.GetLocalIpAddresses().ConfigureAwait(false);

            var udn           = CreateUuid(_appHost.SystemId);
            var descriptorUri = "/dlna/" + udn + "/description.xml";

            foreach (var address in addresses)
            {
                if (address.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    // Not supporting IPv6 right now
                    continue;
                }

                // Limit to LAN addresses only
                if (!_networkManager.IsAddressInSubnets(address, true, true))
                {
                    continue;
                }

                var fullService = "urn:schemas-upnp-org:device:MediaServer:1";

                _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address);

                var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorUri);

                var device = new SsdpRootDevice
                {
                    CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info.
                    Location      = uri,                        // Must point to the URL that serves your devices UPnP description document.
                    Address       = address,
                    SubnetMask    = _networkManager.GetLocalIpSubnetMask(address),
                    FriendlyName  = "Jellyfin",
                    Manufacturer  = "Jellyfin",
                    ModelName     = "Jellyfin Server",
                    Uuid          = udn
                                    // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
                };

                SetProperies(device, fullService);
                _publisher.AddDevice(device);

                var embeddedDevices = new[]
                {
                    "urn:schemas-upnp-org:service:ContentDirectory:1",
                    "urn:schemas-upnp-org:service:ConnectionManager:1",
                    // "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"
                };

                foreach (var subDevice in embeddedDevices)
                {
                    var embeddedDevice = new SsdpEmbeddedDevice
                    {
                        FriendlyName = device.FriendlyName,
                        Manufacturer = device.Manufacturer,
                        ModelName    = device.ModelName,
                        Uuid         = udn
                                       // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
                    };

                    SetProperies(embeddedDevice, subDevice);
                    device.AddDevice(embeddedDevice);
                }
            }
        }
예제 #15
0
        private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs <UpnpDeviceInfo> e)
        {
            if (_disposed)
            {
                return;
            }

            var info = e.Argument;

            if (!info.Headers.TryGetValue("USN", out string usn))
            {
                usn = string.Empty;
            }

            if (!info.Headers.TryGetValue("NT", out string nt))
            {
                nt = string.Empty;
            }

            // Filter device type
            if (usn.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 &&
                nt.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 &&
                usn.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1 &&
                nt.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1)
            {
                return;
            }

            var identifier = string.IsNullOrWhiteSpace(usn) ? nt : usn;

            if (info.Location == null)
            {
                return;
            }

            lock (_usnsHandled)
            {
                if (_usnsHandled.Contains(identifier))
                {
                    return;
                }
                _usnsHandled.Add(identifier);
            }

            _logger.LogDebug("Found NAT device: " + identifier);

            if (IPAddress.TryParse(info.Location.Host, out var address))
            {
                // The Handle method doesn't need the port
                var endpoint = new IPEndPoint(address, info.Location.Port);

                IPAddress localAddress = null;

                try
                {
                    var localAddressString = await _appHost.GetLocalApiUrl(CancellationToken.None).ConfigureAwait(false);

                    if (Uri.TryCreate(localAddressString, UriKind.Absolute, out var uri))
                    {
                        localAddressString = uri.Host;

                        if (!IPAddress.TryParse(localAddressString, out localAddress))
                        {
                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error");
                    return;
                }

                if (_disposed)
                {
                    return;
                }

                // This should never happen, but the Handle method will throw ArgumentNullException if it does
                if (localAddress == null)
                {
                    return;
                }

                var natManager = _natManager;
                if (natManager != null)
                {
                    await natManager.Handle(localAddress, info, endpoint, NatProtocol.Upnp).ConfigureAwait(false);
                }
            }
        }
예제 #16
0
        private async Task RegisterServerEndpoints()
        {
            if (!_config.GetDlnaConfiguration().BlastAliveMessages)
            {
                return;
            }

            var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds;

            _Publisher.SupportPnpRootDevice = false;

            var addresses = (await _appHost.GetLocalIpAddresses().ConfigureAwait(false)).ToList();

            foreach (var address in addresses)
            {
                //if (IPAddress.IsLoopback(address))
                //{
                //    // Should we allow this?
                //    continue;
                //}

                var addressString = address.ToString();

                var udn = (addressString).GetMD5().ToString("N");

                var services = new List <string>
                {
                    "urn:schemas-upnp-org:device:MediaServer:1",
                    "urn:schemas-upnp-org:service:ContentDirectory:1",
                    "urn:schemas-upnp-org:service:ConnectionManager:1",
                    "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"
                };

                foreach (var fullService in services)
                {
                    _logger.Info("Registering publisher for {0} on {1}", fullService, addressString);

                    var descriptorURI = "/dlna/" + udn + "/description.xml";
                    var uri           = new Uri(_appHost.GetLocalApiUrl(address) + descriptorURI);

                    var service = fullService.Replace("urn:", string.Empty).Replace(":1", string.Empty);

                    var serviceParts = service.Split(':');

                    var deviceTypeNamespace = serviceParts[0].Replace('.', '-');

                    var device = new SsdpRootDevice
                    {
                        CacheLifetime       = TimeSpan.FromSeconds(cacheLength), //How long SSDP clients can cache this info.
                        Location            = uri,                               // Must point to the URL that serves your devices UPnP description document.
                        DeviceTypeNamespace = deviceTypeNamespace,
                        DeviceClass         = serviceParts[1],
                        DeviceType          = serviceParts[2],
                        FriendlyName        = "Emby Server",
                        Manufacturer        = "Emby",
                        ModelName           = "Emby Server",
                        Uuid = udn
                               // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
                    };

                    _Publisher.AddDevice(device);
                }
            }
        }