예제 #1
0
파일: SocketFactory.cs 프로젝트: vvuk/Emby
        /// <summary>
        /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port.
        /// </summary>
        /// <returns>An implementation of the <see cref="ISocket"/> interface used by RSSDP components to perform acceptSocket operations.</returns>
        public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort)
        {
            if (localPort < 0)
            {
                throw new ArgumentException("localPort cannot be less than zero.", "localPort");
            }

            var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);

            try
            {
                retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);

                var localIp = NetworkManager.ToIPAddress(localIpAddress);

                retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp));
                return(new UdpSocket(retVal, localPort, localIp));
            }
            catch
            {
                if (retVal != null)
                {
                    retVal.Dispose();
                }

                throw;
            }
        }
예제 #2
0
 public async Task <bool> CheckTunerAvailability(IpAddressInfo remoteIp, int tuner, CancellationToken cancellationToken)
 {
     using (var socket = _socketFactory.CreateTcpSocket(remoteIp, HdHomeRunPort))
     {
         return(await CheckTunerAvailability(socket, remoteIp, tuner, cancellationToken).ConfigureAwait(false));
     }
 }
예제 #3
0
        public void GetIpConfig_HoloLens_1607()
        {
            TestHelpers.MockHttpResponder.AddMockResponse(
                DevicePortal.IpConfigApi,
                this.PlatformType,
                this.FriendlyOperatingSystemVersion,
                HttpMethods.Get);

            Task <IpConfiguration> getTask = TestHelpers.Portal.GetIpConfigAsync();

            getTask.Wait();

            Assert.AreEqual(TaskStatus.RanToCompletion, getTask.Status);

            IpConfiguration ipconfig = getTask.Result;

            // Check some known things about this response.
            Assert.AreEqual(2, ipconfig.Adapters.Count);
            NetworkAdapterInfo adapter = ipconfig.Adapters[0];

            Assert.AreEqual("Bluetooth Device (Personal Area Network)", adapter.Description);
            Assert.AreEqual("4c-0b-be-ff-bd-64", adapter.MacAddress);
            Assert.AreEqual(7, adapter.Index);
            Assert.AreEqual(Guid.Parse("{765C05C8-7B46-4CE6-BEC9-33C6112234B4}"), adapter.Id);
            Assert.AreEqual("Ethernet", adapter.AdapterType);
            IpAddressInfo ipAddress = adapter.IpAddresses[0];

            Assert.AreEqual("0.0.0.0", ipAddress.Address);
            Assert.AreEqual("0.0.0.0", ipAddress.SubnetMask);
        }
예제 #4
0
        private List <ISocket> GetSendSockets(IpAddressInfo fromLocalIpAddress, IpEndPointInfo destination)
        {
            EnsureSendSocketCreated();

            lock (_SendSocketSynchroniser)
            {
                var sockets = _sendSockets.Where(i => i.LocalIPAddress.AddressFamily == fromLocalIpAddress.AddressFamily);

                // Send from the Any socket and the socket with the matching address
                if (fromLocalIpAddress.AddressFamily == IpAddressFamily.InterNetwork)
                {
                    sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.Any) || fromLocalIpAddress.Equals(i.LocalIPAddress));

                    // If sending to the loopback address, filter the socket list as well
                    if (destination.IpAddress.Equals(IpAddressInfo.Loopback))
                    {
                        sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.Any) || i.LocalIPAddress.Equals(IpAddressInfo.Loopback));
                    }
                }
                else if (fromLocalIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
                {
                    sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.IPv6Any) || fromLocalIpAddress.Equals(i.LocalIPAddress));

                    // If sending to the loopback address, filter the socket list as well
                    if (destination.IpAddress.Equals(IpAddressInfo.IPv6Loopback))
                    {
                        sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.IPv6Any) || i.LocalIPAddress.Equals(IpAddressInfo.IPv6Loopback));
                    }
                }

                return(sockets.ToList());
            }
        }
