# 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
  (del orden de decenas de MB; WinForms no admite *trimming*).
- **Dependiente del framework:** unos pocos MB, pero necesita el .NET Desktop Runtime 10.

**Pendiente:** medir el tamaño real de las dos y fijar cuál genera `build.ps1` por defecto
(propuesta: autocontenida, con una variable de entorno para la ligera).

`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) |
| `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.
