From f02acaf13167ac937287e11d453f7a2fbabf8be5 Mon Sep 17 00:00:00 2001 From: Gabriel Felipe Souza Santos Date: Tue, 13 Oct 2026 21:20:20 -0300 Subject: [PATCH] =?UTF-8?q?Consolida=20documenta=C3=A7=C3=A3o=20e=20plugin?= =?UTF-8?q?s=20de=20refer=C3=AAncia=20ao=20n=C3=BAcleo=20atual.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alinha mpChat e screenCast a ConnectionManager/GuiManager, adiciona docs em docs/ e README de plugins; remove artefatos de build do índice. Co-authored-by: Cursor --- .gitignore | 4 + README.md | 59 +- docs/README.md | 35 ++ docs/decision-register.md | 14 + docs/documentation/00_quickstart.md | 63 ++ .../documentation/01_visao_disciplina_e_tp.md | 47 ++ .../02_modulos_do_repositorio.md | 34 ++ docs/documentation/03_build_ant_netbeans.md | 49 ++ docs/documentation/04_inicializacao_e_gui.md | 76 +++ docs/documentation/05_udp_multicast.md | 85 +++ docs/documentation/06_tcp_conexoes.md | 192 ++++++ .../07_mensagens_e_serializacao.md | 18 + docs/documentation/08_heartbeat_e_presenca.md | 62 ++ docs/documentation/09_sistema_de_plugins.md | 60 ++ docs/documentation/10_tutorial_plugin.md | 75 +++ docs/documentation/11_plugins_referencia.md | 59 ++ .../12_menus_unicast_multicast.md | 35 ++ docs/documentation/13_guia_dev_e_agente.md | 42 ++ .../14_arquitetura_e_manutencao.md | 42 ++ docs/documentation/15_testes_e_gate.md | 38 ++ docs/documentation/16_fundamentacao_redes.md | 52 ++ docs/documentation/README.md | 27 + .../appendix_portas_e_multicast.md | 38 ++ docs/documentation/engineering_backlog.md | 11 + docs/references/README.md | 18 + docs/references/bibliografia.bib | 24 + docs/references/notas/java_serializacao.md | 11 + docs/references/notas/java_spi_plugins.md | 9 + docs/references/notas/multicast_lan.md | 12 + docs/references/notas/udp_vs_tcp.md | 10 + docs/references/pdfs/.gitkeep | 0 pitiupi.chat/build/built-jar.properties | 6 - .../META-INF/services/pitiupi.plugin.Plugin | 1 - .../classes/pitiupi/chat/GUI/ChatMenu.class | Bin 922 -> 0 bytes .../pitiupi/chat/GUI/ChatWindow$1.class | Bin 944 -> 0 bytes .../classes/pitiupi/chat/GUI/ChatWindow.class | Bin 5302 -> 0 bytes .../pitiupi/chat/net/ChatMessage.class | Bin 888 -> 0 bytes .../pitiupi/chat/plugin/ChatPlugin.class | Bin 2058 -> 0 bytes pitiupi.mpChat/src/GUI/PrivateChatWindow.java | 10 +- pitiupi.mpChat/src/GUI/PublicChatWindow.java | 15 +- .../src/control/ChatController.java | 73 --- .../src/control/PrivateChatController.java | 22 +- .../src/plugin/MultiProtocolChat.java | 26 +- pitiupi.screenCast/build/built-jar.properties | 6 - .../META-INF/services/pitiupi.plugin.Plugin | 1 - .../screenCast/GUI/ScreenCastMenu.class | Bin 1644 -> 0 bytes .../screenCast/GUI/ScreenCastWindow.class | Bin 5897 -> 0 bytes .../screenCast/control/AlarmClock.class | Bin 629 -> 0 bytes .../control/ImageTransformation.class | Bin 2970 -> 0 bytes .../screenCast/control/ScreenShot.class | Bin 954 -> 0 bytes .../screenCast/net/ScreenCastMessage.class | Bin 925 -> 0 bytes .../screenCast/plugin/ScreenCastPlugin.class | Bin 2459 -> 0 bytes pitiupi.screenCast/dist/README.TXT | 32 - .../screenCast/GUI/ScreenCastMenu.java | 47 +- .../screenCast/GUI/ScreenCastWindow.java | 2 - .../screenCast/net/ScreenCastMessage.java | 4 +- .../screenCast/plugin/ScreenCastPlugin.java | 39 +- pitiupi/docs/Documentation.md | 548 +----------------- pitiupi/docs/PluginTutorial.md | 5 +- pitiupi/docs/README.md | 10 + pitiupi/plugins/README.md | 18 + 61 files changed, 1408 insertions(+), 758 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/decision-register.md create mode 100644 docs/documentation/00_quickstart.md create mode 100644 docs/documentation/01_visao_disciplina_e_tp.md create mode 100644 docs/documentation/02_modulos_do_repositorio.md create mode 100644 docs/documentation/03_build_ant_netbeans.md create mode 100644 docs/documentation/04_inicializacao_e_gui.md create mode 100644 docs/documentation/05_udp_multicast.md create mode 100644 docs/documentation/06_tcp_conexoes.md create mode 100644 docs/documentation/07_mensagens_e_serializacao.md create mode 100644 docs/documentation/08_heartbeat_e_presenca.md create mode 100644 docs/documentation/09_sistema_de_plugins.md create mode 100644 docs/documentation/10_tutorial_plugin.md create mode 100644 docs/documentation/11_plugins_referencia.md create mode 100644 docs/documentation/12_menus_unicast_multicast.md create mode 100644 docs/documentation/13_guia_dev_e_agente.md create mode 100644 docs/documentation/14_arquitetura_e_manutencao.md create mode 100644 docs/documentation/15_testes_e_gate.md create mode 100644 docs/documentation/16_fundamentacao_redes.md create mode 100644 docs/documentation/README.md create mode 100644 docs/documentation/appendix_portas_e_multicast.md create mode 100644 docs/documentation/engineering_backlog.md create mode 100644 docs/references/README.md create mode 100644 docs/references/bibliografia.bib create mode 100644 docs/references/notas/java_serializacao.md create mode 100644 docs/references/notas/java_spi_plugins.md create mode 100644 docs/references/notas/multicast_lan.md create mode 100644 docs/references/notas/udp_vs_tcp.md create mode 100644 docs/references/pdfs/.gitkeep delete mode 100644 pitiupi.chat/build/built-jar.properties delete mode 100644 pitiupi.chat/build/classes/META-INF/services/pitiupi.plugin.Plugin delete mode 100644 pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class delete mode 100644 pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class delete mode 100644 pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class delete mode 100644 pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class delete mode 100644 pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class delete mode 100644 pitiupi.mpChat/src/control/ChatController.java delete mode 100644 pitiupi.screenCast/build/built-jar.properties delete mode 100644 pitiupi.screenCast/build/classes/META-INF/services/pitiupi.plugin.Plugin delete mode 100644 pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class delete mode 100644 pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class delete mode 100644 pitiupi.screenCast/build/classes/pitiupi/screenCast/control/AlarmClock.class delete mode 100644 pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ImageTransformation.class delete mode 100644 pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ScreenShot.class delete mode 100644 pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class delete mode 100644 pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class delete mode 100644 pitiupi.screenCast/dist/README.TXT create mode 100644 pitiupi/docs/README.md create mode 100644 pitiupi/plugins/README.md diff --git a/.gitignore b/.gitignore index 237cb8c..cdddd14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ /pitiupi/build/ /pitiupi/dist/ +/pitiupi/plugins/*.jar /pitiupi.chat/build/ /pitiupi.chat/dist/ /pitiupi.chat/nbproject/private/ /pitiupi.screenCast/build/ /pitiupi.screenCast/dist/ +/pitiupi.mpChat/out/ +/pitiupi.mpChat/dist/ +**/built-jar.properties .idea/ diff --git a/README.md b/README.md index e2b66f8..90788b5 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,50 @@ # pitiupi -Ferramenta p2p para práticas em rede +Ferramenta **P2P** para práticas de Redes de Computadores: núcleo em Java com arquitetura de **plugins** (chat, compartilhamento de tela, exemplos multi-protocolo). -Este repositório tem 3 projetos Java que são independentes: -- A ferramenta pitiupi (P2P) -- Um plugin de Chat -- Um plugin de ScreenCast +**Documentação completa:** [docs/README.md](docs/README.md) -Cada um destes projetos deve ser compilado individualmente. Para isso, use a ferramenta ant no diretório do projeto. -Ex: +## Pré-requisitos + +| Ferramenta | Uso | +| --- | --- | +| **JDK** com `javac` | Compilação (OpenJDK **25** recomendado; núcleo compila com target **17**) | +| **Apache Ant** 1.10+ | `pitiupi/`, `pitiupi.chat/`, `pitiupi.screenCast/` | +| **GNU Make** | `pitiupi.mpChat/` | + +Exemplo Ubuntu / WSL: + +```bash +sudo apt install openjdk-25-jdk ant make +javac -version # deve existir — JRE sozinho não basta ``` -cd pitiupi.chat -ant jar -``` -Feito isso, os arquivos jar dos plugins deverão ser copiados ou linkados na pasta plugin da ferramenta. -No caso de a mesma ser linkada, ao recompilar os plugins não é necessário copiar o mesmo novamente para a pasta de plugins da ferramenta. -Para criar links simbólicos no Linux, use o comando: +## Módulos -``` +| Pasta | Descrição | Build | +| --- | --- | --- | +| `pitiupi/` | Núcleo (GUI, UDP multicast, TCP, heartbeat) | `ant jar` | +| `pitiupi.chat/` | Plugin referência — chat | `ant jar` | +| `pitiupi.screenCast/` | Plugin referência — screen cast | `ant jar` | +| `pitiupi.mpChat/` | Plugin referência — chat multicast + TCP | `make` | + +Compile cada módulo no seu diretório (núcleo primeiro). Instale os JARs dos plugins em `pitiupi/plugins/` — ver [pitiupi/plugins/README.md](pitiupi/plugins/README.md). + +Exemplo de symlinks (Linux): + +```bash cd pitiupi/plugins -ln -s ../../pitiupi.chat/dist/*.jar . -ln -s ../../pitiupi.screenCast/dist/*.jar . -``` -Isso deve resolver! +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 +``` -Para criar um novo plugin: +Execute o núcleo (a partir de `pitiupi/`): +```bash +cd pitiupi +java -jar dist/pitiupi.jar +``` + +Quickstart: [docs/documentation/00_quickstart.md](docs/documentation/00_quickstart.md). +Trabalho prático (plugin próprio): [docs/documentation/10_tutorial_plugin.md](docs/documentation/10_tutorial_plugin.md). diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..d5f2fbf --- /dev/null +++ b/docs/README.md @@ -0,0 +1,35 @@ +# Documentação — Pitiupi + +Entrada na raiz do repositório: [README.md](../README.md). + +## Pilares + +| Pasta / arquivo | Papel | +| --- | --- | +| **[documentation/](documentation/README.md)** | Código, rede, plugins, operação e guia para alunos | +| **[references/](references/README.md)** | Bibliografia e notas de conceitos (UDP, TCP, SPI) | +| **[decision-register.md](decision-register.md)** | Decisões de desenho da plataforma | + +## Público-alvo + +| Leitor | Começar por | +| --- | --- | +| **Aluno (TP)** | [documentation/00_quickstart.md](documentation/00_quickstart.md) → [10_tutorial_plugin.md](documentation/10_tutorial_plugin.md) → [11_plugins_referencia.md](documentation/11_plugins_referencia.md) | +| **Monitor / docência** | [documentation/01_visao_disciplina_e_tp.md](documentation/01_visao_disciplina_e_tp.md) → [15_testes_e_gate.md](documentation/15_testes_e_gate.md) | +| **Desenvolvedor** | [documentation/13_guia_dev_e_agente.md](documentation/13_guia_dev_e_agente.md) → [14_arquitetura_e_manutencao.md](documentation/14_arquitetura_e_manutencao.md) | +| **Professor / banca** | [documentation/16_fundamentacao_redes.md](documentation/16_fundamentacao_redes.md) → [references/README.md](references/README.md) | + +**Idioma:** documentação em PT-BR; pacotes e classes Java como no código. + +## Manutenção + +| Tipo de mudança | Onde documentar | +| --- | --- | +| Protocolo UDP/TCP, multicast, portas | [documentation/05_udp_multicast.md](documentation/05_udp_multicast.md), [06_tcp_conexoes.md](documentation/06_tcp_conexoes.md), [appendix_portas_e_multicast.md](documentation/appendix_portas_e_multicast.md) | +| Contrato de plugin / SPI | [documentation/09_sistema_de_plugins.md](documentation/09_sistema_de_plugins.md), [10_tutorial_plugin.md](documentation/10_tutorial_plugin.md) | +| Novo plugin de referência | [documentation/11_plugins_referencia.md](documentation/11_plugins_referencia.md) | +| Decisão de arquitetura | [decision-register.md](decision-register.md) | +| Débito técnico | [documentation/engineering_backlog.md](documentation/engineering_backlog.md) | +| Literatura de redes | [references/](references/) | + +Documentação legada em `pitiupi/docs/` redireciona para esta árvore. diff --git a/docs/decision-register.md b/docs/decision-register.md new file mode 100644 index 0000000..1f74759 --- /dev/null +++ b/docs/decision-register.md @@ -0,0 +1,14 @@ +# Registro de decisões — Pitiupi + +| ID | Decisão | Motivação | Doc | +| --- | --- | --- | --- | +| D1 | Grupo multicast `224.0.0.3` | Endereço fixo para descoberta e broadcast na LAN da sala | [appendix_portas_e_multicast.md](documentation/appendix_portas_e_multicast.md) | +| D2 | Mesma porta UDP e TCP por instância | Configurada no login; simplifica firewall em laboratório | [00_quickstart.md](documentation/00_quickstart.md) | +| D3 | Heartbeat via UDP multicast | Presença sem conexão TCP permanente com todos os peers | [08_heartbeat_e_presenca.md](documentation/08_heartbeat_e_presenca.md) | +| D4 | Timeout de peer ~15 s sem heartbeat | Remover usuários inativos da lista | [08_heartbeat_e_presenca.md](documentation/08_heartbeat_e_presenca.md) | +| D5 | Framing TCP: `int` tamanho + bytes | Delimitar mensagens em stream orientado a bytes | [06_tcp_conexoes.md](documentation/06_tcp_conexoes.md) | +| D6 | Mensagens `Serializable` em `byte[]` | Independência do transporte; plugins definem tipos | [07_mensagens_e_serializacao.md](documentation/07_mensagens_e_serializacao.md) | +| D7 | Plugins via JAR + Java SPI | Carregamento dinâmico sem recompilar o núcleo | [09_sistema_de_plugins.md](documentation/09_sistema_de_plugins.md) | +| D8 | Classloader por JAR de plugin | Isolar dependências; desserialização com `PluginObjectInputStream` | [09_sistema_de_plugins.md](documentation/09_sistema_de_plugins.md) | + +Novas decisões: adicionar linha nesta tabela e detalhar no arquivo técnico correspondente. diff --git a/docs/documentation/00_quickstart.md b/docs/documentation/00_quickstart.md new file mode 100644 index 0000000..c9cdb04 --- /dev/null +++ b/docs/documentation/00_quickstart.md @@ -0,0 +1,63 @@ +# Quickstart + +## 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`) + +Ubuntu / WSL: + +```bash +sudo apt install openjdk-25-jdk ant make +which javac ant make +``` + +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 +``` + +O núcleo gera `pitiupi/dist/pitiupi.jar`. Cada plugin gera JAR em seu `dist/`. + +## 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): + +```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 +``` + +## Executar + +```bash +cd pitiupi +java -jar dist/pitiupi.jar +``` + +No diálogo inicial informe **nome** e **porta** (UDP/TCP). Para duas instâncias no mesmo computador, use **portas diferentes** (ex.: 5000 e 5001). + +## 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). diff --git a/docs/documentation/01_visao_disciplina_e_tp.md b/docs/documentation/01_visao_disciplina_e_tp.md new file mode 100644 index 0000000..279ff8c --- /dev/null +++ b/docs/documentation/01_visao_disciplina_e_tp.md @@ -0,0 +1,47 @@ +# Visão da disciplina e trabalho prático + +## Papel do Pitiupi + +O Pitiupi é uma **plataforma P2P com plugins** usada em Redes de Computadores para: + +- Experimentar UDP (multicast/unicast) e TCP na mesma aplicação. +- Observar **presença** de peers (heartbeat) sem servidor central de aplicação. +- Desenvolver **trabalhos individuais ou em grupo** como novos plugins (jogos, ferramentas colaborativas, etc.). + +O núcleo fornece rede e GUI; o aluno implementa a lógica no plugin. + +## Trabalho típico (plugin) + +Cada equipe/aluno entrega um **módulo Java separado** que: + +1. Compila para JAR e carrega via `pitiupi/plugins/`. +2. Define mensagens (`extends Message`) e o fluxo entre peers. +3. Integra menus/janelas via `GuiManager`. +4. Inclui README do módulo (build + protocolo). + +Exemplos de tema: chat temático, tabuleiro (xadrez/damas), compartilhamento de arquivo, quiz síncrono. + +## Plugins de referência no repositório + +| 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 | + +Detalhes: [11_plugins_referencia.md](11_plugins_referencia.md). + +## Critérios genéricos (ajustar na disciplina) + +| Critério | Indicador | +| --- | --- | +| Funcionalidade | Comportamento correto entre dois+ peers na rede da sala | +| Uso da plataforma | SPI, mensagens, sem “fork” desnecessário do núcleo | +| Build | `ant jar` / `make` reproduzível | +| Documentação | README do plugin + descrição das mensagens | + +## Para monitores + +- Roteiro de build: [00_quickstart.md](00_quickstart.md). +- Checklist de entrega: [15_testes_e_gate.md](15_testes_e_gate.md). +- Fundamentação para dúvidas de alunos: [16_fundamentacao_redes.md](16_fundamentacao_redes.md). diff --git a/docs/documentation/02_modulos_do_repositorio.md b/docs/documentation/02_modulos_do_repositorio.md new file mode 100644 index 0000000..43a9b3f --- /dev/null +++ b/docs/documentation/02_modulos_do_repositorio.md @@ -0,0 +1,34 @@ +# Módulos do repositório + +``` +pitiupi/ # clone (este repositório) +├── 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 +``` + +## Núcleo (`pitiupi/`) + +- **Build:** Apache Ant (`build.xml`, `nbproject/`). +- **Entrada:** `pitiupi.Main` → login → `MainWindow`. +- **Pacotes principais:** `pitiupi.net`, `pitiupi.control`, `pitiupi.GUI`, `pitiupi.models`. + +## Plugins de referência + +| Pasta | Build | JAR típico | Classe 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` | + +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`). + +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). diff --git a/docs/documentation/03_build_ant_netbeans.md b/docs/documentation/03_build_ant_netbeans.md new file mode 100644 index 0000000..6de92c8 --- /dev/null +++ b/docs/documentation/03_build_ant_netbeans.md @@ -0,0 +1,49 @@ +# Build — Ant, NetBeans e Make + +## Pré-requisitos e versões Java + +| Módulo | Build | `javac.source` / `target` (NetBeans) | +| --- | --- | --- | +| `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`: + +```bash +cd pitiupi && ant jar +cd pitiupi.chat && ant jar +cd pitiupi.screenCast && ant jar +``` + +Abrir no NetBeans: **File → Open Project** em cada pasta. + +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). diff --git a/docs/documentation/04_inicializacao_e_gui.md b/docs/documentation/04_inicializacao_e_gui.md new file mode 100644 index 0000000..e21c2a5 --- /dev/null +++ b/docs/documentation/04_inicializacao_e_gui.md @@ -0,0 +1,76 @@ +# 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 foi desenvolvido como suporte às práticas da disciplina de Redes de +Computadores, servindo também como base para experimentação de aplicações +distribuídas e desenvolvimento de projetos acadêmicos. + +Índice: [README.md](README.md). + +# Arquitetura geral + +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/`. +- **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. + +Ver também: [05_udp_multicast.md](05_udp_multicast.md), [09_sistema_de_plugins.md](09_sistema_de_plugins.md). + +# Interface gráfica + +A interface gráfica da aplicação é baseada em Swing e é centralizada na +classe `MainWindow`. + +Durante a inicialização, cada plugin recebe `ConnectionManager` e `GuiManager` +no método `createPlugin()`. + +A extensão usual é registrar menus por categoria (`MenuCategory`). Ver +[12_menus_unicast_multicast.md](12_menus_unicast_multicast.md). + +## Diagrama de comunicação + +``` + +------------------+ + | MainWindow | + +--------+---------+ + | + +--------------------+--------------------+ + | | | + v v v + HeartbeatManager SocketUDP SocketTCP + | | | + v v v + Heartbeat UDP Multicast TCP Connections + | | + +---------+----------+ + | + v + Plugins + | + v + Message +``` + +O UDP multicast sustenta presença e mensagens broadcast/unicast; o TCP sustenta +canais diretos com framing de mensagens. Detalhes em [05](05_udp_multicast.md) +e [06](06_tcp_conexoes.md). diff --git a/docs/documentation/05_udp_multicast.md b/docs/documentation/05_udp_multicast.md new file mode 100644 index 0000000..d289f61 --- /dev/null +++ b/docs/documentation/05_udp_multicast.md @@ -0,0 +1,85 @@ +# Comunicação UDP + + +A classe `SocketUDP` é responsável pela comunicação UDP da aplicação. + +Ela utiliza um `MulticastSocket` associado à porta configurada pela aplicação e +ingressa no grupo multicast `224.0.0.3`. Por ser baseada em UDP, a comunicação não +estabelece uma conexão permanente entre os peers. + +A classe estende `Thread`, mantendo um processo contínuo de recepção de datagramas +enquanto a aplicação está em execução. + +O SocketUDP suporta dois modos de envio: + +- **multicast**, destinado ao grupo de peers +- **unicast**, destinado diretamente ao endereço IP de um peer específico + +### Inicialização + +Durante sua inicialização, o `SocketUDP`: + +1. obtém o endereço do grupo multicast; +2. cria um `MulticastSocket` utilizando a porta configurada na `MainWindow`; +3. configura os buffers de envio e recepção; +4. habilita o reuso do endereço; +5. ingressa no grupo multicast. + +O tamanho dos buffers de comunicação é configurado para `256000` bytes. + +### Envio de mensagens UDP + +O `SocketUDP` suporta dois modos de envio de mensagens: multicast e unicast, ambos +baseados no mesmo mecanismo interno de criação e envio de DatagramPacket. + +O método `sendMulticast()` envia uma mensagem para o grupo multicast da aplicação. +Nesse caso, o `DatagramPacket` é direcionado ao endereço multicast configurado, +permitindo que todas as instâncias participantes do grupo recebam a mensagem +simultaneamente. + +Já o método `sendUnicast()` permite enviar uma mensagem diretamente para um peer +específico. Nesse caso, o `DatagramPacket` é direcionado ao endereço IP informado pelo +chamador, mantendo a mesma porta utilizada pela aplicação. + +Ambos os métodos são, na prática, abstrações de um único mecanismo interno de envio, +que utiliza o mesmo processo de criação e envio de `DatagramPacket` por baixo dos +panos. A diferença entre eles está apenas no endereço de destino: enquanto o multicast +utiliza o grupo compartilhado, o unicast direciona o pacote a um IP específico. + +### Recepção de mensagens + +O método `receive()` mantém um loop aguardando novos datagramas. + +Ao receber uma mensagem, o `SocketUDP` inicialmente tenta identificar se os dados +correspondem a uma `HeartbeatMessage`. + +O processamento segue o seguinte fluxo: + +1. O datagrama é recebido pelo `MulticastSocket`. +2. Os dados recebidos são analisados pelo método `tryParseHeartbeat()`. +3. Caso seja identificada uma `HeartbeatMessage`, ela é encaminhada ao + `HeartbeatManager`, juntamente com o endereço IP de origem. +4. Caso não seja um heartbeat, a mensagem é encaminhada para todos os plugins + carregados. +5. Cada plugin decide se a mensagem recebida pertence à sua funcionalidade. + +Essa separação mantém as mensagens de infraestrutura, como heartbeat, sob +responsabilidade do núcleo da aplicação, enquanto as mensagens específicas das +funcionalidades são processadas pelos plugins. + +### Identificação de mensagens de heartbeat + +O método `tryParseHeartbeat()` tenta desserializar os dados recebidos e verificar se o +objeto resultante é uma instância de `HeartbeatMessage`. + +Caso a mensagem não possa ser desserializada ou não corresponda ao tipo esperado, o +método retorna `null`. Nesse caso, a mensagem é tratada como uma mensagem destinada aos +plugins. + +### Encerramento + +O método `close()` interrompe a execução do processo de recepção, remove a aplicação +do grupo multicast e fecha o `MulticastSocket`. + +A variável `running` é utilizada para sinalizar que o processo de recepção deve ser +encerrado. diff --git a/docs/documentation/06_tcp_conexoes.md b/docs/documentation/06_tcp_conexoes.md new file mode 100644 index 0000000..f088a22 --- /dev/null +++ b/docs/documentation/06_tcp_conexoes.md @@ -0,0 +1,192 @@ +# Comunicação TCP + + +A comunicação TCP é implementada pela classe `SocketTCP`. + +Diferentemente do UDP, o TCP estabelece conexões entre dois peers. Essas conexões +são mantidas enquanto forem necessárias e podem ser reutilizadas para o envio de +múltiplas mensagens. + +A arquitetura utiliza uma conexão TCP persistente por endereço de peer. + +O SocketTCP possui um mapa de conexões: + +`InetAddress` -> `TcpConnection` + +Esse mapa permite localizar rapidamente uma conexão existente para determinado peer e +reutilizá-la durante novos envios. + +### SocketTCP + +A classe `SocketTCP` estende `Thread` e implementa `PeerListener`. + +Ao ser criada, ela inicializa um `ServerSocket` utilizando a porta configurada na +aplicação. + +O servidor TCP permanece aguardando novas conexões enquanto a aplicação estiver +em execução. + +### Envio de mensagens TCP + +O método `send()` recebe uma mensagem serializada e o endereço IP do peer destinatário. + +Antes de enviar a mensagem, o `SocketTCP` verifica se já existe uma conexão válida com +o peer. + +O comportamento é: + +1. Procurar uma conexão existente no mapa de conexões. +2. Verificar se a conexão está fechada. +3. Caso não exista uma conexão válida, criar um novo Socket TCP para o endereço do peer. +4. Encapsular o socket em uma `TcpConnection`. +5. Registrar a conexão no mapa. +6. Iniciar uma tarefa de recepção para essa conexão. +7. Enviar a mensagem pela conexão. + +Assim, uma conexão TCP existente pode ser reutilizada para várias mensagens, evitando +a criação de um novo socket para cada envio. + +### Recepção de conexões + +O método `receive()` permanece aguardando novas conexões através de +`ServerSocket.accept()`. + +Quando uma conexão é aceita: + +O endereço IP do peer é obtido. +Um objeto `TcpConnection` é criado para encapsular o socket. +A conexão é registrada no mapa de conexões. +Caso já exista uma conexão associada ao mesmo endereço, a conexão anterior é encerrada. +Uma tarefa independente de recepção é criada para a nova conexão. + +Esse modelo permite que o servidor aceite múltiplas conexões sem bloquear o +processamento das conexões já existentes. + +### Recepção concorrente + +A recepção das mensagens TCP é realizada de maneira concorrente por meio de um +`ExecutorService`. + +Cada conexão possui uma tarefa própria responsável por receber continuamente as +mensagens. + +O fluxo de recepção é: + +``` +SocketTCP +| ++-- Peer A → TcpConnection → tarefa de recepção +| ++-- Peer B → TcpConnection → tarefa de recepção +| ++-- Peer C → TcpConnection → tarefa de recepção +``` + +Dessa forma, uma conexão bloqueada ou aguardando dados não impede que outras conexões +continuem sendo processadas. + +Quando uma mensagem é recebida por uma `TcpConnection`, ela é encaminhada para todos os +plugins registrados na `MainWindow`. + +O plugin responsável pela funcionalidade deve identificar o tipo da mensagem e +realizar o processamento correspondente. + +### TcpConnection + +A classe TcpConnection encapsula uma conexão TCP individual entre dois peers. + +Ela mantém: + +o Socket utilizado na conexão; +um DataInputStream para recepção; +um DataOutputStream para envio. + +Além de encapsular esses recursos, a classe é responsável pelo framing das mensagens. + +### Framing das mensagens TCP + +A classe `TcpConnection` encapsula uma conexão TCP individual entre dois peers. + +Ela mantém: + +1. o `Socket` utilizado na conexão; +2. um `DataInputStream` para recepção; +3. um `DataOutputStream` para envio. + +Além de encapsular esses recursos, a classe é responsável pelo framing das mensagens. + +Framing das mensagens TCP + +O protocolo TCP fornece um fluxo contínuo de bytes e não preserva os limites das +mensagens enviadas pela aplicação. + +Por esse motivo, é adicionado o tamanho da mensagem antes do conteúdo. + +O formato utilizado é: + +``` ++----------------------+----------------------+ +| tamanho da mensagem | dados da mensagem | ++----------------------+----------------------+ +4 bytes N bytes +``` + +O tamanho é enviado como um `int`, seguido pelos bytes da mensagem. + +No envio, o método `TcpConnection.send()`: + +1. obtém o tamanho do vetor de bytes; +2. escreve o tamanho no `DataOutputStream`; +3. escreve os dados da mensagem; +4. realiza `flush()` no stream. + +O acesso ao stream de saída é sincronizado para evitar que envios concorrentes +misturem seus dados. + +Na recepção, o método `receive()`: + +1. lê o tamanho da mensagem; +2. verifica se o tamanho é válido; +3. lê a quantidade correspondente de bytes; +4. retorna o vetor de bytes completo. + +Esse mecanismo permite que várias mensagens sejam transmitidas pela mesma conexão +TCP sem que o receptor perca a delimitação entre elas. + +### Integração entre TCP e gerenciamento de peers + +O `SocketTCP` implementa a interface PeerListener para acompanhar as alterações na +lista de peers ativos. + +O `HeartbeatManager` mantém a lista de peers atualmente detectados na rede. Quando +essa lista é alterada, o SocketTCP recebe a notificação por meio do método +`onPeersChanged()`. + +O método obtém os endereços IP dos peers atualmente ativos e compara esses endereços +com as conexões TCP existentes. + +Quando uma conexão pertence a um peer que não está mais ativo: + +a conexão é removida do mapa; +a conexão TCP é encerrada; +os recursos associados são liberados. + +Esse mecanismo impede que conexões TCP permaneçam abertas indefinidamente para peers +que já deixaram de participar da rede. + +O fluxo de integração pode ser representado da seguinte forma: +``` +HeartbeatManager +| +| peers ativos alterados +| +v +SocketTCP.onPeersChanged() +| +| compara peers ativos +| +v ++---- peer ativo ------> mantém conexão +| ++---- peer inativo ----> fecha conexão +``` diff --git a/docs/documentation/07_mensagens_e_serializacao.md b/docs/documentation/07_mensagens_e_serializacao.md new file mode 100644 index 0000000..59b7022 --- /dev/null +++ b/docs/documentation/07_mensagens_e_serializacao.md @@ -0,0 +1,18 @@ +# Mensagens + +### Message + +A classe `Message` representa a estrutura base das mensagens trocadas pela aplicação. + +Todas as mensagens utilizadas pelo sistema devem herdar dessa classe. Ela implementa +`Serializable`, permitindo que objetos de mensagem sejam convertidos em vetores de +bytes para transmissão pela rede. + +A serialização é realizada pelo método `toByteArray()`, que transforma uma instância +da mensagem em uma representação binária enviada pelos mecanismos de comunicação. + +As mensagens específicas devem estender essa classe, adicionando os atributos e +comportamentos necessários para cada funcionalidade. + +A camada de transporte não depende do conteúdo específico das mensagens. Tanto o +UDP quanto o TCP recebem mensagens serializadas como `byte[]`. diff --git a/docs/documentation/08_heartbeat_e_presenca.md b/docs/documentation/08_heartbeat_e_presenca.md new file mode 100644 index 0000000..e7cbcd3 --- /dev/null +++ b/docs/documentation/08_heartbeat_e_presenca.md @@ -0,0 +1,62 @@ +# Heartbeat + +### Heartbeat + +O mecanismo de heartbeat é utilizado para identificar quais usuários estão ativos +na rede. + +A aplicação envia periodicamente uma `HeartbeatMessage` contendo informações do usuário, +um identificador único da instância da aplicação e um timestamp. + +Essas mensagens são transmitidas utilizando a comunicação UDP multicast. + +Quando outra instância recebe uma mensagem de heartbeat, o `SocketUDP` identifica +o tipo da mensagem e encaminha o objeto ao `HeartbeatManager`, juntamente com o endereço +IP de origem. + +O `HeartbeatManager` registra ou atualiza o peer correspondente, utilizando o +identificador da instância para diferenciá-lo das demais. + +Um peer é considerado inativo quando permanece mais de 15 segundos sem receber um novo +heartbeat. O `HeartbeatManager` então remove o peer da lista e notifica todos os +componentes registrados como listeners de mudanças de peers. + +Esses listeners podem incluir diferentes partes da aplicação, como componentes +da interface gráfica, mecanismos de comunicação (como o `SocketTCP`) e também plugins +que desejem reagir à presença ou ausência de usuários na rede. + +Dessa forma, o sistema permite que tanto o núcleo da aplicação quanto extensões +externas sejam notificados sobre alterações no estado da rede, mantendo a arquitetura +flexível e extensível. + +O fluxo completo é: + +``` +HeartbeatManager +| +| cria HeartbeatMessage +| +v +Message.toByteArray() +| +v +SocketUDP.sendMulticast() +| +v +UDP Multicast +| +v +SocketUDP.receive() +| +v +HeartbeatManager.receiveHeartbeat() +| +v +Lista de peers ativos +| ++----> Interface de usuários online +| ++----> SocketTCP (PeerListener) +| ++----> Plugins (PeerListener) +``` diff --git a/docs/documentation/09_sistema_de_plugins.md b/docs/documentation/09_sistema_de_plugins.md new file mode 100644 index 0000000..c209a3b --- /dev/null +++ b/docs/documentation/09_sistema_de_plugins.md @@ -0,0 +1,60 @@ +# Sistema de plugins + +O sistema de plugins permite extensão modular sem alterar o núcleo. O contrato +está em `pitiupi.models.Plugin` (classe abstrata). + +## Interface Plugin + +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 | +| `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étodo | Função | +| --- | --- | +| `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 | +| `onSocketClosed(TcpConnection)` | Limpar estado ao fechar socket | + +### Descoberta de plugins + +Para serem reconhecidos, os plugins devem possuir os arquivos de configuração +do Java Service Provider Interface (SPI): + +``` +MeusPlugins +| ++---META-INF + | + +---services + | + +---pitiupi.models.Plugin +``` + +O arquivo `pitiupi.models.Plugin` deve conter o nome completo das classes que +implementam a interface Plugin: + +``` +MeusPlugins.plugins.NomeDaClasse +``` + +Para serem carregados, os plugins devem estar empacotados como arquivos JAR +e colocados no diretório plugins da aplicação. + +### Carregamento de plugins + +O `PluginManager.loadPlugins()` (chamado pela `MainWindow`): + +1. Lista arquivos `.jar` em `pitiupi/plugins/` (diretório de trabalho = pasta do núcleo). +2. Para cada JAR, cria um `URLClassLoader` e usa `ServiceLoader.load(Plugin.class, classLoader)`. +3. Chama `createPlugin(connectionManager, guiManager)` em cada instância. +4. Na recepção UDP/TCP, tenta desserializar com `PluginObjectInputStream` e despacha para plugins que declararam o tipo em `getMessages()`. + +Implementação: `pitiupi/src/pitiupi/control/plugins/PluginManager.java`. diff --git a/docs/documentation/10_tutorial_plugin.md b/docs/documentation/10_tutorial_plugin.md new file mode 100644 index 0000000..ee9b7bd --- /dev/null +++ b/docs/documentation/10_tutorial_plugin.md @@ -0,0 +1,75 @@ +# Tutorial — criar um plugin + +Este guia complementa [09_sistema_de_plugins.md](09_sistema_de_plugins.md). Use `pitiupi.chat` como modelo. + +## 1. Novo projeto + +- Copie a pasta `pitiupi.chat` para `pitiupi.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`. + +## 2. Classe principal + +```java +public class MeuPlugin extends Plugin { + @Override + public void createPlugin(ConnectionManager cm, GuiManager gui) { + // registrar menus, abrir janelas + } + + @Override + public List> getMessages() { + return List.of(MinhaMessage.class); + } + + @Override + public void receiveMessage(Message message) { + if (message instanceof MinhaMessage m) { /* ... */ } + } + + // getName, getAuthor, getVersion, getIdentifier +} +``` + +## 3. Mensagem + +```java +public class MinhaMessage extends Message implements Serializable { + // campos + serialVersionUID recomendado +} +``` + +Envio típico via `ConnectionManager` (multicast ou unicast UDP, ou TCP conforme o caso). + +## 4. Service Provider Interface + +Arquivo `src/META-INF/services/pitiupi.models.Plugin`: + +``` +pacote.MeuPlugin +``` + +## 5. Build e instalação + +```bash +cd pitiupi.meuPlugin && ant jar +ln -sf ../../pitiupi.meuPlugin/dist/*.jar ../pitiupi/plugins/ +``` + +Reinicie o Pitiupi após trocar JARs. + +## 6. Teste + +Duas instâncias, mesma rede, portas distintas se no mesmo host. Ver [00_quickstart.md](00_quickstart.md). + +## 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). + +## Erros frequentes + +| Problema | Causa provável | +| --- | --- | +| Plugin não aparece | SPI ausente ou JAR fora de `plugins/` | +| `ClassNotFoundException` na recepção | Classe da mensagem não no JAR do remetente/destino | +| Peers não se veem | Multicast bloqueado — [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md) | diff --git a/docs/documentation/11_plugins_referencia.md b/docs/documentation/11_plugins_referencia.md new file mode 100644 index 0000000..0f8360e --- /dev/null +++ b/docs/documentation/11_plugins_referencia.md @@ -0,0 +1,59 @@ +# Plugins de referência + +Três exemplos no repositório para comparar estilos de integração. Todos devem ser empacotados em `pitiupi/plugins/`. + +## Comparativo + +| | pitiupi.chat | pitiupi.screenCast | pitiupi.mpChat | +| --- | --- | --- | --- | +| Build | Ant | Ant | Make | +| Classe | `ChatPlugin` | `ScreenCastPlugin` | `MultiProtocolChat` | +| Categoria menu | `Social` | (menu custom via `GuiManager`) | `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` | + +## pitiupi.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`. + +Caminhos: `pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java`. + +## pitiupi.screenCast + +- Demonstra compartilhamento de tela / imagens (`ScreenCastWindow`, `ScreenCastMessage`). +- Útil para discutir **tamanho de datagramas**, compressão (`ImageTransformation`) e limites UDP. + +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). diff --git a/docs/documentation/12_menus_unicast_multicast.md b/docs/documentation/12_menus_unicast_multicast.md new file mode 100644 index 0000000..f2321c3 --- /dev/null +++ b/docs/documentation/12_menus_unicast_multicast.md @@ -0,0 +1,35 @@ +# Menus — unicast e multicast + +## MenuCategory + +Enum em `pitiupi.models.Menus.MenuCategory`: + +| Valor | Uso sugerido | +| --- | --- | +| `Jogos` | Plugins de jogos entre peers | +| `Social` | Chat, presença, mensagens sociais | +| `Streaming` | Screen cast, mídia | + +## Registrar menu (padrão atual) + +Via `GuiManager.createMenu(MenuCategory category, Menu menu)` — ver `ChatPlugin`: + +```java +guiManager.createMenu(MenuCategory.Social, new ChatMenu(chatWindow)); +``` + +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. + +## Unicast vs multicast na aplicação + +| Modo | API típica | Semântica | +| --- | --- | --- | +| Multicast | `ConnectionManager` → `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 | + +Detalhes de rede: [05_udp_multicast.md](05_udp_multicast.md), [06_tcp_conexoes.md](06_tcp_conexoes.md). + +## mpChat + +`MulticastMpChatMenu` e `UnicastMpChatMenu` mostram como expor as duas modalidades no mesmo plugin — [11_plugins_referencia.md](11_plugins_referencia.md). diff --git a/docs/documentation/13_guia_dev_e_agente.md b/docs/documentation/13_guia_dev_e_agente.md new file mode 100644 index 0000000..61c48f1 --- /dev/null +++ b/docs/documentation/13_guia_dev_e_agente.md @@ -0,0 +1,42 @@ +# Guia para desenvolvedor e agente + +## Leitura mínima antes de mudar código + +1. [00_quickstart.md](00_quickstart.md) — build e execução +2. [04_inicializacao_e_gui.md](04_inicializacao_e_gui.md) — boot e diagrama +3. [09_sistema_de_plugins.md](09_sistema_de_plugins.md) — contrato de extensão +4. [14_arquitetura_e_manutencao.md](14_arquitetura_e_manutencao.md) — mapa de pacotes + +## Por tipo de tarefa + +| Tarefa | Ler primeiro | +| --- | --- | +| Novo plugin (aluno) | [10_tutorial_plugin.md](10_tutorial_plugin.md), [11_plugins_referencia.md](11_plugins_referencia.md) | +| Bug UDP / multicast | [05_udp_multicast.md](05_udp_multicast.md), [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md) | +| Bug TCP / conexão | [06_tcp_conexoes.md](06_tcp_conexoes.md) | +| Presença / lista de usuários | [08_heartbeat_e_presenca.md](08_heartbeat_e_presenca.md) | +| Desserialização / mensagens | [07_mensagens_e_serializacao.md](07_mensagens_e_serializacao.md) | + +## Gate de build + +Compilar núcleo e os três plugins de referência: + +```bash +cd pitiupi && ant jar +cd ../pitiupi.chat && ant jar +cd ../pitiupi.screenCast && ant jar +cd ../pitiupi.mpChat && make +``` + +Requer JDK, Ant e Make no PATH. Teste manual em rede: [15_testes_e_gate.md](15_testes_e_gate.md). + +## Convenções + +- Código e identificadores em inglês (pacotes `pitiupi.*`). +- Documentação em português (BR) em `docs/`. +- Evitar alterar o núcleo para necessidades de um único plugin — preferir extensão via `Plugin`. + +## Decisões e débitos + +- [decision-register.md](../decision-register.md) +- [engineering_backlog.md](engineering_backlog.md) diff --git a/docs/documentation/14_arquitetura_e_manutencao.md b/docs/documentation/14_arquitetura_e_manutencao.md new file mode 100644 index 0000000..1a3bf59 --- /dev/null +++ b/docs/documentation/14_arquitetura_e_manutencao.md @@ -0,0 +1,42 @@ +# Arquitetura e manutenção + +## Onde editar + +| 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` | +| Facade rede para plugins | `pitiupi.control.ConnectionManager` | +| Registro de menus | `pitiupi.control.GuiManager` | +| 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` | +| Handshake / fábrica TCP | `pitiupi.net.tcp.ConnectionFactory`, `HandshakeMessage` | +| Heartbeat | `pitiupi.control.HeartbeatManager`, `HeartbeatMessage` | +| Carregar JARs, despacho | `pitiupi.control.plugins.PluginManager` | +| Contrato plugin | `pitiupi.models.Plugin`, `pitiupi.models.Messages.Message` | +| Menus por categoria | `pitiupi.models.Menus.*` | + +## Dependências entre módulos + +``` +pitiupi (núcleo) + ↑ classpath +pitiupi.chat | pitiupi.screenCast | pitiupi.mpChat +``` + +Plugins **não** devem ser dependência do núcleo. + +## Alterações arriscadas + +- Mudar grupo multicast ou formato de heartbeat → quebra interoperabilidade na sala. +- Mudar framing TCP → todos os plugins que usam TCP precisam acompanhar. +- Alterar nome do arquivo SPI (`pitiupi.models.Plugin`) → todos os JARs de plugin. + +Registrar decisão em [decision-register.md](../decision-register.md). + +## Documentação viva + +Ao mudar protocolo ou API pública do núcleo, atualizar o número correspondente em [documentation/README.md](README.md) e, se aplicável, [11_plugins_referencia.md](11_plugins_referencia.md). diff --git a/docs/documentation/15_testes_e_gate.md b/docs/documentation/15_testes_e_gate.md new file mode 100644 index 0000000..ab1bc64 --- /dev/null +++ b/docs/documentation/15_testes_e_gate.md @@ -0,0 +1,38 @@ +# Testes e gate + +## Estado atual + +Não há suíte JUnit integrada ao repositório. A validação principal é: + +1. **Build** de todos os módulos. +2. **Teste manual** com duas instâncias na rede. + +## Gate de build (recomendado) + +Sequência: + +```bash +cd pitiupi && ant jar +cd ../pitiupi.chat && ant jar +cd ../pitiupi.screenCast && ant jar +cd ../pitiupi.mpChat && make +``` + +Falha se `java`, **`javac`**, Ant ou Make estiverem ausentes (instale `openjdk-*-jdk`, não só JRE). + +## Checklist manual (rede) + +- [ ] 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 plugin de aluno + +- [ ] JAR em `plugins/` + SPI correto +- [ ] README do módulo com build e formato das mensagens +- [ ] Demonstração mínima professor ↔ aluno ou aluno ↔ aluno + +## Melhorias futuras + +Ver [engineering_backlog.md](engineering_backlog.md) (testes automatizados, CI). diff --git a/docs/documentation/16_fundamentacao_redes.md b/docs/documentation/16_fundamentacao_redes.md new file mode 100644 index 0000000..8f135a2 --- /dev/null +++ b/docs/documentation/16_fundamentacao_redes.md @@ -0,0 +1,52 @@ +# Fundamentação — redes e código + +Mapa entre conceitos de **Redes de Computadores** e o Pitiupi. Aprofundamento: [references/README.md](../references/README.md). + +## Camada de aplicação P2P + +| Conceito | No Pitiupi | +| --- | --- | +| Aplicação distribuída sem servidor dedicado | Cada peer executa o mesmo núcleo + plugins | +| Identidade do participante | Nome no login + `HeartbeatMessage` (instância) | +| Broadcast lógico | UDP multicast no grupo `224.0.0.3` | +| Comunicação 1:1 | UDP unicast ou TCP com conexão persistente | + +## UDP + +- Sem conexão; mensagens delimitadas por datagrama. +- Multicast economiza envios para todos os peers do grupo. +- Limitações: perda, ordem, MTU — relevante para plugins com imagens (screenCast). + +Doc: [05_udp_multicast.md](05_udp_multicast.md). + +## TCP + +- Conexão orientada a fluxo; o núcleo adiciona **framing** (tamanho + payload). +- Uma conexão por endereço de peer reutilizada para várias mensagens. +- Fechamento quando peer some do heartbeat. + +Doc: [06_tcp_conexoes.md](06_tcp_conexoes.md). + +## Presença + +Heartbeats periódicos em UDP; timeout ~15 s. Analogia com “keepalive” de presença, não com camada de transporte confiável. + +Doc: [08_heartbeat_e_presenca.md](08_heartbeat_e_presenca.md). + +## Serialização + +Objetos Java `Serializable` em `byte[]` — acoplamento de versão de classes entre peers (mesmo plugin instalado). + +Doc: [07_mensagens_e_serializacao.md](07_mensagens_e_serializacao.md). + +## Extensibilidade + +SPI e classloader por JAR — padrão de plug-in em aplicações Java. + +Doc: [09_sistema_de_plugins.md](09_sistema_de_plugins.md). + +## Leitura complementar + +- [references/notas/udp_vs_tcp.md](../references/notas/udp_vs_tcp.md) +- [references/notas/multicast_lan.md](../references/notas/multicast_lan.md) +- [references/notas/java_spi_plugins.md](../references/notas/java_spi_plugins.md) diff --git a/docs/documentation/README.md b/docs/documentation/README.md new file mode 100644 index 0000000..75751b2 --- /dev/null +++ b/docs/documentation/README.md @@ -0,0 +1,27 @@ +# Documentação técnica — Pitiupi + +Referência para **código Java**, **rede P2P** e **plugins**. Índice geral: [docs/README.md](../README.md). + +## Ordem sugerida + +| # | Arquivo | Conteúdo | +| --- | --- | --- | +| 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 | +| 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 | +| 7 | [07_mensagens_e_serializacao.md](07_mensagens_e_serializacao.md) | Classe Message | +| 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 | +| 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 | +| 15 | [15_testes_e_gate.md](15_testes_e_gate.md) | Build gate e testes manuais | +| 16 | [16_fundamentacao_redes.md](16_fundamentacao_redes.md) | Teoria ↔ código | +| — | [appendix_portas_e_multicast.md](appendix_portas_e_multicast.md) | Portas, multicast, WSL | +| — | [engineering_backlog.md](engineering_backlog.md) | Débitos técnicos | diff --git a/docs/documentation/appendix_portas_e_multicast.md b/docs/documentation/appendix_portas_e_multicast.md new file mode 100644 index 0000000..d6d6597 --- /dev/null +++ b/docs/documentation/appendix_portas_e_multicast.md @@ -0,0 +1,38 @@ +# Apêndice — portas e multicast + +## 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`). + +## Multicast + +- Grupo: **`224.0.0.3`** (fixo no código do núcleo). +- Buffer UDP: **256000** bytes (configuração em `SocketUDP`). + +Todos os peers na mesma LAN devem usar a **mesma porta** para participar do mesmo “grupo lógico” da aula (portas diferentes = grupos isolados). + +## Mesmo computador + +Execute duas instâncias com **portas diferentes** (ex.: 5000 e 5001). Mesmo nome de usuário em duas instâncias pode confundir a lista — use nomes distintos. + +## Firewall e Wi‑Fi + +- Bloqueio de multicast em redes de visitantes ou isolamento AP→AP impede descoberta. +- Em laboratório, preferir cabo ou Wi‑Fi com multicast habilitado. + +## WSL2 + +Executar o Pitiupi no WSL e peers no Windows (ou vice-versa) pode falhar em multicast. Preferir: + +- todos os peers no mesmo ambiente (Linux nativo ou VMs), ou +- dois PCs físicos na mesma sub-rede. + +## Sintomas + +| Sintoma | Verificar | +| --- | --- | +| Lista de usuários vazia | Porta igual entre peers? Mesma sub-rede? Firewall? | +| Plugin não recebe | Desserialização / SPI / JAR em `plugins/` | +| TCP falha | Peer ativo no heartbeat? IP correto? | diff --git a/docs/documentation/engineering_backlog.md b/docs/documentation/engineering_backlog.md new file mode 100644 index 0000000..7317edd --- /dev/null +++ b/docs/documentation/engineering_backlog.md @@ -0,0 +1,11 @@ +# Engineering backlog + +| 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 | + +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). + +Ao fechar um item, atualizar esta tabela e o doc técnico relacionado. diff --git a/docs/references/README.md b/docs/references/README.md new file mode 100644 index 0000000..a290988 --- /dev/null +++ b/docs/references/README.md @@ -0,0 +1,18 @@ +# Referências — Pitiupi + +Bibliografia e notas curtas para apoiar a disciplina de Redes de Computadores. + +| Recurso | Descrição | +| --- | --- | +| [bibliografia.bib](bibliografia.bib) | Entradas BibTeX (livro-texto, RFCs, documentação Java) | +| [notas/](notas/) | Resumos em PT-BR ligados ao código | +| [pdfs/](pdfs/) | PDFs locais (não versionados se grandes; ver `.gitkeep`) | + +## Notas disponíveis + +- [udp_vs_tcp.md](notas/udp_vs_tcp.md) +- [multicast_lan.md](notas/multicast_lan.md) +- [java_serializacao.md](notas/java_serializacao.md) +- [java_spi_plugins.md](notas/java_spi_plugins.md) + +Voltar ao índice: [docs/README.md](../README.md). diff --git a/docs/references/bibliografia.bib b/docs/references/bibliografia.bib new file mode 100644 index 0000000..f0a390e --- /dev/null +++ b/docs/references/bibliografia.bib @@ -0,0 +1,24 @@ +@book{tanenbaum2011, + title = {Computer Networks}, + author = {Tanenbaum, Andrew S. and Wetherall, David J.}, + edition = {5}, + year = {2011}, + publisher = {Prentice Hall}, + note = {UDP, TCP, multicast — conceitos gerais} +} + +@misc{rfc1112, + title = {Host Extensions for IP Multicasting}, + author = {Deering, S.}, + howpublished = {RFC 1112}, + year = {1989}, + url = {https://www.rfc-editor.org/rfc/rfc1112} +} + +@book{oracle_networking, + title = {Java Platform, Standard Edition Documentation: Networking}, + author = {{Oracle}}, + year = {2024}, + url = {https://docs.oracle.com/en/java/javase/}, + note = {MulticastSocket, Socket, serialization} +} diff --git a/docs/references/notas/java_serializacao.md b/docs/references/notas/java_serializacao.md new file mode 100644 index 0000000..d269334 --- /dev/null +++ b/docs/references/notas/java_serializacao.md @@ -0,0 +1,11 @@ +# Serialização Java (nota) + +O Pitiupi serializa objetos `Message` (Java `Serializable`) para `byte[]` antes do envio. + +Implicações: + +- Mesma versão de classe nos peers (mesmo JAR de plugin). +- `serialVersionUID` explícito evita incompatibilidade silenciosa. +- Desserialização no núcleo usa `PluginObjectInputStream` com classloader do plugin. + +Doc: [07_mensagens_e_serializacao.md](../../documentation/07_mensagens_e_serializacao.md). diff --git a/docs/references/notas/java_spi_plugins.md b/docs/references/notas/java_spi_plugins.md new file mode 100644 index 0000000..fa9198f --- /dev/null +++ b/docs/references/notas/java_spi_plugins.md @@ -0,0 +1,9 @@ +# Java SPI — plugins (nota) + +O núcleo usa `ServiceLoader` para localizar implementações de `pitiupi.models.Plugin` declaradas em: + +`META-INF/services/pitiupi.models.Plugin` + +Uma linha por classe concreta (FQCN). O JAR deve estar em `pitiupi/plugins/`. + +Doc: [09_sistema_de_plugins.md](../../documentation/09_sistema_de_plugins.md). diff --git a/docs/references/notas/multicast_lan.md b/docs/references/notas/multicast_lan.md new file mode 100644 index 0000000..140d03c --- /dev/null +++ b/docs/references/notas/multicast_lan.md @@ -0,0 +1,12 @@ +# Multicast em LAN (nota) + +IP multicast envia um datagrama que roteadores/switches encaminham aos assinantes do grupo (ex.: `224.0.0.3`). + +Na sala de aula: + +- Todos os peers devem estar na mesma sub-rede e permitir IGMP/multicast. +- Wi‑Fi com “client isolation” impede descoberta. + +Operação no código: [appendix_portas_e_multicast.md](../../documentation/appendix_portas_e_multicast.md). + +RFC introdutória: ver entrada `rfc1112` em [bibliografia.bib](../bibliografia.bib). diff --git a/docs/references/notas/udp_vs_tcp.md b/docs/references/notas/udp_vs_tcp.md new file mode 100644 index 0000000..e47607e --- /dev/null +++ b/docs/references/notas/udp_vs_tcp.md @@ -0,0 +1,10 @@ +# UDP vs TCP (nota) + +| | UDP | TCP | +| --- | --- | --- | +| Conexão | Não | Sim | +| Confiabilidade | Melhor esforço | Entrega ordenada na conexão | +| Delimitação de mensagem | Por datagrama | Fluxo de bytes — Pitiupi usa framing 4+N | +| Uso no Pitiupi | Heartbeat, multicast, plugins | Canais diretos peer-a-peer | + +Ver [05_udp_multicast.md](../../documentation/05_udp_multicast.md) e [06_tcp_conexoes.md](../../documentation/06_tcp_conexoes.md). diff --git a/docs/references/pdfs/.gitkeep b/docs/references/pdfs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/pitiupi.chat/build/built-jar.properties b/pitiupi.chat/build/built-jar.properties deleted file mode 100644 index 54fc683..0000000 --- a/pitiupi.chat/build/built-jar.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Fri, 02 Oct 2026 20:11:21 -0300 - - -C\:\\Users\\extre\\OneDrive\\Documentos\\Faculdade\\2026_02\\Monitoria\\Pitiupi\\pitiupi.chat= - -C\:\\Users\\extre\\OneDrive\\Documentos\\Faculdade\\2026_02\\Monitoria\\Pitiupi\\pitiupi= diff --git a/pitiupi.chat/build/classes/META-INF/services/pitiupi.plugin.Plugin b/pitiupi.chat/build/classes/META-INF/services/pitiupi.plugin.Plugin deleted file mode 100644 index eea07c1..0000000 --- a/pitiupi.chat/build/classes/META-INF/services/pitiupi.plugin.Plugin +++ /dev/null @@ -1 +0,0 @@ -pitiupi.chat.plugin.ChatPlugin diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class deleted file mode 100644 index af3942e3eaea0de2491bbb847bd3769a9524f5e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 922 zcma)4(M}UV6g{`C-ECQlEd{LzBA{$*bQ9y-5?%-rlSLnjH9l^ar3_hi$#xd~EKM{R zP5b~q%6MmXArx!k!`#fhbI!SE?#!>>-+uzwMYoO;$_6SHZlOweaVDh5&V+NC9EQ=@ z*$?B4V-`sf_+xn^?Po((Ayl_SEaWz!YivN6{>cSuUtxXb!xEM_Hkbm;GqBAP z3%JkOVot&`RyYF-Kfo$W5;t5cq@U`X8@5`X7?O)sxd?Q$h^6=CLWHo64Mr(f&kL&A a`vU75+Bf+t*Z5|^f24anX6B~e*?$0}kl2U- diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class deleted file mode 100644 index 3d3023dea6ab0544590e42c02e72a115284fe166..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 944 zcmaJ<+iuf95ItL`b>g~-Q=lci&;p_40(JWwgalDaE7E|}l8VQTvr4vg>|k$F^^H&A z7m%PJ9{2!03NhjbtQRVbB`+KEqb2nZSG=^d_)c`FbjYG%_YE8}qOk)`wEb(NMZxpDXvp zn*+B_!HEpI;dybFVNUgBT-+gGa|*I%A&Z;|$3`BD4247qKUc08i$J+A#l^EOA1V;+Bae8_T%OuzbC)p$QnQo>0U>;)sGO>lRk9YGTdCy6(6-MIFO@ zEQ0Q#h-2Op44b8?cPY0SQuVM)$XrtfqBRglKa=RCPR#A5QVEJ{SSs=;Ye}s z?2r#9x~!vc6nSD#YUQ~<54)|$OqoXD`C%-B-jysH+j^8){XX?@Fbo44y_VP#vDyz~ z>TVwdfr#opk7E&IlXfXf8_OI=Zxcl`^yhJh{02pJ7)d5qslNRRcJdi!wf2m60@$^Y(>$3v8evYb>g2Psr2oIw?j$fsz_9>YyCE7&1#5jahrzF$-A B*R%it diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class deleted file mode 100644 index 34763e9d4337e5f3fb2089d47a166afe2f704ae6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5302 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 diff --git a/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class b/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class deleted file mode 100644 index 661793bd1c06c00b8e6310cfe9a49aaf814258ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 888 zcmaKp&q^af5XQfrj58*VMx*g>*42|q6z3r5LGdEHr|3lqcx?N5 z2iS)atGW{vGrJ6QRS#c(^{cACuP=W9{J?qv9&#c42onedzTar02RAzI_I{~O8lS2( zm2LH&2n0tu(dJknSFJVkm_$BAA;J_Qfy(H0>sp#PQ6@g2WauH_C$g&qN{!$0R>mEf zwBvKr*Gc=3eP$vQ*~B;M&QLfZ0)b*fC+cj_y;A)PdDXGcdo9^%%D(3N@TYICbt>dz1lRyIc`ZxblP#}Z1EMNWiyEYOV& z%5<{9B`I?hi)>KeenME^dBXIERf$Z16*^au#~Nl(v6dU|+0c>YjfK~6g?ZKk?kl+YaHk!P246eexy;#qdXKsQHI}Ny)=|@G`DqCd9qepPz4z??`|8iX0PNy%9#hCDm{xHCGYpGe z5s0uWw2phiZC^XGLrXXeGh4zD!8SvtTxl!FGF4G!4hFxTjazIm}^R!Gem5xWurW`bhL{#3BmNBb1k6 z<7f=m`yocj=sCQBqJl*gZ{jV68$IYG#U^(`Uz20q2)N~XKTx_Y*A#}$u$m%IwAK|| zVYt#m{ZBb0Y95zyO%`K`p)^p8F-$A%JeIMdprqmkZZcd=QIpc`ha#yNL*Dc_F_tkH zcKXPZnNCiII-p>UVJQtL={Y=zir(bDPkoxjZM?0ZtfGP{!~8Sj%+SI>*jhvQ0mGF0 zlwqyhi2mD#V`-0$pHZXrO8hG|)ulkzRouY_L&4)F7iV0`CkaGN>ZcPGbchMj&0>>b zS~_L%4#TBA`=6iAgj;Hvr@}aM9g)R*3~V!tdkn>+Sk@cTeq;B0qtmsybSITFEHs3} z55vwe_Z}O^@}SUgO~Y;*o{;{UK1$QLV2Wf47rxD93u!ls?))U!PY?c>$c(h zTeUP|D$Gbt^3FvIeVaa#Q=)@Z1Ei#$8Yg+m!elzWMGr=5J610YN+*s++Dc6)!7|LX z0>k{aX>^m`D^!<5qeCeddnrc(Zv~!kEMlJ{gPkxqbv;>d9<;gV(*s9Hv^hB8P9UBN zE)QF7=$U*^NS!T6J;pNGkhg|z{Tw~W09_{e5Yj43YkHb#{D5{E&5Y&?)pM|4XfcHk zX_UvHcjhA+)z|NwqvD%b`*Po*%>1LuT#B{4fw}v7;F0vYu zu1ZDx90vqK5GnCRe1V4)pb`1AA}yOZOd{T)S@O;lv|-YB2S{hqDnA chatWindows; - - public ChatController(ConnectionManager connectionManager, ChatMenu chatMenu) { - this.connectionManager = connectionManager; - publicChatWindow = new PublicChatWindow(connectionManager); - - chatMenus = new HashMap<>(); - chatWindows = new HashMap<>(); - - this.chatMenu = chatMenu; - - this.chatMenu.newMenuItem(new JMenuItem("Show global chat"), publicChatWindow); - } - - public void addChatWindow(TcpConnection tcpConnection) { - if (chatWindows.containsKey(tcpConnection)) return; - - PrivateChatWindow newChat = new PrivateChatWindow(connectionManager, tcpConnection); - chatWindows.put(tcpConnection, newChat); - JMenuItem newMenuItem = new JMenuItem(); - chatMenus.put(tcpConnection, newMenuItem); - newMenuItem.setText(tcpConnection.getAddress().toString()); - chatMenu.newMenuItem(newMenuItem, newChat); - } - - public void removeChatWindow(TcpConnection tcpConnection) { - ChatWindow removedWindow = chatWindows.remove(tcpConnection); - JMenuItem removedMenu = chatMenus.remove(tcpConnection); - - chatMenu.removeMenuItem(removedMenu); - removedWindow.setVisible(false); - removedWindow.dispose(); - } - - public void receivePublic(MpChatMessage message) { - publicChatWindow.receiveMessage(message); - } - public void receivePrivate(TcpConnection tcpConnection, MpChatMessage message) { - chatWindows.get(tcpConnection).receiveMessage(message); - } - - public void openChatWindow(InetAddress address) { - - } - - @Override - public void onPeersChanged(List list) { - - } -} diff --git a/pitiupi.mpChat/src/control/PrivateChatController.java b/pitiupi.mpChat/src/control/PrivateChatController.java index aad138a..d806153 100644 --- a/pitiupi.mpChat/src/control/PrivateChatController.java +++ b/pitiupi.mpChat/src/control/PrivateChatController.java @@ -2,9 +2,9 @@ package control; import GUI.PrivateChatWindow; import net.MpChatMessage; +import pitiupi.control.ConnectionManager; import pitiupi.models.User; import pitiupi.net.tcp.TcpConnection; -import pitiupi.plugin.Pitiupi; import plugin.MultiProtocolChat; import java.util.HashMap; @@ -14,7 +14,7 @@ import java.util.Set; public class PrivateChatController { - private final Pitiupi pitiupi; + private final ConnectionManager connectionManager; private final MultiProtocolChat multiProtocolChat; /* @@ -29,16 +29,20 @@ public class PrivateChatController { private final Set pendingConnections; public PrivateChatController( - Pitiupi pitiupi, + ConnectionManager connectionManager, MultiProtocolChat multiProtocolChat ) { - this.pitiupi = pitiupi; + this.connectionManager = connectionManager; this.multiProtocolChat = multiProtocolChat; this.windows = new HashMap<>(); this.pendingConnections = new HashSet<>(); } + private static String addressKey(TcpConnection connection) { + return connection.getAddress().getHostAddress(); + } + public void openChat(User user) { String address = user.getAddress().getHostAddress(); @@ -70,7 +74,7 @@ public class PrivateChatController { } public void receiveMessage(TcpConnection connection, MpChatMessage message) { - String address = connection.getAddress().toString(); + String address = addressKey(connection); PrivateChatWindow window = windows.get(address); @@ -85,12 +89,12 @@ public class PrivateChatController { * Deve ser chamado quando uma nova conexão privada chegar. */ public void connectionReceived(TcpConnection connection) { - String address = connection.getAddress().toString(); + String address = addressKey(connection); pendingConnections.remove(address); PrivateChatWindow window = new PrivateChatWindow( - pitiupi, + connectionManager, connection ); @@ -105,7 +109,7 @@ public class PrivateChatController { * Fecha a janela e remove o relacionamento. */ public void closeChat(TcpConnection connection) { - String address = connection.getAddress().toString(); + String address = addressKey(connection); PrivateChatWindow window = windows.remove(address); @@ -113,4 +117,4 @@ public class PrivateChatController { window.dispose(); } } -} \ No newline at end of file +} diff --git a/pitiupi.mpChat/src/plugin/MultiProtocolChat.java b/pitiupi.mpChat/src/plugin/MultiProtocolChat.java index bab8d2a..c9915b2 100644 --- a/pitiupi.mpChat/src/plugin/MultiProtocolChat.java +++ b/pitiupi.mpChat/src/plugin/MultiProtocolChat.java @@ -1,16 +1,16 @@ package plugin; import GUI.MulticastMpChatMenu; -import GUI.PrivateChatWindow; import GUI.PublicChatWindow; import GUI.UnicastMpChatMenu; import control.PrivateChatController; import net.MpChatMessage; +import pitiupi.control.ConnectionManager; +import pitiupi.control.GuiManager; import pitiupi.models.Menus.MenuCategory; import pitiupi.models.Messages.Message; -import pitiupi.net.tcp.TcpConnection; import pitiupi.models.Plugin; -import pitiupi.plugin.Pitiupi; +import pitiupi.net.tcp.TcpConnection; import javax.swing.*; import java.io.ByteArrayInputStream; @@ -20,7 +20,7 @@ import java.net.InetAddress; import java.util.List; public class MultiProtocolChat extends Plugin { - Pitiupi pitiupi; + private ConnectionManager connectionManager; PrivateChatController privateChatController; PublicChatWindow publicChatWindow; @@ -46,18 +46,18 @@ public class MultiProtocolChat extends Plugin { } @Override - public void createPlugin(Pitiupi pitiupi) { - this.pitiupi = pitiupi; + public void createPlugin(ConnectionManager connectionManager, GuiManager guiManager) { + this.connectionManager = connectionManager; - privateChatController = new PrivateChatController(pitiupi, this); + privateChatController = new PrivateChatController(connectionManager, this); - publicChatWindow = new PublicChatWindow(pitiupi); + publicChatWindow = new PublicChatWindow(connectionManager); MulticastMpChatMenu multicastMpChatMenu = new MulticastMpChatMenu(publicChatWindow); UnicastMpChatMenu unicastMpChatMenu = new UnicastMpChatMenu(privateChatController); - pitiupi.createMenu(MenuCategory.Social, multicastMpChatMenu); - pitiupi.createMenu(MenuCategory.Social, unicastMpChatMenu); + guiManager.createMenu(MenuCategory.Social, multicastMpChatMenu); + guiManager.createMenu(MenuCategory.Social, unicastMpChatMenu); } @Override @@ -102,7 +102,11 @@ public class MultiProtocolChat extends Plugin { public void openConnection(String ip) { try { - pitiupi.connectTcp(InetAddress.getByName(ip), getIdentifier(), getIdentifier()); + connectionManager.connectPluginTcp( + InetAddress.getByName(ip), + getIdentifier(), + getIdentifier() + ); } catch (Exception e) { System.out.println("Error opening connection: " + e.getMessage()); diff --git a/pitiupi.screenCast/build/built-jar.properties b/pitiupi.screenCast/build/built-jar.properties deleted file mode 100644 index 1f21a31..0000000 --- a/pitiupi.screenCast/build/built-jar.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue, 29 Sep 2026 11:04:58 -0300 - - -C\:\\Users\\Gustavo\\OneDrive\\Documentos\\Faculdade\\2026_2\\Monitoria\\pitiupi\\pitiupi.screenCast= - -C\:\\Users\\Gustavo\\OneDrive\\Documentos\\Faculdade\\2026_2\\Monitoria\\pitiupi\\pitiupi= diff --git a/pitiupi.screenCast/build/classes/META-INF/services/pitiupi.plugin.Plugin b/pitiupi.screenCast/build/classes/META-INF/services/pitiupi.plugin.Plugin deleted file mode 100644 index d11a8fc..0000000 --- a/pitiupi.screenCast/build/classes/META-INF/services/pitiupi.plugin.Plugin +++ /dev/null @@ -1 +0,0 @@ -pitiupi.screenCast.plugin.ScreenCastPlugin diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class deleted file mode 100644 index 4c002f112524930cac724e89e79f82f91994c23b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1644 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 diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/AlarmClock.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/AlarmClock.class deleted file mode 100644 index 40e9f43adeacfcbec5df94a837782a4996e61c96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 629 zcma)4%TB^T6g@)=g<1s#d~aMB0gc_c!I&5##suAfxE@NQqwSRRq2FcVBXQve_)*3? zfOa7ZGRe%GJLjBxbMJh8e|!Qs!?uYGGy}SYEOHFxd;ZAnBo?0C6TTbvc=W)KI~G#J zCk$Gx-Y+1Jf&tUQ0xX8zk%&by5_aT-t}9zSift#5aTs{^smDXVe zL%lOYdwzXkcmJ#=)TW6g6b+OtEUPN_=F~A%BUcVnyGu8U_^r!uP@6kElebZxK$RA- xI$_hfMu>D+Cs#&m1G%Z^(HH~y#tV!$ET)d?4}q8lHpgyCNxZ2Wqo}HH>jzymk_!L; diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ImageTransformation.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ImageTransformation.class deleted file mode 100644 index b4c1d4370e808ac8f51fb5b77f932ab38eda18f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2970 zcmb7GX;%|x7`-o4j~nahA<)m4fDoR zBeh@@^Qp|tyqWa`BE448^7;fq$&N`CQGpg;$+A-e%bwZqIL30O?3K#igy)z>AqEwp zDC%i2U&_a@6T4LG*3f`G0&!`&l(Gs&-lPLvUiFMXc+s&uQ$SCS_|A<*FHlO|HH$gZ zF>}6ZI*|JK7|kl?t0(kTiy__dK*HFoVISfG^`5;BRX|C0JRFd?4rn-tgg{f?^nCYI z5`^OpEDzgG!SKe60wE=1+2?Hb;|G1?RHkU49V7d&5h$8d~-KwH)A7J@fa7~@2> zey`Mt;W#=pbfSwnxTZH~7fO!lx|UrWwR0pyN$MSwQtPCKQ%JF>o3+Nv#)9Q7OT}TS zxD#hIoW(hT16ekRXZl>%mP??wmgJ!G(g8&qI9OVz`X79EDzi`~RsG{rZkrt`{`o2HJw@89Bod9RGi2f z3moC1>lwu?TPU8?b-g+Qa@2#2r27fU{ylCTUxRcFVN$~s-r^L~(M`uF%~@Gjx~Q>V zJ7z09z(W;pYj_8b7<(Pong)}~ImV(NP~comjROq2zI6fl=b0JTbe@_H7mJF=0;fur zXO&A<%4JKN#X-aMQdzs`IW`x9ti(OXD7v%$8sXq@76$#<**#(v&9QP}#&qr(GYh1m zal|G$lZIo-=jx&2%~{Ox^vM4UlNLBylaVEXq&C$w&DFq`UX`IHgOyY z^j@{`8CH?4E>I`E$8IcT&63BoT@|*#UcU%(+h^7#?4N9PuL!ii2J>(L+LcWtAcon_ zi@~PmCJdl$TC>Cx2^6^7eff4{;!rJI3KnOO;C5R6W~FAxl0O;fd9{beSFJn1hOOaAzhP@O};$F)hX_leF`rCRW` zCR76?Iesbxd2Ea?oz7JEhrrGW&&WO*HA>Zvj!oEQCuf(+TtPAsZm*!b z`vp$-L=s9OQo;FzB3|P1bf*xj=t)rNYBw?WsM79wLY2@%J`-n|KS*B`N3jd-Nbp0U z7039NK8|jj;QKd;E9l_v?!-8{Fv(NN+T8$PH8nzo1DAg%jvaHVC1 z7k$Nk^20?Xt~5VKTk}Q5KZ+|-G$=)VEltl6ZR(Svmbju;FxC@(iJ@seG(=Z%m)w!L z`-yNUBr2GmN<_A@bei$cU@y)wqw_5D1)RhsW^$QNS9o_7{pdpm*Z30Y_gT6X;KV0> z0}wGj#b?Y=-hIxyI{rVx7rYD6?u{`CL= diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ScreenShot.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ScreenShot.class deleted file mode 100644 index 3cde756ccc5d720429121c5af500b530519eadd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 954 zcma)4T~8W86g>mT!gdt}KU-_*hZWSi{d%KmV$mi>S`#5OJ`U>$qstCiX4|H}s(q2B zCj9~ZQBCix2t4@E-Q-U0J@=e@=id4A_t$R#`*>v|fux0$gDIpLX3zO&?)p4vyGN~a z;c15S8yQIbmLXXxH!WlsX5u9NMZ3qUrL+ypNZet_j{%~Rh%anRW5z);+%844uHwYXNU@}7=D5`R6xJifVDWuimb#u2C1q#r9!!y48+H%+Y(`ew|t7^ zYs%w(lZVpy!(d8xWS?Q9_Fw81hOFinVz(ZbDo#%7w#FHzLbFy{)_7p?qDjfVzKEFu z!~6t38Vfxb73p3?_}Uo1y^y{C)e}8Uo9bKGVOSXLeD_mhgjsk_n~5Q*+=HVLK<(63 z6nf&lG_%T$C%R*@@eudvb(=2%x)su7ACTwL$>^Ng9Dx0Z;UZZB0|lZ1&UFGF;W2qx zJi$7N7;*=d-xs7vv@I@*ghg>vaGC diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class deleted file mode 100644 index dc8a7ea26b95b1e4f03cc4086d68875edca92d3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 925 zcma)(PjAye5XIj*j!lBw(6mh{|Jq)t6QDi-r=lKGfrJ!#35tYz+NP_pC~+#=LE>A1 z)T&Ysd;mTa;_cc^A`&EIX=lfJ^V>Hwzkc8R1n?GnRX8a5a08U#39Mh}OiwO!6ss)y zpwd(hlz{g}$2vO_D22^l1$R*KQ4Mexfk1d$k@gd%;$xX+wzxY@rx-VuBhu=fFY>F5 zhB6*R-7L}Z;LtEv1JrO&prS{7wEZok)H!VnxX0sj-fJBltCPv-OeG)X+0cT1LmGD$wfuudhRat#HxOX}j4I@CPb8v9345=Awv#^j5IB1Y!^Y5$|U$xna{Z z6|ipZZ#m50t9Hkeq_5s-(_dp@h6iSH*yFSuuFv7e9oQR3$LK+rJ@Q;*_L5OBmRr{l zKdh|I)2tj=hl>rKAi#>4Z89@}22TU{L}iJwW&o{cSMXcUudp&h)d>ORF1Ap?eXL^J zB6st$0!e`NX`ZQ>B@@e`Q=dN*G3Gum;eV&df$?eD0Ctvo+{S~V_=sxLk7xbOtmR!k zWjFhl(8yI&OI~3~;2|Crta&3Ve;awR)W~BzS!QHzM!At!H1hf%M$AOa1a@reyMF)| C`IO!O diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class deleted file mode 100644 index b26bee9dd227c82c34b55127f064982464dae879..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2459 zcmah~TT|Oc7(MF?vK8`Q~zrPc0tzUw*bKmYmVR{(4HHUb~~3Ib6C(ZRUhKWl3JXv-9CO4jKCL89@g;vyG zMbLq6nP?BgN^HwP6?Dxs^ipzF*EGsl=vqeA)B|p$u9$4pgmV_ph0%u_3i_kCi2;U$ zFDcL)?wlIP)wcrQjCBxJS6wqBC5pMKFkAS@La$sYc0f zixAI6FoID9V^Q42J2V0(n$xUCCm0m9Sd_sSZp5}E0Zx+DSAr<;MDC{IIR)=B3|Z6= zdUEB|SqXYHiGE0U24mKa8?14~@1CAC`J*3EUjrWIYQ zFqZK^!NVxhSZNVs_Oxp9GHFV$ktF--#Z$j_4WZd1NJa1nYYNt**uY~a4J(=(fFWe+ zG%*@3Lu(W3yX52vK31?5MF!iBlh!~)n2HQr(kK&qbXFMKg`C^Gyi`7+b7vg3k{ta6 zR`nuh=-3h(->#MSx$#upFVRl-mR?XxIn@yI+ujVAhoVXX@KV_SNHj%R9&mG8EtAtQ ztxR^)@P#55F!Obj#(%6}^#-kDs{IX{Cj1R=F+%tPri~pNgKJ(pQq+jNZY-IoNAj_>iTiJO=vll%CPL0iGd8 zUkuOjn4S_mO>b%E?^b@KS2J|D3F>#DpLsyTm!V^x(7Xrq+GXg3C-idCh8+;@`R?o2cnjD8QOG$iazf*`5|I!}aZhZ<$v;n5zktA6enqB*x)eGY41?KbT*ttBcwWeW(Tz2Uc#)ry( DV!csu diff --git a/pitiupi.screenCast/dist/README.TXT b/pitiupi.screenCast/dist/README.TXT deleted file mode 100644 index 28b99c7..0000000 --- a/pitiupi.screenCast/dist/README.TXT +++ /dev/null @@ -1,32 +0,0 @@ -======================== -BUILD OUTPUT DESCRIPTION -======================== - -When you build an Java application project that has a main class, the IDE -automatically copies all of the JAR -files on the projects classpath to your projects dist/lib folder. The IDE -also adds each of the JAR files to the Class-Path element in the application -JAR files manifest file (MANIFEST.MF). - -To run the project from the command line, go to the dist folder and -type the following: - -java -jar "pitiupi.screenCast.jar" - -To distribute this project, zip up the dist folder (including the lib folder) -and distribute the ZIP file. - -Notes: - -* If two JAR files on the project classpath have the same name, only the first -JAR file is copied to the lib folder. -* Only JAR files are copied to the lib folder. -If the classpath contains other types of files or folders, these files (folders) -are not copied. -* If a library on the projects classpath also has a Class-Path element -specified in the manifest,the content of the Class-Path element has to be on -the projects runtime path. -* To set a main class in a standard Java project, right-click the project node -in the Projects window and choose Properties. Then click Run and enter the -class name in the Main Class field. Alternatively, you can manually type the -class name in the manifest Main-Class element. diff --git a/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastMenu.java b/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastMenu.java index 93abd86..1f87dc5 100644 --- a/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastMenu.java +++ b/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastMenu.java @@ -4,28 +4,49 @@ */ package pitiupi.screenCast.GUI; -import java.awt.event.ActionEvent; -import javax.swing.JMenu; +import java.util.List; + +import pitiupi.models.Menus.MulticastMenus.MulticastActionMenu; +import pitiupi.models.Menus.MulticastMenus.MulticastMenu; +import pitiupi.models.Menus.MulticastMenus.MulticastSubMenu; /** * * @author flavio */ -public class ScreenCastMenu extends JMenu { +public class ScreenCastMenu extends MulticastSubMenu { - private final ScreenCastWindow screenCastWindow; - private final javax.swing.JMenuItem menuItem; + private final ScreenCastShowMenu showMenu; public ScreenCastMenu(ScreenCastWindow screenCastWindow) { - this.screenCastWindow = screenCastWindow; - this.setText("Screen Cast"); - menuItem = new javax.swing.JMenuItem(); - menuItem.setText("ScreenCast Window"); - menuItem.addActionListener(this::chatMenuActionPerformed); - this.add(menuItem); + this.showMenu = new ScreenCastShowMenu(screenCastWindow); } - private void chatMenuActionPerformed(ActionEvent ae) { - this.screenCastWindow.setVisible(true); + @Override + public String getText() { + return "Screen Cast"; + } + + @Override + public List getMenus() { + return List.of(showMenu); + } + + private static final class ScreenCastShowMenu extends MulticastActionMenu { + private final ScreenCastWindow screenCastWindow; + + ScreenCastShowMenu(ScreenCastWindow screenCastWindow) { + this.screenCastWindow = screenCastWindow; + } + + @Override + public String getText() { + return "ScreenCast Window"; + } + + @Override + public void onClick() { + screenCastWindow.setVisible(true); + } } } diff --git a/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastWindow.java b/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastWindow.java index cfd0022..573dc9b 100644 --- a/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastWindow.java +++ b/pitiupi.screenCast/src/pitiupi/screenCast/GUI/ScreenCastWindow.java @@ -22,8 +22,6 @@ import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JLabel; -import pitiupi.GUI.MainWindow; -import pitiupi.net.Message; /** * diff --git a/pitiupi.screenCast/src/pitiupi/screenCast/net/ScreenCastMessage.java b/pitiupi.screenCast/src/pitiupi/screenCast/net/ScreenCastMessage.java index 99b4ae1..d307cf6 100644 --- a/pitiupi.screenCast/src/pitiupi/screenCast/net/ScreenCastMessage.java +++ b/pitiupi.screenCast/src/pitiupi/screenCast/net/ScreenCastMessage.java @@ -5,7 +5,7 @@ */ package pitiupi.screenCast.net; -import pitiupi.net.Message; +import pitiupi.models.Messages.Message; /** * @@ -46,7 +46,7 @@ public class ScreenCastMessage extends Message { } /** - * @param imageByte the image to set + * @param imageByte the imageByte to set */ public void setImageByte(byte[] imageByte) { this.imageByte = imageByte; diff --git a/pitiupi.screenCast/src/pitiupi/screenCast/plugin/ScreenCastPlugin.java b/pitiupi.screenCast/src/pitiupi/screenCast/plugin/ScreenCastPlugin.java index 50641a6..f7dcd55 100644 --- a/pitiupi.screenCast/src/pitiupi/screenCast/plugin/ScreenCastPlugin.java +++ b/pitiupi.screenCast/src/pitiupi/screenCast/plugin/ScreenCastPlugin.java @@ -4,14 +4,13 @@ */ package pitiupi.screenCast.plugin; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import pitiupi.GUI.MainWindow; +import java.util.List; + import pitiupi.control.ConnectionManager; import pitiupi.control.GuiManager; -import pitiupi.net.Message; -import pitiupi.plugin.Plugin; +import pitiupi.models.Menus.MenuCategory; +import pitiupi.models.Messages.Message; +import pitiupi.models.Plugin; import pitiupi.screenCast.GUI.ScreenCastMenu; import pitiupi.screenCast.GUI.ScreenCastWindow; import pitiupi.screenCast.net.ScreenCastMessage; @@ -20,7 +19,7 @@ import pitiupi.screenCast.net.ScreenCastMessage; * * @author flavio */ -public class ScreenCastPlugin implements Plugin { +public class ScreenCastPlugin extends Plugin { private ScreenCastWindow screenCastWindow; @@ -47,26 +46,18 @@ public class ScreenCastPlugin implements Plugin { @Override public void createPlugin(ConnectionManager connectionManager, GuiManager guiManager) { this.screenCastWindow = new ScreenCastWindow(connectionManager, guiManager); - guiManager.addMenu(new ScreenCastMenu(screenCastWindow)); + guiManager.createMenu(MenuCategory.Social, new ScreenCastMenu(screenCastWindow)); } @Override - public void receiveMessage(byte[] message) { - ByteArrayInputStream bis = new ByteArrayInputStream(message); - ObjectInputStream ois; - try { - ois = new ObjectInputStream(bis); - if (ois.readObject() instanceof ScreenCastMessage msg) { - this.screenCastWindow.receiveScreenCastMessage(msg); - } - } catch (IOException | ClassNotFoundException ex) { - System.out.println(ex.toString()); + public List> getMessages() { + return List.of(ScreenCastMessage.class); + } + + @Override + public void receiveMessage(Message message) { + if (message instanceof ScreenCastMessage msg) { + this.screenCastWindow.receiveScreenCastMessage(msg); } } - - @Override - public Message getMessage() { - return new ScreenCastMessage(); - } - } diff --git a/pitiupi/docs/Documentation.md b/pitiupi/docs/Documentation.md index 6e15422..1cc1dff 100644 --- a/pitiupi/docs/Documentation.md +++ b/pitiupi/docs/Documentation.md @@ -1,547 +1,5 @@ -# Visão geral +# Documentação (legado) -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. +Este arquivo foi substituído pela árvore em **[docs/](../../docs/README.md)**. -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. - -Dessa forma, novos comportamentos podem ser adicionados por meio de plugins -sem modificar o núcleo da aplicação. - -O projeto foi desenvolvido como suporte às práticas da disciplina de Redes de -Computadores, servindo também como base para experimentação de aplicações -distribuídas e desenvolvimento de projetos acadêmicos. - -# Arquitetura geral - -A aplicação é dividida em três grupos principais: - -- **Núcleo da aplicação**: A `MainWindow` atua como ponto central da aplicação, - sendo responsável por inicializar e integrar esses componentes durante a - execução. -- **Sistema de plugins**: responsável por adicionar funcionalidades sem - alterar o núcleo da aplicação. -- **Comunicação de rede**: responsável pela troca de mensagens entre - instâncias da aplicação. - -## Inicialização da aplicação - -1. A MainWindow é criada. -2. O SocketUDP é inicializado, associa-se à porta configurada e ingressa no - grupo multicast. -3. O SocketTCP é inicializado e cria um ServerSocket na porta da aplicação - para aceitar conexões TCP. -4. Os mecanismos de comunicação iniciam seus respectivos processos de recepção. -5. O HeartbeatManager é criado e inicia o envio periódico de heartbeats. -6. O painel de usuários online é registrado como listener do HeartbeatManager. -7. O PluginLoader procura e carrega os plugins disponíveis. - -# Sistema de comunicação - -A comunicação entre as instâncias da aplicação é realizada por meio de dois -mecanismos complementares: - -- **UDP multicast/unicast**, implementado por `SocketUDP` -- **TCP**, implementado por `SocketTCP` e `TcpConnection` - -Ambos os mecanismos utilizam mensagens serializadas em `byte[]`, permitindo que -os plugins permaneçam independentes dos detalhes do protocolo de transporte. - -## Comunicação UDP - -A classe `SocketUDP` é responsável pela comunicação UDP da aplicação. - -Ela utiliza um `MulticastSocket` associado à porta configurada pela aplicação e -ingressa no grupo multicast `224.0.0.3`. Por ser baseada em UDP, a comunicação não -estabelece uma conexão permanente entre os peers. - -A classe estende `Thread`, mantendo um processo contínuo de recepção de datagramas -enquanto a aplicação está em execução. - -O SocketUDP suporta dois modos de envio: - -- **multicast**, destinado ao grupo de peers -- **unicast**, destinado diretamente ao endereço IP de um peer específico - -### Inicialização - -Durante sua inicialização, o `SocketUDP`: - -1. obtém o endereço do grupo multicast; -2. cria um `MulticastSocket` utilizando a porta configurada na `MainWindow`; -3. configura os buffers de envio e recepção; -4. habilita o reuso do endereço; -5. ingressa no grupo multicast. - -O tamanho dos buffers de comunicação é configurado para `256000` bytes. - -### Envio de mensagens UDP - -O `SocketUDP` suporta dois modos de envio de mensagens: multicast e unicast, ambos -baseados no mesmo mecanismo interno de criação e envio de DatagramPacket. - -O método `sendMulticast()` envia uma mensagem para o grupo multicast da aplicação. -Nesse caso, o `DatagramPacket` é direcionado ao endereço multicast configurado, -permitindo que todas as instâncias participantes do grupo recebam a mensagem -simultaneamente. - -Já o método `sendUnicast()` permite enviar uma mensagem diretamente para um peer -específico. Nesse caso, o `DatagramPacket` é direcionado ao endereço IP informado pelo -chamador, mantendo a mesma porta utilizada pela aplicação. - -Ambos os métodos são, na prática, abstrações de um único mecanismo interno de envio, -que utiliza o mesmo processo de criação e envio de `DatagramPacket` por baixo dos -panos. A diferença entre eles está apenas no endereço de destino: enquanto o multicast -utiliza o grupo compartilhado, o unicast direciona o pacote a um IP específico. - -### Recepção de mensagens - -O método `receive()` mantém um loop aguardando novos datagramas. - -Ao receber uma mensagem, o `SocketUDP` inicialmente tenta identificar se os dados -correspondem a uma `HeartbeatMessage`. - -O processamento segue o seguinte fluxo: - -1. O datagrama é recebido pelo `MulticastSocket`. -2. Os dados recebidos são analisados pelo método `tryParseHeartbeat()`. -3. Caso seja identificada uma `HeartbeatMessage`, ela é encaminhada ao - `HeartbeatManager`, juntamente com o endereço IP de origem. -4. Caso não seja um heartbeat, a mensagem é encaminhada para todos os plugins - carregados. -5. Cada plugin decide se a mensagem recebida pertence à sua funcionalidade. - -Essa separação mantém as mensagens de infraestrutura, como heartbeat, sob -responsabilidade do núcleo da aplicação, enquanto as mensagens específicas das -funcionalidades são processadas pelos plugins. - -### Identificação de mensagens de heartbeat - -O método `tryParseHeartbeat()` tenta desserializar os dados recebidos e verificar se o -objeto resultante é uma instância de `HeartbeatMessage`. - -Caso a mensagem não possa ser desserializada ou não corresponda ao tipo esperado, o -método retorna `null`. Nesse caso, a mensagem é tratada como uma mensagem destinada aos -plugins. - -### Encerramento - -O método `close()` interrompe a execução do processo de recepção, remove a aplicação -do grupo multicast e fecha o `MulticastSocket`. - -A variável `running` é utilizada para sinalizar que o processo de recepção deve ser -encerrado. - -## Comunicação TCP - -A comunicação TCP é implementada pela classe `SocketTCP`. - -Diferentemente do UDP, o TCP estabelece conexões entre dois peers. Essas conexões -são mantidas enquanto forem necessárias e podem ser reutilizadas para o envio de -múltiplas mensagens. - -A arquitetura utiliza uma conexão TCP persistente por endereço de peer. - -O SocketTCP possui um mapa de conexões: - -`InetAddress` -> `TcpConnection` - -Esse mapa permite localizar rapidamente uma conexão existente para determinado peer e -reutilizá-la durante novos envios. - -### SocketTCP - -A classe `SocketTCP` estende `Thread` e implementa `PeerListener`. - -Ao ser criada, ela inicializa um `ServerSocket` utilizando a porta configurada na -aplicação. - -O servidor TCP permanece aguardando novas conexões enquanto a aplicação estiver -em execução. - -### Envio de mensagens TCP - -O método `send()` recebe uma mensagem serializada e o endereço IP do peer destinatário. - -Antes de enviar a mensagem, o `SocketTCP` verifica se já existe uma conexão válida com -o peer. - -O comportamento é: - -1. Procurar uma conexão existente no mapa de conexões. -2. Verificar se a conexão está fechada. -3. Caso não exista uma conexão válida, criar um novo Socket TCP para o endereço do peer. -4. Encapsular o socket em uma `TcpConnection`. -5. Registrar a conexão no mapa. -6. Iniciar uma tarefa de recepção para essa conexão. -7. Enviar a mensagem pela conexão. - -Assim, uma conexão TCP existente pode ser reutilizada para várias mensagens, evitando -a criação de um novo socket para cada envio. - -### Recepção de conexões - -O método `receive()` permanece aguardando novas conexões através de -`ServerSocket.accept()`. - -Quando uma conexão é aceita: - -O endereço IP do peer é obtido. -Um objeto `TcpConnection` é criado para encapsular o socket. -A conexão é registrada no mapa de conexões. -Caso já exista uma conexão associada ao mesmo endereço, a conexão anterior é encerrada. -Uma tarefa independente de recepção é criada para a nova conexão. - -Esse modelo permite que o servidor aceite múltiplas conexões sem bloquear o -processamento das conexões já existentes. - -### Recepção concorrente - -A recepção das mensagens TCP é realizada de maneira concorrente por meio de um -`ExecutorService`. - -Cada conexão possui uma tarefa própria responsável por receber continuamente as -mensagens. - -O fluxo de recepção é: - -``` -SocketTCP -| -+-- Peer A → TcpConnection → tarefa de recepção -| -+-- Peer B → TcpConnection → tarefa de recepção -| -+-- Peer C → TcpConnection → tarefa de recepção -``` - -Dessa forma, uma conexão bloqueada ou aguardando dados não impede que outras conexões -continuem sendo processadas. - -Quando uma mensagem é recebida por uma `TcpConnection`, ela é encaminhada para todos os -plugins registrados na `MainWindow`. - -O plugin responsável pela funcionalidade deve identificar o tipo da mensagem e -realizar o processamento correspondente. - -### TcpConnection - -A classe TcpConnection encapsula uma conexão TCP individual entre dois peers. - -Ela mantém: - -o Socket utilizado na conexão; -um DataInputStream para recepção; -um DataOutputStream para envio. - -Além de encapsular esses recursos, a classe é responsável pelo framing das mensagens. - -### Framing das mensagens TCP - -A classe `TcpConnection` encapsula uma conexão TCP individual entre dois peers. - -Ela mantém: - -1. o `Socket` utilizado na conexão; -2. um `DataInputStream` para recepção; -3. um `DataOutputStream` para envio. - -Além de encapsular esses recursos, a classe é responsável pelo framing das mensagens. - -Framing das mensagens TCP - -O protocolo TCP fornece um fluxo contínuo de bytes e não preserva os limites das -mensagens enviadas pela aplicação. - -Por esse motivo, é adicionado o tamanho da mensagem antes do conteúdo. - -O formato utilizado é: - -``` -+----------------------+----------------------+ -| tamanho da mensagem | dados da mensagem | -+----------------------+----------------------+ -4 bytes N bytes -``` - -O tamanho é enviado como um `int`, seguido pelos bytes da mensagem. - -No envio, o método `TcpConnection.send()`: - -1. obtém o tamanho do vetor de bytes; -2. escreve o tamanho no `DataOutputStream`; -3. escreve os dados da mensagem; -4. realiza `flush()` no stream. - -O acesso ao stream de saída é sincronizado para evitar que envios concorrentes -misturem seus dados. - -Na recepção, o método `receive()`: - -1. lê o tamanho da mensagem; -2. verifica se o tamanho é válido; -3. lê a quantidade correspondente de bytes; -4. retorna o vetor de bytes completo. - -Esse mecanismo permite que várias mensagens sejam transmitidas pela mesma conexão -TCP sem que o receptor perca a delimitação entre elas. - -### Integração entre TCP e gerenciamento de peers - -O `SocketTCP` implementa a interface PeerListener para acompanhar as alterações na -lista de peers ativos. - -O `HeartbeatManager` mantém a lista de peers atualmente detectados na rede. Quando -essa lista é alterada, o SocketTCP recebe a notificação por meio do método -`onPeersChanged()`. - -O método obtém os endereços IP dos peers atualmente ativos e compara esses endereços -com as conexões TCP existentes. - -Quando uma conexão pertence a um peer que não está mais ativo: - -a conexão é removida do mapa; -a conexão TCP é encerrada; -os recursos associados são liberados. - -Esse mecanismo impede que conexões TCP permaneçam abertas indefinidamente para peers -que já deixaram de participar da rede. - -O fluxo de integração pode ser representado da seguinte forma: -``` -HeartbeatManager -| -| peers ativos alterados -| -v -SocketTCP.onPeersChanged() -| -| compara peers ativos -| -v -+---- peer ativo ------> mantém conexão -| -+---- peer inativo ----> fecha conexão -``` - -### Message - -A classe `Message` representa a estrutura base das mensagens trocadas pela aplicação. - -Todas as mensagens utilizadas pelo sistema devem herdar dessa classe. Ela implementa -`Serializable`, permitindo que objetos de mensagem sejam convertidos em vetores de -bytes para transmissão pela rede. - -A serialização é realizada pelo método `toByteArray()`, que transforma uma instância -da mensagem em uma representação binária enviada pelos mecanismos de comunicação. - -As mensagens específicas devem estender essa classe, adicionando os atributos e -comportamentos necessários para cada funcionalidade. - -A camada de transporte não depende do conteúdo específico das mensagens. Tanto o -UDP quanto o TCP recebem mensagens serializadas como `byte[]`. - -### Heartbeat - -O mecanismo de heartbeat é utilizado para identificar quais usuários estão ativos -na rede. - -A aplicação envia periodicamente uma `HeartbeatMessage` contendo informações do usuário, -um identificador único da instância da aplicação e um timestamp. - -Essas mensagens são transmitidas utilizando a comunicação UDP multicast. - -Quando outra instância recebe uma mensagem de heartbeat, o `SocketUDP` identifica -o tipo da mensagem e encaminha o objeto ao `HeartbeatManager`, juntamente com o endereço -IP de origem. - -O `HeartbeatManager` registra ou atualiza o peer correspondente, utilizando o -identificador da instância para diferenciá-lo das demais. - -Um peer é considerado inativo quando permanece mais de 15 segundos sem receber um novo -heartbeat. O `HeartbeatManager` então remove o peer da lista e notifica todos os -componentes registrados como listeners de mudanças de peers. - -Esses listeners podem incluir diferentes partes da aplicação, como componentes -da interface gráfica, mecanismos de comunicação (como o `SocketTCP`) e também plugins -que desejem reagir à presença ou ausência de usuários na rede. - -Dessa forma, o sistema permite que tanto o núcleo da aplicação quanto extensões -externas sejam notificados sobre alterações no estado da rede, mantendo a arquitetura -flexível e extensível. - -O fluxo completo é: - -``` -HeartbeatManager -| -| cria HeartbeatMessage -| -v -Message.toByteArray() -| -v -SocketUDP.sendMulticast() -| -v -UDP Multicast -| -v -SocketUDP.receive() -| -v -HeartbeatManager.receiveHeartbeat() -| -v -Lista de peers ativos -| -+----> Interface de usuários online -| -+----> SocketTCP (PeerListener) -| -+----> Plugins (PeerListener) -``` - -## Sistema de plugins - -O sistema de plugins é responsável por permitir a extensão das funcionalidades da -aplicação de forma modular, sem a necessidade de alterações no núcleo do sistema. -Ele define um contrato comum que deve ser seguido por todas as extensões, garantindo -que possam ser carregadas dinamicamente e integradas à comunicação e à interface da -aplicação. - -### Interface Plugin - -A interface `Plugin` define o contrato que deve ser implementado por qualquer -extensão da aplicação. - -Um plugin deve fornecer informações básicas de identificação (`name`, -`author` e `version`), inicializar seu estado através de `createPlugin()` e -participar do sistema de comunicação utilizando mensagens derivadas de -`Message`. - -Os principais métodos são: - -#### Identificação - -Os métodos: -- `getName()` -- `getAuthor()` -- `getVersion()` - -fornecem informações utilizadas pela aplicação para identificar o plugin. - -#### Inicialização - -`createPlugin(MainWindow window)` - -É chamado após o carregamento do plugin e permite que ele registre seus -componentes na aplicação, como menus ou elementos de interface. - -#### Comunicação - -`getMessage()` - -Deve retornar uma mensagem utilizada pelo plugin para comunicação com outras -instâncias da aplicação. - -`receiveMessage(byte[] message)` - -É chamado pela aplicação sempre que uma mensagem é recebida. Cada plugin deve -verificar se a mensagem pertence ao seu tipo e realizar o processamento -correspondente. - -### Descoberta de plugins - -Para serem reconhecidos, os plugins devem possuir os arquivos de configuração -do Java Service Provider Interface (SPI): - -``` -MeusPlugins -| -+---META-INF - | - +---services - | - +---pitiupi.models.Plugin -``` - -O arquivo `pitiupi.models.Plugin` deve conter o nome completo das classes que -implementam a interface Plugin: - -``` -MeusPlugins.plugins.NomeDaClasse -``` - -Para serem carregados, os plugins devem estar empacotados como arquivos JAR -e colocados no diretório plugins da aplicação. - -### Carregamento de plugins - -Ao iniciar a aplicação, o `PluginLoader` executa os seguintes passos: - -1. Procura arquivos `.jar` dentro do diretório `plugins`. -2. Cria um `URLClassLoader` contendo os JARs encontrados. -3. Utiliza `ServiceLoader` para localizar classes que implementam - `Plugin`. -4. Instancia cada plugin encontrado. -5. Chama o método `createPlugin(MainWindow)`. -6. Registra o plugin na lista de plugins ativos da aplicação. - -## Interface gráfica - -A interface gráfica da aplicação é baseada em Swing e é centralizada na -classe `MainWindow`. - -Durante a inicialização, cada plugin recebe uma referência para a -`MainWindow` através do método `createPlugin(MainWindow)`. - -Essa referência permite integrar componentes gráficos à aplicação, sendo a -principal forma de extensão a adição de menus à barra de menus: - -``` -JMenu menu = new JMenu("Meu Plugin"); -window.addMenu(menu); -``` - -Visão geral da comunicação - -A arquitetura de comunicação pode ser resumida da seguinte maneira: -``` - +------------------+ - | MainWindow | - +--------+---------+ - | - +--------------------+--------------------+ - | | | - v v v - HeartbeatManager SocketUDP SocketTCP - | | | - | | | - v v v - Heartbeat UDP Multicast TCP Connections - | | - | | - +---------+----------+ - | - v - Plugins - | - v - Message -``` - -O UDP multicast fornece a infraestrutura de descoberta e manutenção da presença dos -peers, além de permitir comunicação multicast e unicast. - -O TCP fornece canais diretos e persistentes entre peers, com uma conexão reutilizável -por endereço. - -Os dois mecanismos encaminham as mensagens destinadas às funcionalidades da aplicação -para os plugins, mantendo separadas as responsabilidades de transporte, infraestrutura -e lógica específica de cada extensão. \ No newline at end of file +Conteúdo técnico fatiado em [docs/documentation/](../../docs/documentation/README.md). diff --git a/pitiupi/docs/PluginTutorial.md b/pitiupi/docs/PluginTutorial.md index 120dcfd..32a15d0 100644 --- a/pitiupi/docs/PluginTutorial.md +++ b/pitiupi/docs/PluginTutorial.md @@ -1,2 +1,5 @@ -# Como criar plugins para o Share my Sheet +# Tutorial de plugin (legado) +Use o tutorial atualizado: + +**[docs/documentation/10_tutorial_plugin.md](../../docs/documentation/10_tutorial_plugin.md)** diff --git a/pitiupi/docs/README.md b/pitiupi/docs/README.md new file mode 100644 index 0000000..82a000b --- /dev/null +++ b/pitiupi/docs/README.md @@ -0,0 +1,10 @@ +# Documentação movida + +A documentação canônica do Pitiupi está na raiz do repositório: + +**[../../docs/README.md](../../docs/README.md)** + +Arquivos legados nesta pasta: + +- [Documentation.md](Documentation.md) — redirecionamento +- [PluginTutorial.md](PluginTutorial.md) — redirecionamento diff --git a/pitiupi/plugins/README.md b/pitiupi/plugins/README.md new file mode 100644 index 0000000..d640687 --- /dev/null +++ b/pitiupi/plugins/README.md @@ -0,0 +1,18 @@ +# Plugins instalados + +O núcleo carrega arquivos `.jar` desta pasta ao iniciar (relativo ao diretório de trabalho — execute `java -jar dist/pitiupi.jar` a partir de `pitiupi/`). + +## Desenvolvimento + +Após compilar os módulos de referência, use symlinks (Linux): + +```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 +``` + +Ordem de build: núcleo (`pitiupi`) primeiro, depois cada plugin. Ver [docs/documentation/00_quickstart.md](../../docs/documentation/00_quickstart.md). + +Os JARs gerados não devem ser commitados — apenas este README e symlinks locais.