예제 #5
0
        /// <summary>
        /// Sends a message to the SSDP multicast address and port.
        /// </summary>
        public async Task SendMulticastMessage(string message, int sendCount, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            byte[] messageData = Encoding.UTF8.GetBytes(message);

            ThrowIfDisposed();

            cancellationToken.ThrowIfCancellationRequested();

            EnsureSendSocketCreated();

            // SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
            for (var i = 0; i < sendCount; i++)
            {
                await SendMessageIfSocketNotDisposed(messageData, new IpEndPointInfo
                {
                    IpAddress = new IpAddressInfo(SsdpConstants.MulticastLocalAdminAddress, IpAddressFamily.InterNetwork),
                    Port      = SsdpConstants.MulticastPort
                }, fromLocalIpAddress, cancellationToken).ConfigureAwait(false);

                await Task.Delay(100, cancellationToken).ConfigureAwait(false);
            }
        }
예제 #6
0
        public void GetIpConfig_IoT()
        {
            TestHelpers.MockHttpResponder.AddMockResponse(
                DevicePortal.IpConfigApi,
                this.PlatformType,
                this.FriendlyOperatingSystemVersion,
                HttpMethods.Get);

            Task <IpConfiguration> getTask = TestHelpers.Portal.GetIpConfig();

            getTask.Wait();

            Assert.AreEqual(TaskStatus.RanToCompletion, getTask.Status);

            IpConfiguration ipconfig = getTask.Result;

            // Check some known things about this response.
            NetworkAdapterInfo adapter = ipconfig.Adapters[0];

            Assert.AreEqual("Bluetooth Device (Personal Area Network)", adapter.Description);
            Assert.AreEqual("b8-27-eb-8d-0b-c5", adapter.MacAddress);
            Assert.AreEqual(4, adapter.Index);
            IpAddressInfo ipAddress = adapter.IpAddresses[0];

            Assert.AreEqual("0.0.0.0", ipAddress.Address);
            Assert.AreEqual("0.0.0.0", ipAddress.SubnetMask);
        }
예제 #7
0
        private void LoadCachedAddress()
        {
            var path = CacheFilePath;

            _logger.Info("Loading data from {0}", path);

            try
            {
                var           endpoint = _encryption.DecryptString(_fileSystem.ReadAllText(path, Encoding.UTF8));
                IpAddressInfo ipAddress;

                if (_networkManager.TryParseIpAddress(endpoint, out ipAddress))
                {
                    _cachedIpAddress = ipAddress;
                    ((ConnectManager)_connectManager).OnWanAddressResolved(ipAddress);
                }
            }
            catch (IOException)
            {
                // File isn't there. no biggie
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error loading data", ex);
            }
        }
예제 #8
0
        public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort)
        {
            if (remotePort < 0)
            {
                throw new ArgumentException("remotePort cannot be less than zero.", "remotePort");
            }

            var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);

            try
            {
                retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }
            catch (SocketException)
            {
                // This is not supported on all operating systems (qnap)
            }

            try
            {
                return(new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)));
            }
            catch
            {
                if (retVal != null)
                {
                    retVal.Dispose();
                }

                throw;
            }
        }
예제 #9
0
        private void CacheAddress(IpAddressInfo address)
        {
            if (_cachedIpAddress != null && _cachedIpAddress.Equals(address))
            {
                // no need to update the file if the address has not changed
                return;
            }

            var path = CacheFilePath;

            try
            {
                _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
            }
            catch (Exception ex)
            {
            }

            try
            {
                _fileSystem.WriteAllText(path, _encryption.EncryptString(address.ToString()), Encoding.UTF8);
                _cachedIpAddress = address;
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error saving data", ex);
            }
        }
