From 63ec7b3aaa4355d46f8a90fb3987190f7685efe0 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Sat, 1 Mar 2025 13:00:58 +0100 Subject: [PATCH] add disconnect --- ChatApp/src/client/Client.java | 3 +- ChatApp/src/client/ClientConnexion.java | 7 ++++ .../src/network/protocol/PacketVisitor.java | 2 + .../protocol/packets/DisconnectPacket.java | 23 ++++++++++ ChatApp/src/server/Server.java | 42 ++++++++++++------- ChatApp/src/server/ServerConnexion.java | 36 ++++++++++------ 6 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 ChatApp/src/network/protocol/packets/DisconnectPacket.java diff --git a/ChatApp/src/client/Client.java b/ChatApp/src/client/Client.java index 826b396..da92c4a 100644 --- a/ChatApp/src/client/Client.java +++ b/ChatApp/src/client/Client.java @@ -5,6 +5,7 @@ import java.net.InetSocketAddress; import java.net.SocketException; import network.protocol.packets.CreateRoomPacket; +import network.protocol.packets.DisconnectPacket; import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LoginPacket; @@ -23,7 +24,7 @@ public class Client { } public void close() { - //TODO: send disconnect packet + this.connexion.sendPacket(new DisconnectPacket("Leaving")); this.connexion.close(); this.callback.handleDisconnect(); } diff --git a/ChatApp/src/client/ClientConnexion.java b/ChatApp/src/client/ClientConnexion.java index 8fb47f4..edce535 100644 --- a/ChatApp/src/client/ClientConnexion.java +++ b/ChatApp/src/client/ClientConnexion.java @@ -11,6 +11,7 @@ import network.protocol.Packet; import network.protocol.PacketVisitor; import network.protocol.packets.ChatMessagePacket; import network.protocol.packets.CreateRoomPacket; +import network.protocol.packets.DisconnectPacket; import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LoginPacket; @@ -68,6 +69,12 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{ this.callback.handleServerResponse(packet.getResponse()); } + @Override + public void visitPacket(DisconnectPacket packet) { + this.close(); + this.callback.handleDisconnect(); + } + @Override public void visitPacket(CreateRoomPacket packet) { throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); diff --git a/ChatApp/src/network/protocol/PacketVisitor.java b/ChatApp/src/network/protocol/PacketVisitor.java index d073f6a..4e69003 100644 --- a/ChatApp/src/network/protocol/PacketVisitor.java +++ b/ChatApp/src/network/protocol/PacketVisitor.java @@ -2,6 +2,7 @@ package network.protocol; import network.protocol.packets.ChatMessagePacket; import network.protocol.packets.CreateRoomPacket; +import network.protocol.packets.DisconnectPacket; import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LoginPacket; @@ -18,6 +19,7 @@ public interface PacketVisitor { void visitPacket(ChatMessagePacket packet); void visitPacket(CreateRoomPacket packet); + void visitPacket(DisconnectPacket packet); void visitPacket(JoinRoomPacket packet); void visitPacket(LeaveRoomPacket packet); void visitPacket(LoginPacket packet); diff --git a/ChatApp/src/network/protocol/packets/DisconnectPacket.java b/ChatApp/src/network/protocol/packets/DisconnectPacket.java new file mode 100644 index 0000000..2d8f854 --- /dev/null +++ b/ChatApp/src/network/protocol/packets/DisconnectPacket.java @@ -0,0 +1,23 @@ +package network.protocol.packets; + +import network.protocol.Packet; +import network.protocol.PacketVisitor; + +public class DisconnectPacket extends Packet { + + private final String reason; + + public DisconnectPacket(String reason) { + this.reason = reason; + } + + public String getReason() { + return reason; + } + + @Override + public void accept(PacketVisitor packetVisitor) { + packetVisitor.visitPacket(this); + } + +} diff --git a/ChatApp/src/server/Server.java b/ChatApp/src/server/Server.java index ad9997b..0652298 100644 --- a/ChatApp/src/server/Server.java +++ b/ChatApp/src/server/Server.java @@ -19,21 +19,21 @@ public class Server implements PacketHandler { private final DatagramSocket serverSocket; private final Map connexions; private final SocketReader reader; - private final Map> roomNames; + private final Map> rooms; public Server(int port) throws SocketException { this.serverSocket = new DatagramSocket(port); this.connexions = new HashMap<>(); this.reader = new SocketReader(serverSocket, this); - this.roomNames = new HashMap<>(); + this.rooms = new HashMap<>(); } public ArrayList getRoomNames() { - return roomNames.keySet().stream().collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + return rooms.keySet().stream().collect(ArrayList::new, ArrayList::add, ArrayList::addAll); } public String getRoomName(ServerConnexion connexion) { - for (Map.Entry> entry : roomNames.entrySet()) { + for (Map.Entry> entry : rooms.entrySet()) { if(entry.getValue().contains(connexion)) { return entry.getKey(); } @@ -42,20 +42,20 @@ public class Server implements PacketHandler { } public void createRoom(String roomName, ServerConnexion connexion) throws SocketException { - if(roomNames.containsKey(roomName)) { + if(rooms.containsKey(roomName)) { throw new SocketException("Room already exists"); } - roomNames.put(roomName, new ArrayList<>()); - roomNames.get(roomName).add(connexion); + rooms.put(roomName, new ArrayList<>()); + rooms.get(roomName).add(connexion); } public void leaveRoom(ServerConnexion connexion) throws SocketException { String roomName = getRoomName(connexion); if(roomName != null) { - roomNames.get(roomName).remove(connexion); + rooms.get(roomName).remove(connexion); // Remove the room if it is empty - if(roomNames.get(roomName).isEmpty()) { - roomNames.remove(roomName); + if(rooms.get(roomName).isEmpty()) { + rooms.remove(roomName); } return; } @@ -63,8 +63,8 @@ public class Server implements PacketHandler { } public void joinRoom(String roomName, ServerConnexion connexion) throws SocketException { - if(roomNames.containsKey(roomName) && !roomNames.get(roomName).contains(connexion)) { - roomNames.get(roomName).add(connexion); + if(rooms.containsKey(roomName) && !rooms.get(roomName).contains(connexion)) { + rooms.get(roomName).add(connexion); return; } throw new SocketException("Room does not exist"); @@ -73,8 +73,8 @@ public class Server implements PacketHandler { public void sendToRoom(ServerConnexion connexion, SendChatMessagePacket packet) throws SocketException { String roomName = getRoomName(connexion); ChatMessagePacket chatPacket = new ChatMessagePacket(Instant.now(), connexion.getChatterName(), packet.getContent()); - if(roomName != null && roomNames.containsKey(roomName)) { - roomNames.get(roomName).forEach(con -> con.sendPacket(chatPacket)); + if(roomName != null && rooms.containsKey(roomName)) { + rooms.get(roomName).forEach(con -> con.sendPacket(chatPacket)); return; } throw new SocketException("You are not in a room or the room does not exist"); @@ -89,6 +89,20 @@ public class Server implements PacketHandler { .anyMatch(connexion -> pseudo.equals(connexion.getChatterName())); } + void removeConnexion(ServerConnexion connexion) { + for (var it = this.connexions.entrySet().iterator(); it.hasNext();) { + var entry = it.next(); + if (entry.getValue() == connexion) { + it.remove(); + break; + } + } + for (var entry : this.rooms.entrySet()) { + if (entry.getValue().remove(connexion)) + return; + } + } + @Override public void handlePacket(Packet packet, InetSocketAddress address) { if (!connexions.containsKey(address)) { diff --git a/ChatApp/src/server/ServerConnexion.java b/ChatApp/src/server/ServerConnexion.java index 5112dfa..5e42f94 100644 --- a/ChatApp/src/server/ServerConnexion.java +++ b/ChatApp/src/server/ServerConnexion.java @@ -10,6 +10,7 @@ import network.protocol.Packet; import network.protocol.PacketVisitor; import network.protocol.packets.ChatMessagePacket; import network.protocol.packets.CreateRoomPacket; +import network.protocol.packets.DisconnectPacket; import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LoginPacket; @@ -41,15 +42,10 @@ public class ServerConnexion implements PacketVisitor { this.writer.sendPacket(packet, clientAddress); } catch (IOException e) { e.printStackTrace(); + this.server.removeConnexion(this); } } - @Override - public void visitPacket(ChatMessagePacket packet) { - // I'm never supposed to receive this from the client - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); - } - @Override public void visitPacket(CreateRoomPacket packet) { try { @@ -97,12 +93,6 @@ public class ServerConnexion implements PacketVisitor { sendPacket(new RoomListPacket(server.getRoomNames())); } - @Override - public void visitPacket(RoomListPacket packet) { - // I'm never supposed to receive this from the client - throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); - } - @Override public void visitPacket(SendChatMessagePacket packet) { try { @@ -112,6 +102,28 @@ public class ServerConnexion implements PacketVisitor { } } + @Override + public void visitPacket(DisconnectPacket packet) { + this.onDisconnect(); + } + + private void onDisconnect() { + this.server.removeConnexion(this); + System.out.println("[Server] Chatter " + chatterName + " disconnected !"); + } + + @Override + public void visitPacket(RoomListPacket packet) { + // I'm never supposed to receive this from the client + throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + } + + @Override + public void visitPacket(ChatMessagePacket packet) { + // I'm never supposed to receive this from the client + throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); + } + @Override public void visitPacket(ServerResponsePacket packet) { // I'm never supposed to receive this from the client