Files
nanofiles/es/um/redes/nanoFiles/logic/NFControllerLogicDir.java

213 lines
7.1 KiB
Java

package es.um.redes.nanoFiles.logic;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import es.um.redes.nanoFiles.application.NanoFiles;
import es.um.redes.nanoFiles.udp.client.DirectoryConnector;
import es.um.redes.nanoFiles.util.FileInfo;
public class NFControllerLogicDir {
// Conector para enviar y recibir mensajes del directorio
private DirectoryConnector directoryConnector;
/**
* Construye el controlador encargado de implementar la lógica de los comandos
* que requieren interactuar con el servidor de directorio dado a través de la
* clase DirectoryConnector.
*
* @param directoryHostname el nombre de host/IP en el que se está ejecutando el
* directorio
*/
protected NFControllerLogicDir(String directoryHostname) {
try {
directoryConnector = new DirectoryConnector(directoryHostname);
} catch (IOException e1) {
System.err.println(
"* Check your connection, the directory server at " + directoryHostname + " is not available.");
System.exit(-1);
}
}
/**
* Método para comprobar que la comunicación con el directorio es exitosa (se
* pueden enviar y recibir datagramas) haciendo uso de la clase
* DirectoryConnector
*
* @return true si se ha conseguido contactar con el directorio.
*/
protected void testCommunicationWithDirectory() {
assert (NanoFiles.testModeUDP);
System.out.println(
"[testMode] Testing communication with directory: " + this.directoryConnector.getDirectoryHostname());
/*
* Utiliza el DirectoryConnector para hacer una prueba de comunicación con el
* directorio. Primero testSendAndReceive envía un mensaje "ping" y espera
* obtener "welcome" como respuesta. Luego pingDirectoryRaw hace lo mismo que
* testSendAndReceive pero enviando además el "protocol ID" para ver si el
* directorio es compatible
*/
if (directoryConnector.testSendAndReceive()) {
System.out.println("[testMode] testSendAndReceived - TEST PASSED!");
/*
* (Boletín EstructuraNanoFiles) Test similar al de testSendAndReceive, pero
* ampliado para comprobar si el directorio es compatible con el protocol ID,
* usando para la comunicación mensajes "en crudo" (sin un formato bien
* definido).
*/
if (directoryConnector.pingDirectoryRaw()) {
System.out.println("[testMode] pingDirectoryRaw - SUCCESS!");
} else {
System.err.println("[testMode] pingDirectoryRaw - FAILED!");
}
} else {
System.err.println("[testMode] testSendAndReceived - TEST FAILED!");
}
}
/**
* Método para comprobar el directorio utiliza un protocolo compatible
*
* @return true si se ha conseguido contactar con el directorio.
*/
protected boolean ping() {
boolean result = false;
System.out.println(
"* Checking if the directory at " + directoryConnector.getDirectoryHostname() + " is available...");
result = directoryConnector.pingDirectory();
if (result) {
System.out.println("* Directory is active and uses compatible protocol " + NanoFiles.PROTOCOL_ID);
} else {
System.err.println("* Ping failed");
}
return result;
}
/**
* Método para obtener y mostrar la lista de ficheros alojados en el directorio
*/
protected void getAndPrintFileList() {
FileInfo[] trackedFiles = directoryConnector.getFileList(); //
System.out.println(
"* These are the files tracked by the directory at " + directoryConnector.getDirectoryHostname());
FileInfo.printToSysout(trackedFiles);
}
/**
* Método para obtener y mostrar el censo de pares servidor registrados en el
* directorio
*/
protected void getAndPrintPeerList() {
Map<String, InetSocketAddress> peers = directoryConnector.getPeerList();
System.out.println("* Registered peers at " + directoryConnector.getDirectoryHostname());
if (peers.isEmpty()) {
System.out.println(" (none)");
return;
}
for (Map.Entry<String, InetSocketAddress> entry : peers.entrySet()) {
System.out.println(" - " + entry.getKey() + " @ " + entry.getValue());
}
}
/**
* Método para obtener el listado de pares servidor registrados en el directorio
*/
protected Map<String, InetSocketAddress> fetchPeerList() {
return directoryConnector.getPeerList();
}
/**
* Método para registrarse en el directorio como servidor de ficheros en un
* puerto determinado. Si el nickname ya está registrado, el directorio debe
* devolver el nuevo nickname asignado a este peer durante el registro.
*
* @param serverPort El puerto TCP en el que está escuchando el servidor de
* ficheros.
* @return Verdadero si el registro se hace con éxito
*/
protected boolean registerFileServer(int serverPort) {
boolean result = false;
if (this.directoryConnector.registerFileServer(serverPort)) {
System.out.println("* File server successfully registered with the directory");
result = true;
} else {
System.err.println("* File server failed to register with the directory");
}
return result;
}
/**
* Método para descargar un fichero del directorio y guardarlo con su nombre
* remoto, añadiendo sufijos si hay colisión.
*/
protected boolean downloadAndSaveFromDirectory(String hashSubstring) {
DirectoryConnector.DownloadedFile dl = directoryConnector.downloadFileFromDirectory(hashSubstring);
if (dl == null) {
System.err.println("* Failed to download file given by hash substring " + hashSubstring);
return false;
}
try {
java.nio.file.Path dest = es.um.redes.nanoFiles.util.FileNameUtil.chooseAvailableName(dl.filename);
java.nio.file.Files.write(dest, dl.data);
String checksum = es.um.redes.nanoFiles.util.FileDigest.computeFileChecksumString(dest.toString());
System.out.println("* Downloaded directory file to " + toDisplayPath(dest) + " (" + dl.data.length
+ " bytes)");
if (dl.filehash != null) {
if (dl.filehash.equals(checksum)) {
System.out.println("* Checksum verified: computed value matches expected hash (" + checksum + ")");
} else {
System.err.println("* WARNING: computed checksum (" + checksum + ") does not match expected hash ("
+ dl.filehash + ")");
}
} else {
System.out.println("* Computed SHA-256: " + checksum);
}
return true;
} catch (java.io.IOException e) {
System.err.println("* Failed to write downloaded file: " + e.getMessage());
return false;
}
}
/**
* Método para dar de baja a nuestro servidor de ficheros en el directorio.
*
* @return Éxito o fracaso de la operación
*/
protected boolean unregisterFileServer() {
boolean result = false;
if (this.directoryConnector.unregisterFileServer()) {
System.out.println("* File server successfully unregistered with the directory");
result = true;
} else {
System.err.println("* File server failed to unregister with the directory");
}
return result;
}
protected String getDirectoryHostname() {
return directoryConnector.getDirectoryHostname();
}
private String toDisplayPath(java.nio.file.Path path) {
java.nio.file.Path abs = path.toAbsolutePath().normalize();
java.nio.file.Path cwd = java.nio.file.Paths.get("").toAbsolutePath().normalize();
if (abs.startsWith(cwd)) {
return cwd.relativize(abs).toString();
}
return path.toString();
}
}