예제 #10
0
        public IpAddressInfo GetLocalIpSubnetMask(IpAddressInfo address)
        {
            NetworkInterface[] interfaces;
            IPAddress          ipaddress = ToIPAddress(address);

            try
            {
                var validStatuses = new[] { OperationalStatus.Up, OperationalStatus.Unknown };

                interfaces = NetworkInterface.GetAllNetworkInterfaces()
                             .Where(i => validStatuses.Contains(i.OperationalStatus))
                             .ToArray();
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error in GetAllNetworkInterfaces");
                return(null);
            }

            foreach (NetworkInterface ni in interfaces)
            {
                if (ni.GetIPProperties().GatewayAddresses.FirstOrDefault() != null)
                {
                    foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                    {
                        if (ip.Address.Equals(ipaddress) && ip.IPv4Mask != null)
                        {
                            return(ToIpAddressInfo(ip.IPv4Mask));
                        }
                    }
                }
            }
            return(null);
        }
예제 #11
0
        public bool IsInSameSubnet(IpAddressInfo address1, IpAddressInfo address2, IpAddressInfo subnetMask)
        {
            IPAddress network1 = GetNetworkAddress(ToIPAddress(address1), ToIPAddress(subnetMask));
            IPAddress network2 = GetNetworkAddress(ToIPAddress(address2), ToIPAddress(subnetMask));

            return(network1.Equals(network2));
        }
예제 #12
0
        private async void TimerCallback(object state)
        {
            IpAddressInfo validIpAddress = null;

            foreach (var ipLookupUrl in _ipLookups)
            {
                try
                {
                    validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false);

                    // Try to find the ipv4 address, if present
                    if (validIpAddress.AddressFamily != IpAddressFamily.InterNetworkV6)
                    {
                        break;
                    }
                }
                catch (HttpException)
                {
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error getting connection info", ex);
                }
            }

            // If this produced an ipv6 address, try again
            if (validIpAddress != null && validIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
            {
                foreach (var ipLookupUrl in _ipLookups)
                {
                    try
                    {
                        var newAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false);

                        // Try to find the ipv4 address, if present
                        if (newAddress.AddressFamily != IpAddressFamily.InterNetworkV6)
                        {
                            validIpAddress = newAddress;
                            break;
                        }
                    }
                    catch (HttpException)
                    {
                    }
                    catch (Exception ex)
                    {
                        _logger.ErrorException("Error getting connection info", ex);
                    }
                }
            }

            if (validIpAddress != null)
            {
                ((ConnectManager)_connectManager).OnWanAddressResolved(validIpAddress);
                CacheAddress(validIpAddress);
            }
        }
예제 #13
0
        private Task <string> GetServerAddress(IpAddressInfo address, CancellationToken cancellationToken)
        {
            if (address == null)
            {
                return(_appHost.GetLocalApiUrl(cancellationToken));
            }

            return(Task.FromResult(_appHost.GetLocalApiUrl(address)));
        }
예제 #14
0
        private Task <string> GetServerAddress(IpAddressInfo address)
        {
            if (address == null)
            {
                return(_appHost.GetLocalApiUrl());
            }

            return(Task.FromResult(_appHost.GetLocalApiUrl(address)));
        }
예제 #15
0
        private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IpAddressInfo localIpAddress)
        {
            if (!NotificationTypeMatchesFilter(device))
            {
                return;
            }

            OnDeviceAvailable(device, isNewDevice, localIpAddress);
        }
예제 #16
0
        public UpnpDevice(string aUuid, string aType, Uri aDescriptor, IpAddressInfo address)
        {
            Uuid       = aUuid;
            Type       = aType;
            Descriptor = aDescriptor;

            Address = address;

            USN = CreateUSN(aUuid, aType);
        }
예제 #17
0
        public void AddListener(IpAddressInfo ipAddress)
        {
            var listener = new Listener(IPAddress.Parse(ipAddress.Ip), ipAddress.Port);

            Listeners.Add(listener);
            if (IsRunning)
            {
                listener.Connect += ListenerOnConnect;
                listener.Start();
            }
        }
예제 #18
0
        public bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo)
        {
            if (IPAddress.TryParse(ipAddress, out var address))
            {
                ipAddressInfo = ToIpAddressInfo(address);
                return(true);
            }

            ipAddressInfo = null;
            return(false);
        }
