Envoie de fichier fonctionnelle :

- Le client reçoit désormais la réponse (ne recevais pas car ne possèdait pas le bon login dans les tâches)
- D'autre problèmes mineur qui empêchait la transimission d'une réponse au client
This commit is contained in:
Benjamin 2022-03-08 14:50:16 +01:00
parent b10f1edf54
commit 45851865fd
18 changed files with 211 additions and 64 deletions

View File

@ -6,10 +6,7 @@ package lightcontainer;
import lightcontainer.domains.server.MulticastServerListener;
import lightcontainer.domains.server.UnicastServerListener;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.rules.reader.FilelistRule;
import lightcontainer.protocol.rules.reader.HelloRule;
import lightcontainer.protocol.rules.reader.SavefileRule;
import lightcontainer.protocol.rules.reader.SigninRule;
import lightcontainer.protocol.rules.reader.*;
import lightcontainer.protocol.rules.writer.*;
import lightcontainer.repository.ClientHandlerRepository;
import lightcontainer.repository.FileFrontEnd;
@ -19,10 +16,10 @@ import lightcontainer.repository.StoreProcessorRepository;
public class App {
// Constant config server
// -- Unicast client port
private static final int UNICAST_PORT = 8500;
private static final int UNICAST_PORT = 8000;
// -- Multicast listener ip, port
private static final String MULTICAST_IP = "226.66.66.1";
private static final int MULTICAST_PORT = 42500;
private static final int MULTICAST_PORT = 15502;
/*
@ -64,23 +61,26 @@ public class App {
protocolRep.addReader(new SigninRule(protocolRep));
protocolRep.addReader(new FilelistRule(protocolRep));
protocolRep.addReader(new SavefileRule(protocolRep));
protocolRep.addReader(new SendOkRule(protocolRep));
protocolRep.addWriter(new SignOkRule());
protocolRep.addWriter(new SignErrorRule());
protocolRep.addWriter(new SignoutRule());
protocolRep.addWriter(new FilesRule());
protocolRep.addWriter(new SaveFileOkRule());
protocolRep.addWriter(new SaveFileErrorRule());
protocolRep.addWriter(new SendfileRule());
new UnicastServerListener(clientRep, protocolRep, UNICAST_PORT);
new MulticastServerListener(storeRep, protocolRep, MULTICAST_IP, MULTICAST_PORT);
FileFrontEnd ffe = new FileFrontEnd(clientRep, storeRep, protocolRep);
new UnicastServerListener(ffe, clientRep, protocolRep, UNICAST_PORT);
new MulticastServerListener(ffe, storeRep, protocolRep, MULTICAST_IP, MULTICAST_PORT);
// close repo et client et server.
Thread.sleep(60000);
// Thread.sleep(60000);
clientRep.close();
storeRep.close();
// clientRep.close();
// storeRep.close();
}
}

View File

@ -2,21 +2,22 @@ package lightcontainer.domains;
import lightcontainer.enumerations.TaskStatus;
import lightcontainer.enumerations.TaskType;
import lightcontainer.protocol.ProtocolWriter;
public class Task {
// Variables
private TaskStatus status;
private String command;
private ProtocolWriter.ProtocolResult command;
private String client;
private String storeDomain;
public Task(TaskStatus pending, String command, String client) {
status = pending;
public Task(TaskStatus status, ProtocolWriter.ProtocolResult command, String client) {
this.status = status;
this.command = command;
this.client = client;
}
public static Task newInstance(String command, String client) {
public static Task newInstance(ProtocolWriter.ProtocolResult command, String client) {
Task task = new Task(TaskStatus.PENDING, command, client);
return task;
}
@ -27,7 +28,7 @@ public class Task {
* @return TRUE si le client doit recevoir cette réponse.
*/
public boolean isResponseOfClient(String storeDomain) {
return (this.storeDomain == storeDomain && status == TaskStatus.PENDING);
return (status == TaskStatus.PROCESSING && this.storeDomain.equals(storeDomain));
}
/**
@ -37,4 +38,15 @@ public class Task {
public String getClient() {
return client;
}
public ProtocolWriter.ProtocolResult getCommand() {
return this.command;
}
public void setDomain(String storeDomain) {
this.storeDomain = storeDomain;
if (storeDomain != null) {
this.status = TaskStatus.PROCESSING;
}
}
}

View File

@ -92,13 +92,15 @@ public class ClientHandler implements Runnable, AutoCloseable {
ProtocolReader.ProtocolResult ruleResult = protocolRep.executeReader(command + "\r\n");
if (isConnected()) {
ProtocolWriter.ProtocolResult writerCommand = ruleResult.getResultCommand();
ruleResult.read(
this.client.getInputStream()
);
ProtocolWriter.ProtocolResult writerCommand = ruleResult.getResultCommand();
if (ruleResult.getReceiver() == ProtocolReader.ResultCmdReceiver.STOREBACKEND) {
fileFrontEnd.newCommand(command, writerCommand.getCommand()); // Envoie dans la file de tâche FileFrontEnd en attente d'un traitement d'un StorBackEnd
fileFrontEnd.newCommand(
writerCommand,
getLogin()); // Envoie dans la file de tâche FileFrontEnd en attente d'un traitement d'un StorBackEnd
// Attend la fin de la réalisation de la tâche
waitTaskResponse();

View File

@ -34,7 +34,7 @@ public class StoreProcessor extends Thread implements AutoCloseable {
private BufferedReader reader;
private PrintWriter writer;
private String currentCommand;
private ProtocolWriter.ProtocolResult protocolResult;
private ProtocolRepository protocolRep;
// Constructor
@ -64,6 +64,8 @@ public class StoreProcessor extends Thread implements AutoCloseable {
this.store.getOutputStream(),
StandardCharsets.UTF_8
), true);
this.start();
} catch (IOException e) {
e.printStackTrace();
}
@ -81,23 +83,25 @@ public class StoreProcessor extends Thread implements AutoCloseable {
while (this.client_run) {
try {
waitAction();
System.out.println("[SBE] Envoie commande : " + protocolResult.getCommand());
// Request
ProtocolWriter.ProtocolResult requestResult = protocolRep.executeWriter(this.currentCommand);
this.writer.write(requestResult.getCommand());
requestResult.write(this.store.getOutputStream());
this.writer.write(protocolResult.getCommand());
this.writer.flush();
protocolResult.write(this.store.getOutputStream());
// Response
String responseCommand = this.reader.readLine();
String responseCommand = this.reader.readLine() + "\r\n";
if (responseCommand != null)
System.out.println("StoreBackEnd: " + responseCommand);
ProtocolReader.ProtocolResult responseResult = protocolRep.executeReader(responseCommand);
responseResult.read(this.store.getInputStream());
responseResult.read(
this.store.getInputStream()
);
System.out.println("StoreBackEnd response to client: " + responseResult.getResultCommand());
alertAvalaible(responseResult.getResultCommand());
// TODO : Faire en sorte que getResultCommand retourne un ProtocolWriter
} catch (IOException ignore) { }
}
@ -105,11 +109,11 @@ public class StoreProcessor extends Thread implements AutoCloseable {
/**
* Permet de demander au StoreBackEnd d'effectuer une commande
* @param command La commande à effectuer
* @param protocolResult La commande à effectuer
*/
public void executeCommand(String command) {
public void executeCommand(ProtocolWriter.ProtocolResult protocolResult) {
synchronized (this) {
this.currentCommand = command;
this.protocolResult = protocolResult;
this.notify();
}
}
@ -119,10 +123,9 @@ public class StoreProcessor extends Thread implements AutoCloseable {
*/
private void alertAvalaible(ProtocolWriter.ProtocolResult responseCommand) {
synchronized (this) {
waitAction();
this.currentCommand = null;
this.protocolResult = null;
fileFrontEnd.onStoreAvailable(this, responseCommand);
waitAction();
}
}
@ -173,6 +176,10 @@ public class StoreProcessor extends Thread implements AutoCloseable {
}
public boolean canProcessTask(Task task) {
return this.currentCommand == null; // Vérifier si tâche veut ce SBE
return this.protocolResult == null; // Vérifier si tâche veut ce SBE
}
public String getDomain() {
return this.domain;
}
}

View File

@ -5,6 +5,7 @@ import lightcontainer.interfaces.MulticastSPR;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.rules.reader.HelloRule;
import lightcontainer.repository.FileFrontEnd;
import java.io.IOException;
import java.net.*;
@ -24,6 +25,7 @@ public class MulticastServerListener implements Runnable {
// Variable
private final String multicast_address;
private final int multicast_port;
private FileFrontEnd ffe;
private final MulticastSPR repository;
private final ProtocolRepository protocolRep;
@ -31,7 +33,8 @@ public class MulticastServerListener implements Runnable {
private MulticastSocket listener;
// Constructor
public MulticastServerListener(MulticastSPR repository, ProtocolRepository protocolRep, String multicast_address, int multicast_port) {
public MulticastServerListener(FileFrontEnd ffe, MulticastSPR repository, ProtocolRepository protocolRep, String multicast_address, int multicast_port) {
this.ffe = ffe;
this.repository = repository;
this.protocolRep = protocolRep;
this.multicast_address = multicast_address;
@ -65,11 +68,13 @@ public class MulticastServerListener implements Runnable {
try {
// TODO Récupérer le port du message du packet et le setup (add description of the line).
HelloRule.Result readerResult = protocolRep.executeReader(data);
System.out.printf("Réception en multicast : Domain=%s | Port=%d\n", readerResult.getDomain(), readerResult.getPort());
System.out.printf("Nouveau SBE : Domain=%s | Port=%d\n", readerResult.getDomain(), readerResult.getPort());
Socket socket = new Socket(packet.getAddress(), readerResult.getPort());
// Create the store processor
StoreProcessor storeProcessor = new StoreProcessor(socket, readerResult.getDomain(), null, protocolRep); // TODO <!!!> : Voir comment on procède get via repo ou ici ?!
StoreProcessor storeProcessor = new StoreProcessor(socket, readerResult.getDomain(), ffe, protocolRep); // TODO <!!!> : Voir comment on procède get via repo ou ici ?!
// Add the store processor to its repository
this.repository.addStore(storeProcessor);
} catch (IOException ignore) {

View File

@ -3,21 +3,24 @@ package lightcontainer.domains.server;
import lightcontainer.domains.client.ClientHandler;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.interfaces.UnicastCHR;
import lightcontainer.repository.FileFrontEnd;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class UnicastServerListener {
public class UnicastServerListener implements Runnable {
// Variables
private ServerSocket server;
private FileFrontEnd ffe;
private final UnicastCHR repository;
private ProtocolRepository protocolRep;
private final int server_port;
private boolean server_run;
// Constructor
public UnicastServerListener(UnicastCHR repository, ProtocolRepository protocolRep, int port) {
public UnicastServerListener(FileFrontEnd ffe, UnicastCHR repository, ProtocolRepository protocolRep, int port) {
this.ffe = ffe;
this.repository = repository;
this.protocolRep = protocolRep;
this.server_port = port;
@ -33,7 +36,8 @@ public class UnicastServerListener {
* @see Thread#start()
* @see ClientHandler
*/
public void start() {
@Override
public void run() {
try {
// Allow looping in the loop and create a socket server
this.server_run = true;
@ -41,10 +45,11 @@ public class UnicastServerListener {
while (this.server_run) {
// Accepting connection requests (blocking)
Socket client = this.server.accept();
System.out.println("New Client");
// Create a new Handler client by passing these dependencies to it
ClientHandler clientHandler = new ClientHandler(client, null, protocolRep); // TODO passer FileFrontEnd ou faire ca dans le repository ?!
ClientHandler clientHandler = new ClientHandler(client, ffe, protocolRep); // TODO passer FileFrontEnd ou faire ca dans le repository ?!
// Add the client handler to its repository (clienthandlerrepository)
// this.repository.add(clientHandler); TODO REPOSITORY
this.repository.addClient(clientHandler);
// Start the thread
(new Thread(clientHandler)).start();
}
@ -66,4 +71,5 @@ public class UnicastServerListener {
} catch (IOException ignored) { }
}
}
}

View File

@ -1,6 +1,7 @@
package lightcontainer.interfaces;
import lightcontainer.domains.client.ClientHandler;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.repository.FileFrontEnd;
/**
@ -14,6 +15,6 @@ public interface ClientHandlerFFE {
* @param command Commande à traiter
* @param client identifiant du client à qui est affilié cette commande
*/
void newCommand(String command, String client);
void newCommand(ProtocolWriter.ProtocolResult command, String client);
}

View File

@ -21,5 +21,7 @@ public interface MulticastSPR {
*/
void addStore(StoreProcessor store);
String findSBE(Task task);
String findDomain(Task task);
void assignTask(String stor, Task task);
}

View File

@ -23,7 +23,7 @@ public abstract class ProtocolReader {
* Lorsqu'il retourne son résultat, on vérifie si il y a une demande de lecture/écriture de fichier depuis le réseau. Si oui on appel ces méthodes, sinon on ne fait rien.
* Ensuite on regarde après l'exécution de ces méthode ou non si il y a une commande de retour ou non et l'envoyons au receiver spécifié par la commande.
*/
public abstract class ProtocolResult {
public class ProtocolResult {
/**
* Command qui sera renvoyée par exemple au client
*/
@ -45,7 +45,7 @@ public abstract class ProtocolReader {
* @return Commande
*/
public ProtocolWriter.ProtocolResult getResultCommand() {
return resultCommand;
return this.resultCommand;
}
/**

View File

@ -25,7 +25,7 @@ public abstract class ProtocolWriter {
return cmdName;
}
public class ProtocolResult {
public static class ProtocolResult {
private String command;
@ -52,11 +52,12 @@ public abstract class ProtocolWriter {
*/
public final <T extends ProtocolResult> T execute(String... data) {
// Concatatène le nom de la commande avec les données (trim), avec un espace entre chaque
StringJoiner builder = new StringJoiner(" ", this.cmdName, "\r\n");
for (String param : data)
builder.add(param);
StringBuilder builder = new StringBuilder(this.cmdName);
String command = builder.toString();
for (String param : data)
builder.append(" " + param);
String command = builder + "\r\n";
Matcher ruleMatcher = this.rulePattern.matcher(command); // Vérifie que tout match (cf. Matcher). Si match alors on retourne la commande build, sinon on retourne NULL
if (ruleMatcher.matches()) {
@ -64,6 +65,7 @@ public abstract class ProtocolWriter {
result.setCommand(command);
return (T) result;
}
return null;
}

View File

@ -4,6 +4,7 @@ import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
import lightcontainer.protocol.rules.writer.SendfileRule;
import lightcontainer.utils.FileReceiver;
import java.io.IOException;
@ -40,11 +41,11 @@ public class SavefileRule extends ProtocolReader {
System.out.printf("Sauvegarde du fichier : %s %d\n", filename, size);
try {
FileReceiver fileReceiver = new FileReceiver("D:\\");
FileReceiver fileReceiver = new FileReceiver("/home/benjamin/ffe"); // "D:\\");
if (!fileReceiver.receiveFile(reader, this.filename, this.size))
throw new IOException();
this.setResultCommand(protocolRep.executeWriter(SaveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
this.setResultCommand(protocolRep.executeWriter(SendfileRule.NAME, this.filename, String.valueOf(this.size), "EMPREINTEBLBLBLBLBLABLABLBALBALBALBALBALBALBALBALBALABLBALBALBALABLABLABLABLABLABLABALBLABALABLABLABLABKJABKAHBHKBHJbhjvgkh"), ResultCmdReceiver.STOREBACKEND);
} catch (IOException e) {
this.setResultCommand(protocolRep.executeWriter(SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
e.printStackTrace();

View File

@ -0,0 +1,29 @@
package lightcontainer.protocol.rules.reader;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
public class SendOkRule extends ProtocolReader {
// Constants
private static final String PATTERN = "^SEND_OK\r\n$";
private ProtocolRepository protocolRep;
// Constructor
public SendOkRule(ProtocolRepository protocolRep) {
super(PATTERN);
this.protocolRep = protocolRep;
}
@Override
protected ProtocolReader.ProtocolResult onExecuted(String... data) {
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult();
result.setResultCommand(protocolRep.executeWriter(SaveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
return result;
}
}

View File

@ -4,7 +4,7 @@ import lightcontainer.protocol.ProtocolWriter;
public class FilesRule extends ProtocolWriter {
private static final String PATTERN = "^FILES(( [^ !]{1,20})!([0-9]{1,10})){0,50}\r\n$";
private static final String PATTERN = "^FILES( ([^ !]{1,20})!([0-9]{1,10})){0,50}\r\n$";
public static final String NAME = "FILES";

View File

@ -0,0 +1,49 @@
package lightcontainer.protocol.rules.writer;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.utils.FileReceiver;
import lightcontainer.utils.FileSender;
import java.io.OutputStream;
public class SendfileRule extends ProtocolWriter {
private static final String PATTERN = "^SENDFILE [A-Za-z0-9.]{0,200} [0-9]{1,10} [A-Za-z0-9.]{50,200}\r\n$";
public static final String NAME = "SENDFILE";
private static final int HASHED_FILE_NAME = 0; // Index file name hashed.
private static final int FILE_SIZE = 1; // Index file size.
private static final int HASHED_FILE_CONTENT = 2; // Index file content hashed.
public SendfileRule() {
super(NAME, PATTERN);
}
public class Result extends ProtocolWriter.ProtocolResult {
private final String hashedFileName;
private final int fileSize;
private final String hashedFileContent;
public Result(String hashedFileName, int fileSize, String hashedFileContent) {
this.hashedFileName = hashedFileName;
this.fileSize = fileSize;
this.hashedFileContent = hashedFileContent;
}
@Override
public void write(OutputStream writer) {
super.write(writer);
System.out.println("Envoie du fichier au SBE");
FileSender fileSender = new FileSender("/home/benjamin/ffe");
fileSender.sendFile(hashedFileName, writer);
}
}
@Override
protected SendfileRule.Result onExecuted(String... data) {
return new SendfileRule.Result(data[HASHED_FILE_NAME], Integer.parseInt(data[FILE_SIZE]), data[HASHED_FILE_CONTENT]);
}
}

View File

@ -41,7 +41,7 @@ public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
@Override
public void setServerListener(UnicastServerListener server) {
this.server = server;
server.start();
new Thread(server).start();
}
/**

View File

@ -2,6 +2,7 @@ package lightcontainer.repository;
import lightcontainer.domains.client.StoreProcessor;
import lightcontainer.domains.Task;
import lightcontainer.enumerations.TaskStatus;
import lightcontainer.interfaces.ClientHandlerFFE;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.interfaces.StoreProcessorFFE;
@ -30,8 +31,11 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
*/
public void alertStoreProcessors(Task task) {
// On avertit les stor processors d'une nouvelle tâche
String stor = storeRepository.findSBE(task);
String stor = storeRepository.findDomain(task);
if (stor != null) {
storeRepository.assignTask(stor, task);
task.setDomain(stor);
}
}
/**
@ -43,20 +47,36 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
@Override
public void onStoreAvailable(StoreProcessor store, ProtocolWriter.ProtocolResult response) {
// TODO : Chercher une tâche appropriée
if (response != null) {
Iterator<Task> it = tasks.iterator();
while (it.hasNext()) {
Task task = it.next();
if (task.isResponseOfClient(store.getDomain())) {
clientRepository.respondToClient(task.getClient(), response);
it.remove(); // Suppression de la tâche
break;
}
}
}
assignOtherTask(store);
}
private void assignOtherTask(StoreProcessor store) {
Iterator<Task> it = tasks.iterator();
while (it.hasNext()) {
Task task = it.next();
if (task.isResponseOfClient(store.getName())) {
clientRepository.respondToClient(task.getClient(), response);
it.remove(); // Suppression de la tâche
if (store.canProcessTask(task)) {
storeRepository.assignTask(store.getDomain(), task);
task.setDomain(store.getDomain());
}
}
}
@Override
public void newCommand(String command, String client) {
// TODO : Ajouter la tâche - Alerter les StorBackEnds
public void newCommand(ProtocolWriter.ProtocolResult command, String client) {
Task task = Task.newInstance(command, client);
tasks.add(task);
alertStoreProcessors(task);

View File

@ -40,7 +40,7 @@ public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
@Override
public void setServerListener(MulticastServerListener server) {
this.server = server;
server.run();
new Thread(server).start();
}
/**
@ -52,20 +52,31 @@ public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
@Override
public void addStore(StoreProcessor store) {
this.handlers.add(store);
}
@Override
public String findSBE(Task task) {
public String findDomain(Task task) {
StoreProcessor handler = findSBE(task);
return handler == null ? null : handler.getDomain();
}
private StoreProcessor findSBE(Task task) {
for (StoreProcessor handler : handlers) {
if (handler.canProcessTask(task)) {
return handler.getName();
return handler;
}
}
return null;
}
@Override
public void assignTask(String stor, Task task) {
StoreProcessor handler = findSBE(task);
handler.executeCommand(task.getCommand());
}
/**
* AutoClosable Function
* Closes all StoreProcessor stored in this repository and deallocates all resources.

View File

@ -33,7 +33,7 @@ client_signin = ^SIGNIN ([A-Za-z0-9]{2,20}) ([^ !]{5,50})\r\n$
client_signup = ^SIGNUP ([A-Za-z0-9]{2,20}) ([^ !]{5,50})\r\n$
ffe_signresult = ^(SIGN_OK|SIGN_ERROR)\r\n$
client_filelist = ^FILELIST\r\n$
ffe_filelistresult = ^FILES(( [^ !]{1,20})!([0-9]{1,10})){0,50}$
ffe_filelistresult = ^FILES (([^ !]{1,20})!([0-9]{1,10})){0,50}$
client_savefile = ^SAVE_FILE ([^ !]{1,20}) ([0-9]{1,10})\r\n$
ffe_savefileresult = ^(SAVEFILE_OK|SAVEFILE_ERROR)\r\n$
client_getfile = ^GETFILE ([^ !]{1,20})\r\n$