package es.um.redes.nanoFiles.logic; import java.net.InetSocketAddress; import java.net.ServerSocket; 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; import es.um.redes.nanoFiles.util.FileInfo; 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 * */ try { fileServer = new NFServer(); ServerSocket serverSocket = fileServer.getServerSocket(); if (serverSocket.isBound()) { System.out.println("Server socket listening on port " + serverSocket.getLocalPort()); serverRunning = true; } Thread mainServerThread = new Thread(fileServer); mainServerThread.start(); } catch (IOException e) { e.printStackTrace(); System.err.println("Cannot start the file server"); fileServer = null; } } 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)); // meter la ip como primer argumento a InetSocketAddress() 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; try { NFConnector nfc = new NFConnector(peerAddr); FileInfo[] filelist = nfc.getFileList(); if (filelist == null) return success; System.out.println("Files available in peer: "); FileInfo.printToSysout(filelist); success = true; } catch (IOException e) {} 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 NFServer.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; } }