Newer
Older
Sunfish / src / Sunfish.Core / Net / LocalAddresses.cs
@Ivan Dominguez Ivan Dominguez 21 hours ago 2 KB 3.0
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Sunfish.Config;
using Sunfish.Web;

namespace Sunfish.Net;

/// <summary>Una direccion local util para dar a otros equipos.</summary>
public sealed record LocalAddress(string Interface, NetworkInterfaceType Type, IPAddress Address);

public static class LocalAddresses
{
    /// <summary>Direcciones de las interfaces activas, sin loopback (IPv4 primero).</summary>
    public static List<LocalAddress> Get()
    {
        var result = new List<LocalAddress>();
        NetworkInterface[] interfaces;
        try
        {
            interfaces = NetworkInterface.GetAllNetworkInterfaces();
        }
        catch (NetworkInformationException)
        {
            return result;
        }
        foreach (var nic in interfaces)
        {
            if (nic.OperationalStatus != OperationalStatus.Up || nic.NetworkInterfaceType == NetworkInterfaceType.Loopback)
                continue;
            foreach (var unicast in nic.GetIPProperties().UnicastAddresses)
            {
                var address = unicast.Address;
                if (IPAddress.IsLoopback(address))
                    continue;
                if (address.AddressFamily == AddressFamily.InterNetworkV6 && address.IsIPv6LinkLocal)
                    continue;
                if (address.AddressFamily is AddressFamily.InterNetwork or AddressFamily.InterNetworkV6)
                    result.Add(new LocalAddress(nic.Name, nic.NetworkInterfaceType, address));
            }
        }
        return result.OrderBy(a => a.Address.AddressFamily == AddressFamily.InterNetwork ? 0 : 1).ToList();
    }

    /// <summary>URL de un share en una direccion: http://192.168.1.10:8080/fotos/</summary>
    public static string HttpUrl(IPAddress address, int port, ShareConfig? share = null)
    {
        string host = address.AddressFamily == AddressFamily.InterNetworkV6 ? $"[{address}]" : address.ToString();
        string path = "/";
        if (share is not null && share.Location != "/")
            path = "/" + string.Join('/', share.Location.Split('/', StringSplitOptions.RemoveEmptyEntries).Select(HtmlBuilder.UrlSegment)) + "/";
        return port == 80 ? $"http://{host}{path}" : $"http://{host}:{port}{path}";
    }

    /// <summary>URL FTP de un share: ftp://192.168.1.10:2121/fotos/</summary>
    public static string FtpUrl(IPAddress address, int port, ShareConfig? share = null)
    {
        string http = HttpUrl(address, 80, share);
        string rest = http["http://".Length..];
        int slash = rest.IndexOf('/');
        string host = rest[..slash];
        return port == 21 ? $"ftp://{host}{rest[slash..]}" : $"ftp://{host}:{port}{rest[slash..]}";
    }
}