package fr.univ.lyon1.client; import fr.univ.lyon1.common.Channel; import fr.univ.lyon1.common.ChatSSL; import fr.univ.lyon1.common.Message; import fr.univ.lyon1.common.command.Command; import fr.univ.lyon1.common.command.CommandType; import fr.univ.lyon1.common.exception.ChatException; import fr.univ.lyon1.common.exception.UnknownCommand; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocket; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class Client { private final int port; private final String address; private final String username; private final String password; protected final Socket socket; protected final ObjectOutputStream out; private ObjectInputStream in; private List<Channel> channels = new ArrayList<>(); protected boolean started = false; public Client(String address, int port, String username, String password) throws IOException { this.address = address; this.port = port; this.username = username; this.password = password; socket = initSSL(); out = new ObjectOutputStream(socket.getOutputStream()); getIn(); } private Socket initSSL() throws IOException { SSLContext ctx = ChatSSL.getSSLContext(); SocketFactory factory = ctx.getSocketFactory(); Socket connection = factory.createSocket(address, port); ((SSLSocket) connection).setEnabledProtocols(new String[] {ChatSSL.tlsVersion}); SSLParameters sslParams = new SSLParameters(); sslParams.setEndpointIdentificationAlgorithm("HTTPS"); ((SSLSocket) connection).setSSLParameters(sslParams); return connection; } public void disconnectedServer() throws IOException { socket.close(); out.close(); if (in != null) in.close(); System.exit(0); } public String sendMessage(String content) { try { out.writeObject(new Command(CommandType.message, List.of(new Message(content, channels.get(0))))); out.flush(); } catch (IOException e) { System.err.println("Fail to send message !"); e.printStackTrace(); } return content; } public void action(Object data) throws IOException { if (data instanceof Command) command((Command) data); else if (data instanceof ChatException) ((ChatException) data).printStackTrace(); else { out.writeObject(new UnknownCommand()); out.flush(); } } private void command(Command cmd) throws IOException { switch (cmd.getType()) { case login -> commandLogin(); case message -> commandMessage(cmd); case list -> commandList(cmd); case join -> commandJoin(cmd); } } private void commandLogin() throws IOException { out.writeObject(new Command(CommandType.list, null)); out.flush(); out.writeObject(new Command(CommandType.join, List.of("general"))); out.flush(); } protected void commandMessage(Command cmd) { System.out.println(); System.out.println(cmd.getArgs().get(0)); } private void commandList(Command cmd) { List<Object> users = cmd.getArgs(); for (Object u : users) { System.out.println(u); } } private void commandJoin(Command cmd) { Channel chan = (Channel) cmd.getArgs().get(0); channels.add(chan); System.out.println("You join "+chan); } public void run() throws InterruptedException, IOException { if (started) return; Thread clientSendThread = new Thread(new ClientSend(this, out, socket)); clientSendThread.start(); Thread clientReceiveThread = new Thread(new ClientReceive(this, socket)); clientReceiveThread.start(); started = true; out.writeObject(new Command(CommandType.login, List.of(username, password))); out.flush(); clientSendThread.join(); socket.close(); clientReceiveThread.interrupt(); } public ObjectInputStream getIn() throws IOException { if (in == null) in = new ObjectInputStream(socket.getInputStream()); return in; } }