diff --git a/ChatApp/app/src/main/java/client/ClientConnexion.java b/ChatApp/app/src/main/java/client/ClientConnexion.java index f664170..6d2c63b 100644 --- a/ChatApp/app/src/main/java/client/ClientConnexion.java +++ b/ChatApp/app/src/main/java/client/ClientConnexion.java @@ -65,11 +65,6 @@ public class ClientConnexion implements PacketVisitor, PacketHandler { this.callback.handleConnect(); } - @Override - public void visitPacket(RequestActualRoomPacket packet) { - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); - } - @Override public void visitPacket(ActualRoomPacket packet) { this.callback.handleActualRoom(packet.getRoomName()); @@ -81,6 +76,15 @@ public class ClientConnexion implements PacketVisitor, PacketHandler { this.callback.handleDisconnect(); } + public void changeCallback(ClientListener callback) { + this.callback = callback; + } + + @Override + public void visitPacket(RequestActualRoomPacket packet) { + throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + } + @Override public void visitPacket(CreateRoomPacket packet) { throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); @@ -110,8 +114,4 @@ public class ClientConnexion implements PacketVisitor, PacketHandler { public void visitPacket(SendChatMessagePacket packet) { throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); } - - public void changeCallback(ClientListener callback) { - this.callback = callback; - } } diff --git a/ChatApp/app/src/main/java/network/PacketPool.java b/ChatApp/app/src/main/java/network/PacketPool.java index 65869ef..32832f1 100644 --- a/ChatApp/app/src/main/java/network/PacketPool.java +++ b/ChatApp/app/src/main/java/network/PacketPool.java @@ -42,6 +42,9 @@ public class PacketPool { } } + /** + * Data specific to one connexion + */ private static class AdressContext { public int currentSeqRecv = 0; public int currentSeqSend = 0; @@ -50,22 +53,43 @@ public class PacketPool { public final Map packetsSentTries = new HashMap<>(); } + /** + * @param address the address to send to + * @return The next send sequence + */ private int getNextSeqSend(InetSocketAddress address) { return this.addressContexts.get(address).currentSeqSend++; } + /** + * @param address the address which a packet was recieved + * @return the current recieve sequence number + */ private int getCurrentSeqRecv(InetSocketAddress address) { return this.addressContexts.get(address).currentSeqRecv; } + /** + * Set the recieve sequence number + * @param address + * @param newValue + */ private void setSeqRecv(InetSocketAddress address, int newValue) { this.addressContexts.get(address).currentSeqRecv = newValue; } + /** + * Try to add the address into memory + * @param address + */ private void tryAddContext(InetSocketAddress address) { this.addressContexts.putIfAbsent(address, new AdressContext()); } + /** + * Construct a PacketPool + * @param socket + */ public PacketPool(Socket socket) { this.socket = socket; this.packetQueue = new Stack<>(); @@ -88,6 +112,12 @@ public class PacketPool { + " with seq : " + packet.getSeq()); } + /** + * Send a packet to the socket + * @param packet + * @param address + * @throws IOException + */ private void sendPacketToSocket(ReliablePacket packet, InetSocketAddress address) throws IOException { var packetsSentTries = this.addressContexts.get(address).packetsSentTries; @@ -112,6 +142,12 @@ public class PacketPool { } } + /** + * Send a packet to socket and try to resend if an acknowlegment was not recieved + * @param packet + * @param address + * @throws IOException + */ private synchronized void sendPacket(ReliablePacket packet, InetSocketAddress address) throws IOException { sendPacketToSocket(packet, address); debugSend(packet, address); @@ -125,12 +161,22 @@ public class PacketPool { } } + /** + * Send a packet (and encapsulate it) + * @param packet + * @param address + * @throws IOException + */ public synchronized void sendPacket(Packet packet, InetSocketAddress address) throws IOException { tryAddContext(address); ReliablePacket reliablePacket = new ReliablePacket(packet, getNextSeqSend(address)); sendPacket(reliablePacket, address); } + /** + * Try to resend a packet + * @param reliablePacketAddress + */ private void tryResend(ReliablePacketAddress reliablePacketAddress) { try { while (!Thread.interrupted()) { @@ -166,6 +212,11 @@ public class PacketPool { ctx.sendThreads.remove(Thread.currentThread()); } + + /** + * @param address + * @return The smallest sequence number recieved + */ private ReliablePacket getMinimumSeqReceived(InetSocketAddress address) { List packetRecvBuffer = this.addressContexts.get(address).packetRecvBuffer; if (packetRecvBuffer.isEmpty()) @@ -175,6 +226,11 @@ public class PacketPool { }); } + /** + * Move packets in buffer to the packet recieved queue to be processed by the app + * @param address + * @return the sequence number of the last packet that was added to the queue + */ private int fillPacketQueue(InetSocketAddress address) { List packetRecvBuffer = this.addressContexts.get(address).packetRecvBuffer; ReliablePacket minimum = getMinimumSeqReceived(address); @@ -193,6 +249,12 @@ public class PacketPool { return lastSeqProcessed; } + /** + * Process packet when recieved + * @param packet + * @param address + * @throws IOException + */ public void onPacketReceived(ReliablePacket packet, InetSocketAddress address) throws IOException { tryAddContext(address); @@ -236,6 +298,9 @@ public class PacketPool { } + /** + * @return The next packet in the queue + */ public Entry getNextPacket() { if (this.packetQueue.isEmpty()) return null; @@ -244,18 +309,29 @@ public class PacketPool { return entry; } + /** + * Closes the connexion + * @param adress + */ private void close(InetSocketAddress adress) { var ctx = this.addressContexts.get(adress); if (ctx != null) close(ctx); } + /** + * Stop the threads of the connexion + * @param adressContext + */ private void close(AdressContext adressContext) { for (Thread thread : adressContext.sendThreads) { thread.interrupt(); } } + /** + * Stop the PacketPool + */ public void close() { for (AdressContext adressContext : this.addressContexts.values()) { close(adressContext); diff --git a/ChatApp/app/src/main/java/network/ReliablePacket.java b/ChatApp/app/src/main/java/network/ReliablePacket.java index 12a62c6..893e6c6 100644 --- a/ChatApp/app/src/main/java/network/ReliablePacket.java +++ b/ChatApp/app/src/main/java/network/ReliablePacket.java @@ -14,10 +14,16 @@ public class ReliablePacket implements Serializable { this.seq = seq; } + /** + * @return The encapsulated packet + */ public Packet getPacket() { return packet; } + /** + * @return The sequence number of this packet + */ public int getSeq() { return seq; } diff --git a/ChatApp/app/src/main/java/network/Socket.java b/ChatApp/app/src/main/java/network/Socket.java index f758aad..4850ad3 100644 --- a/ChatApp/app/src/main/java/network/Socket.java +++ b/ChatApp/app/src/main/java/network/Socket.java @@ -23,6 +23,10 @@ public class Socket { public final Signal onClose = new Signal(); + /** + * Construct a UDP Socket to connect to a server + * @throws SocketException + */ public Socket() throws SocketException { this.socket = new DatagramSocket(); this.handlers = new ArrayList<>(); @@ -31,6 +35,11 @@ public class Socket { this.readThread.start(); } + /** + * Construct a UDP Socket to listen to connexion at the specified port + * @param listeningPort the port to listen to + * @throws SocketException + */ public Socket(int listeningPort) throws SocketException { this.socket = new DatagramSocket(listeningPort); this.handlers = new ArrayList<>(); @@ -43,11 +52,20 @@ public class Socket { this.handlers.add(handler); } + /** + * @return this.socket.getLocalPort() + */ public int getLocalPort() { return this.socket.getLocalPort(); } // needs to be accessible by PacketPool + /** + * Send a packet to the specified address + * @param packet the packet to send + * @param address the address to send to + * @throws IOException + */ void sendPacket(ReliablePacket packet, InetSocketAddress address) throws IOException { ByteArrayOutputStream stream = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(stream); @@ -59,6 +77,12 @@ public class Socket { this.socket.send(dataPacket); } + /** + * Try to recieve packets and send them to the PacketPool. + * This method blocks until something has been read + * @throws IOException + * @throws ClassNotFoundException + */ private void recievePacketReliable() throws IOException, ClassNotFoundException { byte[] buffer = new byte[65535]; @@ -73,10 +97,22 @@ public class Socket { this.packetPool.onPacketReceived(packet, address); } + /** + * Send a packet to the specified address + * @param packet the packet to send + * @param address the address to send to + * @throws IOException + */ public void sendPacket(Packet packet, InetSocketAddress address) throws IOException { this.packetPool.sendPacket(packet, address); } + /** + * Recieve packet in a reliable way (packets are in the right order). + * This method is blocking + * @throws IOException + * @throws ClassNotFoundException + */ private void recievePacket() throws IOException, ClassNotFoundException { this.recievePacketReliable(); var entry = this.packetPool.getNextPacket(); @@ -86,6 +122,9 @@ public class Socket { } } + /** + * Close the socket + */ public void close() { this.socket.close(); this.packetPool.close(); @@ -93,12 +132,20 @@ public class Socket { this.onClose.emit(); } + /** + * Dispatch the packet + * @param packet the packet to dispatch + * @param address the incoming address + */ void handlePacket(Packet packet, InetSocketAddress address) { for (PacketHandler handler : this.handlers) { handler.handlePacket(packet, address); } } + /** + * Loop to read all packets + */ private void readLoop() { try { while (!Thread.interrupted()) { diff --git a/ChatApp/app/src/main/java/network/protocol/Packet.java b/ChatApp/app/src/main/java/network/protocol/Packet.java index dc1d7f2..ee66381 100644 --- a/ChatApp/app/src/main/java/network/protocol/Packet.java +++ b/ChatApp/app/src/main/java/network/protocol/Packet.java @@ -4,6 +4,10 @@ import java.io.Serializable; public abstract class Packet implements Serializable { + /** + * Used for double dispatch + * @param packetVisitor the visitor to dispatch to + */ public abstract void accept(PacketVisitor packetVisitor); } diff --git a/ChatApp/app/src/main/java/network/protocol/PacketVisitor.java b/ChatApp/app/src/main/java/network/protocol/PacketVisitor.java index b925726..3f7a132 100644 --- a/ChatApp/app/src/main/java/network/protocol/PacketVisitor.java +++ b/ChatApp/app/src/main/java/network/protocol/PacketVisitor.java @@ -4,6 +4,10 @@ import network.protocol.packets.*; public interface PacketVisitor { + /** + * Use double dispatch to process a packet + * @param packet the packet to process + */ default void visit(Packet packet) { packet.accept(this); } diff --git a/ChatApp/app/src/main/java/network/protocol/packets/AcknowlegdementPacket.java b/ChatApp/app/src/main/java/network/protocol/packets/AcknowlegdementPacket.java index 39001e9..6592c10 100644 --- a/ChatApp/app/src/main/java/network/protocol/packets/AcknowlegdementPacket.java +++ b/ChatApp/app/src/main/java/network/protocol/packets/AcknowlegdementPacket.java @@ -13,7 +13,7 @@ public class AcknowlegdementPacket extends Packet { @Override public void accept(PacketVisitor packetVisitor) { - + // this packet should not be handled by the app } public int getAck() {