Compare commits

..

2 Commits

Author SHA1 Message Date
0533c16cf2 refactor server room operations 2025-03-01 13:06:55 +01:00
63ec7b3aaa add disconnect 2025-03-01 13:00:58 +01:00
6 changed files with 105 additions and 60 deletions

View File

@@ -5,6 +5,7 @@ import java.net.InetSocketAddress;
import java.net.SocketException; import java.net.SocketException;
import network.protocol.packets.CreateRoomPacket; import network.protocol.packets.CreateRoomPacket;
import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.JoinRoomPacket;
import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LeaveRoomPacket;
import network.protocol.packets.LoginPacket; import network.protocol.packets.LoginPacket;
@@ -23,7 +24,7 @@ public class Client {
} }
public void close() { public void close() {
//TODO: send disconnect packet this.connexion.sendPacket(new DisconnectPacket("Leaving"));
this.connexion.close(); this.connexion.close();
this.callback.handleDisconnect(); this.callback.handleDisconnect();
} }

View File

@@ -11,6 +11,7 @@ import network.protocol.Packet;
import network.protocol.PacketVisitor; import network.protocol.PacketVisitor;
import network.protocol.packets.ChatMessagePacket; import network.protocol.packets.ChatMessagePacket;
import network.protocol.packets.CreateRoomPacket; import network.protocol.packets.CreateRoomPacket;
import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.JoinRoomPacket;
import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LeaveRoomPacket;
import network.protocol.packets.LoginPacket; import network.protocol.packets.LoginPacket;
@@ -68,6 +69,12 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{
this.callback.handleServerResponse(packet.getResponse()); this.callback.handleServerResponse(packet.getResponse());
} }
@Override
public void visitPacket(DisconnectPacket packet) {
this.close();
this.callback.handleDisconnect();
}
@Override @Override
public void visitPacket(CreateRoomPacket packet) { public void visitPacket(CreateRoomPacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); throw new UnsupportedOperationException("Unimplemented method 'visitPacket'");

View File

@@ -2,6 +2,7 @@ package network.protocol;
import network.protocol.packets.ChatMessagePacket; import network.protocol.packets.ChatMessagePacket;
import network.protocol.packets.CreateRoomPacket; import network.protocol.packets.CreateRoomPacket;
import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.JoinRoomPacket;
import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LeaveRoomPacket;
import network.protocol.packets.LoginPacket; import network.protocol.packets.LoginPacket;
@@ -18,6 +19,7 @@ public interface PacketVisitor {
void visitPacket(ChatMessagePacket packet); void visitPacket(ChatMessagePacket packet);
void visitPacket(CreateRoomPacket packet); void visitPacket(CreateRoomPacket packet);
void visitPacket(DisconnectPacket packet);
void visitPacket(JoinRoomPacket packet); void visitPacket(JoinRoomPacket packet);
void visitPacket(LeaveRoomPacket packet); void visitPacket(LeaveRoomPacket packet);
void visitPacket(LoginPacket packet); void visitPacket(LoginPacket packet);

View File

@@ -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);
}
}

View File

