Entrega v1 aula: shell com abas, PITIUPI_HOME e plugins de referência.

Consolida núcleo (presença, peer actions, MessageDispatcher), chat e screencast na galeria, documentação PT-BR e testes JUnit; remove mpChat do catálogo em favor do chat unificado.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Gabriel Felipe Souza SantosandCursor committed 2026-10-27 11:08:21 -03:00
1 parent b10c196fc9
commit eeb1936f6d
178 files changed
+7641 -1481

No files matched your search

+16 -32
View File
@@ -3,61 +3,45 @@
## Pré-requisitos
- **JDK completo** (`java` e `javac`) — OpenJDK 25 recomendado; o núcleo usa `javac.source/target=17`, plugins Ant usam 25.
- Apache Ant (`pitiupi`, `pitiupi.chat`, `pitiupi.screenCast`)
- GNU Make (`pitiupi.mpChat`)
- Apache Ant (`pitiupi`, `plugins/chat`, `plugins/screencast`)
Ubuntu / WSL:
```bash
sudo apt install openjdk-25-jdk ant make
which javac ant make
sudo apt install openjdk-25-jdk ant
which javac ant
```
Se `ant jar` falhar com *Cannot run program "javac"*, você instalou apenas JRE — instale `openjdk-*-jdk`.
## Build
Na raiz do clone:
```bash
cd pitiupi && ant jar
cd ../pitiupi.chat && ant jar
cd ../pitiupi.screenCast && ant jar
cd ../pitiupi.mpChat && make
./scripts/pitiupi.sh build --all
```
O núcleo gera `pitiupi/dist/pitiupi.jar`. Cada plugin gera JAR em seu `dist/`.
Ou manualmente:
```bash
cd pitiupi && ant jar
cd plugins/chat && ant jar
cd plugins/screencast && ant jar
```
## Instalar plugins
A aplicação lê JARs de `pitiupi/plugins/` (relativo ao diretório de trabalho ao executar o núcleo). Detalhes: [pitiupi/plugins/README.md](../../pitiupi/plugins/README.md).
Symlinks em desenvolvimento (Linux):
Runtime: JARs em **`PITIUPI_HOME/plugins`** (padrão `~/pitiupi/plugins`).
```bash
cd pitiupi/plugins
ln -sf ../../pitiupi.chat/dist/pitiupi.chat.jar pitiupi.chat.jar
ln -sf ../../pitiupi.screenCast/dist/pitiupi.screenCast.jar pitiupi.screenCast.jar
ln -sf ../../pitiupi.mpChat/dist/mpChat.jar mpChat.jar
./scripts/pitiupi.sh link --all
```
## Executar
```bash
cd pitiupi
java -jar dist/pitiupi.jar
./scripts/pitiupi.sh run --all
```
No diálogo inicial informe **nome** e **porta** (UDP/TCP). Para duas instâncias no mesmo computador, use **portas diferentes** (ex.: 5000 e 5001).
Login com nome e porta; abra plugins pela aba **Plugins**. Clique em **Todos** ou em um peer na lista lateral para ver ações de cada plugin.
## Verificar P2P
1. Abra duas instâncias (mesma rede ou mesmo host com portas distintas).
2. Confirme que os nomes aparecem no painel de usuários online.
3. Teste um plugin de referência (ex.: chat em `MenuCategory.Social`).
Problemas de multicast: [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md).
Gate de build (quatro módulos): [15_testes_e_gate.md](15_testes_e_gate.md).
Próximo passo para o TP: [10_tutorial_plugin.md](10_tutorial_plugin.md).
Validação rápida do núcleo: `cd pitiupi && ant test`.
@@ -25,9 +25,9 @@ Exemplos de tema: chat temático, tabuleiro (xadrez/damas), compartilhamento de
| Módulo | Ideia pedagógica |
| --- | --- |
| `pitiupi.chat` | Mensagens UDP + UI simples |
| `pitiupi.screenCast` | Payload maior / streaming de imagem |
| `pitiupi.mpChat` | Multicast + TCP privado no mesmo plugin |
| `plugins/chat` | Mensagens UDP + UI simples |
| `plugins/screencast` | Payload maior / streaming de imagem |
| `plugins/chat` | Multicast, unicast, TCP e canal TCP privado |
Detalhes: [11_plugins_referencia.md](11_plugins_referencia.md).
+15 -23
View File
@@ -1,36 +1,28 @@
# Módulos do repositório
```
pitiupi/ # clone (este repositório)
├── plugins.registry.json # catálogo de módulos (build/link via scripts/pitiupi.sh)
pitiupi/ # clone (este repositório)
├── plugins.registry.json
├── scripts/pitiupi.sh
├── pitiupi/ # núcleo P2P (executável)
├── pitiupi.chat/ # plugin referência — chat
├── pitiupi.screenCast/ # plugin referência — captura de tela
├── pitiupi.mpChat/ # plugin referência — chat multi-protocolo
└── docs/ # documentação canônica
├── pitiupi/ # núcleo P2P (executável)
├── plugins/
│ ├── chat/ # chat unificado (UDP/multicast/TCP + TCP privado)
│ ├── screencast/ # compartilhamento de tela
│ └── ping/ # exercício de aula (só doc)
└── docs/
```
## Núcleo (`pitiupi/`)
- **Build:** Apache Ant (`build.xml`, `nbproject/`).
- **Entrada:** `pitiupi.Main` → login → `MainWindow`.
- **Pacotes principais:** `pitiupi.net`, `pitiupi.control`, `pitiupi.GUI`, `pitiupi.models`.
- **Build:** Apache Ant.
- **Entrada:** `pitiupi.Main` → login → `MainShellFrame`.
- **Messaging:** `pitiupi.application.messaging.MessageDispatcher`.
## Plugins de referência
| Pasta | Build | JAR típico | Classe SPI |
| Pasta | Build | JAR típico | SPI |
| --- | --- | --- | --- |
| `pitiupi.chat` | `ant jar` | `dist/pitiupi.chat.jar` | `pitiupi.chat.plugin.ChatPlugin` |
| `pitiupi.screenCast` | `ant jar` | `dist/pitiupi.screenCast.jar` | `pitiupi.screenCast.plugin.ScreenCastPlugin` |
| `pitiupi.mpChat` | `make` | `dist/mpChat.jar` | `plugin.MultiProtocolChat` |
| `plugins/chat` | `ant jar` | `dist/pitiupi.chat.jar` | `pitiupi.chat.plugin.ChatPlugin` |
| `plugins/screencast` | `ant jar` | `dist/pitiupi.screenCast.jar` | `pitiupi.screenCast.plugin.ScreenCastPlugin` |
Todos dependem do JAR do núcleo no classpath de compilação.
## O que o aluno cria
Novo diretório irmão, por exemplo `pitiupi.xadrez/`, copiando a estrutura de `pitiupi.chat` (Ant + `META-INF/services`). Registre o módulo em `plugins.registry.json` e use `MenuCategory` adequado no código.
Não é obrigatório commitar o plugin do aluno neste repositório base; o professor pode definir fork ou entrega em zip.
Ver [03_build_ant_netbeans.md](03_build_ant_netbeans.md) e [10_tutorial_plugin.md](10_tutorial_plugin.md).
Ver [10_tutorial_plugin.md](10_tutorial_plugin.md) e [17_tutorial_ping_aula.md](17_tutorial_ping_aula.md).
+8 -40
View File
@@ -1,49 +1,17 @@
# Build — Ant, NetBeans e Make
# Build — Ant e NetBeans
## Pré-requisitos e versões Java
| Módulo | Build | `javac.source` / `target` (NetBeans) |
| Módulo | Build | Java |
| --- | --- | --- |
| `pitiupi` | Ant | 17 |
| `pitiupi.chat` | Ant | 25 |
| `pitiupi.screenCast` | Ant | 25 |
| `pitiupi.mpChat` | Make | (sem `project.properties`; compila contra `pitiupi.jar`) |
Use um JDK que forneça `javac` (ex.: OpenJDK 25). Ant 1.10+ e Make no PATH.
## Núcleo e plugins NetBeans
Projetos com `nbproject/` e `build.xml`:
| `plugins/chat` | Ant | 25 |
| `plugins/screencast` | Ant | 25 |
```bash
cd pitiupi && ant jar
cd pitiupi.chat && ant jar
cd pitiupi.screenCast && ant jar
cd plugins/chat && ant jar
cd plugins/screencast && ant jar
```
Abrir no NetBeans: **File → Open Project** em cada pasta.
Classpath dos plugins: `../../pitiupi/dist/pitiupi.jar`.
O target `jar` produz o executável do núcleo e os JARs dos plugins. O classpath de compilação dos plugins aponta para `../pitiupi/dist/pitiupi.jar` (ver `project.properties` de cada módulo).
## pitiupi.mpChat (Makefile)
```bash
cd pitiupi.mpChat
make
```
O Makefile compila com `javac -cp ../pitiupi/dist/pitiupi.jar`, copia `META-INF` e gera `dist/mpChat.jar`. **Compile o núcleo antes.**
## Diretório `plugins/`
A pasta `pitiupi/plugins/` contém os JARs carregados em runtime. Apenas arquivos `.jar` são lidos. Ver [pitiupi/plugins/README.md](../../pitiupi/plugins/README.md).
## Ordem recomendada de build
1. `pitiupi` (núcleo)
2. Plugins em qualquer ordem
3. Symlink ou cópia para `pitiupi/plugins/`
## Gate automatizado (docentes)
Quem mantém o meta-workspace Cursor pode usar o script de gate que executa `ant jar` nos três módulos Ant e `make` no mpChat (requer Ant/Make no PATH). Detalhes em [15_testes_e_gate.md](15_testes_e_gate.md).
Catálogo: [`plugins.registry.json`](../../plugins.registry.json).
+56 -16
View File
@@ -20,38 +20,78 @@ distribuídas e desenvolvimento de projetos acadêmicos.
A aplicação é dividida em três grupos principais:
- **Núcleo da aplicação**: a `MainWindow` coordena GUI, rede e plugins.
- **Sistema de plugins**: extensões em JAR carregadas de `pitiupi/plugins/`.
- **Núcleo da aplicação**: a `MainShellFrame` coordena GUI, rede e plugins.
- **Sistema de plugins**: extensões em JAR carregadas de `PITIUPI_HOME/plugins` (dev: `./scripts/pitiupi.sh link --all`).
- **Comunicação de rede**: UDP (`SocketUDP`) e TCP (`SocketTCP`, `TcpConnection`).
## Inicialização da aplicação
1. A `MainWindow` é criada após o diálogo de login (nome e porta).
2. O `SocketUDP` associa-se à porta configurada e ingressa no grupo multicast.
3. O `SocketTCP` cria um `ServerSocket` na mesma porta para conexões TCP.
4. Os mecanismos de comunicação iniciam threads de recepção.
5. O `HeartbeatManager` envia heartbeats periodicamente.
6. O painel de usuários online registra-se como listener do heartbeat.
7. O `PluginManager` carrega os JARs em `plugins/` via SPI.
1. `Main` garante o layout em `PITIUPI_HOME` e abre o `LoginDialog` (nome e porta, PT-BR, ~30% da área útil do monitor, centralizado).
2. Após confirmar o login, a `MainShellFrame` é exibida (1024×768, centralizada).
3. O `SocketUDP` associa-se à porta configurada e ingressa no grupo multicast.
4. O `SocketTCP` cria um `ServerSocket` na mesma porta para conexões TCP.
5. Os mecanismos de comunicação iniciam threads de recepção.
6. O `HeartbeatManager` envia heartbeats periodicamente; o `NetworkUsersPanel` lista peers via `PresenceService`.
7. O `PluginManager` carrega os JARs em `plugins/` via SPI, com `ShellPluginWorkspace` ligado às abas centrais.
Ver também: [05_udp_multicast.md](05_udp_multicast.md), [09_sistema_de_plugins.md](09_sistema_de_plugins.md).
### Teste manual T-LOGIN-01 (login centralizado)
1. Compilar e executar: `./scripts/pitiupi.sh run --all` na raiz do repositório.
2. O `LoginDialog` deve aparecer **no centro** do monitor principal (WSL/KDE), não no canto superior esquerdo.
3. Após entrar, a `MainShellFrame` (1024×768) também deve abrir centralizada.
A posição exata depende do gerenciador de janelas; o núcleo recentra após exibir a janela.
### Atualizar plugin Chat (Onda E)
O JAR do módulo é `plugins/chat/dist/pitiupi.chat.jar` (catálogo `plugins.registry.json`). Não use `dist/chat.jar`.
```bash
cd plugins/chat && ant clean jar
./scripts/pitiupi.sh link --all
```
Isso recria o symlink `~/pitiupi/plugins/chat.jar` → o JAR buildado. O comando `link` lista o destino real de cada `.jar`.
# Interface gráfica
A interface gráfica da aplicação é baseada em Swing e é centralizada na
classe `MainWindow`.
A interface gráfica é Swing, organizada em shell (`pitiupi.presentation.shell`):
Durante a inicialização, cada plugin recebe `ConnectionManager` e `GuiManager`
no método `createPlugin()`.
| Região | Componente |
|--------|------------|
| Centro | `TabWorkspacePanel` — aba **Plugins** (galeria; abre plugin sob demanda), abas de plugin **fecháveis** (×), aba **Configurações** |
| Leste | `NetworkUsersPanel` — “Usuários nesta rede”, badges de convite, peer actions |
| Sul | Barra de status (porta e nome local) |
| Menu | `ShellMenuBar` — apenas **Ajuda → Sobre** (sair pelo X da janela) |
A extensão usual é registrar menus por categoria (`MenuCategory`). Ver
[12_menus_unicast_multicast.md](12_menus_unicast_multicast.md).
Plugins expõem `getName()` (técnico), `getIdentifier()` (SPI) e `getDisplayName()` (texto na galeria e nas abas).
A aba **Configurações** mostra em cima **Sua conexão** (nome, porta, IP local, ID da instância, contagem de peers; campos selecionáveis para copiar manualmente) e embaixo a tabela de JARs instalados (altura reduzida).
Durante a inicialização, cada plugin recebe `ConnectionManager` e `PluginWorkspace`
no método `createPlugin()`. Menus multicast na barra superior não são mais usados;
ações para todos os peers migram para **peer actions** (contexto na lista lateral).
Ao iniciar, só as abas **Plugins** e **Configurações** ficam visíveis. Cada plugin registra um painel com `bindShellWorkspaceContent`; a aba abre ao clicar na galeria ou via peer action. Referência: **Conversa na rede** (`ChatPanel`) e **Compartilhar tela** (`ScreenCastPanel`).
O **chat** usa campo de mensagem compacto (~2 linhas, quebra de linha; barra de rolagem vertical só se o texto não couber). O histórico ocupa a maior parte da altura da aba (divisor proporcional ao abrir a janela).
Canal TCP privado do chat fica no mesmo `ChatPanel` (histórico separado por conversa: sala geral, peer por IP, privado com toggle). A lista lateral usa `PeerActivityInbox` (bolinha vermelha e contagem; no menu, ● na ação correspondente).
Ao fechar a aba superior de **Compartilhar tela** (×), o núcleo chama `Plugin.onShellTabClosed()` — o plugin interrompe captura e envio (toggle desligado). Reabrir pela galeria deve mostrar compartilhamento inativo.
**TCP (transporte)** envia uma mensagem serializada pelo núcleo (`sendTcp`), na porta do login. **TCP privado** (toggle) abre conexão dedicada ao plugin entre dois peers; com o toggle ativo, o combo de transporte fica desabilitado e o envio usa esse canal. Na UI só se informa o **IP** do peer: UDP/TCP unicast do Pitiupi usa sempre a **mesma porta** que você escolheu no login (convenção de sala: todos com a mesma porta, ex. 5000 e 5001 em testes no mesmo PC).
Textos da UI (destino, combo de forma de envio e linha **“Como esta mensagem vai”**) usam linguagem simples e o termo técnico entre parênteses (multicast UDP, UDP unicast, TCP). Na sala, o transporte não é só multicast: o combo pode escolher cópias unicast ou TCP para cada pessoa, conforme o plugin.
Ver [12_menus_unicast_multicast.md](12_menus_unicast_multicast.md).
## Diagrama de comunicação
```
+------------------+
| MainWindow |
| MainShellFrame |
+--------+---------+
|
+--------------------+--------------------+
+24 -5
View File
@@ -10,14 +10,17 @@ Métodos obrigatórios:
| Método | Função |
| --- | --- |
| `getName()`, `getAuthor()`, `getVersion()`, `getIdentifier()` | Identificação (o `identifier` distingue plugins em conexões TCP dedicadas) |
| `createPlugin(ConnectionManager, GuiManager)` | Inicialização: menus, janelas, uso da rede |
| `getDisplayName()` | Texto na galeria e título de aba (padrão: `getName()`) |
| `createPlugin(ConnectionManager, PluginWorkspace)` | Inicialização na shell: painel na aba, peer actions, rede |
| `createPlugin(ConnectionManager, GuiManager)` | Legado — adapter na carga; não usar em plugins novos |
| `getMessages()` | Lista de classes `Message` que o plugin desserializa |
| `receiveMessage(Message)` | Processamento após o `PluginManager` identificar o tipo |
Métodos opcionais (TCP avançado):
Métodos opcionais (ciclo de vida e TCP avançado):
| Método | Função |
| --- | --- |
| `onShellTabClosed()` | Usuário fechou a aba do plugin no topo; liberar timers, captura, envio contínuo |
| `receiveAllTypes()` | Receber todas as mensagens públicas |
| `receivePrivateConnection(TcpConnection)` | Aceitar conexão TCP direcionada ao plugin |
| `receiveBytes(TcpConnection, byte[])` | Ler payload bruto na conexão privada |
@@ -50,11 +53,27 @@ e colocados no diretório plugins da aplicação.
### Carregamento de plugins
O `PluginManager.loadPlugins()` (chamado pela `MainWindow`):
O `PluginManager.loadPlugins()` (chamado pela `MainShellFrame`):
1. Lista arquivos `.jar` em `pitiupi/plugins/` (diretório de trabalho = pasta do núcleo).
1. Lista arquivos `.jar` em `PITIUPI_HOME/plugins` (ver [00_quickstart.md](00_quickstart.md); symlinks de dev via `./scripts/pitiupi.sh link`).
2. Para cada JAR, cria um `URLClassLoader` e usa `ServiceLoader.load(Plugin.class, classLoader)`.
3. Chama `createPlugin(connectionManager, guiManager)` em cada instância.
3. Chama `createPlugin(connectionManager, pluginWorkspace)` em cada instância (`ShellPluginWorkspace`).
4. Na recepção UDP/TCP, tenta desserializar com `PluginObjectInputStream` e despacha para plugins que declararam o tipo em `getMessages()`.
Ao fechar uma aba dinâmica de plugin, `TabWorkspacePanel` notifica `PluginManager.notifyShellTabClosed(pluginId)` **antes** de remover o conteúdo, para o plugin encerrar trabalho em segundo plano.
Implementação: `pitiupi/src/pitiupi/control/plugins/PluginManager.java`.
## Shell e abas (PluginWorkspace)
Na `MainShellFrame`, `createPlugin(ConnectionManager, PluginWorkspace)` registra o painel com `bindShellWorkspaceContent(JPanel)` **sem** abrir aba no boot. A galeria **Plugins** e as peer actions abrem a aba sob demanda.
## Peer actions na lista lateral
`PeerActionBroker.getAllActionsFor(target)` agrupa ações de **todos** os plugins (submenu por `getDisplayName()`). Destinos: `SINGLE_PEER` (um usuário) ou `ALL_PEERS` (linha **Todos**).
## Envio didático (núcleo)
`PluginRoutingPanel` (núcleo) padroniza destino, forma de envio e dica embaixo para chat, screencast e futuros plugins.
`MessageDispatcher` envia com `TransportMode` e `SendTarget`. `PluginTransportCatalog` define quais transportes cada plugin mostra na UI (sala geral vs um IP). Os combos usam textos didáticos (`describeForUi`) com o termo técnico entre parênteses (multicast UDP, UDP unicast, TCP). Na sala geral o campo IP fica desativado; um resumo **“Como esta mensagem vai”** (chat) deixa explícito o transporte escolhido — na sala pode ser multicast ou cópias unicast/TCP para cada pessoa, conforme o plugin. Para um peer use o IP manualmente ou a peer action na lista lateral.
+3 -3
View File
@@ -1,10 +1,10 @@
# Tutorial — criar um plugin
Este guia complementa [09_sistema_de_plugins.md](09_sistema_de_plugins.md). Use `pitiupi.chat` como modelo.
Este guia complementa [09_sistema_de_plugins.md](09_sistema_de_plugins.md). Use `plugins/chat` como modelo.
## 1. Novo projeto
- Copie a pasta `pitiupi.chat` para `pitiupi.meuPlugin` (nome à escolha).
- Copie a pasta `plugins/chat` para `plugins/meuPlugin` (nome à escolha).
- Ajuste `project.properties` / `build.xml` com o nome do JAR de saída.
- Mantenha `javac.classpath` apontando para `../pitiupi/dist/pitiupi.jar`.
@@ -98,7 +98,7 @@ Duas instâncias, mesma rede, portas distintas se no mesmo host. Ver [00_quickst
## TCP dedicado (avançado)
Se o plugin precisa de canal TCP com handshake por `getIdentifier()`, estude `pitiupi.mpChat` e os métodos opcionais em `Plugin` (`receivePrivateConnection`, `receiveBytes`). Ver [11_plugins_referencia.md](11_plugins_referencia.md).
Se o plugin precisa de canal TCP com handshake por `getIdentifier()`, estude `plugins/chat` (`receivePrivateConnection`, `receiveBytes`). Use `MessageDispatcher` para envios didáticos. Ver [11_plugins_referencia.md](11_plugins_referencia.md).
## Erros frequentes
+20 -49
View File
@@ -1,60 +1,31 @@
# Plugins de referência
Três exemplos no repositório para comparar estilos de integração. Todos devem ser empacotados em `pitiupi/plugins/`.
Dois módulos buildáveis no catálogo; o chat unifica o antigo mpChat (multicast, unicast, TCP e canal TCP privado).
## Comparativo
| | pitiupi.chat | pitiupi.screenCast | pitiupi.mpChat |
| --- | --- | --- | --- |
| Build | Ant | Ant | Make |
| id (`plugins.registry.json`) | `chat` | `screencast` | `mpchat` |
| Classe | `ChatPlugin` | `ScreenCastPlugin` | `MultiProtocolChat` |
| Categoria menu | `Social` | `Streaming` | `Social` (multicast + unicast) |
| Mensagem | `ChatMessage` | `ScreenCastMessage` | `MpChatMessage` |
| Transporte principal | UDP (via `ConnectionManager`) | UDP / payloads maiores | UDP público + **TCP privado** |
| TCP avançado | Não | Depende da versão do módulo | `receivePrivateConnection`, `receiveBytes` |
| | plugins/chat | plugins/screencast |
| --- | --- | --- |
| Build | Ant | Ant |
| id | `chat` | `screencast` |
| Classe | `ChatPlugin` | `ScreenCastPlugin` |
| Mensagem | `ChatMessage`, `LegacyMpChatMessage` | `ScreenCastMessage` |
| UI | `ChatPanel` (destino + transporte) | `ScreenCastPanel` (destino + transporte) |
| TCP privado | Toggle no `ChatPanel` + hooks `receiveBytes` (histórico `private:<IP>`) | — |
## pitiupi.chat
## plugins/chat
- **Referência canônica** alinhada ao contrato atual `Plugin` + `ConnectionManager` / `GuiManager`.
- `createPlugin` registra `ChatMenu` em `MenuCategory.Social`.
- `getMessages()` retorna `ChatMessage.class`; `receiveMessage` atualiza `ChatWindow`.
- Sala geral ou um peer (lista + IP).
- Transportes: multicast UDP, unicast UDP, TCP via `MessageDispatcher`.
- Peer actions: abrir sala geral; conversar com peer; canal TCP privado.
- Caminho: `plugins/chat/src/pitiupi/chat/plugin/ChatPlugin.java`.
Caminhos: `pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java`.
## plugins/screencast
## pitiupi.screenCast
- Compartilhamento contínuo com destino geral (multicast recomendado) ou um peer (unicast/TCP).
- Peer actions: compartilhar na rede; compartilhar com este peer.
- Caminho: `plugins/screencast/src/pitiupi/screenCast/plugin/ScreenCastPlugin.java`.
- Demonstra compartilhamento de tela / imagens (`ScreenCastWindow`, `ScreenCastMessage`).
- Útil para discutir **tamanho de datagramas**, compressão (`ImageTransformation`) e limites UDP.
## Exercício Ping
Caminhos: `pitiupi.screenCast/src/pitiupi/screenCast/`. Alinhado ao contrato `Plugin` + `ConnectionManager` / `GuiManager` (como `ChatPlugin`).
## pitiupi.mpChat
- Chat **público** (multicast / unicast UDP) e **privado** (TCP).
- `createPlugin(ConnectionManager, GuiManager)` como nos demais plugins; usa `ConnectionManager.connectPluginTcp` para abrir canal privado.
- Sobrescreve hooks TCP do `Plugin` (`receivePrivateConnection`, `receiveBytes`, `onSocketClosed`).
Caminhos: `pitiupi.mpChat/src/plugin/MultiProtocolChat.java`.
## Fluxo UDP (todos os plugins)
```mermaid
sequenceDiagram
participant App as MainWindow
participant UDP as SocketUDP
participant HB as HeartbeatManager
participant PM as PluginManager
participant Peer as OutroPeer
App->>UDP: join multicast
UDP->>HB: HeartbeatMessage
Peer->>UDP: Message plugin
UDP->>PM: handleMessage bytes
PM->>PM: deserialize + dispatch
```
Heartbeat não passa pelos plugins — ver [08_heartbeat_e_presenca.md](08_heartbeat_e_presenca.md).
## Próximo passo
Criar plugin próprio: [10_tutorial_plugin.md](10_tutorial_plugin.md).
Material em [17_tutorial_ping_aula.md](17_tutorial_ping_aula.md) e pasta `plugins/ping/` (sem JAR no repositório).
@@ -1,35 +1,34 @@
# Menus — unicast e multicast
# Menus, peer actions e transportes
## MenuCategory
## Interface atual (shell v1)
Enum em `pitiupi.models.Menus.MenuCategory`:
Plugins de referência **não** dependem da barra de menus superior para o fluxo principal:
| Valor | Uso sugerido |
| --- | --- |
| `Jogos` | Plugins de jogos entre peers |
| `Social` | Chat, presença, mensagens sociais |
| `Streaming` | Screen cast, mídia |
- **Galeria** na aba **Plugins** abre cada extensão em aba própria (fechável com ×).
- **Peer actions** na lista **Usuários nesta rede** (clique em um peer ou em **Todos**) agrupam ações de todos os plugins instalados.
- Dentro da aba do plugin, **`PluginRoutingPanel`** padroniza destino (sala geral vs IP), forma de envio (multicast UDP, UDP unicast, TCP) e texto de ajuda.
## Registrar menu (padrão atual)
Ver [04_inicializacao_e_gui.md](04_inicializacao_e_gui.md) e [09_sistema_de_plugins.md](09_sistema_de_plugins.md).
Via `GuiManager.createMenu(MenuCategory category, Menu menu)` — ver `ChatPlugin`:
## MenuCategory (legado)
```java
guiManager.createMenu(MenuCategory.Social, new ChatMenu(chatWindow));
```
Enum em `pitiupi.models.Menus.MenuCategory` (`Jogos`, `Social`, `Streaming`) ainda aparece no **catálogo** (`menuCategory` em `plugins.registry.json`) e em plugins antigos que chamam `GuiManager.createMenu(...)`.
A hierarquia de menus unicast/multicast do núcleo (`UnicastMenu`, `MulticastMenu`, etc.) permite ações por peer ou broadcast; plugins de referência encapsulam isso em classes `*Menu` próprias.
Novos plugins devem preferir `PluginWorkspace` + peer actions. O menu da shell expõe apenas **Ajuda → Sobre**.
## Unicast vs multicast na aplicação
| Modo | API típica | Semântica |
| --- | --- | --- |
| Multicast | `ConnectionManager` → `SocketUDP.sendMulticast` | Todos no grupo na porta configurada |
| Multicast | `MessageDispatcher` / `SocketUDP.sendMulticast` | Todos no grupo na porta configurada |
| Unicast UDP | envio para IP de um peer | Um destinatário, sem estabelecer TCP |
| TCP | `ConnectionManager` / `SocketTCP` | Canal persistente, framing 4+N bytes |
| TCP | `ConnectionManager` / `SocketTCP` | Canal com framing 4+N bytes |
Detalhes de rede: [05_udp_multicast.md](05_udp_multicast.md), [06_tcp_conexoes.md](06_tcp_conexoes.md).
## mpChat
## Referência de código
`MulticastMpChatMenu` e `UnicastMpChatMenu` mostram como expor as duas modalidades no mesmo plugin — [11_plugins_referencia.md](11_plugins_referencia.md).
- Chat e screencast: peer actions em `ChatPlugin` e `ScreenCastPlugin`.
- Envio unificado: `pitiupi.application.messaging.MessageDispatcher` e `TransportMode`.
O antigo plugin **mpChat** foi unificado no módulo `plugins/chat` (mensagens `LegacyMpChatMessage` para compatibilidade TCP privado). Ver [11_plugins_referencia.md](11_plugins_referencia.md) e decisão D19 no [decision-register.md](../decision-register.md).
+9 -6
View File
@@ -1,5 +1,7 @@
# Guia para desenvolvedor e agente
Esta documentação descreve **apenas** a ferramenta Pitiupi neste repositório: build, rede, plugins e convenções de código. Quem clona o projeto não precisa de pastas ou ferramentas de meta-desenvolvimento externas; mantenha referências técnicas e tutoriais limitados ao que está em `docs/` e no código do próprio repo.
## Leitura mínima antes de mudar código
1. [00_quickstart.md](00_quickstart.md) — build e execução
@@ -19,16 +21,17 @@
## Gate de build
Compilar núcleo e os três plugins de referência:
Compilar núcleo e os dois plugins do catálogo:
```bash
cd pitiupi && ant jar
cd ../pitiupi.chat && ant jar
cd ../pitiupi.screenCast && ant jar
cd ../pitiupi.mpChat && make
cd pitiupi && ant jar && ant test
cd plugins/chat && ant jar
cd plugins/screencast && ant jar
```
Requer JDK, Ant e Make no PATH. Teste manual em rede: [15_testes_e_gate.md](15_testes_e_gate.md).
Ou na raiz do clone: `./scripts/pitiupi.sh build --all`.
Requer JDK e Ant no PATH. Teste manual em rede: [15_testes_e_gate.md](15_testes_e_gate.md).
## Convenções
@@ -4,12 +4,13 @@
| Comportamento | Pacote / classe |
| --- | --- |
| Login, porta, nome | `pitiupi.GUI.Login` |
| Orquestração GUI + plugins | `pitiupi.GUI.MainWindow` |
| Barra de menus base | `pitiupi.GUI.MenuBar` |
| Usuários online | `pitiupi.GUI.OnlineUsersPanel`, `HeartbeatManager` |
| Login, porta, nome | `pitiupi.presentation.shell.LoginDialog` |
| Shell principal (abas, galeria) | `pitiupi.presentation.shell.MainShellFrame`, `TabWorkspacePanel` |
| Menu Ajuda | `pitiupi.presentation.shell.ShellMenuBar` |
| Usuários online, peer actions | `pitiupi.presentation.shell.NetworkUsersPanel`, `PeerActionBroker` |
| Facade rede para plugins | `pitiupi.control.ConnectionManager` |
| Registro de menus | `pitiupi.control.GuiManager` |
| Workspace na aba (SPI) | `pitiupi.api.plugin.PluginWorkspace`, `ShellPluginWorkspace` |
| Menus legados (adapter) | `pitiupi.control.GuiManager` — deprecado; preferir peer actions |
| UDP | `pitiupi.net.udp.SocketUDP` |
| TCP servidor e mapa de conexões | `pitiupi.net.tcp.SocketTCP`, `TcpConnectionManager` |
| Conexão TCP por peer | `pitiupi.net.tcp.TcpConnection` |
@@ -24,7 +25,7 @@
```
pitiupi (núcleo)
↑ classpath
pitiupi.chat | pitiupi.screenCast | pitiupi.mpChat
plugins/chat | plugins/screencast
```
Plugins **não** devem ser dependência do núcleo.
+35 -17
View File
@@ -1,15 +1,18 @@
# Testes e gate
## Estado atual
## Gate automatizado (núcleo)
Não há suíte JUnit integrada ao repositório. A validação principal é:
O módulo `pitiupi/` inclui testes JUnit:
1. **Build** de todos os módulos.
2. **Teste manual** com duas instâncias na rede.
```bash
cd pitiupi && ant test
```
## Gate de build (recomendado)
Falha se `java`, `javac` ou Ant estiverem ausentes.
Na raiz do clone (todos os módulos do catálogo):
## Gate de build (produto)
Na raiz do clone:
```bash
./scripts/pitiupi.sh build --all
@@ -19,26 +22,41 @@ Equivalente manual:
```bash
cd pitiupi && ant jar
cd ../pitiupi.chat && ant jar
cd ../pitiupi.screenCast && ant jar
cd ../pitiupi.mpChat && make
cd plugins/chat && ant jar
cd plugins/screencast && ant jar
```
Falha se `java`, **`javac`**, Ant, Make ou `python3` estiverem ausentes (instale `openjdk-*-jdk`, não só JRE).
Depois, para runtime local:
## Checklist manual (rede)
```bash
./scripts/pitiupi.sh link --all
```
- [ ] Duas instâncias com portas distintas (mesmo host) ou dois hosts na mesma LAN
- [ ] Nomes visíveis no painel de usuários em até ~15 s
- [ ] Plugin de referência troca mensagens entre os dois
- [ ] Encerrar uma instância remove o peer da lista após timeout de heartbeat
## Checklist manual — uma máquina (5000 / 5001)
- [ ] Duas instâncias com portas distintas; nomes diferentes
- [ ] Peers visíveis na lista em até ~15 s
- [ ] Chat: sala geral e conversa por IP; tags de transporte coloridas no histórico
- [ ] ScreenCast: abrir aba, destino sala ou peer; fechar aba com × interrompe compartilhamento
- [ ] Compose do chat sem barra de rolagem vazio em janela ~1024×768
- [ ] Encerrar uma instância remove o peer após timeout de heartbeat
## Checklist manual — dois PCs (mesma Wi‑Fi)
Mesma **porta** em ambos (ex. 5000), **mesmos JARs** em `~/pitiupi/plugins` em cada máquina:
- [ ] Presença e linha **Todos**
- [ ] Troca de mensagens no chat (multicast e, se possível, unicast/TCP)
- [ ] Compartilhamento de tela entre os dois (ambiente com captura de tela funcional — no WSL a captura nativa pode falhar)
- [ ] Plugin Ping do aluno (tutorial [17_tutorial_ping_aula.md](17_tutorial_ping_aula.md)) medindo RTT — recomendado antes da entrega final
## Checklist plugin de aluno
- [ ] JAR em `plugins/` + SPI correto
- [ ] JAR em `PITIUPI_HOME/plugins` + SPI correto
- [ ] README do módulo com build e formato das mensagens
- [ ] UI na aba (`PluginWorkspace`), sem `JFrame` principal
- [ ] Demonstração mínima professor ↔ aluno ou aluno ↔ aluno
## Melhorias futuras
Ver [engineering_backlog.md](engineering_backlog.md) (testes automatizados, CI).
Ver [engineering_backlog.md](engineering_backlog.md) (CI contínuo, mais testes de rede sem sockets reais).
+134
View File
@@ -0,0 +1,134 @@
# Tutorial de aula — plugin Ping
Material para o aluno implementar um plugin **Ping/Pong** com medição de RTT (round-trip time). A solução em Java **não** entra no repositório oficial; apenas este tutorial e a pasta [`plugins/ping/`](../../plugins/ping/) (README + `.gitignore`).
Índice geral: [README.md](README.md).
## Objetivos
- Estender `Plugin` e registrar SPI.
- Mensagens `Serializable` que estendem `Message`.
- `ConnectionManager`: multicast UDP, unicast UDP e TCP.
- UI na aba central: `JPanel` + `bindShellWorkspaceContent` (sem `JFrame`); abrir pela galeria **Plugins** ou peer actions.
- Instalar JAR em `PITIUPI_HOME/plugins` e testar com um colega.
## Pré-requisitos
- Pitiupi com login (nome + porta).
- [09_sistema_de_plugins.md](09_sistema_de_plugins.md).
- JDK, Ant; núcleo em `pitiupi/dist/pitiupi.jar`.
## Estrutura sugerida (projeto do aluno)
```
plugins/ping/ # ou projeto fora do repo oficial
├── build.xml
├── nbproject/
├── src/
│ ├── META-INF/services/pitiupi.models.Plugin
│ └── br/ufsj/redes/ping/
│ ├── PingPlugin.java
│ ├── PingMessage.java
│ ├── PongMessage.java
│ └── PingPanel.java
└── dist/pitiupi.ping.jar
```
Modelo Ant: copiar [`plugins/chat`](../chat) e ajustar classpath para `../../pitiupi/dist/pitiupi.jar`.
## Passo 1 — Projeto Ant
1. Copiar `plugins/chat`.
2. JAR de saída: `dist/pitiupi.ping.jar`.
3. Classpath de compilação: JAR do núcleo.
**Verificação:** `ant jar` sem erros.
## Passo 2 — `PingPlugin`
| Método | Exemplo |
| --- | --- |
| `getName()` | `"Ping"` |
| `getDisplayName()` | `"Ping na rede"` |
| `getIdentifier()` | `"pitiupi.ping"` (único na sala) |
Em `createPlugin(ConnectionManager cm, PluginWorkspace workspace)`:
```java
pingPanel = new PingPanel(cm);
bindShellWorkspaceContent(pingPanel);
installPeerActions(workspace.peerActions());
```
**Não** chame `openOrFocusTab` no boot — a aba abre quando o usuário clicar na galeria ou usar peer action.
Peer actions sugeridas: “Enviar ping” (peer único), “Ping para todos”.
**Verificação:** após instalar o JAR e reiniciar, só **Plugins** e **Configurações** no boot; botão na galeria abre a aba Ping.
## Passo 3 — Mensagens
`PingMessage` e `PongMessage` com `pingId` (UUID) e timestamps para RTT.
Registrar em `getMessages()`:
```java
return List.of(PingMessage.class, PongMessage.class);
```
Em `receiveMessage`: ao receber ping, responder pong; ao receber pong, calcular RTT e atualizar a UI com `SwingUtilities.invokeLater`.
## Passo 4 — `PingPanel`
Botões para multicast, unicast UDP e TCP; área de log ou label com último RTT em ms. Para um peer, use campo IP como no `ChatPanel` ou peer action na lista lateral.
## Passo 5 — Transportes
Use `pitiupi.application.messaging.MessageDispatcher` no núcleo:
```java
MessageDispatcher.send(connectionManager, pingMessage, SendTarget.broadcastAll(), TransportMode.MULTICAST_UDP);
MessageDispatcher.send(connectionManager, pingMessage, SendTarget.singlePeer(addr), TransportMode.UNICAST_UDP);
MessageDispatcher.send(connectionManager, pingMessage, SendTarget.singlePeer(addr), TransportMode.TCP);
```
| Destino | Transporte didático | Observação |
| --- | --- | --- |
| Todos | Multicast UDP | Padrão em sala |
| Todos | Unicast UDP | Loop em cada peer online (demo) |
| Um peer | Unicast UDP / TCP | IP da lista ou manual |
Não alterar o endereço multicast do núcleo (`224.0.0.3`).
## Passo 6 — SPI e instalação
`META-INF/services/pitiupi.models.Plugin`:
```
br.ufsj.redes.ping.PingPlugin
```
Copiar JAR para `~/pitiupi/plugins/` (ou instalar pela aba Configurações) e **reiniciar**.
## Critérios de sucesso
| # | Critério |
| --- | --- |
| C1 | JAR carrega sem exceção |
| C2 | Pelo menos um transporte funciona entre duas instâncias |
| C3 | RTT em ms após o pong |
| C4 | README do aluno com build e transporte usado |
## Anti-padrões
- Commitar solução no repo oficial.
- Busy-wait na EDT.
- Objetos não `Serializable`.
- Mesmo `getIdentifier()` que outro plugin.
## Referências
- [10_tutorial_plugin.md](10_tutorial_plugin.md)
- [05_udp_multicast.md](05_udp_multicast.md)
- [06_tcp_conexoes.md](06_tcp_conexoes.md)
- [04_inicializacao_e_gui.md](04_inicializacao_e_gui.md)
+3 -2
View File
@@ -9,7 +9,7 @@ Referência para **código Java**, **rede P2P** e **plugins**. Índice geral: [d
| 0 | [00_quickstart.md](00_quickstart.md) | Build, plugins, duas instâncias |
| 1 | [01_visao_disciplina_e_tp.md](01_visao_disciplina_e_tp.md) | Uso na disciplina e trabalho prático |
| 2 | [02_modulos_do_repositorio.md](02_modulos_do_repositorio.md) | Núcleo e três plugins de referência |
| 3 | [03_build_ant_netbeans.md](03_build_ant_netbeans.md) | Ant, NetBeans, Makefile mpChat |
| 3 | [03_build_ant_netbeans.md](03_build_ant_netbeans.md) | Ant e NetBeans (núcleo + plugins) |
| 4 | [04_inicializacao_e_gui.md](04_inicializacao_e_gui.md) | Boot, MainWindow, diagrama |
| 5 | [05_udp_multicast.md](05_udp_multicast.md) | SocketUDP |
| 6 | [06_tcp_conexoes.md](06_tcp_conexoes.md) | SocketTCP, TcpConnection, framing |
@@ -17,7 +17,8 @@ Referência para **código Java**, **rede P2P** e **plugins**. Índice geral: [d
| 8 | [08_heartbeat_e_presenca.md](08_heartbeat_e_presenca.md) | HeartbeatManager |
| 9 | [09_sistema_de_plugins.md](09_sistema_de_plugins.md) | Plugin, PluginManager, SPI |
| 10 | [10_tutorial_plugin.md](10_tutorial_plugin.md) | Passo a passo novo plugin |
| 11 | [11_plugins_referencia.md](11_plugins_referencia.md) | chat, screenCast, mpChat |
| 11 | [11_plugins_referencia.md](11_plugins_referencia.md) | chat e screencast |
| 17 | [17_tutorial_ping_aula.md](17_tutorial_ping_aula.md) | Exercício Ping (aula) |
| 12 | [12_menus_unicast_multicast.md](12_menus_unicast_multicast.md) | MenuCategory e ações |
| 13 | [13_guia_dev_e_agente.md](13_guia_dev_e_agente.md) | Leitura para dev/agente |
| 14 | [14_arquitetura_e_manutencao.md](14_arquitetura_e_manutencao.md) | Onde editar cada comportamento |
+3 -3
View File
@@ -2,10 +2,10 @@
| Item | Prioridade | Notas |
| --- | --- | --- |
| Completar tutorial legado em `pitiupi/docs/PluginTutorial.md` | Média | Substituído por [10_tutorial_plugin.md](10_tutorial_plugin.md) |
| Testes JUnit para desserialização e framing TCP | Média | Sem rede real |
| CI (GitHub Actions) com `ant jar` + `make` | Baixa | Requer imagem com Ant |
| CI (GitHub Actions) com `ant jar` + `ant test` | Baixa | Requer imagem com Ant/JDK |
| Captura de tela nativa no WSL | Baixa | Limitação de ambiente; validar em Windows/Linux com display |
Itens concluídos recentemente: alinhamento de `pitiupi.mpChat` a `ConnectionManager` / `GuiManager`; documentação de JDK mínimo no [README](../../README.md) e [00_quickstart.md](00_quickstart.md).
Itens concluídos recentemente: shell com abas e peer actions (D16–D18); chat unificado (D19); docs alinhadas à shell v1 (Onda G); suíte JUnit no núcleo (`ant test`); tutorial Ping em [17_tutorial_ping_aula.md](17_tutorial_ping_aula.md).
Ao fechar um item, atualizar esta tabela e o doc técnico relacionado.