Linux, WSL e Windows usam o mesmo run --all, e plugins, cache e logs ficam em .pitiupi na raiz do projeto. Co-authored-by: Cursor <cursoragent@cursor.com>
8.0 KiB
Visão geral
O Pitiupi é uma plataforma P2P baseada em uma arquitetura de plugins,
desenvolvida para permitir a criação de aplicações distribuídas sobre uma
infraestrutura comum de comunicação em rede.
A aplicação fornece mecanismos de descoberta de usuários, comunicação entre peers, troca de mensagens serializadas e integração de extensões por meio de plugins. A comunicação de rede utiliza dois protocolos de transporte: UDP, empregado principalmente na descoberta e comunicação multicast entre as instâncias, e TCP, utilizado para comunicação direta e persistente entre peers.
O projeto serve como base para experimentação de aplicações distribuídas e desenvolvimento de extensões via plugins.
Índice: README.md.
Arquitetura geral
A aplicação é dividida em três grupos principais:
- Núcleo da aplicação: a
MainShellFramecoordena 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
Maingarante o layout emPITIUPI_HOMEe abre oLoginDialog(nome e porta, PT-BR, ~30% da área útil do monitor, centralizado).- Após confirmar o login, a
MainShellFrameé exibida (1024×768, centralizada). - O
SocketUDPassocia-se à porta configurada e ingressa no grupo multicast. - O
SocketTCPcria umServerSocketna mesma porta para conexões TCP. - Os mecanismos de comunicação iniciam threads de recepção.
- O
HeartbeatManagerenvia heartbeats periodicamente; oNetworkUsersPanellista peers viaPresenceService. - O
PluginManagercarrega os JARs emplugins/via SPI, comShellPluginWorkspaceligado às abas centrais.
Ver também: 05_udp_multicast.md, 09_sistema_de_plugins.md.
Teste manual T-LOGIN-01 (login centralizado)
- Compilar e executar:
./scripts/pitiupi.sh run --allna raiz do repositório. - O
LoginDialogdeve aparecer no centro do monitor principal (WSL/KDE), não no canto superior esquerdo. - 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.
cd plugins/chat && ant clean jar
./scripts/pitiupi.sh link --all
Isso recria o symlink .pitiupi/plugins/chat.jar → o JAR buildado, na raiz do clone. O comando link lista o destino real de cada .jar.
Interface gráfica
A interface gráfica é Swing, organizada em shell (pitiupi.presentation.shell):
| 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”, peer actions (badges na lista: D23, adiados — ver decision-register.md) |
| Sul | Barra de status (porta e nome local) |
| Menu | ShellMenuBar — apenas Ajuda → Sobre (sair pelo X da janela) |
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 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). 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, 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.
Ver 12_menus_unicast_multicast.md.
Boot (sequência)
sequenceDiagram
participant Main
participant Home as PitiupiHome
participant Login as LoginDialog
participant Shell as MainShellFrame
participant CM as ConnectionManager
participant PM as PluginManager
Main->>Home: ensureLayout()
Main->>Login: showLogin()
Login-->>Main: nome + porta
Main->>Shell: new MainShellFrame(nome, porta)
Shell->>CM: iniciar UDP/TCP/heartbeat
Shell->>PM: carregar JARs SPI
PM-->>Shell: createPlugin(cm, workspace)
Camadas de comunicação
flowchart TB
subgraph ui [presentation.shell]
Shell[MainShellFrame]
Users[NetworkUsersPanel]
end
subgraph app [application + control]
CM[ConnectionManager]
HB[HeartbeatManager]
Disp[MessageDispatcher]
end
subgraph net [net]
UDP[SocketUDP]
TCP[SocketTCP]
end
subgraph ext [plugins]
PL[Plugin JARs]
end
Shell --> CM
Users --> CM
CM --> UDP
CM --> TCP
CM --> HB
Disp --> CM
PL --> Disp
UDP --> PL
TCP --> PL
O UDP multicast sustenta presença e mensagens broadcast/unicast; o TCP sustenta canais diretos com framing de mensagens. Detalhes em 05 e 06.
Exemplo: um envio UDP até outro peer
- Plugin chama
MessageDispatcher(ouConnectionManager) comTransportModee destino. - Mensagem serializada (
Message.toByteArray()). SocketUDPmontaDatagramPacket(multicast224.0.0.3ou unicast ao IP do peer).- Peer receptor: thread de
SocketUDP.receive()desserializa ePluginManagerentrega ao plugin que declarou o tipo emgetMessages().