# Arquitectura (prevista)

> Sunfish 3 está en diseño: todavía no hay código nuevo. El código de la 2.0 sigue en el
> repositorio hasta que empiece la reescritura (ver [LEGACY-2.0.md](LEGACY-2.0.md)).

## Idea general

Una **biblioteca común** con todo el servidor (HTTP, web, FTP, WebDAV, configuración, Mac
clásico) y **aplicaciones finas** encima, una por tipo de interfaz:

```
   Sunfish.exe (WinForms)    sunfish-cli (TUI / consola)    futuro: GTK · macOS
            │                          │                           │
            └──────────────┬───────────┴───────────────────────────┘
                           │  SunfishHost: arrancar, parar, estado, eventos
                ┌──────────┴───────────────────────────────────────────┐
                │                    Sunfish.Core                      │
                │  Config · Shares/rutas · Usuarios · Registro         │
                │  HTTP propio ─┬─ Web (HTML4) ─ Admin ─ WebDAV        │
                │  FTP ─────────┘                                      │
                │  Mac clásico (MacBinary, BinHex, AppleDouble) · ZIP  │
                │  QR · IP locales · Textos ES/EN                      │
                └──────────────────────────────────────────────────────┘
```

Las aplicaciones no contienen lógica de servidor: muestran el estado, editan la configuración
y llaman a `SunfishHost`. Así una interfaz GTK o macOS futura solo tiene que hacer eso mismo.

## Estructura del repositorio

```
Sunfish/
├─ Sunfish.slnx
├─ src/
│  ├─ Sunfish.Core/        biblioteca (net10.0), compatible con Native AOT
│  ├─ Sunfish.WinForms/    Sunfish.exe (net10.0-windows, WinExe)
│  └─ Sunfish.Cli/         sunfish-cli (net10.0, Native AOT)
│     (futuro) Sunfish.Gtk/, Sunfish.Mac/
├─ tests/
│  └─ Sunfish.Tests/       xUnit; InternalsVisibleTo desde Sunfish.Core
├─ DOC/
├─ build.ps1               Windows: compila Sunfish.exe y sunfish-cli.exe
├─ build.sh                Linux y macOS: compila sunfish-cli
├─ run.cmd · run-cli.cmd   dotnet run (GUI / consola) para doble clic en Windows
├─ run.sh                  dotnet run de la consola en Linux y macOS
├─ AGENTS.md · CLAUDE.md
└─ README.md · LICENSE
```

## Publicación

| Ejecutable | Sistemas | Modo | Notas |
|---|---|---|---|
| `sunfish-cli` | win, linux, osx (x64 y arm64) | **Native AOT** | Un binario nativo sin runtime. Se compila en cada sistema |
| `Sunfish.exe` | win-x64, win-arm64 | **Un solo `.exe`** (`PublishSingleFile`) | WinForms no admite Native AOT |

Para `Sunfish.exe` hay dos variantes:

- **Autocontenida** (`SelfContained`, `EnableCompressionInSingleFile`): incluye el runtime de
  .NET y funciona en cualquier Windows 10/11 sin instalar nada. Es la más portable, pero grande:
  **~49 MB** (WinForms no admite *trimming*). Es la que genera `build.ps1` por defecto.
- **Dependiente del framework** (`-p:SelfContained=false`, o `SUNFISH_LIGHT=1` en `build.ps1`):
  **~0,5 MB**, pero necesita el .NET Desktop Runtime 10.

`build.ps1` exige las herramientas de C++ (para `sunfish-cli`) y falla con el comando para
instalarlas si no están, como el resto de proyectos.

`sunfish-cli` es la opción más portable de verdad: nativo y pequeño en los tres sistemas.

## Módulos de `Sunfish.Core`

