diff --git a/Jenkinsfile b/Jenkinsfile index 644d8db..9e9770e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,10 +7,10 @@ sh 'javac -cp "./src" -d "./bin" $(find . -iname "*.java" -type f) -Xlint:deprecation -encoding UTF8' sh 'echo "BUILDING CLIENT"' sh 'echo Main-Class: clientP2P/ClientP2P > MANIFEST.MF' - sh 'jar -cvmf MANIFEST.MF client.jar $(find . \\( -iname "*.class" -and ! -iwholename "*/serverP2P/*.class" \\) -type f)' + sh 'jar -cvmf MANIFEST.MF client.jar $(find bin/ -maxdepth 1 -mindepth 1 -printf "-C bin %f\n")' sh 'echo "BUILDING SERVER"' - sh 'echo Main-Class: javaProjet2020/Server > MANIFEST.MF' - sh 'jar -cvmf MANIFEST.MF server.jar $(find . \\( -iname "*.class" -and ! -iwholename "*/clientP2P/*.class" \\) -type f)' + sh 'echo Main-Class: serverP2P/ServerP2P > MANIFEST.MF' + sh 'jar -cvmf MANIFEST.MF server.jar $(find bin/ -maxdepth 1 -mindepth 1 -printf "-C bin %f\n")' sh 'tar -zcvf sources.tar.gz src/' } } diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index b160d26..728cd8e 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -33,6 +33,8 @@ import protocolP2P.HashRequest; import protocolP2P.HashResponse; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import tools.HostItem; +import java.util.List; /** Implementation of P2P-JAVA-PROJECT CLIENT * @author Louis Royer @@ -42,10 +44,7 @@ import java.security.NoSuchAlgorithmException; */ public class ClientManagementTCP implements Runnable { private String baseDirectory; - private int TCPPort; - private String host; - private Socket socket; - + private List hostList; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. @@ -53,22 +52,9 @@ public class ClientManagementTCP implements Runnable { * @param host hostname of the server * @param TCPPort the server will listen on this port */ - public ClientManagementTCP(String baseDirectory, String host, int TCPPort) { + public ClientManagementTCP(String baseDirectory, List hostList) { this.baseDirectory = baseDirectory; - this.host = host; - this.TCPPort = TCPPort; - try { - socket = new Socket(InetAddress.getByName(host), TCPPort); - } catch (SocketException e) { - System.err.println("Error: No TCP socket available."); - System.exit(-1); - } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); - System.exit(-1); - } catch (IOException e) { - System.err.println("Error: Cannot create TCP socket"); - System.exit(-1); - } + this.hostList = hostList; } /** Implementation of Runnable @@ -114,11 +100,8 @@ public class ClientManagementTCP implements Runnable { } catch (EmptyFile e) { System.err.println("Error: File is empty"); } finally { - try { - System.err.println("Closing socket"); - socket.close(); - } catch (IOException e2) { - System.err.println("Error: cannot close socket"); + for (HostItem h: hostList) { + h.closeTCPSocket(); } } } @@ -145,7 +128,7 @@ public class ClientManagementTCP implements Runnable { HashAlgorithm[] hashesAlgo = new HashAlgorithm[1]; hashesAlgo[0] = HashAlgorithm.SHA512; ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new HashRequest(filename, hashesAlgo)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getTCPSocket()); try { Payload pHash = d.receiveResponse().getPayload(); assert pHash instanceof HashResponse : "This payload must be instance of HashResponse"; @@ -164,7 +147,7 @@ public class ClientManagementTCP implements Runnable { } d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getTCPSocket()); boolean fileFullyWritten = false; long offset = 0; do { @@ -194,7 +177,7 @@ public class ClientManagementTCP implements Runnable { if (offset != fp.getTotalSize()) { System.err.println("Sending following request with offset: " + offset + " maxpartialsize: " + MAX_PARTIAL_SIZE); d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getTCPSocket()); } else { fileFullyWritten = true; } @@ -214,7 +197,7 @@ public class ClientManagementTCP implements Runnable { } else { // next partialContentRequest d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getTCPSocket()); } } else { @@ -242,7 +225,7 @@ public class ClientManagementTCP implements Runnable { System.err.println(""); throw new InternalError(); } - socket.close(); + hostList.get(0).closeTCPSocket(); } /** list server’s directory content @@ -262,7 +245,7 @@ public class ClientManagementTCP implements Runnable { */ private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, SocketClosed, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getTCPSocket()); try { Payload p = d.receiveResponse().getPayload(); assert p instanceof FileList : "This payload must be instance of Filelist"; diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index 83b3d7b..095e8ed 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -12,15 +12,17 @@ import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import java.net.UnknownHostException; import java.util.Scanner; -import java.net.InetAddress; +//import java.net.InetAddress; import java.net.DatagramSocket; -import java.net.SocketException; +//import java.net.SocketException; import java.io.IOException; import java.nio.file.Files; import java.io.File; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.Arrays; +import java.util.List; +import tools.HostItem; import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; @@ -41,44 +43,30 @@ import java.security.NoSuchAlgorithmException; */ public class ClientManagementUDP implements Runnable { private String baseDirectory; - private int UDPPort; - private String host; - private DatagramSocket socket; - - + private List hostList; /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. * @param baseDirectory the root directory where files are stored * @param host hostname of the server * @param UDPPort the server will listen on this port */ - public ClientManagementUDP(String baseDirectory, String host, int UDPPort) { + public ClientManagementUDP(String baseDirectory, List hostList) { this.baseDirectory = baseDirectory; - this.host = host; - this.UDPPort = UDPPort; - try { - socket = new DatagramSocket(); - socket.connect(InetAddress.getByName(host), UDPPort); - } catch (SocketException e) { - System.err.println("Error: No UDP socket available."); - System.exit(-1); - } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); - System.exit(-1); - } + this.hostList = hostList; } /** Implementation of Runnable */ public void run() { try { + System.out.println("Enter all servers: type \"stop\" when finished"); + Scanner scanner = new Scanner(System.in); String[] list = listDirectory(); System.out.println("Files present on the server:"); for(String listItem: list) { System.out.println(listItem); } System.out.println("Name of the file to download:"); - Scanner scanner = new Scanner(System.in); String f = scanner.nextLine(); download(f); System.out.println("File sucessfully downloaded"); @@ -132,7 +120,7 @@ public class ClientManagementUDP implements Runnable { HashAlgorithm[] hashesAlgo = new HashAlgorithm[1]; hashesAlgo[0] = HashAlgorithm.SHA512; ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new HashRequest(filename, hashesAlgo)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getUDPSocket()); try { Payload pHash = d.receiveResponse().getPayload(); assert pHash instanceof HashResponse : "This payload must be instance of HashResponse"; @@ -151,7 +139,7 @@ public class ClientManagementUDP implements Runnable { } d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getUDPSocket()); boolean fileFullyWritten = false; long offset = 0; do { @@ -181,7 +169,7 @@ public class ClientManagementUDP implements Runnable { if (offset != fp.getTotalSize()) { System.err.println("Sending following request with offset: " + offset + " maxpartialsize: " + MAX_PARTIAL_SIZE); d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getUDPSocket()); } else { fileFullyWritten = true; } @@ -201,7 +189,7 @@ public class ClientManagementUDP implements Runnable { } else { // next partialContentRequest d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getUDPSocket()); } } else { @@ -247,7 +235,7 @@ public class ClientManagementUDP implements Runnable { */ private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); - d.sendRequest((Object)socket); + d.sendRequest((Object)hostList.get(0).getUDPSocket()); try { Payload p = d.receiveResponse().getPayload(); assert p instanceof FileList : "This payload must be instance of Filelist"; diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index c8ee8a9..f5ab3db 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -3,17 +3,25 @@ import clientP2P.ClientManagementUDP; import clientP2P.ClientManagementTCP; import tools.Directories; import java.util.Scanner; +import java.util.List; +import tools.HostItem; +import tools.HostList; public class ClientP2P { private String host; private int port; private Directories directories; + private List hostList; + private String parts = ".parts"; public ClientP2P() { directories = new Directories("P2P_JAVA_PROJECT_CLIENT"); + directories.createSubdir(parts); host = "localhost"; port = 40001; System.out.println("Client will try to contact server at " + host + " on port " + port + ". It will save files in " + directories.getDataHomeDirectory()); directories.askOpenDataHomeDirectory(null); + System.out.println("Please enter list of servers to use; first one will be used to ask list of files"); + hostList = HostList.getServList(); } public static void main(String [] args) { @@ -27,7 +35,7 @@ public class ClientP2P { case "udp": case "2" : System.out.println("Starting with UDP"); - ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.host, c.port); + ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.hostList); t = new Thread(cmudp); break; case "TCP": @@ -35,7 +43,7 @@ public class ClientP2P { case "1": default: System.out.println("Starting with TCP"); - ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.host, c.port); + ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.hostList); t = new Thread(cmtcp); break; } diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java new file mode 100644 index 0000000..ffe2f58 --- /dev/null +++ b/src/tools/HostItem.java @@ -0,0 +1,88 @@ +package tools; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.Socket; +import java.net.DatagramSocket; +import java.net.UnknownHostException; +import java.io.IOException; + +/** Class to store hostnames + ports +* @author Louis Royer +* @author Flavien Haas +* @author JS Auge +* @version 1.0 +*/ +public class HostItem { + private String hostname; + private int port; + private Socket tcpSocket; + private DatagramSocket udpSocket; + + /** Constructor with hostname and port + * @param hostname Hostname + * @param port Port + */ + public HostItem(String hostname, int port) { + this.port = port; + this.hostname = hostname; + } + + /** Get TCP Socket. + * @return TCP Socket + */ + public Socket getTCPSocket() { + if (tcpSocket == null) { + try { + tcpSocket = new Socket(InetAddress.getByName(hostname), port); + } catch (SocketException e) { + System.err.println("Error: No TCP socket available."); + System.exit(-1); + } catch (UnknownHostException e) { + System.err.println("Error: Unknown host."); + System.exit(-1); + } catch (IOException e) { + System.err.println("Error: Cannot create TCP socket"); + System.exit(-1); + } + } + return tcpSocket; + } + + /** Closes tcp socket + */ + public void closeTCPSocket() { + if (tcpSocket != null) { + try { + tcpSocket.close(); + } catch (IOException e2) { + System.err.println("Error: cannot close socket"); + } + } + tcpSocket = null; + } + + /** Get UDP Socket + * return UDP Socket + */ + public DatagramSocket getUDPSocket() { + if (udpSocket == null) { + try { + udpSocket = new DatagramSocket(); + udpSocket.connect(InetAddress.getByName(hostname), port); + } catch (SocketException e) { + System.err.println("Error: No UDP socket available."); + System.exit(-1); + } catch (UnknownHostException e) { + System.err.println("Error: Unknown host."); + System.exit(-1); + } + } + return udpSocket; + } + public void closeUDPSocket() { + if (udpSocket != null) { + udpSocket.close(); + } + udpSocket = null; + } +} diff --git a/src/tools/HostList.java b/src/tools/HostList.java new file mode 100644 index 0000000..510e3ba --- /dev/null +++ b/src/tools/HostList.java @@ -0,0 +1,55 @@ +package tools; + +import java.util.Scanner; +import java.util.ArrayList; +import java.util.List; +import java.util.InputMismatchException; +import tools.HostItem; + +/** Helper to get the server list from the user +* @author Louis Royer +* @author Flavien Haas +* @author JS Auge +* @version 1.0 +*/ +public class HostList { + /** + * Let the user enter all server and puts it in a list + * @return list of servers + */ + public static List getServList() { + List serverList = new ArrayList(); + Scanner scanner = new Scanner(System.in); + String servName; + int port = 0; + do { + System.out.println("Enter hostname of next server: (or \"stop\" when finished, default: localhost)."); + servName = scanner.nextLine(); + if (servName.equals("")) { + servName = "localhost"; + } + if (!servName.equals("stop")) { + boolean err = false; + do { + System.out.println("Enter port for this server"); + try { + port = scanner.nextInt(); + scanner.nextLine(); + if (port > 65535 || port <= 0) { + err = true; + System.out.println("Port number must be in 1-65535 range. Try again."); + } else { + err = false; + } + } catch (InputMismatchException e) { + System.out.println("Invalid number. Try again."); + err = true; + } + } while (err); + serverList.add(new HostItem(servName, port)); + } + + } while (!servName.equals("stop")); + return serverList; + } +}