mirror of
https://github.com/binlaab/nanofiles.git
synced 2026-07-01 13:47:41 +02:00
práctica 3, falta la última parte
This commit is contained in:
299
es/um/redes/nanoFiles/logic/NFController.java
Normal file
299
es/um/redes/nanoFiles/logic/NFController.java
Normal file
@@ -0,0 +1,299 @@
|
||||
package es.um.redes.nanoFiles.logic;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import es.um.redes.nanoFiles.application.NanoFiles;
|
||||
import es.um.redes.nanoFiles.shell.NFCommands;
|
||||
import es.um.redes.nanoFiles.shell.NFShell;
|
||||
import es.um.redes.nanoFiles.util.FileInfo;
|
||||
|
||||
public class NFController {
|
||||
/**
|
||||
* Diferentes estados del cliente de acuerdo con el autómata
|
||||
*/
|
||||
private static final byte OFFLINE = 0;
|
||||
/*
|
||||
* TODO: (Boletín Autómatas) Añadir más constantes que representen los estados
|
||||
* del autómata del cliente de directorio.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Shell para leer comandos de usuario de la entrada estándar
|
||||
*/
|
||||
private NFShell shell;
|
||||
/**
|
||||
* Último comando proporcionado por el usuario
|
||||
*/
|
||||
private byte currentCommand;
|
||||
|
||||
/**
|
||||
* Objeto controlador encargado de la comunicación con el directorio
|
||||
*/
|
||||
private NFControllerLogicDir controllerDir;
|
||||
/**
|
||||
* Objeto controlador encargado de la comunicación con otros peers (como
|
||||
* servidor o cliente)
|
||||
*/
|
||||
private NFControllerLogicP2P controllerPeer;
|
||||
|
||||
/**
|
||||
* El estado en que se encuentra este peer (según el autómata). El estado debe
|
||||
* actualizarse cuando se produce un evento (comando) que supone un cambio en el
|
||||
* autómata.
|
||||
*/
|
||||
private byte currentState;
|
||||
/**
|
||||
* Atributos donde se establecen los argumentos pasados a los distintos comandos
|
||||
* del shell. Estos atributos se establecen automáticamente según la orden y se
|
||||
* deben usar para pasar los valores de los parámetros a las funciones invocadas
|
||||
* desde este controlador.
|
||||
*/
|
||||
private String targetHashSubstring; // Nombre del fichero a descargar
|
||||
private String targetPeerNickname; // Nickname para listar ficheros de un peer (peerfiles)
|
||||
private String newNickname; // Nuevo nickname solicitado por el usuario
|
||||
|
||||
// Constructor
|
||||
public NFController(String defaultDirectory) {
|
||||
shell = new NFShell();
|
||||
|
||||
String directory = shell.chooseDirectory(defaultDirectory);
|
||||
|
||||
controllerDir = new NFControllerLogicDir(directory);
|
||||
controllerPeer = new NFControllerLogicP2P();
|
||||
// Estado inicial del autómata
|
||||
currentState = OFFLINE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Método que procesa los comandos introducidos por un usuario. Se encarga
|
||||
* principalmente de invocar los métodos adecuados de NFControllerLogicDir y
|
||||
* NFControllerLogicP2P según el comando.
|
||||
*/
|
||||
public void testCommunication() {
|
||||
assert (NanoFiles.testModeUDP);
|
||||
System.out
|
||||
.println("[testMode] Attempting to reach directory server at " + controllerDir.getDirectoryHostname());
|
||||
controllerDir.testCommunicationWithDirectory();
|
||||
System.out.println("[testMode] Test terminated!");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Método que procesa los comandos introducidos por un usuario. Se encarga
|
||||
* principalmente de invocar los métodos adecuados de NFControllerLogicDir y
|
||||
* NFControllerLogicP2P según el comando.
|
||||
*/
|
||||
public void processCommand() {
|
||||
|
||||
if (!canProcessCommandInCurrentState()) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* En función del comando, invocar los métodos adecuados de NFControllerLogicDir
|
||||
* y NFControllerLogicP2P, ya que son estas dos clases las que implementan
|
||||
* realmente la lógica de cada comando y procesan la información recibida
|
||||
* mediante la comunicación con el directorio u otros pares de NanoFiles
|
||||
* (imprimir por pantalla el resultado de la acción y los datos recibidos,
|
||||
* etc.).
|
||||
*/
|
||||
boolean commandSucceeded = false;
|
||||
switch (currentCommand) {
|
||||
case NFCommands.COM_MYFILES:
|
||||
showMyLocalFiles(); // Muestra los ficheros en el directorio local compartido
|
||||
break;
|
||||
case NFCommands.COM_PING:
|
||||
/*
|
||||
* Pedir al controllerDir enviar un "ping" al directorio, para comprobar que
|
||||
* está activo y disponible, y comprobar que es compatible.
|
||||
*/
|
||||
commandSucceeded = controllerDir.ping();
|
||||
break;
|
||||
case NFCommands.COM_FILELIST_DIR:
|
||||
/*
|
||||
* Pedir al controllerDir que obtenga del directorio la lista de ficheros que
|
||||
* tiene, y la imprima por pantalla
|
||||
*/
|
||||
controllerDir.getAndPrintFileList();
|
||||
break;
|
||||
case NFCommands.COM_PEERLIST:
|
||||
/*
|
||||
* Pedir al controllerDir que obtenga del directorio la lista de pares que están
|
||||
* sirviendo ficheros y la imprima por pantalla.
|
||||
*/
|
||||
controllerDir.getAndPrintPeerList();
|
||||
break;
|
||||
case NFCommands.COM_FILELIST_PEER:
|
||||
/*
|
||||
* Pedir al controllerDir que obtenga del directorio la lista de pares que están
|
||||
* sirviendo ficheros, y luego pedir al controllerPeer que obtenga la lista de
|
||||
* ficheros que tiene disponible el peer dado por "targetPeerNickname"
|
||||
*/
|
||||
java.util.Map<String, InetSocketAddress> peers = controllerDir.fetchPeerList();
|
||||
InetSocketAddress peerAddr = peers.get(targetPeerNickname);
|
||||
if (peerAddr == null) {
|
||||
System.err.println("* Peer '" + targetPeerNickname + "' not found in directory");
|
||||
break;
|
||||
}
|
||||
commandSucceeded = controllerPeer.listPeerFiles(peerAddr);
|
||||
break;
|
||||
case NFCommands.COM_DOWNLOAD_PEER:
|
||||
commandSucceeded = controllerPeer.downloadFromPeers(controllerDir, targetPeerNickname,
|
||||
targetHashSubstring);
|
||||
break;
|
||||
case NFCommands.COM_SERVE:
|
||||
/*
|
||||
* Pedir al controllerPeer que lance un servidor de ficheros. Si el servidor se
|
||||
* ha podido iniciar correctamente, pedir al controllerDir darnos de alta como
|
||||
* servidor de ficheros en el directorio, indicando el puerto en el que nuestro
|
||||
* servidor escucha conexiones de otros peers así como la lista de ficheros
|
||||
* disponibles.
|
||||
*/
|
||||
if (NanoFiles.testModeTCP) {
|
||||
controllerPeer.testTCPServer();
|
||||
} else {
|
||||
boolean serverRunning = controllerPeer.startFileServer();
|
||||
if (serverRunning) {
|
||||
commandSucceeded = controllerDir.registerFileServer(controllerPeer.getServerPort());
|
||||
} else {
|
||||
System.err.println("Cannot start file server");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NFCommands.COM_DOWNLOAD_DIR:
|
||||
/*
|
||||
* Descargar directamente un fichero pequeño servido por el directorio (carpeta
|
||||
* dir-shared), identificado por subcadena de hash. Solo se descarga si el
|
||||
* tamaño cabe en un datagrama (lo asegura el servidor al responder).
|
||||
*/
|
||||
commandSucceeded = controllerDir.downloadAndSaveFromDirectory(targetHashSubstring);
|
||||
break;
|
||||
case NFCommands.COM_QUIT:
|
||||
/*
|
||||
* Pedir al controllerPeer que pare el servidor en segundo plano (método método
|
||||
* stopBackgroundFileServer). A continuación, pedir al controllerDir que
|
||||
* solicite al directorio darnos de baja como servidor de ficheros (método
|
||||
* unregisterFileServer).
|
||||
*/
|
||||
if (controllerPeer.serving()) {
|
||||
controllerPeer.stopFileServer();
|
||||
commandSucceeded = controllerDir.unregisterFileServer();
|
||||
}
|
||||
break;
|
||||
case NFCommands.COM_NICK:
|
||||
if (controllerPeer.serving()) {
|
||||
System.err.println("* Cannot change nickname while serving files. Stop the server first.");
|
||||
break;
|
||||
}
|
||||
if (newNickname == null || newNickname.isBlank()) {
|
||||
System.err.println("* Invalid nickname");
|
||||
break;
|
||||
}
|
||||
NanoFiles.peerNickname = newNickname;
|
||||
System.out.println("* Nickname changed to: " + NanoFiles.peerNickname);
|
||||
commandSucceeded = true;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
updateCurrentState(commandSucceeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Método que comprueba si se puede procesar un comando introducidos por un
|
||||
* usuario, en función del estado del autómata en el que nos encontramos.
|
||||
*/
|
||||
private boolean canProcessCommandInCurrentState() {
|
||||
/*
|
||||
* TODO: (Boletín Autómatas) Para cada comando tecleado en el shell
|
||||
* (currentCommand), comprobar "currentState" para ver si dicho comando es
|
||||
* válido según el estado actual del autómata, ya que no todos los comandos
|
||||
* serán válidos en cualquier estado. Este método NO debe modificar
|
||||
* clientStatus.
|
||||
*/
|
||||
boolean commandAllowed = true;
|
||||
switch (currentCommand) {
|
||||
case NFCommands.COM_MYFILES: {
|
||||
commandAllowed = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// System.err.println("ERROR: undefined behaviour for " + currentCommand + "
|
||||
// command!");
|
||||
}
|
||||
return commandAllowed;
|
||||
}
|
||||
|
||||
private void updateCurrentState(boolean success) {
|
||||
/*
|
||||
* TODO: (Boletín Autómatas) Si el comando ha sido procesado con éxito, debemos
|
||||
* actualizar currentState de acuerdo con el autómata diseñado para pasar al
|
||||
* siguiente estado y así permitir unos u otros comandos en cada caso.
|
||||
*/
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
switch (currentCommand) {
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void showMyLocalFiles() {
|
||||
System.out.println("List of files in local folder:");
|
||||
FileInfo.printToSysout(NanoFiles.db.getFiles());
|
||||
}
|
||||
|
||||
/**
|
||||
* Método que comprueba si el usuario ha introducido el comando para salir de la
|
||||
* aplicación
|
||||
*/
|
||||
public boolean shouldQuit() {
|
||||
return currentCommand == NFCommands.COM_QUIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establece el comando actual
|
||||
*
|
||||
* @param command el comando tecleado en el shell
|
||||
*/
|
||||
private void setCurrentCommand(byte command) {
|
||||
currentCommand = command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registra en atributos internos los posibles parámetros del comando tecleado
|
||||
* por el usuario.
|
||||
*/
|
||||
private void setCurrentCommandArguments(String[] args) {
|
||||
switch (currentCommand) {
|
||||
case NFCommands.COM_DOWNLOAD_DIR:
|
||||
targetHashSubstring = args[0];
|
||||
break;
|
||||
case NFCommands.COM_DOWNLOAD_PEER:
|
||||
targetPeerNickname = args[0];
|
||||
targetHashSubstring = args[1];
|
||||
break;
|
||||
case NFCommands.COM_FILELIST_PEER:
|
||||
targetPeerNickname = args[0];
|
||||
break;
|
||||
case NFCommands.COM_NICK:
|
||||
newNickname = args[0];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Método para leer un comando general
|
||||
*/
|
||||
public void readGeneralCommandFromShell() {
|
||||
// Pedimos el comando al shell
|
||||
shell.readGeneralCommand();
|
||||
// Establecemos que el comando actual es el que ha obtenido el shell
|
||||
setCurrentCommand(shell.getCommand());
|
||||
// Analizamos los posibles parámetros asociados al comando
|
||||
setCurrentCommandArguments(shell.getCommandArguments());
|
||||
}
|
||||
|
||||
}
|
||||
212
es/um/redes/nanoFiles/logic/NFControllerLogicDir.java
Normal file
212
es/um/redes/nanoFiles/logic/NFControllerLogicDir.java
Normal file
@@ -0,0 +1,212 @@
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
208
es/um/redes/nanoFiles/logic/NFControllerLogicP2P.java
Normal file
208
es/um/redes/nanoFiles/logic/NFControllerLogicP2P.java
Normal file
@@ -0,0 +1,208 @@
|
||||
package es.um.redes.nanoFiles.logic;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.io.IOException;
|
||||
import es.um.redes.nanoFiles.tcp.client.NFConnector;
|
||||
import es.um.redes.nanoFiles.application.NanoFiles;
|
||||
|
||||
|
||||
|
||||
import es.um.redes.nanoFiles.tcp.server.NFServer;
|
||||
|
||||
public class NFControllerLogicP2P {
|
||||
// Servidor TCP local para compartir ficheros con otros peers
|
||||
private NFServer fileServer = null;
|
||||
|
||||
|
||||
|
||||
protected NFControllerLogicP2P() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Método para ejecutar un servidor de ficheros en segundo plano. Debe arrancar
|
||||
* el servidor en un nuevo hilo creado a tal efecto.
|
||||
*
|
||||
* @return Verdadero si se ha arrancado en un nuevo hilo con el servidor de
|
||||
* ficheros, y está a la escucha en un puerto, falso en caso contrario.
|
||||
*
|
||||
*/
|
||||
protected boolean startFileServer() {
|
||||
boolean serverRunning = false;
|
||||
/*
|
||||
* Comprobar que no existe ya un objeto NFServer previamente creado, en cuyo
|
||||
* caso el servidor ya está en marcha.
|
||||
*/
|
||||
if (fileServer != null) {
|
||||
System.err.println("File server is already running");
|
||||
} else {
|
||||
/*
|
||||
* TODO: (Boletín Servidor TCP concurrente) Arrancar servidor en segundo plano
|
||||
* creando un nuevo hilo, comprobar que el servidor está escuchando en un puerto
|
||||
* válido (>0), imprimir mensaje informando sobre el puerto de escucha, y
|
||||
* devolver verdadero. Las excepciones que puedan lanzarse deben ser capturadas
|
||||
* y tratadas en este método. Si se produce una excepción de entrada/salida
|
||||
* (error del que no es posible recuperarse), se debe informar sin abortar el
|
||||
* programa
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
return serverRunning;
|
||||
|
||||
}
|
||||
|
||||
protected void testTCPServer() {
|
||||
assert (NanoFiles.testModeTCP);
|
||||
/*
|
||||
* Comprobar que no existe ya un objeto NFServer previamente creado, en cuyo
|
||||
* caso el servidor ya está en marcha.
|
||||
*/
|
||||
assert (fileServer == null);
|
||||
try {
|
||||
|
||||
fileServer = new NFServer();
|
||||
/*
|
||||
* (Boletín SocketsTCP) Inicialmente, se creará un NFServer y se ejecutará su
|
||||
* método "test" (servidor minimalista en primer plano, que sólo puede atender a
|
||||
* un cliente conectado). Posteriormente, se desactivará "testModeTCP" para
|
||||
* implementar un servidor en segundo plano, que se ejecute en un hilo
|
||||
* secundario para permitir que este hilo (principal) siga procesando comandos
|
||||
* introducidos mediante el shell.
|
||||
*/
|
||||
fileServer.test();
|
||||
// Este código es inalcanzable: el método 'test' nunca retorna...
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
System.err.println("Cannot start the file server");
|
||||
fileServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void testTCPClient() {
|
||||
|
||||
assert (NanoFiles.testModeTCP);
|
||||
/*
|
||||
* (Boletín SocketsTCP) Inicialmente, se creará un NFConnector (cliente TCP)
|
||||
* para conectarse a un servidor que esté escuchando en la misma máquina y un
|
||||
* puerto fijo. Después, se ejecutará el método "test" para comprobar la
|
||||
* comunicación mediante el socket TCP. Posteriormente, se desactivará
|
||||
* "testModeTCP" para implementar la descarga de un fichero desde múltiples
|
||||
* servidores.
|
||||
*/
|
||||
|
||||
try {
|
||||
NFConnector nfConnector = new NFConnector(new InetSocketAddress(NFServer.PORT));
|
||||
nfConnector.test();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Método para listar los ficheros de un peer concreto vía TCP e imprimirlos por
|
||||
* pantalla.
|
||||
*
|
||||
* @param La dirección del peer cuyos ficheros se quiere listar
|
||||
* @return Verdadero si se ha obtenido exitosamente el listado de fichero del
|
||||
* peer
|
||||
*/
|
||||
protected boolean listPeerFiles(InetSocketAddress peerAddr) {
|
||||
boolean success = false;
|
||||
|
||||
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Descarga un fichero identificado por subcadena de hash desde uno o varios
|
||||
* peers. Si se pasa "*" como nickname, usa el directorio para localizar los
|
||||
* peers que tienen el hash.
|
||||
*/
|
||||
protected boolean downloadFromPeers(NFControllerLogicDir dirLogic, String targetPeerNickname,
|
||||
String targetHashSubstring) {
|
||||
// TODO: localizar peers con el hash solicitado (o uno concreto) y delegar en
|
||||
// downloadFileFromServers
|
||||
boolean success = false;
|
||||
|
||||
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Método para descargar un fichero del peer servidor de ficheros
|
||||
*
|
||||
* @param serverAddressList La lista de direcciones de los servidores a los
|
||||
* que se conectará
|
||||
* @param targetHashSubstring Subcadena del hash del fichero a descargar
|
||||
*/
|
||||
protected boolean downloadFileFromServers(InetSocketAddress[] serverAddressList, String targetHashSubstring) {
|
||||
boolean downloaded = false;
|
||||
|
||||
if (serverAddressList.length == 0) {
|
||||
System.err.println("* Cannot start download - No list of server addresses provided");
|
||||
return false;
|
||||
}
|
||||
// TODO: crear conectores TCP solo a los servidores que confirmen el hash
|
||||
// pedido, obtener nombre remoto, reservar nombre local sin colisiones, alternar
|
||||
// descarga de chunks y verificar hash final. Cerrar los sockets al terminar.
|
||||
|
||||
|
||||
|
||||
|
||||
return downloaded;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Método para obtener el puerto de escucha de nuestro servidor de ficheros
|
||||
*
|
||||
* @return El puerto en el que escucha el servidor, o 0 en caso de error.
|
||||
*/
|
||||
protected int getServerPort() {
|
||||
int port = 0;
|
||||
/*
|
||||
* TODO: Devolver el puerto de escucha de nuestro servidor de ficheros
|
||||
*/
|
||||
|
||||
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Método para detener nuestro servidor de ficheros en segundo plano
|
||||
*
|
||||
*/
|
||||
protected void stopFileServer() {
|
||||
/*
|
||||
* TODO: Enviar señal para detener nuestro servidor de ficheros en segundo plano
|
||||
*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected boolean serving() {
|
||||
boolean result = false;
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user