diff --git a/pitiupi/src/pitiupi/net/tcp/ConnectionFactory.java b/pitiupi/src/pitiupi/net/tcp/ConnectionFactory.java index 0a3f098..8982c12 100644 --- a/pitiupi/src/pitiupi/net/tcp/ConnectionFactory.java +++ b/pitiupi/src/pitiupi/net/tcp/ConnectionFactory.java @@ -11,10 +11,44 @@ import java.net.SocketTimeoutException; import java.util.logging.Level; import java.util.logging.Logger; +/** + * Fábrica responsável pela criação e configuração de conexões TCP. + * + *
Esta classe centraliza o estabelecimento de conexões de saída e a + * configuração de conexões recebidas. Antes de uma conexão ser considerada + * válida, é realizado um handshake entre os peers para identificar o remetente, + * o destinatário e se a conexão é privada.
+ * + *Durante o handshake é utilizado um timeout menor, definido por + * {@link #HANDSHAKE_TIMEOUT}. Após a validação bem-sucedida, a conexão passa + * a utilizar o timeout padrão definido por {@link #STANDARD_TIMEOUT}.
+ */ public class ConnectionFactory { private static final int HANDSHAKE_TIMEOUT = 5000; private static final int STANDARD_TIMEOUT = 300_000; + /** + * Cria uma conexão TCP de saída com o peer de destino e realiza o handshake + * necessário para validá-la. + * + *A conexão é configurada com os identificadores do remetente e do + * destinatário e com o tipo indicado pelo parâmetro {@code isPrivate}. + * Após o estabelecimento do socket, o método envia um + * {@link HandshakeMessage} e aguarda uma resposta válida.
+ * + *Se o handshake for validado com sucesso, o timeout da conexão é + * alterado de {@link #HANDSHAKE_TIMEOUT} para {@link #STANDARD_TIMEOUT} + * e a conexão é retornada. Caso contrário, {@code null} é retornado.
+ * + * @param address endereço IP do peer de destino. + * @param port porta TCP na qual o peer de destino está aguardando conexões. + * @param sender identificador do remetente da conexão. + * @param receiver identificador do destinatário da conexão. + * @param isPrivate {@code true} se a conexão deve ser privada; + * {@code false} se deve ser pública. + * @return a conexão TCP estabelecida e validada ou {@code null} caso + * não seja possível estabelecer ou validar a conexão. + */ public static TcpConnection createConnection(InetAddress address, int port, String sender, String receiver, boolean isPrivate) { try { TcpConnection connection; @@ -42,6 +76,22 @@ public class ConnectionFactory { return null; } + /** + * Configura uma conexão TCP recebida e valida o handshake enviado pelo + * peer remoto. + * + *O handshake recebido é utilizado para obter e configurar os + * identificadores do remetente e do destinatário, bem como o tipo da + * conexão. Após a validação bem-sucedida, o timeout da conexão é alterado + * para {@link #STANDARD_TIMEOUT}.
+ * + *O {@link Socket} recebido deve representar uma conexão TCP já aceita + * pelo servidor.
+ * + * @param socket socket TCP correspondente à conexão recebida. + * @return a conexão TCP configurada e validada ou {@code null} caso + * o handshake seja inválido ou não possa ser processado. + */ public static TcpConnection receiveConnection(Socket socket) { try { TcpConnection connection; @@ -66,6 +116,27 @@ public class ConnectionFactory { return null; } + /** + * Aguarda e valida a mensagem de handshake de uma conexão TCP. + * + *Durante a validação, a conexão utiliza {@link #HANDSHAKE_TIMEOUT} + * como limite para o recebimento do handshake. A mensagem recebida deve + * ser uma instância de {@link Message} e, especificamente, de + * {@link HandshakeMessage}. Mensagens de sistema ou mensagens de outros + * tipos são rejeitadas.
+ * + *Quando o handshake é recebido, seus campos de remetente e destinatário + * são validados por {@link #validateHandshake(HandshakeMessage, TcpConnection)}. + * Caso a validação seja bem-sucedida, o próprio handshake é retornado.
+ * + *Em caso de timeout, mensagem inválida ou erro durante o processamento, + * uma mensagem de sistema apropriada pode ser enviada ao peer e + * {@code null} é retornado.
+ * + * @param connection conexão TCP da qual o handshake será recebido. + * @return o {@link HandshakeMessage} validado ou {@code null} caso o + * handshake não seja recebido ou seja inválido. + */ private static HandshakeMessage validateConnection(TcpConnection connection) { try { connection.setTimeout(HANDSHAKE_TIMEOUT); @@ -113,6 +184,20 @@ public class ConnectionFactory { return null; } + /** + * Valida os identificadores presentes em uma mensagem de handshake. + * + *O remetente e o destinatário devem estar presentes e não podem ser + * vazios ou conter apenas espaços em branco. Quando um dos identificadores + * é inválido, uma mensagem de rejeição é enviada ao peer e a validação + * falha.
+ * + * @param handshake mensagem de handshake a ser validada. + * @param connection conexão associada ao handshake, utilizada para enviar + * uma mensagem de rejeição quando necessário. + * @return {@code true} se os identificadores do remetente e do destinatário + * forem válidos; {@code false} caso contrário. + */ private static boolean validateHandshake(HandshakeMessage handshake, TcpConnection connection) { String sender = handshake.getSender(); String receiver = handshake.getReceiver(); diff --git a/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java b/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java index 823b43a..b8b774c 100644 --- a/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java +++ b/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java @@ -14,11 +14,27 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -public class ConnectionManager implements PeerListener { +/** + * Gerencia as conexões TCP estabelecidas com os peers da aplicação. + * + *As conexões públicas são armazenadas individualmente por endereço IP, + * enquanto as conexões privadas são agrupadas por endereço, permitindo que + * um mesmo peer mantenha múltiplas conexões privadas simultaneamente.
+ * + *Além de manter o registro das conexões ativas, esta classe é responsável + * por encerrá-las quando necessário e por remover do gerenciamento as + * conexões que forem fechadas. Também acompanha as alterações na lista de + * peers ativos para encerrar conexões associadas a peers que deixaram de + * estar disponíveis.
+ */ +class ConnectionManager implements PeerListener { private final Logger logger; private final MapUm mesmo peer pode possuir múltiplas conexões privadas. Por isso, + * as conexões são armazenadas em uma lista associada ao endereço do + * peer.
+ * + * @param connection conexão privada a ser registrada. + */ + public void addPrivateConnection(TcpConnection connection) { ListCada peer pode possuir apenas uma conexão pública registrada. + * Quando já existe uma conexão pública para o endereço da nova conexão, + * a conexão anterior é encerrada e substituída pela nova.
+ * + * @param connection nova conexão pública a ser registrada. + */ + + public void addPublicConnection(TcpConnection connection) { TcpConnection oldConnection = publicConnections.put(connection.getAddress(), connection); if (oldConnection != null && oldConnection != connection) { closeConnection(oldConnection); } } + /** + * Envia uma mensagem de encerramento ao peer e fecha a conexão. + * + *A mensagem enviada informa o motivo do encerramento antes que a + * conexão seja removida do gerenciamento e fechada.
+ * + * @param connection conexão TCP a ser encerrada. + * @param reason motivo do encerramento que será informado ao peer. + */ public void closeConnection(TcpConnection connection, String reason) { SysInfoMessage.sendSystemInfo(connection, SysInfoType.CONNECTION_CLOSED, reason); closeConnection(connection); } + + /** + * Remove uma conexão do gerenciamento e encerra seu socket. + * + *Para conexões privadas, a conexão é removida da lista associada ao + * endereço do peer. Caso essa seja a última conexão privada do endereço, + * a lista também é removida do mapa.
+ * + *Para conexões públicas, a conexão é removida do mapa somente se + * ainda for a conexão registrada para seu endereço.
+ * + *Se a conexão já estiver fechada ou for {@code null}, nenhuma ação + * adicional de fechamento é realizada.
+ * + * @param connection conexão TCP a ser removida e encerrada. + */ + public void closeConnection(TcpConnection connection) { if (connection == null) return; if (connection.isPrivate()) { @@ -73,6 +143,13 @@ public class ConnectionManager implements PeerListener { } } + /** + * Envia uma mensagem de encerramento para todas as conexões de um peer + * e, em seguida, fecha essas conexões. + * + * @param address endereço IP do peer cujas conexões serão encerradas. + * @param reason motivo do encerramento informado ao peer. + */ public void closeByAdress(InetAddress address, String reason) { ListTanto a conexão pública quanto todas as conexões privadas associadas + * ao endereço são encerradas e removidas do gerenciamento.
+ * + * @param address endereço IP do peer cujas conexões serão encerradas. + */ public void closeByAdress(InetAddress address) { TcpConnection publicConnection = publicConnections.remove(address); @@ -111,6 +196,12 @@ public class ConnectionManager implements PeerListener { } } + /** + * Envia uma mensagem de encerramento para todas as conexões privadas + * gerenciadas e, em seguida, fecha todas elas. + * + * @param reason motivo do encerramento informado aos peers. + */ public void closeAllConnections(String reason) { for (ListApós a execução, não devem permanecer conexões registradas nos + * mapas de conexões deste gerenciador.
+ */ + public void closeAllConnections() { for (TcpConnection connection : publicConnections.values()) { closeConnection(connection); @@ -137,11 +236,14 @@ public class ConnectionManager implements PeerListener { /** * Atualiza as conexões de acordo com os peers atualmente ativos. * - *Conexões associadas a peers que não estão mais ativos são encerradas - * e removidas.
+ *Os endereços presentes na lista de peers são utilizados como + * referência para determinar quais conexões ainda devem permanecer + * ativas. Conexões públicas e privadas associadas a endereços que não + * estão mais presentes na lista de peers são encerradas e removidas.
* * @param peers lista atualizada de peers ativos. */ + @Override public void onPeersChanged(ListO servidor utiliza a porta definida pela aplicação e inicia sem - * estabelecer conexões com os peers. As conexões são criadas conforme - * necessário durante o envio ou recebidas de outros peers.
+ *O servidor é criado na porta definida pela aplicação. As conexões + * 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. + * @param main janela principal da aplicação, usada para obter a porta, + * o identificador local e os plugins disponíveis. */ public SocketTCP(MainWindow main) { this.main = main; @@ -66,6 +67,17 @@ public class SocketTCP extends Thread { } } + /** + * Envia uma mensagem por meio de uma conexão TCP pública com o peer de destino. + * + *A conexão pública existente para o endereço informado é reutilizada. + * Caso não exista uma conexão válida, uma nova conexão é estabelecida antes + * 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 destinationAddress endereço IP do peer que receberá a mensagem. + */ public void send(byte[] msg, InetAddress destinationAddress) { try { TcpConnection connection = getPublicConnection(destinationAddress, main.getIdentifier(), main.getIdentifier()); @@ -80,10 +92,44 @@ public class SocketTCP extends Thread { } } + /** + * 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 + * por receber os dados dessa conexão.
+ * + * @param destinationAddress endereço IP do peer de destino. + * @param senderId identificador do remetente da conexão. + * @param receiverId identificador do plugin que receberá os dados. + * @return a conexão privada estabelecida ou {@code null} quando a criação + * da conexão falhar. + * @throws IllegalArgumentException se o endereço de destino for o endereço + * local desta instância. + */ public TcpConnection createPrivateConnection(InetAddress destinationAddress, String senderId, String receiverId) { return establishOutgoingConnection(destinationAddress, senderId, receiverId, true); } + /** + * 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}. + * 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.
+ * + *O acesso ao método é sincronizado para evitar que múltiplas threads + * estabeleçam simultaneamente conexões públicas para o mesmo peer.
+ * + * @param destinationAddress endereço IP do peer de destino. + * @param senderId identificador usado como remetente no estabelecimento da conexão. + * @param receiverId identificador usado como destinatário no estabelecimento da conexão. + * @return uma conexão pública válida ou {@code null} caso não seja possível + * estabelecê-la. + */ private synchronized TcpConnection getPublicConnection(InetAddress destinationAddress, String senderId, String receiverId) { TcpConnection connection; @@ -98,9 +144,9 @@ public class SocketTCP extends Thread { /** * Aguarda e aceita novas conexões TCP. * - *Cada conexão aceita é associada ao endereço do peer e registrada para - * que possa ser utilizada tanto para recepção quanto para envio de - * mensagens.
+ *Cada socket aceito é encaminhado para processamento assíncrono, + * interpretado como uma {@link TcpConnection}, registrado pelo + * {@link ConnectionManager} e associado ao receptor adequado.
*/ private void receive() { while (running) { @@ -120,6 +166,22 @@ public class SocketTCP extends Thread { } } + /** + * Estabelece uma conexão TCP de saída com outro peer. + * + *O método impede conexões com o próprio endereço local, cria a conexão + * por meio da {@link ConnectionFactory}, registra-a no gerenciador de + * conexões e inicia uma tarefa para receber dados continuamente.
+ * + * @param destinationAddress endereço IP do peer de destino. + * @param sender identificador do remetente. + * @param receiver identificador do destinatário. + * @param isPrivate {@code true} para uma conexão destinada a um plugin + * específico; {@code false} para uma conexão pública. + * @return a conexão estabelecida ou {@code null} se a + * {@link ConnectionFactory} não conseguir criá-la. + * @throws IllegalArgumentException se o destino for o endereço desta máquina. + */ private TcpConnection establishOutgoingConnection(InetAddress destinationAddress, String sender, String receiver, boolean isPrivate) { if (address.equals(destinationAddress)) { System.out.println("Failed to get socket."); @@ -138,6 +200,15 @@ public class SocketTCP extends Thread { return connection; } + /** + * Agenda o processamento de uma conexão TCP recebida. + * + *A conexão é interpretada pela {@link ConnectionFactory}, registrada + * no gerenciador e associada a uma tarefa de recepção. O processamento é + * executado de forma assíncrona pelo executor compartilhado.
+ * + * @param socket socket aceito pelo {@link ServerSocket}. + */ private void acceptIncomingConnection(Socket socket) { connectionExecutor.submit(() -> { TcpConnection connection = ConnectionFactory.receiveConnection(socket); @@ -148,40 +219,67 @@ public class SocketTCP extends Thread { }); } + /** + * Registra uma conexão no gerenciador de acordo com seu tipo. + * + *Conexões privadas são armazenadas na coleção de conexões privadas; + * as demais são armazenadas na coleção de conexões públicas.
+ * + * @param connection conexão que será registrada. + */ private void saveConnection(TcpConnection connection) { if (connection.isPrivate()) { - connectionManager.addPrivateConnection(connection.getAddress(), connection); + connectionManager.addPrivateConnection(connection); } else { - connectionManager.addPublicConnection(connection.getAddress(), connection); + connectionManager.addPublicConnection(connection); } } + /** + * Seleciona e inicia o receptor adequado para uma conexão. + * + *Conexões públicas são tratadas pelo receptor de mensagens públicas. + * Conexões privadas destinadas ao próprio sistema são tratadas + * separadamente; as demais são encaminhadas ao plugin identificado como + * destinatário. Quando solicitado, o plugin também é notificado sobre o + * estabelecimento da conexão.
+ * + * @param connection conexão cujo fluxo de entrada será processado. + * @param notify indica se o plugin destinatário deve ser notificado sobre + * o recebimento de uma nova conexão privada. + */ private void startReceiver(TcpConnection connection, boolean notify) { - try { - if (!connection.isPrivate()) { - publicConnectionReceiver(connection); - return; - } - - if (connection.getReceiver().equals(main.getIdentifier())) { - systemConnectionReceiver(connection); - return; - } - - Plugin receiver = findConnectionReceiver(connection); - if (receiver instanceof PrivateConnectionPlugin plugin) { - if (notify) { - plugin.receivePrivateConnection(connection); - } - privateConnectionReceiver(connection, plugin); - } + if (!connection.isPrivate()) { + publicConnectionReceiver(connection); + return; } - catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); + + if (connection.getReceiver().equals(main.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()) { @@ -201,6 +299,19 @@ public class SocketTCP extends Thread { return receiver; } + /** + * Processa continuamente as mensagens recebidas em uma conexão pública. + * + *As mensagens são desserializadas e, quando são instâncias de + * {@link Message}, encaminhadas a todos os plugins da aplicação. Mensagens + * de controle do sistema podem encerrar a conexão ou registrar uma + * 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.
+ * + * @param connection conexão pública da qual as mensagens serão recebidas. + */ private void publicConnectionReceiver(TcpConnection connection) { while (running) { try { @@ -260,6 +371,18 @@ public class SocketTCP extends Thread { } } + /** + * Processa os dados recebidos em uma conexão privada e os encaminha + * ao plugin destinatário. + * + *Dados que não representam mensagens de controle são entregues + * diretamente ao {@link PrivateConnectionPlugin}. Mensagens de controle + * relacionadas ao encerramento ou a erros internos provocam a notificação + * 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) { @@ -295,7 +418,16 @@ public class SocketTCP extends Thread { } } - private void systemConnectionReceiver(TcpConnection connection) throws IOException { + /** + * Processa mensagens recebidas em uma conexão destinada ao próprio sistema. + * + *Atualmente, mensagens destinadas ao sistema são apenas verificadas + * quanto ao seu formato de controle. Não há processamento adicional de + * mensagens de sistema neste método.
+ * + * @param connection conexão destinada ao identificador da própria aplicação. + */ + private void systemConnectionReceiver(TcpConnection connection) { while (running) { try { byte[] message = connection.receive(); @@ -308,12 +440,25 @@ public class SocketTCP extends Thread { //TODO: Ainda não existem mensagens trocadas entre o sistema. } - } catch (SocketTimeoutException ex) { + } + catch (SocketTimeoutException ex) { if (connection.hasTimedOut()) return; } + catch (IOException ex) { + connectionManager.closeConnection(connection); + } } } + /** + * 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}.
+ * + * @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( connection, @@ -321,11 +466,22 @@ public class SocketTCP extends Thread { ); } + @Override public void run() { receive(); } + /** + * Encerra o servidor TCP e libera os recursos associados. + * + *Interrompe o laço de aceitação de conexões, fecha o + * {@link ServerSocket}, encerra todas as conexões gerenciadas e interrompe + * as tarefas do executor.
+ * + *Após a chamada, esta instância não deve ser reutilizada para aceitar + * novas conexões.
+ */ public void close() { running = false; diff --git a/pitiupi/src/pitiupi/net/tcp/TcpConnection.java b/pitiupi/src/pitiupi/net/tcp/TcpConnection.java index 947cb25..be7c0e4 100644 --- a/pitiupi/src/pitiupi/net/tcp/TcpConnection.java +++ b/pitiupi/src/pitiupi/net/tcp/TcpConnection.java @@ -8,16 +8,15 @@ import java.net.Socket; import java.net.SocketException; /** - * Representa uma conexão TCP persistente com um peer. + * Representa uma conexão TCP ativa com um peer remoto. * - *Encapsula o socket e os streams utilizados para enviar e receber - * mensagens. Também é responsável pelo framing das mensagens, permitindo - * que várias mensagens sejam transmitidas pela mesma conexão.
+ *A conexão permite o envio e recebimento de mensagens, além de manter + * informações sobre o endereço remoto e metadados da conexão, como remetente, + * destinatário e se a conexão é privada.
* * @author Gustavo */ public class TcpConnection { - private static final long TIMEOUT = 300_000; // 5 minutos private final Socket socket; private final DataInputStream input; @@ -25,19 +24,35 @@ public class TcpConnection { private final InetAddress address; private String sender; private String receiver; - private boolean isPrivate; - private volatile long lastActivity; + private long timeout; + /** + * Cria uma conexão TCP a partir de um socket existente. + * + * @param socket socket utilizado para a comunicação + * @throws IOException se não for possível obter os fluxos de entrada ou saída + * do socket + */ TcpConnection(Socket socket) throws IOException { this.socket = socket; this.input = new DataInputStream(socket.getInputStream()); this.output = new DataOutputStream(socket.getOutputStream()); this.address = socket.getInetAddress(); this.lastActivity = System.currentTimeMillis(); + this.timeout = 300_000; // 5 minutos } + /** + * Envia uma mensagem pela conexão. + * + *A mensagem é enviada precedida pelo seu tamanho, permitindo que o + * receptor determine quantos bytes devem ser lidos.
+ * + * @param message mensagem a ser enviada + * @throws IOException se ocorrer um erro durante o envio + */ public synchronized void send(byte[] message) throws IOException { output.writeInt(message.length); output.write(message); @@ -45,6 +60,16 @@ public class TcpConnection { updateLastActivity(); } + /** + * Recebe uma mensagem da conexão. + * + *Primeiro lê o tamanho da mensagem e, em seguida, lê aquantidade + * correspondente de bytes.
+ * + * @return mensagem recebida + * @throws IOException se o tamanho da mensagem for inválido ou se a conexão + * for encerrada antes que a mensagem seja completamente recebida + */ byte[] receive() throws IOException { int length = input.readInt(); @@ -61,28 +86,63 @@ public class TcpConnection { return message; } + /** + * Verifica se o socket da conexão está fechado. + * + * @return {@code true} se o socket estiver fechado; + * {@code false} caso contrário + */ public boolean isClosed() { return socket.isClosed(); } + /** + * Fecha o socket da conexão. + * + * @throws IOException se ocorrer um erro ao fechar o socket + */ void close() throws IOException { socket.close(); } + /** + * Retorna o endereço do peer remoto conectado. + * + * @return endereço IP do peer remoto + */ public InetAddress getAddress() { return address; } + /** + * Atualiza o instante da última atividade da conexão. + */ private void updateLastActivity() { lastActivity = System.currentTimeMillis(); } + /** + * Define o tempo limite de leitura do socket. + * + * @param timeout tempo limite, em milissegundos + * @throws SocketException se ocorrer um erro ao definir o tempo limite + */ void setTimeout(int timeout) throws SocketException { socket.setSoTimeout(timeout); + this.timeout = timeout; } + /** + * Verifica se a conexão ficou inativa pelo tempo limite configurado. + * + *A verificação é baseada no instante da última atividade registrada + * durante o envio ou recebimento de uma mensagem.
+ * + * @return {@code true} se a conexão estiver inativa há pelo menos 5 minutos; + * {@code false} caso contrário + */ boolean hasTimedOut() { - return System.currentTimeMillis() - lastActivity >= TIMEOUT; + return System.currentTimeMillis() - lastActivity >= timeout; } public String getReceiver() {