예제 #19
0
        public void RemoveListener(IpAddressInfo ipAddress)
        {
            var listener =
                Listeners.FirstOrDefault(x => x.IpAddress.ToString() == ipAddress.Ip && x.Port == ipAddress.Port);

            if (listener == null)
            {
                return;
            }

            RemoveListener(listener);
        }
예제 #20
0
        private void CacheAddress(IpAddressInfo address)
        {
            var path = CacheFilePath;

            try
            {
                _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
                _fileSystem.WriteAllText(path, address.ToString(), Encoding.UTF8);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error saving data", ex);
            }
        }
예제 #21
0
        private static async Task <bool> CheckTunerAvailability(ISocket socket, IpAddressInfo remoteIp, int tuner, CancellationToken cancellationToken)
        {
            var ipEndPoint = new IpEndPointInfo(remoteIp, HdHomeRunPort);

            var lockkeyMsg = CreateGetMessage(tuner, "lockkey");
            await socket.SendToAsync(lockkeyMsg, 0, lockkeyMsg.Length, ipEndPoint, cancellationToken);

            var receiveBuffer = new byte[8192];
            var response      = await socket.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false);

            ParseReturnMessage(response.Buffer, response.ReceivedBytes, out string returnVal);

            return(string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase));
        }
예제 #22
0
        public UdpSocket(Socket socket, int localPort, IPAddress ip)
        {
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            _socket        = socket;
            _localPort     = localPort;
            LocalIPAddress = NetworkManager.ToIpAddressInfo(ip);

            _socket.Bind(new IPEndPoint(ip, _localPort));

            InitReceiveSocketAsyncEventArgs();
        }
예제 #23
0
        private void AddListenerButton_Click(object sender, EventArgs e)
        {
            var window = new CreateNewListenerForm();

            if (window.ShowDialog(this) == DialogResult.OK)
            {
                var ipAddressInfo = new IpAddressInfo {
                    Ip = window.IpAddress, Port = window.Port
                };
                _settings.IpAddresses.Add(ipAddressInfo);
                _settings.Save();
                _bindingSource.ResetBindings(false);
                _server.AddListener(ipAddressInfo);
            }
        }
예제 #24
0
        private void ProcessNotificationMessage(HttpRequestMessage message, IpAddressInfo localIpAddress)
        {
            if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0)
            {
                return;
            }

            var notificationType = GetFirstHeaderStringValue("NTS", message);

            if (String.Compare(notificationType, SsdpConstants.SsdpKeepAliveNotification, StringComparison.OrdinalIgnoreCase) == 0)
            {
                ProcessAliveNotification(message, localIpAddress);
            }
            else if (String.Compare(notificationType, SsdpConstants.SsdpByeByeNotification, StringComparison.OrdinalIgnoreCase) == 0)
            {
                ProcessByeByeNotification(message);
            }
        }
예제 #25
0
        private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IpAddressInfo localIpAddress)
        {
            // Don't raise the event if we've already done it for a cached
            // version of this device, and the cached version isn't
            // "significantly" different, i.e location and cachelifetime
            // haven't changed.
            var raiseEvent = false;

            if (!NotificationTypeMatchesFilter(device))
            {
                return;
            }

            lock (_SearchResultsSynchroniser)
            {
                if (_SearchResults != null)
                {
                    var existingDevice = FindExistingDeviceNotification(_SearchResults, device.NotificationType, device.Usn);
                    if (existingDevice == null)
                    {
                        _SearchResults.Add(device);
                        raiseEvent = true;
                    }
                    else
                    {
                        if (existingDevice.DescriptionLocation != device.DescriptionLocation || existingDevice.CacheLifetime != device.CacheLifetime)
                        {
                            _SearchResults.Remove(existingDevice);
                            _SearchResults.Add(device);
                            raiseEvent = true;
                        }
                    }
                }
                else
                {
                    raiseEvent = true;
                }
            }

            if (raiseEvent)
            {
                OnDeviceAvailable(device, isNewDevice, localIpAddress);
            }
        }