@@ -19,21 +19,21 @@ public class Server implements PacketHandler {
private final DatagramSocket serverSocket; private final DatagramSocket serverSocket;
private final Map<InetSocketAddress, ServerConnexion> connexions; private final Map<InetSocketAddress, ServerConnexion> connexions;
private final SocketReader reader; private final SocketReader reader;
private final Map<String, ArrayList<ServerConnexion>> roomNames; private final Map<String, ArrayList<ServerConnexion>> rooms;
public Server(int port) throws SocketException { public Server(int port) throws SocketException {
this.serverSocket = new DatagramSocket(port); this.serverSocket = new DatagramSocket(port);
this.connexions = new HashMap<>(); this.connexions = new HashMap<>();
this.reader = new SocketReader(serverSocket, this); this.reader = new SocketReader(serverSocket, this);
this.roomNames = new HashMap<>(); this.rooms = new HashMap<>();
} }
public ArrayList<String> getRoomNames() { public ArrayList<String> 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) { public String getRoomName(ServerConnexion connexion) {
for (Map.Entry<String, ArrayList<ServerConnexion>> entry : roomNames.entrySet()) { for (Map.Entry<String, ArrayList<ServerConnexion>> entry : rooms.entrySet()) {
if (entry.getValue().contains(connexion)) { if (entry.getValue().contains(connexion)) {
return entry.getKey(); return entry.getKey();
} }
@@ -41,43 +41,45 @@ public class Server implements PacketHandler {
return null; return null;
} }
public void createRoom(String roomName, ServerConnexion connexion) throws SocketException { public boolean createRoom(String roomName, ServerConnexion connexion) {
if(roomNames.containsKey(roomName)) { if (rooms.containsKey(roomName)) {
throw new SocketException("Room already exists"); return false;
} }
roomNames.put(roomName, new ArrayList<>()); rooms.put(roomName, new ArrayList<>());
roomNames.get(roomName).add(connexion); rooms.get(roomName).add(connexion);
return true;
} }
public void leaveRoom(ServerConnexion connexion) throws SocketException { public boolean leaveRoom(ServerConnexion connexion) {
String roomName = getRoomName(connexion); String roomName = getRoomName(connexion);
if (roomName != null) { if (roomName != null) {
roomNames.get(roomName).remove(connexion); rooms.get(roomName).remove(connexion);
// Remove the room if it is empty // Remove the room if it is empty
if(roomNames.get(roomName).isEmpty()) { if (rooms.get(roomName).isEmpty()) {
roomNames.remove(roomName); rooms.remove(roomName);
} }
return; return true;
} }
throw new SocketException("Room does not exist"); return false;
} }
public void joinRoom(String roomName, ServerConnexion connexion) throws SocketException { public boolean joinRoom(String roomName, ServerConnexion connexion) {
if(roomNames.containsKey(roomName) && !roomNames.get(roomName).contains(connexion)) { if (rooms.containsKey(roomName) && !rooms.get(roomName).contains(connexion)) {
roomNames.get(roomName).add(connexion); rooms.get(roomName).add(connexion);
return; return true;
} }
throw new SocketException("Room does not exist"); return false;
} }
public void sendToRoom(ServerConnexion connexion, SendChatMessagePacket packet) throws SocketException { public boolean sendToRoom(ServerConnexion connexion, SendChatMessagePacket packet) {
String roomName = getRoomName(connexion); String roomName = getRoomName(connexion);
ChatMessagePacket chatPacket = new ChatMessagePacket(Instant.now(), connexion.getChatterName(), packet.getContent()); ChatMessagePacket chatPacket = new ChatMessagePacket(Instant.now(), connexion.getChatterName(),
if(roomName != null && roomNames.containsKey(roomName)) { packet.getContent());
roomNames.get(roomName).forEach(con -> con.sendPacket(chatPacket)); if (roomName != null && rooms.containsKey(roomName)) {
return; rooms.get(roomName).forEach(con -> con.sendPacket(chatPacket));
return true;
} }
throw new SocketException("You are not in a room or the room does not exist"); return false;
} }
public void close() { public void close() {
@@ -89,6 +91,20 @@ public class Server implements PacketHandler {
.anyMatch(connexion -> pseudo.equals(connexion.getChatterName())); .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 @Override
public void handlePacket(Packet packet, InetSocketAddress address) { public void handlePacket(Packet packet, InetSocketAddress address) {
if (!connexions.containsKey(address)) { if (!connexions.containsKey(address)) {

View File

@@ -3,13 +3,13 @@ package server;
import java.io.IOException; import java.io.IOException;
import java.net.DatagramSocket; import java.net.DatagramSocket;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketException;
import network.SocketWriter; import network.SocketWriter;
import network.protocol.Packet; import network.protocol.Packet;
import network.protocol.PacketVisitor; import network.protocol.PacketVisitor;
import network.protocol.packets.ChatMessagePacket; import network.protocol.packets.ChatMessagePacket;
import network.protocol.packets.CreateRoomPacket; import network.protocol.packets.CreateRoomPacket;
import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.JoinRoomPacket; import network.protocol.packets.JoinRoomPacket;
import network.protocol.packets.LeaveRoomPacket; import network.protocol.packets.LeaveRoomPacket;
import network.protocol.packets.LoginPacket; import network.protocol.packets.LoginPacket;
@@ -41,43 +41,26 @@ public class ServerConnexion implements PacketVisitor {
this.writer.sendPacket(packet, clientAddress); this.writer.sendPacket(packet, clientAddress);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); 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 @Override
public void visitPacket(CreateRoomPacket packet) { public void visitPacket(CreateRoomPacket packet) {
try { boolean created = server.createRoom(packet.getRoomName(), this);
server.createRoom(packet.getRoomName(), this); sendPacket(new ServerResponsePacket(created ? Response.RoomCreated : Response.RoomNotCreated));
sendPacket(new ServerResponsePacket(Response.RoomCreated));
} catch (SocketException e) {
sendPacket(new ServerResponsePacket(Response.RoomNotCreated));
}
} }
@Override @Override
public void visitPacket(JoinRoomPacket packet) { public void visitPacket(JoinRoomPacket packet) {
try { boolean joined = server.joinRoom(packet.getRoomName(), this);
server.joinRoom(packet.getRoomName(), this); sendPacket(new ServerResponsePacket(joined ? Response.RoomJoined : Response.RoomNotJoined));
sendPacket(new ServerResponsePacket(Response.RoomJoined));
} catch (SocketException e) {
sendPacket(new ServerResponsePacket(Response.RoomNotJoined));
}
} }
@Override @Override
public void visitPacket(LeaveRoomPacket packet) { public void visitPacket(LeaveRoomPacket packet) {
try { boolean left = server.leaveRoom(this);
server.leaveRoom(this); sendPacket(new ServerResponsePacket(left ? Response.RoomLeft : Response.RoomNotLeft));
sendPacket(new ServerResponsePacket(Response.RoomLeft));
} catch (SocketException e) {
sendPacket(new ServerResponsePacket(Response.RoomNotLeft));
}
} }
@Override @Override
@@ -97,6 +80,22 @@ public class ServerConnexion implements PacketVisitor {
sendPacket(new RoomListPacket(server.getRoomNames())); sendPacket(new RoomListPacket(server.getRoomNames()));
} }
@Override
public void visitPacket(SendChatMessagePacket packet) {
boolean messageSent = server.sendToRoom(this, packet);
sendPacket(new ServerResponsePacket(messageSent ? Response.MessageSent : Response.MessageNotSent));
}
@Override
public void visitPacket(DisconnectPacket packet) {
this.onDisconnect();
}
private void onDisconnect() {
this.server.removeConnexion(this);
System.out.println("[Server] Chatter " + chatterName + " disconnected !");
}
@Override @Override
public void visitPacket(RoomListPacket packet) { public void visitPacket(RoomListPacket packet) {
// I'm never supposed to receive this from the client // I'm never supposed to receive this from the client
@@ -104,12 +103,9 @@ public class ServerConnexion implements PacketVisitor {
} }
@Override @Override
public void visitPacket(SendChatMessagePacket packet) { public void visitPacket(ChatMessagePacket packet) {
try { // I'm never supposed to receive this from the client
server.sendToRoom(this, packet); throw new UnsupportedOperationException("Unimplemented method 'visitPacket'");
} catch (SocketException e) {
sendPacket(new ServerResponsePacket(Response.MessageNotSent));
}
} }
@Override @Override