docs: reescreve o manual e registra o JAR instalado no catálogo
O texto explica o núcleo, a rede e o tutorial do ping como o código está hoje. Instalar ou remover um JAR atualiza plugins.registry.json para o próximo run não perder o plugin. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
61753c421a
commit
8338936251
47 files changed
+1423
-1712
No files matched your search
@@ -0,0 +1,73 @@
|
||||
# Mapa do núcleo
|
||||
|
||||
O código do programa está em `pitiupi/src/pitiupi`. Um plugin não precisa abrir essas pastas para funcionar: o contrato de chamada está em [nucleo-para-plugins.md](nucleo-para-plugins.md). Este capítulo é para quem vai ler o código ou alterar o núcleo.
|
||||
|
||||
## Pastas
|
||||
|
||||
| Pacote | O que faz |
|
||||
| --- | --- |
|
||||
| `Main` | Garante `.pitiupi/`, pede nome e porta no `LoginDialog` e abre `MainShellFrame` |
|
||||
| `control.ConnectionManager` | Fachada da rede: porta, nome, envio UDP e TCP, presença, lista de ações |
|
||||
| `control.HeartbeatManager` | Anúncio periódico e timeout de quem sumiu |
|
||||
| `control.plugins.PluginManager` | Lê os JARs, acha as classes pelo SPI e entrega `receiveMessage` |
|
||||
| `net.udp.SocketUDP` | O `MulticastSocket` do grupo `224.0.0.3` |
|
||||
| `net.tcp` | `ServerSocket`, uma `TcpConnection` por IP, framing de 4 bytes + N bytes |
|
||||
| `application.messaging` | `MessageDispatcher`, `SendTarget`, `TransportMode`, combo de transporte |
|
||||
| `application.presence` | A lista **Usuários nesta rede** (`PresenceService`, `UserPeerView`) |
|
||||
| `application.peeractions` | O menu que aparece ao clicar numa pessoa |
|
||||
| `application.session` | Aviso de início ou fim de uma atividade (`SessionNoticeMessage`) |
|
||||
| `application.invites` | Convite de sessão. O núcleo recebe e pode chamar `onInviteAccepted`. Nenhum plugin de referência envia convite, e a janela não mostra uma caixa de convite |
|
||||
| `application.activity` | Contagem de atividade por pessoa. A lista lateral não desenha selo |
|
||||
| `presentation.shell` | Janela, abas, galeria, configurações, painéis que o plugin reutiliza |
|
||||
| `models` | `Plugin`, `Message` e as mensagens do próprio núcleo |
|
||||
| `plugins.store` | Copia o JAR para `.pitiupi/plugins` e, no clone, grava `plugins.registry.json` |
|
||||
| `platform` | Onde fica `.pitiupi` (`PitiupiHome`) e `config.properties` de layout |
|
||||
| `errors.ErrorCode` | Quatro textos em português: falha ao instalar, ao remover, ao carregar, caminho inválido |
|
||||
|
||||
Nome, porta, TTL e saída de rede ficam nas preferências do Java (`NetworkPreferences`), não nesse `config.properties`.
|
||||
|
||||
## Caminho de um datagrama UDP
|
||||
|
||||
`SocketUDP.receive` lê o pacote e tenta desserializar com o classloader do núcleo.
|
||||
|
||||
1. `HeartbeatMessage` vai para `ConnectionManager.receiveHeartbeat`. Não chega no plugin.
|
||||
2. `GoodbyeMessage` vai para `receiveGoodbye`. Não chega no plugin.
|
||||
3. `SessionInviteMessage` vai para `receiveSessionInvite`. Não chega em `receiveMessage`.
|
||||
4. Qualquer outro byte vai para `PluginManager.handleMessage`. Cada JAR tenta desserializar com o próprio classloader. Se a classe está em `getMessages()` (ou `receiveAllTypes()` é verdadeiro e a mensagem é pública), o núcleo chama `receiveMessage`.
|
||||
|
||||
Por isso heartbeat e goodbye não entram na lista do plugin. Se entrarem, o classloader do JAR não é o dono dessas classes.
|
||||
|
||||
## Caminho de um frame TCP
|
||||
|
||||
`TcpConnection` lê um `int` e depois exatamente essa quantidade de bytes. Na abertura, o núcleo troca um `HandshakeMessage` (classe interna de `net.tcp`, invisível ao plugin) com o remetente, o destinatário e a marca de conexão privada.
|
||||
|
||||
- Conexão pública: o frame, se for uma `Message`, segue o mesmo `PluginManager.handleMessage` do UDP.
|
||||
- Conexão privada cujo destinatário é um `getIdentifier()` de plugin: `PluginManager.handleConnection` chama `receivePrivateConnection`. Se o plugin devolve `true`, os frames seguintes vão para `receiveBytes`, e o fechamento chama `onSocketClosed`.
|
||||
- Destinatário que nenhum plugin aceita: o núcleo manda um `InfoMessage` de receptor não encontrado e não entrega os bytes.
|
||||
|
||||
O prazo de 5 segundos para abrir o socket está em [rede.md](rede.md).
|
||||
|
||||
## Mensagens que o núcleo define
|
||||
|
||||
| Classe | Quem cria | Quem consome |
|
||||
| --- | --- | --- |
|
||||
| `HeartbeatMessage` | `HeartbeatManager`, em multicast | `SocketUDP` → presença. Fora do plugin |
|
||||
| `GoodbyeMessage` | Fechamento da janela ou troca de porta | `SocketUDP` → tira a pessoa da lista. Fora do plugin |
|
||||
| `InfoMessage` | Núcleo, em conexões TCP de controle | O próprio TCP (erro, fechamento, plugin ausente). Não é texto de chat |
|
||||
| `HandshakeMessage` | Abertura TCP, pacote `net.tcp` | Só o núcleo. Não declare no plugin |
|
||||
| `SessionNoticeMessage` | Um plugin, em geral o screencast ao parar | Outro plugin que listar a classe em `getMessages()` |
|
||||
| `SessionInviteMessage` | Quem chamar o envio | `InviteInboxService`. A interface atual não mostra o convite |
|
||||
|
||||
`SessionNoticeMessage` carrega o id do plugin, a fase (`START` ou `END`), o canal (`SCREEN_CAST` hoje), o nome e o IP de quem enviou, o escopo (`BROADCAST` ou `DIRECT`) e o `TransportMode`. O screencast manda `END` no canal `SCREEN_CAST` quando o compartilhamento para. Quem recebe e registrou o tipo fecha a aba de recebimento.
|
||||
|
||||
## Onde alterar o núcleo
|
||||
|
||||
| Mudança | Onde |
|
||||
| --- | --- |
|
||||
| Novo tipo só do seu plugin | Classe no JAR, `extends Message`, entrada em `getMessages()`. O núcleo não muda |
|
||||
| Novo transporte no combo da interface | Valor em `PluginTransportCatalog.PluginKind`. Hoje existem `CHAT`, `SCREEN_CAST` e `PING` |
|
||||
| Mensagem de infraestrutura (todo mundo precisa entender sem ter o JAR) | `models.Messages` e o filtro em `SocketUDP.tryParseCoreUdpMessage` |
|
||||
| Nova ação na lista de pessoas | Não é mudança de núcleo: `PeerAction` no plugin |
|
||||
| Texto de erro de instalação | `errors.ErrorCode` |
|
||||
|
||||
O grupo multicast, a porta única e o framing TCP estão decididos em [decision-register.md](decision-register.md). O comportamento na rede está em [rede.md](rede.md).
|
||||
Reference in new issue
Block a user