Setup commands action
This commit is contained in:
parent
06bc4d5451
commit
f8a5cde8bf
13 changed files with 210 additions and 116 deletions
|
@ -1,51 +1,39 @@
|
||||||
package fr.univ.lyon1.client;
|
package fr.univ.lyon1.client;
|
||||||
|
|
||||||
|
import fr.univ.lyon1.common.Channel;
|
||||||
import fr.univ.lyon1.common.Message;
|
import fr.univ.lyon1.common.Message;
|
||||||
import fr.univ.lyon1.common.User;
|
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 java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Client {
|
public class Client {
|
||||||
private final int port;
|
private final int port;
|
||||||
private final String address;
|
private final String address;
|
||||||
|
private final String username;
|
||||||
|
private final String password;
|
||||||
protected final Socket socket;
|
protected final Socket socket;
|
||||||
protected final ObjectOutputStream out;
|
protected final ObjectOutputStream out;
|
||||||
private ObjectInputStream in;
|
private ObjectInputStream in;
|
||||||
|
private List<Channel> channels = new ArrayList<>();
|
||||||
protected boolean started = false;
|
protected boolean started = false;
|
||||||
|
|
||||||
public Client(String address, int port, String uuid, String password) throws Exception {
|
|
||||||
|
public Client(String address, int port, String username, String password) throws Exception {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
socket = new Socket(address, port);
|
socket = new Socket(address, port);
|
||||||
out = new ObjectOutputStream(socket.getOutputStream());
|
out = new ObjectOutputStream(socket.getOutputStream());
|
||||||
while (!this.auth(uuid, password));
|
|
||||||
out.writeObject("listUsers");
|
|
||||||
out.flush();
|
|
||||||
out.writeObject("join general");
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean auth(String uuid, String password) throws IOException {
|
|
||||||
getIn();
|
getIn();
|
||||||
|
|
||||||
out.writeUTF(uuid);
|
|
||||||
out.flush();
|
|
||||||
out.writeUTF(password);
|
|
||||||
out.flush();
|
|
||||||
|
|
||||||
String response = in.readUTF();
|
|
||||||
System.out.println(response);
|
|
||||||
|
|
||||||
if (response.startsWith("err:"))
|
|
||||||
return false;
|
|
||||||
else if (response.equals("logged"))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
throw new IOException("Uk message");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnectedServer() throws IOException {
|
public void disconnectedServer() throws IOException {
|
||||||
|
@ -60,7 +48,7 @@ public class Client {
|
||||||
public String sendMessage(String content) {
|
public String sendMessage(String content) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
out.writeObject(new Message(content));
|
out.writeObject(new Command(CommandType.message, List.of(new Message(content, channels.get(0)))));
|
||||||
out.flush();
|
out.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Fail to send message !");
|
System.err.println("Fail to send message !");
|
||||||
|
@ -70,26 +58,51 @@ public class Client {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message messageReceived(Message msg) {
|
public void action(Object data) throws IOException {
|
||||||
System.out.println();
|
if (data instanceof Command)
|
||||||
System.out.println(msg);
|
command((Command) data);
|
||||||
return msg;
|
else if (data instanceof ChatException)
|
||||||
|
((ChatException) data).printStackTrace();
|
||||||
|
else {
|
||||||
|
out.writeObject(new UnknownCommand());
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void action(Object data) {
|
private void command(Command cmd) throws IOException {
|
||||||
if (data instanceof Message)
|
switch (cmd.getType()) {
|
||||||
messageReceived((Message) data);
|
case login -> commandLogin();
|
||||||
else if (data instanceof List) {
|
case message -> commandMessage(cmd);
|
||||||
List<Object> tmpList = (List<Object>) data;
|
case list -> commandList(cmd);
|
||||||
if (tmpList.get(0) instanceof User) {
|
case join -> commandJoin(cmd);
|
||||||
List<User> users = (List<User>) data;
|
|
||||||
for (User u : users) {
|
|
||||||
System.out.println(u);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
public void run() throws InterruptedException, IOException {
|
||||||
if (started)
|
if (started)
|
||||||
return;
|
return;
|
||||||
|
@ -102,6 +115,9 @@ public class Client {
|
||||||
|
|
||||||
started = true;
|
started = true;
|
||||||
|
|
||||||
|
out.writeObject(new Command(CommandType.login, List.of(username, password)));
|
||||||
|
out.flush();
|
||||||
|
|
||||||
clientSendThread.join();
|
clientSendThread.join();
|
||||||
socket.close();
|
socket.close();
|
||||||
clientReceiveThread.interrupt();
|
clientReceiveThread.interrupt();
|
||||||
|
|
|
@ -46,7 +46,11 @@ public class ClientReceive implements Runnable {
|
||||||
if (data == null)
|
if (data == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
this.client.action(data);
|
try {
|
||||||
|
this.client.action(data);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -24,9 +24,10 @@ public class Message implements Serializable {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message(String content) {
|
public Message(String content, Channel channel) {
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
this.channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message repley(User user, String content) {
|
public Message repley(User user, String content) {
|
||||||
|
|
23
src/fr/univ/lyon1/common/command/Command.java
Normal file
23
src/fr/univ/lyon1/common/command/Command.java
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package fr.univ.lyon1.common.command;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Command implements Serializable {
|
||||||
|
private final CommandType type;
|
||||||
|
private final List<Object> args;
|
||||||
|
|
||||||
|
public Command(CommandType type, List<Object> args) {
|
||||||
|
this.type = type;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Object> getArgs() {
|
||||||
|
return new ArrayList<>(args);
|
||||||
|
}
|
||||||
|
}
|
27
src/fr/univ/lyon1/common/command/CommandType.java
Normal file
27
src/fr/univ/lyon1/common/command/CommandType.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package fr.univ.lyon1.common.command;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public enum CommandType implements Serializable {
|
||||||
|
login("login", "Login to the server"),
|
||||||
|
message("message", "Send a message"),
|
||||||
|
join("join", "Join a channel"),
|
||||||
|
leave("leave", "Leave a channel"),
|
||||||
|
list("list", "List all users"),
|
||||||
|
listChannels("listChannels", "List all channels");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String description;
|
||||||
|
CommandType(String name, String description) {
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
7
src/fr/univ/lyon1/common/exception/ChatException.java
Normal file
7
src/fr/univ/lyon1/common/exception/ChatException.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
|
public class ChatException extends Exception {
|
||||||
|
public ChatException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
7
src/fr/univ/lyon1/common/exception/LoginInvalid.java
Normal file
7
src/fr/univ/lyon1/common/exception/LoginInvalid.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
|
public class LoginInvalid extends ChatException {
|
||||||
|
public LoginInvalid(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
7
src/fr/univ/lyon1/common/exception/LoginRequired.java
Normal file
7
src/fr/univ/lyon1/common/exception/LoginRequired.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
|
public class LoginRequired extends ChatException {
|
||||||
|
public LoginRequired() {
|
||||||
|
super("Login required");
|
||||||
|
}
|
||||||
|
}
|
9
src/fr/univ/lyon1/common/exception/UnknownCommand.java
Normal file
9
src/fr/univ/lyon1/common/exception/UnknownCommand.java
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
|
import fr.univ.lyon1.common.command.Command;
|
||||||
|
|
||||||
|
public class UnknownCommand extends ChatException {
|
||||||
|
public UnknownCommand() {
|
||||||
|
super("Command unknown");
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,22 +2,21 @@ package fr.univ.lyon1.gui;
|
||||||
|
|
||||||
import fr.univ.lyon1.client.Client;
|
import fr.univ.lyon1.client.Client;
|
||||||
import fr.univ.lyon1.client.ClientReceive;
|
import fr.univ.lyon1.client.ClientReceive;
|
||||||
import fr.univ.lyon1.common.Message;
|
import fr.univ.lyon1.common.command.Command;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ClientGUI extends Client {
|
public class ClientGUI extends Client {
|
||||||
private final MainGui gui;
|
private final MainGui gui;
|
||||||
|
|
||||||
public ClientGUI(MainGui gui, String address, int port) throws IOException, InterruptedException, Exception {
|
public ClientGUI(MainGui gui, String address, int port) throws Exception {
|
||||||
super(address, port, null, null);
|
super(address, port, null, null);
|
||||||
this.gui = gui;
|
this.gui = gui;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message messageReceived(Message msg) {
|
protected void commandMessage(Command cmd) {
|
||||||
gui.receiveMessage(msg.toString());
|
gui.receiveMessage(cmd.getArgs().get(0).toString());
|
||||||
return msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,6 +3,12 @@ package fr.univ.lyon1.server;
|
||||||
import fr.univ.lyon1.common.Channel;
|
import fr.univ.lyon1.common.Channel;
|
||||||
import fr.univ.lyon1.common.Message;
|
import fr.univ.lyon1.common.Message;
|
||||||
import fr.univ.lyon1.common.User;
|
import fr.univ.lyon1.common.User;
|
||||||
|
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.LoginInvalid;
|
||||||
|
import fr.univ.lyon1.common.exception.LoginRequired;
|
||||||
|
import fr.univ.lyon1.common.exception.UnknownCommand;
|
||||||
import fr.univ.lyon1.server.models.ChannelModel;
|
import fr.univ.lyon1.server.models.ChannelModel;
|
||||||
import fr.univ.lyon1.server.models.UserModel;
|
import fr.univ.lyon1.server.models.UserModel;
|
||||||
|
|
||||||
|
@ -11,6 +17,7 @@ import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ConnectedClient implements Runnable {
|
public class ConnectedClient implements Runnable {
|
||||||
|
@ -26,77 +33,67 @@ public class ConnectedClient implements Runnable {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.out = new ObjectOutputStream(socket.getOutputStream());
|
this.out = new ObjectOutputStream(socket.getOutputStream());
|
||||||
|
this.in = new ObjectInputStream(socket.getInputStream());
|
||||||
System.out.println("New user try to auth");
|
|
||||||
while (!this.auth());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean auth() throws IOException {
|
|
||||||
if (in == null)
|
|
||||||
in = new ObjectInputStream(socket.getInputStream());
|
|
||||||
|
|
||||||
String username = in.readUTF();
|
|
||||||
System.out.println("username: "+username);
|
|
||||||
String password = in.readUTF();
|
|
||||||
System.out.println("Pass: "+password);
|
|
||||||
|
|
||||||
if (username.isEmpty() || password.isEmpty()) {
|
|
||||||
out.writeUTF("err: Login required");
|
|
||||||
out.flush();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserModel user = UserModel.get(username);
|
|
||||||
|
|
||||||
if (user == null)
|
|
||||||
out.writeUTF("err: Username not found !");
|
|
||||||
else if (!user.checkPassword(password))
|
|
||||||
out.writeUTF("err: Password invalid !");
|
|
||||||
else {
|
|
||||||
out.writeUTF("logged");
|
|
||||||
out.flush();
|
|
||||||
this.user = user;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
out.flush();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message sendMessage(Message message) throws IOException {
|
public Message sendMessage(Message message) throws IOException {
|
||||||
out.writeObject(message);
|
out.writeObject(new Command(CommandType.message, List.of(message)));
|
||||||
out.flush();
|
out.flush();
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void actionMessage(Object data) throws IOException, ClassNotFoundException {
|
private void actionCommand(Command command) throws IOException, ChatException {
|
||||||
Message msg = (Message) data;
|
CommandType type = command.getType();
|
||||||
|
if (user == null && type != CommandType.login)
|
||||||
|
throw new LoginRequired();
|
||||||
|
|
||||||
if (msg.getContent().startsWith("/"))
|
switch (command.getType()) {
|
||||||
command(msg);
|
case login -> commandLogin(command);
|
||||||
else {
|
case message -> commandMessage(command);
|
||||||
msg.setSender(this.user);
|
case list -> commandList();
|
||||||
server.broadcastMessage(msg, id);
|
case join -> commandJoin(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void command(Message msg) throws IOException {
|
private void commandLogin(Command cmd) throws IOException, ChatException {
|
||||||
String content = msg.getContent();
|
List<Object> args = cmd.getArgs();
|
||||||
if (content.equals("/list")) {
|
|
||||||
List<User> users = server.getUsers();
|
String username = (String) args.get(0);
|
||||||
sendMessage(msg.repley(Server.getServerUser(), "Total: "+users.toArray().length + "\n" + String.join(", ", users.stream().map(User::getUsername).toList())));
|
System.out.println("username: "+username);
|
||||||
} else if (content.startsWith("/join"))
|
String password = (String) args.get(1);
|
||||||
actionJoinChannel(content);
|
System.out.println("Pass: "+password);
|
||||||
|
|
||||||
|
if (username.isEmpty() || password.isEmpty())
|
||||||
|
throw new LoginInvalid("Invalid args");
|
||||||
|
|
||||||
|
UserModel user = UserModel.get(username);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
throw new LoginInvalid("Username not found");
|
||||||
|
else if (!user.checkPassword(password))
|
||||||
|
throw new LoginInvalid("Password invalid");
|
||||||
|
else {
|
||||||
|
out.writeObject(new Command(CommandType.login, null));
|
||||||
|
out.flush();
|
||||||
|
this.user = user;
|
||||||
|
System.out.println("Client "+user.getUsername()+" is connected !");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void actionListUsers() throws IOException {
|
private void commandMessage(Command cmd) {
|
||||||
out.writeObject(server.getUsers());
|
Message msg = (Message) cmd.getArgs().get(0);
|
||||||
|
msg.setSender(this.user);
|
||||||
|
// ToDo: Check the user channel
|
||||||
|
server.broadcastMessage(msg, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void commandList() throws IOException {
|
||||||
|
out.writeObject(new Command(CommandType.list, Collections.singletonList(server.getUsers())));
|
||||||
out.flush();
|
out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void actionJoinChannel(String msg) throws IOException {
|
private void commandJoin(Command cmd) throws IOException {
|
||||||
String name = msg.replaceAll("^(/?join) ", "");
|
String name = (String) cmd.getArgs().get(0);
|
||||||
System.out.println(name);
|
|
||||||
ChannelModel chan = ChannelModel.get(name);
|
ChannelModel chan = ChannelModel.get(name);
|
||||||
|
|
||||||
if (chan == null) {
|
if (chan == null) {
|
||||||
|
@ -106,7 +103,7 @@ public class ConnectedClient implements Runnable {
|
||||||
if (!chan.have(user))
|
if (!chan.have(user))
|
||||||
chan.addUser(user);
|
chan.addUser(user);
|
||||||
|
|
||||||
out.writeObject(chan);
|
out.writeObject(new Command(CommandType.join, List.of((Channel) chan)));
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
server.broadcastMessage(new Message(chan, Server.getServerUser(), user.getUsername()+" joined the channel !"), -1);
|
server.broadcastMessage(new Message(chan, Server.getServerUser(), user.getUsername()+" joined the channel !"), -1);
|
||||||
|
@ -115,19 +112,18 @@ public class ConnectedClient implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
Object data = in.readObject();
|
Object data = in.readObject();
|
||||||
if (data == null)
|
if (data == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (data instanceof Message)
|
try {
|
||||||
actionMessage(data);
|
if (data instanceof Command)
|
||||||
else if (data instanceof String) {
|
actionCommand((Command) data);
|
||||||
String msg = (String) data;
|
else
|
||||||
if (data.equals("listUsers"))
|
throw new UnknownCommand();
|
||||||
actionListUsers();
|
} catch (ChatException e) {
|
||||||
else if (((String) data).startsWith("join"))
|
out.writeObject(e);
|
||||||
actionJoinChannel(msg);
|
out.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
|
|
@ -23,9 +23,6 @@ public class Server {
|
||||||
|
|
||||||
public ConnectedClient addClient(ConnectedClient newClient) {
|
public ConnectedClient addClient(ConnectedClient newClient) {
|
||||||
clients.add(newClient);
|
clients.add(newClient);
|
||||||
|
|
||||||
System.out.println("Client "+newClient.getUser().getUsername()+" is connected !");
|
|
||||||
|
|
||||||
return newClient;
|
return newClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,5 +8,6 @@ module fr.univ.lyon1.gui {
|
||||||
requires org.mariadb.jdbc;
|
requires org.mariadb.jdbc;
|
||||||
|
|
||||||
opens fr.univ.lyon1.gui to javafx.fxml;
|
opens fr.univ.lyon1.gui to javafx.fxml;
|
||||||
|
exports fr.univ.lyon1.common.command;
|
||||||
exports fr.univ.lyon1.gui;
|
exports fr.univ.lyon1.gui;
|
||||||
}
|
}
|
Reference in a new issue