add: first implementation of login
This commit is contained in:
@@ -59,7 +59,28 @@ public class ClientService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a Request to get all the messages, the other clients sent, and that the client is not currently aware of.
|
* Sends a ping to the server
|
||||||
|
* Returns nothing, the method processMessage() already handles the cases "+OK" or "-ERROR"
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void ping() {
|
||||||
|
processMessage("PING");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a login request to the server to create a new user on the server
|
||||||
|
* @param username
|
||||||
|
* @return - a new username, if the same username is already used by someone else
|
||||||
|
*/
|
||||||
|
|
||||||
|
public String login(String username) {
|
||||||
|
String msg = "LOGIN USERNAME=" + username;
|
||||||
|
return processMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a Request to get the number of Messages currently in the Queue for the client.
|
||||||
|
* Then proceeds, if needed, to get the messages by sending
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public List<Message> getMessages() {
|
public List<Message> getMessages() {
|
||||||
@@ -77,11 +98,26 @@ public class ClientService {
|
|||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String sendMessage(Message message) {
|
/**
|
||||||
|
* Sends a Request to the Server containing all relevant information of the message the client wrote.
|
||||||
|
* @param message
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void sendMessage(Message message) {
|
||||||
String request = "SEND_MESSAGE " + message.toArgsString();
|
String request = "SEND_MESSAGE " + message.toArgsString();
|
||||||
return processMessage(request);
|
processMessage(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the Requests to the server and waits for the response
|
||||||
|
* If the response is "+OK" it proceeds normal
|
||||||
|
* If the response "-ERROR" it throws a runtime exception
|
||||||
|
* @param message
|
||||||
|
* @return - The response as a string, if it has to be returned
|
||||||
|
* (+OK will not be returned)
|
||||||
|
*/
|
||||||
|
|
||||||
private String processMessage(String message) {
|
private String processMessage(String message) {
|
||||||
AtomicReference<String> response = new AtomicReference<>();
|
AtomicReference<String> response = new AtomicReference<>();
|
||||||
sendRequest(() -> {
|
sendRequest(() -> {
|
||||||
@@ -93,7 +129,7 @@ public class ClientService {
|
|||||||
System.out.println("Raw message '" + responseLine + "'");
|
System.out.println("Raw message '" + responseLine + "'");
|
||||||
if ("+OK".equals(responseLine)) {
|
if ("+OK".equals(responseLine)) {
|
||||||
return;
|
return;
|
||||||
} else if ("-FAIL".equals(responseLine)) {
|
} else if (("-ERROR").equals(responseLine)) {
|
||||||
throw new RuntimeException(responseLine);
|
throw new RuntimeException(responseLine);
|
||||||
}
|
}
|
||||||
response.set(responseLine);
|
response.set(responseLine);
|
||||||
@@ -105,6 +141,11 @@ public class ClientService {
|
|||||||
return response.get();
|
return response.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
*/
|
||||||
|
|
||||||
private void sendRequest(Runnable request) {
|
private void sendRequest(Runnable request) {
|
||||||
Future<?> future = executor.submit(request);
|
Future<?> future = executor.submit(request);
|
||||||
try {
|
try {
|
||||||
@@ -116,6 +157,12 @@ public class ClientService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Runtime Exceptions thrown by the sendRequest method
|
||||||
|
* @param e - an Exception
|
||||||
|
* @return - a Runtime Exception
|
||||||
|
*/
|
||||||
|
|
||||||
private static RuntimeException getRuntimeException(Exception e) {
|
private static RuntimeException getRuntimeException(Exception e) {
|
||||||
Throwable reason = e.getCause();
|
Throwable reason = e.getCause();
|
||||||
RuntimeException re;
|
RuntimeException re;
|
||||||
@@ -127,6 +174,7 @@ public class ClientService {
|
|||||||
re = new RuntimeException(reason);
|
re = new RuntimeException(reason);
|
||||||
return re;
|
return re;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the Socket and shuts down the Threadpool associated with that Socket-Connection.
|
* Closes the Socket and shuts down the Threadpool associated with that Socket-Connection.
|
||||||
*/
|
*/
|
||||||
@@ -142,6 +190,12 @@ public class ClientService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to write with the tcp transport to the server
|
||||||
|
* @param s - Message to be sent
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
|
||||||
private void writeToTransport(String s) throws IOException {
|
private void writeToTransport(String s) throws IOException {
|
||||||
int id = this.idGenerator.incrementAndGet();
|
int id = this.idGenerator.incrementAndGet();
|
||||||
this.clienttcptransport.write(new RawPacket(id, s));
|
this.clienttcptransport.write(new RawPacket(id, s));
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.client.network;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
public class sendRequest implements Runnable {
|
|
||||||
|
|
||||||
final private String request;
|
|
||||||
final private BufferedReader input;
|
|
||||||
final private BufferedWriter output;
|
|
||||||
|
|
||||||
public sendRequest(String request, BufferedReader input, BufferedWriter output) {
|
|
||||||
this.request = request;
|
|
||||||
this.input = input;
|
|
||||||
this.output = output;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
output.write(request + "\r\n");
|
|
||||||
output.flush();
|
|
||||||
//System.out.println("Writing following request: " + request);
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
String line;
|
|
||||||
line = input.readLine();
|
|
||||||
if (line.toLowerCase().startsWith("+ok")) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ClientService.response.add(line);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+22
-1
@@ -9,6 +9,11 @@ import java.util.ArrayDeque;
|
|||||||
public class ChatHandler {
|
public class ChatHandler {
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final ArrayDeque<Message> receivedMessages = new ArrayDeque<>();
|
private final ArrayDeque<Message> receivedMessages = new ArrayDeque<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ChatHandler for a Session
|
||||||
|
* @param eventBus
|
||||||
|
*/
|
||||||
public ChatHandler(EventBus eventBus) {
|
public ChatHandler(EventBus eventBus) {
|
||||||
eventBus.subscribe(ChatMessageEvent.class, (event) -> {
|
eventBus.subscribe(ChatMessageEvent.class, (event) -> {
|
||||||
processMessageEvent(event.getMessage());
|
processMessageEvent(event.getMessage());
|
||||||
@@ -16,18 +21,34 @@ public class ChatHandler {
|
|||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the Chat Message that the server received to the queue
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
|
||||||
private synchronized void processMessageEvent(Message message) {
|
private synchronized void processMessageEvent(Message message) {
|
||||||
// TODO: filter
|
// TODO: filter for Messages that were sent by the Client
|
||||||
this.receivedMessages.offer(message);
|
this.receivedMessages.offer(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current size of the queue (Used for Command GET_MESSAGE_COUNT)
|
||||||
|
*/
|
||||||
public synchronized int getMessageCount() {
|
public synchronized int getMessageCount() {
|
||||||
return this.receivedMessages.size();
|
return this.receivedMessages.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes the next message out of the queue, to be sent to the Client
|
||||||
|
*/
|
||||||
public synchronized Message getNextMessage() {
|
public synchronized Message getNextMessage() {
|
||||||
return this.receivedMessages.poll();
|
return this.receivedMessages.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message is converted into a String and sent to the Client
|
||||||
|
*/
|
||||||
public void sendMessage(String messageString) {
|
public void sendMessage(String messageString) {
|
||||||
Message msg = Message.toMessage(messageString);
|
Message msg = Message.toMessage(messageString);
|
||||||
this.eventBus.publish(new ChatMessageEvent(msg));
|
this.eventBus.publish(new ChatMessageEvent(msg));
|
||||||
|
|||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.network.handlers;
|
||||||
|
|
||||||
|
import jdk.jshell.spi.ExecutionControl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class UserHandler {
|
||||||
|
|
||||||
|
private final List<String> usernames;
|
||||||
|
|
||||||
|
public UserHandler() {
|
||||||
|
this.usernames = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean checkUsername(String username) {
|
||||||
|
for (int i = 0; i < this.usernames.size(); i++) {
|
||||||
|
if (this.usernames.get(i).equals(username)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pattern usrRex = Pattern.compile("USERNAME=(?<user>\\w+)");
|
||||||
|
|
||||||
|
public String addUsername(String username) {
|
||||||
|
Matcher matcher = usrRex.matcher(username);
|
||||||
|
if (! matcher.find()) {
|
||||||
|
throw new RuntimeException("Cannot parse " + username);
|
||||||
|
}
|
||||||
|
String usr = matcher.group("user");
|
||||||
|
if (!this.checkUsername(usr)) {
|
||||||
|
this.usernames.add(usr);
|
||||||
|
} else {
|
||||||
|
this.usernames.add(getAltUsername(usr));
|
||||||
|
}
|
||||||
|
return String.format("USERNAME=%s", usr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUsername(String username) {
|
||||||
|
this.usernames.remove(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAltUsername(String username) {
|
||||||
|
int count = 0;
|
||||||
|
while (true) {
|
||||||
|
username = String.format("%s%d", username, ++count);
|
||||||
|
if (this.checkUsername(username)) {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import java.io.IOException;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.handlers.ChatHandler;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.handlers.ChatHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.handlers.UserHandler;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.RawPacket;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.RawPacket;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -18,6 +19,7 @@ import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.TransportLayer;
|
|||||||
*/
|
*/
|
||||||
public class Session implements Runnable {
|
public class Session implements Runnable {
|
||||||
private final ChatHandler chatHandler;
|
private final ChatHandler chatHandler;
|
||||||
|
private final UserHandler userHandler;
|
||||||
private SessionId id;
|
private SessionId id;
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
private TransportLayer transport;
|
private TransportLayer transport;
|
||||||
@@ -44,6 +46,7 @@ public class Session implements Runnable {
|
|||||||
this.logger.info("Created new session");
|
this.logger.info("Created new session");
|
||||||
this.idGenerator = new AtomicInteger();
|
this.idGenerator = new AtomicInteger();
|
||||||
this.chatHandler = new ChatHandler(eventBus);
|
this.chatHandler = new ChatHandler(eventBus);
|
||||||
|
this.userHandler = new UserHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,7 +100,7 @@ public class Session implements Runnable {
|
|||||||
case "GET_NEXT_MESSAGE":
|
case "GET_NEXT_MESSAGE":
|
||||||
if (chatHandler.getMessageCount() == 0) {
|
if (chatHandler.getMessageCount() == 0) {
|
||||||
logger.warn("FAIL No more messages!");
|
logger.warn("FAIL No more messages!");
|
||||||
writeToTransport("-FAIL");
|
writeToTransport("-ERROR");
|
||||||
} else {
|
} else {
|
||||||
String msgString = chatHandler.getNextMessage().toArgsString();
|
String msgString = chatHandler.getNextMessage().toArgsString();
|
||||||
logger.debug("Session "+id.value()+" Write next message "+msgString);
|
logger.debug("Session "+id.value()+" Write next message "+msgString);
|
||||||
@@ -105,9 +108,19 @@ public class Session implements Runnable {
|
|||||||
writeToTransport("+OK");
|
writeToTransport("+OK");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "LOGIN":
|
||||||
|
String usr = userHandler.addUsername(commandAndArgs[1]);
|
||||||
|
writeToTransport(usr);
|
||||||
|
writeToTransport("+OK");
|
||||||
|
|
||||||
|
case "LOGOUT":
|
||||||
|
userHandler.removeUsername(commandAndArgs[1]);
|
||||||
|
writeToTransport("+OK");
|
||||||
|
case "PING":
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this.logger.warn("Unknown command: " + commandWord);
|
this.logger.warn("Unknown command: " + commandWord);
|
||||||
writeToTransport("-FAIL");
|
writeToTransport("-ERROR");
|
||||||
}
|
}
|
||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
logger.info("Client disconnected");
|
logger.info("Client disconnected");
|
||||||
|
|||||||
@@ -33,15 +33,20 @@ public class ClientServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testClientService() throws ExecutionException, InterruptedException {
|
public void testClientService() throws ExecutionException, InterruptedException {
|
||||||
ClientService client1 = new ClientService("localhost", 5000);
|
ClientService client1 = new ClientService("localhost", 5000);
|
||||||
|
/*
|
||||||
ClientService client2 = new ClientService("localhost", 5000);
|
ClientService client2 = new ClientService("localhost", 5000);
|
||||||
Thread.sleep(2000);
|
Thread.sleep(2000);
|
||||||
String response = client1.sendMessage(new Message(Message.MessageType.GLOBAL, 0, "Mathis", null, "blahh"));
|
client1.sendMessage(new Message(Message.MessageType.GLOBAL, 0, "Mathis", null, "blahh"));
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
List<Message> received = client2.getMessages();
|
List<Message> received = client2.getMessages();
|
||||||
|
|
||||||
assertEquals(1, received.size());
|
assertEquals(1, received.size());
|
||||||
Message s = received.get(0);
|
Message s = received.get(0);
|
||||||
assertEquals(Message.MessageType.GLOBAL, s.getMessageType());
|
assertEquals(Message.MessageType.GLOBAL, s.getMessageType());
|
||||||
|
*/
|
||||||
|
|
||||||
|
String username = client1.login("Mathis");
|
||||||
|
assertEquals("USERNAME=Mathis", username);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user