예제 #26
0
        private void ProcessAliveNotification(HttpRequestMessage message, IpAddressInfo localIpAddress)
        {
            var location = GetFirstHeaderUriValue("Location", message);

            if (location != null)
            {
                var device = new DiscoveredSsdpDevice()
                {
                    DescriptionLocation = location,
                    Usn = GetFirstHeaderStringValue("USN", message),
                    NotificationType = GetFirstHeaderStringValue("NT", message),
                    CacheLifetime    = CacheAgeFromHeader(message.Headers.CacheControl),
                    AsAt             = DateTimeOffset.Now,
                    ResponseHeaders  = message.Headers
                };

                AddOrUpdateDiscoveredDevice(device, localIpAddress);
            }
        }
예제 #27
0
        private void ProcessMessage(string data, IpEndPointInfo endPoint, IpAddressInfo receivedOnLocalIpAddress)
        {
            //Responses start with the HTTP version, prefixed with HTTP/ while
            //requests start with a method which can vary and might be one we haven't
            //seen/don't know. We'll check if this message is a request or a response
            //by checking for the HTTP/ prefix on the start of the message.
            if (data.StartsWith("HTTP/", StringComparison.OrdinalIgnoreCase))
            {
                HttpResponseMessage responseMessage = null;
                try
                {
                    responseMessage = _ResponseParser.Parse(data);
                }
                catch (ArgumentException)
                {
                    // Ignore invalid packets.
                }

                if (responseMessage != null)
                {
                    OnResponseReceived(responseMessage, endPoint, receivedOnLocalIpAddress);
                }
            }
            else
            {
                HttpRequestMessage requestMessage = null;
                try
                {
                    requestMessage = _RequestParser.Parse(data);
                }
                catch (ArgumentException)
                {
                    // Ignore invalid packets.
                }

                if (requestMessage != null)
                {
                    OnRequestReceived(requestMessage, endPoint, receivedOnLocalIpAddress);
                }
            }
        }
예제 #28
0
        private void AddOrUpdateDiscoveredDevice(DiscoveredSsdpDevice device, IpAddressInfo localIpAddress)
        {
            bool isNewDevice = false;

            lock (_Devices)
            {
                var existingDevice = FindExistingDeviceNotification(_Devices, device.NotificationType, device.Usn);
                if (existingDevice == null)
                {
                    _Devices.Add(device);
                    isNewDevice = true;
                }
                else
                {
                    _Devices.Remove(existingDevice);
                    _Devices.Add(device);
                }
            }

            DeviceFound(device, isNewDevice, localIpAddress);
        }
        public static IPAddress ToIPAddress(IpAddressInfo address)
        {
            if (address.Equals(IpAddressInfo.Any))
            {
                return(IPAddress.Any);
            }
            if (address.Equals(IpAddressInfo.IPv6Any))
            {
                return(IPAddress.IPv6Any);
            }
            if (address.Equals(IpAddressInfo.Loopback))
            {
                return(IPAddress.Loopback);
            }
            if (address.Equals(IpAddressInfo.IPv6Loopback))
            {
                return(IPAddress.IPv6Loopback);
            }

            return(IPAddress.Parse(address.Address));
        }
예제 #30
0
        public EndPointListener(HttpListener listener, IpAddressInfo addr, int port, bool secure, ICertificate cert, ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding)
        {
            this.listener        = listener;
            _logger              = logger;
            _cryptoProvider      = cryptoProvider;
            _streamFactory       = streamFactory;
            _socketFactory       = socketFactory;
            _memoryStreamFactory = memoryStreamFactory;
            _textEncoding        = textEncoding;

            this.secure = secure;
            this.cert   = cert;

            _enableDualMode = addr.Equals(IpAddressInfo.IPv6Any);
            endpoint        = new IpEndPointInfo(addr, port);

            prefixes     = new Dictionary <ListenerPrefix, HttpListener>();
            unregistered = new Dictionary <HttpConnection, HttpConnection>();

            CreateSocket();
        }