diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53d2375 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/pitiupi/build/ +/pitiupi/dist/ +/pitiupi.chat/build/ +/pitiupi.chat/dist/ +/pitiupi.chat/nbproject/private/ +/pitiupi.screenCast/build/ +/pitiupi.screenCast/dist/ diff --git a/pitiupi.chat/build/built-jar.properties b/pitiupi.chat/build/built-jar.properties index 499f65e..8290d48 100644 --- a/pitiupi.chat/build/built-jar.properties +++ b/pitiupi.chat/build/built-jar.properties @@ -1,6 +1,6 @@ -#Thu, 16 Jul 2026 15:21:36 -0300 +#Fri, 17 Jul 2026 17:31:55 -0300 -/home/flavio/NetBeansProjects/pitiupi.chat= +/home/perolanegra/facul/pitiupi/pitiupi.chat= -/home/flavio/NetBeansProjects/pitiupi= +/home/perolanegra/facul/pitiupi/pitiupi= diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class index e78acc9..de16c23 100644 Binary files a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class and b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatMenu.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class index 254570a..3d5ef32 100644 Binary files a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class and b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow$1.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class index 4d4bde2..6b44117 100644 Binary files a/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class and b/pitiupi.chat/build/classes/pitiupi/chat/GUI/ChatWindow.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class b/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class index de14b13..869eaed 100644 Binary files a/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class and b/pitiupi.chat/build/classes/pitiupi/chat/net/ChatMessage.class differ diff --git a/pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class b/pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class index b5d0c5d..7e4c905 100644 Binary files a/pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class and b/pitiupi.chat/build/classes/pitiupi/chat/plugin/ChatPlugin.class differ diff --git a/pitiupi.chat/dist/pitiupi.chat.jar b/pitiupi.chat/dist/pitiupi.chat.jar index 78438b7..5ddc242 100644 Binary files a/pitiupi.chat/dist/pitiupi.chat.jar and b/pitiupi.chat/dist/pitiupi.chat.jar differ diff --git a/pitiupi.chat/nbproject/project.properties b/pitiupi.chat/nbproject/project.properties index b87aa66..61584ac 100644 --- a/pitiupi.chat/nbproject/project.properties +++ b/pitiupi.chat/nbproject/project.properties @@ -47,8 +47,8 @@ javac.modulepath= javac.processormodulepath= javac.processorpath=\ ${javac.classpath} -javac.source=25 -javac.target=25 +javac.source=21 +javac.target=21 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java b/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java index f894a65..99b59eb 100644 --- a/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java +++ b/pitiupi.chat/src/pitiupi/chat/GUI/ChatWindow.java @@ -5,18 +5,16 @@ */ package pitiupi.chat.GUI; -import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.logging.Level; -import java.util.logging.Logger; import pitiupi.chat.net.ChatMessage; -import pitiupi.GUI.MainWindow; +import pitiupi.plugin.PitiupiFacade; import pitiupi.net.Message; /** * * @author flavio + * @author tony */ public class ChatWindow extends javax.swing.JDialog { @@ -29,10 +27,10 @@ public class ChatWindow extends javax.swing.JDialog { private javax.swing.JSplitPane jSplitPane1; private javax.swing.JTextArea jTextArea1; - private final MainWindow mainWindow; + private final PitiupiFacade pitiupi; - public ChatWindow(MainWindow mainWindow) { - this.mainWindow = mainWindow; + public ChatWindow(PitiupiFacade pitiupi) { + this.pitiupi = pitiupi; initComponents(); } @@ -94,17 +92,13 @@ public class ChatWindow extends javax.swing.JDialog { if (jTextArea1.getText().trim().length() == 0) { return; } - ChatMessage message = new ChatMessage(mainWindow.getName(), jTextArea1.getText()); + ChatMessage message = new ChatMessage(pitiupi.getUserName(), jTextArea1.getText()); this.sendChatMessage(message); jTextArea1.setText(""); } public void sendChatMessage(Message message) { - try { - mainWindow.getSocket().send(message.toByteArray()); - } catch (IOException ex) { - Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex); - } + pitiupi.send(message); } public void receiveChatMessage(ChatMessage message) { diff --git a/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java b/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java index 44f3911..32b875f 100644 --- a/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java +++ b/pitiupi.chat/src/pitiupi/chat/plugin/ChatPlugin.java @@ -7,7 +7,7 @@ package pitiupi.chat.plugin; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; -import pitiupi.GUI.MainWindow; +import pitiupi.plugin.PitiupiFacade; import pitiupi.chat.GUI.ChatMenu; import pitiupi.chat.GUI.ChatWindow; import pitiupi.chat.net.ChatMessage; @@ -17,20 +17,18 @@ import pitiupi.plugin.Plugin; /** * * @author flavio + * @author tony */ public class ChatPlugin implements Plugin { private ChatWindow chatWindow; - private MainWindow mainWindow; - - public ChatPlugin() { - } + private PitiupiFacade pitiupi; @Override - public void createPlugin(MainWindow mainWindow) { - this.mainWindow = mainWindow; - this.chatWindow = new ChatWindow(mainWindow); - this.mainWindow.addMenu(new ChatMenu(chatWindow)); + public void createPlugin(PitiupiFacade pitiupi) { + this.pitiupi = pitiupi; + this.chatWindow = new ChatWindow(pitiupi); + this.pitiupi.addMenu(new ChatMenu(chatWindow)); } @Override diff --git a/pitiupi.screenCast/build/built-jar.properties b/pitiupi.screenCast/build/built-jar.properties index 6898243..cb608af 100644 --- a/pitiupi.screenCast/build/built-jar.properties +++ b/pitiupi.screenCast/build/built-jar.properties @@ -1,6 +1,6 @@ -#Thu, 16 Jul 2026 15:21:39 -0300 +#Thu, 16 Jul 2026 17:43:45 -0300 -/home/flavio/NetBeansProjects/pitiupi.screenCast= +/home/perolanegra/facul/2.26/fls/pitiupi/pitiupi.screenCast= -/home/flavio/NetBeansProjects/pitiupi= +/home/perolanegra/facul/2.26/fls/pitiupi/pitiupi= diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class index 4c002f1..6125405 100644 Binary files a/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class and b/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastMenu.class differ diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class index 490ff3f..5c3b088 100644 Binary files a/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class and b/pitiupi.screenCast/build/classes/pitiupi/screenCast/GUI/ScreenCastWindow.class differ diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/AlarmClock.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/AlarmClock.class index 40e9f43..4aee013 100644 Binary files a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/AlarmClock.class and b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/AlarmClock.class differ diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ImageTransformation.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ImageTransformation.class index b4c1d43..af842e8 100644 Binary files a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ImageTransformation.class and b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ImageTransformation.class differ diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ScreenShot.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ScreenShot.class index 3cde756..17d7d73 100644 Binary files a/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ScreenShot.class and b/pitiupi.screenCast/build/classes/pitiupi/screenCast/control/ScreenShot.class differ diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class index dc8a7ea..7f1e06c 100644 Binary files a/pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class and b/pitiupi.screenCast/build/classes/pitiupi/screenCast/net/ScreenCastMessage.class differ diff --git a/pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class b/pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class index 77a7e76..34f7f46 100644 Binary files a/pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class and b/pitiupi.screenCast/build/classes/pitiupi/screenCast/plugin/ScreenCastPlugin.class differ 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/dist/lib/pitiupi.jar b/pitiupi.screenCast/dist/lib/pitiupi.jar deleted file mode 100644 index 85ec1b8..0000000 Binary files a/pitiupi.screenCast/dist/lib/pitiupi.jar and /dev/null differ diff --git a/pitiupi.screenCast/dist/pitiupi.screenCast.jar b/pitiupi.screenCast/dist/pitiupi.screenCast.jar index 06682ea..863132f 100644 Binary files a/pitiupi.screenCast/dist/pitiupi.screenCast.jar and b/pitiupi.screenCast/dist/pitiupi.screenCast.jar differ diff --git a/pitiupi.screenCast/nbproject/project.properties b/pitiupi.screenCast/nbproject/project.properties index 59c1b5f..38e2f1b 100644 --- a/pitiupi.screenCast/nbproject/project.properties +++ b/pitiupi.screenCast/nbproject/project.properties @@ -45,8 +45,8 @@ javac.modulepath= javac.processormodulepath= javac.processorpath=\ ${javac.classpath} -javac.source=25 -javac.target=25 +javac.source=21 +javac.target=21 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/pitiupi/build/classes/.netbeans_automatic_build b/pitiupi/build/classes/.netbeans_automatic_build deleted file mode 100644 index e69de29..0000000 diff --git a/pitiupi/build/classes/.netbeans_update_resources b/pitiupi/build/classes/.netbeans_update_resources deleted file mode 100644 index e69de29..0000000 diff --git a/pitiupi/build/classes/pitiupi/GUI/Login.class b/pitiupi/build/classes/pitiupi/GUI/Login.class index b5380ba..2488cd0 100644 Binary files a/pitiupi/build/classes/pitiupi/GUI/Login.class and b/pitiupi/build/classes/pitiupi/GUI/Login.class differ diff --git a/pitiupi/build/classes/pitiupi/GUI/MainWindow.class b/pitiupi/build/classes/pitiupi/GUI/MainWindow.class index e7780db..2eac6d8 100644 Binary files a/pitiupi/build/classes/pitiupi/GUI/MainWindow.class and b/pitiupi/build/classes/pitiupi/GUI/MainWindow.class differ diff --git a/pitiupi/build/classes/pitiupi/GUI/MenuBar.class b/pitiupi/build/classes/pitiupi/GUI/MenuBar.class index 71aaa0d..10b0769 100644 Binary files a/pitiupi/build/classes/pitiupi/GUI/MenuBar.class and b/pitiupi/build/classes/pitiupi/GUI/MenuBar.class differ diff --git a/pitiupi/build/classes/pitiupi/Main$1.class b/pitiupi/build/classes/pitiupi/Main$1.class index ab626d0..0e02556 100644 Binary files a/pitiupi/build/classes/pitiupi/Main$1.class and b/pitiupi/build/classes/pitiupi/Main$1.class differ diff --git a/pitiupi/build/classes/pitiupi/Main.class b/pitiupi/build/classes/pitiupi/Main.class index c1bcbbd..bf19abe 100644 Binary files a/pitiupi/build/classes/pitiupi/Main.class and b/pitiupi/build/classes/pitiupi/Main.class differ diff --git a/pitiupi/build/classes/pitiupi/control/PluginLoader.class b/pitiupi/build/classes/pitiupi/control/PluginLoader.class index 97ef0bc..5a4363d 100644 Binary files a/pitiupi/build/classes/pitiupi/control/PluginLoader.class and b/pitiupi/build/classes/pitiupi/control/PluginLoader.class differ diff --git a/pitiupi/build/classes/pitiupi/net/Message.class b/pitiupi/build/classes/pitiupi/net/Message.class index 4033d96..96a0002 100644 Binary files a/pitiupi/build/classes/pitiupi/net/Message.class and b/pitiupi/build/classes/pitiupi/net/Message.class differ diff --git a/pitiupi/build/classes/pitiupi/net/Socket.class b/pitiupi/build/classes/pitiupi/net/Socket.class index d182b43..9a1e1bb 100644 Binary files a/pitiupi/build/classes/pitiupi/net/Socket.class and b/pitiupi/build/classes/pitiupi/net/Socket.class differ diff --git a/pitiupi/build/classes/pitiupi/plugin/Plugin.class b/pitiupi/build/classes/pitiupi/plugin/Plugin.class index 13963a8..eee5a23 100644 Binary files a/pitiupi/build/classes/pitiupi/plugin/Plugin.class and b/pitiupi/build/classes/pitiupi/plugin/Plugin.class differ diff --git a/pitiupi/dist/pitiupi.jar b/pitiupi/dist/pitiupi.jar index 85ec1b8..f4b8365 100644 Binary files a/pitiupi/dist/pitiupi.jar and b/pitiupi/dist/pitiupi.jar differ diff --git a/pitiupi/nbproject/private/private.properties b/pitiupi/nbproject/private/private.properties index 2a5dca8..093bd1b 100644 --- a/pitiupi/nbproject/private/private.properties +++ b/pitiupi/nbproject/private/private.properties @@ -5,4 +5,4 @@ do.jlink=false javac.debug=true javadoc.preview=true jlink.strip=false -user.properties.file=/home/flavio/snap/netbeans/145/build.properties +user.properties.file=/home/perolanegra/snap/netbeans/145/build.properties diff --git a/pitiupi/nbproject/private/private.xml b/pitiupi/nbproject/private/private.xml index b64f1b3..6807a2b 100644 --- a/pitiupi/nbproject/private/private.xml +++ b/pitiupi/nbproject/private/private.xml @@ -2,9 +2,6 @@ - - file:/home/flavio/NetBeansProjects/pitiupi/src/pitiupi/control/PluginManager.java - file:/home/flavio/NetBeansProjects/pitiupi/src/pitiupi/control/ImageTransformation.java - + diff --git a/pitiupi/nbproject/project.properties b/pitiupi/nbproject/project.properties index 19c843c..8b9f096 100644 --- a/pitiupi/nbproject/project.properties +++ b/pitiupi/nbproject/project.properties @@ -46,8 +46,8 @@ javac.modulepath= javac.processormodulepath= javac.processorpath=\ ${javac.classpath} -javac.source=25 -javac.target=25 +javac.source=21 +javac.target=21 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir} diff --git a/pitiupi/plugins/pitiupi.screenCast.jar b/pitiupi/plugins/pitiupi.screenCast.jar deleted file mode 120000 index e6a0dc7..0000000 --- a/pitiupi/plugins/pitiupi.screenCast.jar +++ /dev/null @@ -1 +0,0 @@ -../../pitiupi.screenCast/dist/pitiupi.screenCast.jar \ No newline at end of file diff --git a/pitiupi/src/pitiupi/GUI/MainWindow.java b/pitiupi/src/pitiupi/GUI/MainWindow.java index bcd03fe..54e561d 100644 --- a/pitiupi/src/pitiupi/GUI/MainWindow.java +++ b/pitiupi/src/pitiupi/GUI/MainWindow.java @@ -11,6 +11,7 @@ import java.util.List; import javax.swing.JMenu; import pitiupi.control.PluginLoader; import pitiupi.plugin.Plugin; +import pitiupi.control.HeartbeatManager; /** * @@ -23,6 +24,8 @@ public class MainWindow extends javax.swing.JFrame { private javax.swing.JLabel status; private javax.swing.JPanel statusPanel; private javax.swing.JTabbedPane tabbedPane; + private HeartbeatManager heartbeatManager; + private OnlineUsersPanel onlineUsersPanel; private Socket socket; @@ -63,6 +66,12 @@ public class MainWindow extends javax.swing.JFrame { this.socket = new Socket(this); this.socket.start(); + + this.heartbeatManager = new HeartbeatManager(this); + this.onlineUsersPanel = new OnlineUsersPanel(); + this.heartbeatManager.addPeerListener(this.onlineUsersPanel); + this.getContentPane().add(this.onlineUsersPanel, java.awt.BorderLayout.LINE_END); + this.heartbeatManager.start(); this.setSize(new java.awt.Dimension(1024, 768)); this.pluginManager = new PluginLoader(this); @@ -76,6 +85,10 @@ public class MainWindow extends javax.swing.JFrame { System.exit(0); } + public HeartbeatManager getHeartbeatManager() { + return heartbeatManager; + } + public String getUserName(){ return this.userName; } diff --git a/pitiupi/src/pitiupi/GUI/OnlineUsersPanel.java b/pitiupi/src/pitiupi/GUI/OnlineUsersPanel.java new file mode 100644 index 0000000..690a362 --- /dev/null +++ b/pitiupi/src/pitiupi/GUI/OnlineUsersPanel.java @@ -0,0 +1,39 @@ +package pitiupi.GUI; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.util.List; +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import pitiupi.control.PeerInfo; +import pitiupi.control.PeerListener; + +public class OnlineUsersPanel extends JPanel implements PeerListener { + + private final DefaultListModel listModel; + private final JList userList; + + public OnlineUsersPanel() { + setLayout(new BorderLayout()); + setBorder(BorderFactory.createTitledBorder("Online")); + setPreferredSize(new Dimension(160, 0)); + + listModel = new DefaultListModel<>(); + userList = new JList<>(listModel); + add(new JScrollPane(userList), BorderLayout.CENTER); + } + + @Override + public void onPeersChanged(List peers) { + SwingUtilities.invokeLater(() -> { + listModel.clear(); + for (PeerInfo peer : peers) { + listModel.addElement(peer.toString()); + } + }); + } +} \ No newline at end of file diff --git a/pitiupi/src/pitiupi/control/HeartbeatManager.java b/pitiupi/src/pitiupi/control/HeartbeatManager.java new file mode 100644 index 0000000..865cb73 --- /dev/null +++ b/pitiupi/src/pitiupi/control/HeartbeatManager.java @@ -0,0 +1,98 @@ +package pitiupi.control; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import pitiupi.GUI.MainWindow; +import pitiupi.net.HeartbeatMessage; + +public class HeartbeatManager { + + private static final long HEARTBEAT_INTERVAL_MS = 5000; + private static final long PEER_TIMEOUT_MS = 15000; // ~3 batimentos perdidos + + private final MainWindow mainWindow; + private final Map peers = new ConcurrentHashMap<>(); + private final List listeners = new CopyOnWriteArrayList<>(); + private ScheduledExecutorService scheduler; + + public HeartbeatManager(MainWindow mainWindow) { + this.mainWindow = mainWindow; + } + + public void start() { + scheduler = Executors.newScheduledThreadPool(1); + scheduler.scheduleAtFixedRate(this::announce, 0, HEARTBEAT_INTERVAL_MS, TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate(this::checkTimeouts, HEARTBEAT_INTERVAL_MS, HEARTBEAT_INTERVAL_MS, TimeUnit.MILLISECONDS); + } + + public void stop() { + if (scheduler != null) { + scheduler.shutdownNow(); + } + } + + private void announce() { + try { + HeartbeatMessage msg = new HeartbeatMessage(mainWindow.getUserName()); + mainWindow.getSocket().send(msg.toByteArray()); + } catch (IOException ex) { + Logger.getLogger(HeartbeatManager.class.getName()).log(Level.WARNING, "Falha ao enviar heartbeat", ex); + } + } + + // Chamado pelo Socket quando um pacote é identificado como heartbeat + public void receiveHeartbeat(HeartbeatMessage msg, InetAddress from) { + // ignora o próprio heartbeat (multicast normalmente ecoa pro remetente) + if (msg.getUserName().equals(mainWindow.getUserName())) { + return; + } + + String key = from.getHostAddress() + "#" + msg.getUserName(); + boolean isNew = !peers.containsKey(key); + + PeerInfo peer = peers.computeIfAbsent(key, k -> new PeerInfo(msg.getUserName(), from, msg.getTimestamp())); + peer.touch(System.currentTimeMillis()); + + if (isNew) { + notifyListeners(); + } + } + + private void checkTimeouts() { + long now = System.currentTimeMillis(); + boolean changed = peers.values().removeIf(p -> now - p.getLastSeen() > PEER_TIMEOUT_MS); + if (changed) { + notifyListeners(); + } + } + + private void notifyListeners() { + List snapshot = new ArrayList<>(peers.values()); + for (PeerListener l : listeners) { + l.onPeersChanged(snapshot); + } + } + + public void addPeerListener(PeerListener l) { + listeners.add(l); + l.onPeersChanged(new ArrayList<>(peers.values())); + } + + public void removePeerListener(PeerListener l) { + listeners.remove(l); + } + + public List getPeers() { + return new ArrayList<>(peers.values()); + } +} diff --git a/pitiupi/src/pitiupi/control/PeerInfo.java b/pitiupi/src/pitiupi/control/PeerInfo.java new file mode 100644 index 0000000..ce855fc --- /dev/null +++ b/pitiupi/src/pitiupi/control/PeerInfo.java @@ -0,0 +1,37 @@ +package pitiupi.control; + +import java.net.InetAddress; + +public class PeerInfo { + + private final String userName; + private final InetAddress address; + private volatile long lastSeen; + + public PeerInfo(String userName, InetAddress address, long lastSeen) { + this.userName = userName; + this.address = address; + this.lastSeen = lastSeen; + } + + public String getUserName() { + return userName; + } + + public InetAddress getAddress() { + return address; + } + + public long getLastSeen() { + return lastSeen; + } + + public void touch(long timestamp) { + this.lastSeen = timestamp; + } + + @Override + public String toString() { + return userName + " (" + address.getHostAddress() + ")"; + } +} diff --git a/pitiupi/src/pitiupi/control/PeerListener.java b/pitiupi/src/pitiupi/control/PeerListener.java new file mode 100644 index 0000000..aa9ed74 --- /dev/null +++ b/pitiupi/src/pitiupi/control/PeerListener.java @@ -0,0 +1,7 @@ +package pitiupi.control; + +import java.util.List; + +public interface PeerListener { + void onPeersChanged(List peers); +} diff --git a/pitiupi/src/pitiupi/control/PluginLoader.java b/pitiupi/src/pitiupi/control/PluginLoader.java index 386724a..d7440c4 100644 --- a/pitiupi/src/pitiupi/control/PluginLoader.java +++ b/pitiupi/src/pitiupi/control/PluginLoader.java @@ -15,10 +15,11 @@ import java.util.Vector; import pitiupi.GUI.MainWindow; import pitiupi.Main; import pitiupi.plugin.Plugin; - +import pitiupi.plugin.PitiupiFacade; /** * * @author flavio + * @author tony */ public class PluginLoader { @@ -55,12 +56,14 @@ public class PluginLoader { // 4. Locate and instantiate all classes implementing the Plugin interface ServiceLoader serviceLoader = ServiceLoader.load(Plugin.class, pluginClassLoader); - System.out.println("\n--- Executing Discovered Plugins ---" + serviceLoader.findFirst()); - for (Plugin plugin : serviceLoader) { - System.out.println("Loading: " + plugin.getName()); - plugin.createPlugin(this.mainWindow); - this.mainWindow.getPlugins().add(plugin); - } + PitiupiFacade facade = new PitiupiFacade(this.mainWindow); + + System.out.println("\n--- Executing Discovered Plugins ---" + serviceLoader.findFirst()); + for (Plugin plugin : serviceLoader) { + System.out.println("Loading: " + plugin.getName()); + plugin.createPlugin(facade); + this.mainWindow.getPlugins().add(plugin); + } } catch (MalformedURLException e) { System.out.println(e.toString()); diff --git a/pitiupi/src/pitiupi/net/HeartbeatMessage.java b/pitiupi/src/pitiupi/net/HeartbeatMessage.java new file mode 100644 index 0000000..3b2c371 --- /dev/null +++ b/pitiupi/src/pitiupi/net/HeartbeatMessage.java @@ -0,0 +1,20 @@ +package pitiupi.net; + +public class HeartbeatMessage extends Message { + + private final String userName; + private final long timestamp; + + public HeartbeatMessage(String userName) { + this.userName = userName; + this.timestamp = System.currentTimeMillis(); + } + + public String getUserName() { + return userName; + } + + public long getTimestamp() { + return timestamp; + } +} diff --git a/pitiupi/src/pitiupi/net/Message.java b/pitiupi/src/pitiupi/net/Message.java index 3b5966b..b53b034 100644 --- a/pitiupi/src/pitiupi/net/Message.java +++ b/pitiupi/src/pitiupi/net/Message.java @@ -1,4 +1,4 @@ -/* + /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. diff --git a/pitiupi/src/pitiupi/net/Socket.java b/pitiupi/src/pitiupi/net/Socket.java index 8710697..8c85fe2 100644 --- a/pitiupi/src/pitiupi/net/Socket.java +++ b/pitiupi/src/pitiupi/net/Socket.java @@ -17,10 +17,13 @@ import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger; import pitiupi.plugin.Plugin; - +import java.net.NetworkInterface; +import java.net.InetSocketAddress; +import pitiupi.net.HeartbeatMessage; // lib /** * * @author flavio + * @author tony */ public class Socket extends Thread { @@ -41,7 +44,45 @@ public class Socket extends Thread { multicastSocket.setSendBufferSize(256000); multicastSocket.setReceiveBufferSize(256000); multicastSocket.setReuseAddress(true); - multicastSocket.joinGroup(address); + System.out.println("Endereço local: " + multicastSocket.getLocalAddress()); + System.out.println("Interface: " + multicastSocket.getNetworkInterface()); + //InetAddress local = InetAddress.getLocalHost(); + + NetworkInterface nif = null; + + for (NetworkInterface ni : java.util.Collections.list( + NetworkInterface.getNetworkInterfaces())) { + + if (ni.isUp() + && ni.supportsMulticast() + && !ni.isLoopback()) { + + nif = ni; + break; + } + } + if (nif != null) { + System.out.println("Interface escolhida:"); + System.out.println("Nome: " + nif.getName()); + System.out.println("Descrição: " + nif.getDisplayName()); + System.out.println("Ativa: " + nif.isUp()); + System.out.println("Multicast: " + nif.supportsMulticast()); + + System.out.println("Endereços IP:"); + + for (InetAddress ip : java.util.Collections.list(nif.getInetAddresses())) { + System.out.println(" " + ip.getHostAddress()); + } + } else { + System.out.println("Nenhuma interface multicast encontrada"); + } + multicastSocket.joinGroup( + new InetSocketAddress(address, main.getPort()), + nif + ); + System.out.println("nif: " + nif); + + // multicastSocket.joinGroup(address); } catch (IOException ex) { System.out.println("There is no socket connection. Sorry."); System.out.println(ex.toString()); @@ -51,15 +92,27 @@ public class Socket extends Thread { public void send(byte[] msg) throws IOException { DatagramPacket msgPacket; msgPacket = new DatagramPacket(msg, msg.length, this.address, this.main.getPort()); + + System.out.println("Enviando pacote"); + System.out.println("Destino: " + address); + System.out.println("Porta: " + this.main.getPort()); + System.out.println("Bytes: " + msg.length); + multicastSocket.send(msgPacket); } - +//------------------------------------------------------------------------------------------------------- public void receive() throws UnknownHostException, IOException, ClassNotFoundException { byte[] buf = new byte[256000]; while (true) { - // Receive the information and print it. DatagramPacket msgPacket = new DatagramPacket(buf, buf.length); multicastSocket.receive(msgPacket); + + HeartbeatMessage heartbeat = tryParseHeartbeat(msgPacket.getData()); + if (heartbeat != null) { + main.getHeartbeatManager().receiveHeartbeat(heartbeat, msgPacket.getAddress()); + continue; + } + for (Plugin plugin : main.getPlugins()) { System.out.println(msgPacket.getAddress().toString()); plugin.receiveMessage(msgPacket.getData()); @@ -67,6 +120,17 @@ public class Socket extends Thread { } } + private HeartbeatMessage tryParseHeartbeat(byte[] data) { + try { + ByteArrayInputStream bais = new ByteArrayInputStream(data); + ObjectInput in = new ObjectInputStream(bais); + Object obj = in.readObject(); + return (obj instanceof HeartbeatMessage) ? (HeartbeatMessage) obj : null; + } catch (IOException | ClassNotFoundException | ClassCastException ex) { + return null; + } + } +//------------------------------------------------------------------------------------------------------------------ @Override public void run() { try { diff --git a/pitiupi/src/pitiupi/plugin/PitiupiFacade.java b/pitiupi/src/pitiupi/plugin/PitiupiFacade.java new file mode 100644 index 0000000..f68508d --- /dev/null +++ b/pitiupi/src/pitiupi/plugin/PitiupiFacade.java @@ -0,0 +1,35 @@ +package pitiupi.plugin; + +import java.io.IOException; +import javax.swing.JMenu; +import pitiupi.GUI.MainWindow; +import pitiupi.net.Message; + +public class PitiupiFacade { + + private final MainWindow mainWindow; + + public PitiupiFacade(MainWindow mainWindow) { + this.mainWindow = mainWindow; + } + + public void addMenu(JMenu menu) { + mainWindow.addMenu(menu); + } + + public void send(Message message) { + try { + mainWindow.getSocket().send(message.toByteArray()); + } catch (IOException ex) { + System.out.println("Falha ao enviar mensagem: " + ex); + } + } + + public String getUserName() { + return mainWindow.getUserName(); + } + + public int getPort() { + return mainWindow.getPort(); + } +} diff --git a/pitiupi/src/pitiupi/plugin/Plugin.java b/pitiupi/src/pitiupi/plugin/Plugin.java index 7a6b711..f2a6e78 100644 --- a/pitiupi/src/pitiupi/plugin/Plugin.java +++ b/pitiupi/src/pitiupi/plugin/Plugin.java @@ -4,20 +4,19 @@ */ package pitiupi.plugin; -import javax.swing.JMenu; -import pitiupi.GUI.MainWindow; import pitiupi.net.Message; /** * * @author flavio + * @author tony */ public interface Plugin { public String getName(); public String getAuthor(); public String getVersion(); - public void createPlugin(MainWindow window); + public void createPlugin(PitiupiFacade pitiupi); public Message getMessage(); public void receiveMessage(byte[] message); -} \ No newline at end of file +}