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
+}