| Módulo | Responsabilidad | Documento |
|---|---|---|
| `Host` | `SunfishHost`: arranque y parada de los servicios, estado, eventos (registro, conexiones, transferencias) para las interfaces | — |
| `Config` | Fichero INI (leer y escribir conservando comentarios), ubicación, importación de la 2.0 | [SHARES-Y-RUTAS.md](SHARES-Y-RUTAS.md) |
| `Shares` | Árbol de *locations*, resolución por prefijo más largo, directorios virtuales, validación de rutas | [SHARES-Y-RUTAS.md](SHARES-Y-RUTAS.md) |
| `Auth` | Usuarios, hashes PBKDF2, caché de credenciales verificadas, límite de intentos | [SEGURIDAD.md](SEGURIDAD.md) |
| `Http` | Servidor HTTP propio sobre `Socket`: HTTP/0.9, 1.0 y 1.1, rangos, multipart en flujo, Basic | [WEB.md](WEB.md) |
| `Web` | Páginas HTML4, juego de caracteres, iconos GIF, mejora progresiva con JS, autodescarga | [WEB.md](WEB.md) |
| `Admin` | Panel de administración web con contraseña | [WEB.md](WEB.md#panel-de-administración) |
| `WebDav` | Clase 1 + LOCK simulado sobre el mismo motor HTTP | [FTP-Y-WEBDAV.md](FTP-Y-WEBDAV.md) |
| `Ftp` | Servidor FTP: control, datos activo/pasivo, listados, juegos de caracteres | [FTP-Y-WEBDAV.md](FTP-Y-WEBDAV.md) |
| `Mac` | MacBinary I/II/III, BinHex 4.0, AppleDouble, tabla de tipo/creador | [MAC-CLASICO.md](MAC-CLASICO.md) |
| `Clients` | Perfiles de cliente por User-Agent o por sesión FTP; alias 8.3 estables | [CLIENTES.md](CLIENTES.md) |
| `DavClient` | Cliente WebDAV para explorar otros servidores | [FTP-Y-WEBDAV.md](FTP-Y-WEBDAV.md#de-sunfish-a-sunfish) |
| `Discovery` | Anuncio y búsqueda DNS-SD sobre mDNS | [FTP-Y-WEBDAV.md](FTP-Y-WEBDAV.md#de-sunfish-a-sunfish) |
| `Zip` | Escritor ZIP en flujo, compatible con descompresores antiguos | [WEB.md](WEB.md#descargar-carpetas-en-zip) |
| `Qr` | Generador de códigos QR propio (para la URL; lo pintan la GUI y la TUI) | [APLICACIONES.md](APLICACIONES.md) |
| `Net` | Lista de IP locales por interfaz, URLs por share | [APLICACIONES.md](APLICACIONES.md) |
| `Strings` | Textos en español e inglés | — |
| `Log` | Registro en memoria (para las interfaces) y opcionalmente a fichero | — |

Los recursos web (GIF, CSS, JS mínimo) van como `EmbeddedResource` de `Sunfish.Core`: no hay
carpeta `$sunfish` externa ni "sellado".

## Concurrencia

- Todo asíncrono con `Socket` y `async`/`await`; ni un hilo por petición ni `Thread.Abort`.
- HTTP: una tarea por conexión, con keep-alive cuando el cliente lo admite.
- FTP: una tarea por conexión de control y otra por cada conexión de datos.
- Límites globales y por IP de conexiones simultáneas; plazos de lectura y escritura.
- Las interfaces reciben los eventos del host en su propio hilo (la GUI hace `Invoke`).

## Restricciones de Native AOT (para `Sunfish.Core` y `sunfish-cli`)

- Sin reflexión: nada de plugins, ni plantillas por reflexión (como en la 2.0), ni serialización
  por reflexión. Las páginas se generan con código y plantillas simples con diccionarios.
- La importación de la configuración 2.0 (JSON) usa `JsonDocument`, que no necesita reflexión.
- El XML de WebDAV se lee con `XmlReader` y se escribe con `XmlWriter`.
- Los juegos de caracteres antiguos (ISO-8859-1, MacRoman, CP437, CP850, Windows-1252) usan
  `CodePagesEncodingProvider`, registrado al arrancar.
- P/Invoke, si hiciera falta, solo con `LibraryImport`.
- `Sunfish.Core` lleva `IsAotCompatible`; los avisos de AOT y *trimming* se tratan como errores.
