feat(rede): nome, porta, saída e TTL em tempo real

A sala acompanha a interface escolhida, o TCP deixa de travar a janela e a aba de um peer continua fechável quando o IP muda. O guia do colega usa os saltos do traceroute como TTL mínimo.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Gabriel Felipe Souza SantosandCursor committed 2026-11-03 22:50:23 -03:00
1 parent baaf7582d3
commit 22540eaffb
31 files changed
+1194 -110

No files matched your search

+2 -2
View File
@@ -17,14 +17,14 @@ Convenções editoriais: [documentation/00_convencoes.md](documentation/00_conve
| Leitor | Trilha |
| --- | --- |
| **Primeiro uso** | [00_quickstart](documentation/00_quickstart.md) → [09_sistema_de_plugins](documentation/09_sistema_de_plugins.md) → [10_tutorial_plugin](documentation/10_tutorial_plugin.md) → [11_plugins_referencia](documentation/11_plugins_referencia.md) |
| **Redes (conceito + código)** | [16_fundamentacao_redes](documentation/16_fundamentacao_redes.md) → [05](documentation/05_udp_multicast.md)–[08](documentation/08_heartbeat_e_presenca.md) → [appendix_portas_e_multicast](documentation/appendix_portas_e_multicast.md) |
| **Redes (conceito + código)** | [16_fundamentacao_redes](documentation/16_fundamentacao_redes.md) → [05](documentation/05_udp_multicast.md)–[08](documentation/08_heartbeat_e_presenca.md) → [appendix_portas_e_multicast](documentation/appendix_portas_e_multicast.md) → [17_teste_com_colega](documentation/17_teste_com_colega.md) |
| **Desenvolvedor núcleo** | [13_guia_desenvolvimento](documentation/13_guia_desenvolvimento.md) → [14_arquitetura_e_manutencao](documentation/14_arquitetura_e_manutencao.md) → [04_inicializacao_e_gui](documentation/04_inicializacao_e_gui.md) |
## Manutenção rápida
| Mudança | Onde documentar |
| --- | --- |
| UDP/TCP, multicast, portas | 05, 06, appendix |
| UDP/TCP, multicast, portas | 05, 06, appendix, 17 |
| SPI / plugins | 09, 10 |
| Decisão de arquitetura | decision-register |
| Débito técnico | engineering_backlog |
+5
View File
@@ -22,5 +22,10 @@
| D22 | `PeerIpv4` para IP de peer na UI | No Windows, `InetAddress.getHostAddress()` pode devolver IPv6-mapeado e sufixo de zona (`%n`); chat e roteamento usam IPv4 pontilhado | [appendix_portas_e_multicast.md](documentation/appendix_portas_e_multicast.md) |
| D23 | Foco de atividade e badges | **Adiado na v1** — núcleo (`PeerActivityFocus` / `PeerActivityInbox`) mantido; UI sem badges; recebimento passivo em sub-abas (`addTabIfAbsent`) | [09_sistema_de_plugins.md](documentation/09_sistema_de_plugins.md) |
| D24 | Avisos de sessão (`SessionNoticeMessage`) | Início/fim de atividades (ex. `screen_cast` END ao parar share); extensível por plugin/canal | [09_sistema_de_plugins.md](documentation/09_sistema_de_plugins.md) |
| D25 | Nome novo no heartbeat já existente | A lista do colega atualiza o `User` quando o `userName` muda | [08_heartbeat_e_presenca.md](documentation/08_heartbeat_e_presenca.md) |
| D26 | Troca de porta sai da sala | Goodbye na porta antiga, lista local zerada, anúncio na porta nova | [appendix_portas_e_multicast.md](documentation/appendix_portas_e_multicast.md) |
| D27 | TTL padrão 1, ajustável de 1 a 32 | 1 permanece na sub-rede local; valor maior é opção de configuração | [appendix_portas_e_multicast.md](documentation/appendix_portas_e_multicast.md) |
| D28 | Saída Automático, Cabo ou Wi-Fi | Multicast, IP exibido e TCP de saída usam a interface escolhida | [appendix_portas_e_multicast.md](documentation/appendix_portas_e_multicast.md) |
| D29 | Connect TCP com prazo de 5 s fora da EDT | Aviso só enquanto não há socket aberto para aquele IP | [06_tcp_conexoes.md](documentation/06_tcp_conexoes.md) |
Novas decisões: adicionar linha nesta tabela e detalhar no arquivo técnico correspondente.
+3 -3
View File
@@ -67,20 +67,20 @@ A interface gráfica é Swing, organizada em shell (`pitiupi.presentation.shell`
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).
A aba **Configurações** mostra em cima **Sua conexão**: nome e porta editáveis, saída (Automático, Cabo ou Wi-Fi), TTL, IP local, interface em uso, ID da instância e contagem de peers. **Aplicar** grava a preferência e, se porta, saída ou TTL mudaram, reabre a rede na hora. IP e ID continuam somente leitura. Embaixo fica a tabela de JARs instalados.
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).
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). Cada pessoa tem uma sub-aba; o × fecha essa sub-aba mesmo com outras ao lado. Se a pessoa muda de cabo para Wi-Fi, a sub-aba já aberta passa a usar o IP novo em vez de aparecer uma segunda vez com o mesmo nome.
Canal TCP privado do chat fica no mesmo `ChatPanel` (histórico separado por conversa: sala geral, peer por IP, privado com toggle). O núcleo mantém `PeerActivityInbox` para atividade por peer; indicadores visuais completos na lista lateral ainda não fazem parte da v1 (**D23**).
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).
**TCP (transporte)** envia uma mensagem serializada pelo núcleo, na porta desta instância. A primeira conexão com um IP que ainda não tem socket aberto corre fora da thread da janela: o chat mostra “Conectando em …”, espera no máximo cerca de 5 s e, se falhar, avisa uma vez. Mensagens seguintes no mesmo socket não repetem esse aviso. **TCP privado** (toggle) abre conexão dedicada ao plugin entre dois peers, com o mesmo aviso só na abertura. Na UI só se informa o **IP** do peer: UDP/TCP unicast do Pitiupi usa sempre a **mesma porta** desta instância (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.
+2 -1
View File
@@ -24,7 +24,8 @@ Durante sua inicialização, o `SocketUDP`:
2. cria um `MulticastSocket` na **porta escolhida no login** (mesma porta TCP da sala);
3. configura os buffers de envio e recepção;
4. habilita o reuso do endereço;
5. ingressa no grupo multicast.
5. define o TTL (padrão **1**, alterável na aba Configurações) e a interface de saída;
6. ingressa no grupo multicast.
O tamanho dos buffers de comunicação é configurado para `256000` bytes.
+4
View File
@@ -10,6 +10,10 @@ múltiplas mensagens.
A arquitetura utiliza uma conexão TCP persistente por endereço de peer.
**Teoria:** `connect` sem prazo pode ficar parado até o sistema operacional desistir. **No Pitiupi:** `ConnectionFactory` usa `Socket.connect` com prazo de **5 s** (`CONNECT_TIMEOUT_MS`). O chat dispara essa abertura numa thread do núcleo (`sendTcpAsync` / `connectPluginTcpAsync`) e só mostra “Conectando em …” quando ainda não existe socket aberto para aquele IP. **Limitação:** o prazo não é configurável na tela; o timeout de leitura depois do handshake continua longo (minutos).
Ao mudar porta, saída ou TTL, o `ConnectionManager` envia goodbye, fecha as TCP locais e reabre o `ServerSocket`. Se a porta nova não abre, a sala anterior é restaurada.
O `TcpConnectionManager` mantém um mapa `InetAddress` → `TcpConnection`, permitindo reutilizar a mesma conexão para vários envios ao mesmo peer.
### SocketTCP
@@ -72,7 +72,13 @@ Lista de peers ativos
| Timeout de ausência | ~15 s | Peer some após queda ou fechamento sem goodbye |
| Goodbye | multicast ao sair | Remove peer mais rápido que só timeout |
Em **Wi‑Fi de laboratório**, heartbeat usa o mesmo multicast que o chat na sala geral — mesma porta no login, mesma sub-rede, sem isolamento AP→AP. Ver [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md).
Em **Wi‑Fi de laboratório**, heartbeat usa o mesmo multicast que o chat na sala geral — mesma porta, mesma sub-rede, sem isolamento AP→AP. Ver [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md) e [17_teste_com_colega.md](17_teste_com_colega.md).
### Nome e troca de sala
O nome vai dentro do `HeartbeatMessage` que já existe. Se o nome mudar, o receptor atualiza o peer na lista e avisa a interface; não há outra mensagem só para isso.
Trocar a porta (ou a saída, ou o TTL) envia `GoodbyeMessage` na sala atual, esvazia a lista local e anuncia de imediato depois do novo socket. Quem ficou na porta antiga deixa de ver esta instância. Quem já está na porta nova aparece no anúncio seguinte. Se o goodbye se perder, o timeout de cerca de 15 s ainda remove o peer.
```mermaid
flowchart LR
+48
View File
@@ -0,0 +1,48 @@
# Teste com um colega
**Teoria:** dois processos só se descobrem se compartilham a mesma sub-rede, a mesma porta de aplicação e um caminho em que o multicast da LAN não seja filtrado. **No Pitiupi:** a lista **Usuários nesta rede** enche com heartbeats UDP. **Limitação:** o Pitiupi não executa `ping` nem `traceroute` do sistema; esses comandos servem para separar problema de rede de problema do aplicativo.
Os dois Pitiupi precisam usar a **mesma porta** (na sala, em geral **5000**). Portas diferentes são salas diferentes: quem está em 5001 não aparece para quem ficou em 5000.
## O que conferir na aplicação
Abra a aba **Configurações**, seção **Sua conexão**:
- **IP local** e o nome da **interface** (por exemplo `eth0 · 192.168.0.15`).
- **Porta** em que esta instância escuta UDP e TCP.
- **Saída:** Automático, Cabo ou Wi-Fi. Os dois colegas precisam estar na mesma rede dessa interface.
- **TTL:** o padrão é **1**. O número de saltos do `tracert` (ou `traceroute`) até o IP do colega é o mínimo a colocar aqui. Se a linha 1 já é o IP dele, use **1**. Cada roteador no meio soma 1, até o máximo **32**. O teste na mesma sub-rede usa 1.
O nome na rede também se altera aí. O colega passa a ver o nome novo no próximo anúncio (até cerca de 5 s), sem você sair e voltar da lista.
## O que conferir no sistema
Substitua `5000` e o IP do colega pelos valores da aba Configurações.
### Windows
- IP: `ipconfig` e o IPv4 do adaptador Ethernet ou Wi-Fi.
- Porta em escuta: `netstat -ano | findstr :5000`
- Alcance: `ping` no IP do colega.
- Caminho: `tracert` no IP do colega. Conte as linhas numeradas até o IP dele: esse número é o TTL mínimo na aba Configurações.
- Porta TCP do aplicativo: no PowerShell, `Test-NetConnection -ComputerName IP -Port 5000`
### Linux
- IP: `ip -4 addr`
- Porta em escuta: `ss -lntu | grep 5000`
- Alcance: `ping -c 3 IP`
- Caminho: `traceroute IP` ou `tracepath IP`. Conte os saltos até o IP do colega: esse número é o TTL mínimo.
- Porta TCP do aplicativo: `nc -vz -w 3 IP 5000` (ou `ncat`)
## Como ler o resultado
- **O ping falha.** O problema está na rede entre os PCs: sub-rede diferente, cabo, Wi-Fi ou isolamento de clientes no roteador. O Pitiupi não contorna isso.
- **O ping funciona e a porta TCP não abre.** Firewall, porta errada ou o outro Pitiupi não está escutando. Confira a porta na aba Configurações e libere UDP e TCP nessa porta.
- **O ping com TTL 1 responde e a lista só mostra Todos.** A descoberta é multicast, e um TTL baixo não é a causa quando o `tracert` tem um salto só. Confira porta igual, a mesma saída (os dois no cabo ou os dois no Wi-Fi; `169.254` e `192.168` ao mesmo tempo não se veem), firewall de UDP e isolamento de clientes. Um lado no WSL e o outro no Windows costuma impedir o multicast: os dois peers precisam estar no mesmo tipo de ambiente.
- **O `tracert` tem mais de um salto e a lista fica vazia.** Suba o TTL em Configurações até o número de saltos (máximo 32) e aplique nos dois. Um roteador no meio só entrega o multicast se estiver disposto a encaminhar o grupo.
- **O colega está na lista e o TCP avisa que não conectou.** A tentativa de abrir o socket espera no máximo cerca de **5 s** e a janela continua utilizável. Veja firewall de TCP ou se a porta mudou no meio do caminho.
A lista espera cerca de **5 s** entre anúncios e remove quem fica cerca de **15 s** sem heartbeat. Ao trocar de porta, esta instância envia goodbye na sala antiga e passa a anunciar na porta nova.
Detalhe de portas, interface e TTL: [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md).
+2 -1
View File
@@ -8,7 +8,7 @@
| --- | --- |
| **Início** | [00_quickstart](00_quickstart.md), [02_modulos](02_modulos_do_repositorio.md), [03_build](03_build_ant_netbeans.md) |
| **Arquitetura e GUI** | [04_inicializacao_e_gui](04_inicializacao_e_gui.md), [13_guia_desenvolvimento](13_guia_desenvolvimento.md), [14_arquitetura_e_manutencao](14_arquitetura_e_manutencao.md) |
| **Rede** | [05_udp_multicast](05_udp_multicast.md), [06_tcp_conexoes](06_tcp_conexoes.md), [07_mensagens](07_mensagens_e_serializacao.md), [08_heartbeat](08_heartbeat_e_presenca.md), [16_fundamentacao_redes](16_fundamentacao_redes.md), [appendix_portas_e_multicast](appendix_portas_e_multicast.md) |
| **Rede** | [05_udp_multicast](05_udp_multicast.md), [06_tcp_conexoes](06_tcp_conexoes.md), [07_mensagens](07_mensagens_e_serializacao.md), [08_heartbeat](08_heartbeat_e_presenca.md), [16_fundamentacao_redes](16_fundamentacao_redes.md), [17_teste_com_colega](17_teste_com_colega.md), [appendix_portas_e_multicast](appendix_portas_e_multicast.md) |
| **Plugins** | [09_sistema_de_plugins](09_sistema_de_plugins.md), [10_tutorial_plugin](10_tutorial_plugin.md), [11_plugins_referencia](11_plugins_referencia.md), [12_transporte_e_peer_actions](12_menus_unicast_multicast.md) |
| **Qualidade** | [15_testes_e_gate](15_testes_e_gate.md), [engineering_backlog](engineering_backlog.md) |
@@ -23,4 +23,5 @@
| 9–12 | 09–12 | Plugins, tutorial genérico, transporte na UI |
| 13–15 | 13–15 | Dev, manutenção, testes |
| 16 | [16_fundamentacao_redes.md](16_fundamentacao_redes.md) | Fundamentação redes ↔ código |
| 17 | [17_teste_com_colega.md](17_teste_com_colega.md) | IP, porta, ping e lista entre dois PCs |
| — | [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md) | Portas, Wi‑Fi, WSL |
@@ -2,9 +2,11 @@
## Configuração
- **Nome** e **porta** definidos no diálogo de login (`Login`).
- A mesma porta é usada para UDP (multicast socket) e TCP (`ServerSocket`).
- Preferências persistidas localmente (`java.util.prefs`).
- **Nome** e **porta** começam no diálogo de login e podem ser alterados na aba **Configurações** sem reiniciar. A alteração vale na hora.
- A mesma porta é usada para UDP (multicast socket) e TCP (`ServerSocket`). Trocar a porta sai da sala antiga (goodbye) e passa a procurar colegas na porta nova.
- **Saída:** Automático (cabo antes de Wi-Fi), só Cabo ou só Wi-Fi. O multicast e o IP exibido seguem essa escolha. O TCP de saída também sai pelo IPv4 dessa interface.
- **TTL** do multicast: padrão **1** (só a rede local). Na Configurações, de 1 a 32.
- Preferências persistidas localmente (`java.util.prefs`): nome, porta, TTL e saída. `config.properties` não guarda esses campos.
## Multicast
@@ -31,7 +33,9 @@ Executar o Pitiupi no WSL e peers no Windows (ou vice-versa) pode falhar em mult
## Escolha de interface (multicast)
O núcleo associa o socket multicast à interface de rede preferida: **cabo (Ethernet) antes de Wi‑Fi**; em cabo com link-local APIPA, prioriza IPv4 **`169.254.*`**. Isso não substitui a exigência de **mesma sub-rede** entre os dois PCs — `169.254.x` e `192.168.x` ao mesmo tempo em hosts diferentes não compartilham heartbeat.
No modo **Automático**, o núcleo associa o socket multicast à interface preferida: **cabo (Ethernet) antes de Wi‑Fi**; em cabo com link-local APIPA, prioriza IPv4 **`169.254.*`**. **Cabo** ou **Wi-Fi** na aba Configurações restringe a essa família (nome da interface ou rótulo `Ethernet` / `Wi-Fi`). Isso não substitui a exigência de **mesma sub-rede** entre os dois PCs — `169.254.x` e `192.168.x` ao mesmo tempo em hosts diferentes não compartilham heartbeat.
Roteiro para achar o próprio IP, a porta e o motivo de a lista ficar vazia: [17_teste_com_colega.md](17_teste_com_colega.md).
## IP do peer na UI (Windows)
@@ -51,4 +55,4 @@ Ao abrir conversa pela lista de presença, o campo de destino usa **`PeerIpv4`**
| --- | --- |
| Lista só com **Todos**, sem peers | Porta igual? Mesma sub-rede? Firewall UDP? AP isolation? WSL num dos PCs? |
| Plugin não recebe | Desserialização / SPI / JAR em `PITIUPI_HOME/plugins` |
| TCP falha | Peer visível na lista? IP correto? |
| TCP falha | Peer visível na lista? IP correto? A tentativa avisa em cerca de 5 s e não trava a janela |