diff --git a/ChatApp/src/ChatApp.java b/ChatApp/src/ChatApp.java index 26ba79e..cd591ae 100644 --- a/ChatApp/src/ChatApp.java +++ b/ChatApp/src/ChatApp.java @@ -1,23 +1,21 @@ import java.net.InetSocketAddress; -import java.util.Scanner; -import client.Client; +import client.ClientConsole; import server.Server; public class ChatApp { public static void main(String[] args) throws Exception { Server server = new Server(6665); - Client client = new Client(new InetSocketAddress("localhost", 6665)); + ClientConsole client = new ClientConsole(new InetSocketAddress("localhost", 6665)); - client.SendCreateRoom("101"); + client.getClientInterface().SendCreateRoom("101"); - Scanner scanner = new Scanner(System.in); - while (true) { - String message = scanner.nextLine(); - System.out.print("\033[1A"); - System.out.print("\r\033[2K"); - System.out.flush(); - client.visitMessage(message); - } + client.joinThread(); + + System.out.println("Stopping server ..."); + + server.close(); + + System.out.println("Done !"); } } diff --git a/ChatApp/src/client/Client.java b/ChatApp/src/client/Client.java index 52f5bb5..826b396 100644 --- a/ChatApp/src/client/Client.java +++ b/ChatApp/src/client/Client.java @@ -1,118 +1,54 @@ package client; -import java.io.IOException; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; -import java.util.Objects; -import java.util.Scanner; -import network.protocol.packets.*; +import network.protocol.packets.CreateRoomPacket; +import network.protocol.packets.JoinRoomPacket; +import network.protocol.packets.LeaveRoomPacket; +import network.protocol.packets.LoginPacket; +import network.protocol.packets.RequestRoomListPacket; +import network.protocol.packets.SendChatMessagePacket; public class Client { private final ClientConnexion connexion; + private final ClientListener callback; - public static void main(String[] args) { - String host = "localhost"; - int port = 6665; - try { - Client client = new Client(new InetSocketAddress(host, port)); - Scanner scanner = new Scanner(System.in); - while(true) { - String message = scanner.nextLine(); - client.visitMessage(message); - } - } catch (SocketException e) { - e.printStackTrace(); - } - } - - public Client(InetSocketAddress serverAddress) throws SocketException { - this.connexion = new ClientConnexion(new DatagramSocket(), serverAddress); - Scanner scanner = new Scanner(System.in); - System.out.println("Enter your pseudo:"); - String pseudo = scanner.nextLine(); + public Client(InetSocketAddress serverAddress, ClientListener callback, String pseudo) throws SocketException { + this.connexion = new ClientConnexion(new DatagramSocket(), serverAddress, callback); + this.callback = callback; login(pseudo); } - public void visitMessage(String message){ - try { - if(message.startsWith("/")){ - if(message.startsWith("/createRoom")) { - String roomName = message.substring(12).trim(); - SendCreateRoom(roomName); - } else if(message.startsWith("/listRooms")) { - RequestRoomList(); - } else if(message.startsWith("/joinRoom")) { - String roomName = message.substring(10).trim(); - SendJoinRoom(roomName); - } else if(message.startsWith("/leaveRoom")) { - SendLeaveRoom(); - } else if(message.startsWith("/help")) { - System.out.println("Available commands:"); - System.out.println("\t/createRoom "); - System.out.println("\t/listRooms"); - System.out.println("\t/joinRoom "); - System.out.println("\t/leaveRoom"); - System.out.println("\t/help"); - } - else { - System.out.println("Unknown command"); - } - } else { - SendChatMessage(message); - } - } catch (Exception e) { - e.printStackTrace(); - } + public void close() { + //TODO: send disconnect packet + this.connexion.close(); + this.callback.handleDisconnect(); } private void login(String pseudo) { - try { - this.connexion.sendPacket(new LoginPacket(pseudo)); - } catch (IOException e) { - e.printStackTrace(); - } + this.connexion.sendPacket(new LoginPacket(pseudo)); } public void SendChatMessage(String message) { - try { - this.connexion.sendPacket(new SendChatMessagePacket(message)); - } catch (IOException e) { - e.printStackTrace(); - } + this.connexion.sendPacket(new SendChatMessagePacket(message)); } public void SendCreateRoom(String roomName) { - try { - this.connexion.sendPacket(new CreateRoomPacket(roomName)); - } catch (Exception e) { - e.printStackTrace(); - } + this.connexion.sendPacket(new CreateRoomPacket(roomName)); } public void SendJoinRoom(String roomName) { - try { - this.connexion.sendPacket(new JoinRoomPacket(roomName)); - } catch (Exception e) { - e.printStackTrace(); - } + this.connexion.sendPacket(new JoinRoomPacket(roomName)); } public void SendLeaveRoom() { - try { - this.connexion.sendPacket(new LeaveRoomPacket()); - } catch (Exception e) { - e.printStackTrace(); - } + this.connexion.sendPacket(new LeaveRoomPacket()); } public void RequestRoomList() { - try { - this.connexion.sendPacket(new RequestRoomListPacket()); - } catch (Exception e) { - e.printStackTrace(); - } + this.connexion.sendPacket(new RequestRoomListPacket()); } } diff --git a/ChatApp/src/client/ClientConnexion.java b/ChatApp/src/client/ClientConnexion.java index 4a40f04..8fb47f4 100644 --- a/ChatApp/src/client/ClientConnexion.java +++ b/ChatApp/src/client/ClientConnexion.java @@ -7,7 +7,6 @@ import java.net.InetSocketAddress; import network.PacketHandler; import network.SocketReader; import network.SocketWriter; -import network.protocol.ANSIColor; import network.protocol.Packet; import network.protocol.PacketVisitor; import network.protocol.packets.ChatMessagePacket; @@ -25,19 +24,27 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{ private final InetSocketAddress serverAddress; private final SocketWriter writer; private final SocketReader reader; + private final ClientListener callback; - public ClientConnexion(DatagramSocket socket, InetSocketAddress serverAddress) { + public ClientConnexion(DatagramSocket socket, InetSocketAddress serverAddress, ClientListener callback) { this.serverAddress = serverAddress; this.writer = new SocketWriter(socket); this.reader = new SocketReader(socket, this); + this.callback = callback; } public void close() { this.reader.stop(); } - public void sendPacket(Packet packet) throws IOException { - this.writer.sendPacket(packet, serverAddress); + public void sendPacket(Packet packet) { + try { + this.writer.sendPacket(packet, serverAddress); + } catch (IOException e) { + this.close(); + this.callback.handleDisconnect(); + e.printStackTrace(); + } } @Override @@ -48,16 +55,17 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{ @Override public void visitPacket(ChatMessagePacket packet) { - StringBuilder sb = new StringBuilder(); - String time = packet.getTime().toString(); - sb.append("&y["); - sb.append(time, 11, 19); // We only take the HH:MM:SS part - sb.append("]&n"); - sb.append(" "); - sb.append(packet.getChatter()); - sb.append(" : "); - sb.append(packet.getContent()).append("&n"); // make the color back to normal at the end of every message - System.out.println(ANSIColor.formatString(sb.toString())); + this.callback.handleChatMessage(packet.getTime(), packet.getChatter(), packet.getContent()); + } + + @Override + public void visitPacket(RoomListPacket packet) { + this.callback.handleRoomList(packet.getRoomNames()); + } + + @Override + public void visitPacket(ServerResponsePacket packet) { + this.callback.handleServerResponse(packet.getResponse()); } @Override @@ -85,25 +93,9 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{ throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); } - @Override - public void visitPacket(RoomListPacket packet) { - System.out.println("Rooms :"); - for (String room : packet.getRoomNames()) { - System.out.println("\t" + room); - } - } - @Override public void visitPacket(SendChatMessagePacket packet) { throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); } - - @Override - public void visitPacket(ServerResponsePacket packet) { - if(packet.getResponse() == ServerResponsePacket.Response.MessageSent || packet.getResponse() == ServerResponsePacket.Response.MessageNotSent) { - return; - } - System.out.println(packet.getResponse()); - } - + } diff --git a/ChatApp/src/client/ClientConsole.java b/ChatApp/src/client/ClientConsole.java new file mode 100644 index 0000000..b23c3a7 --- /dev/null +++ b/ChatApp/src/client/ClientConsole.java @@ -0,0 +1,128 @@ +package client; + +import java.net.InetSocketAddress; +import java.net.SocketException; +import java.time.Instant; +import java.util.List; +import java.util.Scanner; + +import network.protocol.ANSIColor; +import network.protocol.packets.ServerResponsePacket; +import network.protocol.packets.ServerResponsePacket.Response; + +public class ClientConsole implements ClientListener { + + private Client client; + private final Thread inputThread; + private final Scanner scanner; + + public static void main(String[] args) { + new ClientConsole(new InetSocketAddress("localhost", 6665)); + } + + public ClientConsole(InetSocketAddress address) { + this.inputThread = new Thread(this::inputLoop); + this.scanner = new Scanner(System.in); + String pseudo = inputPseudo(); + try { + this.client = new Client(address, this, pseudo); + this.inputThread.start(); + } catch (SocketException e) { + e.printStackTrace(); + } + } + + private String inputPseudo() { + System.out.println("Enter your pseudo:"); + String pseudo = this.scanner.nextLine(); + return pseudo; + } + + public Client getClientInterface() { + return this.client; + } + + private void inputLoop() { + while (!Thread.interrupted()) { + String message = scanner.nextLine(); + visitMessage(message); + } + this.scanner.close(); + } + + public void joinThread() throws InterruptedException { + this.inputThread.join(); + } + + private void visitMessage(String message) { + try { + if (message.startsWith("/")) { + if (message.startsWith("/createRoom")) { + String roomName = message.substring(12).trim(); + this.client.SendCreateRoom(roomName); + } else if (message.startsWith("/listRooms")) { + this.client.RequestRoomList(); + } else if (message.startsWith("/joinRoom")) { + String roomName = message.substring(10).trim(); + this.client.SendJoinRoom(roomName); + } else if (message.startsWith("/leaveRoom")) { + this.client.SendLeaveRoom(); + } else if (message.startsWith("/bye")) { + this.client.close(); + } else if (message.startsWith("/help")) { + System.out.println("Available commands:"); + System.out.println("\t/bye"); + System.out.println("\t/createRoom "); + System.out.println("\t/listRooms"); + System.out.println("\t/joinRoom "); + System.out.println("\t/leaveRoom"); + System.out.println("\t/help"); + } else { + System.out.println("Unknown command"); + } + } else { + this.client.SendChatMessage(message); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void handleDisconnect() { + System.out.println("Disconnected !"); + this.inputThread.interrupt(); + } + + @Override + public void handleChatMessage(Instant time, String chatter, String content) { + StringBuilder sb = new StringBuilder(); + String strTime = time.toString(); + sb.append("&y["); + sb.append(strTime, 11, 19); // We only take the HH:MM:SS part + sb.append("]&n"); + sb.append(" "); + sb.append(chatter); + sb.append(" : "); + sb.append(content).append("&n"); // make the color back to normal at the end of every message + System.out.println(ANSIColor.formatString(sb.toString())); + } + + @Override + public void handleRoomList(List roomNames) { + System.out.println("Rooms :"); + for (String room : roomNames) { + System.out.println("\t" + room); + } + } + + @Override + public void handleServerResponse(Response response) { + if (response == ServerResponsePacket.Response.MessageSent + || response == ServerResponsePacket.Response.MessageNotSent) { + return; + } + System.out.println(response); + } + +} diff --git a/ChatApp/src/client/ClientListener.java b/ChatApp/src/client/ClientListener.java new file mode 100644 index 0000000..7fcf584 --- /dev/null +++ b/ChatApp/src/client/ClientListener.java @@ -0,0 +1,15 @@ +package client; + +import java.time.Instant; +import java.util.List; + +import network.protocol.packets.ServerResponsePacket; + +public interface ClientListener { + + void handleDisconnect(); + void handleChatMessage(Instant time, String chatter, String content); + void handleRoomList(List roomNames); + void handleServerResponse(ServerResponsePacket.Response response); + +} \ No newline at end of file diff --git a/ChatApp/src/network/SocketReader.java b/ChatApp/src/network/SocketReader.java index dba0724..334e72c 100644 --- a/ChatApp/src/network/SocketReader.java +++ b/ChatApp/src/network/SocketReader.java @@ -24,6 +24,7 @@ public class SocketReader { public void stop() { this.readThread.interrupt(); + socket.close(); } private void readLoop() { @@ -32,9 +33,9 @@ public class SocketReader { byte[] buffer = new byte[65535]; DatagramPacket dataPacket = new DatagramPacket(buffer, buffer.length); socket.receive(dataPacket); - + InetSocketAddress address = new InetSocketAddress(dataPacket.getAddress(), dataPacket.getPort()); - + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(dataPacket.getData())); Packet packet = (Packet) ois.readObject(); diff --git a/ChatApp/src/network/protocol/packets/RoomListPacket.java b/ChatApp/src/network/protocol/packets/RoomListPacket.java index 36b6196..4693f36 100644 --- a/ChatApp/src/network/protocol/packets/RoomListPacket.java +++ b/ChatApp/src/network/protocol/packets/RoomListPacket.java @@ -1,19 +1,19 @@ package network.protocol.packets; -import java.util.ArrayList; +import java.util.List; import network.protocol.Packet; import network.protocol.PacketVisitor; public class RoomListPacket extends Packet { - private final ArrayList roomNames; + private final List roomNames; - public RoomListPacket(ArrayList roomNames) { + public RoomListPacket(List roomNames) { this.roomNames = roomNames; } - public ArrayList getRoomNames() { + public List getRoomNames() { return roomNames; }