diff --git a/pitiupi/src/pitiupi/GUI/MainWindow.java b/pitiupi/src/pitiupi/GUI/MainWindow.java
index cc72db4..9d99aa7 100644
--- a/pitiupi/src/pitiupi/GUI/MainWindow.java
+++ b/pitiupi/src/pitiupi/GUI/MainWindow.java
@@ -5,13 +5,11 @@
*/
package pitiupi.GUI;
-import pitiupi.net.tcp.SocketTCP;
-import pitiupi.net.udp.SocketUDP;
-import java.util.ArrayList;
-import java.util.List;
+import pitiupi.control.ConnectionManager;
+import pitiupi.control.PluginManager;
+
import javax.swing.JMenu;
-import pitiupi.control.PluginLoader;
-import pitiupi.plugin.Plugin;
+
import pitiupi.control.HeartbeatManager;
/**
@@ -36,20 +34,12 @@ public class MainWindow extends javax.swing.JFrame {
private javax.swing.JPanel statusPanel;
private javax.swing.JTabbedPane tabbedPane;
- private HeartbeatManager heartbeatManager;
private OnlineUsersPanel onlineUsersPanel;
-
- private SocketUDP socketUDP;
- private SocketTCP socketTCP;
-
private String userName;
- private int port;
- private String pitiupiIdentifier;
-
- private PluginLoader pluginManager;
- private final List plugins;
+ private ConnectionManager connectionManager;
+ private PluginManager pluginManager;
/**
* Cria a janela principal da aplicação.
@@ -59,22 +49,18 @@ public class MainWindow extends javax.swing.JFrame {
*/
public MainWindow(String userName, int port) {
this.userName = userName;
- this.port = port;
- this.pitiupiIdentifier = "Pitiupi.Alice.2026";
- this.menuBar = new MenuBar(this);
- this.plugins = new ArrayList<>();
- this.initComponents();
+
+ pluginManager = new PluginManager(this);
+ loadPlugins();
+
+ connectionManager = new ConnectionManager(this, pluginManager, port);
+
+ menuBar = new MenuBar(this);
+
+ initComponents();
}
private void initComponents() {
- initGUI();
- initSocket();
- initHeartbeat();
- initPlugins();
- this.setSize(new java.awt.Dimension(1024, 768));
- }
-
- private void initGUI() {
this.setJMenuBar(menuBar);
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.setTitle("Share My Sheet");
@@ -86,34 +72,19 @@ public class MainWindow extends javax.swing.JFrame {
jScrollPane1.setViewportView(tabbedPane);
statusPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));
- status.setText("Connected on port " + this.port + " name " + this.userName);
+ updateStatus();
statusPanel.add(status);
this.getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
this.getContentPane().add(statusPanel, java.awt.BorderLayout.PAGE_END);
- this.pack();
- }
-
- private void initSocket() {
- this.socketUDP = new SocketUDP(this);
- this.socketTCP = new SocketTCP(this);
-
- this.socketUDP.start();
- this.socketTCP.start();
- }
-
- private void initHeartbeat() {
- this.heartbeatManager = new HeartbeatManager(this);
this.onlineUsersPanel = new OnlineUsersPanel();
- this.heartbeatManager.addPeerListener(this.onlineUsersPanel);
+ this.connectionManager.addPeerListener(onlineUsersPanel);
this.getContentPane().add(this.onlineUsersPanel, java.awt.BorderLayout.LINE_END);
- this.heartbeatManager.start();
- }
- private void initPlugins() {
- this.pluginManager = new PluginLoader(this);
- this.pluginManager.loadPlugins();
+ this.pack();
+
+ this.setSize(new java.awt.Dimension(1024, 768));
}
public void exit() {
@@ -122,65 +93,29 @@ public class MainWindow extends javax.swing.JFrame {
System.exit(0);
}
- public HeartbeatManager getHeartbeatManager() {
- return heartbeatManager;
- }
-
public String getUserName(){
return this.userName;
}
- public String getIdentifier(){
- return this.pitiupiIdentifier;
+ public ConnectionManager getConnectionManager() {
+ return connectionManager;
+ }
+
+ public void loadPlugins() {
+ pluginManager.loadPlugins();
}
public void addMenu(JMenu menu) {
this.menuBar.addPlugin(menu);
}
- public int getPort() {
- return this.port;
- }
-
- public SocketUDP getSocketUDP() {
- return this.socketUDP;
- }
-
- public SocketTCP getSocketTCP() {
- return this.socketTCP;
- }
-
- public List getPlugins() {
- return plugins;
- }
-
public void setUserName(String userName) {
this.userName = userName;
updateStatus();
}
- public void setPort(int port) {
- this.port = port;
- reconnect();
- updateStatus();
- }
-
private void updateStatus() {
- this.status.setText("Connected on port " + this.port + " name " + this.userName);
+ this.status.setText("Connected on port " + connectionManager + " name " + this.userName);
}
- private void reconnect() {
- if (this.socketUDP != null) {
- this.socketUDP.close();
- }
- if (this.socketTCP != null) {
- this.socketTCP.close();
- }
-
- this.socketUDP = new SocketUDP(this);
- this.socketTCP = new SocketTCP(this);
-
- this.socketUDP.start();
- this.socketTCP.start();
- }
}
diff --git a/pitiupi/src/pitiupi/GUI/MenuBar.java b/pitiupi/src/pitiupi/GUI/MenuBar.java
index db4ca35..4e517a8 100644
--- a/pitiupi/src/pitiupi/GUI/MenuBar.java
+++ b/pitiupi/src/pitiupi/GUI/MenuBar.java
@@ -80,7 +80,7 @@ public class MenuBar extends JMenuBar {
login.setVisible(true);
mainWindow.setUserName(login.getName());
- mainWindow.setPort(login.getPort());
+ mainWindow.getConnectionManager().setPort(login.getPort());
login.dispose();
}
diff --git a/pitiupi/src/pitiupi/control/ConnectionManager.java b/pitiupi/src/pitiupi/control/ConnectionManager.java
new file mode 100644
index 0000000..4b744d8
--- /dev/null
+++ b/pitiupi/src/pitiupi/control/ConnectionManager.java
@@ -0,0 +1,104 @@
+package pitiupi.control;
+
+import pitiupi.GUI.MainWindow;
+import pitiupi.net.HeartbeatMessage;
+import pitiupi.net.Message;
+import pitiupi.net.tcp.SocketTCP;
+import pitiupi.net.tcp.TcpConnection;
+import pitiupi.net.udp.SocketUDP;
+
+import java.net.InetAddress;
+
+public class ConnectionManager {
+ private final String pitiupiIdentifier;
+
+ private PluginManager pluginManager;
+
+ private HeartbeatManager heartbeatManager;
+
+ private SocketTCP socketTCP;
+ private SocketUDP socketUDP;
+ private int port;
+
+ public ConnectionManager(MainWindow main, PluginManager pluginManager, int port) {
+ this.pluginManager = pluginManager;
+ this.port = port;
+
+ pitiupiIdentifier = "Pitiupi.Alice.2026";
+
+ reconnect();
+
+ heartbeatManager = new HeartbeatManager(main, this);
+ heartbeatManager.start();
+ }
+
+ public TcpConnection connectPluginTcp(InetAddress destinationAdress, String senderId, String receiverId) {
+ return socketTCP.createPrivateConnection(destinationAdress, senderId, receiverId);
+ }
+
+ public boolean sendTcp(Message message, InetAddress destinationAddress) {
+ return socketTCP.send(message, destinationAddress);
+ }
+
+ public boolean sendUdpUnicast(Message message, InetAddress destinationAddress) {
+ try {
+ socketUDP.sendUnicast(message, destinationAddress);
+ return true;
+ } catch (Exception ex) {
+ return false;
+ }
+ }
+
+ public boolean sendUdpMulticast(Message message) {
+ try {
+ socketUDP.sendMulticast(message);
+ return true;
+ } catch (Exception ex) {
+ return false;
+ }
+ }
+
+ public void broadcastLocal(Message message) {
+ pluginManager.handlePublicMessage(message);
+ }
+
+ public boolean sendLocal(byte[] message, String receiverId) {
+ return pluginManager.handlePrivateMessage(message, receiverId);
+ }
+
+ public void addPeerListener(PeerListener peerListener) {
+ heartbeatManager.addPeerListener(peerListener);
+ }
+
+ public void receiveHeartbeat(HeartbeatMessage message, InetAddress destinationAddress) {
+ heartbeatManager.receiveHeartbeat(message, destinationAddress);
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ reconnect();
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getIdentifier(){
+ return this.pitiupiIdentifier;
+ }
+
+ private void reconnect() {
+ if (this.socketUDP != null) {
+ this.socketUDP.close();
+ }
+ if (this.socketTCP != null) {
+ this.socketTCP.close();
+ }
+
+ this.socketUDP = new SocketUDP(this, pluginManager);
+ this.socketTCP = new SocketTCP(this, pluginManager);
+
+ this.socketUDP.start();
+ this.socketTCP.start();
+ }
+}
diff --git a/pitiupi/src/pitiupi/control/HeartbeatManager.java b/pitiupi/src/pitiupi/control/HeartbeatManager.java
index 1cfa480..bbdf84e 100644
--- a/pitiupi/src/pitiupi/control/HeartbeatManager.java
+++ b/pitiupi/src/pitiupi/control/HeartbeatManager.java
@@ -30,6 +30,7 @@ public class HeartbeatManager {
private static final long PEER_TIMEOUT_MS = 15000; // ~3 batimentos perdidos
private final MainWindow mainWindow;
+ private final ConnectionManager connectionManager;
private final Map peers = new ConcurrentHashMap<>();
private final List listeners = new CopyOnWriteArrayList<>();
private ScheduledExecutorService scheduler;
@@ -41,8 +42,9 @@ public class HeartbeatManager {
* @param mainWindow janela principal utilizada para obter o nome do usuário
* e o socket de comunicação.
*/
- public HeartbeatManager(MainWindow mainWindow) {
+ public HeartbeatManager(MainWindow mainWindow, ConnectionManager connectionManager) {
this.mainWindow = mainWindow;
+ this.connectionManager = connectionManager;
}
/**
@@ -64,12 +66,8 @@ public class HeartbeatManager {
}
private void announce() {
- try {
- HeartbeatMessage msg = new HeartbeatMessage(mainWindow.getUserName(), instanceId);
- mainWindow.getSocketUDP().sendMulticast(msg.toByteArray());
- } catch (IOException ex) {
- Logger.getLogger(HeartbeatManager.class.getName()).log(Level.WARNING, "Falha ao enviar heartbeat", ex);
- }
+ HeartbeatMessage msg = new HeartbeatMessage(mainWindow.getUserName(), instanceId);
+ connectionManager.sendUdpMulticast(msg);
}
// Chamado pelo Socket quando um pacote é identificado como heartbeat
diff --git a/pitiupi/src/pitiupi/control/PluginLoader.java b/pitiupi/src/pitiupi/control/PluginLoader.java
index db549e4..7a40dd9 100644
--- a/pitiupi/src/pitiupi/control/PluginLoader.java
+++ b/pitiupi/src/pitiupi/control/PluginLoader.java
@@ -4,14 +4,12 @@
*/
package pitiupi.control;
-import java.awt.List;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.ServiceLoader;
-import java.util.Vector;
+import java.util.*;
+
import pitiupi.GUI.MainWindow;
import pitiupi.Main;
import pitiupi.plugin.Plugin;
@@ -33,7 +31,7 @@ public class PluginLoader {
this.mainWindow = main;
}
- public void loadPlugins() {
+ public void loadPlugins(List plugins, HashSet loadedJars) {
File pluginDir = new File("plugins");
File[] jarFiles = pluginDir.listFiles((dir, name) -> name.endsWith(".jar"));
@@ -42,33 +40,34 @@ public class PluginLoader {
return;
}
- try {
- // 2. Convert jar file paths into URLs
- ArrayList urls = new ArrayList();
- for (File file : jarFiles) {
- urls.add(file.toURI().toURL());
- System.out.println("Discovered plugin package: " + file.getName());
+ for (File file : jarFiles) {
+
+ if (loadedJars.contains(file.getName())) {
+ continue;
}
- // 3. Create a class loader isolated from the application's default loader
- URLClassLoader pluginClassLoader = new URLClassLoader(
- (URL[])urls.toArray(new URL[0]),
- Main.class.getClassLoader()
- );
- System.out.println(pluginClassLoader);
+ System.out.println("Discovered plugin package: " + file.getName());
- // 4. Locate and instantiate all classes implementing the Plugin interface
- ServiceLoader serviceLoader = ServiceLoader.load(Plugin.class, pluginClassLoader);
+ try {
+ URLClassLoader classLoader = new URLClassLoader(
+ new URL[]{file.toURI().toURL()},
+ Main.class.getClassLoader()
+ );
- 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);
+ ServiceLoader serviceLoader = ServiceLoader.load(Plugin.class, classLoader);
+
+ for (Plugin plugin : serviceLoader) {
+ System.out.println("Loading: " + plugin.getName());
+
+ plugin.createPlugin(this.mainWindow);
+ plugins.add(plugin);
+ loadedJars.add(file.getName());
+ }
+
+ } catch (Exception e) {
+ System.out.println("Failed to load plugin " + file.getName());
+ e.printStackTrace();
}
-
- } catch (MalformedURLException e) {
- System.out.println(e.toString());
}
}
}
diff --git a/pitiupi/src/pitiupi/control/PluginManager.java b/pitiupi/src/pitiupi/control/PluginManager.java
new file mode 100644
index 0000000..08ea55c
--- /dev/null
+++ b/pitiupi/src/pitiupi/control/PluginManager.java
@@ -0,0 +1,71 @@
+package pitiupi.control;
+
+import pitiupi.GUI.MainWindow;
+import pitiupi.net.Message;
+import pitiupi.net.tcp.TcpConnection;
+import pitiupi.plugin.Plugin;
+import pitiupi.plugin.PrivateConnectionPlugin;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+public class PluginManager {
+ private PluginLoader pluginLoader;
+ private final List plugins;
+ private final HashSet loadedJars;
+
+ public PluginManager(MainWindow main) {
+ this.pluginLoader = new PluginLoader(main);
+ this.plugins = new ArrayList<>();
+ this.loadedJars = new HashSet<>();
+ }
+
+ public void loadPlugins() {
+ pluginLoader.loadPlugins(plugins, loadedJars);
+ }
+
+ public void handlePublicMessage(Message msg) {
+ for (Plugin plugin : plugins) {
+ plugin.receiveMessage(msg);
+ }
+ }
+
+ private Plugin getPlugin(String pluginId) {
+ for (Plugin plugin : plugins) {
+ if (plugin.getIdentifier().equals(pluginId)) return plugin;
+ }
+ return null;
+ }
+
+ public boolean handlePrivateMessage(byte[] msg, String receiverId) {
+ Plugin plugin = getPlugin(receiverId);
+ if (plugin == null) return false;
+
+ if (plugin instanceof PrivateConnectionPlugin privatePlugin) {
+ privatePlugin.receiveBytes(msg);
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean handleConnection(TcpConnection connection, String receiverId) {
+ Plugin plugin = getPlugin(receiverId);
+ if (plugin == null) return false;
+
+ if (plugin instanceof PrivateConnectionPlugin privatePlugin) {
+ privatePlugin.receivePrivateConnection(connection);
+ return true;
+ }
+
+ return false;
+ }
+
+ public void handleDisconnection(TcpConnection connection, String receiverId) {
+ Plugin plugin = getPlugin(receiverId);
+ if (plugin instanceof PrivateConnectionPlugin privatePlugin) {
+ privatePlugin.onSocketClosed(connection);
+ }
+ }
+}
diff --git a/pitiupi/src/pitiupi/net/tcp/SocketTCP.java b/pitiupi/src/pitiupi/net/tcp/SocketTCP.java
index 920dffa..9033903 100644
--- a/pitiupi/src/pitiupi/net/tcp/SocketTCP.java
+++ b/pitiupi/src/pitiupi/net/tcp/SocketTCP.java
@@ -1,11 +1,12 @@
package pitiupi.net.tcp;
import pitiupi.GUI.MainWindow;
+import pitiupi.control.ConnectionManager;
+import pitiupi.control.PluginManager;
import pitiupi.net.Message;
import pitiupi.plugin.Plugin;
import pitiupi.plugin.PrivateConnectionPlugin;
-import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.Objects;
@@ -35,12 +36,13 @@ public class SocketTCP extends Thread {
private final ExecutorService connectionExecutor = Executors.newCachedThreadPool();
- private final ConnectionManager connectionManager;
+ private final TcpConnectionManager tcpConnectionManager;
private ServerSocket serverSocket;
private InetAddress address;
- private final MainWindow main;
+ private final ConnectionManager connectionManager;
+ private final PluginManager pluginManager;
private volatile boolean running = true;
@@ -51,15 +53,18 @@ public class SocketTCP extends Thread {
* com os peers são estabelecidas sob demanda durante o envio ou aceitas
* quando iniciadas por outros peers.
*
- * @param main janela principal da aplicação, usada para obter a porta,
- * o identificador local e os plugins disponíveis.
+ * @param connectionManager interface de conexão da aplicação, usada para obter a porta,
+ * o identificador local e os plugins disponíveis.
*/
- public SocketTCP(MainWindow main) {
- this.main = main;
+ public SocketTCP(ConnectionManager connectionManager, PluginManager pluginManager) {
+ this.connectionManager = connectionManager;
+ this.pluginManager = pluginManager;
+
logger = Logger.getLogger(getClass().getName());
- connectionManager = new ConnectionManager();
+ tcpConnectionManager = new TcpConnectionManager();
+
try {
- serverSocket = new ServerSocket(main.getPort());
+ serverSocket = new ServerSocket(connectionManager.getPort());
address = InetAddress.getByName(InetAddress.getLocalHost().getHostAddress());
} catch (IOException ex) {
System.out.println("There is no socket connection. Sorry.");
@@ -75,28 +80,36 @@ public class SocketTCP extends Thread {
* do envio. Falhas durante o estabelecimento ou envio são registradas na
* saída padrão e não são propagadas ao chamador.
*
- * @param msg mensagem serializada em bytes que será enviada.
+ * @param msg mensagem que será enviada.
* @param destinationAddress endereço IP do peer que receberá a mensagem.
*/
- public void send(byte[] msg, InetAddress destinationAddress) {
+ public boolean send(Message msg, InetAddress destinationAddress) {
try {
- TcpConnection connection = getPublicConnection(destinationAddress, main.getIdentifier(), main.getIdentifier());
+ TcpConnection connection = getPublicConnection(
+ destinationAddress,
+ connectionManager.getIdentifier(),
+ connectionManager.getIdentifier()
+ );
+
if (connection == null) {
System.out.println("Could not establish TCP connection.");
- return;
+ return false;
}
- connection.send(msg);
+
+ connection.send(msg.toByteArray());
} catch (Exception ex) {
System.out.println("Could not send TCP message.");
System.out.println(ex.toString());
+ return false;
}
+ return true;
}
/**
* Estabelece uma conexão TCP privada com um plugin específico do peer de destino.
*
* A conexão é criada como privada e passa a ser gerenciada pelo
- * {@link ConnectionManager}. O método também inicia a tarefa responsável
+ * {@link TcpConnectionManager}. O método também inicia a tarefa responsável
* por receber os dados dessa conexão.
*
* @param destinationAddress endereço IP do peer de destino.
@@ -115,11 +128,11 @@ public class SocketTCP extends Thread {
* Obtém uma conexão TCP pública existente com o peer de destino ou estabelece
* uma nova caso não exista uma conexão válida.
*
- * As conexões públicas são gerenciadas pelo {@link ConnectionManager}.
+ *
As conexões públicas são gerenciadas pelo {@link TcpConnectionManager}.
* O método primeiro verifica se já existe uma conexão pública registrada
* para o endereço de destino e, caso ela exista e não esteja fechada,
* reutiliza-a. Caso contrário, uma nova conexão pública é estabelecida,
- * registrada no {@link ConnectionManager} e disponibilizada para uso.
+ * registrada no {@link TcpConnectionManager} e disponibilizada para uso.
*
* O acesso ao método é sincronizado para evitar que múltiplas threads
* estabeleçam simultaneamente conexões públicas para o mesmo peer.
@@ -133,7 +146,7 @@ public class SocketTCP extends Thread {
private synchronized TcpConnection getPublicConnection(InetAddress destinationAddress, String senderId, String receiverId) {
TcpConnection connection;
- connection = connectionManager.getPublicConnection(destinationAddress);
+ connection = tcpConnectionManager.getPublicConnection(destinationAddress);
if (connection != null && !connection.isClosed()) return connection;
connection = establishOutgoingConnection(destinationAddress, senderId, receiverId, false);
@@ -146,7 +159,7 @@ public class SocketTCP extends Thread {
*
* Cada socket aceito é encaminhado para processamento assíncrono,
* interpretado como uma {@link TcpConnection}, registrado pelo
- * {@link ConnectionManager} e associado ao receptor adequado.
+ * {@link TcpConnectionManager} e associado ao receptor adequado.
*/
private void receive() {
while (running) {
@@ -188,7 +201,7 @@ public class SocketTCP extends Thread {
throw new IllegalArgumentException("Connections to the local host are forbidden.");
}
- TcpConnection connection = ConnectionFactory.createConnection(destinationAddress, main.getPort(), sender, receiver, isPrivate);
+ TcpConnection connection = ConnectionFactory.createConnection(destinationAddress, connectionManager.getPort(), sender, receiver, isPrivate);
if (connection == null) return null;
saveConnection(connection);
@@ -229,10 +242,10 @@ public class SocketTCP extends Thread {
*/
private void saveConnection(TcpConnection connection) {
if (connection.isPrivate()) {
- connectionManager.addPrivateConnection(connection);
+ tcpConnectionManager.addPrivateConnection(connection);
}
else {
- connectionManager.addPublicConnection(connection);
+ tcpConnectionManager.addPublicConnection(connection);
}
}
@@ -255,48 +268,21 @@ public class SocketTCP extends Thread {
return;
}
- if (connection.getReceiver().equals(main.getIdentifier())) {
+ if (connection.getReceiver().equals(connectionManager.getIdentifier())) {
systemConnectionReceiver(connection);
return;
}
- Plugin receiver = findConnectionReceiver(connection);
- if (receiver instanceof PrivateConnectionPlugin plugin) {
- if (notify) {
- plugin.receivePrivateConnection(connection);
- }
- privateConnectionReceiver(connection, plugin);
- }
- }
-
- /**
- * Localiza o plugin responsável por receber uma conexão privada.
- *
- * A busca é feita pelo identificador do destinatário informado na
- * própria conexão. Caso nenhum plugin correspondente seja encontrado,
- * uma mensagem de erro é enviada ao peer remoto.
- *
- * @param connection conexão privada cujo destinatário será localizado.
- * @return o plugin com o identificador correspondente ao destinatário,
- * ou {@code null} se nenhum plugin for encontrado.
- */
- private Plugin findConnectionReceiver(TcpConnection connection) {
- Plugin receiver = null;
- for(Plugin plugin : main.getPlugins()) {
- if (plugin.getIdentifier().equals(connection.getReceiver())) {
- receiver = plugin;
- break;
- }
- }
-
- if (receiver == null) {
+ if (pluginManager.handleConnection(connection, connection.getReceiver()))
+ privateConnectionReceiver(connection);
+ else {
SysInfoMessage.sendSystemInfo(
connection,
SysInfoType.RECEIVER_NOT_FOUND,
"This peer does not have the plugin: " + connection.getReceiver()
);
}
- return receiver;
+
}
/**
@@ -308,7 +294,7 @@ public class SocketTCP extends Thread {
* condição de erro.
*
* O método também trata timeouts e erros de I/O, removendo a conexão
- * do {@link ConnectionManager} quando ela deixa de ser utilizável.
+ * do {@link TcpConnectionManager} quando ela deixa de ser utilizável.
*
* @param connection conexão pública da qual as mensagens serão recebidas.
*/
@@ -324,15 +310,13 @@ public class SocketTCP extends Thread {
SysInfoMessage sysMessage = SysInfoMessage.parseSystemInfo(message);
if (sysMessage == null) {
- for (Plugin plugin : main.getPlugins()) {
- plugin.receiveMessage(message);
- }
+ pluginManager.handlePublicMessage(message);
continue;
}
switch (sysMessage.getType()) {
case CONNECTION_CLOSED, INTERNAL_ERROR -> {
- connectionManager.closeConnection(connection);
+ tcpConnectionManager.closeConnection(connection);
return;
}
case MESSAGE_REJECTED -> {
@@ -356,17 +340,17 @@ public class SocketTCP extends Thread {
"class Message not found."
);
logger.log(Level.SEVERE, null, ex);
- connectionManager.closeConnection(connection);
+ tcpConnectionManager.closeConnection(connection);
}
}
catch (SocketTimeoutException ex) {
if (connection.hasTimedOut()) {
- connectionManager.closeConnection(connection, "Connection timeout");
+ tcpConnectionManager.closeConnection(connection, "Connection timeout");
return;
}
}
catch (IOException ex) {
- connectionManager.closeConnection(connection);
+ tcpConnectionManager.closeConnection(connection);
}
}
}
@@ -381,40 +365,37 @@ public class SocketTCP extends Thread {
* do plugin e o fechamento da conexão.
*
* @param connection conexão privada da qual os dados serão recebidos.
- * @param plugin plugin responsável pelo processamento dos dados recebidos.
*/
- private void privateConnectionReceiver(TcpConnection connection, Plugin plugin) {
- if (plugin instanceof PrivateConnectionPlugin privatePlugin) {
- while (running) {
- try {
- byte[] message = connection.receive();
- SysInfoMessage sysMessage = SysInfoMessage.parseSystemInfo(message);
+ private void privateConnectionReceiver(TcpConnection connection) {
+ while (running) {
+ try {
+ byte[] message = connection.receive();
+ SysInfoMessage sysMessage = SysInfoMessage.parseSystemInfo(message);
- if (sysMessage == null) {
- privatePlugin.receiveBytes(message);
+ if (sysMessage == null) {
+ pluginManager.handlePrivateMessage(message, connection.getReceiver());
+ continue;
+ }
+
+ switch (sysMessage.getType()) {
+ case CONNECTION_CLOSED, INTERNAL_ERROR -> {
+ pluginManager.handleDisconnection(connection, connection.getReceiver());
+ tcpConnectionManager.closeConnection(connection);
+ }
+ default -> {
continue;
}
-
- switch (sysMessage.getType()) {
- case CONNECTION_CLOSED, INTERNAL_ERROR -> {
- privatePlugin.onSocketClosed(connection);
- connectionManager.closeConnection(connection);
- }
- default -> {
- continue;
- }
- }
}
- catch (SocketTimeoutException ex) {
- if (connection.hasTimedOut()) {
- connectionManager.closeConnection(connection, "Connection timeout");
- return;
- }
- }
- catch (IOException ex) {
- connectionManager.closeConnection(connection);
+ }
+ catch (SocketTimeoutException ex) {
+ if (connection.hasTimedOut()) {
+ tcpConnectionManager.closeConnection(connection, "Connection timeout");
+ return;
}
}
+ catch (IOException ex) {
+ tcpConnectionManager.closeConnection(connection);
+ }
}
}
@@ -445,7 +426,7 @@ public class SocketTCP extends Thread {
if (connection.hasTimedOut()) return;
}
catch (IOException ex) {
- connectionManager.closeConnection(connection);
+ tcpConnectionManager.closeConnection(connection);
}
}
}
@@ -454,13 +435,13 @@ public class SocketTCP extends Thread {
* Encerra uma conexão TCP e registra o motivo informado.
*
* Quando nenhuma descrição é fornecida, é utilizado um motivo padrão.
- * O fechamento efetivo da conexão é delegado ao {@link ConnectionManager}.
+ * O fechamento efetivo da conexão é delegado ao {@link TcpConnectionManager}.
*
* @param connection conexão que será encerrada.
* @param description motivo do encerramento; pode ser {@code null}.
*/
public void disconnect(TcpConnection connection, String description) {
- connectionManager.closeConnection(
+ tcpConnectionManager.closeConnection(
connection,
Objects.requireNonNullElse(description, "No reason provided")
);
@@ -493,7 +474,7 @@ public class SocketTCP extends Thread {
}
}
- connectionManager.closeAllConnections("The peer must have closed the application or changed ports");
+ tcpConnectionManager.closeAllConnections("The peer must have closed the application or changed ports");
connectionExecutor.shutdownNow();
}
diff --git a/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java b/pitiupi/src/pitiupi/net/tcp/TcpConnectionManager.java
similarity index 99%
rename from pitiupi/src/pitiupi/net/tcp/ConnectionManager.java
rename to pitiupi/src/pitiupi/net/tcp/TcpConnectionManager.java
index b8b774c..a8df7db 100644
--- a/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java
+++ b/pitiupi/src/pitiupi/net/tcp/TcpConnectionManager.java
@@ -27,7 +27,7 @@ import java.util.stream.Collectors;
* peers ativos para encerrar conexões associadas a peers que deixaram de
* estar disponíveis.
*/
-class ConnectionManager implements PeerListener {
+class TcpConnectionManager implements PeerListener {
private final Logger logger;
private final Map publicConnections;
private final Map> privateConnections;
@@ -35,7 +35,7 @@ class ConnectionManager implements PeerListener {
/**
* Cria um gerenciador de conexões TCP vazio.
*/
- public ConnectionManager() {
+ public TcpConnectionManager() {
publicConnections = new ConcurrentHashMap<>();
privateConnections = new ConcurrentHashMap<>();
diff --git a/pitiupi/src/pitiupi/net/udp/SocketUDP.java b/pitiupi/src/pitiupi/net/udp/SocketUDP.java
index da9fa5f..6389cad 100644
--- a/pitiupi/src/pitiupi/net/udp/SocketUDP.java
+++ b/pitiupi/src/pitiupi/net/udp/SocketUDP.java
@@ -14,6 +14,8 @@ import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
+import pitiupi.control.ConnectionManager;
+import pitiupi.control.PluginManager;
import pitiupi.net.HeartbeatMessage;
import pitiupi.net.Message;
import pitiupi.plugin.Plugin;
@@ -37,7 +39,10 @@ public class SocketUDP extends Thread {
private MulticastSocket multicastSocket;
private InetAddress address;
- private MainWindow main;
+
+ private ConnectionManager connectionManager;
+ private PluginManager pluginManager;
+
private volatile boolean running = true;
public final static String INET_ADDR = "224.0.0.3";
@@ -47,22 +52,26 @@ public class SocketUDP extends Thread {
* O socket é associado à porta da aplicação e ingressa no grupo
* multicast configurado.
*
- * @param main janela principal da aplicação.
+ * @param connectionManager interface que gerencia toda conexão da aplicação.
+ * @param pluginManager interface que gerencia os plugins da conexão.
*/
- public SocketUDP(MainWindow main) {
- this.main = main;
+ public SocketUDP(ConnectionManager connectionManager, PluginManager pluginManager) {
+ this.connectionManager = connectionManager;
+ this.pluginManager = pluginManager;
+
try {
this.address = InetAddress.getByName(SocketUDP.INET_ADDR);
- } catch (UnknownHostException ex) {
- System.getLogger(SocketUDP.class.getName()).log(System.Logger.Level.ERROR, (String) null, ex);
- }
- try {
- multicastSocket = new MulticastSocket(this.main.getPort());
+
+ multicastSocket = new MulticastSocket(connectionManager.getPort());
multicastSocket.setSendBufferSize(256000);
multicastSocket.setReceiveBufferSize(256000);
multicastSocket.setReuseAddress(true);
multicastSocket.joinGroup(address);
- } catch (IOException ex) {
+ }
+ catch (UnknownHostException ex) {
+ System.getLogger(SocketUDP.class.getName()).log(System.Logger.Level.ERROR, (String) null, ex);
+ }
+ catch (IOException ex) {
System.out.println("There is no socket connection. Sorry.");
System.out.println(ex);
}
@@ -71,22 +80,22 @@ public class SocketUDP extends Thread {
/**
* Envia uma mensagem para o grupo multicast da aplicação.
*
- * @param msg mensagem serializada a ser enviada.
+ * @param msg mensagem a ser enviada.
* @throws IOException caso ocorra um erro durante o envio.
*/
- public void sendMulticast(byte[] msg) throws IOException {
- send(msg, this.address);
+ public void sendMulticast(Message msg) throws IOException {
+ send(msg.toByteArray(), this.address);
}
/**
* Envia uma mensagem diretamente para um peer utilizando UDP.
*
- * @param msg mensagem serializada a ser enviada.
+ * @param msg mensagem a ser enviada.
* @param destinationAddress endereço IP do peer destinatário.
* @throws IOException caso ocorra um erro durante o envio.
*/
- public void sendUnicast(byte[] msg, InetAddress destinationAddress) throws IOException {
- send(msg, destinationAddress);
+ public void sendUnicast(Message msg, InetAddress destinationAddress) throws IOException {
+ send(msg.toByteArray(), destinationAddress);
}
/**
@@ -98,7 +107,7 @@ public class SocketUDP extends Thread {
*/
private void send(byte[] msg, InetAddress destinationAddress) throws IOException {
DatagramPacket msgPacket;
- msgPacket = new DatagramPacket(msg, msg.length, destinationAddress, this.main.getPort());
+ msgPacket = new DatagramPacket(msg, msg.length, destinationAddress, connectionManager.getPort());
multicastSocket.send(msgPacket);
}
@@ -145,7 +154,7 @@ public class SocketUDP extends Thread {
}
HeartbeatMessage heartbeat = tryParseHeartbeat(msgPacket.getData());
if (heartbeat != null) {
- main.getHeartbeatManager().receiveHeartbeat(heartbeat, msgPacket.getAddress());
+ connectionManager.receiveHeartbeat(heartbeat, msgPacket.getAddress());
continue;
}
@@ -154,10 +163,8 @@ public class SocketUDP extends Thread {
continue;
}
- for (Plugin plugin : main.getPlugins()) {
- System.out.println(msgPacket.getAddress().toString());
- plugin.receiveMessage(message);
- }
+ System.out.println(msgPacket.getAddress().toString());
+ pluginManager.handlePublicMessage(message);
}
}