Merge branch 'dev'
This commit is contained in:
commit
1cee0e63af
@ -16,5 +16,10 @@
|
|||||||
<option name="name" value="MavenRepo" />
|
<option name="name" value="MavenRepo" />
|
||||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="BintrayJCenter" />
|
||||||
|
<option name="name" value="BintrayJCenter" />
|
||||||
|
<option name="url" value="https://jcenter.bintray.com/" />
|
||||||
|
</remote-repository>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
15
README.md
15
README.md
@ -0,0 +1,15 @@
|
|||||||
|
# FileFrontEnd
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Technologies utilisées
|
||||||
|
|
||||||
|
* Java 11 (ressources informatiques)
|
||||||
|
* Gradle 7.1
|
||||||
|
|
||||||
|
### Projet
|
||||||
|
|
||||||
|
* src > main > resources > appdata.json -> Fichier de configuration à modifier
|
||||||
|
* storagePath : indiquer le dossier où les fichiers temporaires du FFE seront stockés
|
||||||
|
* network_interface : indiquer l'interface réseau à utiliser. Si elle n'est pas bonne, le programme demande laquelle utiliser au démarrage
|
||||||
|
|
@ -24,6 +24,8 @@ dependencies {
|
|||||||
implementation 'com.google.guava:guava:30.1-jre'
|
implementation 'com.google.guava:guava:30.1-jre'
|
||||||
// Use gson to serialize/deserialize json files
|
// Use gson to serialize/deserialize json files
|
||||||
implementation 'com.google.code.gson:gson:2.9.0'
|
implementation 'com.google.code.gson:gson:2.9.0'
|
||||||
|
// https://mvnrepository.com/artifact/org.mindrot/jbcrypt
|
||||||
|
implementation group: 'org.mindrot', name: 'jbcrypt', version: '0.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
@ -35,3 +37,8 @@ tasks.named('test') {
|
|||||||
// Use JUnit Platform for unit tests.
|
// Use JUnit Platform for unit tests.
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
run {
|
||||||
|
standardInput = System.in
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
package lightcontainer;
|
package lightcontainer;
|
||||||
|
|
||||||
|
import lightcontainer.domains.FFETimer;
|
||||||
import lightcontainer.domains.server.MulticastServerListener;
|
import lightcontainer.domains.server.MulticastServerListener;
|
||||||
import lightcontainer.domains.server.UnicastServerListener;
|
import lightcontainer.domains.server.UnicastServerListener;
|
||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
@ -16,14 +17,11 @@ import lightcontainer.storage.AppData;
|
|||||||
import lightcontainer.storage.JsonAdapter;
|
import lightcontainer.storage.JsonAdapter;
|
||||||
import lightcontainer.storage.Repository;
|
import lightcontainer.storage.Repository;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Timer;
|
||||||
|
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
setupVM();
|
setupVM();
|
||||||
Repository repositoryStorage = prepareStorage();
|
Repository repositoryStorage = prepareStorage();
|
||||||
@ -31,7 +29,28 @@ public class App {
|
|||||||
// Create all repository
|
// Create all repository
|
||||||
ClientHandlerRepository clientRep = new ClientHandlerRepository();
|
ClientHandlerRepository clientRep = new ClientHandlerRepository();
|
||||||
StoreProcessorRepository storeRep = new StoreProcessorRepository();
|
StoreProcessorRepository storeRep = new StoreProcessorRepository();
|
||||||
|
|
||||||
|
// Initialisation des protocoles
|
||||||
ProtocolRepository protocolRep = new ProtocolRepositoryImpl();
|
ProtocolRepository protocolRep = new ProtocolRepositoryImpl();
|
||||||
|
initProtocols(repositoryStorage, protocolRep);
|
||||||
|
|
||||||
|
// Initialisation du dispatcher et des servers
|
||||||
|
FileFrontEnd ffe = new FileFrontEnd(clientRep, storeRep, protocolRep);
|
||||||
|
new UnicastServerListener(ffe, clientRep, protocolRep, repositoryStorage, repositoryStorage.getUnicastPort());
|
||||||
|
new MulticastServerListener(ffe, storeRep, protocolRep, repositoryStorage.getMulticastIp(), repositoryStorage.getMulticastPort(), repositoryStorage.getNetworkInterface());
|
||||||
|
|
||||||
|
// S'occupe de distribué les timeout pour les SBE plus connecté et donc de Timeout les clients
|
||||||
|
Timer ffeTimer = new Timer();
|
||||||
|
ffeTimer.schedule(new FFETimer(storeRep), 50000, 50000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initProtocols(Repository repositoryStorage, ProtocolRepository protocolRep) {
|
||||||
|
initReadersProtocols(repositoryStorage, protocolRep);
|
||||||
|
initWritersProtocols(repositoryStorage, protocolRep);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initReadersProtocols(Repository repositoryStorage, ProtocolRepository protocolRep) {
|
||||||
protocolRep.addReader(new HelloRule());
|
protocolRep.addReader(new HelloRule());
|
||||||
protocolRep.addReader(new SigninRule(protocolRep));
|
protocolRep.addReader(new SigninRule(protocolRep));
|
||||||
protocolRep.addReader(new SignupRule(protocolRep));
|
protocolRep.addReader(new SignupRule(protocolRep));
|
||||||
@ -39,24 +58,28 @@ public class App {
|
|||||||
protocolRep.addReader(new FilelistRule(protocolRep));
|
protocolRep.addReader(new FilelistRule(protocolRep));
|
||||||
protocolRep.addReader(new SavefileRule(protocolRep, repositoryStorage.getStoragePath()));
|
protocolRep.addReader(new SavefileRule(protocolRep, repositoryStorage.getStoragePath()));
|
||||||
protocolRep.addReader(new SendOkRule(protocolRep));
|
protocolRep.addReader(new SendOkRule(protocolRep));
|
||||||
|
protocolRep.addReader(new SendErrorRule(protocolRep));
|
||||||
|
protocolRep.addReader(new GetFileRule(protocolRep));
|
||||||
|
protocolRep.addReader(new EraseErrorRule(protocolRep));
|
||||||
|
protocolRep.addReader(new EraseOkRule(protocolRep));
|
||||||
|
protocolRep.addReader(new RemoveFileRule(protocolRep));
|
||||||
|
protocolRep.addReader(new RetrieveErrorRule(protocolRep));
|
||||||
|
protocolRep.addReader(new RetrieveOkRule(protocolRep, repositoryStorage.getStoragePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initWritersProtocols(Repository repositoryStorage, ProtocolRepository protocolRep) {
|
||||||
protocolRep.addWriter(new SignOkRule());
|
protocolRep.addWriter(new SignOkRule());
|
||||||
protocolRep.addWriter(new SignErrorRule());
|
protocolRep.addWriter(new SignErrorRule());
|
||||||
protocolRep.addWriter(new FilesRule());
|
protocolRep.addWriter(new FilesRule());
|
||||||
protocolRep.addWriter(new SaveFileOkRule());
|
protocolRep.addWriter(new SaveFileOkRule(repositoryStorage.getStoragePath()));
|
||||||
protocolRep.addWriter(new SaveFileErrorRule());
|
protocolRep.addWriter(new SaveFileErrorRule(repositoryStorage.getStoragePath()));
|
||||||
protocolRep.addWriter(new SendfileRule(repositoryStorage.getStoragePath()));
|
protocolRep.addWriter(new SendfileRule(repositoryStorage.getStoragePath()));
|
||||||
|
protocolRep.addWriter(new GetFileErrorRule(repositoryStorage.getStoragePath()));
|
||||||
FileFrontEnd ffe = new FileFrontEnd(clientRep, storeRep, protocolRep);
|
protocolRep.addWriter(new EraseFileRule());
|
||||||
new UnicastServerListener(ffe, clientRep, protocolRep, repositoryStorage, repositoryStorage.getUnicastPort());
|
protocolRep.addWriter(new RemoveFileErrorRule());
|
||||||
new MulticastServerListener(ffe, storeRep, protocolRep, repositoryStorage.getMulticastIp(), repositoryStorage.getMulticastPort());
|
protocolRep.addWriter(new RemoveFileOkRule());
|
||||||
|
protocolRep.addWriter(new GetFileOkRule(repositoryStorage.getStoragePath()));
|
||||||
// close repo et client et server.
|
protocolRep.addWriter(new RetrieveFileRule());
|
||||||
|
|
||||||
// Thread.sleep(60000);
|
|
||||||
|
|
||||||
// clientRep.close();
|
|
||||||
// storeRep.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Repository prepareStorage() {
|
private static Repository prepareStorage() {
|
||||||
@ -71,9 +94,9 @@ public class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void setupVM() {
|
private static void setupVM() {
|
||||||
System.setProperty("javax.net.ssl.keyStore","../ffe.labo.swilabus.com.p12");
|
System.setProperty("javax.net.ssl.keyStore", "../ffe.labo.swilabus.com.p12");
|
||||||
System.setProperty("javax.net.ssl.keyStorePassword","labo2022");
|
System.setProperty("javax.net.ssl.keyStorePassword", "labo2022");
|
||||||
System.setProperty("https.protocols","TLSv1.3");
|
System.setProperty("https.protocols", "TLSv1.3");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
31
app/src/main/java/lightcontainer/domains/FFETimer.java
Normal file
31
app/src/main/java/lightcontainer/domains/FFETimer.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package lightcontainer.domains;
|
||||||
|
|
||||||
|
import lightcontainer.interfaces.MulticastSPR;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class s'occupant de gérer les timeout des différents SBE
|
||||||
|
*/
|
||||||
|
public class FFETimer extends TimerTask {
|
||||||
|
|
||||||
|
private final MulticastSPR processorRepository;
|
||||||
|
|
||||||
|
public FFETimer(MulticastSPR processorRepository) {
|
||||||
|
this.processorRepository = processorRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (String domain : processorRepository.getDomains()) {
|
||||||
|
LocalDateTime lastAnnounce = processorRepository.getLastAnnounce(domain);
|
||||||
|
long secondBetween = Math.abs(ChronoUnit.SECONDS.between(lastAnnounce, LocalDateTime.now()));
|
||||||
|
|
||||||
|
if (secondBetween > 50) {
|
||||||
|
processorRepository.closeStore(domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,33 +10,35 @@ import lightcontainer.protocol.ProtocolWriter;
|
|||||||
public class Task {
|
public class Task {
|
||||||
// Variables
|
// Variables
|
||||||
private TaskStatus status;
|
private TaskStatus status;
|
||||||
private ProtocolWriter.ProtocolResult command;
|
private final ProtocolWriter.ProtocolResult command;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Défini le context courrant dans laquelle la tâche opère
|
* Défini le context courant dans laquelle la tâche opère
|
||||||
*/
|
*/
|
||||||
private Context context;
|
private final Context context;
|
||||||
|
|
||||||
public Task(Context context, TaskStatus status, ProtocolWriter.ProtocolResult command) {
|
public Task(Context context, TaskStatus status, ProtocolWriter.ProtocolResult command, String requestDomain) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.command = command;
|
this.command = command;
|
||||||
|
context.setDomain(requestDomain); // Domaine requis
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de créer une instance de la class {@link Task}
|
* Permet de créer une instance de la class {@link Task}
|
||||||
|
*
|
||||||
* @param context Context à utiliser pour cette tâche
|
* @param context Context à utiliser pour cette tâche
|
||||||
* @param command Commande à exécuter
|
* @param command Commande à exécuter
|
||||||
* @return L'instance de la tâche créée
|
* @return L'instance de la tâche créée
|
||||||
*/
|
*/
|
||||||
public static Task newInstance(Context context, ProtocolWriter.ProtocolResult command) {
|
public static Task newInstance(Context context, ProtocolWriter.ProtocolResult command, String requestDomain) {
|
||||||
Task task = new Task(context, TaskStatus.PENDING, command);
|
return new Task(context, TaskStatus.PENDING, command, requestDomain);
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de savoir si la réponse est destinée au client
|
* Permet de savoir si la réponse est destinée au client
|
||||||
|
*
|
||||||
* @param storeDomain Nom du store back end fournissant la réponse.
|
* @param storeDomain Nom du store back end fournissant la réponse.
|
||||||
* @return TRUE si le client doit recevoir cette réponse.
|
* @return TRUE si le client doit recevoir cette réponse.
|
||||||
*/
|
*/
|
||||||
@ -46,6 +48,7 @@ public class Task {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer le login du client associé à la tâche
|
* Permet de récupérer le login du client associé à la tâche
|
||||||
|
*
|
||||||
* @return Login du client
|
* @return Login du client
|
||||||
*/
|
*/
|
||||||
public String getClient() {
|
public String getClient() {
|
||||||
@ -54,6 +57,7 @@ public class Task {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer la commande à executer
|
* Permet de récupérer la commande à executer
|
||||||
|
*
|
||||||
* @return Commande à exécuter
|
* @return Commande à exécuter
|
||||||
*/
|
*/
|
||||||
public ProtocolWriter.ProtocolResult getCommand() {
|
public ProtocolWriter.ProtocolResult getCommand() {
|
||||||
@ -62,6 +66,7 @@ public class Task {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de définir le StorBackEnd à utiliser pour cette tâche
|
* Permet de définir le StorBackEnd à utiliser pour cette tâche
|
||||||
|
*
|
||||||
* @param storeDomain Le StorBackEnd à utiliser
|
* @param storeDomain Le StorBackEnd à utiliser
|
||||||
*/
|
*/
|
||||||
public void setDomain(String storeDomain) {
|
public void setDomain(String storeDomain) {
|
||||||
@ -77,4 +82,12 @@ public class Task {
|
|||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
return this.context;
|
return this.context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Le domaine actuellement utilisé OU requis, null si aucune domaine requis/associé
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getDomain() {
|
||||||
|
return context.getDomain();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package lightcontainer.domains.client;
|
package lightcontainer.domains.client;
|
||||||
|
|
||||||
import lightcontainer.domains.server.UnicastServerListener;
|
|
||||||
import lightcontainer.interfaces.ClientHandlerFFE;
|
import lightcontainer.interfaces.ClientHandlerFFE;
|
||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
import lightcontainer.interfaces.UnicastCHR;
|
import lightcontainer.interfaces.UnicastCHR;
|
||||||
@ -10,153 +9,107 @@ import lightcontainer.protocol.rules.reader.SigninRule;
|
|||||||
import lightcontainer.protocol.rules.reader.SignoutRule;
|
import lightcontainer.protocol.rules.reader.SignoutRule;
|
||||||
import lightcontainer.protocol.rules.reader.SignupRule;
|
import lightcontainer.protocol.rules.reader.SignupRule;
|
||||||
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
||||||
import lightcontainer.protocol.rules.writer.SignOkRule;
|
import lightcontainer.utils.Log;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import java.io.IOException;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClientHandler
|
* ClientHandler
|
||||||
*
|
* <p>
|
||||||
* <!> UNICAST CLIENT <!>
|
* <!> UNICAST CLIENT <!>
|
||||||
* Class communicating with the client, and
|
* Class communicating with the client, and
|
||||||
* intercepting and sending files to the client.
|
* intercepting and sending files to the client.
|
||||||
*
|
*
|
||||||
* @version 1.1
|
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
||||||
* @since 1.0
|
* @version 1.1
|
||||||
*
|
* @see Runnable
|
||||||
* @see Runnable
|
* @see AutoCloseable
|
||||||
* @see AutoCloseable
|
* @since 1.0
|
||||||
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
|
||||||
*/
|
*/
|
||||||
public class ClientHandler implements Runnable, AutoCloseable {
|
public class ClientHandler extends UnicastThread implements AutoCloseable {
|
||||||
// Variables
|
// Variables
|
||||||
private ClientHandlerFFE fileFrontEnd;
|
private final ClientHandlerFFE fileFrontEnd;
|
||||||
private final Socket client;
|
private final ProtocolRepository protocolRep;
|
||||||
private ProtocolRepository protocolRep;
|
private final UnicastCHR repository;
|
||||||
private Context context;
|
|
||||||
private boolean client_run;
|
|
||||||
private UnicastCHR repository;
|
|
||||||
|
|
||||||
|
|
||||||
private BufferedReader reader;
|
|
||||||
private PrintWriter writer;
|
|
||||||
private ProtocolWriter.ProtocolResult response;
|
private ProtocolWriter.ProtocolResult response;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public ClientHandler(UnicastCHR repository, Socket client, ClientHandlerFFE ffe, ProtocolRepository protocolRep, Context context) {
|
public ClientHandler(UnicastCHR repository, Socket client, ClientHandlerFFE ffe, ProtocolRepository protocolRep, Context context) {
|
||||||
|
super(client, context);
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
this.fileFrontEnd = ffe;
|
this.fileFrontEnd = ffe;
|
||||||
this.client = client;
|
|
||||||
this.protocolRep = protocolRep;
|
this.protocolRep = protocolRep;
|
||||||
this.context = context;
|
|
||||||
this.client_run = false;
|
|
||||||
initClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise the Client's Reader and Writer.
|
|
||||||
*
|
|
||||||
* @since 1.0
|
|
||||||
*
|
|
||||||
* @see BufferedReader
|
|
||||||
* @see PrintWriter
|
|
||||||
*/
|
|
||||||
private void initClient() {
|
|
||||||
// Start the thread
|
|
||||||
try {
|
|
||||||
this.reader = new BufferedReader(new InputStreamReader(
|
|
||||||
this.client.getInputStream(),
|
|
||||||
StandardCharsets.UTF_8
|
|
||||||
));
|
|
||||||
this.writer = new PrintWriter(new OutputStreamWriter(
|
|
||||||
this.client.getOutputStream(),
|
|
||||||
StandardCharsets.UTF_8
|
|
||||||
), true);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread Function
|
* Thread Function
|
||||||
* Start the dialogue with the client.
|
* Start the dialogue with the client.
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
this.client_run = true;
|
// Set process to true
|
||||||
while (this.client_run) {
|
this.setRunning(true);
|
||||||
|
// Process while
|
||||||
|
while (this.isRunning()) {
|
||||||
// Signifie le démarrage d'une nouvelle rquête
|
// Signifie le démarrage d'une nouvelle rquête
|
||||||
context.newBundle();
|
getContext().newBundle();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String command = this.reader.readLine();
|
String command = this.readLine();
|
||||||
if (command != null) {
|
if (command != null) {
|
||||||
System.out.println("Client: " + command);
|
Log.getInstance().infoln("Client: " + command);
|
||||||
} else {
|
} else {
|
||||||
repository.disconnect(this);
|
this.repository.disconnect(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolReader.ProtocolResult ruleResult = protocolRep.executeReader(context, command + "\r\n");
|
ProtocolReader.ProtocolResult ruleResult = this.protocolRep.executeReader(getContext(), command + "\r\n");
|
||||||
if (ruleResult == null) {
|
if (ruleResult == null) {
|
||||||
repository.disconnect(this);
|
this.repository.disconnect(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkAccess(ruleResult)) {
|
if (checkAccess(ruleResult)) {
|
||||||
ruleResult.read(this.client.getInputStream());
|
// Lecture du fichier client
|
||||||
|
ruleResult.read(this.getInputStream());
|
||||||
ProtocolWriter.ProtocolResult writerCommand = ruleResult.getResultCommand();
|
ProtocolWriter.ProtocolResult writerCommand = ruleResult.getResultCommand();
|
||||||
|
// TODO : Vérifier que le StorBackEnd demandé (Pas toujours demandé) est disponible
|
||||||
if (ruleResult.getReceiver() == ProtocolReader.ResultCmdReceiver.STOREBACKEND) {
|
if (ruleResult.getReceiver() == ProtocolReader.ResultCmdReceiver.STOREBACKEND && !fileFrontEnd.canExecuteCommand(ruleResult.getRequestDomain())) {
|
||||||
fileFrontEnd.newCommand(context, writerCommand); // Envoie dans la file de tâche FileFrontEnd en attente d'un traitement d'un StorBackEnd
|
this.print(ruleResult.onNotExecutable(getContext())); // Renvoie au client
|
||||||
|
} else if (ruleResult.getReceiver() == ProtocolReader.ResultCmdReceiver.STOREBACKEND) {
|
||||||
|
this.fileFrontEnd.newCommand(getContext(), writerCommand, ruleResult.getRequestDomain()); // 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
|
// Attend la fin de la réalisation de la tâche
|
||||||
waitTaskResponse();
|
waitTaskResponse();
|
||||||
|
if (this.response != null) {
|
||||||
writer.write(response.getCommand()); // Renvoye au client
|
this.write(this.response.getCommand()); // Renvoie au client
|
||||||
writer.flush();
|
this.response.write(this.getOutputStream()); // Ecrit au client si nécessaire
|
||||||
response.write(this.client.getOutputStream()); // Ecrit au client si nécessaire
|
} else {
|
||||||
|
this.print(ruleResult.onNotExecutable(getContext())); // Renvoie au client
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.print(writerCommand.getCommand()); // Renvoye au client
|
this.print(writerCommand.getCommand()); // Renvoie au client
|
||||||
writer.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println(4);
|
|
||||||
accessDenied();
|
accessDenied();
|
||||||
}
|
}
|
||||||
} catch (IOException ignore) {
|
} catch (IOException e) {
|
||||||
ignore.printStackTrace();
|
this.close();
|
||||||
repository.disconnect(this);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
this.reader.close();
|
|
||||||
this.writer.close();
|
|
||||||
this.client.close();
|
|
||||||
System.out.printf("[CLIENT] %s s'est déconnecté\n", context.getLogin());
|
|
||||||
} catch (IOException ignored) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de vérifier si le client possède l'accès demandé
|
* Permet de vérifier si le client possède l'accès demandé
|
||||||
|
*
|
||||||
* @param ruleResult La règle
|
* @param ruleResult La règle
|
||||||
* @return TRUE si le client possède l'accès demandé
|
* @return TRUE si le client possède l'accès demandé
|
||||||
*/
|
*/
|
||||||
private boolean checkAccess(ProtocolReader.ProtocolResult ruleResult) {
|
private boolean checkAccess(ProtocolReader.ProtocolResult ruleResult) {
|
||||||
checkSignout(ruleResult);
|
checkSignout(ruleResult);
|
||||||
if (context.isConnected())
|
if (getContext().isConnected())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ruleResult
|
ruleResult
|
||||||
.getClass()
|
.getClass()
|
||||||
@ -166,9 +119,8 @@ public class ClientHandler implements Runnable, AutoCloseable {
|
|||||||
try {
|
try {
|
||||||
ruleResult.getClass().asSubclass(SigninRule.Result.class);
|
ruleResult.getClass().asSubclass(SigninRule.Result.class);
|
||||||
return true;
|
return true;
|
||||||
} catch (ClassCastException e2) { }
|
} catch (ClassCastException ignored) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,31 +128,20 @@ public class ClientHandler implements Runnable, AutoCloseable {
|
|||||||
* Lorsque l'accès à été refusé.
|
* Lorsque l'accès à été refusé.
|
||||||
*/
|
*/
|
||||||
private void accessDenied() {
|
private void accessDenied() {
|
||||||
ProtocolWriter.ProtocolResult signErrorResult = protocolRep.executeWriter(context, SignErrorRule.NAME);
|
ProtocolWriter.ProtocolResult signErrorResult = this.protocolRep.executeWriter(getContext(), SignErrorRule.NAME);
|
||||||
writer.write(signErrorResult.getCommand()); // Envoie SignError car echec de la connection
|
this.write(signErrorResult.getCommand()); // Envoie SignError car echec de la connection
|
||||||
writer.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vérifie s'il s'âgit d'une demande de déconnexion
|
* Vérifie s'il s'âgit d'une demande de déconnexion
|
||||||
|
*
|
||||||
* @param ruleResult
|
* @param ruleResult
|
||||||
*/
|
*/
|
||||||
private void checkSignout(ProtocolReader.ProtocolResult ruleResult) {
|
private void checkSignout(ProtocolReader.ProtocolResult ruleResult) {
|
||||||
try {
|
try {
|
||||||
ruleResult.getClass().asSubclass(SignoutRule.Result.class);
|
ruleResult.getClass().asSubclass(SignoutRule.Result.class);
|
||||||
repository.disconnect(this);
|
this.repository.disconnect(this);
|
||||||
} catch (ClassCastException e2) { }
|
} catch (ClassCastException ignored) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vérifie s'il s'âgit d'une demande de déconnexion
|
|
||||||
* @param ruleResult
|
|
||||||
*/
|
|
||||||
private void checkSignError(ProtocolWriter.ProtocolResult ruleResult) {
|
|
||||||
if (ruleResult.getCommand().startsWith(SignErrorRule.NAME)) {
|
|
||||||
System.out.println("Pas pu connecter");
|
|
||||||
repository.disconnect(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,12 +151,15 @@ public class ClientHandler implements Runnable, AutoCloseable {
|
|||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
try {
|
||||||
this.wait();
|
this.wait();
|
||||||
} catch (InterruptedException e) { e.printStackTrace(); }
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet d'envoyer la réponse au client.
|
* Permet d'envoyer la réponse au client.
|
||||||
|
*
|
||||||
* @param response La réponse
|
* @param response La réponse
|
||||||
*/
|
*/
|
||||||
public void respond(ProtocolWriter.ProtocolResult response) {
|
public void respond(ProtocolWriter.ProtocolResult response) {
|
||||||
@ -229,16 +173,23 @@ public class ClientHandler implements Runnable, AutoCloseable {
|
|||||||
* AutoClosable Function
|
* AutoClosable Function
|
||||||
* Close the Client thread and resources.
|
* Close the Client thread and resources.
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
System.out.println("Call close");
|
if (this.isRunning()) {
|
||||||
this.client_run = false;
|
try {
|
||||||
|
super.close();
|
||||||
|
this.repository.disconnect(this);
|
||||||
|
Log.getInstance().infof("[CLIENT] %s s'est déconnecté\n", getContext().getLogin());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.getInstance().infoln("[CH] Error while closing client.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLogin() {
|
public String getLogin() {
|
||||||
return this.context.getLogin();
|
return this.getContext().getLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package lightcontainer.domains.client;
|
package lightcontainer.domains.client;
|
||||||
|
|
||||||
import lightcontainer.storage.AppData;
|
import lightcontainer.repository.ReadOnlyClientRepository;
|
||||||
import lightcontainer.storage.File;
|
import lightcontainer.storage.File;
|
||||||
|
import lightcontainer.storage.ReadOnlyFile;
|
||||||
import lightcontainer.storage.Repository;
|
import lightcontainer.storage.Repository;
|
||||||
import lightcontainer.storage.User;
|
|
||||||
import lightcontainer.utils.AES_GCM;
|
import lightcontainer.utils.AES_GCM;
|
||||||
|
import lightcontainer.utils.BCryptHasher;
|
||||||
import lightcontainer.utils.ShaHasher;
|
import lightcontainer.utils.ShaHasher;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -17,10 +16,10 @@ import java.util.Set;
|
|||||||
* Permet de récupérer les données à celui-ci et d'effectuer des actions sur le context courant.
|
* Permet de récupérer les données à celui-ci et d'effectuer des actions sur le context courant.
|
||||||
*/
|
*/
|
||||||
public class Context {
|
public class Context {
|
||||||
|
// Variables
|
||||||
private Repository repository;
|
private final Repository repository;
|
||||||
|
|
||||||
private RequestBundle requestBundle;
|
private RequestBundle requestBundle;
|
||||||
|
private ReadOnlyClientRepository clientRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login de l'utilisateur
|
* Login de l'utilisateur
|
||||||
@ -33,8 +32,9 @@ public class Context {
|
|||||||
private String domain;
|
private String domain;
|
||||||
|
|
||||||
// Constructeur
|
// Constructeur
|
||||||
public Context(Repository repository) {
|
public Context(Repository repository, ReadOnlyClientRepository clientRepository) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
|
this.clientRepository = clientRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -46,18 +46,18 @@ public class Context {
|
|||||||
* @return TRUE si l'utilisateur a pu être créé
|
* @return TRUE si l'utilisateur a pu être créé
|
||||||
*/
|
*/
|
||||||
public boolean createUser(String login, String password) {
|
public boolean createUser(String login, String password) {
|
||||||
|
if (clientRepository.hasClient(login)) { // Empêcher double connection
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String key = AES_GCM.generateSecretKey();
|
String key = AES_GCM.generateSecretKey();
|
||||||
|
String hashedPassword = BCryptHasher.hashPassword(password);
|
||||||
ShaHasher hasher = new ShaHasher(password);
|
if (this.repository.addUser(login, hashedPassword, key)) {
|
||||||
password = hasher.nextHashing();
|
|
||||||
String passwordSalt = hasher.getSalt();
|
|
||||||
|
|
||||||
if (this.repository.addUser(login, password, key, passwordSalt)) {
|
|
||||||
this.login = login;
|
this.login = login;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (AES_GCM.AesGcmException e) {
|
} catch (AES_GCM.AesGcmException ignored) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -73,21 +73,21 @@ public class Context {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de demander la connection de l'utilisateur
|
* Permet de demander la connexion de l'utilisateur
|
||||||
*
|
*
|
||||||
* @param login Login
|
* @param login Login
|
||||||
* @param password Mot de passe
|
* @param password Mot de passe
|
||||||
* @return TRUE si l'utilisateur a été authentifié
|
* @return TRUE si l'utilisateur a été authentifié
|
||||||
*/
|
*/
|
||||||
public boolean signIn(String login, String password) {
|
public boolean signIn(String login, String password) {
|
||||||
String passwordSalt = this.repository.getUserPasswordSalt(login);
|
if (login == null || password == null) {
|
||||||
if (passwordSalt != null) {
|
return false;
|
||||||
ShaHasher hasher = new ShaHasher(password);
|
}
|
||||||
|
|
||||||
if (this.repository.verifyUser(login, hasher.fromSalt(hasher.saltToByte(passwordSalt)))) {
|
// Empêcher double connection
|
||||||
this.login = login;
|
if (!clientRepository.hasClient(login) && this.repository.verifyUser(login, password)) {
|
||||||
return true;
|
this.login = login;
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ public class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet d'ajouter des données pour la requête courrante
|
* Permet d'ajouter des données pour la requête courante
|
||||||
*
|
*
|
||||||
* @param key La clé permettant de retrouver la valeur
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @param value La valeur associée à la clé
|
* @param value La valeur associée à la clé
|
||||||
@ -129,7 +129,7 @@ public class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet d'ajouter des données pour la requête courrante
|
* Permet d'ajouter des données pour la requête courante
|
||||||
*
|
*
|
||||||
* @param key La clé permettant de retrouver la valeur
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @param value La valeur associée à la clé
|
* @param value La valeur associée à la clé
|
||||||
@ -139,7 +139,15 @@ public class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer des données pour la requête courrante
|
* @param key La clé permettant de retrouver la valeur
|
||||||
|
* @param value La valeur associée à la clé
|
||||||
|
*/
|
||||||
|
public void putDataLong(String key, long value) {
|
||||||
|
requestBundle.putLong(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de récupérer des données pour la requête courante
|
||||||
*
|
*
|
||||||
* @param key La clé permettant de retrouver la valeur
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @return La valeur associée à la clé ou null
|
* @return La valeur associée à la clé ou null
|
||||||
@ -149,7 +157,7 @@ public class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer des données pour la requête courrante
|
* Permet de récupérer des données pour la requête courante
|
||||||
*
|
*
|
||||||
* @param key La clé permettant de retrouver la valeur
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @return La valeur associée à la clé
|
* @return La valeur associée à la clé
|
||||||
@ -158,6 +166,14 @@ public class Context {
|
|||||||
return requestBundle.getInt(key);
|
return requestBundle.getInt(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key La clé permettant de retrouver la valeur
|
||||||
|
* @return La valeur associée à la clé
|
||||||
|
*/
|
||||||
|
public long getDataLong(String key) {
|
||||||
|
return requestBundle.getLong(key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet d'ajouter un fichier à l'utilisateur
|
* Permet d'ajouter un fichier à l'utilisateur
|
||||||
*
|
*
|
||||||
@ -168,10 +184,24 @@ public class Context {
|
|||||||
* @param domain Domain dans lequel est stocké le fichier
|
* @param domain Domain dans lequel est stocké le fichier
|
||||||
* @return TRUE si le fichier a pu être enregistré.
|
* @return TRUE si le fichier a pu être enregistré.
|
||||||
*/
|
*/
|
||||||
public boolean addFile(String fileName, String fileNameSalt, int size, String iv, String domain) {
|
public boolean addFile(String fileName, String fileNameSalt, long size, String iv, String domain) {
|
||||||
return this.repository.addFileFor(new File(fileName, fileNameSalt, size, iv, Set.of(domain)), getLogin());
|
return this.repository.addFileFor(new File(fileName, fileNameSalt, size, iv, Set.of(domain)), getLogin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHashedFileName(String fileName) {
|
||||||
|
ReadOnlyFile file = repository.getFileOf(fileName, login);
|
||||||
|
if (file != null) {
|
||||||
|
String completeFileName = login + "_" + fileName;
|
||||||
|
ShaHasher hasher = new ShaHasher(completeFileName);
|
||||||
|
return hasher.fromSalt(hasher.saltToByte(file.getFileNameSalt()));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyFile getFile(String fileName) {
|
||||||
|
return this.repository.getFileOf(fileName, login);
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> getStringifiedFilesOf() {
|
public List<String> getStringifiedFilesOf() {
|
||||||
return repository.getStringifiedFilesOf(login);
|
return repository.getStringifiedFilesOf(login);
|
||||||
}
|
}
|
||||||
@ -187,4 +217,8 @@ public class Context {
|
|||||||
public void setDomain(String domain) {
|
public void setDomain(String domain) {
|
||||||
this.domain = domain;
|
this.domain = domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteFile(String deletedFileName) {
|
||||||
|
repository.deleteFileOf(deletedFileName, login);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
package lightcontainer.domains.client;
|
package lightcontainer.domains.client;
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class RequestBundle {
|
public class RequestBundle {
|
||||||
|
|
||||||
private Map<String, String> stringData = new HashMap<>();
|
private final Map<String, String> stringData = new HashMap<>();
|
||||||
|
|
||||||
private Map<String, Integer> intData = new HashMap<>();
|
private final Map<String, Integer> intData = new HashMap<>();
|
||||||
|
|
||||||
|
private final Map<String, Long> longData = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet d'ajouter des String
|
* Permet d'ajouter des String
|
||||||
* @param key La clé permettant de retrouver la valeur
|
*
|
||||||
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @param value La valeur associée à la clé
|
* @param value La valeur associée à la clé
|
||||||
*/
|
*/
|
||||||
public void putString(String key, String value) {
|
public void putString(String key, String value) {
|
||||||
@ -21,7 +23,8 @@ public class RequestBundle {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet d'ajouter des int
|
* Permet d'ajouter des int
|
||||||
* @param key La clé permettant de retrouver la valeur
|
*
|
||||||
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @param value La valeur associée à la clé
|
* @param value La valeur associée à la clé
|
||||||
*/
|
*/
|
||||||
public void putInt(String key, int value) {
|
public void putInt(String key, int value) {
|
||||||
@ -30,6 +33,7 @@ public class RequestBundle {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer des données string
|
* Permet de récupérer des données string
|
||||||
|
*
|
||||||
* @param key La clé permettant de retrouver la valeur
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @return La valeur associée à la clé ou null
|
* @return La valeur associée à la clé ou null
|
||||||
*/
|
*/
|
||||||
@ -39,10 +43,28 @@ public class RequestBundle {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer des données int
|
* Permet de récupérer des données int
|
||||||
|
*
|
||||||
* @param key La clé permettant de retrouver la valeur
|
* @param key La clé permettant de retrouver la valeur
|
||||||
* @return La valeur associée à la clé
|
* @return La valeur associée à la clé
|
||||||
*/
|
*/
|
||||||
public int getInt(String key) {
|
public int getInt(String key) {
|
||||||
return intData.get(key);
|
return intData.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key La clé permettant de retrouver la valeur
|
||||||
|
* @param value La valeur associée à la clé
|
||||||
|
*/
|
||||||
|
public void putLong(String key, long value) {
|
||||||
|
longData.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param key La clé permettant de retrouver la valeur
|
||||||
|
* @return La valeur associée à la clé ou null
|
||||||
|
*/
|
||||||
|
public long getLong(String key) {
|
||||||
|
return longData.get(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,75 +1,44 @@
|
|||||||
package lightcontainer.domains.client;
|
package lightcontainer.domains.client;
|
||||||
|
|
||||||
import lightcontainer.domains.Task;
|
|
||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
import lightcontainer.interfaces.StoreProcessorFFE;
|
import lightcontainer.interfaces.StoreProcessorFFE;
|
||||||
import lightcontainer.protocol.ProtocolReader;
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
import lightcontainer.utils.Log;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StoreProcessor
|
* StoreProcessor
|
||||||
*
|
* <p>
|
||||||
* <!> MULTICAST CLIENT <!>
|
* <!> MULTICAST CLIENT <!>
|
||||||
* Class communicating with the storebackend and
|
* Class communicating with the storebackend and
|
||||||
* processing the tasks in the FileFrontEnd
|
* processing the tasks in the FileFrontEnd
|
||||||
*
|
*
|
||||||
* @version 1.1
|
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
||||||
* @since 1.0
|
* @version 1.1
|
||||||
*
|
* @see Runnable
|
||||||
* @see Runnable
|
* @see AutoCloseable
|
||||||
* @see AutoCloseable
|
* @since 1.0
|
||||||
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
|
||||||
*/
|
*/
|
||||||
public class StoreProcessor extends Thread implements AutoCloseable {
|
public class StoreProcessor extends UnicastThread implements AutoCloseable {
|
||||||
// Variables
|
// Variables
|
||||||
private final StoreProcessorFFE fileFrontEnd;
|
private final StoreProcessorFFE fileFrontEnd;
|
||||||
private final Socket store;
|
|
||||||
private final String domain;
|
private final String domain;
|
||||||
private boolean client_run;
|
private LocalDateTime lastAnnounce;
|
||||||
|
|
||||||
private BufferedReader reader;
|
|
||||||
private Context context;
|
|
||||||
private PrintWriter writer;
|
|
||||||
private ProtocolWriter.ProtocolResult protocolResult;
|
private ProtocolWriter.ProtocolResult protocolResult;
|
||||||
private ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public StoreProcessor(Socket socket, String domain, StoreProcessorFFE ffe, ProtocolRepository protocolRep) {
|
public StoreProcessor(Socket socket, String domain, StoreProcessorFFE ffe, ProtocolRepository protocolRep) {
|
||||||
|
super(socket);
|
||||||
this.domain = domain;
|
this.domain = domain;
|
||||||
this.fileFrontEnd = ffe;
|
this.fileFrontEnd = ffe;
|
||||||
this.store = socket;
|
|
||||||
this.protocolRep = protocolRep;
|
this.protocolRep = protocolRep;
|
||||||
this.client_run = false;
|
|
||||||
initStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise the Store's Reader and Writer.
|
|
||||||
*
|
|
||||||
* @see BufferedReader
|
|
||||||
* @see PrintWriter
|
|
||||||
* @since 1.0
|
|
||||||
*/
|
|
||||||
private void initStore() {
|
|
||||||
try {
|
|
||||||
this.reader = new BufferedReader(new InputStreamReader(
|
|
||||||
this.store.getInputStream(),
|
|
||||||
StandardCharsets.UTF_8
|
|
||||||
));
|
|
||||||
this.writer = new PrintWriter(new OutputStreamWriter(
|
|
||||||
this.store.getOutputStream(),
|
|
||||||
StandardCharsets.UTF_8
|
|
||||||
), true);
|
|
||||||
|
|
||||||
this.start();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,42 +49,71 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
this.client_run = true;
|
// Set process to true
|
||||||
while (this.client_run) {
|
this.setRunning(true);
|
||||||
|
// Process while
|
||||||
|
while (this.isRunning()) {
|
||||||
try {
|
try {
|
||||||
waitAction();
|
if (protocolResult == null) { // Si on n'a pas encore la commande à envoyer
|
||||||
System.out.println("[SBE] Envoie commande : " + protocolResult.getCommand());
|
waitAction();
|
||||||
|
}
|
||||||
|
Log.getInstance().infoln("[SBE] Envoie commande : " + protocolResult.getCommand());
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
this.writer.write(protocolResult.getCommand());
|
this.write(protocolResult.getCommand());
|
||||||
this.writer.flush();
|
|
||||||
protocolResult.write(this.store.getOutputStream());
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
protocolResult.write(this.getOutputStream());
|
||||||
|
} catch (IOException writeException) { // Si SBE fermé
|
||||||
|
// Envoie au client que la requête n'a pu être traitée
|
||||||
|
alertAvailable(null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
// Response
|
// Response
|
||||||
String responseCommand = this.reader.readLine() + "\r\n";
|
String responseCommand = this.readLine();
|
||||||
if (responseCommand != null)
|
if (responseCommand != null && !responseCommand.isBlank()) {
|
||||||
System.out.println("StoreBackEnd: " + responseCommand);
|
responseCommand += "\r\n";
|
||||||
ProtocolReader.ProtocolResult responseResult = protocolRep.executeReader(context, responseCommand);
|
ProtocolReader.ProtocolResult responseResult = protocolRep.executeReader(getContext(), responseCommand);
|
||||||
responseResult.read(
|
if (responseResult != null) {
|
||||||
this.store.getInputStream()
|
Log.getInstance().infoln("StoreBackEnd (" + domain + ") response to client: " + responseResult.getResultCommand());
|
||||||
);
|
responseResult.read(
|
||||||
System.out.println("StoreBackEnd response to client: " + responseResult.getResultCommand());
|
this.getInputStream()
|
||||||
|
);
|
||||||
|
|
||||||
alertAvalaible(responseResult.getResultCommand());
|
alertAvailable(responseResult.getResultCommand());
|
||||||
|
} else {
|
||||||
|
Log.getInstance().infoln("StoreBackEnd result: Commande null");
|
||||||
|
alertAvailable(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.getInstance().infoln("StoreBackEnd: Commande null");
|
||||||
|
alertAvailable(null);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (IOException ignore) { }
|
} catch (IOException exception) {
|
||||||
|
Log.getInstance().infoln("[ERROR] Problem with SBE (" + domain + ") : " + exception.getMessage());
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closing SBE
|
||||||
|
try {
|
||||||
|
this.close();
|
||||||
|
this.fileFrontEnd.onStoreDisconnect(this.domain);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.getInstance().infoln("[ERROR] Error while closing SBE (" + domain + ") : " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de demander au StoreBackEnd d'effectuer une commande
|
* Permet de demander au StoreBackEnd d'effectuer une commande
|
||||||
|
*
|
||||||
* @param protocolResult La commande à effectuer
|
* @param protocolResult La commande à effectuer
|
||||||
*/
|
*/
|
||||||
public void executeCommand(Context context, ProtocolWriter.ProtocolResult protocolResult) {
|
public void executeCommand(Context context, ProtocolWriter.ProtocolResult protocolResult) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
this.protocolResult = protocolResult;
|
this.protocolResult = protocolResult;
|
||||||
this.context = context;
|
setContext(context);
|
||||||
this.notify();
|
this.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,10 +121,13 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
|||||||
/**
|
/**
|
||||||
* Permet de déclarer le StoreBackEnd disponible
|
* Permet de déclarer le StoreBackEnd disponible
|
||||||
*/
|
*/
|
||||||
private void alertAvalaible(ProtocolWriter.ProtocolResult responseCommand) {
|
private void alertAvailable(ProtocolWriter.ProtocolResult responseCommand) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
this.protocolResult = null;
|
this.protocolResult = null;
|
||||||
fileFrontEnd.onStoreAvailable(this, responseCommand);
|
if (responseCommand == null) {
|
||||||
|
this.setRunning(false);
|
||||||
|
}
|
||||||
|
fileFrontEnd.onStoreAvailable(this.getDomain(), responseCommand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +138,9 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
|||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
try {
|
||||||
this.wait();
|
this.wait();
|
||||||
} catch (InterruptedException e) { e.printStackTrace(); }
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,11 +152,9 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
if (this.client_run) {
|
if (this.isRunning()) {
|
||||||
try {
|
this.setRunning(false);
|
||||||
this.client_run = false;
|
Log.getInstance().infoln("[SBE] Fermeture de " + domain);
|
||||||
this.store.close();
|
|
||||||
} catch (IOException ignored) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,11 +177,25 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
|||||||
return Objects.hash(domain);
|
return Objects.hash(domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canProcessTask(Task task) {
|
public boolean canProcessTask() {
|
||||||
return this.protocolResult == null; // Vérifier si tâche veut ce SBE
|
return this.protocolResult == null; // Vérifier si tâche veut ce SBE
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDomain() {
|
public String getDomain() {
|
||||||
return this.domain;
|
return this.domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de mettre à jours la dernière annonce de ce SBE au FFE
|
||||||
|
*/
|
||||||
|
public void setLastAnnounce(LocalDateTime lastAnnounce) {
|
||||||
|
this.lastAnnounce = lastAnnounce;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de mettre à jours la dernière annonce de ce SBE au FFE
|
||||||
|
*/
|
||||||
|
public LocalDateTime getLastAnnounce() {
|
||||||
|
return lastAnnounce;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,148 @@
|
|||||||
|
package lightcontainer.domains.client;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public abstract class UnicastThread extends Thread implements AutoCloseable {
|
||||||
|
// Variables
|
||||||
|
private final Socket socket;
|
||||||
|
private Context context;
|
||||||
|
private BufferedReader reader;
|
||||||
|
private PrintWriter writer;
|
||||||
|
private boolean isRunning = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnicastThread Constructor
|
||||||
|
*
|
||||||
|
* @param socket Unicast Socket
|
||||||
|
*/
|
||||||
|
public UnicastThread(Socket socket) {
|
||||||
|
this(socket, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnicastThread Constructor
|
||||||
|
*
|
||||||
|
* @param socket Unicast Socket
|
||||||
|
* @param context Connection context
|
||||||
|
*/
|
||||||
|
public UnicastThread(Socket socket, Context context) {
|
||||||
|
this.socket = socket;
|
||||||
|
this.context = context;
|
||||||
|
initSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the Socket's Reader and Writer.
|
||||||
|
*
|
||||||
|
* @see BufferedReader
|
||||||
|
* @see PrintWriter
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
private void initSocket() {
|
||||||
|
// Start the thread
|
||||||
|
try {
|
||||||
|
this.reader = new BufferedReader(new InputStreamReader(
|
||||||
|
this.socket.getInputStream(),
|
||||||
|
StandardCharsets.UTF_8
|
||||||
|
));
|
||||||
|
this.writer = new PrintWriter(new OutputStreamWriter(
|
||||||
|
this.socket.getOutputStream(),
|
||||||
|
StandardCharsets.UTF_8
|
||||||
|
), true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read from the socket.
|
||||||
|
*
|
||||||
|
* @return Returns the line that was read
|
||||||
|
*/
|
||||||
|
protected String readLine() throws IOException {
|
||||||
|
return this.reader.readLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to the socket.
|
||||||
|
*
|
||||||
|
* @param str Content to write.
|
||||||
|
*/
|
||||||
|
protected void write(String str) {
|
||||||
|
this.writer.write(str);
|
||||||
|
this.writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print to the socket.
|
||||||
|
*
|
||||||
|
* @param str Content to print.
|
||||||
|
*/
|
||||||
|
protected void print(String str) {
|
||||||
|
this.writer.print(str);
|
||||||
|
this.writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter, allow to retrieve an inputstream of the socket.
|
||||||
|
*
|
||||||
|
* @return Socket inputstream.
|
||||||
|
*/
|
||||||
|
protected InputStream getInputStream() throws IOException {
|
||||||
|
return this.socket.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter, allow to retrieve an outputstream of the socket.
|
||||||
|
*
|
||||||
|
* @return Socket outputstream.
|
||||||
|
*/
|
||||||
|
protected OutputStream getOutputStream() throws IOException {
|
||||||
|
return this.socket.getOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close all connection stream and resources.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
this.reader.close();
|
||||||
|
this.writer.close();
|
||||||
|
this.socket.close();
|
||||||
|
setRunning(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow to verify if the thread is running.
|
||||||
|
* @return True; yes, False; no.
|
||||||
|
*/
|
||||||
|
protected boolean isRunning() {
|
||||||
|
return this.isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter, define the running status.
|
||||||
|
* @param running True; is running, False; is not running.
|
||||||
|
*/
|
||||||
|
protected void setRunning(boolean running) {
|
||||||
|
this.isRunning = running;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve connection context.
|
||||||
|
* @return Context.
|
||||||
|
*/
|
||||||
|
protected Context getContext() {
|
||||||
|
return this.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set connection context.
|
||||||
|
* @param context context.
|
||||||
|
*/
|
||||||
|
protected void setContext(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,10 @@ package lightcontainer.domains.server;
|
|||||||
import lightcontainer.domains.client.StoreProcessor;
|
import lightcontainer.domains.client.StoreProcessor;
|
||||||
import lightcontainer.interfaces.MulticastSPR;
|
import lightcontainer.interfaces.MulticastSPR;
|
||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
import lightcontainer.protocol.ProtocolReader;
|
|
||||||
import lightcontainer.protocol.rules.reader.HelloRule;
|
import lightcontainer.protocol.rules.reader.HelloRule;
|
||||||
import lightcontainer.repository.FileFrontEnd;
|
import lightcontainer.repository.FileFrontEnd;
|
||||||
|
import lightcontainer.utils.Log;
|
||||||
|
import lightcontainer.utils.NetChooser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
@ -25,7 +26,8 @@ public class MulticastServerListener implements Runnable {
|
|||||||
// Variable
|
// Variable
|
||||||
private final String multicast_address;
|
private final String multicast_address;
|
||||||
private final int multicast_port;
|
private final int multicast_port;
|
||||||
private FileFrontEnd ffe;
|
private final String network_interface;
|
||||||
|
private final FileFrontEnd ffe;
|
||||||
private final MulticastSPR repository;
|
private final MulticastSPR repository;
|
||||||
private final ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
@ -33,12 +35,13 @@ public class MulticastServerListener implements Runnable {
|
|||||||
private MulticastSocket listener;
|
private MulticastSocket listener;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public MulticastServerListener(FileFrontEnd ffe, MulticastSPR repository, ProtocolRepository protocolRep, String multicast_address, int multicast_port) {
|
public MulticastServerListener(FileFrontEnd ffe, MulticastSPR repository, ProtocolRepository protocolRep, String multicast_address, int multicast_port, String network_interface) {
|
||||||
this.ffe = ffe;
|
this.ffe = ffe;
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
this.protocolRep = protocolRep;
|
this.protocolRep = protocolRep;
|
||||||
this.multicast_address = multicast_address;
|
this.multicast_address = multicast_address;
|
||||||
this.multicast_port = multicast_port;
|
this.multicast_port = multicast_port;
|
||||||
|
this.network_interface = network_interface;
|
||||||
repository.setServerListener(this);
|
repository.setServerListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +57,9 @@ public class MulticastServerListener implements Runnable {
|
|||||||
try {
|
try {
|
||||||
// Create a new listening socket
|
// Create a new listening socket
|
||||||
this.listener = new MulticastSocket(this.multicast_port);
|
this.listener = new MulticastSocket(this.multicast_port);
|
||||||
|
|
||||||
|
this.selectInterface();
|
||||||
|
|
||||||
// Create an identifier for the multicast group on the specified ip
|
// Create an identifier for the multicast group on the specified ip
|
||||||
InetAddress listener_group = InetAddress.getByName(this.multicast_address);
|
InetAddress listener_group = InetAddress.getByName(this.multicast_address);
|
||||||
// Creation of a packet for the information received
|
// Creation of a packet for the information received
|
||||||
@ -63,25 +69,52 @@ public class MulticastServerListener implements Runnable {
|
|||||||
while (true) {
|
while (true) {
|
||||||
// Read the packet received and build a string of characters
|
// Read the packet received and build a string of characters
|
||||||
this.listener.receive(packet);
|
this.listener.receive(packet);
|
||||||
String data = new String(packet.getData(), 0, packet.getLength());
|
|
||||||
// Create a new StoreBacked (try used in the case of an error to maintain the listening loop)
|
|
||||||
try {
|
|
||||||
// TODO Récupérer le port du message du packet et le setup (add description of the line).
|
|
||||||
HelloRule.Result readerResult = protocolRep.executeReader(null, data);
|
|
||||||
System.out.printf("Nouveau SBE : Domain=%s | Port=%d\n", readerResult.getDomain(), readerResult.getPort());
|
|
||||||
|
|
||||||
Socket socket = new Socket(packet.getAddress(), readerResult.getPort());
|
onNewSbe(packet);
|
||||||
|
}
|
||||||
// Create the store processor
|
} catch (IOException ioException) {
|
||||||
StoreProcessor storeProcessor = new StoreProcessor(socket, readerResult.getDomain(), ffe, protocolRep); // TODO <!!!> : Voir comment on procède get via repo ou ici ?!
|
Log.getInstance().infoln("[ERREUR] Multicast server can't start : " + ioException.getMessage());
|
||||||
|
}
|
||||||
// Add the store processor to its repository
|
}
|
||||||
this.repository.addStore(storeProcessor);
|
|
||||||
} catch (IOException ignore) {
|
private void onNewSbe(DatagramPacket packet) {
|
||||||
ignore.printStackTrace();
|
try {
|
||||||
}
|
String data = new String(packet.getData(), 0, packet.getLength());
|
||||||
|
|
||||||
|
HelloRule.Result readerResult = protocolRep.executeReader(null, data);
|
||||||
|
|
||||||
|
Log.getInstance().infof("Nouveau SBE : Domain=%s | Port=%d\n", readerResult.getDomain(), readerResult.getPort());
|
||||||
|
|
||||||
|
if (!this.repository.hasDomain(readerResult.getDomain())){
|
||||||
|
Socket socket = new Socket(packet.getAddress(), readerResult.getPort());
|
||||||
|
|
||||||
|
// Create the store processor
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// Contient déjà le SBE donc maj de la dernière activité
|
||||||
|
this.repository.updateLastAnnounce(readerResult.getDomain());
|
||||||
|
} catch (IOException | ClassCastException exception) {
|
||||||
|
Log.getInstance().infoln("[ERREUR] Une SBE essaye de se connecter avec une mauvaise configuration : " + exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de choisir l'interface réseau d'écoute en Multicast
|
||||||
|
*/
|
||||||
|
private void selectInterface() {
|
||||||
|
try {
|
||||||
|
this.listener.setNetworkInterface(NetworkInterface.getByName(network_interface));
|
||||||
|
} catch (SocketException| NullPointerException e) {
|
||||||
|
NetChooser netChooser = new NetChooser();
|
||||||
|
try {
|
||||||
|
this.listener.setNetworkInterface(netChooser.requestInterface());
|
||||||
|
} catch (SocketException socketException) {
|
||||||
|
socketException.printStackTrace();
|
||||||
|
this.stop();
|
||||||
}
|
}
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +125,7 @@ public class MulticastServerListener implements Runnable {
|
|||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
repository.disconnectDomains();
|
||||||
this.listener.close();
|
this.listener.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,12 @@ import lightcontainer.domains.client.Context;
|
|||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
import lightcontainer.interfaces.UnicastCHR;
|
import lightcontainer.interfaces.UnicastCHR;
|
||||||
import lightcontainer.repository.FileFrontEnd;
|
import lightcontainer.repository.FileFrontEnd;
|
||||||
import lightcontainer.storage.AppData;
|
|
||||||
import lightcontainer.storage.Repository;
|
import lightcontainer.storage.Repository;
|
||||||
|
|
||||||
import javax.net.ssl.SSLServerSocket;
|
|
||||||
import javax.net.ssl.SSLServerSocketFactory;
|
import javax.net.ssl.SSLServerSocketFactory;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
|
||||||
|
|
||||||
public class UnicastServerListener implements Runnable {
|
public class UnicastServerListener implements Runnable {
|
||||||
// Variables
|
// Variables
|
||||||
@ -55,11 +52,11 @@ public class UnicastServerListener implements Runnable {
|
|||||||
SSLSocket client = (SSLSocket) this.server.accept();
|
SSLSocket client = (SSLSocket) this.server.accept();
|
||||||
|
|
||||||
// Create a new Handler client by passing these dependencies to it
|
// Create a new Handler client by passing these dependencies to it
|
||||||
ClientHandler clientHandler = new ClientHandler(this.repository, client, ffe, protocolRep, new Context(repositoryStorage));
|
ClientHandler clientHandler = new ClientHandler(this.repository, client, ffe, protocolRep, new Context(repositoryStorage, repository));
|
||||||
// Add the client handler to its repository (clienthandlerrepository)
|
// Add the client handler to its repository (clienthandlerrepository)
|
||||||
this.repository.addClient(clientHandler);
|
this.repository.addClient(clientHandler);
|
||||||
// Start the thread
|
// Start the thread
|
||||||
(new Thread(clientHandler)).start();
|
clientHandler.start();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -3,7 +3,7 @@ package lightcontainer.enumerations;
|
|||||||
import lightcontainer.domains.Task;
|
import lightcontainer.domains.Task;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enumeration to define the type of a {@link Task}.
|
* enumeration to define the type of {@link Task}.
|
||||||
*/
|
*/
|
||||||
public enum TaskType {
|
public enum TaskType {
|
||||||
SEND,
|
SEND,
|
||||||
|
@ -13,9 +13,11 @@ public interface ClientHandlerFFE {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Demande le traitement d'une commande
|
* Demande le traitement d'une commande
|
||||||
|
*
|
||||||
* @param context Context de la requête
|
* @param context Context de la requête
|
||||||
* @param command Commande à traiter
|
* @param command Commande à traiter
|
||||||
*/
|
*/
|
||||||
void newCommand(Context context, ProtocolWriter.ProtocolResult command);
|
void newCommand(Context context, ProtocolWriter.ProtocolResult command, String requestDomain);
|
||||||
|
|
||||||
|
boolean canExecuteCommand(String domain);
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,63 @@ import lightcontainer.domains.client.StoreProcessor;
|
|||||||
import lightcontainer.domains.server.MulticastServerListener;
|
import lightcontainer.domains.server.MulticastServerListener;
|
||||||
import lightcontainer.repository.StoreProcessorRepository;
|
import lightcontainer.repository.StoreProcessorRepository;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A communication interface between a {@link StoreProcessor} and the {@link StoreProcessorRepository}.
|
* A communication interface between a {@link StoreProcessor} and the {@link StoreProcessorRepository}.
|
||||||
*/
|
*/
|
||||||
public interface MulticastSPR {
|
public interface MulticastSPR {
|
||||||
/**
|
/**
|
||||||
* Setter, allow to define the ServerListener of a repository.
|
* Setter, allow to define the ServerListener of a repository.
|
||||||
|
*
|
||||||
* @param server ServerListener to set as default.
|
* @param server ServerListener to set as default.
|
||||||
*/
|
*/
|
||||||
void setServerListener(MulticastServerListener server);
|
void setServerListener(MulticastServerListener server);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a StorePorcessor.
|
* Add a StorePorcessor.
|
||||||
|
*
|
||||||
* @param store Store processor to add.
|
* @param store Store processor to add.
|
||||||
*/
|
*/
|
||||||
void addStore(StoreProcessor store);
|
boolean addStore(StoreProcessor store);
|
||||||
|
|
||||||
String findDomain(Task task);
|
String findDomain();
|
||||||
|
|
||||||
void assignTask(String stor, Task task);
|
void assignTask(String stor, Task task);
|
||||||
|
|
||||||
|
boolean hasDomain(String domain);
|
||||||
|
|
||||||
|
int domainCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déconnecte tous les SBE
|
||||||
|
*/
|
||||||
|
void disconnectDomains();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de déconnecter un SBE
|
||||||
|
*
|
||||||
|
* @param domain Le domaine du SBE à déconnecter
|
||||||
|
*/
|
||||||
|
void closeStore(String domain);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de mettre à jours la dernière annonce de ce SBE au FFE
|
||||||
|
* @param domain Le domain s'annoncant
|
||||||
|
*/
|
||||||
|
void updateLastAnnounce(String domain);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de récupérer les noms des domaines connectés au FFE
|
||||||
|
* @return Les noms des domaines connectés au FFE
|
||||||
|
*/
|
||||||
|
Collection<String> getDomains();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de récupérer la dernière annonce d'un SBE
|
||||||
|
* @return La dernière annonce d'un SBE
|
||||||
|
*/
|
||||||
|
LocalDateTime getLastAnnounce(String domain);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ public interface ProtocolRepository {
|
|||||||
|
|
||||||
<T extends ProtocolReader.ProtocolResult> T executeReader(Context context, String data);
|
<T extends ProtocolReader.ProtocolResult> T executeReader(Context context, String data);
|
||||||
|
|
||||||
<T extends ProtocolWriter.ProtocolResult> T executeWriter(Context context, String cmdName, String... data);
|
<T extends ProtocolWriter.ProtocolResult> T executeWriter(Context context, String cmdName, String... data);
|
||||||
|
|
||||||
void addReader(ProtocolReader reader);
|
void addReader(ProtocolReader reader);
|
||||||
|
|
||||||
|
@ -10,8 +10,16 @@ import lightcontainer.repository.FileFrontEnd;
|
|||||||
public interface StoreProcessorFFE {
|
public interface StoreProcessorFFE {
|
||||||
/**
|
/**
|
||||||
* Allows a {@link StoreProcessor} to notify the FFE that it's available.
|
* Allows a {@link StoreProcessor} to notify the FFE that it's available.
|
||||||
* @param store The store processor that is now available.
|
*
|
||||||
* @param responseCommand
|
* @param storeDomain The store processor that is now available.
|
||||||
|
* @param response
|
||||||
*/
|
*/
|
||||||
void onStoreAvailable(StoreProcessor store, ProtocolWriter.ProtocolResult response);
|
void onStoreAvailable(String storeDomain, ProtocolWriter.ProtocolResult response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de déconnecter un SBE
|
||||||
|
*
|
||||||
|
* @param domain Le domaine du SBE à déconnecter
|
||||||
|
*/
|
||||||
|
void onStoreDisconnect(String domain);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,33 @@
|
|||||||
package lightcontainer.interfaces;
|
package lightcontainer.interfaces;
|
||||||
|
|
||||||
import lightcontainer.domains.client.ClientHandler;
|
import lightcontainer.domains.client.ClientHandler;
|
||||||
import lightcontainer.domains.server.MulticastServerListener;
|
|
||||||
import lightcontainer.domains.server.UnicastServerListener;
|
import lightcontainer.domains.server.UnicastServerListener;
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
import lightcontainer.repository.ClientHandlerRepository;
|
import lightcontainer.repository.ClientHandlerRepository;
|
||||||
|
import lightcontainer.repository.ReadOnlyClientRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A communication interface between a {@link ClientHandler} and the {@link ClientHandlerRepository}.
|
* A communication interface between a {@link ClientHandler} and the {@link ClientHandlerRepository}.
|
||||||
*/
|
*/
|
||||||
public interface UnicastCHR {
|
public interface UnicastCHR extends ReadOnlyClientRepository {
|
||||||
/**
|
/**
|
||||||
* Setter, allow to define the ServerListener of a repository.
|
* Setter, allow to define the ServerListener of a repository.
|
||||||
|
*
|
||||||
* @param server ServerListener to set as default.
|
* @param server ServerListener to set as default.
|
||||||
*/
|
*/
|
||||||
void setServerListener(UnicastServerListener server);
|
void setServerListener(UnicastServerListener server);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a ClientHandler.
|
* Add a ClientHandler.
|
||||||
|
*
|
||||||
* @param client Client Handler to add.
|
* @param client Client Handler to add.
|
||||||
*/
|
*/
|
||||||
void addClient(ClientHandler client);
|
void addClient(ClientHandler client);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de demander la déconnection d'un client
|
* Permet de demander la déconnection d'un client
|
||||||
|
*
|
||||||
* @param client Le client à déconnecter
|
* @param client Le client à déconnecter
|
||||||
*/
|
*/
|
||||||
void disconnect(ClientHandler client);
|
void disconnect(ClientHandler client);
|
||||||
|
@ -20,11 +20,13 @@ public abstract class ProtocolReader {
|
|||||||
this.rulePattern = Pattern.compile(pattern);
|
this.rulePattern = Pattern.compile(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Receiver list
|
||||||
public enum ResultCmdReceiver {
|
public enum ResultCmdReceiver {
|
||||||
CLIENT,
|
CLIENT,
|
||||||
STOREBACKEND
|
STOREBACKEND
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modèle utilisé par tout les résultats des règles de protocol.
|
* Modèle utilisé par tout les résultats des règles de protocol.
|
||||||
* 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.
|
* 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.
|
||||||
@ -39,7 +41,12 @@ public abstract class ProtocolReader {
|
|||||||
/**
|
/**
|
||||||
* Le context courant
|
* Le context courant
|
||||||
*/
|
*/
|
||||||
private Context context;
|
private final Context context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domaine demandé pour l'exécution de cette commande (NULL si aucun domaine spécifique demandé)
|
||||||
|
*/
|
||||||
|
private String requestDomain;
|
||||||
|
|
||||||
public ProtocolResult(Context context) {
|
public ProtocolResult(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -52,7 +59,12 @@ public abstract class ProtocolReader {
|
|||||||
*/
|
*/
|
||||||
private ResultCmdReceiver receiver;
|
private ResultCmdReceiver receiver;
|
||||||
|
|
||||||
public ResultCmdReceiver getReceiver() {
|
/**
|
||||||
|
* Récupérer le destinataire
|
||||||
|
*
|
||||||
|
* @return Receiver
|
||||||
|
*/
|
||||||
|
public final ResultCmdReceiver getReceiver() {
|
||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +73,7 @@ public abstract class ProtocolReader {
|
|||||||
*
|
*
|
||||||
* @return Commande
|
* @return Commande
|
||||||
*/
|
*/
|
||||||
public ProtocolWriter.ProtocolResult getResultCommand() {
|
public final ProtocolWriter.ProtocolResult getResultCommand() {
|
||||||
return this.resultCommand;
|
return this.resultCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,11 +83,12 @@ public abstract class ProtocolReader {
|
|||||||
* @param resultCommand Commande à envoyer
|
* @param resultCommand Commande à envoyer
|
||||||
* @param receiver Le receveur de cette commande
|
* @param receiver Le receveur de cette commande
|
||||||
*/
|
*/
|
||||||
public void setResultCommand(ProtocolWriter.ProtocolResult resultCommand, ResultCmdReceiver receiver) {
|
public final void setResultCommand(ProtocolWriter.ProtocolResult resultCommand, ResultCmdReceiver receiver) {
|
||||||
this.resultCommand = resultCommand;
|
this.resultCommand = resultCommand;
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de lire un fichier. Cad reçevoir le contenu d'un fichier provenant du réseau.
|
* Permet de lire un fichier. Cad reçevoir le contenu d'un fichier provenant du réseau.
|
||||||
* Redéfinissez cette méthode pour l'utiliser
|
* Redéfinissez cette méthode pour l'utiliser
|
||||||
@ -87,12 +100,35 @@ public abstract class ProtocolReader {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer le context courant
|
* Permet de récupérer le context courant
|
||||||
|
*
|
||||||
* @return Context courant
|
* @return Context courant
|
||||||
*/
|
*/
|
||||||
protected Context getContext() {
|
protected final Context getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette méthode est appelée lorsque la commande à exécuter ne peut pas être exécutée
|
||||||
|
*/
|
||||||
|
public final String onNotExecutable(Context context) {
|
||||||
|
ProtocolResult cmdResult = onError(context);
|
||||||
|
return cmdResult == null ? null : cmdResult.getResultCommand().getCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur du domaine demandé pour l'exécution de cette commande (NULL si aucun domaine spécifique demandé)
|
||||||
|
*/
|
||||||
|
public String getRequestDomain() {
|
||||||
|
return requestDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutateur du domaine demandé pour l'exécution de cette commande (NULL si aucun domaine spécifique demandé)
|
||||||
|
*/
|
||||||
|
public void setRequestDomain(String requestDomain) {
|
||||||
|
this.requestDomain = requestDomain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,19 +159,18 @@ public abstract class ProtocolReader {
|
|||||||
private String extractName(String data) {
|
private String extractName(String data) {
|
||||||
String name;
|
String name;
|
||||||
int endIndex = data.indexOf(' ');
|
int endIndex = data.indexOf(' ');
|
||||||
if (endIndex > 0) {
|
if (endIndex <= 0) {
|
||||||
name = data.substring(0, endIndex);
|
|
||||||
} else {
|
|
||||||
endIndex = data.indexOf('\r');
|
endIndex = data.indexOf('\r');
|
||||||
name = data.substring(0, endIndex);
|
|
||||||
}
|
}
|
||||||
|
name = data.substring(0, endIndex);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cette méthode est appelée lors de l'exécution de la règle
|
* Cette méthode est appelée lors de l'exécution de la règle
|
||||||
*
|
*
|
||||||
* @param data Paramètres pour créer la commande.
|
* @param context Utilisateur context.
|
||||||
|
* @param data Paramètres pour créer la commande.
|
||||||
*/
|
*/
|
||||||
protected abstract <T extends ProtocolResult> T onExecuted(Context context, String... data);
|
protected abstract <T extends ProtocolResult> T onExecuted(Context context, String... data);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package lightcontainer.protocol;
|
|||||||
|
|
||||||
import lightcontainer.domains.client.Context;
|
import lightcontainer.domains.client.Context;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -22,6 +23,7 @@ public abstract class ProtocolWriter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de récupérer le nom de la commande.
|
* Permet de récupérer le nom de la commande.
|
||||||
|
*
|
||||||
* @return Nom de la commande.
|
* @return Nom de la commande.
|
||||||
*/
|
*/
|
||||||
public final String getCmdName() {
|
public final String getCmdName() {
|
||||||
@ -49,21 +51,26 @@ public abstract class ProtocolWriter {
|
|||||||
/**
|
/**
|
||||||
* Permet d'écrire un fichier sur le réseau. Cad envoyer le contenu d'un fichier sur le réseau.
|
* Permet d'écrire un fichier sur le réseau. Cad envoyer le contenu d'un fichier sur le réseau.
|
||||||
* Redéfinissez cette méthode pour l'utiliser.
|
* Redéfinissez cette méthode pour l'utiliser.
|
||||||
|
*
|
||||||
* @param writer Buffer à remplir qui sera envoyer via le réseau
|
* @param writer Buffer à remplir qui sera envoyer via le réseau
|
||||||
*/
|
*/
|
||||||
public void write(OutputStream writer) {}
|
public void write(OutputStream writer) throws IOException {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accesseur au contexte courant sur lequel opère la commande
|
* Accesseur au contexte courant sur lequel opère la commande
|
||||||
|
*
|
||||||
* @return Context
|
* @return Context
|
||||||
*/
|
*/
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permet de contruire une commande selon une règle établie.
|
* Permet de contruire une commande selon une règle établie.
|
||||||
|
*
|
||||||
* @param data Les données à ajouter dans la commande; L'ordre défini leur position dans la commande
|
* @param data Les données à ajouter dans la commande; L'ordre défini leur position dans la commande
|
||||||
* @return La commande construites
|
* @return La commande construites
|
||||||
*/
|
*/
|
||||||
@ -72,11 +79,11 @@ public abstract class ProtocolWriter {
|
|||||||
StringBuilder builder = new StringBuilder(this.cmdName);
|
StringBuilder builder = new StringBuilder(this.cmdName);
|
||||||
|
|
||||||
for (String param : data)
|
for (String param : data)
|
||||||
builder.append(" " + param);
|
builder.append(" ").append(param);
|
||||||
|
|
||||||
String command = builder + "\r\n";
|
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
|
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
|
||||||
System.out.println("Essaye : " + command);
|
|
||||||
if (ruleMatcher.matches()) {
|
if (ruleMatcher.matches()) {
|
||||||
ProtocolResult result = onExecuted(context, data);
|
ProtocolResult result = onExecuted(context, data);
|
||||||
result.setCommand(command);
|
result.setCommand(command);
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package lightcontainer.protocol;
|
||||||
|
|
||||||
|
public class StandardizedDefinitions {
|
||||||
|
|
||||||
|
//Parties de regex non-utilisées en dehors de cette classe.
|
||||||
|
private final static String DIGIT = "[\\x30-\\x39]";
|
||||||
|
private final static String VISIBLECHAR = "[\\x20-\\xFF]";
|
||||||
|
private final static String PASSCHAR = "[\\x22-\\xFF]";
|
||||||
|
private final static String BINARY = "[\\x00-\\xFF]";
|
||||||
|
private final static String LETTER = "[\\x41-\\x5A\\x61-\\x7A]";
|
||||||
|
private final static String DIGIT_LETTER = "[\\x30-\\x39\\x41-\\x5A\\x61-\\x7A]";
|
||||||
|
private final static String PORT = "(6553[\\x30-\\x35])|(655[\\x30-\\x32][\\x30-\\x39])|(65[\\x30-\\x34][\\x30-\\x32]{2})|(6[\\x30-\\x34][\\x30-\\x39]{3})|([\\x31-\\x35][\\x30-\\x39]{4})|([\\x30-\\x35]{0,5})|([\\x30-\\x39]{1,4})";
|
||||||
|
private final static String SIZE = DIGIT + "{1,10}";
|
||||||
|
private final static String LINE = "\\x0D\\x0A";
|
||||||
|
private final static String PASSWORD = PASSCHAR + "{5,50}";
|
||||||
|
private final static String BL = "\\x20";
|
||||||
|
private final static String FILENAME = PASSCHAR + "{1,20}";
|
||||||
|
private final static String DOMAIN = "[a-z-A-Z0-9.]{5,20}";
|
||||||
|
private final static String HASH_FILENAME = DIGIT_LETTER + "{50,200}";
|
||||||
|
private final static String HASH_FILECONTENT = DIGIT_LETTER + "{50,200}";
|
||||||
|
private final static String FILE_INFO = "(" + HASH_FILENAME + ")" + BL + "(" + SIZE + ")" + BL + "(" + HASH_FILECONTENT + ")";
|
||||||
|
private final static String LOGIN = DIGIT_LETTER + "{5,20}";
|
||||||
|
|
||||||
|
//Regex à utiliser dans les différents protocoles.
|
||||||
|
//SBE s'annonce à FFE.
|
||||||
|
public final static String SBE_HELLO = "^HELLO" + BL + "(" + DOMAIN + ")" + BL + "(" + PORT + ")" + LINE + "$";
|
||||||
|
|
||||||
|
//FFE demande à SBE une tâche. SBE répond à FFE.
|
||||||
|
public final static String FFE_SENDFILE = "^SENDFILE" + BL + FILE_INFO + LINE + "$";
|
||||||
|
public final static String SBE_SEND_RESULT_OK = "^SEND_OK" + LINE + "$";
|
||||||
|
public final static String SBE_SEND_RESULT_ERROR = "^SEND_ERROR" + LINE + "$";
|
||||||
|
public final static String FFE_ERASE_FILE = "^ERASEFILE" + BL + "(" + HASH_FILENAME + ")" + LINE + "$";
|
||||||
|
public final static String SBE_ERASE_RESULT_OK = "^ERASE_OK" + LINE + "$";
|
||||||
|
public final static String SBE_ERASE_RESULT_ERROR = "^ERASE_ERROR" + LINE + "$";
|
||||||
|
public final static String FFE_RETRIEVE_FILE = "^RETRIEVEFILE" + BL + "(" + HASH_FILENAME + ")" + LINE + "$";
|
||||||
|
public final static String SBE_RETRIEVE_RESULT_OK = "^RETRIEVE_OK" + BL + FILE_INFO + LINE + "$";
|
||||||
|
public final static String SBE_RETRIEVE_RESULT_ERROR = "^RETRIEVE_ERROR" + LINE + "$";
|
||||||
|
|
||||||
|
//Client demande à FFE une tâche. FFE répond à client.
|
||||||
|
public final static String CLIENT_SIGN_IN = "^SIGNIN" + BL + "(" + LOGIN + ")" + BL + "(" + PASSWORD + ")" + LINE + "$";
|
||||||
|
public final static String CLIENT_SIGN_UP = "^SIGNUP" + BL + "(" + LOGIN + ")" + BL + "(" + PASSWORD + ")" + LINE + "$";
|
||||||
|
public final static String FFE_SIGN_OK = "^SIGN_OK" + LINE + "$";
|
||||||
|
public final static String FFE_SIGN_ERROR = "^SIGN_ERROR" + LINE + "$";
|
||||||
|
public final static String CLIENT_FILE_LIST = "^FILELIST" + LINE + "$";
|
||||||
|
public final static String FFE_FILE_LIST_RESULT = "^FILES" + "( (" + PASSCHAR + "{1,20})!(" + DIGIT + "{1,10})){0,50}" + LINE + "$";
|
||||||
|
public final static String CLIENT_SAVE_FILE = "^SAVEFILE" + BL + "(" + FILENAME + ")" + BL + "(" + SIZE + ")" + LINE + "$";
|
||||||
|
public final static String FFE_SAVE_FILE_OK = "^SAVEFILE_OK" + LINE + "$";
|
||||||
|
public final static String FFE_SAVE_FILE_ERROR = "^SAVEFILE_ERROR" + LINE + "$";
|
||||||
|
public final static String CLIENT_GET_FILE = "^GETFILE" + BL + "(" + FILENAME + ")" + LINE + "$";
|
||||||
|
public final static String FFE_GET_FILE_RESULT_OK = "^GETFILE_OK" + BL + FILENAME + BL + SIZE + LINE + "$";
|
||||||
|
public final static String FFE_GET_FILE_RESULT_ERROR = "^GETFILE_ERROR" + LINE + "$";
|
||||||
|
public final static String CLIENT_REMOVE_FILE = "^REMOVEFILE" + BL + "(" + FILENAME + ")" + LINE + "$";
|
||||||
|
public final static String FFE_REMOVE_OK = "^REMOVEFILE_OK" + LINE + "$";
|
||||||
|
public final static String FFE_REMOVE_ERROR = "^REMOVEFILE_ERROR" + LINE + "$";
|
||||||
|
public final static String CLIENT_SIGN_OUT = "^SIGNOUT" + LINE + "$";
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package lightcontainer.protocol.rules.reader;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
import lightcontainer.protocol.rules.writer.RemoveFileErrorRule;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.SBE_ERASE_RESULT_ERROR;
|
||||||
|
|
||||||
|
public class EraseErrorRule extends ProtocolReader {
|
||||||
|
//"^ERASE_ERROR\r\n$"
|
||||||
|
private static final String PATTERN = SBE_ERASE_RESULT_ERROR;
|
||||||
|
|
||||||
|
private static final String NAME = "ERASE_ERROR";
|
||||||
|
|
||||||
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
|
|
||||||
|
public EraseErrorRule(ProtocolRepository protocolRep) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.protocolRep = protocolRep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProtocolResult onExecuted(Context context, String... data) {
|
||||||
|
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, RemoveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package lightcontainer.protocol.rules.reader;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
import lightcontainer.protocol.rules.writer.RemoveFileOkRule;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.SBE_ERASE_RESULT_OK;
|
||||||
|
|
||||||
|
public class EraseOkRule extends ProtocolReader {
|
||||||
|
|
||||||
|
private static final String PATTERN = SBE_ERASE_RESULT_OK;
|
||||||
|
|
||||||
|
private static final String NAME = "ERASE_OK";
|
||||||
|
|
||||||
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
|
public EraseOkRule(ProtocolRepository protocolRep) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.protocolRep = protocolRep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProtocolReader.ProtocolResult onExecuted(Context context, String... data) {
|
||||||
|
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
|
||||||
|
String deletedFileName = context.getDataString("fileName");
|
||||||
|
context.deleteFile(deletedFileName);
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, RemoveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -7,16 +7,18 @@ import lightcontainer.protocol.rules.writer.FilesRule;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.CLIENT_FILE_LIST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant de récupérer la liste des fichiers d'un utilisateur
|
* Règle permettant de récupérer la liste des fichiers d'un utilisateur
|
||||||
*/
|
*/
|
||||||
public class FilelistRule extends ProtocolReader {
|
public class FilelistRule extends ProtocolReader {
|
||||||
// Constants
|
// Constants
|
||||||
private static final String PATTERN = "^FILELIST\r\n$";
|
private static final String PATTERN = CLIENT_FILE_LIST;
|
||||||
|
|
||||||
private static final String NAME = "FILELIST";
|
private static final String NAME = "FILELIST";
|
||||||
|
|
||||||
private ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public FilelistRule(ProtocolRepository protocolRep) {
|
public FilelistRule(ProtocolRepository protocolRep) {
|
||||||
@ -47,7 +49,7 @@ public class FilelistRule extends ProtocolReader {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override//TODO ???
|
||||||
protected <T extends ProtocolResult> T onError(Context context) {
|
protected <T extends ProtocolResult> T onError(Context context) {
|
||||||
return super.onError(context);
|
return super.onError(context);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
package lightcontainer.protocol.rules.reader;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
import lightcontainer.protocol.rules.writer.GetFileErrorRule;
|
||||||
|
import lightcontainer.protocol.rules.writer.RetrieveFileRule;
|
||||||
|
import lightcontainer.storage.ReadOnlyFile;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.CLIENT_GET_FILE;
|
||||||
|
|
||||||
|
public class GetFileRule extends ProtocolReader {
|
||||||
|
// Constants
|
||||||
|
//"^GETFILE ([^ !]{1,20})\r\n$"
|
||||||
|
private static final String PATTERN = CLIENT_GET_FILE;
|
||||||
|
private static final String NAME = "GETFILE";
|
||||||
|
// -- arguments
|
||||||
|
private static final int FILE_NAME = 0; // Index file name.
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public GetFileRule(ProtocolRepository protocolRep) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.protocolRep = protocolRep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rule Result
|
||||||
|
*/
|
||||||
|
public class Result extends ProtocolResult {
|
||||||
|
// Variables
|
||||||
|
private final String fileName;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public Result(Context context, String fileName) {
|
||||||
|
super(context);
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette méthode est appelée lors de l'exécution de la règle
|
||||||
|
*
|
||||||
|
* @param context Utilisateur context.
|
||||||
|
* @param data Paramètres pour créer la commande.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected GetFileRule.Result onExecuted(Context context, String... data) {
|
||||||
|
GetFileRule.Result result = new GetFileRule.Result(context, data[FILE_NAME]);
|
||||||
|
|
||||||
|
ReadOnlyFile file = context.getFile(data[FILE_NAME]);
|
||||||
|
|
||||||
|
if (file != null) {
|
||||||
|
// Précision du store back end demandé pour traiter cette commande.
|
||||||
|
String requestDomain = extractRequestDomain(file.getStorageIterator());
|
||||||
|
result.setRequestDomain(requestDomain);
|
||||||
|
|
||||||
|
// Save into bundle
|
||||||
|
context.putDataString("fileName", file.getName());
|
||||||
|
context.putDataLong("fileSize", file.getSize());
|
||||||
|
context.putDataString("fileIV", file.getIv());
|
||||||
|
|
||||||
|
// Create cmd for storebacked
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, RetrieveFileRule.NAME, context.getHashedFileName(file.getName())), ResultCmdReceiver.STOREBACKEND);
|
||||||
|
} else {
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, GetFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette méthode est appelée lors d'une erreur de la règle
|
||||||
|
*/
|
||||||
|
protected ProtocolReader.ProtocolResult onError(Context context) {
|
||||||
|
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
|
||||||
|
// Make getFileErrorRule
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, GetFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TMP
|
||||||
|
* TODO : But futur est de pouvoir en avoir plusieurs (sbe)
|
||||||
|
* Cette méthode permet de choisir le domaine voulu.
|
||||||
|
*
|
||||||
|
* @param storageIterator Les domaines
|
||||||
|
* @return Le domain choisi
|
||||||
|
*/
|
||||||
|
private String extractRequestDomain(Iterator<String> storageIterator) {
|
||||||
|
return storageIterator.next();
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,16 @@ package lightcontainer.protocol.rules.reader;
|
|||||||
import lightcontainer.domains.client.Context;
|
import lightcontainer.domains.client.Context;
|
||||||
import lightcontainer.protocol.ProtocolReader;
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.SBE_HELLO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant d'être alerter de l'annoncement d'un SBE
|
* Règle permettant d'être alerter de l'annoncement d'un SBE
|
||||||
*/
|
*/
|
||||||
public class HelloRule extends ProtocolReader {
|
public class HelloRule extends ProtocolReader {
|
||||||
|
//"^HELLO ([A-Za-z0-9.]{5,20}) ([\\d]{0,5})\r\n$"
|
||||||
|
private static final String PATTERN = SBE_HELLO;
|
||||||
|
|
||||||
private static final String PATTERN = "^HELLO ([A-Za-z0-9]{5,20}) ([0-9]{1,5})\r\n$";
|
private static final String NAME = "HELLO";
|
||||||
|
|
||||||
private static final String NAME = "HELLO";
|
|
||||||
|
|
||||||
// Index du domain dans le tableau de donnée
|
// Index du domain dans le tableau de donnée
|
||||||
private static final int DOMAIN = 0;
|
private static final int DOMAIN = 0;
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
package lightcontainer.protocol.rules.reader;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
import lightcontainer.protocol.rules.writer.EraseFileRule;
|
||||||
|
import lightcontainer.protocol.rules.writer.RemoveFileErrorRule;
|
||||||
|
import lightcontainer.storage.ReadOnlyFile;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.CLIENT_REMOVE_FILE;
|
||||||
|
|
||||||
|
public class RemoveFileRule extends ProtocolReader {
|
||||||
|
//"^REMOVEFILE ([^ !]{1,20})\r\n$"
|
||||||
|
private static final String PATTERN = CLIENT_REMOVE_FILE;
|
||||||
|
|
||||||
|
private static final String NAME = "REMOVEFILE";
|
||||||
|
|
||||||
|
private static final int FILENAME = 0;
|
||||||
|
|
||||||
|
|
||||||
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
|
public RemoveFileRule(ProtocolRepository protocolRep) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.protocolRep = protocolRep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Result extends ProtocolResult {
|
||||||
|
private final String fileName;
|
||||||
|
|
||||||
|
public Result(Context context, String fileName) {
|
||||||
|
super(context);
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RemoveFileRule.Result onExecuted(Context context, String... data) {
|
||||||
|
RemoveFileRule.Result result = new RemoveFileRule.Result(context, data[FILENAME]);
|
||||||
|
ReadOnlyFile file = context.getFile(result.getFileName());
|
||||||
|
|
||||||
|
if (file != null) {
|
||||||
|
String extendedFileName = context.getHashedFileName(result.getFileName());
|
||||||
|
context.putDataString("fileName", result.getFileName());
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, EraseFileRule.NAME, extendedFileName), ResultCmdReceiver.STOREBACKEND);
|
||||||
|
|
||||||
|
// Précision du store back end demandé pour traiter cette commande.
|
||||||
|
String requestDomain = extractRequestDomain(file.getStorageIterator());
|
||||||
|
result.setRequestDomain(requestDomain);
|
||||||
|
} else {
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, RemoveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProtocolReader.ProtocolResult onError(Context context) {
|
||||||
|
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, RemoveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : But futur est de pouvoir en avoir plusieurs
|
||||||
|
* Cette méthode permet de choisir le domaine voulu.
|
||||||
|
*
|
||||||
|
* @param storageIterator Les domaines
|
||||||
|
* @return Le domain choisi
|
||||||
|
*/
|
||||||
|
private String extractRequestDomain(Iterator<String> storageIterator) {
|
||||||
|
return storageIterator.next();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package lightcontainer.protocol.rules.reader;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
import lightcontainer.protocol.rules.writer.GetFileErrorRule;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.SBE_RETRIEVE_RESULT_ERROR;
|
||||||
|
|
||||||
|
public class RetrieveErrorRule extends ProtocolReader {
|
||||||
|
// Constants
|
||||||
|
//"^RETRIEVE_ERROR\r\n$"
|
||||||
|
private static final String PATTERN = SBE_RETRIEVE_RESULT_ERROR;
|
||||||
|
private static final String NAME = "RETRIEVE_ERROR";
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public RetrieveErrorRule(ProtocolRepository protocolRep) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.protocolRep = protocolRep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette méthode est appelée lors de l'exécution de la règle
|
||||||
|
*
|
||||||
|
* @param context Utilisateur context.
|
||||||
|
* @param data Paramètres pour créer la commande.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected ProtocolReader.ProtocolResult onExecuted(Context context, String... data) {
|
||||||
|
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, GetFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package lightcontainer.protocol.rules.reader;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
import lightcontainer.protocol.rules.writer.GetFileErrorRule;
|
||||||
|
import lightcontainer.protocol.rules.writer.GetFileOkRule;
|
||||||
|
import lightcontainer.utils.FileReceiver;
|
||||||
|
import lightcontainer.utils.SHA;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.SBE_RETRIEVE_RESULT_OK;
|
||||||
|
|
||||||
|
public class RetrieveOkRule extends ProtocolReader {
|
||||||
|
// Constants
|
||||||
|
//"^RETRIEVE_OK ([A-Za-z0-9.]{50,200}) ([0-9]{1,10}) ([A-Za-z0-9.]{50,200})\r\n$"
|
||||||
|
private static final String PATTERN = SBE_RETRIEVE_RESULT_OK;
|
||||||
|
private static final String NAME = "RETRIEVE_OK";
|
||||||
|
// -- arguments
|
||||||
|
private static final int HASHED_FILE_NAME = 0; // Index hashed filename
|
||||||
|
private static final int FILE_SIZE = 1; // Index file size
|
||||||
|
private static final int HASHED_FILE_CONTENT = 2; // Index hashed file content
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
private final ProtocolRepository protocolRep;
|
||||||
|
private final String storagePath;
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
public RetrieveOkRule(ProtocolRepository protocolRep, String storagePath) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.protocolRep = protocolRep;
|
||||||
|
this.storagePath = storagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Result extends ProtocolResult {
|
||||||
|
// Variables
|
||||||
|
private final String filename;
|
||||||
|
private final long filesize;
|
||||||
|
private final String hashedFileContent;
|
||||||
|
|
||||||
|
public Result(Context context, String filename, long filesize, String hashedFileContent) {
|
||||||
|
super(context);
|
||||||
|
this.filename = filename;
|
||||||
|
this.filesize = filesize;
|
||||||
|
this.hashedFileContent = hashedFileContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilename() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFilesize() {
|
||||||
|
return filesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param reader Buffer rempli du fichier
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void read(InputStream reader) {
|
||||||
|
super.read(reader);
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileReceiver fileReceiver = new FileReceiver(storagePath);
|
||||||
|
if (!fileReceiver.receiveFile(reader, this.filename, this.filesize)) {
|
||||||
|
throw new IllegalStateException("Bad file reception");
|
||||||
|
}
|
||||||
|
if (!SHA.hashFile(storagePath, this.filename).equals(this.hashedFileContent)) {
|
||||||
|
throw new IllegalStateException("File hash content are not equals");
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException|SHA.ShaException e) {
|
||||||
|
this.setResultCommand(protocolRep.executeWriter(getContext(), GetFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette méthode est appelée lors de l'exécution de la règle
|
||||||
|
*
|
||||||
|
* @param context Utilisateur context.
|
||||||
|
* @param data Paramètres pour créer la commande.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected RetrieveOkRule.Result onExecuted(Context context, String... data) {
|
||||||
|
RetrieveOkRule.Result result = new RetrieveOkRule.Result(context, data[HASHED_FILE_NAME], Integer.parseInt(data[FILE_SIZE]), data[HASHED_FILE_CONTENT]);
|
||||||
|
|
||||||
|
// save encrypted file size into bundle
|
||||||
|
context.putDataLong("encryptedFileSize", result.getFilesize()); // TODO to long ?!
|
||||||
|
context.putDataString("hashedFileName", result.getFilename());
|
||||||
|
|
||||||
|
// Set result command
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, GetFileOkRule.NAME, context.getDataString("fileName"), String.valueOf(context.getDataLong("fileSize"))), ResultCmdReceiver.CLIENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProtocolReader.ProtocolResult onError(Context context) {
|
||||||
|
ProtocolResult result = new ProtocolResult(context);
|
||||||
|
result.setResultCommand(protocolRep.executeWriter(context, GetFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -4,17 +4,16 @@ import lightcontainer.domains.client.Context;
|
|||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
import lightcontainer.protocol.ProtocolReader;
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
|
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
|
||||||
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
|
|
||||||
import lightcontainer.protocol.rules.writer.SendfileRule;
|
import lightcontainer.protocol.rules.writer.SendfileRule;
|
||||||
import lightcontainer.utils.AES_GCM;
|
import lightcontainer.utils.AES_GCM;
|
||||||
import lightcontainer.utils.FileReceiver;
|
import lightcontainer.utils.FileReceiver;
|
||||||
import lightcontainer.utils.SHA;
|
import lightcontainer.utils.SHA;
|
||||||
import lightcontainer.utils.ShaHasher;
|
import lightcontainer.utils.ShaHasher;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.CLIENT_SAVE_FILE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant de sauvegarder un fichier sur le SBE.
|
* Règle permettant de sauvegarder un fichier sur le SBE.
|
||||||
@ -22,15 +21,16 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
*/
|
*/
|
||||||
public class SavefileRule extends ProtocolReader {
|
public class SavefileRule extends ProtocolReader {
|
||||||
// Constants
|
// Constants
|
||||||
private static final String PATTERN = "^SAVEFILE ([^ !]{1,20}) ([0-9]{1,10})\r\n$";
|
//"^SAVEFILE ([^ !]{1,20}) ([0-9]{1,10})\r\n$"
|
||||||
|
private static final String PATTERN = CLIENT_SAVE_FILE;
|
||||||
|
|
||||||
private static final String NAME = "SAVEFILE";
|
private static final String NAME = "SAVEFILE";
|
||||||
|
|
||||||
private static final int FILE_NAME = 0; // Index file name.
|
private static final int FILE_NAME = 0; // Index file name.
|
||||||
private static final int FILE_SIZE = 1; // Index file size.
|
private static final int FILE_SIZE = 1; // Index file size.
|
||||||
|
|
||||||
private ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
private String storagePath;
|
private final String storagePath;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public SavefileRule(ProtocolRepository protocolRep, String storagePath) {
|
public SavefileRule(ProtocolRepository protocolRep, String storagePath) {
|
||||||
@ -42,10 +42,10 @@ public class SavefileRule extends ProtocolReader {
|
|||||||
public class Result extends ProtocolResult {
|
public class Result extends ProtocolResult {
|
||||||
// Variables
|
// Variables
|
||||||
private String filename;
|
private String filename;
|
||||||
private int size;
|
private final long size;
|
||||||
|
|
||||||
// Construct
|
// Construct
|
||||||
public Result(Context context, String filename, int size) {
|
public Result(Context context, String filename, long size) {
|
||||||
super(context);
|
super(context);
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
@ -54,7 +54,6 @@ public class SavefileRule extends ProtocolReader {
|
|||||||
@Override
|
@Override
|
||||||
public void read(InputStream reader) {
|
public void read(InputStream reader) {
|
||||||
super.read(reader);
|
super.read(reader);
|
||||||
System.out.printf("Sauvegarde du fichier : %s %d\n", filename, size);
|
|
||||||
|
|
||||||
if (getContext().canAddFile()) {
|
if (getContext().canAddFile()) {
|
||||||
try {
|
try {
|
||||||
@ -73,20 +72,19 @@ public class SavefileRule extends ProtocolReader {
|
|||||||
String iv = AES_GCM.generateIV();
|
String iv = AES_GCM.generateIV();
|
||||||
|
|
||||||
// retrieve file and new size
|
// retrieve file and new size
|
||||||
int encryptedFileSize = fileReceiver.receiveFile(reader, this.filename, this.size, key, iv);
|
long encryptedFileSize = fileReceiver.receiveFile(reader, this.filename, this.size, key, iv);
|
||||||
if (encryptedFileSize < 0) throw new IOException();
|
if (encryptedFileSize < 0) throw new IOException();
|
||||||
|
|
||||||
String fileHash = SHA.hashFile(storagePath, this.filename);
|
String fileHash = SHA.hashFile(storagePath, this.filename);
|
||||||
|
|
||||||
// On met les données de la requête actuelle
|
// On met les données de la requête actuelle
|
||||||
getContext().putDataInt("size", size);
|
getContext().putDataLong("size", size);
|
||||||
getContext().putDataString("iv", iv);
|
getContext().putDataString("iv", iv);
|
||||||
getContext().putDataString("fileNameSalt", fileNameSalt);
|
getContext().putDataString("fileNameSalt", fileNameSalt);
|
||||||
|
|
||||||
this.setResultCommand(protocolRep.executeWriter(getContext(), SendfileRule.NAME, this.filename, String.valueOf(encryptedFileSize), fileHash), ResultCmdReceiver.STOREBACKEND);
|
this.setResultCommand(protocolRep.executeWriter(getContext(), SendfileRule.NAME, this.filename, String.valueOf(encryptedFileSize), fileHash), ResultCmdReceiver.STOREBACKEND);
|
||||||
} catch (IOException | SHA.ShaException e) {
|
} catch (IOException | SHA.ShaException e) {
|
||||||
this.setResultCommand(protocolRep.executeWriter(getContext(), SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
this.setResultCommand(protocolRep.executeWriter(getContext(), SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setResultCommand(protocolRep.executeWriter(getContext(), SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
this.setResultCommand(protocolRep.executeWriter(getContext(), SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
@ -102,6 +100,8 @@ public class SavefileRule extends ProtocolReader {
|
|||||||
@Override
|
@Override
|
||||||
protected SavefileRule.Result onExecuted(Context context, String... data) {
|
protected SavefileRule.Result onExecuted(Context context, String... data) {
|
||||||
SavefileRule.Result result = new SavefileRule.Result(context, data[FILE_NAME], Integer.parseInt(data[FILE_SIZE]));
|
SavefileRule.Result result = new SavefileRule.Result(context, data[FILE_NAME], Integer.parseInt(data[FILE_SIZE]));
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,20 +4,20 @@ import lightcontainer.domains.client.Context;
|
|||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
import lightcontainer.protocol.ProtocolReader;
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
|
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
|
||||||
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.SBE_SEND_RESULT_ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant de de confirmer la sauvegrade d'un fichier.
|
* Règle permettant de de confirmer la sauvegrade d'un fichier.
|
||||||
*/
|
*/
|
||||||
public class SendErrorRule extends ProtocolReader {
|
public class SendErrorRule extends ProtocolReader {
|
||||||
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
private static final String PATTERN = "^SEND_ERROR\r\n$";
|
//"^SEND_ERROR\r\n$"
|
||||||
|
private static final String PATTERN = SBE_SEND_RESULT_ERROR;
|
||||||
|
|
||||||
private static final String NAME = "SEND_ERROR";
|
private static final String NAME = "SENDERROR";
|
||||||
|
|
||||||
private ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public SendErrorRule(ProtocolRepository protocolRep) {
|
public SendErrorRule(ProtocolRepository protocolRep) {
|
||||||
@ -25,7 +25,6 @@ public class SendErrorRule extends ProtocolReader {
|
|||||||
this.protocolRep = protocolRep;
|
this.protocolRep = protocolRep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ProtocolResult onExecuted(Context context, String... data) {
|
protected ProtocolResult onExecuted(Context context, String... data) {
|
||||||
ProtocolResult result = new ProtocolResult(context);
|
ProtocolResult result = new ProtocolResult(context);
|
||||||
|
@ -5,17 +5,20 @@ import lightcontainer.interfaces.ProtocolRepository;
|
|||||||
import lightcontainer.protocol.ProtocolReader;
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
|
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.SBE_SEND_RESULT_OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant de de confirmer la sauvegrade d'un fichier.
|
* Règle permettant de de confirmer la sauvegrade d'un fichier.
|
||||||
*/
|
*/
|
||||||
public class SendOkRule extends ProtocolReader {
|
public class SendOkRule extends ProtocolReader {
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
private static final String PATTERN = "^SEND_OK\r\n$";
|
//"^SEND_OK\r\n$"
|
||||||
|
private static final String PATTERN = SBE_SEND_RESULT_OK;
|
||||||
|
|
||||||
private static final String NAME = "SEND_OK";
|
private static final String NAME = "SEND_OK";
|
||||||
|
|
||||||
private ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public SendOkRule(ProtocolRepository protocolRep) {
|
public SendOkRule(ProtocolRepository protocolRep) {
|
||||||
@ -23,16 +26,10 @@ public class SendOkRule extends ProtocolReader {
|
|||||||
this.protocolRep = protocolRep;
|
this.protocolRep = protocolRep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ProtocolReader.ProtocolResult onExecuted(Context context, String... data) {
|
protected ProtocolResult onExecuted(Context context, String... data) {
|
||||||
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
|
ProtocolReader.ProtocolResult result = new ProtocolReader.ProtocolResult(context);
|
||||||
result.setResultCommand(protocolRep.executeWriter(context, SaveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
|
result.setResultCommand(protocolRep.executeWriter(context, SaveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
|
||||||
|
|
||||||
// Sauvegarder dans JSON
|
|
||||||
System.out.println("Save en json du fichier");
|
|
||||||
context.addFile(context.getDataString("fileName"), context.getDataString("fileNameSalt"), context.getDataInt("size"), context.getDataString("iv"), context.getDomain());
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,22 @@ import lightcontainer.protocol.ProtocolReader;
|
|||||||
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
||||||
import lightcontainer.protocol.rules.writer.SignOkRule;
|
import lightcontainer.protocol.rules.writer.SignOkRule;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.CLIENT_SIGN_IN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant de gérer la connection d'un utilisateur
|
* Règle permettant de gérer la connection d'un utilisateur
|
||||||
*/
|
*/
|
||||||
public class SigninRule extends ProtocolReader {
|
public class SigninRule extends ProtocolReader {
|
||||||
// Constants
|
// Constants
|
||||||
private static final String PATTERN = "^SIGNIN ([A-Za-z0-9]{5,20}) ([^ !]{5,50})\r\n$";
|
//"^SIGNIN ([A-Za-z0-9]{5,20}) ([^ !]{5,50})\r\n$"
|
||||||
|
private static final String PATTERN = CLIENT_SIGN_IN;
|
||||||
|
|
||||||
private static final String NAME = "SIGNIN";
|
private static final String NAME = "SIGNIN";
|
||||||
|
|
||||||
private static final int LOGIN = 0; // Index du domain dans le tableau de données
|
private static final int LOGIN = 0; // Index du domain dans le tableau de données
|
||||||
private static final int PASSWORD = 1; // Index du port dans le tableau de données
|
private static final int PASSWORD = 1; // Index du port dans le tableau de données
|
||||||
|
|
||||||
private ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public SigninRule(ProtocolRepository protocolRep) {
|
public SigninRule(ProtocolRepository protocolRep) {
|
||||||
|
@ -3,12 +3,14 @@ package lightcontainer.protocol.rules.reader;
|
|||||||
import lightcontainer.domains.client.Context;
|
import lightcontainer.domains.client.Context;
|
||||||
import lightcontainer.protocol.ProtocolReader;
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.CLIENT_SIGN_OUT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle demandant la déconnexion du client
|
* Règle demandant la déconnexion du client
|
||||||
*/
|
*/
|
||||||
public class SignoutRule extends ProtocolReader {
|
public class SignoutRule extends ProtocolReader {
|
||||||
|
//"^SIGNOUT\r\n$"
|
||||||
private static final String PATTERN = "^SIGNOUT\r\n$";
|
private static final String PATTERN = CLIENT_SIGN_OUT;
|
||||||
|
|
||||||
public static final String NAME = "SIGNOUT";
|
public static final String NAME = "SIGNOUT";
|
||||||
|
|
||||||
|
@ -6,17 +6,20 @@ import lightcontainer.protocol.ProtocolReader;
|
|||||||
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
||||||
import lightcontainer.protocol.rules.writer.SignOkRule;
|
import lightcontainer.protocol.rules.writer.SignOkRule;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.CLIENT_SIGN_UP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant de gérer la création d'un utilisateur
|
* Règle permettant de gérer la création d'un utilisateur
|
||||||
*/
|
*/
|
||||||
public class SignupRule extends ProtocolReader {
|
public class SignupRule extends ProtocolReader {
|
||||||
// Constants
|
// Constants
|
||||||
private static final String PATTERN = "^SIGNUP ([A-Za-z0-9]{5,20}) ([^ !]{5,50})\r\n$";
|
//"^SIGNUP ([A-Za-z0-9]{5,20}) ([^ !]{5,50})\r\n$"
|
||||||
|
private static final String PATTERN = CLIENT_SIGN_UP;
|
||||||
private static final String NAME = "SIGNUP";
|
private static final String NAME = "SIGNUP";
|
||||||
private static final int LOGIN = 0;
|
private static final int LOGIN = 0;
|
||||||
private static final int PASSWORD = 1;
|
private static final int PASSWORD = 1;
|
||||||
|
|
||||||
private ProtocolRepository protocolRep;
|
private final ProtocolRepository protocolRep;
|
||||||
|
|
||||||
public SignupRule(ProtocolRepository protocolRep) {
|
public SignupRule(ProtocolRepository protocolRep) {
|
||||||
super(NAME, PATTERN);
|
super(NAME, PATTERN);
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_ERASE_FILE;
|
||||||
|
|
||||||
|
public class EraseFileRule extends ProtocolWriter {
|
||||||
|
|
||||||
|
//"^ERASEFILE ([A-Za-z0-9.]{50,200})\r\n$"
|
||||||
|
private static final String PATTERN = FFE_ERASE_FILE;
|
||||||
|
|
||||||
|
public static String NAME = "ERASEFILE";
|
||||||
|
|
||||||
|
|
||||||
|
public EraseFileRule() {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
}
|
||||||
|
}
|
@ -2,12 +2,14 @@ package lightcontainer.protocol.rules.writer;
|
|||||||
|
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_FILE_LIST_RESULT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle permettant de construire une commande contenant la liste des fichiers d'un utilisateur
|
* Règle permettant de construire une commande contenant la liste des fichiers d'un utilisateur
|
||||||
*/
|
*/
|
||||||
public class FilesRule extends ProtocolWriter {
|
public class FilesRule extends ProtocolWriter {
|
||||||
|
//"^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$";
|
private static final String PATTERN = FFE_FILE_LIST_RESULT;
|
||||||
|
|
||||||
public static final String NAME = "FILES";
|
public static final String NAME = "FILES";
|
||||||
|
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
import lightcontainer.utils.DeepFileEraser;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_GET_FILE_RESULT_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Règle utilisé dans le cas ou une erreur survient lors
|
||||||
|
* de la demande de récupération d'un fichier.
|
||||||
|
*/
|
||||||
|
public class GetFileErrorRule extends ProtocolWriter {
|
||||||
|
// Constants
|
||||||
|
//"^GETFILE_ERROR\r\n$"
|
||||||
|
private static final String PATTERN = FFE_GET_FILE_RESULT_ERROR;
|
||||||
|
public static final String NAME = "GETFILE_ERROR";
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
private final String storagePath;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
public GetFileErrorRule(String storagePath) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.storagePath = storagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProtocolResult onExecuted(Context context, String... data) {
|
||||||
|
// Delete the file
|
||||||
|
try {
|
||||||
|
DeepFileEraser.eraseFile(String.format("%s/%s", storagePath, context.getDataString("hashedFileName")));
|
||||||
|
} catch (DeepFileEraser.DeepFileEraserException ignore) { }
|
||||||
|
// Return new protocol result
|
||||||
|
return new ProtocolResult(context);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
import lightcontainer.utils.DeepFileEraser;
|
||||||
|
import lightcontainer.utils.FileSender;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_GET_FILE_RESULT_OK;
|
||||||
|
|
||||||
|
public class GetFileOkRule extends ProtocolWriter {
|
||||||
|
// Constants
|
||||||
|
//"^GETFILE_OK ([^ !]{1,20}) ([0-9]{1,10})\r\n$"
|
||||||
|
private static final String PATTERN = FFE_GET_FILE_RESULT_OK;
|
||||||
|
public static final String NAME = "GETFILE_OK";
|
||||||
|
// -- params
|
||||||
|
private static final int FILE_NAME = 0; // Index file name hashed
|
||||||
|
private static final int FILE_SIZE = 1; // Index file size
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
private final String storagePath;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
public GetFileOkRule(String storagePath) {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
this.storagePath = storagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Result extends ProtocolWriter.ProtocolResult {
|
||||||
|
// Variables
|
||||||
|
private final String filename;
|
||||||
|
private final long filesize;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
public Result(Context context, String filename, long filesize) {
|
||||||
|
super(context);
|
||||||
|
this.filename = filename;
|
||||||
|
this.filesize = filesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Oh yeahh baby by tonton EndMove ;-)
|
||||||
|
*
|
||||||
|
* @param writer Buffer à remplir qui sera envoyer via le réseau
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void write(OutputStream writer) throws IOException {
|
||||||
|
FileSender fileSender = new FileSender(storagePath);
|
||||||
|
fileSender.sendFile(
|
||||||
|
getContext().getDataString("hashedFileName"),
|
||||||
|
writer,
|
||||||
|
getContext().getDataLong("encryptedFileSize"), // Encrypted file size (because data is parsing into AES system)
|
||||||
|
getContext().getAesKey(),
|
||||||
|
getContext().getDataString("fileIV")
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
DeepFileEraser.eraseFile(String.format("%s/%s", storagePath, getContext().getDataString("hashedFileName")));
|
||||||
|
} catch (DeepFileEraser.DeepFileEraserException ignore) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GetFileOkRule.Result onExecuted(Context context, String... data) {
|
||||||
|
return new GetFileOkRule.Result(context, data[FILE_NAME], Integer.parseInt(data[FILE_SIZE]));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_REMOVE_ERROR;
|
||||||
|
|
||||||
|
public class RemoveFileErrorRule extends ProtocolWriter {
|
||||||
|
|
||||||
|
//"^REMOVEFILE_ERROR\r\n$"
|
||||||
|
private static final String PATTERN = FFE_REMOVE_ERROR;
|
||||||
|
|
||||||
|
public static String NAME = "REMOVEFILE_ERROR";
|
||||||
|
|
||||||
|
public RemoveFileErrorRule() {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_REMOVE_OK;
|
||||||
|
|
||||||
|
public class RemoveFileOkRule extends ProtocolWriter {
|
||||||
|
//"^REMOVEFILE_OK\r\n$"
|
||||||
|
private static final String PATTERN = FFE_REMOVE_OK;
|
||||||
|
public static String NAME = "REMOVEFILE_OK";
|
||||||
|
|
||||||
|
public RemoveFileOkRule() {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_RETRIEVE_FILE;
|
||||||
|
|
||||||
|
public class RetrieveFileRule extends ProtocolWriter {
|
||||||
|
// Constants
|
||||||
|
//"^RETRIEVEFILE ([A-Za-z0-9]{50,200})\r\n$"
|
||||||
|
private static final String PATTERN = FFE_RETRIEVE_FILE;
|
||||||
|
public static final String NAME = "RETRIEVEFILE";
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public RetrieveFileRule() {
|
||||||
|
super(NAME, PATTERN);
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,44 @@
|
|||||||
package lightcontainer.protocol.rules.writer;
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
import lightcontainer.utils.DeepFileEraser;
|
||||||
|
import lightcontainer.utils.ShaHasher;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_SAVE_FILE_ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle signifiant que la sauvegarde d'un fichier a échoué
|
* Règle signifiant que la sauvegarde d'un fichier a échoué
|
||||||
*/
|
*/
|
||||||
public class SaveFileErrorRule extends ProtocolWriter {
|
public class SaveFileErrorRule extends ProtocolWriter {
|
||||||
|
//"^SAVEFILE_ERROR\r\n$"
|
||||||
private static final String PATTERN = "^SAVEFILE_ERROR\r\n$";
|
private static final String PATTERN = FFE_SAVE_FILE_ERROR;
|
||||||
|
|
||||||
public static final String NAME = "SAVEFILE_ERROR";
|
public static final String NAME = "SAVEFILE_ERROR";
|
||||||
|
|
||||||
public SaveFileErrorRule() {
|
private final String storagePath;
|
||||||
|
|
||||||
|
public SaveFileErrorRule(String storagePath) {
|
||||||
super(NAME, PATTERN);
|
super(NAME, PATTERN);
|
||||||
|
this.storagePath = storagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProtocolResult onExecuted(Context context, String... data) {
|
||||||
|
ProtocolResult result = new ProtocolResult(context);
|
||||||
|
String fileName = context.getDataString("fileName");
|
||||||
|
String fileNameSalt = context.getDataString("fileNameSalt");
|
||||||
|
|
||||||
|
if (fileName != null && fileNameSalt != null) {
|
||||||
|
// Suppression du fichier temporaire dans le stockage du FFE
|
||||||
|
ShaHasher hasher = new ShaHasher(context.getLogin() + "_" + context.getDataString("fileName"));
|
||||||
|
try {
|
||||||
|
DeepFileEraser.eraseFile(String.format("%s/%s", this.storagePath,
|
||||||
|
hasher.fromSalt(hasher.saltToByte(context.getDataString("fileNameSalt")))));
|
||||||
|
} catch (DeepFileEraser.DeepFileEraserException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,40 @@
|
|||||||
package lightcontainer.protocol.rules.writer;
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
|
import lightcontainer.domains.client.Context;
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
import lightcontainer.utils.DeepFileEraser;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_SAVE_FILE_OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle signifiant que la sauvegarde d'un fichier fût un succès
|
* Règle signifiant que la sauvegarde d'un fichier fût un succès
|
||||||
*/
|
*/
|
||||||
public class SaveFileOkRule extends ProtocolWriter {
|
public class SaveFileOkRule extends ProtocolWriter {
|
||||||
|
//"^SAVEFILE_OK\r\n$"
|
||||||
private static final String PATTERN = "^SAVEFILE_OK\r\n$";
|
private static final String PATTERN = FFE_SAVE_FILE_OK;
|
||||||
|
|
||||||
public static final String NAME = "SAVEFILE_OK";
|
public static final String NAME = "SAVEFILE_OK";
|
||||||
|
|
||||||
public SaveFileOkRule() {
|
private final String storagePath;
|
||||||
|
|
||||||
|
public SaveFileOkRule(String storagePath) {
|
||||||
super(NAME, PATTERN);
|
super(NAME, PATTERN);
|
||||||
|
this.storagePath = storagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProtocolWriter.ProtocolResult onExecuted(Context context, String... data) {
|
||||||
|
ProtocolWriter.ProtocolResult result = new ProtocolWriter.ProtocolResult(context);
|
||||||
|
|
||||||
|
// Sauvegarder dans JSON
|
||||||
|
context.addFile(context.getDataString("fileName"), context.getDataString("fileNameSalt"), context.getDataLong("size"), context.getDataString("iv"), context.getDomain());
|
||||||
|
|
||||||
|
// Suppression du fichier temporaire dans le stockage du FFE
|
||||||
|
String hashedFileName = context.getHashedFileName(context.getDataString("fileName"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
DeepFileEraser.eraseFile(String.format("%s/%s", storagePath, hashedFileName));
|
||||||
|
} catch (DeepFileEraser.DeepFileEraserException ignore) { }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,17 @@ import lightcontainer.domains.client.Context;
|
|||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
import lightcontainer.utils.FileSender;
|
import lightcontainer.utils.FileSender;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_SENDFILE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle envoyée au SBE, demandant la sauvegarde d'un fichier.
|
* Règle envoyée au SBE, demandant la sauvegarde d'un fichier.
|
||||||
*/
|
*/
|
||||||
public class SendfileRule extends ProtocolWriter {
|
public class SendfileRule extends ProtocolWriter {
|
||||||
|
//"^SENDFILE [A-Za-z0-9]{50,200} [0-9]{1,10} [A-Za-z0-9]{50,200}\r\n$"
|
||||||
private static final String PATTERN = "^SENDFILE [A-Za-z0-9.]{0,200} [0-9]{1,10} [A-Za-z0-9.]{50,200}\r\n$";
|
private static final String PATTERN = FFE_SENDFILE;
|
||||||
|
|
||||||
public static final String NAME = "SENDFILE";
|
public static final String NAME = "SENDFILE";
|
||||||
|
|
||||||
@ -19,7 +22,7 @@ public class SendfileRule extends ProtocolWriter {
|
|||||||
private static final int FILE_SIZE = 1; // Index file size.
|
private static final int FILE_SIZE = 1; // Index file size.
|
||||||
private static final int HASHED_FILE_CONTENT = 2; // Index file content hashed.
|
private static final int HASHED_FILE_CONTENT = 2; // Index file content hashed.
|
||||||
|
|
||||||
private String storagePath;
|
private final String storagePath;
|
||||||
|
|
||||||
public SendfileRule(String storagePath) {
|
public SendfileRule(String storagePath) {
|
||||||
super(NAME, PATTERN);
|
super(NAME, PATTERN);
|
||||||
@ -29,10 +32,10 @@ public class SendfileRule extends ProtocolWriter {
|
|||||||
public class Result extends ProtocolWriter.ProtocolResult {
|
public class Result extends ProtocolWriter.ProtocolResult {
|
||||||
|
|
||||||
private final String hashedFileName;
|
private final String hashedFileName;
|
||||||
private final int fileSize;
|
private final long fileSize;
|
||||||
private final String hashedFileContent;
|
private final String hashedFileContent;
|
||||||
|
|
||||||
public Result(Context context, String hashedFileName, int fileSize, String hashedFileContent) {
|
public Result(Context context, String hashedFileName, long fileSize, String hashedFileContent) {
|
||||||
super(context);
|
super(context);
|
||||||
this.hashedFileName = hashedFileName;
|
this.hashedFileName = hashedFileName;
|
||||||
this.fileSize = fileSize;
|
this.fileSize = fileSize;
|
||||||
@ -40,19 +43,14 @@ public class SendfileRule extends ProtocolWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(OutputStream writer) {
|
public void write(OutputStream writer) throws IOException {
|
||||||
super.write(writer);
|
super.write(writer);
|
||||||
System.out.println("Envoie du fichier au SBE");
|
|
||||||
|
|
||||||
|
|
||||||
FileSender fileSender = new FileSender(storagePath);
|
FileSender fileSender = new FileSender(storagePath);
|
||||||
fileSender.sendFile(hashedFileName, writer);
|
fileSender.sendFile(hashedFileName, writer);
|
||||||
|
|
||||||
// TODO : Supprimer le fichier du FFE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SendfileRule.Result onExecuted(Context context, String... data) {
|
protected SendfileRule.Result onExecuted(Context context, String... data) {
|
||||||
return new SendfileRule.Result(context, data[HASHED_FILE_NAME], Integer.parseInt(data[FILE_SIZE]), data[HASHED_FILE_CONTENT]);
|
return new SendfileRule.Result(context, data[HASHED_FILE_NAME], Integer.parseInt(data[FILE_SIZE]), data[HASHED_FILE_CONTENT]);
|
||||||
|
@ -2,12 +2,14 @@ package lightcontainer.protocol.rules.writer;
|
|||||||
|
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_SIGN_ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle renvoyée au client lorsque l'authentification a échoué.
|
* Règle renvoyée au client lorsque l'authentification a échoué.
|
||||||
*/
|
*/
|
||||||
public class SignErrorRule extends ProtocolWriter {
|
public class SignErrorRule extends ProtocolWriter {
|
||||||
|
//"^SIGN_ERROR\r\n$"
|
||||||
private static final String PATTERN = "^SIGN_ERROR\r\n$";
|
private static final String PATTERN = FFE_SIGN_ERROR;
|
||||||
|
|
||||||
public static final String NAME = "SIGN_ERROR";
|
public static final String NAME = "SIGN_ERROR";
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@ package lightcontainer.protocol.rules.writer;
|
|||||||
|
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
import lightcontainer.protocol.ProtocolWriter;
|
||||||
|
|
||||||
|
import static lightcontainer.protocol.StandardizedDefinitions.FFE_SIGN_OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Règle renvoyée au client lorsque l'authentification a réusie.
|
* Règle renvoyée au client lorsque l'authentification a réusie.
|
||||||
*/
|
*/
|
||||||
public class SignOkRule extends ProtocolWriter {
|
public class SignOkRule extends ProtocolWriter {
|
||||||
|
//"^SIGN_OK\r\n$"
|
||||||
private static final String PATTERN = "^SIGN_OK\r\n$";
|
private static final String PATTERN = FFE_SIGN_OK;
|
||||||
|
|
||||||
public static final String NAME = "SIGN_OK";
|
public static final String NAME = "SIGN_OK";
|
||||||
|
|
||||||
|
@ -8,18 +8,18 @@ import lightcontainer.protocol.ProtocolWriter;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
// TODO : C'est genre un ClientHandlerManager quoi hein, normal qu'il fasse blinder de chose ;)
|
// TODO : C'est genre un ClientHandlerManager quoi hein, normal qu'il fasse blinder de chose ;)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClientHandlerRepository
|
* ClientHandlerRepository
|
||||||
*
|
* <p>
|
||||||
* Repository storing ClientHandler class.
|
* Repository storing ClientHandler class.
|
||||||
* Contains some utility functions.
|
* Contains some utility functions.
|
||||||
*
|
*
|
||||||
* @version 1.0
|
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
||||||
* @since 1.0
|
* @version 1.0
|
||||||
*
|
* @see ClientHandler
|
||||||
* @see ClientHandler
|
* @see AutoCloseable
|
||||||
* @see AutoCloseable
|
* @since 1.0
|
||||||
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
|
||||||
*/
|
*/
|
||||||
public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
|
public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
|
||||||
// Variable
|
// Variable
|
||||||
@ -34,9 +34,9 @@ public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
|
|||||||
/**
|
/**
|
||||||
* Setter, allow to define the ServerListener of a repository.
|
* Setter, allow to define the ServerListener of a repository.
|
||||||
* & Start the server.
|
* & Start the server.
|
||||||
* @param server ServerListener to set as default.
|
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @param server ServerListener to set as default.
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setServerListener(UnicastServerListener server) {
|
public void setServerListener(UnicastServerListener server) {
|
||||||
@ -46,15 +46,31 @@ public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a ClientHandler.
|
* Add a ClientHandler.
|
||||||
* @param client Client Handler to add.
|
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @param client Client Handler to add.
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addClient(ClientHandler client) {
|
public void addClient(ClientHandler client) {
|
||||||
this.handlers.add(client);
|
this.handlers.add(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de savoir si un client est déjà connecté avec ce login.
|
||||||
|
*
|
||||||
|
* @param login Login du client.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean hasClient(String login) {
|
||||||
|
for (ClientHandler client : handlers) {
|
||||||
|
if (client.getLogin() != null && client.getLogin().equals(login)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect(ClientHandler client) {
|
public void disconnect(ClientHandler client) {
|
||||||
if (handlers.remove(client))
|
if (handlers.remove(client))
|
||||||
@ -75,7 +91,7 @@ public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
|
|||||||
* AutoClosable Function
|
* AutoClosable Function
|
||||||
* Closes all ClientHandlers stored in this repository and deallocates all resources.
|
* Closes all ClientHandlers stored in this repository and deallocates all resources.
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package lightcontainer.repository;
|
package lightcontainer.repository;
|
||||||
|
|
||||||
|
import lightcontainer.domains.Task;
|
||||||
import lightcontainer.domains.client.Context;
|
import lightcontainer.domains.client.Context;
|
||||||
import lightcontainer.domains.client.StoreProcessor;
|
import lightcontainer.domains.client.StoreProcessor;
|
||||||
import lightcontainer.domains.Task;
|
|
||||||
import lightcontainer.enumerations.TaskStatus;
|
|
||||||
import lightcontainer.interfaces.ClientHandlerFFE;
|
import lightcontainer.interfaces.ClientHandlerFFE;
|
||||||
import lightcontainer.interfaces.ProtocolRepository;
|
import lightcontainer.interfaces.ProtocolRepository;
|
||||||
import lightcontainer.interfaces.StoreProcessorFFE;
|
import lightcontainer.interfaces.StoreProcessorFFE;
|
||||||
@ -15,9 +14,9 @@ import java.util.concurrent.ConcurrentLinkedDeque;
|
|||||||
|
|
||||||
public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
|
public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
|
||||||
// Variables
|
// Variables
|
||||||
private Deque<Task> tasks = new ConcurrentLinkedDeque<>();
|
private final Deque<Task> tasks = new ConcurrentLinkedDeque<>();
|
||||||
private ClientHandlerRepository clientRepository; // TODO -> pourquoi pas une interface ? end
|
private final ClientHandlerRepository clientRepository; // TODO -> pourquoi pas une interface ? end
|
||||||
private StoreProcessorRepository storeRepository; // TODO -> pourquoi pas une interface ? end
|
private final StoreProcessorRepository storeRepository; // TODO -> pourquoi pas une interface ? end
|
||||||
private ProtocolRepository protocolRepository;
|
private ProtocolRepository protocolRepository;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
@ -32,7 +31,7 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
|
|||||||
*/
|
*/
|
||||||
public void alertStoreProcessors(Task task) {
|
public void alertStoreProcessors(Task task) {
|
||||||
// On avertit les stor processors d'une nouvelle tâche
|
// On avertit les stor processors d'une nouvelle tâche
|
||||||
String stor = storeRepository.findDomain(task);
|
String stor = storeRepository.findDomain();
|
||||||
if (stor != null) {
|
if (stor != null) {
|
||||||
storeRepository.assignTask(stor, task);
|
storeRepository.assignTask(stor, task);
|
||||||
task.setDomain(stor);
|
task.setDomain(stor);
|
||||||
@ -42,44 +41,60 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
|
|||||||
/**
|
/**
|
||||||
* Permet à un {@link StoreProcessor} d'avertir le FFE qu'il est disponible
|
* Permet à un {@link StoreProcessor} d'avertir le FFE qu'il est disponible
|
||||||
*
|
*
|
||||||
* @param store Le SBE qui s'est occupé de la tâche
|
* @param storeDomain Le SBE qui s'est occupé de la tâche
|
||||||
* @param response La réponse à envoyer au client
|
* @param response La réponse à envoyer au client
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onStoreAvailable(StoreProcessor store, ProtocolWriter.ProtocolResult response) {
|
public void onStoreAvailable(String storeDomain, ProtocolWriter.ProtocolResult response) {
|
||||||
// TODO : Chercher une tâche appropriée
|
responseToClient(storeDomain, response);
|
||||||
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();
|
Iterator<Task> it = tasks.iterator();
|
||||||
|
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Task task = it.next();
|
Task task = it.next();
|
||||||
if (store.canProcessTask(task)) {
|
if (task.getDomain() == null || task.getDomain().equals(storeDomain)) { // Si tâche sans domaine ou si domaine requis pour la tâche est le domaine
|
||||||
storeRepository.assignTask(store.getDomain(), task);
|
task.setDomain(storeDomain);
|
||||||
task.setDomain(store.getDomain());
|
storeRepository.assignTask(storeDomain, task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStoreDisconnect(String domain) {
|
||||||
|
responseToClient(domain, null);
|
||||||
|
Iterator<Task> it = tasks.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Task task = it.next();
|
||||||
|
if (storeRepository.domainCount() == 0 || (task.getDomain() != null && task.getDomain().equals(domain))) {
|
||||||
|
clientRepository.respondToClient(it.next().getClient(), null);
|
||||||
|
it.remove(); // Suppression de la tâche
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.storeRepository.closeStore(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void responseToClient(String storeDomain, ProtocolWriter.ProtocolResult response) {
|
||||||
|
Iterator<Task> it = tasks.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Task task = it.next();
|
||||||
|
if (task.isResponseOfClient(storeDomain)) {
|
||||||
|
clientRepository.respondToClient(task.getClient(), response);
|
||||||
|
it.remove(); // Suppression de la tâche
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void newCommand(Context context, ProtocolWriter.ProtocolResult command) {
|
public void newCommand(Context context, ProtocolWriter.ProtocolResult command, String requestDomain) {
|
||||||
Task task = Task.newInstance(context, command);
|
Task task = Task.newInstance(context, command, requestDomain);
|
||||||
tasks.add(task);
|
tasks.add(task);
|
||||||
alertStoreProcessors(task);
|
alertStoreProcessors(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canExecuteCommand(String domain) {
|
||||||
|
return domain == null ? storeRepository.domainCount() > 0 : storeRepository.hasDomain(domain);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ public class ProtocolRepositoryImpl implements ProtocolRepository {
|
|||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("COMMANDE NULL");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package lightcontainer.repository;
|
||||||
|
|
||||||
|
public interface ReadOnlyClientRepository {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de savoir si un client est déjà connecté avec ce login.
|
||||||
|
*
|
||||||
|
* @param login Login du client.
|
||||||
|
*/
|
||||||
|
boolean hasClient(String login);
|
||||||
|
|
||||||
|
}
|
@ -5,20 +5,22 @@ import lightcontainer.domains.client.StoreProcessor;
|
|||||||
import lightcontainer.domains.server.MulticastServerListener;
|
import lightcontainer.domains.server.MulticastServerListener;
|
||||||
import lightcontainer.interfaces.MulticastSPR;
|
import lightcontainer.interfaces.MulticastSPR;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
// TODO : C'est genre un ClientHandlerManager quoi hein, normal qu'il fasse blinder de chose ;)
|
// TODO : C'est genre un ClientHandlerManager quoi hein, normal qu'il fasse blinder de chose ;)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StoreProcessorRepository
|
* StoreProcessorRepository
|
||||||
*
|
* <p>
|
||||||
* Repository storing StorePorcessor class.
|
* Repository storing StorePorcessor class.
|
||||||
* Contains some utility functions.
|
* Contains some utility functions.
|
||||||
*
|
*
|
||||||
* @version 1.0
|
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
||||||
* @since 1.0
|
* @version 1.0
|
||||||
*
|
* @see StoreProcessor
|
||||||
* @see StoreProcessor
|
* @since 1.0
|
||||||
* @author Jérémi NIHART <j.nihart@student.helmo.be>
|
|
||||||
*/
|
*/
|
||||||
public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
|
public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
|
||||||
// Variables
|
// Variables
|
||||||
@ -33,9 +35,9 @@ public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
|
|||||||
/**
|
/**
|
||||||
* Setter, allow to define the ServerListener of a repository.
|
* Setter, allow to define the ServerListener of a repository.
|
||||||
* & start the server.
|
* & start the server.
|
||||||
* @param server ServerListener to set as default.
|
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @param server ServerListener to set as default.
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setServerListener(MulticastServerListener server) {
|
public void setServerListener(MulticastServerListener server) {
|
||||||
@ -45,25 +47,38 @@ public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a StorePorcessor.
|
* Add a StorePorcessor.
|
||||||
* @param store Store processor to add.
|
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @param store Store processor to add.
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addStore(StoreProcessor store) {
|
public boolean addStore(StoreProcessor store) {
|
||||||
this.handlers.add(store);
|
if (!this.hasDomain(store.getDomain())) {
|
||||||
|
store.start();
|
||||||
|
return this.handlers.add(store);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String findDomain(Task task) {
|
public String findDomain() {
|
||||||
StoreProcessor handler = findSBE(task);
|
StoreProcessor handler = findSBE();
|
||||||
return handler == null ? null : handler.getDomain();
|
return handler == null ? null : handler.getDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
private StoreProcessor findSBE(Task task) {
|
private StoreProcessor findSBE() {
|
||||||
for (StoreProcessor handler : handlers) {
|
for (StoreProcessor handler : handlers) {
|
||||||
if (handler.canProcessTask(task)) {
|
if (handler.canProcessTask()) {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StoreProcessor getSBE(String stor) {
|
||||||
|
for (StoreProcessor handler : handlers) {
|
||||||
|
if (handler.getDomain().equals(stor)) {
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,16 +88,95 @@ public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignTask(String stor, Task task) {
|
public void assignTask(String stor, Task task) {
|
||||||
StoreProcessor handler = findSBE(task);
|
StoreProcessor handler = getSBE(stor);
|
||||||
System.out.println("Find stor : " + handler);
|
if (handler != null) {
|
||||||
handler.executeCommand(task.getContext(), task.getCommand());
|
handler.executeCommand(task.getContext(), task.getCommand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDomain(String domain) {
|
||||||
|
for (StoreProcessor handler : handlers) {
|
||||||
|
if (handler.getDomain().equals(domain)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int domainCount() {
|
||||||
|
return handlers.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnectDomains() {
|
||||||
|
for (StoreProcessor handler : handlers) {
|
||||||
|
handler.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de déconnecter un SBE
|
||||||
|
*
|
||||||
|
* @param domain Le domaine du SBE à déconnecter
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void closeStore(String domain) {
|
||||||
|
StoreProcessor storeProcessor = getSBE(domain);
|
||||||
|
if (storeProcessor != null) {
|
||||||
|
storeProcessor.close();
|
||||||
|
handlers.remove(storeProcessor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de mettre à jours la dernière annonce de ce SBE au FFE
|
||||||
|
*
|
||||||
|
* @param domain Le domain s'annoncant
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateLastAnnounce(String domain) {
|
||||||
|
StoreProcessor storeProcessor = getSBE(domain);
|
||||||
|
if (storeProcessor != null) {
|
||||||
|
storeProcessor.setLastAnnounce(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de récupérer les noms des domaines connectés au FFE
|
||||||
|
*
|
||||||
|
* @return Les noms des domaines connectés au FFE
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Collection<String> getDomains() {
|
||||||
|
Set<String> domains = new HashSet<>();
|
||||||
|
|
||||||
|
for (StoreProcessor domain : handlers) {
|
||||||
|
domains.add(domain.getDomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
return domains;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de récupérer la dernière annonce d'un SBE
|
||||||
|
*
|
||||||
|
* @param domain
|
||||||
|
* @return La dernière annonce d'un SBE
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public LocalDateTime getLastAnnounce(String domain) {
|
||||||
|
StoreProcessor storeProcessor = getSBE(domain);
|
||||||
|
return storeProcessor == null ? null : storeProcessor.getLastAnnounce();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AutoClosable Function
|
* AutoClosable Function
|
||||||
* Closes all StoreProcessor stored in this repository and deallocates all resources.
|
* Closes all StoreProcessor stored in this repository and deallocates all resources.
|
||||||
*
|
*
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
@ -91,4 +185,7 @@ public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
|
|||||||
// Close each client.
|
// Close each client.
|
||||||
this.handlers.forEach(StoreProcessor::close);
|
this.handlers.forEach(StoreProcessor::close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ public class AppConfig {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Méthode permettant de récupérer le chemin de sauvegarde des fichiers
|
* Méthode permettant de récupérer le chemin de sauvegarde des fichiers
|
||||||
|
*
|
||||||
* @return Chemin de sauvegarde
|
* @return Chemin de sauvegarde
|
||||||
*/
|
*/
|
||||||
public String getStoragePath() {
|
public String getStoragePath() {
|
||||||
|
@ -16,12 +16,11 @@ import java.util.Map;
|
|||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public class AppData {
|
public class AppData {
|
||||||
|
// Variable
|
||||||
private static AppData instance = null;
|
private static AppData instance = null;
|
||||||
private AppConfig appConfig;
|
private AppConfig appConfig;
|
||||||
private final Map<String, User> users;
|
private final Map<String, User> users;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new instance of AppData.
|
* Constructs a new instance of AppData.
|
||||||
* Sets appConfig to null and creates a new Hashmap of users.
|
* Sets appConfig to null and creates a new Hashmap of users.
|
||||||
@ -76,14 +75,13 @@ public class AppData {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this method when a user signs up.
|
* Use this method when a user signs up.
|
||||||
*
|
*
|
||||||
* @return True if the user was added. False if a user with the same name already exists.
|
* @return True if the user was added. False if a user with the same name already exists.
|
||||||
*/
|
*/
|
||||||
public boolean addUser(String login, String password, String key, String passwordSalt) {
|
public boolean addUser(String login, String password, String key) {
|
||||||
User user = new User(login, password, key, passwordSalt, new HashMap<>());
|
User user = new User(login, password, key, new HashMap<>());
|
||||||
if (this.users.containsKey(user.getName())) {
|
if (this.users.containsKey(user.getName())) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -138,6 +136,24 @@ public class AppData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter, allow to retrieve a specified file object.
|
||||||
|
*
|
||||||
|
* @param fileName The name of the file to retrieve.
|
||||||
|
* @param userName The name of the user who wants to retrieve the file.
|
||||||
|
* @return The requested file matching file name and username, or null
|
||||||
|
* if the user or file do not exist.
|
||||||
|
* @author Unknown...
|
||||||
|
* @see User#getFile(String)
|
||||||
|
* @see File
|
||||||
|
*/
|
||||||
|
public File getFileOf(String fileName, String userName) {
|
||||||
|
if (this.users.containsKey(userName)) {
|
||||||
|
return this.users.get(userName).getFile(fileName);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this method after receiving REMOVEFILE_OK from the StorBackEnd.
|
* Call this method after receiving REMOVEFILE_OK from the StorBackEnd.
|
||||||
* Do NOT call when receiving REMOVEFILE_ERROR, or it will break the system's synchronization.
|
* Do NOT call when receiving REMOVEFILE_ERROR, or it will break the system's synchronization.
|
||||||
@ -171,17 +187,16 @@ public class AppData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param login The login of the user to test password
|
||||||
|
* @param password The plain text password to try against user's hashed password
|
||||||
|
* @return True if password matches user's password. False if user could not be found or password didn't match
|
||||||
|
*/
|
||||||
public boolean verifyUser(String login, String password) {
|
public boolean verifyUser(String login, String password) {
|
||||||
User user = getUser(login);
|
User user = getUser(login);
|
||||||
return user != null && user.verifyPassword(password);
|
return user != null && user.verifyPassword(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUserPasswordSalt(String login) {
|
|
||||||
User user = getUser(login);
|
|
||||||
return user == null ? null : user.getPasswordSalt();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Méthode permettant de récupérer la clé AES d'un utilisateur
|
* Méthode permettant de récupérer la clé AES d'un utilisateur
|
||||||
*
|
*
|
||||||
@ -192,5 +207,4 @@ public class AppData {
|
|||||||
User user = getUser(login);
|
User user = getUser(login);
|
||||||
return user == null ? null : user.getAesKey();
|
return user == null ? null : user.getAesKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,16 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* File represents all information related to a file
|
* File represents all information related to a file
|
||||||
*/
|
*/
|
||||||
public class File {
|
public class File implements ReadOnlyFile {
|
||||||
|
// Variables
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String fileNameSalt;
|
private final String fileNameSalt;
|
||||||
private final int size;
|
private final long size;
|
||||||
private final String iv;
|
private final String iv;
|
||||||
private final Set<String> storage;
|
private final Set<String> storage;
|
||||||
|
|
||||||
public File(String name, String fileNameSalt, int size, String iv, Set<String> storage) {
|
// Constructor
|
||||||
|
public File(String name, String fileNameSalt, long size, String iv, Set<String> storage) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.fileNameSalt = fileNameSalt;
|
this.fileNameSalt = fileNameSalt;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
@ -22,22 +23,27 @@ public class File {
|
|||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getFileNameSalt() {
|
public String getFileNameSalt() {
|
||||||
return fileNameSalt;
|
return fileNameSalt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
@Override
|
||||||
|
public long getSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getIv() {
|
public String getIv() {
|
||||||
return iv;
|
return iv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Iterator<String> getStorageIterator() {
|
public Iterator<String> getStorageIterator() {
|
||||||
return storage.iterator();
|
return storage.iterator();
|
||||||
}
|
}
|
||||||
@ -50,6 +56,5 @@ public class File {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package lightcontainer.storage;
|
package lightcontainer.storage;
|
||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
|
import lightcontainer.utils.Log;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -40,7 +41,6 @@ public class JsonAdapter implements Adapter {
|
|||||||
user.addProperty("name", current.getName());
|
user.addProperty("name", current.getName());
|
||||||
user.addProperty("password", current.getPassword());
|
user.addProperty("password", current.getPassword());
|
||||||
user.addProperty("aes_key", current.getAesKey());
|
user.addProperty("aes_key", current.getAesKey());
|
||||||
user.addProperty("passwordSalt", current.getPasswordSalt());
|
|
||||||
JsonArray files = new JsonArray();
|
JsonArray files = new JsonArray();
|
||||||
Iterator<File> fileIterator = current.fileIterator();
|
Iterator<File> fileIterator = current.fileIterator();
|
||||||
addFiles(fileIterator, files);
|
addFiles(fileIterator, files);
|
||||||
@ -98,7 +98,7 @@ public class JsonAdapter implements Adapter {
|
|||||||
}
|
}
|
||||||
return appData;
|
return appData;
|
||||||
} catch (JsonParseException parseException) {
|
} catch (JsonParseException parseException) {
|
||||||
System.out.println("[FFE] : Error while loading configuration file"); //TODO - changer en log
|
Log.getInstance().infoln("[FFE] : Error while loading configuration file"); //TODO - changer en log
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,11 +109,10 @@ public class JsonAdapter implements Adapter {
|
|||||||
String name = jsonUser.get("name").getAsString();
|
String name = jsonUser.get("name").getAsString();
|
||||||
String password = jsonUser.get("password").getAsString();
|
String password = jsonUser.get("password").getAsString();
|
||||||
String aeskey = jsonUser.get("aes_key").getAsString();
|
String aeskey = jsonUser.get("aes_key").getAsString();
|
||||||
String passwordSalt = jsonUser.get("passwordSalt").getAsString();
|
|
||||||
Map<String, File> userFiles = new HashMap<>();
|
Map<String, File> userFiles = new HashMap<>();
|
||||||
JsonArray jsonFiles = jsonUser.getAsJsonArray("files");
|
JsonArray jsonFiles = jsonUser.getAsJsonArray("files");
|
||||||
getFiles(userFiles, jsonFiles);
|
getFiles(userFiles, jsonFiles);
|
||||||
User user = new User(name, password, aeskey, passwordSalt, userFiles);
|
User user = new User(name, password, aeskey, userFiles);
|
||||||
users.add(user);
|
users.add(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
app/src/main/java/lightcontainer/storage/ReadOnlyFile.java
Normal file
16
app/src/main/java/lightcontainer/storage/ReadOnlyFile.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package lightcontainer.storage;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public interface ReadOnlyFile {
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
String getFileNameSalt();
|
||||||
|
|
||||||
|
long getSize();
|
||||||
|
|
||||||
|
String getIv();
|
||||||
|
|
||||||
|
Iterator<String> getStorageIterator();
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package lightcontainer.storage;
|
package lightcontainer.storage;
|
||||||
|
|
||||||
|
import lightcontainer.utils.Log;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -10,7 +12,7 @@ import java.nio.file.StandardOpenOption;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Repository {
|
public class Repository {
|
||||||
|
// Variables
|
||||||
private final String filePath;
|
private final String filePath;
|
||||||
private final Adapter adapter;
|
private final Adapter adapter;
|
||||||
private final AppData appData;
|
private final AppData appData;
|
||||||
@ -28,20 +30,20 @@ public class Repository {
|
|||||||
/**
|
/**
|
||||||
* Saves configuration file
|
* Saves configuration file
|
||||||
*/
|
*/
|
||||||
public void save() {
|
public synchronized void save() {
|
||||||
if (filePath != null) {
|
if (filePath != null) {
|
||||||
String jsonAppData = adapter.toString(appData);
|
String jsonAppData = adapter.toString(appData);
|
||||||
try (BufferedWriter bufferedWriter = Files.newBufferedWriter(Paths.get(filePath).toAbsolutePath(), StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
|
try (BufferedWriter bufferedWriter = Files.newBufferedWriter(Paths.get(filePath).toAbsolutePath(), StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
|
||||||
bufferedWriter.write(jsonAppData);
|
bufferedWriter.write(jsonAppData);
|
||||||
bufferedWriter.flush();
|
bufferedWriter.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("Error while saving configuration file !");
|
Log.getInstance().infoln("Error while saving configuration file !");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addUser(String login, String password, String key, String passwordSalt) {
|
public boolean addUser(String login, String password, String key) {
|
||||||
if (appData.addUser(login, password, key, passwordSalt)) {
|
if (appData.addUser(login, password, key)) {
|
||||||
save();
|
save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -76,7 +78,6 @@ public class Repository {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads configuration file
|
* Loads configuration file
|
||||||
*
|
*
|
||||||
@ -94,7 +95,7 @@ public class Repository {
|
|||||||
builder.append(reader.readLine());
|
builder.append(reader.readLine());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("Error while reading configuration file");
|
Log.getInstance().infoln("Error while reading configuration file");
|
||||||
builder.setLength(0);
|
builder.setLength(0);
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
@ -112,14 +113,15 @@ public class Repository {
|
|||||||
return appData.getAppConfig().getMulticastPort();
|
return appData.getAppConfig().getMulticastPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param login The login of the user to test password
|
||||||
|
* @param password The plain text password to try against user's hashed password
|
||||||
|
* @return True if password matches user's password. False if user could not be found or password didn't match
|
||||||
|
*/
|
||||||
public boolean verifyUser(String login, String password) {
|
public boolean verifyUser(String login, String password) {
|
||||||
return appData.verifyUser(login, password);
|
return appData.verifyUser(login, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUserPasswordSalt(String login) {
|
|
||||||
return appData.getUserPasswordSalt(login);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Méthode permettant de récupérer le chemin de sauvegarde des fichiers
|
* Méthode permettant de récupérer le chemin de sauvegarde des fichiers
|
||||||
*
|
*
|
||||||
@ -139,8 +141,26 @@ public class Repository {
|
|||||||
return appData.getUserAesKey(login);
|
return appData.getUserAesKey(login);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter, allow to retrieve a specified file object.
|
||||||
|
*
|
||||||
|
* @param fileName The name of the file to retrieve.
|
||||||
|
* @param userName The name of the user who wants to retrieve the file.
|
||||||
|
* @return The requested file matching file name and username, or null
|
||||||
|
* if the user or file do not exist.
|
||||||
|
* @author Unknown...
|
||||||
|
* @see AppData#getFileOf(String, String)
|
||||||
|
* @see File
|
||||||
|
*/
|
||||||
|
public ReadOnlyFile getFileOf(String fileName, String userName) {
|
||||||
|
return this.appData.getFileOf(fileName, userName);
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> getStringifiedFilesOf(String login) {
|
public List<String> getStringifiedFilesOf(String login) {
|
||||||
return this.appData.getStringifiedFilesOf(login);
|
return this.appData.getStringifiedFilesOf(login);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNetworkInterface() {
|
||||||
|
return this.appData.getAppConfig().getNetworkInterface();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package lightcontainer.storage;
|
package lightcontainer.storage;
|
||||||
|
|
||||||
|
import lightcontainer.utils.BCryptHasher;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -13,20 +15,18 @@ import java.util.Map;
|
|||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public class User {
|
public class User {
|
||||||
|
// Variables
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String password;
|
private final String password;
|
||||||
private final String aesKey;
|
private final String aesKey;
|
||||||
private final String passwordSalt;
|
|
||||||
private final Map<String, File> files;
|
private final Map<String, File> files;
|
||||||
|
|
||||||
public User(String name, String password, String aesKey, String passwordSalt, Map<String, File> files) {
|
// Constructor
|
||||||
|
public User(String name, String password, String aesKey, Map<String, File> files) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.aesKey = aesKey;
|
this.aesKey = aesKey;
|
||||||
this.passwordSalt = passwordSalt;
|
|
||||||
this.files = files;
|
this.files = files;
|
||||||
System.out.println(files.size() + " fichiers trouvéssss pour " + name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -41,10 +41,6 @@ public class User {
|
|||||||
return aesKey;
|
return aesKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPasswordSalt() {
|
|
||||||
return this.passwordSalt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator<File> fileIterator() {
|
public Iterator<File> fileIterator() {
|
||||||
return files.values().iterator();
|
return files.values().iterator();
|
||||||
}
|
}
|
||||||
@ -106,8 +102,11 @@ public class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param password The plain text password to test
|
||||||
|
* @return True if password matches user's hashed password. False otherwise
|
||||||
|
*/
|
||||||
public boolean verifyPassword(String password) {
|
public boolean verifyPassword(String password) {
|
||||||
return this.password.equals(password);
|
return BCryptHasher.checkPassword(password, this.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ package lightcontainer.utils;
|
|||||||
import javax.crypto.*;
|
import javax.crypto.*;
|
||||||
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.io.*;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
@ -11,10 +12,9 @@ import java.util.Base64;
|
|||||||
/**
|
/**
|
||||||
* AES GCM 256 Encryption Class [DO NOT EDIT]
|
* AES GCM 256 Encryption Class [DO NOT EDIT]
|
||||||
*
|
*
|
||||||
* @since 1.0
|
|
||||||
* @version 1.0
|
|
||||||
*
|
|
||||||
* @author Jérémi Nihart <contact@endmove.eu>
|
* @author Jérémi Nihart <contact@endmove.eu>
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public class AES_GCM {
|
public class AES_GCM {
|
||||||
// Constants
|
// Constants
|
||||||
@ -22,65 +22,12 @@ public class AES_GCM {
|
|||||||
public static final int GCM_IV_LENGTH = 16;
|
public static final int GCM_IV_LENGTH = 16;
|
||||||
public static final int GCM_TAG_LENGTH = 16;
|
public static final int GCM_TAG_LENGTH = 16;
|
||||||
|
|
||||||
// Main method for testing
|
|
||||||
public static void main(String[] args) throws Exception
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* FILE ENCRYPTION DEMO
|
|
||||||
*/
|
|
||||||
// Init files
|
|
||||||
File inFile = new File("D:\\HELMo.png");
|
|
||||||
File outFile = new File("D:\\HELMoCrypted.png");
|
|
||||||
File clearFile = new File("D:\\HELMoClear.png");
|
|
||||||
outFile.createNewFile();
|
|
||||||
clearFile.createNewFile();
|
|
||||||
// Make options
|
|
||||||
String IVFile = generateIV();
|
|
||||||
String keyFile = generateSecretKey();
|
|
||||||
// Show options
|
|
||||||
System.out.println("IV : "+IVFile);
|
|
||||||
System.out.println("Key : "+keyFile);
|
|
||||||
// Encrypt
|
|
||||||
encryptStream(
|
|
||||||
new FileInputStream(inFile),
|
|
||||||
new FileOutputStream(outFile),
|
|
||||||
inFile.length(),
|
|
||||||
IVFile,
|
|
||||||
keyFile
|
|
||||||
);
|
|
||||||
// Decrypt
|
|
||||||
decryptStream(
|
|
||||||
new FileInputStream(outFile),
|
|
||||||
new FileOutputStream(clearFile),
|
|
||||||
outFile.length(),
|
|
||||||
IVFile,
|
|
||||||
keyFile
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TEXT ENCRYPTION DEMO
|
|
||||||
*/
|
|
||||||
// Make option
|
|
||||||
String plainText = "Salut sombre fils de pute, comment vas tu ?";//TODO enlever le text chelou de Jérémi (ce fou là)
|
|
||||||
String IV = generateIV();
|
|
||||||
String key = generateSecretKey();
|
|
||||||
// Show options
|
|
||||||
System.out.println("IV : "+IV);
|
|
||||||
System.out.println("Key : "+key);
|
|
||||||
System.out.println("Original text : " + plainText);
|
|
||||||
// Crypt
|
|
||||||
String cryptText = encrypt(plainText, key, IV);
|
|
||||||
System.out.println("Encrypted text : " + cryptText);
|
|
||||||
// Decrypt
|
|
||||||
String decryptedText = decrypt(cryptText, key, IV);
|
|
||||||
System.out.println("Decrypted text : " + decryptedText);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decoder to decode base64 vector to byte vector.
|
* Decoder to decode base64 vector to byte vector.
|
||||||
*
|
*
|
||||||
* @param base64Vector A base64 encoded vector.
|
* @param base64Vector A base64 encoded vector.
|
||||||
* @return Byte vector.
|
* @return Byte vector.
|
||||||
*/
|
*/
|
||||||
private static byte[] decodeBase64Vector(String base64Vector) {
|
private static byte[] decodeBase64Vector(String base64Vector) {
|
||||||
Base64.Decoder b64Decoder = Base64.getDecoder();
|
Base64.Decoder b64Decoder = Base64.getDecoder();
|
||||||
@ -90,10 +37,9 @@ public class AES_GCM {
|
|||||||
/**
|
/**
|
||||||
* Decoder to decode base64 string to plain string.
|
* Decoder to decode base64 string to plain string.
|
||||||
*
|
*
|
||||||
* @param base64String A base64 encoded string.
|
* @param base64String A base64 encoded string.
|
||||||
* @return Plain string.
|
* @return Plain string.
|
||||||
*
|
* @see AES_GCM#decodeBase64Vector(String)
|
||||||
* @see AES_GCM#decodeBase64Vector(String)
|
|
||||||
*/
|
*/
|
||||||
private static String decodeBase64String(String base64String) {
|
private static String decodeBase64String(String base64String) {
|
||||||
return new String(decodeBase64Vector(base64String));
|
return new String(decodeBase64Vector(base64String));
|
||||||
@ -101,8 +47,9 @@ public class AES_GCM {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Encoder to encode vector to base64 string.
|
* Encoder to encode vector to base64 string.
|
||||||
* @param rawVector A raw vector.
|
*
|
||||||
* @return A base64 encoded vector.
|
* @param rawVector A raw vector.
|
||||||
|
* @return A base64 encoded vector.
|
||||||
*/
|
*/
|
||||||
private static String encodeBase64(byte[] rawVector) {
|
private static String encodeBase64(byte[] rawVector) {
|
||||||
Base64.Encoder b64Encoder = Base64.getEncoder();
|
Base64.Encoder b64Encoder = Base64.getEncoder();
|
||||||
@ -111,10 +58,10 @@ public class AES_GCM {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Encoder to encode string to base64 string.
|
* Encoder to encode string to base64 string.
|
||||||
* @param rawString A raw string.
|
|
||||||
* @return A base64 encoded string.
|
|
||||||
*
|
*
|
||||||
* @see AES_GCM#encodeBase64(byte[]))
|
* @param rawString A raw string.
|
||||||
|
* @return A base64 encoded string.
|
||||||
|
* @see AES_GCM#encodeBase64(byte[]))
|
||||||
*/
|
*/
|
||||||
private static String encodeBase64(String rawString) {
|
private static String encodeBase64(String rawString) {
|
||||||
return encodeBase64(rawString.getBytes(StandardCharsets.UTF_8));
|
return encodeBase64(rawString.getBytes(StandardCharsets.UTF_8));
|
||||||
@ -123,14 +70,12 @@ public class AES_GCM {
|
|||||||
/**
|
/**
|
||||||
* FACTORY, to setting up a Java cryptographic cypher.
|
* FACTORY, to setting up a Java cryptographic cypher.
|
||||||
*
|
*
|
||||||
* @param op_mode the operation mode of this cipher (this is one of the
|
* @param op_mode the operation mode of this cipher (this is one of the
|
||||||
* following: ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE or UNWRAP_MODE)
|
* following: ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE or UNWRAP_MODE)
|
||||||
* @param key Base64 encoded secret key.
|
* @param key Base64 encoded secret key.
|
||||||
* @param IV Base64 encoded vector.
|
* @param IV Base64 encoded vector.
|
||||||
*
|
* @return A Cryptography cypher.
|
||||||
* @return A Cryptography cypher.
|
* @throws AesGcmException Throw an exception in case of an error occur while setting up the the cypher.
|
||||||
*
|
|
||||||
* @throws AesGcmException Throw an exception in case of an error occur while setting up the the cypher.
|
|
||||||
*/
|
*/
|
||||||
private static Cipher createCipher(int op_mode, String key, String IV) throws AesGcmException {
|
private static Cipher createCipher(int op_mode, String key, String IV) throws AesGcmException {
|
||||||
try {
|
try {
|
||||||
@ -151,9 +96,8 @@ public class AES_GCM {
|
|||||||
/**
|
/**
|
||||||
* Generate a secret key base64 encoded.
|
* Generate a secret key base64 encoded.
|
||||||
*
|
*
|
||||||
* @return New Secret key b64 encoded.
|
* @return New Secret key b64 encoded.
|
||||||
*
|
* @throws AesGcmException Exception if an error occur.
|
||||||
* @throws AesGcmException Exception if an error occur.
|
|
||||||
*/
|
*/
|
||||||
public static String generateSecretKey() throws AesGcmException {
|
public static String generateSecretKey() throws AesGcmException {
|
||||||
try {
|
try {
|
||||||
@ -169,7 +113,7 @@ public class AES_GCM {
|
|||||||
/**
|
/**
|
||||||
* Generate an IV (initialisation vector) base64 encoded.
|
* Generate an IV (initialisation vector) base64 encoded.
|
||||||
*
|
*
|
||||||
* @return New generated IV b64 encoded.
|
* @return New generated IV b64 encoded.
|
||||||
*/
|
*/
|
||||||
public static String generateIV() {
|
public static String generateIV() {
|
||||||
byte[] IV = new byte[GCM_IV_LENGTH];
|
byte[] IV = new byte[GCM_IV_LENGTH];
|
||||||
@ -181,13 +125,11 @@ public class AES_GCM {
|
|||||||
/**
|
/**
|
||||||
* Encrypt text, with AES GCM.
|
* Encrypt text, with AES GCM.
|
||||||
*
|
*
|
||||||
* @param plainText Plain text to encrypt.
|
* @param plainText Plain text to encrypt.
|
||||||
* @param key Base64 encoded secret key.
|
* @param key Base64 encoded secret key.
|
||||||
* @param IV Base64 encoded vector.
|
* @param IV Base64 encoded vector.
|
||||||
*
|
* @return The encrypted plain text Base64 encoded.
|
||||||
* @return The encrypted plain text Base64 encoded.
|
* @throws AesGcmException Exception if an error occur.
|
||||||
*
|
|
||||||
* @throws AesGcmException Exception if an error occur.
|
|
||||||
*/
|
*/
|
||||||
public static String encrypt(String plainText, String key, String IV) throws AesGcmException {
|
public static String encrypt(String plainText, String key, String IV) throws AesGcmException {
|
||||||
try {
|
try {
|
||||||
@ -202,18 +144,18 @@ public class AES_GCM {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt stream, with AES GCM.
|
* Encrypt stream, with AES GCM.
|
||||||
|
* The output stream is automatically closed after processing.
|
||||||
*
|
*
|
||||||
* @param in InputStream to the input, flux to encrypt.
|
* @param in InputStream to the input, flux to encrypt.
|
||||||
* @param out OutputStream to the output, encrypted flux.
|
* @param out OutputStream to the output, encrypted flux.
|
||||||
* @param fileSize Stream/file size.
|
* @param fileSize Stream/file size (! unencrypted size !).
|
||||||
* @param key Base64 encoded secret key.
|
* @param key Base64 encoded secret key.
|
||||||
* @param IV Base64 encoded vector.
|
* @param IV Base64 encoded vector.
|
||||||
*
|
* @throws AesGcmException Exception if an error occur.
|
||||||
* @throws AesGcmException Exception if an error occur.
|
|
||||||
*/
|
*/
|
||||||
public static void encryptStream(InputStream in, OutputStream out, long fileSize, String key, String IV) throws AesGcmException {
|
public static void encryptStream(InputStream in, OutputStream out, long fileSize, String key, String IV) throws AesGcmException {
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int currentSize = 0;
|
long currentSize = 0;
|
||||||
int bytes;
|
int bytes;
|
||||||
try {
|
try {
|
||||||
// Make the cipher for encryption
|
// Make the cipher for encryption
|
||||||
@ -221,7 +163,7 @@ public class AES_GCM {
|
|||||||
// Initialize a CipherOutputStream
|
// Initialize a CipherOutputStream
|
||||||
CipherOutputStream cipherOut = new CipherOutputStream(out, cipher);
|
CipherOutputStream cipherOut = new CipherOutputStream(out, cipher);
|
||||||
// Encryption Process
|
// Encryption Process
|
||||||
while((currentSize < fileSize) && (bytes = in.read(buffer)) > 0) {
|
while ((currentSize < fileSize) && (bytes = in.read(buffer)) > 0) {
|
||||||
cipherOut.write(buffer, 0, bytes);
|
cipherOut.write(buffer, 0, bytes);
|
||||||
cipherOut.flush();
|
cipherOut.flush();
|
||||||
currentSize += bytes;
|
currentSize += bytes;
|
||||||
@ -236,13 +178,11 @@ public class AES_GCM {
|
|||||||
/**
|
/**
|
||||||
* Decrypt, with AES GCM.
|
* Decrypt, with AES GCM.
|
||||||
*
|
*
|
||||||
* @param cryptText The encrypted text.
|
* @param cryptText The encrypted text.
|
||||||
* @param key Base64 encoded secret key.
|
* @param key Base64 encoded secret key.
|
||||||
* @param IV Base64 encoded vector.
|
* @param IV Base64 encoded vector.
|
||||||
*
|
* @return The decrypted plain text.
|
||||||
* @return The decrypted plain text.
|
* @throws AesGcmException Exception if an error occur.
|
||||||
*
|
|
||||||
* @throws AesGcmException Exception if an error occur.
|
|
||||||
*/
|
*/
|
||||||
public static String decrypt(String cryptText, String key, String IV) throws AesGcmException {
|
public static String decrypt(String cryptText, String key, String IV) throws AesGcmException {
|
||||||
try {
|
try {
|
||||||
@ -257,18 +197,18 @@ public class AES_GCM {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt stream, with AES GCM.
|
* Decrypt stream, with AES GCM.
|
||||||
|
* The input stream is automatically closed after processing.
|
||||||
*
|
*
|
||||||
* @param in InputStream to the input, flux to decrypt.
|
* @param in InputStream to the input, flux to decrypt.
|
||||||
* @param out OutputStream to the output, decrypted flux.
|
* @param out OutputStream to the output, decrypted flux.
|
||||||
* @param fileSize Stream/file size.
|
* @param fileSize Stream/file size (! encrypted size !).
|
||||||
* @param key Base64 encoded secret key.
|
* @param key Base64 encoded secret key.
|
||||||
* @param IV Base64 encoded vector.
|
* @param IV Base64 encoded vector.
|
||||||
*
|
* @throws AesGcmException Exception if an error occur.
|
||||||
* @throws AesGcmException Exception if an error occur.
|
|
||||||
*/
|
*/
|
||||||
public static void decryptStream(InputStream in, OutputStream out, long fileSize, String key, String IV) throws AesGcmException {
|
public static void decryptStream(InputStream in, OutputStream out, long fileSize, String key, String IV) throws AesGcmException {
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int currentSize = 0;
|
long currentSize = 0;
|
||||||
int bytes;
|
int bytes;
|
||||||
try {
|
try {
|
||||||
// Make the cipher for decryption
|
// Make the cipher for decryption
|
||||||
@ -276,7 +216,7 @@ public class AES_GCM {
|
|||||||
// Initialize a CipherOutputStream
|
// Initialize a CipherOutputStream
|
||||||
CipherInputStream cipherIn = new CipherInputStream(in, cipher);
|
CipherInputStream cipherIn = new CipherInputStream(in, cipher);
|
||||||
// Encryption Process
|
// Encryption Process
|
||||||
while((currentSize < fileSize) && (bytes = cipherIn.read(buffer)) > 0) {
|
while ((currentSize < fileSize) && (bytes = cipherIn.read(buffer)) > 0) {
|
||||||
out.write(buffer, 0, bytes);
|
out.write(buffer, 0, bytes);
|
||||||
out.flush();
|
out.flush();
|
||||||
currentSize += bytes;
|
currentSize += bytes;
|
||||||
@ -299,7 +239,7 @@ public class AES_GCM {
|
|||||||
* Constructor of AesGcmException,
|
* Constructor of AesGcmException,
|
||||||
* which define it's own detail message.
|
* which define it's own detail message.
|
||||||
*
|
*
|
||||||
* @param msg The detail message.
|
* @param msg The detail message.
|
||||||
*/
|
*/
|
||||||
public AesGcmException(String msg) {
|
public AesGcmException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
@ -310,7 +250,7 @@ public class AES_GCM {
|
|||||||
* which propagates the error triggering
|
* which propagates the error triggering
|
||||||
* a crash of the encryption system.
|
* a crash of the encryption system.
|
||||||
*
|
*
|
||||||
* @param e Previous exception throwable.
|
* @param e Previous exception throwable.
|
||||||
*/
|
*/
|
||||||
public AesGcmException(Throwable e) {
|
public AesGcmException(Throwable e) {
|
||||||
super(e);
|
super(e);
|
||||||
@ -322,8 +262,8 @@ public class AES_GCM {
|
|||||||
* a crash of the encryption system with
|
* a crash of the encryption system with
|
||||||
* a chosen detail message.
|
* a chosen detail message.
|
||||||
*
|
*
|
||||||
* @param e Previous exception throwable.
|
* @param e Previous exception throwable.
|
||||||
* @param msg The detail message.
|
* @param msg The detail message.
|
||||||
*/
|
*/
|
||||||
public AesGcmException(GeneralSecurityException e, String msg) {
|
public AesGcmException(GeneralSecurityException e, String msg) {
|
||||||
super(msg, e);
|
super(msg, e);
|
||||||
|
14
app/src/main/java/lightcontainer/utils/BCryptHasher.java
Normal file
14
app/src/main/java/lightcontainer/utils/BCryptHasher.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package lightcontainer.utils;
|
||||||
|
|
||||||
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
|
|
||||||
|
public class BCryptHasher {
|
||||||
|
|
||||||
|
public static String hashPassword(String plainTextPassword) {
|
||||||
|
return BCrypt.hashpw(plainTextPassword, BCrypt.gensalt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkPassword(String plainTextPassword, String hashedPassword) {
|
||||||
|
return BCrypt.checkpw(plainTextPassword, hashedPassword);
|
||||||
|
}
|
||||||
|
}
|
139
app/src/main/java/lightcontainer/utils/DeepFileEraser.java
Normal file
139
app/src/main/java/lightcontainer/utils/DeepFileEraser.java
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package lightcontainer.utils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DeepFileEraser - Secure file remover
|
||||||
|
*
|
||||||
|
* @since 1.0
|
||||||
|
* @version 1.0
|
||||||
|
*
|
||||||
|
* @author Jérémi Nihart <contact@endmove.eu>
|
||||||
|
*/
|
||||||
|
public class DeepFileEraser {
|
||||||
|
public static final int DFE_BUFFER_DEFAULT_SIZE = 1024; // Default buffer size
|
||||||
|
public static final int DFE_BUFFER_MINIMUM_SIZE = 250; // Minimum buffer size
|
||||||
|
public static final int DFE_BASE_DEFAULT_FILL_VALUE = 0; // Filling value of the initialisation phase
|
||||||
|
public static final int DFE_STEP_MIN_FILL_VALUE = 0; // Minimum filling value of a writing phase
|
||||||
|
public static final int DFE_STEP_MAX_FILL_VALUE = 15; // Maximum filling value of a writing phase
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a number randomly.
|
||||||
|
*
|
||||||
|
* @param min Minimal value (included)
|
||||||
|
* @param max Maximal value (included)
|
||||||
|
*
|
||||||
|
* @return Random generated number.
|
||||||
|
*/
|
||||||
|
private static int random(int min, int max) {
|
||||||
|
return min + (int)(Math.random() * ((max - min) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple remove operation.
|
||||||
|
*
|
||||||
|
* @param target File object on which to operate.
|
||||||
|
* @param length File size.
|
||||||
|
*
|
||||||
|
* @throws DeepFileEraserException Exception if an error occur.
|
||||||
|
*/
|
||||||
|
private static void eraseBase(File target, long length) throws DeepFileEraserException {
|
||||||
|
byte[] buffer = new byte[DFE_BUFFER_DEFAULT_SIZE];
|
||||||
|
long wroteLength = 0;
|
||||||
|
try (OutputStream out = new FileOutputStream(target)) {
|
||||||
|
Arrays.fill(buffer, (byte)DFE_BASE_DEFAULT_FILL_VALUE);
|
||||||
|
while (wroteLength < length) {
|
||||||
|
if (wroteLength + buffer.length > length) {
|
||||||
|
buffer = new byte[(int)(length-wroteLength)];
|
||||||
|
Arrays.fill(buffer, (byte)DFE_BASE_DEFAULT_FILL_VALUE);
|
||||||
|
}
|
||||||
|
out.write(buffer);
|
||||||
|
wroteLength += buffer.length;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new DeepFileEraserException(e, "Error while the Base erasing step.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deep remove operation.
|
||||||
|
*
|
||||||
|
* @param target File object on which to operate.
|
||||||
|
* @param length File size.
|
||||||
|
*
|
||||||
|
* @throws DeepFileEraserException Exception if an error occur.
|
||||||
|
*/
|
||||||
|
private static void eraseStep(File target, long length) throws DeepFileEraserException {
|
||||||
|
byte[] buffer = new byte[random(DFE_BUFFER_MINIMUM_SIZE, DFE_BUFFER_DEFAULT_SIZE)];
|
||||||
|
long wroteLength = 0;
|
||||||
|
try (OutputStream out = new FileOutputStream(target)) {
|
||||||
|
while(wroteLength < length) {
|
||||||
|
if (wroteLength + buffer.length > length) buffer = new byte[(int)(length-wroteLength)];
|
||||||
|
Arrays.fill(buffer, (byte) random(DFE_STEP_MIN_FILL_VALUE, DFE_STEP_MAX_FILL_VALUE));
|
||||||
|
out.write(buffer);
|
||||||
|
wroteLength += buffer.length;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new DeepFileEraserException(e, "Error while the Step erasing step.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase a file deeply.
|
||||||
|
* default deeply level = 7.
|
||||||
|
*
|
||||||
|
* @param filePath Path of the file.
|
||||||
|
*
|
||||||
|
* @throws DeepFileEraserException Exception if an error occur.
|
||||||
|
*/
|
||||||
|
public static void eraseFile(String filePath) throws DeepFileEraserException {
|
||||||
|
eraseFile(filePath, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase a file deeply.
|
||||||
|
*
|
||||||
|
* @param filePath Path of the file.
|
||||||
|
* @param depthLevel Erasure level (the higher the number, the longer and more secure the erasure).
|
||||||
|
*
|
||||||
|
* @throws DeepFileEraserException Exception if an error occur.
|
||||||
|
*/
|
||||||
|
public static void eraseFile(String filePath, int depthLevel) throws DeepFileEraserException {
|
||||||
|
// Init
|
||||||
|
File target = new File(filePath);
|
||||||
|
if (target.exists()) {
|
||||||
|
long targetSize = target.length();
|
||||||
|
// Base write
|
||||||
|
eraseBase(target, targetSize);
|
||||||
|
// Deep write
|
||||||
|
for (int i = 0; i < depthLevel; i++) eraseStep(target, targetSize);
|
||||||
|
// Delete file
|
||||||
|
target.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal Error from DeepFileEraser encryption Class
|
||||||
|
*/
|
||||||
|
public static class DeepFileEraserException extends Exception {
|
||||||
|
// Constant
|
||||||
|
private static final long serialVersionUID = -158979547897543145L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of DeepFileEraserException,
|
||||||
|
* which propagates the error triggering
|
||||||
|
* a crash of the erasing file system with
|
||||||
|
* a chosen detail message.
|
||||||
|
*
|
||||||
|
* @param e Previous exception throwable.
|
||||||
|
* @param msg The detail message.
|
||||||
|
*/
|
||||||
|
public DeepFileEraserException(Throwable e, String msg) {
|
||||||
|
super(msg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,28 +3,55 @@ package lightcontainer.utils;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
public class FileReceiver {
|
public class FileReceiver {
|
||||||
private String path;
|
private final String path;
|
||||||
|
|
||||||
public FileReceiver(String path) { this.path = path; }
|
public FileReceiver(String path) {
|
||||||
|
this.path = path;
|
||||||
public int receiveFile(InputStream input, String fileName, int fileSize, String key, String iv) {
|
}
|
||||||
BufferedOutputStream bosFile = null;
|
|
||||||
|
|
||||||
|
public int receiveFile(InputStream input, String fileName, long fileSize, String key, String iv) {
|
||||||
try {
|
try {
|
||||||
bosFile = new BufferedOutputStream(new FileOutputStream(String.format("%s/%s", path, fileName)));
|
File file = new File(String.format("%s/%s", path, fileName));
|
||||||
|
if (file.createNewFile()) {
|
||||||
AES_GCM.encryptStream(input, bosFile, fileSize, key, iv);
|
try (BufferedOutputStream bufferedStream = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||||
|
// AES close l'outputstream mais on le try with ressources au cas ou ;)
|
||||||
bosFile.flush();
|
AES_GCM.encryptStream(input, bufferedStream, fileSize, key, iv);
|
||||||
bosFile.close();
|
}
|
||||||
|
}
|
||||||
File f = new File(String.format("%s/%s", path, fileName));
|
return (int) file.length(); // TODO change the size to LONG
|
||||||
return (int)f.length();
|
} catch (IOException | AES_GCM.AesGcmException ex) {
|
||||||
} catch(IOException | AES_GCM.AesGcmException ex) {
|
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
if(bosFile != null) { try { bosFile.close(); } catch(Exception e) {} }
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean receiveFile(InputStream input, String fileName, long fileSize) {
|
||||||
|
int bytesReceived = 0;
|
||||||
|
BufferedOutputStream bosFile = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
bosFile = new BufferedOutputStream(new FileOutputStream(String.format("%s/%s", path, fileName)));
|
||||||
|
long currentOffset = 0;
|
||||||
|
|
||||||
|
while ((currentOffset < fileSize) && ((bytesReceived = input.read(buffer)) > 0)) {
|
||||||
|
bosFile.write(buffer, 0, bytesReceived);
|
||||||
|
currentOffset += bytesReceived;
|
||||||
|
}
|
||||||
|
bosFile.flush();
|
||||||
|
bosFile.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
if (bosFile != null) {
|
||||||
|
try {
|
||||||
|
bosFile.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,53 +3,49 @@ package lightcontainer.utils;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
public class FileSender {
|
public class FileSender {
|
||||||
private static final int DEFAULT_BUFFER=8000;
|
private static final int DEFAULT_BUFFER = 8000;
|
||||||
private final String path;
|
private final String path;
|
||||||
|
|
||||||
public FileSender(String path) { this.path = path; }
|
public FileSender(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean sendFile(String filename, OutputStream out, int fileSize, String aesKey, String iv) {
|
public boolean sendFile(String filename, OutputStream out, long fileSize, String aesKey, String iv) throws IOException {
|
||||||
BufferedInputStream bisFile;
|
BufferedInputStream bisFile;
|
||||||
System.out.printf("Envoie fichier : %s - %s - %s \n", filename, aesKey, iv);
|
|
||||||
try {
|
try {
|
||||||
File f = new File(String.format("%s/%s", path, filename));
|
File f = new File(String.format("%s/%s", path, filename));
|
||||||
if(f.exists()) {
|
if (f.exists()) {
|
||||||
bisFile = new BufferedInputStream(new FileInputStream(f));
|
bisFile = new BufferedInputStream(new FileInputStream(f));
|
||||||
|
|
||||||
AES_GCM.decryptStream(bisFile, out, fileSize, aesKey, iv);
|
AES_GCM.decryptStream(bisFile, out, fileSize, aesKey, iv);
|
||||||
|
|
||||||
bisFile.close();
|
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
} catch(IOException | AES_GCM.AesGcmException ex) {
|
} catch (IOException | AES_GCM.AesGcmException ex) {
|
||||||
ex.printStackTrace();
|
throw new IOException();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean sendFile(String filename, OutputStream out) {
|
public boolean sendFile(String filename, OutputStream out) throws IOException {
|
||||||
BufferedInputStream bisFile;
|
BufferedInputStream bisFile;
|
||||||
int bytesReaded = 0;
|
int bytesRead = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
File f = new File(String.format("%s/%s", path, filename));
|
File file = new File(String.format("%s/%s", path, filename));
|
||||||
long fileSize = f.length();
|
long fileSize = file.length();
|
||||||
if(f.exists()) {
|
if (file.exists()) {
|
||||||
byte[] buffer = new byte[DEFAULT_BUFFER];
|
byte[] buffer = new byte[DEFAULT_BUFFER];
|
||||||
bisFile = new BufferedInputStream(new FileInputStream(f));
|
bisFile = new BufferedInputStream(new FileInputStream(file));
|
||||||
long currentOffset = 0;
|
long currentOffset = 0;
|
||||||
while((currentOffset < fileSize) && (bytesReaded = bisFile.read(buffer)) > 0) {
|
while ((currentOffset < fileSize) && (bytesRead = bisFile.read(buffer)) > 0) {
|
||||||
out.write(buffer, 0, bytesReaded); out.flush();
|
out.write(buffer, 0, bytesRead);
|
||||||
currentOffset+= bytesReaded;
|
out.flush();
|
||||||
|
currentOffset += bytesRead;
|
||||||
}
|
}
|
||||||
bisFile.close();
|
bisFile.close();
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
} catch(IOException ex) {
|
} catch (IOException ex) {// todo change
|
||||||
ex.printStackTrace();
|
throw ex;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
app/src/main/java/lightcontainer/utils/Log.java
Normal file
35
app/src/main/java/lightcontainer/utils/Log.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package lightcontainer.utils;
|
||||||
|
|
||||||
|
public class Log {
|
||||||
|
|
||||||
|
public void infoln(String msg) {
|
||||||
|
System.out.println(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void infoln(int msg) {
|
||||||
|
System.out.println(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void infoln(long msg) {
|
||||||
|
System.out.println(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void infoln(Object msg) {
|
||||||
|
System.out.println(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void infof(String msg, Object... data) {
|
||||||
|
System.out.printf(msg, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Log instance;
|
||||||
|
|
||||||
|
public static Log getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new Log();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,15 +13,18 @@ public class NetChooser {
|
|||||||
|
|
||||||
public NetChooser() {
|
public NetChooser() {
|
||||||
loadInterfaces();
|
loadInterfaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkInterface requestInterface() {
|
||||||
Scanner console = new Scanner(System.in);
|
Scanner console = new Scanner(System.in);
|
||||||
String[] allInterfaceNames = getInterfaces();
|
String[] allInterfaceNames = getInterfaces();
|
||||||
for(int index=0; index < allInterfaceNames.length; ++index) {
|
for (int index = 0; index < allInterfaceNames.length; ++index) {
|
||||||
System.out.printf("%d. %s\n", index, allInterfaceNames[index]);
|
Log.getInstance().infof("%d. %s\n", index, allInterfaceNames[index]);
|
||||||
}
|
}
|
||||||
System.out.printf("Select your interface :");
|
Log.getInstance().infof("Select your interface :");
|
||||||
NetworkInterface selected = getInterfacesByIndex(console.nextInt());
|
NetworkInterface selected = getInterfacesByIndex(console.nextInt());
|
||||||
System.out.printf("Selected interface: %s\n", selected.getDisplayName());
|
Log.getInstance().infof("Selected interface: %s\n", selected.getDisplayName());
|
||||||
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadInterfaces() {
|
private void loadInterfaces() {
|
||||||
@ -32,38 +35,35 @@ public class NetChooser {
|
|||||||
NetworkInterface currentInterface = discoveredInterfaces.nextElement();
|
NetworkInterface currentInterface = discoveredInterfaces.nextElement();
|
||||||
Enumeration<InetAddress> inetAddresses = currentInterface.getInetAddresses();
|
Enumeration<InetAddress> inetAddresses = currentInterface.getInetAddresses();
|
||||||
int ipCount = 0;
|
int ipCount = 0;
|
||||||
while(inetAddresses.hasMoreElements()) {
|
while (inetAddresses.hasMoreElements()) {
|
||||||
InetAddress currentAddress = inetAddresses.nextElement();
|
InetAddress currentAddress = inetAddresses.nextElement();
|
||||||
ipCount++;
|
ipCount++;
|
||||||
}
|
}
|
||||||
if(ipCount > 0)
|
if (ipCount > 0)
|
||||||
interfaces.add(currentInterface);
|
interfaces.add(currentInterface);
|
||||||
}
|
}
|
||||||
} catch(SocketException ex) {
|
} catch (SocketException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkInterface getInterfacesByIndex(int i) {
|
public NetworkInterface getInterfacesByIndex(int i) {
|
||||||
if(i >= 0)
|
if (i >= 0)
|
||||||
return interfaces.get(i);
|
return interfaces.get(i);
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getInterfaces() {
|
public String[] getInterfaces() {
|
||||||
if(interfaces.size() > 0) {
|
if (interfaces.size() > 0) {
|
||||||
String[] result = new String[interfaces.size()];
|
String[] result = new String[interfaces.size()];
|
||||||
for (int i = 0; i < interfaces.size(); ++i) {
|
for (int i = 0; i < interfaces.size(); ++i) {
|
||||||
result[i] = interfaces.get(i).getDisplayName();
|
result[i] = interfaces.get(i).getDisplayName() + " --> " + interfaces.get(i).getName();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else
|
} else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
new NetChooser();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -3,53 +3,29 @@ package lightcontainer.utils;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SHA 256 Hashing and borrowing Class [DO NOT EDIT]
|
* SHA 256 Hashing and borrowing Class [DO NOT EDIT]
|
||||||
*
|
*
|
||||||
* @since 1.0
|
|
||||||
* @version 1.0
|
|
||||||
*
|
|
||||||
* @author Jérémi Nihart <contact@endmove.eu>
|
* @author Jérémi Nihart <contact@endmove.eu>
|
||||||
|
* @version 1.0
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public class SHA {
|
public class SHA {
|
||||||
// Constants
|
// Constants
|
||||||
public static final String SHA_VERSION = "SHA-256";
|
public static final String SHA_VERSION = "SHA-256";
|
||||||
|
|
||||||
// Main method for testing
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
/*
|
|
||||||
* BORROWING ENCRYPTION DEMO
|
|
||||||
*/
|
|
||||||
File inFile = new File("D:\\HELMo.txt");
|
|
||||||
System.out.println(hashStream(
|
|
||||||
new FileInputStream(inFile),
|
|
||||||
(int)inFile.length()
|
|
||||||
));
|
|
||||||
|
|
||||||
System.out.println(hashFile( // caca5439dc02f2ced5094e95f1a3403d42127cda29feecd2eb1c68ff38a6fee3
|
|
||||||
"D:\\ffe",
|
|
||||||
"46ba86ddecd2fe80c3bdb9fb2f9480b4c92057447e9d1b43863dd1a6d540f3a316571684f9e3a7459f533a9792d4925e"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a borrowing of the stream.
|
* Make a borrowing of the stream.
|
||||||
*
|
*
|
||||||
* @param in InputStream to the input, flux to hash.
|
* @param in InputStream to the input, flux to hash.
|
||||||
* @param fileSize Stream/file size.
|
* @param fileSize Stream/file size.
|
||||||
*
|
* @return Borrowing of the full current flux.
|
||||||
* @return Borrowing of the full current flux.
|
* @throws ShaException if an error occur.
|
||||||
*
|
|
||||||
* @throws ShaException if an error occur.
|
|
||||||
*/
|
*/
|
||||||
public static String hashStream(InputStream in, int fileSize) throws ShaException {
|
public static String hashStream(InputStream in, long fileSize) throws ShaException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int currentSize = 0;
|
int currentSize = 0;
|
||||||
@ -58,7 +34,7 @@ public class SHA {
|
|||||||
// Init Digest algo
|
// Init Digest algo
|
||||||
MessageDigest digest = MessageDigest.getInstance(SHA_VERSION);
|
MessageDigest digest = MessageDigest.getInstance(SHA_VERSION);
|
||||||
// Process flux
|
// Process flux
|
||||||
while ((currentSize < fileSize) && (bytes=in.read(buffer)) > 0) {
|
while ((currentSize < fileSize) && (bytes = in.read(buffer)) > 0) {
|
||||||
digest.update(buffer, 0, bytes);
|
digest.update(buffer, 0, bytes);
|
||||||
currentSize += bytes;
|
currentSize += bytes;
|
||||||
}
|
}
|
||||||
@ -77,17 +53,19 @@ public class SHA {
|
|||||||
/**
|
/**
|
||||||
* Make a borrowing of the file.
|
* Make a borrowing of the file.
|
||||||
*
|
*
|
||||||
* @param rootPath Root path of the file.
|
* @param rootPath Root path of the file.
|
||||||
* @param fileName File Name.
|
* @param fileName File Name.
|
||||||
*
|
* @return Borrowing of the file.
|
||||||
* @return Borrowing of the file.
|
* @throws ShaException if an error occur.
|
||||||
*
|
|
||||||
* @throws ShaException if an error occur.
|
|
||||||
*/
|
*/
|
||||||
public static String hashFile(String rootPath, String fileName) throws ShaException {
|
public static String hashFile(String rootPath, String fileName) throws ShaException {
|
||||||
try {
|
try {
|
||||||
File file = new File(String.format("%s/%s", rootPath, fileName));
|
File file = new File(String.format("%s/%s", rootPath, fileName));
|
||||||
return hashStream(new FileInputStream(file), (int)file.length());
|
String hash;
|
||||||
|
try (InputStream inStream = new FileInputStream(file)) {
|
||||||
|
hash = hashStream(inStream, file.length());
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ShaException(e);
|
throw new ShaException(e);
|
||||||
}
|
}
|
||||||
@ -105,11 +83,10 @@ public class SHA {
|
|||||||
* which propagates the error triggering
|
* which propagates the error triggering
|
||||||
* a crash of the hash system.
|
* a crash of the hash system.
|
||||||
*
|
*
|
||||||
* @param e Previous exception throwable.
|
* @param e Previous exception throwable.
|
||||||
*/
|
*/
|
||||||
public ShaException(Throwable e) {
|
public ShaException(Throwable e) {
|
||||||
super(e);
|
super(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1 +1,10 @@
|
|||||||
{"unicast_port":8000,"multicast_ip":"226.66.66.1","multicast_port":15502,"network_interface":"My network interface","tls":true,"storagePath":"/home/benjamin/ffe","users":[{"name":"endmove","password":"1f82407cace28cd7d97d23f82e8235d9da97575d033a12334fc71d3517f6a90fa04af829df3c722c38d3b68842e4ca2b","aes_key":"p0G+iViPp656O6aMKgcXSDT/e9/00wQH/ztUWf4tyr4=","passwordSalt":"ItYiXkwPa84Gwb6dGHQvXQ==","files":[]},{"name":"aaaaa","password":"5d628c274ebb008324f1e199d3bfff0a3fe839730a7f2355e82850d7acca5e5ca64db9071abf3d91034295695f84a617","aes_key":"qlTH6TijnfMRnrS0Qf+k6IPKGp5LoRMXGxCq16e+mF4=","passwordSalt":"Ns8Al6DpqPsIDlCSRBVTEg==","files":[{"name":"ca.crt","fileNameSalt":"Mjo7iQeEl2PYX1RDUZbSlQ==","size":4207,"iv":"uALI+Feo1lIg1lBxbCMwIQ==","storage":["lightcontainerSB01"]},{"name":"main.py","fileNameSalt":"YRwnBiXINCJ+zyxwADgNRQ==","size":854,"iv":"9LXrJFtcgU4DeUBghc4Dgw==","storage":["lightcontainerSB01"]}]}]}
|
{
|
||||||
|
"unicast_port": 8000,
|
||||||
|
"multicast_ip": "224.66.66.1",
|
||||||
|
"multicast_port": 15502,
|
||||||
|
"network_interface": "Mon interface réseau",
|
||||||
|
"tls": true,
|
||||||
|
"storagePath": "Chemin vers le dossier FFE",
|
||||||
|
"users": [
|
||||||
|
]
|
||||||
|
}
|
@ -1,22 +1,23 @@
|
|||||||
//Standardized definitions
|
//Standardized definitions
|
||||||
digit = [0-9]
|
digit = [\x30-\x39] //Unicode
|
||||||
port = (6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4})
|
port = (6553[\x30-\x35])|(655[\x30-\x32][\x30-\x39])|(65[\x30-\x34][\x30-\x32]{2})|(6[\x30-\x34][\x30-\x39]{3})|([\x31-\x35][\x30-\x39]{4})|([\x30-\x35]{0,5})|([\x30-\x39]{1,4})
|
||||||
size = [0-9]{1,10}
|
size = [\x30-\x39]{1,10}
|
||||||
line = \r\n
|
line = \x0D\x0A
|
||||||
visiblechar = \p{Print}
|
visiblechar = [\x20-\xFF]
|
||||||
passchar = [^ !]
|
passchar = [\x22-\xFF]
|
||||||
binary = .
|
binary = [\x00-\xFF]
|
||||||
password = [^ !]{5,50}
|
password = [\x22-\xFF]{5,50}
|
||||||
bl = //espace
|
bl = \x20 //espace
|
||||||
letter = [A-Za-z]
|
letter = [\x41-\x5A\x61-\x7A]
|
||||||
digit_letter = [A-Za-z0-9]
|
digit_letter = [\x30-\x39]|[\x41-\x5A\x61-\x7A]
|
||||||
filename = [^ !]{1,20}
|
filename = [\x22-\xFF]{1,20}
|
||||||
domain = [A-Za-z0-9.]{5,20}
|
domain = [\x30-\x39\x41-\x5A\x61-\x7A]{5,20}[.] //Le point est obligatoire
|
||||||
hash_filename = [A-Za-z0-9.]{50,200}
|
hash_filename = [\x30-\x39\x41-\x5A\x61-\x7A]{50,200}
|
||||||
hash_filecontent = [A-Za-z0-9.]{50,200}
|
hash_filecontent = [\x30-\x39\x41-\x5A\x61-\x7A]{50,200}
|
||||||
file_info = [A-Za-z0-9.]{50,200} [0-9]{1,10} [A-Za-z0-9.]{50,200}
|
file_info = [\x30-\x39\x41-\x5A\x61-\x7A]{50,200}\x20[\x30-\x39]{1,10}\x20[\x30-\x39\x41-\x5A\x61-\x7A]{50,200}
|
||||||
login = [A-Za-z0-9]{2,20}
|
login = [\x30-\x39\x41-\x5A\x61-\x7A]{5,20}
|
||||||
|
|
||||||
|
//OBSOLETE
|
||||||
//StorBackEnd to FileFrontEnd
|
//StorBackEnd to FileFrontEnd
|
||||||
sbe_hello = ^HELLO ([A-Za-z0-9.]{5,20}) ([\d]{0,5})\r\n$ //TODO \r\n -> à tester pour voir si déjà dans le flux ou doit être construit
|
sbe_hello = ^HELLO ([A-Za-z0-9.]{5,20}) ([\d]{0,5})\r\n$ //TODO \r\n -> à tester pour voir si déjà dans le flux ou doit être construit
|
||||||
|
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
package lightcontainer;
|
package lightcontainer;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class AppTest {
|
class AppTest {
|
||||||
// @Test void appHasAGreeting() {
|
// @Test void appHasAGreeting() {
|
||||||
// App classUnderTest = new App();
|
// App classUnderTest = new App();
|
||||||
|
@ -3,8 +3,6 @@ package lightcontainer.protocol.rules.reader;
|
|||||||
import lightcontainer.protocol.ProtocolReader;
|
import lightcontainer.protocol.ProtocolReader;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class HelloRuleTest {
|
class HelloRuleTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package lightcontainer.protocol.rules.writer;
|
package lightcontainer.protocol.rules.writer;
|
||||||
|
|
||||||
import lightcontainer.protocol.ProtocolWriter;
|
|
||||||
import lightcontainer.protocol.rules.reader.SignoutRule;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class SignoutRuleTest {
|
class SignoutRuleTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
package lightcontainer.storage;
|
package lightcontainer.storage;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class JsonAdapterTests {
|
public class JsonAdapterTests {
|
||||||
/*
|
/*
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,17 +1,5 @@
|
|||||||
package lightcontainer.storage;
|
package lightcontainer.storage;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class RepositoryTests {
|
public class RepositoryTests {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -20,7 +8,7 @@ public class RepositoryTests {
|
|||||||
try {
|
try {
|
||||||
Files.deleteIfExists(Paths.get("src", "test", "resources", "test.json").toAbsolutePath());
|
Files.deleteIfExists(Paths.get("src", "test", "resources", "test.json").toAbsolutePath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("Error while destroying file");
|
Log.getInstance().infoln("Error while destroying file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user