From 740e25546aaed82a86ac32c5ea16c4a33b65ddaa Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 19 Mar 2020 13:48:39 +0100 Subject: [PATCH 01/40] refractor exception -> localexception --- src/clientP2P/ClientDownloadPartTCP.java | 12 ++++++------ src/clientP2P/ClientDownloadPartUDP.java | 14 +++++++------- src/clientP2P/ClientDownloadTCP.java | 12 ++++++------ src/clientP2P/ClientDownloadUDP.java | 18 +++++++++--------- src/clientP2P/ClientManagementTCP.java | 12 ++++++------ src/clientP2P/ClientManagementUDP.java | 10 +++++----- .../InternalError.java | 2 +- .../ProtocolError.java | 2 +- .../SizeError.java | 2 +- .../SocketClosed.java | 2 +- .../TransmissionError.java | 2 +- .../VersionError.java | 2 +- src/protocolP2P/FileList.java | 8 ++++---- src/protocolP2P/FilePart.java | 10 +++++----- src/protocolP2P/HashRequest.java | 12 ++++++------ src/protocolP2P/HashResponse.java | 16 ++++++++-------- src/protocolP2P/LoadRequest.java | 10 +++++----- src/protocolP2P/Payload.java | 14 +++++++------- src/protocolP2P/ProtocolP2PPacket.java | 14 +++++++------- src/protocolP2P/ProtocolP2PPacketTCP.java | 16 ++++++++-------- src/protocolP2P/ProtocolP2PPacketUDP.java | 16 ++++++++-------- src/protocolP2P/RequestResponseCode.java | 8 +++----- src/serverP2P/ServerManagementTCP.java | 18 +++++++++--------- src/serverP2P/ServerManagementUDP.java | 19 +++++++++---------- src/tools/BytesArrayTools.java | 4 ++-- 25 files changed, 126 insertions(+), 129 deletions(-) rename src/{exception => localException}/InternalError.java (80%) rename src/{exception => localException}/ProtocolError.java (80%) rename src/{exception => localException}/SizeError.java (89%) rename src/{exception => localException}/SocketClosed.java (80%) rename src/{exception => localException}/TransmissionError.java (81%) rename src/{exception => localException}/VersionError.java (80%) diff --git a/src/clientP2P/ClientDownloadPartTCP.java b/src/clientP2P/ClientDownloadPartTCP.java index 11a277c..a56b049 100644 --- a/src/clientP2P/ClientDownloadPartTCP.java +++ b/src/clientP2P/ClientDownloadPartTCP.java @@ -6,22 +6,22 @@ import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; import protocolP2P.LoadRequest; import protocolP2P.FilePart; -import exception.InternalError; +import localException.InternalError; import remoteException.EmptyDirectory; import remoteException.EmptyFile; -import exception.ProtocolError; +import localException.ProtocolError; import remoteException.InternalRemoteError; import remoteException.VersionRemoteError; -import exception.TransmissionError; +import localException.TransmissionError; import remoteException.ProtocolRemoteError; -import exception.VersionError; -import exception.SizeError; +import localException.VersionError; +import localException.SizeError; import remoteException.NotFound; import java.nio.file.Files; import java.io.File; import java.nio.file.Paths; import java.io.IOException; -import exception.SocketClosed; +import localException.SocketClosed; /** Class to download file parts on tcp. * @author Louis Royer diff --git a/src/clientP2P/ClientDownloadPartUDP.java b/src/clientP2P/ClientDownloadPartUDP.java index 30c373c..da25d4b 100644 --- a/src/clientP2P/ClientDownloadPartUDP.java +++ b/src/clientP2P/ClientDownloadPartUDP.java @@ -6,16 +6,16 @@ import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.Payload; import protocolP2P.LoadRequest; import protocolP2P.FilePart; -import exception.InternalError; +import localException.InternalError; import remoteException.EmptyDirectory; import remoteException.EmptyFile; -import exception.ProtocolError; +import localException.ProtocolError; import remoteException.InternalRemoteError; import remoteException.VersionRemoteError; -import exception.TransmissionError; +import localException.TransmissionError; import remoteException.ProtocolRemoteError; -import exception.VersionError; -import exception.SizeError; +import localException.VersionError; +import localException.SizeError; import remoteException.NotFound; import java.nio.file.Files; import java.io.File; @@ -165,7 +165,7 @@ public class ClientDownloadPartUDP implements Runnable { if (p == null) { stop = true; } - + failed = downloadPart(p); if (failed) { System.err.println("Error: DownloadPart failed."); @@ -176,7 +176,7 @@ public class ClientDownloadPartUDP implements Runnable { } catch (IndexOutOfBoundsException e) { noTask = true; } - + } } diff --git a/src/clientP2P/ClientDownloadTCP.java b/src/clientP2P/ClientDownloadTCP.java index 442d105..bc80c86 100644 --- a/src/clientP2P/ClientDownloadTCP.java +++ b/src/clientP2P/ClientDownloadTCP.java @@ -16,11 +16,11 @@ import protocolP2P.HashResponse; import protocolP2P.HashRequest; import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; -import exception.ProtocolError; -import exception.InternalError; -import exception.TransmissionError; -import exception.SizeError; -import exception.VersionError; +import localException.ProtocolError; +import localException.InternalError; +import localException.TransmissionError; +import localException.SizeError; +import localException.VersionError; import protocolP2P.FilePart; import protocolP2P.LoadRequest; import java.io.IOException; @@ -29,7 +29,7 @@ import java.io.File; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.StandardCopyOption; -import exception.SocketClosed; +import localException.SocketClosed; /** Class to download file from tcp * @author Louis Royer diff --git a/src/clientP2P/ClientDownloadUDP.java b/src/clientP2P/ClientDownloadUDP.java index 2bd2f29..46a4476 100644 --- a/src/clientP2P/ClientDownloadUDP.java +++ b/src/clientP2P/ClientDownloadUDP.java @@ -16,11 +16,11 @@ import protocolP2P.HashResponse; import protocolP2P.HashRequest; import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.Payload; -import exception.ProtocolError; -import exception.InternalError; -import exception.TransmissionError; -import exception.SizeError; -import exception.VersionError; +import localException.ProtocolError; +import localException.InternalError; +import localException.TransmissionError; +import localException.SizeError; +import localException.VersionError; import protocolP2P.FilePart; import protocolP2P.LoadRequest; import java.io.IOException; @@ -70,7 +70,7 @@ public class ClientDownloadUDP implements Runnable { public void setStop() { stop = true; } - + /** Runnable implementation */ public void run() { @@ -188,7 +188,7 @@ public class ClientDownloadUDP implements Runnable { assert pHash instanceof HashResponse : "This payload must be instance of HashResponse"; if (!(pHash instanceof HashResponse)) { throw new InternalError(); - } else { + } else { hash = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512); } } catch (EmptyDirectory e) { @@ -260,14 +260,14 @@ public class ClientDownloadUDP implements Runnable { private void init() throws InternalError { // get size setSize(); - + // get hashsum from 1st server in list hash512 = getHashSum512(hostList.get(0)); if (hash512.length == 0) { System.err.println("Error: no hash512sum support."); throw new InternalError(); } - + // Add tasks if (!stop) { for(long i=MAX_PARTIAL_SIZE; i= 0 : "totalSize cannot be negative"; - assert partialContent.length != 0 : "partialContent.length cannot be zero, see RRCode.EMPTY_FILE"; + assert partialContent.length != 0 : "partialContent.length cannot be zero, see RRCode.EMPTY_FILE"; assert totalSize >= partialContent.length : "totalSize must be greater than partialContent.length"; assert offset >= 0 : "offset cannot be negative"; assert filename != null : "filename is required"; diff --git a/src/protocolP2P/HashRequest.java b/src/protocolP2P/HashRequest.java index 92ab812..452fd32 100644 --- a/src/protocolP2P/HashRequest.java +++ b/src/protocolP2P/HashRequest.java @@ -2,10 +2,10 @@ package protocolP2P; import protocolP2P.Payload; import protocolP2P.HashAlgorithm; import java.io.UnsupportedEncodingException; -import exception.TransmissionError; -import exception.SizeError; -import exception.ProtocolError; -import exception.InternalError; +import localException.TransmissionError; +import localException.SizeError; +import localException.ProtocolError; +import localException.InternalError; import tools.BytesArrayTools; @@ -21,12 +21,12 @@ public class HashRequest extends Payload { private HashAlgorithm[] algoList; private static final int FILENAME_SIZE_POSITION = PAYLOAD_START_POSITION; private static final int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4; - + /** Constructor (typically used by the server) with a filename parameter. * @param filename name of the file to download. Must not be empty. * @param algoList List of hash algorithms used * @throws InternalError - * + * */ public HashRequest(String filename, HashAlgorithm[] algoList) throws InternalError { super(RequestResponseCode.HASH_REQUEST); diff --git a/src/protocolP2P/HashResponse.java b/src/protocolP2P/HashResponse.java index 2ff0440..769fbd7 100644 --- a/src/protocolP2P/HashResponse.java +++ b/src/protocolP2P/HashResponse.java @@ -3,10 +3,10 @@ import protocolP2P.Payload; import java.util.HashMap; import java.util.Map; import java.io.UnsupportedEncodingException; -import exception.TransmissionError; -import exception.SizeError; -import exception.ProtocolError; -import exception.InternalError; +import localException.TransmissionError; +import localException.SizeError; +import localException.ProtocolError; +import localException.InternalError; import tools.BytesArrayTools; @@ -22,12 +22,12 @@ public class HashResponse extends Payload { private Map hashes = new HashMap<>(); private static final int FILENAME_SIZE_POSITION = PAYLOAD_START_POSITION; private static final int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4; - + /** Constructor (typically used by the server) with a filename parameter. * @param filename name of the file to download. Must not be empty. * @param hashes HashMap containing hashes for file. * @throws InternalError - * + * */ public HashResponse(String filename, Map hashes) throws InternalError { super(RequestResponseCode.HASH_RESPONSE); @@ -80,7 +80,7 @@ public class HashResponse extends Payload { } start += hashSize; } while (start < size); - + } /** Returns a byte[] containing Packet with padding. @@ -100,7 +100,7 @@ public class HashResponse extends Payload { size += 4 + s.length; } byte[] packet = new byte[size + 1]; // java initialize all to zero - + // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; // set Payload size diff --git a/src/protocolP2P/LoadRequest.java b/src/protocolP2P/LoadRequest.java index 4017cb0..251981d 100644 --- a/src/protocolP2P/LoadRequest.java +++ b/src/protocolP2P/LoadRequest.java @@ -1,10 +1,10 @@ package protocolP2P; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; -import exception.TransmissionError; -import exception.ProtocolError; -import exception.InternalError; -import exception.SizeError; +import localException.TransmissionError; +import localException.ProtocolError; +import localException.InternalError; +import localException.SizeError; import tools.BytesArrayTools; import java.io.UnsupportedEncodingException; @@ -61,7 +61,7 @@ public class LoadRequest extends Payload { /* Read maxSizePartialContent */ maxSizePartialContent = BytesArrayTools.readLong(packet, MAX_SIZE_PARTIAL_CONTENT_POSITION); - + /* Read filename */ int size = BytesArrayTools.readInt(packet, FILENAME_SIZE_POSITION); filename = BytesArrayTools.readString(packet, FILENAME_POSITION, size); diff --git a/src/protocolP2P/Payload.java b/src/protocolP2P/Payload.java index cbe9767..f0dcb34 100644 --- a/src/protocolP2P/Payload.java +++ b/src/protocolP2P/Payload.java @@ -5,10 +5,10 @@ import protocolP2P.FileList; import protocolP2P.LoadRequest; import protocolP2P.HashRequest; import protocolP2P.HashResponse; -import exception.ProtocolError; -import exception.InternalError; -import exception.TransmissionError; -import exception.SizeError; +import localException.ProtocolError; +import localException.InternalError; +import localException.TransmissionError; +import localException.SizeError; import tools.BytesArrayTools; /** Representation of payload. If payload has a size, use subclasses instead. * @author Louis Royer @@ -59,7 +59,7 @@ public class Payload { /** Used to check RRCode used is compatible with this class use, or if a more specific subclass is required. * @throws InternalError - */ + */ private void checkRequestResponseCode() throws InternalError { /* Incorrect use cases (use subclasses instead) */ if ((requestResponseCode == RequestResponseCode.LIST_RESPONSE && !(this instanceof FileList)) @@ -68,7 +68,7 @@ public class Payload { throw new InternalError(); } } - + /** Returns a byte[] containing Packet with padding. * This Packet is still incomplete and should not be send directly. * ProtocolP2PPacket will use this method to generate the complete Packet. @@ -90,7 +90,7 @@ public class Payload { * @param size integer representing payload size * @param packet Packet to be completed * @throws InternalError - */ + */ protected static void setPayloadSize(int size, byte[] packet) throws InternalError { /* assert to help debugging */ assert size >= 0: "Payload size cannot be negative"; diff --git a/src/protocolP2P/ProtocolP2PPacket.java b/src/protocolP2P/ProtocolP2PPacket.java index d1298d5..be23aec 100644 --- a/src/protocolP2P/ProtocolP2PPacket.java +++ b/src/protocolP2P/ProtocolP2PPacket.java @@ -1,10 +1,10 @@ package protocolP2P; -import exception.InternalError; -import exception.ProtocolError; -import exception.SizeError; -import exception.TransmissionError; -import exception.VersionError; -import exception.SocketClosed; +import localException.InternalError; +import localException.ProtocolError; +import localException.SizeError; +import localException.TransmissionError; +import localException.VersionError; +import localException.SocketClosed; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; @@ -88,7 +88,7 @@ public abstract class ProtocolP2PPacket { * @throws SizeError */ protected ProtocolP2PPacket(byte[] packet) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError {} - + /** Returns Payload associated with the Packet. * @return payload associated with the Packet. */ diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index 40280d3..7c80474 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -1,10 +1,10 @@ package protocolP2P; -import exception.InternalError; -import exception.ProtocolError; -import exception.SizeError; -import exception.TransmissionError; -import exception.VersionError; -import exception.SocketClosed; +import localException.InternalError; +import localException.ProtocolError; +import localException.SizeError; +import localException.TransmissionError; +import localException.VersionError; +import localException.SocketClosed; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; @@ -30,10 +30,10 @@ import java.net.Socket; * @version 1.0 */ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { - + private Socket responseSocket; // socket used to recept request and send response private Socket requestSocket; // socket used to send request and to reception response - + /** Constructor with payload parameter (typically used when sending packet). * @param payload the payload associated with the packet to send */ diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index a997754..aea6dcc 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -1,10 +1,10 @@ package protocolP2P; -import exception.InternalError; -import exception.ProtocolError; -import exception.SizeError; -import exception.TransmissionError; -import exception.VersionError; -import exception.SocketClosed; +import localException.InternalError; +import localException.ProtocolError; +import localException.SizeError; +import localException.TransmissionError; +import localException.VersionError; +import localException.SocketClosed; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; @@ -31,12 +31,12 @@ import java.io.IOException; * @version 1.0 */ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { - + private final static int CHECKSUM_POSITION = 2; private SocketAddress responseSocketAddress; // socket address used when receptionning request and to sending response private DatagramSocket responseSocket; // socket used to recept request and send response private DatagramSocket requestSocket; // socket used to send request and to reception response - + /** Constructor with payload parameter (typically used when sending packet). * @param payload the payload associated with the packet to send */ diff --git a/src/protocolP2P/RequestResponseCode.java b/src/protocolP2P/RequestResponseCode.java index b69ebb3..a6e68d3 100644 --- a/src/protocolP2P/RequestResponseCode.java +++ b/src/protocolP2P/RequestResponseCode.java @@ -1,6 +1,6 @@ package protocolP2P; import protocolP2P.CodeType; -import exception.ProtocolError; +import localException.ProtocolError; import java.util.HashMap; import java.util.Map; import java.lang.Byte; @@ -24,7 +24,7 @@ public enum RequestResponseCode { EMPTY_DIRECTORY(CodeType.ERROR, (byte)0xC3), NOT_FOUND(CodeType.ERROR, (byte)0xC4), EMPTY_FILE(CodeType.ERROR, (byte)0xC5); - + public final CodeType codeType; public final byte codeValue; protected final static int RRCODE_POSITION = 1; @@ -62,7 +62,5 @@ public enum RequestResponseCode { return r; } - -} - +} diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index e1bc711..257fe3d 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -17,12 +17,12 @@ import protocolP2P.Payload; import protocolP2P.LoadRequest; import protocolP2P.FileList; import protocolP2P.FilePart; -import exception.InternalError; -import exception.ProtocolError; -import exception.SizeError; -import exception.TransmissionError; -import exception.VersionError; -import exception.SocketClosed; +import localException.InternalError; +import localException.ProtocolError; +import localException.SizeError; +import localException.TransmissionError; +import localException.VersionError; +import localException.SocketClosed; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; @@ -106,7 +106,7 @@ public class ServerManagementTCP implements Runnable { /** Implementation of runnable. This method allow to serve one client. */ public void run() { - + boolean end = false; logger.writeTCP(addr + "New connection", LogLevel.Action); do { @@ -176,7 +176,7 @@ public class ServerManagementTCP implements Runnable { private void initSha512() { for(String f: fileList) { try { - MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); + MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); sha512.put(f, md.digest(Files.readAllBytes(Paths.get(baseDirectory + f)))); md.reset(); } catch (NoSuchAlgorithmException e) { @@ -254,7 +254,7 @@ public class ServerManagementTCP implements Runnable { } } } - + /** Send response to load request * @param pd Request received diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index ced8643..c6b3078 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -16,12 +16,12 @@ import protocolP2P.Payload; import protocolP2P.LoadRequest; import protocolP2P.FileList; import protocolP2P.FilePart; -import exception.InternalError; -import exception.ProtocolError; -import exception.SizeError; -import exception.TransmissionError; -import exception.VersionError; -import exception.SocketClosed; +import localException.InternalError; +import localException.ProtocolError; +import localException.SizeError; +import localException.TransmissionError; +import localException.VersionError; +import localException.SocketClosed; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; @@ -116,7 +116,7 @@ public class ServerManagementUDP implements Runnable { for (String f: fileList) { logger.writeUDP("- " + f, LogLevel.Debug); } - + throw new IOException(); // to send a NOT_FOUND in the catch block } } catch (IOException e) { @@ -182,7 +182,7 @@ public class ServerManagementUDP implements Runnable { private void initSha512() { for(String f: fileList) { try { - MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); + MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); sha512.put(f, md.digest(Files.readAllBytes(Paths.get(baseDirectory + f)))); md.reset(); } catch (NoSuchAlgorithmException e) { @@ -192,7 +192,7 @@ public class ServerManagementUDP implements Runnable { } } } - + /** Send an internal error message. * @param pd ProtocolP2PPacketUDP to respond */ @@ -245,4 +245,3 @@ public class ServerManagementUDP implements Runnable { } } - diff --git a/src/tools/BytesArrayTools.java b/src/tools/BytesArrayTools.java index c11088c..8f80fcb 100644 --- a/src/tools/BytesArrayTools.java +++ b/src/tools/BytesArrayTools.java @@ -1,6 +1,6 @@ package tools; -import exception.SizeError; -import exception.ProtocolError; +import localException.SizeError; +import localException.ProtocolError; import java.io.UnsupportedEncodingException; import java.util.Arrays; From 05be51d604bdeb07edf109054eac9ae4ad1a336f Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 19 Mar 2020 14:05:58 +0100 Subject: [PATCH 02/40] added motherclass for exceptions --- src/exception/localException.java | 5 +++++ src/exception/remoteException.java | 5 +++++ src/localException/InternalError.java | 5 ++++- src/localException/ProtocolError.java | 5 ++++- src/localException/SizeError.java | 6 +++++- src/localException/SocketClosed.java | 5 ++++- src/localException/TransmissionError.java | 5 ++++- src/localException/VersionError.java | 5 ++++- src/remoteException/EmptyDirectory.java | 5 ++++- src/remoteException/EmptyFile.java | 5 ++++- src/remoteException/InternalRemoteError.java | 5 ++++- src/remoteException/NotFound.java | 5 ++++- src/remoteException/ProtocolRemoteError.java | 5 ++++- src/remoteException/VersionRemoteError.java | 5 ++++- 14 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 src/exception/localException.java create mode 100644 src/exception/remoteException.java diff --git a/src/exception/localException.java b/src/exception/localException.java new file mode 100644 index 0000000..868d366 --- /dev/null +++ b/src/exception/localException.java @@ -0,0 +1,5 @@ +package exception; + +public class localException extends Exception { + private static final long serialVersionUID = 12L; +} diff --git a/src/exception/remoteException.java b/src/exception/remoteException.java new file mode 100644 index 0000000..2eb7251 --- /dev/null +++ b/src/exception/remoteException.java @@ -0,0 +1,5 @@ +package exception; + +public class remoteException extends Exception { + private static final long serialVersionUID = 12L; +} diff --git a/src/localException/InternalError.java b/src/localException/InternalError.java index 43628c1..c9c4f38 100644 --- a/src/localException/InternalError.java +++ b/src/localException/InternalError.java @@ -1,4 +1,7 @@ package localException; -public class InternalError extends Exception { + +import exception.localException; + +public class InternalError extends exception.localException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/ProtocolError.java b/src/localException/ProtocolError.java index 1c74a89..41f3b55 100644 --- a/src/localException/ProtocolError.java +++ b/src/localException/ProtocolError.java @@ -1,4 +1,7 @@ package localException; -public class ProtocolError extends Exception { + +import exception.localException; + +public class ProtocolError extends exception.localException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SizeError.java b/src/localException/SizeError.java index 29abc88..d579101 100644 --- a/src/localException/SizeError.java +++ b/src/localException/SizeError.java @@ -1,5 +1,9 @@ package localException; + +import exception.localException; + + /** Used on reception side when size as set in Packet is too big, and we cant store this in a int/long as usual. */ -public class SizeError extends Exception { +public class SizeError extends exception.localException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SocketClosed.java b/src/localException/SocketClosed.java index 3c87d7b..b3a0859 100644 --- a/src/localException/SocketClosed.java +++ b/src/localException/SocketClosed.java @@ -1,4 +1,7 @@ package localException; -public class SocketClosed extends Exception { + +import exception.localException; + +public class SocketClosed extends exception.localException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/TransmissionError.java b/src/localException/TransmissionError.java index 11437ae..b6628d5 100644 --- a/src/localException/TransmissionError.java +++ b/src/localException/TransmissionError.java @@ -1,4 +1,7 @@ package localException; -public class TransmissionError extends Exception { + +import exception.localException; + +public class TransmissionError extends exception.localException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/VersionError.java b/src/localException/VersionError.java index 12ec48c..f2e1502 100644 --- a/src/localException/VersionError.java +++ b/src/localException/VersionError.java @@ -1,4 +1,7 @@ package localException; -public class VersionError extends Exception { + +import exception.localException; + +public class VersionError extends exception.localException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/EmptyDirectory.java b/src/remoteException/EmptyDirectory.java index 5d4f765..d778779 100644 --- a/src/remoteException/EmptyDirectory.java +++ b/src/remoteException/EmptyDirectory.java @@ -1,4 +1,7 @@ package remoteException; -public class EmptyDirectory extends Exception { + +import exception.remoteException; + +public class EmptyDirectory extends exception.remoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/EmptyFile.java b/src/remoteException/EmptyFile.java index deba543..5c802a1 100644 --- a/src/remoteException/EmptyFile.java +++ b/src/remoteException/EmptyFile.java @@ -1,4 +1,7 @@ package remoteException; -public class EmptyFile extends Exception { + +import exception.remoteException; + +public class EmptyFile extends exception.remoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/InternalRemoteError.java b/src/remoteException/InternalRemoteError.java index c3d5c57..1b9298c 100644 --- a/src/remoteException/InternalRemoteError.java +++ b/src/remoteException/InternalRemoteError.java @@ -1,4 +1,7 @@ package remoteException; -public class InternalRemoteError extends Exception { + +import exception.remoteException; + +public class InternalRemoteError extends exception.remoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/NotFound.java b/src/remoteException/NotFound.java index 8f9d27e..c58b61e 100644 --- a/src/remoteException/NotFound.java +++ b/src/remoteException/NotFound.java @@ -1,4 +1,7 @@ package remoteException; -public class NotFound extends Exception { + +import exception.remoteException; + +public class NotFound extends exception.remoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/ProtocolRemoteError.java b/src/remoteException/ProtocolRemoteError.java index fbc857f..c396a98 100644 --- a/src/remoteException/ProtocolRemoteError.java +++ b/src/remoteException/ProtocolRemoteError.java @@ -1,4 +1,7 @@ package remoteException; -public class ProtocolRemoteError extends Exception { + +import exception.remoteException; + +public class ProtocolRemoteError extends exception.remoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/VersionRemoteError.java b/src/remoteException/VersionRemoteError.java index 8da9c1a..a39001f 100644 --- a/src/remoteException/VersionRemoteError.java +++ b/src/remoteException/VersionRemoteError.java @@ -1,4 +1,7 @@ package remoteException; -public class VersionRemoteError extends Exception { + +import exception.remoteException; + +public class VersionRemoteError extends exception.remoteException { private static final long serialVersionUID = 12L; } From 2a4ad8316fce095cd9e69f0e85cc9c5f184ea5d0 Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 19 Mar 2020 14:26:39 +0100 Subject: [PATCH 03/40] rename exceptions to accomodate java's nomenclature --- src/exception/{localException.java => LocalException.java} | 2 +- src/exception/{remoteException.java => RemoteException.java} | 2 +- src/localException/InternalError.java | 4 ++-- src/localException/ProtocolError.java | 4 ++-- src/localException/SizeError.java | 4 ++-- src/localException/SocketClosed.java | 4 ++-- src/localException/TransmissionError.java | 4 ++-- src/localException/VersionError.java | 4 ++-- src/remoteException/EmptyDirectory.java | 4 ++-- src/remoteException/EmptyFile.java | 4 ++-- src/remoteException/InternalRemoteError.java | 4 ++-- src/remoteException/NotFound.java | 4 ++-- src/remoteException/ProtocolRemoteError.java | 4 ++-- src/remoteException/VersionRemoteError.java | 4 ++-- 14 files changed, 26 insertions(+), 26 deletions(-) rename src/exception/{localException.java => LocalException.java} (60%) rename src/exception/{remoteException.java => RemoteException.java} (59%) diff --git a/src/exception/localException.java b/src/exception/LocalException.java similarity index 60% rename from src/exception/localException.java rename to src/exception/LocalException.java index 868d366..5c115d5 100644 --- a/src/exception/localException.java +++ b/src/exception/LocalException.java @@ -1,5 +1,5 @@ package exception; -public class localException extends Exception { +public class LocalException extends Exception { private static final long serialVersionUID = 12L; } diff --git a/src/exception/remoteException.java b/src/exception/RemoteException.java similarity index 59% rename from src/exception/remoteException.java rename to src/exception/RemoteException.java index 2eb7251..cfb2cd7 100644 --- a/src/exception/remoteException.java +++ b/src/exception/RemoteException.java @@ -1,5 +1,5 @@ package exception; -public class remoteException extends Exception { +public class RemoteException extends Exception { private static final long serialVersionUID = 12L; } diff --git a/src/localException/InternalError.java b/src/localException/InternalError.java index c9c4f38..08326f9 100644 --- a/src/localException/InternalError.java +++ b/src/localException/InternalError.java @@ -1,7 +1,7 @@ package localException; -import exception.localException; +import exception.LocalException; -public class InternalError extends exception.localException { +public class InternalError extends exception.LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/ProtocolError.java b/src/localException/ProtocolError.java index 41f3b55..8a8be52 100644 --- a/src/localException/ProtocolError.java +++ b/src/localException/ProtocolError.java @@ -1,7 +1,7 @@ package localException; -import exception.localException; +import exception.LocalException; -public class ProtocolError extends exception.localException { +public class ProtocolError extends exception.LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SizeError.java b/src/localException/SizeError.java index d579101..cb927bc 100644 --- a/src/localException/SizeError.java +++ b/src/localException/SizeError.java @@ -1,9 +1,9 @@ package localException; -import exception.localException; +import exception.LocalException; /** Used on reception side when size as set in Packet is too big, and we cant store this in a int/long as usual. */ -public class SizeError extends exception.localException { +public class SizeError extends exception.LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SocketClosed.java b/src/localException/SocketClosed.java index b3a0859..ceaac40 100644 --- a/src/localException/SocketClosed.java +++ b/src/localException/SocketClosed.java @@ -1,7 +1,7 @@ package localException; -import exception.localException; +import exception.LocalException; -public class SocketClosed extends exception.localException { +public class SocketClosed extends exception.LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/TransmissionError.java b/src/localException/TransmissionError.java index b6628d5..38fca4f 100644 --- a/src/localException/TransmissionError.java +++ b/src/localException/TransmissionError.java @@ -1,7 +1,7 @@ package localException; -import exception.localException; +import exception.LocalException; -public class TransmissionError extends exception.localException { +public class TransmissionError extends exception.LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/VersionError.java b/src/localException/VersionError.java index f2e1502..c0cb7d4 100644 --- a/src/localException/VersionError.java +++ b/src/localException/VersionError.java @@ -1,7 +1,7 @@ package localException; -import exception.localException; +import exception.LocalException; -public class VersionError extends exception.localException { +public class VersionError extends exception.LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/EmptyDirectory.java b/src/remoteException/EmptyDirectory.java index d778779..12fce76 100644 --- a/src/remoteException/EmptyDirectory.java +++ b/src/remoteException/EmptyDirectory.java @@ -1,7 +1,7 @@ package remoteException; -import exception.remoteException; +import exception.RemoteException; -public class EmptyDirectory extends exception.remoteException { +public class EmptyDirectory extends exception.RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/EmptyFile.java b/src/remoteException/EmptyFile.java index 5c802a1..cbc580f 100644 --- a/src/remoteException/EmptyFile.java +++ b/src/remoteException/EmptyFile.java @@ -1,7 +1,7 @@ package remoteException; -import exception.remoteException; +import exception.RemoteException; -public class EmptyFile extends exception.remoteException { +public class EmptyFile extends exception.RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/InternalRemoteError.java b/src/remoteException/InternalRemoteError.java index 1b9298c..802ee05 100644 --- a/src/remoteException/InternalRemoteError.java +++ b/src/remoteException/InternalRemoteError.java @@ -1,7 +1,7 @@ package remoteException; -import exception.remoteException; +import exception.RemoteException; -public class InternalRemoteError extends exception.remoteException { +public class InternalRemoteError extends exception.RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/NotFound.java b/src/remoteException/NotFound.java index c58b61e..f8002bc 100644 --- a/src/remoteException/NotFound.java +++ b/src/remoteException/NotFound.java @@ -1,7 +1,7 @@ package remoteException; -import exception.remoteException; +import exception.RemoteException; -public class NotFound extends exception.remoteException { +public class NotFound extends exception.RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/ProtocolRemoteError.java b/src/remoteException/ProtocolRemoteError.java index c396a98..c0c6161 100644 --- a/src/remoteException/ProtocolRemoteError.java +++ b/src/remoteException/ProtocolRemoteError.java @@ -1,7 +1,7 @@ package remoteException; -import exception.remoteException; +import exception.RemoteException; -public class ProtocolRemoteError extends exception.remoteException { +public class ProtocolRemoteError extends exception.RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/VersionRemoteError.java b/src/remoteException/VersionRemoteError.java index a39001f..775d9cb 100644 --- a/src/remoteException/VersionRemoteError.java +++ b/src/remoteException/VersionRemoteError.java @@ -1,7 +1,7 @@ package remoteException; -import exception.remoteException; +import exception.RemoteException; -public class VersionRemoteError extends exception.remoteException { +public class VersionRemoteError extends exception.RemoteException { private static final long serialVersionUID = 12L; } From c5f63795d05f6882d2daef42fc811684a4e5afeb Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 19 Mar 2020 17:49:39 +0100 Subject: [PATCH 04/40] added logs to the client --- src/clientP2P/ClientDownloadPartTCP.java | 55 ++++++++++++--- src/clientP2P/ClientDownloadPartUDP.java | 31 ++++++++- src/clientP2P/ClientDownloadTCP.java | 85 +++++++++++++++++++----- src/clientP2P/ClientDownloadUDP.java | 82 ++++++++++++++++++----- src/clientP2P/ClientManagementTCP.java | 59 +++++++++++----- src/clientP2P/ClientManagementUDP.java | 58 +++++++++++----- src/clientP2P/ClientP2P.java | 30 +++++---- 7 files changed, 310 insertions(+), 90 deletions(-) diff --git a/src/clientP2P/ClientDownloadPartTCP.java b/src/clientP2P/ClientDownloadPartTCP.java index 40d7c47..e6635cd 100644 --- a/src/clientP2P/ClientDownloadPartTCP.java +++ b/src/clientP2P/ClientDownloadPartTCP.java @@ -2,26 +2,28 @@ package clientP2P; import java.util.List; import java.util.ArrayList; import java.net.Socket; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; import protocolP2P.LoadRequest; import protocolP2P.FilePart; import localException.InternalError; +import localException.ProtocolError; +import localException.TransmissionError; +import localException.VersionError; +import localException.SizeError; +import localException.SocketClosed; import remoteException.EmptyDirectory; import remoteException.EmptyFile; -import localException.ProtocolError; import remoteException.InternalRemoteError; import remoteException.VersionRemoteError; -import localException.TransmissionError; import remoteException.ProtocolRemoteError; -import localException.VersionError; -import localException.SizeError; import remoteException.NotFound; -import java.nio.file.Files; -import java.io.File; -import java.nio.file.Paths; -import java.io.IOException; -import localException.SocketClosed; +import tools.Logger; +import tools.LogLevel; /** Class to download file parts on tcp. * @author Louis Royer @@ -43,17 +45,19 @@ public class ClientDownloadPartTCP implements Runnable { private String partsSubdir; private static final long MAX_PARTIAL_SIZE = 4096; private ClientDownloadTCP manager; + private Logger logger; /** Constructor with filename, socket, and part subdir * @param filename name of file to download * @param socket socket to use * @param partsSubdir directory to store .part files */ - public ClientDownloadPartTCP(ClientDownloadTCP manager, String filename, Socket socket, String partsSubdir) { + public ClientDownloadPartTCP(ClientDownloadTCP manager, String filename, Socket socket, String partsSubdir, Logger logger) { this.manager = manager; this.partsSubdir = partsSubdir; this.filename = filename; this.socket = socket; + this.logger = logger; stop = false; failed = false; pendingTasks = new ArrayList<>(); @@ -97,10 +101,12 @@ public class ClientDownloadPartTCP implements Runnable { } } System.err.println("Closing socket"); + logger.writeTCP("Closing socket", LogLevel.Info); try{ socket.close(); } catch(IOException e){ System.err.println("can't close socket"); + logger.writeTCP("can't close socket", LogLevel.Error); } } @@ -174,11 +180,13 @@ public class ClientDownloadPartTCP implements Runnable { failed = downloadPart(p); if (failed) { System.err.println("Error: DownloadPart failed."); + logger.writeTCP("DownloadPart failed.", LogLevel.Error); stop = true; } else if (toDoTasks.isEmpty()) { noTask = true; } } catch (IndexOutOfBoundsException e) { + logger.writeTCP(e, LogLevel.Error); noTask = true; } @@ -190,7 +198,8 @@ public class ClientDownloadPartTCP implements Runnable { * @return ProtocolP2PPacketTCP used to send request */ private ProtocolP2PPacketTCP reqPart(Long offset) { - System.err.println("New request: "+ offset); + System.err.println("New request: " + offset); + logger.writeTCP("New request: " + offset, LogLevel.Info); // maintain tracking of tasks if (toDoTasks.contains(offset)) { try { @@ -206,10 +215,12 @@ public class ClientDownloadPartTCP implements Runnable { } } catch(InterruptedException e) { System.err.println("Error: reqPart interruptedException"); + logger.writeTCP("reqPart interruptedException", LogLevel.Error); return null; } } else { System.err.println("Error: reqPart (offset " + offset + " not in toDoTasks)"); + logger.writeTCP("reqPart (offset " + offset + " not in toDoTasks)", LogLevel.Error); return null; } // send request @@ -219,13 +230,16 @@ public class ClientDownloadPartTCP implements Runnable { return d; } catch (InternalError e) { System.err.println("Error: reqPart internalError"); + logger.writeTCP("reqPart internalError", LogLevel.Error); return null; } catch (IOException e) { e.printStackTrace(); System.err.println("Error: reqPart ioexception"); + logger.writeTCP("reqPart ioexception", LogLevel.Error); return null; } catch (SocketClosed e){ System.err.println("Error: reqPart SocketClosed"); + logger.writeTCP("reqPart SocketClosed", LogLevel.Error); return null; } } @@ -237,6 +251,7 @@ public class ClientDownloadPartTCP implements Runnable { public boolean downloadPart(ProtocolP2PPacketTCP d) { if (d == null) { System.err.println("Error: downloadPart -> d is null."); + logger.writeTCP("downloadPart -> d is null.", LogLevel.Error); return true; } try { @@ -244,11 +259,13 @@ public class ClientDownloadPartTCP implements Runnable { assert p instanceof FilePart : "This payload must be instance of FilePart"; if (!(p instanceof FilePart)) { System.err.println("Error: cannot get size."); + logger.writeTCP("cannot get size.", LogLevel.Error); return true; } else { FilePart fp = (FilePart)p; if (!fp.getFilename().equals(filename)) { System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); + logger.writeTCP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); return true; } Long offset = Long.valueOf(fp.getOffset()); @@ -257,9 +274,11 @@ public class ClientDownloadPartTCP implements Runnable { Files.write(new File(partsSubdir + filename + "_" + offset + ".part").toPath(), fp.getPartialContent()); } catch (IOException e) { System.err.println("Error: cannot write file (" + partsSubdir + filename + "_" + offset + ".part)"); + logger.writeTCP("cannot write file (" + partsSubdir + filename + "_" + offset + ".part)", LogLevel.Error); } } else { System.err.println("Error: wrong file part received."); + logger.writeTCP("wrong file part received.", LogLevel.Error); return true; } try { @@ -275,48 +294,62 @@ public class ClientDownloadPartTCP implements Runnable { } } catch(InterruptedException e) { System.err.println("Error: DownloadPart Interrupted exception"); + logger.writeTCP("DownloadPart Interrupted exception", LogLevel.Error); return true; } } } catch (EmptyDirectory e) { System.err.println("Error: empty directory."); + logger.writeTCP("empty directory.", LogLevel.Error); return true; } catch (EmptyFile e) { System.err.println("Error: downloadPart emptyFile"); + logger.writeTCP("downloadPart emptyFile", LogLevel.Error); // TODO: use more specific errors return true; } catch (ProtocolError e) { System.err.println("Error: downloadPart protocolError"); + logger.writeTCP("downloadPart protocolError", LogLevel.Error); return true; } catch (InternalRemoteError e) { System.err.println("Error: downloadPart internalRemoteError"); + logger.writeTCP("downloadPart internalRemoteError", LogLevel.Error); return true; } catch (VersionRemoteError e) { System.err.println("Error: downloadPart versionRemoteError"); + logger.writeTCP("downloadPart versionRemoteError", LogLevel.Error); return true; } catch (ProtocolRemoteError e) { System.err.println("Error: downloadPart protocolRemoteError"); + logger.writeTCP("downloadPart protocolRemoteError", LogLevel.Error); return true; } catch (TransmissionError e) { System.err.println("Error: downloadPart transmissionError"); + logger.writeTCP("downloadPart transmissionError", LogLevel.Error); return true; } catch (VersionError e) { System.err.println("Error: downloadPart versionError"); + logger.writeTCP("downloadPart versionError", LogLevel.Error); return true; } catch (SizeError e) { System.err.println("Error: downloadPart sizeError"); + logger.writeTCP("downloadPart sizeError", LogLevel.Error); return true; } catch (NotFound e) { System.err.println("Error: downloadPart notFound"); + logger.writeTCP("downloadPart notFound", LogLevel.Error); return true; } catch (IOException e) { System.err.println("Error: downloadPart ioexception"); + logger.writeTCP("downloadPart ioexception", LogLevel.Error); return true; } catch (InternalError e) { System.err.println("Error: downloadPart internalError"); + logger.writeTCP("downloadPart internalError", LogLevel.Error); return true; } catch (SocketClosed e){ System.err.println("Error: downloadPart SocketClosed"); + logger.writeTCP("downloadPart SocketClosed", LogLevel.Error); return true; } return false; diff --git a/src/clientP2P/ClientDownloadPartUDP.java b/src/clientP2P/ClientDownloadPartUDP.java index 1159096..b818553 100644 --- a/src/clientP2P/ClientDownloadPartUDP.java +++ b/src/clientP2P/ClientDownloadPartUDP.java @@ -21,6 +21,8 @@ import java.nio.file.Files; import java.io.File; import java.nio.file.Paths; import java.io.IOException; +import tools.Logger; +import tools.LogLevel; /** Class to download file parts on udp. * @author Louis Royer @@ -42,17 +44,19 @@ public class ClientDownloadPartUDP implements Runnable { private String partsSubdir; private static final long MAX_PARTIAL_SIZE = 4096; private ClientDownloadUDP manager; + private Logger logger; /** Constructor with filename, socket, and part subdir * @param filename name of file to download * @param socket socket to use * @param partsSubdir directory to store .part files */ - public ClientDownloadPartUDP(ClientDownloadUDP manager, String filename, DatagramSocket socket, String partsSubdir) { + public ClientDownloadPartUDP(ClientDownloadUDP manager, String filename, DatagramSocket socket, String partsSubdir, Logger logger) { this.manager = manager; this.partsSubdir = partsSubdir; this.filename = filename; this.socket = socket; + this.logger = logger; stop = false; failed = false; pendingTasks = new ArrayList<>(); @@ -96,6 +100,7 @@ public class ClientDownloadPartUDP implements Runnable { } } System.err.println("Closing socket"); + logger.writeUDP("Closing socket", LogLevel.Info); socket.close(); } @@ -174,6 +179,7 @@ public class ClientDownloadPartUDP implements Runnable { noTask = true; } } catch (IndexOutOfBoundsException e) { + logger.writeUDP(e, LogLevel.Error); noTask = true; } @@ -186,6 +192,7 @@ public class ClientDownloadPartUDP implements Runnable { */ private ProtocolP2PPacketUDP reqPart(Long offset) { System.err.println("New request: "+ offset); + logger.writeUDP("New request: "+ offset, LogLevel.Info); // maintain tracking of tasks if (toDoTasks.contains(offset)) { try { @@ -201,10 +208,12 @@ public class ClientDownloadPartUDP implements Runnable { } } catch(InterruptedException e) { System.err.println("Error: reqPart interruptedException"); + logger.writeUDP("reqPart interruptedException", LogLevel.Error); return null; } } else { System.err.println("Error: reqPart (offset " + offset + " not in toDoTasks)"); + logger.writeUDP("reqPart (offset " + offset + " not in toDoTasks)", LogLevel.Error); return null; } // send request @@ -214,10 +223,12 @@ public class ClientDownloadPartUDP implements Runnable { return d; } catch (InternalError e) { System.err.println("Error: reqPart internalError"); + logger.writeUDP("reqPart internalError", LogLevel.Error); return null; } catch (IOException e) { e.printStackTrace(); System.err.println("Error: reqPart ioexception"); + logger.writeUDP("reqPart ioexception", LogLevel.Error); return null; } } @@ -229,6 +240,7 @@ public class ClientDownloadPartUDP implements Runnable { public boolean downloadPart(ProtocolP2PPacketUDP d) { if (d == null) { System.err.println("Error: downloadPart -> d is null."); + logger.writeUDP("downloadPart -> d is null.", LogLevel.Error); return true; } try { @@ -236,11 +248,13 @@ public class ClientDownloadPartUDP implements Runnable { assert p instanceof FilePart : "This payload must be instance of FilePart"; if (!(p instanceof FilePart)) { System.err.println("Error: cannot get size."); + logger.writeUDP("cannot get size.", LogLevel.Error); return true; } else { FilePart fp = (FilePart)p; if (!fp.getFilename().equals(filename)) { System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); + logger.writeUDP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); return true; } Long offset = Long.valueOf(fp.getOffset()); @@ -249,9 +263,11 @@ public class ClientDownloadPartUDP implements Runnable { Files.write(new File(partsSubdir + filename + "_" + offset + ".part").toPath(), fp.getPartialContent()); } catch (IOException e) { System.err.println("Error: cannot write file (" + partsSubdir + filename + "_" + offset + ".part)"); + logger.writeUDP("cannot write file (" + partsSubdir + filename + "_" + offset + ".part)", LogLevel.Error); } } else { System.err.println("Error: wrong file part received."); + logger.writeUDP("wrong file part received.", LogLevel.Error); return true; } try { @@ -267,45 +283,58 @@ public class ClientDownloadPartUDP implements Runnable { } } catch(InterruptedException e) { System.err.println("Error: DownloadPart Interrupted exception"); + logger.writeUDP("DownloadPart Interrupted exception", LogLevel.Error); return true; } } } catch (EmptyDirectory e) { System.err.println("Error: empty directory."); + logger.writeUDP("empty directory.", LogLevel.Error); return true; } catch (EmptyFile e) { System.err.println("Error: downloadPart emptyFile"); + logger.writeUDP("downloadPart emptyFile", LogLevel.Error); // TODO: use more specific errors return true; } catch (ProtocolError e) { System.err.println("Error: downloadPart protocolError"); + logger.writeUDP("downloadPart protocolError", LogLevel.Error); return true; } catch (InternalRemoteError e) { System.err.println("Error: downloadPart internalRemoteError"); + logger.writeUDP("downloadPart internalRemoteError", LogLevel.Error); return true; } catch (VersionRemoteError e) { System.err.println("Error: downloadPart versionRemoteError"); + logger.writeUDP("downloadPart versionRemoteError", LogLevel.Error); return true; } catch (ProtocolRemoteError e) { System.err.println("Error: downloadPart protocolRemoteError"); + logger.writeUDP("downloadPart protocolRemoteError", LogLevel.Error); return true; } catch (TransmissionError e) { System.err.println("Error: downloadPart transmissionError"); + logger.writeUDP("downloadPart transmissionError", LogLevel.Error); return true; } catch (VersionError e) { System.err.println("Error: downloadPart versionError"); + logger.writeUDP("downloadPart versionError", LogLevel.Error); return true; } catch (SizeError e) { System.err.println("Error: downloadPart sizeError"); + logger.writeUDP("downloadPart sizeError", LogLevel.Error); return true; } catch (NotFound e) { System.err.println("Error: downloadPart notFound"); + logger.writeUDP("downloadPart notFound", LogLevel.Error); return true; } catch (IOException e) { System.err.println("Error: downloadPart ioexception"); + logger.writeUDP("downloadPart ioexception", LogLevel.Error); return true; } catch (InternalError e) { System.err.println("Error: downloadPart internalError"); + logger.writeUDP("downloadPart internalError", LogLevel.Error); return true; } return false; diff --git a/src/clientP2P/ClientDownloadTCP.java b/src/clientP2P/ClientDownloadTCP.java index 2ed8a0c..92bbc43 100644 --- a/src/clientP2P/ClientDownloadTCP.java +++ b/src/clientP2P/ClientDownloadTCP.java @@ -1,35 +1,38 @@ package clientP2P; -import clientP2P.ClientDownloadPartTCP; -import tools.HostItem; + import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; +import java.io.IOException; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.nio.file.StandardCopyOption; import remoteException.EmptyDirectory; import remoteException.EmptyFile; import remoteException.VersionRemoteError; import remoteException.ProtocolRemoteError; import remoteException.NotFound; import remoteException.InternalRemoteError; -import protocolP2P.HashAlgorithm; -import protocolP2P.HashResponse; -import protocolP2P.HashRequest; -import protocolP2P.ProtocolP2PPacketTCP; -import protocolP2P.Payload; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; import localException.SizeError; import localException.VersionError; +import localException.SocketClosed; +import protocolP2P.HashAlgorithm; +import protocolP2P.HashResponse; +import protocolP2P.HashRequest; +import protocolP2P.ProtocolP2PPacketTCP; +import protocolP2P.Payload; import protocolP2P.FilePart; import protocolP2P.LoadRequest; -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.nio.file.StandardCopyOption; -import localException.SocketClosed; +import clientP2P.ClientDownloadPartTCP; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; /** Class to download file from tcp * @author Louis Royer @@ -51,6 +54,7 @@ public class ClientDownloadTCP implements Runnable { private String partsSubdir; private String dirStorage; private boolean success = false; + private Logger logger; /** Constructor with parameters: filename, list of hosts, parts subdirectory and dirStorage * @param filename name of file to download @@ -58,11 +62,12 @@ public class ClientDownloadTCP implements Runnable { * @param partsSubdir directory to store .part files * @param dirStorage directory to write assembled file */ - public ClientDownloadTCP(String filename, List hostList, String partsSubdir, String dirStorage) { + public ClientDownloadTCP(String filename, List hostList, String partsSubdir, String dirStorage, Logger logger) { this.partsSubdir = partsSubdir; this.dirStorage = dirStorage; this.filename = filename; this.hostList = hostList; + this.logger = logger; this.stop = false; } @@ -79,9 +84,11 @@ public class ClientDownloadTCP implements Runnable { init(); if (stop) { System.err.println("File is smaller than part max size."); + logger.writeTCP("File is smaller than part max size.", LogLevel.Info); hostList.get(0).closeTCPSocket(); } else { System.err.println("File is bigger than part max size."); + logger.writeTCP("File is bigger than part max size.", LogLevel.Info); purgeList(); initThreads(); while(!stop) { @@ -91,9 +98,11 @@ public class ClientDownloadTCP implements Runnable { } } System.err.println("Reassembling file parts."); + logger.writeTCP("Reassembling file parts.", LogLevel.Info); reassembleFile(); } catch(InternalError e) { System.err.println("Error while downloading file. Aborting."); + logger.writeTCP("Error while downloading file. Aborting.", LogLevel.Error); } finally { stopTasks(); } @@ -103,13 +112,14 @@ public class ClientDownloadTCP implements Runnable { */ private void initThreads() { for(HostItem hostItem: hostList) { - sockList.add(new ClientDownloadPartTCP(this, filename, hostItem.getTCPSocket(), partsSubdir)); + sockList.add(new ClientDownloadPartTCP(this, filename, hostItem.getTCPSocket(), partsSubdir, logger)); } for(ClientDownloadPartTCP c: sockList) { Thread t = new Thread(c); t.start(); } System.err.println("Threads initialized"); + logger.writeTCP("Threads initialized", LogLevel.Info); } /** Remove tasks from failed threads. Update done status. @@ -133,15 +143,18 @@ public class ClientDownloadTCP implements Runnable { } } System.err.println("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending"); + logger.writeTCP("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending", LogLevel.Info); if (offsetsToAsk.isEmpty() && offsetsPending.isEmpty()) { stop = true; } if (sockList.size() == 0) { System.err.println("No thread working"); + logger.writeTCP("No thread working", LogLevel.Error); throw new InternalError(); } } } catch (InterruptedException e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } } @@ -157,6 +170,7 @@ public class ClientDownloadTCP implements Runnable { offsetsPending.add(offset); System.err.println("Assigned task "+ offset); } catch(InterruptedException e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } } @@ -168,7 +182,9 @@ public class ClientDownloadTCP implements Runnable { for(ClientDownloadPartTCP c : sockList) { try { c.setStop(); - } catch (InterruptedException e) {} + } catch (InterruptedException e) { + logger.writeTCP(e, LogLevel.Error); + } } } @@ -193,32 +209,44 @@ public class ClientDownloadTCP implements Runnable { hash = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512); } } catch (EmptyDirectory e) { + logger.writeTCP(e, LogLevel.Error); hash = new byte[0]; } catch (NotFound e) { + logger.writeTCP(e, LogLevel.Error); hash = new byte[0]; // TODO: use more specific errors } catch (EmptyFile e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (ProtocolError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (InternalRemoteError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (VersionRemoteError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (ProtocolRemoteError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (TransmissionError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (VersionError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (SizeError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } return hash; } catch (IOException e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (SocketClosed e){ System.err.println("getHashSum512 : SocketClosed"); + logger.writeTCP("getHashSum512 : SocketClosed", LogLevel.Error); throw new InternalError(); } } @@ -248,6 +276,7 @@ public class ClientDownloadTCP implements Runnable { hostList.remove(host); } System.err.println("Host list purge: done"); + logger.writeTCP("Host list purge: done", LogLevel.Info); } /** Getter for hash512sum @@ -269,6 +298,7 @@ public class ClientDownloadTCP implements Runnable { hash512 = getHashSum512(hostList.get(0)); if (hash512.length == 0) { System.err.println("Error: no hash512sum support."); + logger.writeTCP("no hash512sum support.", LogLevel.Error); throw new InternalError(); } @@ -278,6 +308,7 @@ public class ClientDownloadTCP implements Runnable { offsetsToAsk.add(Long.valueOf(i)); } System.err.println("Adding tasks: done"); + logger.writeTCP("Adding tasks: done", LogLevel.Info); } } @@ -293,11 +324,13 @@ public class ClientDownloadTCP implements Runnable { assert p instanceof FilePart : "This payload must be instance of FilePart"; if (!(p instanceof FilePart)) { System.err.println("Error: cannot get size."); + logger.writeTCP("cannot get size.", LogLevel.Error); throw new InternalError(); } else { FilePart fp = (FilePart)p; if (!fp.getFilename().equals(filename)) { System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); + logger.writeTCP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); throw new ProtocolError(); } if (fp.getOffset() == 0) { @@ -305,6 +338,7 @@ public class ClientDownloadTCP implements Runnable { Files.write(new File(partsSubdir + filename + "_0.part").toPath(), fp.getPartialContent()); } catch (IOException e) { System.err.println("Error: cannot write file (" + partsSubdir + filename + "_0.part)"); + logger.writeTCP("cannot write file (" + partsSubdir + filename + "_0.part)", LogLevel.Error); } size = fp.getTotalSize(); if (fp.getPartialContent().length == size) { @@ -312,36 +346,49 @@ public class ClientDownloadTCP implements Runnable { } } else { System.err.println("Error: wrong file part received."); + logger.writeTCP("wrong file part received.", LogLevel.Error); throw new InternalError(); } } } catch (EmptyDirectory e) { System.err.println("Error: empty directory."); + logger.writeTCP("empty directory.", LogLevel.Error); throw new InternalError(); } catch (EmptyFile e) { + logger.writeTCP(e, LogLevel.Error); // TODO: use more specific errors throw new InternalError(); } catch (ProtocolError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (InternalRemoteError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (VersionRemoteError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (ProtocolRemoteError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (TransmissionError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (VersionError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (SizeError e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (NotFound e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } } catch (IOException e) { + logger.writeTCP(e, LogLevel.Error); throw new InternalError(); } catch (SocketClosed e){ System.err.println("setSize : SocketClosed"); + logger.writeTCP("setSize : SocketClosed", LogLevel.Error); } } @@ -362,6 +409,7 @@ public class ClientDownloadTCP implements Runnable { do { if (firstPart) { System.err.println("Reassembling: First part"); + logger.writeTCP("Reassembling: First part", LogLevel.Info); try { // create file Files.copy(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath(), new File(dirStorage + filename).toPath(), StandardCopyOption.REPLACE_EXISTING); @@ -369,11 +417,13 @@ public class ClientDownloadTCP implements Runnable { firstPart = false; } catch (IOException e) { System.err.println("Reassembling: aborting on first part"); + logger.writeTCP("Reassembling: aborting on first part", LogLevel.Error); abort = true; } } else if (nextOffset >= size) { success = true; System.err.println("Reassembling: success"); + logger.writeTCP("Reassembling: success", LogLevel.Info); } else { // append to file try { @@ -382,6 +432,7 @@ public class ClientDownloadTCP implements Runnable { } catch (IOException e) { abort = true; System.err.println("Aborting: bad number " + nextOffset); + logger.writeTCP("Aborting: bad number " + nextOffset, LogLevel.Error); } } } while((!success) && (!abort)); diff --git a/src/clientP2P/ClientDownloadUDP.java b/src/clientP2P/ClientDownloadUDP.java index 2eb1779..87d6bab 100644 --- a/src/clientP2P/ClientDownloadUDP.java +++ b/src/clientP2P/ClientDownloadUDP.java @@ -1,10 +1,20 @@ package clientP2P; -import clientP2P.ClientDownloadPartUDP; -import tools.HostItem; + import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; +import java.io.IOException; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.nio.file.StandardCopyOption; +import localException.ProtocolError; +import localException.InternalError; +import localException.TransmissionError; +import localException.SizeError; +import localException.VersionError; import remoteException.EmptyDirectory; import remoteException.EmptyFile; import remoteException.VersionRemoteError; @@ -16,19 +26,13 @@ import protocolP2P.HashResponse; import protocolP2P.HashRequest; import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.Payload; -import localException.ProtocolError; -import localException.InternalError; -import localException.TransmissionError; -import localException.SizeError; -import localException.VersionError; import protocolP2P.FilePart; import protocolP2P.LoadRequest; -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.nio.file.StandardCopyOption; +import clientP2P.ClientDownloadPartUDP; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; + /** Class to download file from udp * @author Louis Royer @@ -50,6 +54,7 @@ public class ClientDownloadUDP implements Runnable { private String partsSubdir; private String dirStorage; private boolean success = false; + private Logger logger; /** Constructor with parameters: filename, list of hosts, parts subdirectory and dirStorage * @param filename name of file to download @@ -57,11 +62,12 @@ public class ClientDownloadUDP implements Runnable { * @param partsSubdir directory to store .part files * @param dirStorage directory to write assembled file */ - public ClientDownloadUDP(String filename, List hostList, String partsSubdir, String dirStorage) { + public ClientDownloadUDP(String filename, List hostList, String partsSubdir, String dirStorage, Logger logger) { this.partsSubdir = partsSubdir; this.dirStorage = dirStorage; this.filename = filename; this.hostList = hostList; + this.logger = logger; this.stop = false; } @@ -78,9 +84,11 @@ public class ClientDownloadUDP implements Runnable { init(); if (stop) { System.err.println("File is smaller than part max size."); + logger.writeUDP("File is smaller than part max size.", LogLevel.Info); hostList.get(0).closeUDPSocket(); } else { System.err.println("File is bigger than part max size."); + logger.writeUDP("File is bigger than part max size.", LogLevel.Info); purgeList(); initThreads(); while(!stop) { @@ -90,9 +98,11 @@ public class ClientDownloadUDP implements Runnable { } } System.err.println("Reassembling file parts."); + logger.writeUDP("Reassembling file parts.", LogLevel.Info); reassembleFile(); } catch(InternalError e) { System.err.println("Error while downloading file. Aborting."); + logger.writeUDP("Error while downloading file. Aborting.", LogLevel.Error); } finally { stopTasks(); } @@ -102,13 +112,14 @@ public class ClientDownloadUDP implements Runnable { */ private void initThreads() { for(HostItem hostItem: hostList) { - sockList.add(new ClientDownloadPartUDP(this, filename, hostItem.getUDPSocket(), partsSubdir)); + sockList.add(new ClientDownloadPartUDP(this, filename, hostItem.getUDPSocket(), partsSubdir, logger)); } for(ClientDownloadPartUDP c: sockList) { Thread t = new Thread(c); t.start(); } System.err.println("Threads initialized"); + logger.writeUDP("Threads initialized", LogLevel.Error); } /** Remove tasks from failed threads. Update done status. @@ -132,11 +143,13 @@ public class ClientDownloadUDP implements Runnable { } } System.err.println("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending"); + logger.writeUDP("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending", LogLevel.Info); if (offsetsToAsk.isEmpty() && offsetsPending.isEmpty()) { stop = true; } if (sockList.size() == 0) { System.err.println("No thread working"); + logger.writeUDP("No thread working", LogLevel.Error); throw new InternalError(); } } @@ -155,7 +168,9 @@ public class ClientDownloadUDP implements Runnable { sockList.get(rand.nextInt(sockList.size())).assignTask(offset); offsetsPending.add(offset); System.err.println("Assigned task "+ offset); + logger.writeUDP("Assigned task "+ offset, LogLevel.Info); } catch(InterruptedException e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } } @@ -167,7 +182,9 @@ public class ClientDownloadUDP implements Runnable { for(ClientDownloadPartUDP c : sockList) { try { c.setStop(); - } catch (InterruptedException e) {} + } catch (InterruptedException e) { + logger.writeUDP(e, LogLevel.Error); + } } } @@ -192,29 +209,40 @@ public class ClientDownloadUDP implements Runnable { hash = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512); } } catch (EmptyDirectory e) { + logger.writeUDP(e, LogLevel.Error); hash = new byte[0]; } catch (NotFound e) { + logger.writeUDP(e, LogLevel.Error); hash = new byte[0]; // TODO: use more specific errors } catch (EmptyFile e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (ProtocolError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (InternalRemoteError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (VersionRemoteError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (ProtocolRemoteError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (TransmissionError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (VersionError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (SizeError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } return hash; } catch (IOException e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } } @@ -244,6 +272,7 @@ public class ClientDownloadUDP implements Runnable { hostList.remove(host); } System.err.println("Host list purge: done"); + logger.writeUDP("Host list purge: done", LogLevel.Info); } /** Getter for hash512sum @@ -265,6 +294,7 @@ public class ClientDownloadUDP implements Runnable { hash512 = getHashSum512(hostList.get(0)); if (hash512.length == 0) { System.err.println("Error: no hash512sum support."); + logger.writeUDP("no hash512sum support.", LogLevel.Error); throw new InternalError(); } @@ -274,6 +304,7 @@ public class ClientDownloadUDP implements Runnable { offsetsToAsk.add(Long.valueOf(i)); } System.err.println("Adding tasks: done"); + logger.writeUDP("Adding tasks: done", LogLevel.Info); } } @@ -289,11 +320,13 @@ public class ClientDownloadUDP implements Runnable { assert p instanceof FilePart : "This payload must be instance of FilePart"; if (!(p instanceof FilePart)) { System.err.println("Error: cannot get size."); + logger.writeUDP("cannot get size.", LogLevel.Error); throw new InternalError(); } else { FilePart fp = (FilePart)p; if (!fp.getFilename().equals(filename)) { System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); + logger.writeUDP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); throw new ProtocolError(); } if (fp.getOffset() == 0) { @@ -301,6 +334,7 @@ public class ClientDownloadUDP implements Runnable { Files.write(new File(partsSubdir + filename + "_0.part").toPath(), fp.getPartialContent()); } catch (IOException e) { System.err.println("Error: cannot write file (" + partsSubdir + filename + "_0.part)"); + logger.writeUDP("cannot write file (" + partsSubdir + filename + "_0.part)", LogLevel.Error); } size = fp.getTotalSize(); if (fp.getPartialContent().length == size) { @@ -308,33 +342,45 @@ public class ClientDownloadUDP implements Runnable { } } else { System.err.println("Error: wrong file part received."); + logger.writeUDP("wrong file part received.", LogLevel.Error); throw new InternalError(); } } } catch (EmptyDirectory e) { System.err.println("Error: empty directory."); + logger.writeUDP("empty directory.", LogLevel.Error); throw new InternalError(); } catch (EmptyFile e) { + logger.writeUDP(e, LogLevel.Error); // TODO: use more specific errors throw new InternalError(); } catch (ProtocolError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (InternalRemoteError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (VersionRemoteError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (ProtocolRemoteError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (TransmissionError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (VersionError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (SizeError e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } catch (NotFound e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } } catch (IOException e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } } @@ -356,6 +402,7 @@ public class ClientDownloadUDP implements Runnable { do { if (firstPart) { System.err.println("Reassembling: First part"); + logger.writeUDP("Reassembling: First part", LogLevel.Info); try { // create file Files.copy(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath(), new File(dirStorage + filename).toPath(), StandardCopyOption.REPLACE_EXISTING); @@ -363,11 +410,13 @@ public class ClientDownloadUDP implements Runnable { firstPart = false; } catch (IOException e) { System.err.println("Reassembling: aborting on first part"); + logger.writeUDP("Reassembling: aborting on first part", LogLevel.Warning); abort = true; } } else if (nextOffset >= size) { success = true; System.err.println("Reassembling: success"); + logger.writeUDP("Reassembling: success", LogLevel.Info); } else { // append to file try { @@ -376,6 +425,7 @@ public class ClientDownloadUDP implements Runnable { } catch (IOException e) { abort = true; System.err.println("Aborting: bad number " + nextOffset); + logger.writeUDP("Aborting: bad number " + nextOffset, LogLevel.Error); } } } while((!success) && (!abort)); diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index ba71b3c..f479df0 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -1,25 +1,28 @@ package clientP2P; + +import java.net.UnknownHostException; +import java.util.Scanner; +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 java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import localException.InternalError; import localException.ProtocolError; import localException.SizeError; import localException.TransmissionError; import localException.VersionError; +import localException.SocketClosed; import remoteException.EmptyFile; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; -import java.net.UnknownHostException; -import java.util.Scanner; -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.ProtocolP2PPacketTCP; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; @@ -29,10 +32,10 @@ import protocolP2P.LoadRequest; import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import clientP2P.ClientDownloadTCP; -import localException.SocketClosed; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; /** Implementation of P2P-JAVA-PROJECT CLIENT * @author Louis Royer @@ -44,16 +47,18 @@ public class ClientManagementTCP implements Runnable { private String baseDirectory; private String partsSubdir; private List hostList; + private Logger logger; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. * @param baseDirectory the root directory where files are stored * @param host hostname of the server * @param TCPPort the server will listen on this port */ - public ClientManagementTCP(String baseDirectory, List hostList, String partsSubdir) { + public ClientManagementTCP(String baseDirectory, List hostList, String partsSubdir, Logger logger) { this.baseDirectory = baseDirectory; this.hostList = hostList; this.partsSubdir = partsSubdir; + this.logger = logger; } /** Implementation of Runnable @@ -70,33 +75,47 @@ public class ClientManagementTCP implements Runnable { System.out.println("Name of the file to download:"); String f = scanner.nextLine(); download(f); - System.out.println("File sucessfully downloaded"); + System.out.println("File " + f + " sucessfully downloaded"); + logger.writeTCP("File " + f + " sucessfully downloaded", LogLevel.Info); } catch (EmptyDirectory e) { System.err.println("Error: Server has no file in directory"); + logger.writeTCP("Error: Server has no file in directory", LogLevel.Error); } catch (InternalError e) { System.err.println("Error: Client internal error"); + logger.writeTCP("Error: Client internal error", LogLevel.Error); } catch (UnknownHostException e) { System.err.println("Error: Server host is unknown"); + logger.writeTCP("Error: Server host is unknown", LogLevel.Error); } catch (IOException e) { System.err.println("Error: Request cannot be send or response cannot be received"); + logger.writeTCP("Error: Request cannot be send or response cannot be received", LogLevel.Error); } catch (TransmissionError e) { System.err.println("Error: Message received is too big"); + logger.writeTCP("Error: Message received is too big", LogLevel.Error); } catch (ProtocolError e) { System.err.println("Error: Cannot decode server’s response"); + logger.writeTCP("Error: Cannot decode server’s response", LogLevel.Error); } catch (VersionError e) { System.err.println("Error: Server’s response use bad version of the protocol"); + logger.writeTCP("Error: Server’s response use bad version of the protocol", LogLevel.Error); } catch (SizeError e) { System.err.println("Error: Cannot handle this packets because of internal representation limitations of numbers on the client"); + logger.writeTCP("Error: Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); } catch (InternalRemoteError e) { System.err.println("Error: Server internal error"); + logger.writeTCP("Error: Server internal error", LogLevel.Error); } catch (ProtocolRemoteError e) { System.err.println("Error: Server cannot decode client’s request"); + logger.writeTCP("Error: Server cannot decode client’s request", LogLevel.Error); } catch (VersionRemoteError e) { System.err.println("Error: Server cannot decode this version of the protocol"); + logger.writeTCP("Error: Server cannot decode this version of the protocol", LogLevel.Error); } catch (NotFound e) { System.err.println("Error: Server has not this file in directory"); + logger.writeTCP("Error: Server has not this file in directory", LogLevel.Error); } catch (EmptyFile e) { System.err.println("Error: File is empty"); + logger.writeTCP("Error: File is empty", LogLevel.Error); } } @@ -116,7 +135,7 @@ public class ClientManagementTCP implements Runnable { * @throws EmptyFile */ private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { - ClientDownloadTCP downLoader = new ClientDownloadTCP(filename, hostList, partsSubdir, baseDirectory); + ClientDownloadTCP downLoader = new ClientDownloadTCP(filename, hostList, partsSubdir, baseDirectory, logger); Thread t = new Thread(downLoader); t.start(); try { @@ -125,15 +144,18 @@ public class ClientManagementTCP implements Runnable { byte[] hash512 = downLoader.getHashSum512(); if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) { System.err.println("Error: Hashsum does not match"); + logger.writeTCP("Error: Hashsum does not match", LogLevel.Error); System.err.println("Computed checksum:"); byte[] c = computeHashsum(filename, HashAlgorithm.SHA512); for (byte b: c) { System.err.print(String.format("%02X", b)); + logger.writeTCP("Computed checksum:" + String.format("%02X", b), LogLevel.Info); } System.err.println(""); System.err.println("Received checksum:"); for (byte b: hash512) { System.err.print(String.format("%02X", b)); + logger.writeTCP("Received checksum:" + String.format("%02X", b), LogLevel.Info); } System.err.println(""); throw new InternalError(); @@ -172,11 +194,14 @@ public class ClientManagementTCP implements Runnable { return ((FileList)p).getFileList(); } } catch (NotFound e) { + logger.writeTCP(e, LogLevel.Error); throw new ProtocolError(); } catch (EmptyFile e) { + logger.writeTCP(e, LogLevel.Error); throw new ProtocolError(); } catch (SocketClosed e){ System.err.println("listDirectory : SocketClosed"); + logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); throw new ProtocolError(); } } @@ -191,8 +216,10 @@ public class ClientManagementTCP implements Runnable { return md.digest(Files.readAllBytes(Paths.get(baseDirectory + filename))); } catch (NoSuchAlgorithmException e) { System.out.println("Error: " + h.getName() + " not supported"); + logger.writeTCP("Error: " + h.getName() + " not supported", LogLevel.Error); } catch (IOException e) { System.out.println("Error: cannot read " + filename); + logger.writeTCP("Error: cannot read " + filename, LogLevel.Error); } return new byte[0]; } diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index da720b6..914dc44 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -1,4 +1,17 @@ package clientP2P; + +import java.util.Scanner; +import java.util.Arrays; +import java.util.List; +import java.io.IOException; +import java.io.File; +import java.net.DatagramSocket; +import java.net.UnknownHostException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import localException.InternalError; import localException.ProtocolError; import localException.SizeError; @@ -10,17 +23,6 @@ import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; -import java.net.UnknownHostException; -import java.util.Scanner; -import java.net.DatagramSocket; -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; @@ -30,8 +32,9 @@ import protocolP2P.LoadRequest; import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; import clientP2P.ClientDownloadUDP; /** Implementation of P2P-JAVA-PROJECT CLIENT @@ -44,16 +47,18 @@ public class ClientManagementUDP implements Runnable { private String baseDirectory; private String partsSubdir; private List hostList; + private Logger logger; /** 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, List hostList, String partsSubdir) { + public ClientManagementUDP(String baseDirectory, List hostList, String partsSubdir, Logger logger) { this.baseDirectory = baseDirectory; this.hostList = hostList; this.partsSubdir = partsSubdir; + this.logger = logger; } /** Implementation of Runnable @@ -70,33 +75,47 @@ public class ClientManagementUDP implements Runnable { System.out.println("Name of the file to download:"); String f = scanner.nextLine(); download(f); - System.out.println("File sucessfully downloaded"); + System.out.println("File " + f + " sucessfully downloaded"); + logger.writeUDP("File " + f + " sucessfully downloaded", LogLevel.Info); } catch (EmptyDirectory e) { System.err.println("Error: Server has no file in directory"); + logger.writeUDP("Error: Server has no file in directory", LogLevel.Error); } catch (InternalError e) { System.err.println("Error: Client internal error"); + logger.writeUDP("Error: Client internal error", LogLevel.Error); } catch (UnknownHostException e) { System.err.println("Error: Server host is unknown"); + logger.writeUDP("Error: Server host is unknown", LogLevel.Error); } catch (IOException e) { System.err.println("Error: Request cannot be send or response cannot be received"); + logger.writeUDP("Error: Request cannot be send or response cannot be received", LogLevel.Error); } catch (TransmissionError e) { System.err.println("Error: Message received is too big"); + logger.writeUDP("Error: Message received is too big", LogLevel.Error); } catch (ProtocolError e) { System.err.println("Error: Cannot decode server’s response"); + logger.writeUDP("Error: Cannot decode server’s response", LogLevel.Error); } catch (VersionError e) { System.err.println("Error: Server’s response use bad version of the protocol"); + logger.writeUDP("Error: Server’s response use bad version of the protocol", LogLevel.Error); } catch (SizeError e) { System.err.println("Error: Cannot handle this packets because of internal representation limitations of numbers on the client"); + logger.writeUDP("Error: Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); } catch (InternalRemoteError e) { System.err.println("Error: Server internal error"); + logger.writeUDP("Error: Server internal error", LogLevel.Error); } catch (ProtocolRemoteError e) { System.err.println("Error: Server cannot decode client’s request"); + logger.writeUDP("Error: Server cannot decode client’s request", LogLevel.Error); } catch (VersionRemoteError e) { System.err.println("Error: Server cannot decode this version of the protocol"); + logger.writeUDP("Error: Server cannot decode this version of the protocol", LogLevel.Error); } catch (NotFound e) { System.err.println("Error: Server has not this file in directory"); + logger.writeUDP("Error: Server has not this file in directory", LogLevel.Error); } catch (EmptyFile e) { System.err.println("Error: File is empty"); + logger.writeUDP("Error: File is empty", LogLevel.Error); } } @@ -116,7 +135,7 @@ public class ClientManagementUDP implements Runnable { * @throws EmptyFile */ private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { - ClientDownloadUDP downLoader = new ClientDownloadUDP(filename, hostList, partsSubdir, baseDirectory); + ClientDownloadUDP downLoader = new ClientDownloadUDP(filename, hostList, partsSubdir, baseDirectory, logger); Thread t = new Thread(downLoader); t.start(); try { @@ -129,11 +148,13 @@ public class ClientManagementUDP implements Runnable { byte[] c = computeHashsum(filename, HashAlgorithm.SHA512); for (byte b: c) { System.err.print(String.format("%02X", b)); + logger.writeUDP("Computed checksum:" + String.format("%02X", b), LogLevel.Info); } System.err.println(""); System.err.println("Received checksum:"); for (byte b: hash512) { System.err.print(String.format("%02X", b)); + logger.writeUDP("Received checksum:" + String.format("%02X", b), LogLevel.Info); } System.err.println(""); throw new InternalError(); @@ -142,6 +163,7 @@ public class ClientManagementUDP implements Runnable { throw new InternalError(); } } catch (InterruptedException e) { + logger.writeUDP(e, LogLevel.Error); throw new InternalError(); } } @@ -172,8 +194,10 @@ public class ClientManagementUDP implements Runnable { return ((FileList)p).getFileList(); } } catch (NotFound e) { + logger.writeUDP(e, LogLevel.Error); throw new ProtocolError(); } catch (EmptyFile e) { + logger.writeUDP(e, LogLevel.Error); throw new ProtocolError(); } } @@ -188,8 +212,10 @@ public class ClientManagementUDP implements Runnable { return md.digest(Files.readAllBytes(Paths.get(baseDirectory + filename))); } catch (NoSuchAlgorithmException e) { System.out.println("Error: " + h.getName() + " not supported"); + logger.writeUDP("Error: " + h.getName() + " not supported", LogLevel.Error); } catch (IOException e) { System.out.println("Error: cannot read " + filename); + logger.writeUDP("Error: cannot read " + filename, LogLevel.Error); } return new byte[0]; } diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index f857427..2d56fd8 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -1,4 +1,7 @@ package clientP2P; + +import java.util.Scanner; +import java.util.List; import clientP2P.ClientManagementUDP; import clientP2P.ClientManagementTCP; import serverP2P.ServerManagementUDP; @@ -7,8 +10,6 @@ import tools.Directories; import tools.Logger; import tools.LogLevel; import tools.Directories; -import java.util.Scanner; -import java.util.List; import tools.HostItem; import tools.HostList; @@ -18,10 +19,12 @@ import tools.HostList; * @author JS Auge * @version 1.0 */ + public class ClientP2P { static private final String subdir = "seeded/"; static private String parts = ".parts"; - private Logger logger; + private Logger loggerServer; + private Logger loggerClient; private String host; private int port; private Directories directories; @@ -29,13 +32,14 @@ public class ClientP2P { private static final int defaultPort = 20000; - /** Initialize logger if directories and logger are null, + /** Initialize loggers if directories and logger are null, * else fail silently. */ public void initLogger() { - if (directories == null && logger == null) { - directories = new Directories("P2P_JAVA_PROJECT" + port); - logger = new Logger(directories.getDataHomeDirectory() + "server.log"); + if (directories == null && loggerServer == null && loggerClient == null) { + directories = new Directories("P2P_JAVA_PROJECT_" + port); + loggerServer = new Logger(directories.getDataHomeDirectory() + "server.log"); + loggerClient = new Logger(directories.getDataHomeDirectory() + "client.log"); } } @@ -50,7 +54,7 @@ public class ClientP2P { port = defaultPort; initLogger(); System.err.println("Error incorrect port " + oldPort + " using default port " + defaultPort); - logger.write("incorrect port " + oldPort + " using default port " + defaultPort, LogLevel.Info); + loggerServer.write("incorrect port " + oldPort + " using default port " + defaultPort, LogLevel.Info); } initLogger(); directories.createSubdir(subdir); @@ -65,7 +69,7 @@ public class ClientP2P { * 1rst parameter is optionnal, and is used to * define port used by the server module to listen. If not provided, default to another port. * @param args server listenning port - */ + */ public static void main(String [] args) { ClientP2P c; try { @@ -75,8 +79,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.logger); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.logger); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); @@ -104,7 +108,7 @@ public class ClientP2P { case "upd": // alias typo case "2" : System.out.println("Starting with UDP"); - ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/"); + ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); t = new Thread(cmudp); break; case "TCP": @@ -112,7 +116,7 @@ public class ClientP2P { case "1": default: System.out.println("Starting with TCP"); - ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/"); + ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); t = new Thread(cmtcp); break; } From cfc24354b9866137c929d2b9e18a694f971d865a Mon Sep 17 00:00:00 2001 From: flavien Date: Fri, 20 Mar 2020 15:57:09 +0100 Subject: [PATCH 05/40] added help argument --- src/clientP2P/ClientP2P.java | 100 +++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 2d56fd8..34a9519 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -71,57 +71,63 @@ public class ClientP2P { * @param args server listenning port */ public static void main(String [] args) { - ClientP2P c; - try { - c = new ClientP2P(args[1]); - } catch (IndexOutOfBoundsException e){ - c = new ClientP2P("" + defaultPort); + + if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ + System.out.println("usage : java -ea clientP2P.ClientP2P -- "); } + else{ + ClientP2P c; + try { + c = new ClientP2P(args[1]); + } catch (IndexOutOfBoundsException e){ + c = new ClientP2P("" + defaultPort); + } - // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); - Thread tudp = new Thread(smudp); - tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); - tudp.start(); - Thread ttcp = new Thread(smtcp); - ttcp.setName("server TCP P2P-JAVA-PROJECT (port: " + c.port + ")"); - ttcp.start(); + // Server threads + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); + Thread tudp = new Thread(smudp); + tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); + tudp.start(); + Thread ttcp = new Thread(smtcp); + ttcp.setName("server TCP P2P-JAVA-PROJECT (port: " + c.port + ")"); + ttcp.start(); - // Wait a bit before printing client interface - // This is not required, but allow to have a cleaner interface - try { - Thread.sleep(100); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + // Wait a bit before printing client interface + // This is not required, but allow to have a cleaner interface + try { + Thread.sleep(100); + } catch(InterruptedException e) { + Thread.currentThread().interrupt(); + } - // initialize Host lists - c.hostList = HostList.getServList(); - System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]"); - Scanner sc = new Scanner(System.in); - String transportchoosen = sc.nextLine(); - Thread t; - switch(transportchoosen){ - case "UDP": - case "udp": - case "upd": // alias typo - case "2" : - System.out.println("Starting with UDP"); - ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); - t = new Thread(cmudp); - break; - case "TCP": - case "tcp": - case "1": - default: - System.out.println("Starting with TCP"); - ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); - t = new Thread(cmtcp); - break; - } + // initialize Host lists + c.hostList = HostList.getServList(); + System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]"); + Scanner sc = new Scanner(System.in); + String transportchoosen = sc.nextLine(); + Thread t; + switch(transportchoosen){ + case "UDP": + case "udp": + case "upd": // alias typo + case "2" : + System.out.println("Starting with UDP"); + ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); + t = new Thread(cmudp); + break; + case "TCP": + case "tcp": + case "1": + default: + System.out.println("Starting with TCP"); + ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); + t = new Thread(cmtcp); + break; + } - t.setName("client P2P-JAVA-PROJECT"); - t.start(); + t.setName("client P2P-JAVA-PROJECT"); + t.start(); + } } } From 879164304a17d15c856d0d4750236a64c823f756 Mon Sep 17 00:00:00 2001 From: flavien Date: Fri, 20 Mar 2020 16:39:27 +0100 Subject: [PATCH 06/40] added server help argument --- src/serverP2P/ServerP2P.java | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index 313d263..be8bfec 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -35,15 +35,21 @@ public class ServerP2P { * @param args parameters */ public static void main(String [] args) { - ServerP2P s = new ServerP2P(args[1]); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); - Thread tudp = new Thread(smudp); - tudp.setName("server UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(smtcp); - ttcp.setName("server TCP P2P-JAVA-PROJECT"); - ttcp.start(); + + if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ + System.out.println("usage : java -ea serveurP2P.ServeurP2P -- "); + } + else{ + ServerP2P s = new ServerP2P(args[1]); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); + Thread tudp = new Thread(smudp); + tudp.setName("server UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(smtcp); + ttcp.setName("server TCP P2P-JAVA-PROJECT"); + ttcp.start(); + } } } From 223e5126845076f3afd102675e550d54b10b288d Mon Sep 17 00:00:00 2001 From: flavien Date: Fri, 20 Mar 2020 17:03:30 +0100 Subject: [PATCH 07/40] refactor servermanagemntudp methods --- src/serverP2P/ServerManagementUDP.java | 126 +++++++++++++------------ 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index c6b3078..986e8d0 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -80,67 +80,10 @@ public class ServerManagementUDP implements Runnable { Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: - logger.writeUDP("Received LOAD_REQUEST", LogLevel.Action); - assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; - if (!(p instanceof LoadRequest)) { - sendInternalError(pd); - } else { - String filename = ((LoadRequest)p).getFilename(); - long offset = ((LoadRequest)p).getOffset(); - long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent(); - try { - byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename)); - long sizeToSend = 0; - if (fullLoad.length - offset < maxSizePartialContent) { - logger.writeUDP("Sending last partialContent", LogLevel.Debug); - sizeToSend = fullLoad.length - offset; - } else { - sizeToSend = maxSizePartialContent; - } - logger.writeUDP("maxSizePartialContent: " + maxSizePartialContent, LogLevel.Debug); - logger.writeUDP("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend), LogLevel.Debug); - byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend)); - if (Arrays.binarySearch(fileList, filename) >= 0) { - try { - if (load.length == 0) { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_FILE))); - } else { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); - } - } catch (Exception e2) { - logger.writeUDP(e2, LogLevel.Error); - } - } else { - logger.writeUDP("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename), LogLevel.Debug); - logger.writeUDP("File list:", LogLevel.Debug); - for (String f: fileList) { - logger.writeUDP("- " + f, LogLevel.Debug); - } - - throw new IOException(); // to send a NOT_FOUND in the catch block - } - } catch (IOException e) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e2) { - logger.writeUDP(e2, LogLevel.Error); - } - } - } + LoadRequestManagement(logger, p, pd); break; case LIST_REQUEST: - logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); - try { - if (fileList.length == 0) { - logger.writeUDP("Sending EMPTY_DIRECTORY", LogLevel.Action); - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); - } else { - logger.writeUDP("Sending LIST_RESPONSE", LogLevel.Action); - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FileList(fileList)))); - } - } catch (Exception e2) { - logger.writeUDP(e2, LogLevel.Error); - } + ListRequestManagement(logger, pd); break; case HASH_REQUEST: logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); @@ -205,6 +148,71 @@ public class ServerManagementUDP implements Runnable { } } + public void LoadRequestManagement(Logger logger, Payload p, ProtocolP2PPacketUDP pd){ + logger.writeUDP("Received LOAD_REQUEST", LogLevel.Action); + assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; + if (!(p instanceof LoadRequest)) { + sendInternalError(pd); + } else { + String filename = ((LoadRequest)p).getFilename(); + long offset = ((LoadRequest)p).getOffset(); + long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent(); + try { + byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename)); + long sizeToSend = 0; + if (fullLoad.length - offset < maxSizePartialContent) { + logger.writeUDP("Sending last partialContent", LogLevel.Debug); + sizeToSend = fullLoad.length - offset; + } else { + sizeToSend = maxSizePartialContent; + } + logger.writeUDP("maxSizePartialContent: " + maxSizePartialContent, LogLevel.Debug); + logger.writeUDP("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend), LogLevel.Debug); + byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend)); + if (Arrays.binarySearch(fileList, filename) >= 0) { + try { + if (load.length == 0) { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_FILE))); + } else { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); + } + } catch (Exception e2) { + logger.writeUDP(e2, LogLevel.Error); + } + } else { + logger.writeUDP("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename), LogLevel.Debug); + logger.writeUDP("File list:", LogLevel.Debug); + for (String f: fileList) { + logger.writeUDP("- " + f, LogLevel.Debug); + } + + throw new IOException(); // to send a NOT_FOUND in the catch block + } + } catch (IOException e) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e2) { + logger.writeUDP(e2, LogLevel.Error); + } + } + } + } + + public void ListRequestManagement(Logger logger, ProtocolP2PPacketUDP pd){ + logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); + try { + if (fileList.length == 0) { + logger.writeUDP("Sending EMPTY_DIRECTORY", LogLevel.Action); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } else { + logger.writeUDP("Sending LIST_RESPONSE", LogLevel.Action); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FileList(fileList)))); + } + } catch (Exception e2) { + logger.writeUDP(e2, LogLevel.Error); + } + } + /** Send hash response to hash request * @param pd Request received */ From d1ae5960a68c21b01b298a1658505a3824f2735c Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 14:04:33 +0100 Subject: [PATCH 08/40] Update protocol for #16 --- doc/protocol.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/protocol.md b/doc/protocol.md index b21a615..a2cf4d5 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -17,17 +17,22 @@ x bytes: [(bytes 8-?): PAYLOAD] - `LIST` (0x00) - `LOAD` (0x01) - `HASH` (0x02) + - `DISCOVER` (0x03) + - `REGISTER` (0x04) + - `UNREGISTER` (0x05) - RESPONSES (msb is 1): - `LIST` (0x80) - `LOAD` (0x81) - `HASH` (0x82) + - `DISCOVER` (0x83) - `VERSION ERROR` (0xC0) - `PROTOCOL ERROR` (0xC1) - `INTERNAL ERROR` (0xC2) - `EMPTY DIRECTORY` (0xC3) - `NOT FOUND` (0xC4) - `EMPTY FILE` (0xC5) + - `NOT A TRACKER` (0xC6) ### List Payload size for list request is always zero. @@ -97,6 +102,47 @@ A algo hash bloc contains: ``` +### Tracker specific messages +#### Register +Used by a server to register itself on a tracker. +Payload contains `0x01` if working on udp, `0x02` if working on tcp, `0x03` if working on both. +Server may want to do a free `DISCOVER` to check if they have been registered. + +#### Unregister +Used by a server to unregister itself from a tracker. +Payload contains `0x01` if unregister from udp, `0x02` if unregister from tcp, `0x03` if unregister on both. +No error is raised if the server was not registered. +Server may want to do a free `DISCOVER` to check if they have been unregistered. + +#### Discover request +If payload size is null, lists all servers registered. +If payload contains a filename, list all servers having this file in their list. + +``` +? bytes: [] + +``` + +#### Discover response +Contains: +``` +4 bytes: [(bytes 8-11): FILENAME SIZE] +y bytes: [] +? bytes [multiple server blocks] +``` + +Server block is composed with: + +``` +2 bytes: [port] +1 byte: [protocols (udp: 0x01, tcp: 0x02, tcp+udp: 0x03)] +? bytes: hostname +\n +``` + +#### Not a Tracker +This error is raised when receiving a DISCOVER, a REGISTER, or an UNREGISTER request, +but this application is not a tracker. ### Other response code (errors) #### Version error From f0988e3af3d65d8b5ad25122ba680f209fd77f32 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 14:42:34 +0100 Subject: [PATCH 09/40] Add sequence diagrams --- doc/tracker_sequence_diagram.drawio | 1 + doc/tracker_sequence_diagram.svg | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 doc/tracker_sequence_diagram.drawio create mode 100644 doc/tracker_sequence_diagram.svg diff --git a/doc/tracker_sequence_diagram.drawio b/doc/tracker_sequence_diagram.drawio new file mode 100644 index 0000000..baa61f9 --- /dev/null +++ b/doc/tracker_sequence_diagram.drawio @@ -0,0 +1 @@ +7Ztfc+I2EMA/DTO5h2RsyzbwmBCS3vR6lwvptdM3YQtQIyxqRP7003eFZYMlbDjHEJOSh4y8lteS9qfVrmRaqDd9uY3xbPIbDwlrOVb40kLXLcfp+B34LwWvicDtdhPBOKZhIrJXggH9lyihpaQLGpJ5rqLgnAk6ywsDHkUkEDkZjmP+nK824iz/1hkeE0MwCDAzpX/QUEyU1Las1Y1fCB1P1Ks7nroxxMHjOOaLSL2v5aDR8i+5PcWpLlV/PsEhf14ToX4L9WLORVKavvQIk0ObDlvy3E3B3azdMYnELg+0h3iI7cAdBk575A6tcyfR8ITZQo3FQwx9IrFqr3hNxwiaPpPFxZR9oSPCaARXVzMS0ykRUB9dMyW+W8munidUkMEMB/LRZ4AHZBMxZXBlQxEMKjA8EmfXjOHZnA6Xb7VAEpNgEc/pE7kn84QbKeULId/Uy3hYVpV2IKFSlQ21tdQ7pYEqMzwk7CozXI8zLl8f8WWH5iLmjxkFUtEI2niDp5RJuH+QOMQRVmJFsg12vMKMjiO4CMAUy66btlHmeiKxIC9rImWrW8Jh2OJXqKLuOq7iRs2rjrp8XoM0ZXSyxqeXVsRqYowz1Ss4oKD42JEVZLDSYxQ6Z59YaQArrtUkVtoGKy10+W34t7TAiZb3p6XrN4mWjkHLgMTQmZNnaQIrdqM8i+sbsHzlghSSEsmbWxFQVrVdKMuRoRAcXqqxFHy2NrKMjIR8AFTRaPwg712f+znDWwc3fP0OAe1oZOTVYOP279E0/pP++tdAXP9zs+j74XRDZHrfv/08eOjfny3CWcu5EsHsk2H1NZPqZhxyIfgUbpAovJRJg5QxHjxms4SERppgjKjA8ZiIAjadzUO8NobplIgJwwL8SU73pjFU2u44hYaspqSXt5bta1NtzhdxQNRT6wmBpiizc5GipL+GoqVJsy5Wt7JrWPkL2Bgk9/3vlYw7hwaL1Lwc9KayG8rShzcAsKyi5lOnPiA6W4Hw6wHC6ebt6FgVgUDeFkUFQMCA4te1ajNZYV7S4M7m96z4SjTWSptXTNvg7mxEGYGB78kdBCg61bxLswAs8EjKCNaF7bYNP18TkrqPypLZn/ZR9hZFBUiuFKUV+Wg0J3vxY12DrOvPg963H/37lK55EtGew+J1DktXwlkidDYJUSo8EgwTa5ZhuAVVdChfiXRfqcepu4Lp6oTrimrylbpPdtEBfGU66YykzDF4PCVllZIyIzjfMK8KXbenMXHYpGwjMLYBTF0R+1GsqfU7Kt+qKcr3/feN8tMM9aOE+cX+8l1i/apYGLH+gbHYsEns+EzuroT0CYpjWczFUd/PPqVV4I1rtY4DotIYCTXJ9RihTbciY54evOuKaoqRXCf/HtS2StuV3i+ov6eYyjxC0xNQZ5WAoiNZLHNUl4WSDUFbW1Ur56Wuv0VRTWh7+tasfsivtwuV1t8T2v/PnTw15OfWhYV8pWcPyGrfAbiVvbG1RVEDtlJsc5cuSTyRgdEp8Tx84ulrC2cDEk/zRPBoE8/ta6nX5LU0XWrevJYaimpaS33Nk9rdQ6yN5vcNR702FnP5LulvVeaM9HdH5mrDwjw0KDmO+jjZwMmDvcWDeXp0725JdDul9ffj8dK+75boHstJa+n2TWcHqguOuLLTWMtCKL88mcFVXaezevLqVeTe6XYvvHJVdX0yoG0lpRFlYcvapfXz5JsDlO/D/vKd7FutgrPj7zBdggkl8YeYJs3a5dTTYbsm528oquskWNvl9A+xteM4BqBfARUw4oTA/2D5IwAoPEbyhzjp9wu27FYUZtdI5oP4iSifD9RdQhHS4YhxLKsFOIL/QzKm0YUB+sG/5my9PVO2Nf/jb0iVUwPmUuW2Bk9931Sa+88/8ZnK6YuUQ/khr+rXe/rWr7+npVjfkEwPmCv6Ibhc/QYuqb76nSHq/wc= \ No newline at end of file diff --git a/doc/tracker_sequence_diagram.svg b/doc/tracker_sequence_diagram.svg new file mode 100644 index 0000000..ee79363 --- /dev/null +++ b/doc/tracker_sequence_diagram.svg @@ -0,0 +1,3 @@ + + +
Tracker
Tracker
Client1
Client1
:Object
:Object
Server1
Server1
Note
Note
REGISTER(udp+tcp)
REGISTER(udp+tc...
LIST REQ
LIST REQ
LIST RESP(file1, file2)
LIST RESP(f...
DISCOVER RESP(server1-udp-tcp, server2-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Server2
Server2
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
DISCOVER REQ()
DISCOVER RE...
LIST RESP(file2, file3)
LIST RESP(f...
LIST REQ
LIST REQ
Server3
Server3
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
LIST RESP(file1, file3)
LIST RESP(f...
LIST RESP(file2, file2)
LIST RESP(f...
DISCOVER REQ(fichier2)
DISCOVER RE...
Now the client knows server1 and server3 have file1: download can begin.
Now the client knows server1 and server3 have file1: download can begin.
DISCOVER RESP(server1-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Viewer does not support full SVG 1.1
\ No newline at end of file From f1beed30e11753ceaa70998225eff79c71bedf61 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 15:51:02 +0100 Subject: [PATCH 10/40] Update doc --- doc/protocol.md | 3 --- doc/tracker_sequence_diagram.drawio | 2 +- doc/tracker_sequence_diagram.svg | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/protocol.md b/doc/protocol.md index a2cf4d5..a01a6c9 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -105,12 +105,10 @@ A algo hash bloc contains: ### Tracker specific messages #### Register Used by a server to register itself on a tracker. -Payload contains `0x01` if working on udp, `0x02` if working on tcp, `0x03` if working on both. Server may want to do a free `DISCOVER` to check if they have been registered. #### Unregister Used by a server to unregister itself from a tracker. -Payload contains `0x01` if unregister from udp, `0x02` if unregister from tcp, `0x03` if unregister on both. No error is raised if the server was not registered. Server may want to do a free `DISCOVER` to check if they have been unregistered. @@ -135,7 +133,6 @@ Server block is composed with: ``` 2 bytes: [port] -1 byte: [protocols (udp: 0x01, tcp: 0x02, tcp+udp: 0x03)] ? bytes: hostname \n ``` diff --git a/doc/tracker_sequence_diagram.drawio b/doc/tracker_sequence_diagram.drawio index baa61f9..85919a8 100644 --- a/doc/tracker_sequence_diagram.drawio +++ b/doc/tracker_sequence_diagram.drawio @@ -1 +1 @@ -7Ztfc+I2EMA/DTO5h2RsyzbwmBCS3vR6lwvptdM3YQtQIyxqRP7003eFZYMlbDjHEJOSh4y8lteS9qfVrmRaqDd9uY3xbPIbDwlrOVb40kLXLcfp+B34LwWvicDtdhPBOKZhIrJXggH9lyihpaQLGpJ5rqLgnAk6ywsDHkUkEDkZjmP+nK824iz/1hkeE0MwCDAzpX/QUEyU1Las1Y1fCB1P1Ks7nroxxMHjOOaLSL2v5aDR8i+5PcWpLlV/PsEhf14ToX4L9WLORVKavvQIk0ObDlvy3E3B3azdMYnELg+0h3iI7cAdBk575A6tcyfR8ITZQo3FQwx9IrFqr3hNxwiaPpPFxZR9oSPCaARXVzMS0ykRUB9dMyW+W8munidUkMEMB/LRZ4AHZBMxZXBlQxEMKjA8EmfXjOHZnA6Xb7VAEpNgEc/pE7kn84QbKeULId/Uy3hYVpV2IKFSlQ21tdQ7pYEqMzwk7CozXI8zLl8f8WWH5iLmjxkFUtEI2niDp5RJuH+QOMQRVmJFsg12vMKMjiO4CMAUy66btlHmeiKxIC9rImWrW8Jh2OJXqKLuOq7iRs2rjrp8XoM0ZXSyxqeXVsRqYowz1Ss4oKD42JEVZLDSYxQ6Z59YaQArrtUkVtoGKy10+W34t7TAiZb3p6XrN4mWjkHLgMTQmZNnaQIrdqM8i+sbsHzlghSSEsmbWxFQVrVdKMuRoRAcXqqxFHy2NrKMjIR8AFTRaPwg712f+znDWwc3fP0OAe1oZOTVYOP279E0/pP++tdAXP9zs+j74XRDZHrfv/08eOjfny3CWcu5EsHsk2H1NZPqZhxyIfgUbpAovJRJg5QxHjxms4SERppgjKjA8ZiIAjadzUO8NobplIgJwwL8SU73pjFU2u44hYaspqSXt5bta1NtzhdxQNRT6wmBpiizc5GipL+GoqVJsy5Wt7JrWPkL2Bgk9/3vlYw7hwaL1Lwc9KayG8rShzcAsKyi5lOnPiA6W4Hw6wHC6ebt6FgVgUDeFkUFQMCA4te1ajNZYV7S4M7m96z4SjTWSptXTNvg7mxEGYGB78kdBCg61bxLswAs8EjKCNaF7bYNP18TkrqPypLZn/ZR9hZFBUiuFKUV+Wg0J3vxY12DrOvPg963H/37lK55EtGew+J1DktXwlkidDYJUSo8EgwTa5ZhuAVVdChfiXRfqcepu4Lp6oTrimrylbpPdtEBfGU66YykzDF4PCVllZIyIzjfMK8KXbenMXHYpGwjMLYBTF0R+1GsqfU7Kt+qKcr3/feN8tMM9aOE+cX+8l1i/apYGLH+gbHYsEns+EzuroT0CYpjWczFUd/PPqVV4I1rtY4DotIYCTXJ9RihTbciY54evOuKaoqRXCf/HtS2StuV3i+ov6eYyjxC0xNQZ5WAoiNZLHNUl4WSDUFbW1Ur56Wuv0VRTWh7+tasfsivtwuV1t8T2v/PnTw15OfWhYV8pWcPyGrfAbiVvbG1RVEDtlJsc5cuSTyRgdEp8Tx84ulrC2cDEk/zRPBoE8/ta6nX5LU0XWrevJYaimpaS33Nk9rdQ6yN5vcNR702FnP5LulvVeaM9HdH5mrDwjw0KDmO+jjZwMmDvcWDeXp0725JdDul9ffj8dK+75boHstJa+n2TWcHqguOuLLTWMtCKL88mcFVXaezevLqVeTe6XYvvHJVdX0yoG0lpRFlYcvapfXz5JsDlO/D/vKd7FutgrPj7zBdggkl8YeYJs3a5dTTYbsm528oquskWNvl9A+xteM4BqBfARUw4oTA/2D5IwAoPEbyhzjp9wu27FYUZtdI5oP4iSifD9RdQhHS4YhxLKsFOIL/QzKm0YUB+sG/5my9PVO2Nf/jb0iVUwPmUuW2Bk9931Sa+88/8ZnK6YuUQ/khr+rXe/rWr7+npVjfkEwPmCv6Ibhc/QYuqb76nSHq/wc= \ No newline at end of file +7Vtfc+I2EP80zFwfkrEt28BjQkh60+tdEtJrp2/CFqBGWFSI/LlP3xWWDZbAEJ8hZpo8MNJqvZJ2f1rtSkoL9aYvNwLPJr/zmLCW58QvLXTV8rxO2IFfRXhNCX63mxLGgsYpyV0RBvQH0URHUxc0JvMCo+ScSTorEiOeJCSSBRoWgj8X2UacFXud4TGxCIMIM5v6J43lRFNdx1k1/EroeKK77gS6YYijx7Hgi0T31/LQaPmXNk9xJkvzzyc45s9rJNRvoZ7gXKal6UuPMKXaTG3pd9dbWvNxC5LIfT5oD/EQu5E/jLz2yB86Z14q4QmzhdbFg4A5EaHHK18zHcHQZ6q4mLIvdEQYTaB2OSOCTokEfnTFNPl2Rbt8nlBJBjMcqU+fATxAm8gpg5oLRTCoxPCJyOuM4dmcDpe9OkARJFqIOX0i92Se4kZR+UKqnno5Hpasyg4k1qJyVTtLuVMa6TLDQ8Iuc8P1OOOq+4QvJzSXgj/mKFCCRjDGazylTIH7OxExTrAmayS7YMdLzOg4gUoEplhO3baNNtcTEZK8rJG0rW4IB7WJV2DRrZ6vcaPXVUdXn9dAmmF0sobPIGPEemGMc9ErcEBB42NPrCALKz1GYXLuB1YagBXfaRJW2hZWWuji2/AfZYEPtLw/Wrphk9DSsdAyIAIm8+FZmoAVt1GexQ8tsHzlkmxFSqIad0JAW9X1oaw0QyE4vNC6lHy2pllGRlJ9AKJoMn5QbVdnYcHwztENX79DQHsaGQU12Lj9RzIVf9Hf/h7Iq3+vF/0wnm6ITO/7N58HD/37T79Yxl6zpGm9IZeST6GBJPGFyhUUjfHosWxxSCzGRG5BoB4ZiQtJha3ZNdVlK0EQhiW4kUJnm1Snpd1yCiNbrcSgaCQ3NFbYnC9ERPRX63mAISg37zZBqQIsQUtL5lOsblzfMu4XMC1Q7vt3lYw7hwHLzLwc5Ga0a8qyjzcAYMmil1GnMiA6bwdEWA8gvG7Rjp5TERAo2CFoCyBAofh1jW2mGOYlA+5s7meFr1RirWgLtqNtcPtpRBkBxffUwQEUvWre5V0BuK9H0kZwzl2/bbn3miBp+qg8h32zj3J3CNoCyZWgjJGPRnNyED/WtZB19XnQ+/a9f5+ha54FsgpfacVbr6Bmwi01UjncSiGJ3s0nItMnmmHovgD0TSSbgmryiabv9dERfGK2uKycy7Pw+JFzHT/nCoL3zLk2Asa1APOTAflJbJn1+6fQqSmID8P3DeKzvPNEo/gyr9iEUL4qLKxQ/siw2HD064VMnZnE9AmKY1UshEl3yoGkLNDjGlcjQVQaGqFGux4roulWxFhgxuamoJpCI98r9oPaTum4svYt/AcKpeyLMTO/9Fb55SkE/GWusanQNnbVymmnH+4QVBO0A/PA1by6N8eFSvkPBO3/50GdVvmZc+6gUAs+AGSN232/sjd2dghqwEmJax/CpfkmsmD0kW8eP98MjY2zAfmmfc/X8Hxz9xYanNQWmu0wP72FWoJq2kJDw4G63WNsifZjhVPaEstw2YSstyrmrKx3T8zVBgv7KqDkkulkk4APD1ZvEmAG9f6O/LZTyn8Yj5fNfb/8tqH3p6WnNp09UL3vhVZ+x+o4CBW3JzumquvO1cxZg4q497rd86BcVF0PAYwTpCyQ3Dqydil/Efm2gopzOFyak0feW26E72C5RBNKxCkuk4YfbppZsFuT87cE1XXvaxxuhsc40fE8C6BfASpg1QmB32j5oh8Kj4n6r5rslYKrppXEeR2pNBA/Ee3zAXUXUIQsOGEcK7YIJ/A7JGOanFtAP/rTzK1wf8MjWMP/hBsy5MyAhQy5bYCnvgeS9rHzHo9PTiHyPK33JqbfCaq+wTNPeMMDbb3muWN2j1zR70B19Q9sKfvqnwRR/z8= \ No newline at end of file diff --git a/doc/tracker_sequence_diagram.svg b/doc/tracker_sequence_diagram.svg index ee79363..7018a9a 100644 --- a/doc/tracker_sequence_diagram.svg +++ b/doc/tracker_sequence_diagram.svg @@ -1,3 +1,3 @@ -
Tracker
Tracker
Client1
Client1
:Object
:Object
Server1
Server1
Note
Note
REGISTER(udp+tcp)
REGISTER(udp+tc...
LIST REQ
LIST REQ
LIST RESP(file1, file2)
LIST RESP(f...
DISCOVER RESP(server1-udp-tcp, server2-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Server2
Server2
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
DISCOVER REQ()
DISCOVER RE...
LIST RESP(file2, file3)
LIST RESP(f...
LIST REQ
LIST REQ
Server3
Server3
REGISTER(udp+tcp)
REGISTER(ud...
LIST REQ
LIST REQ
LIST RESP(file1, file3)
LIST RESP(f...
LIST RESP(file2, file2)
LIST RESP(f...
DISCOVER REQ(fichier2)
DISCOVER RE...
Now the client knows server1 and server3 have file1: download can begin.
Now the client knows server1 and server3 have file1: download can begin.
DISCOVER RESP(server1-udp-tcp, server3-udp-tcp)
DISCOVER RE...
Viewer does not support full SVG 1.1
\ No newline at end of file +
Tracker
Tracker
Client1
Client1
:Object
:Object
Server1
Server1
Note
Note
REGISTER()
REGISTER()
LIST REQ
LIST REQ
LIST RESP(file1, file2)
LIST RESP(f...
DISCOVER RESP(server1, server2, server3)
DISCOVER RE...
Server2
Server2
REGISTER()
REGISTER()
LIST REQ
LIST REQ
DISCOVER REQ()
DISCOVER RE...
LIST RESP(file2, file3)
LIST RESP(f...
LIST REQ
LIST REQ
Server3
Server3
REGISTER()
REGISTER()
LIST REQ
LIST REQ
LIST RESP(file1, file3)
LIST RESP(f...
LIST RESP(file2, file2)
LIST RESP(f...
DISCOVER REQ(fichier2)
DISCOVER RE...
Now the client knows server1 and server3 have file1: download can begin.
Now the client knows server1 and server3 have file1: download can begin.
DISCOVER RESP(server1, server3)
DISCOVER RE...
Viewer does not support full SVG 1.1
\ No newline at end of file From 5c89bc6957251ad5fbc3ccea43f8d0778cbdd87e Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 17:31:03 +0100 Subject: [PATCH 11/40] Add protocol elements for tracker Needs to implements tracker now. --- src/protocolP2P/CodeType.java | 1 + src/protocolP2P/DiscoverRequest.java | 65 +++++++++++++ src/protocolP2P/DiscoverResponse.java | 111 ++++++++++++++++++++++ src/protocolP2P/FilePart.java | 2 +- src/protocolP2P/Payload.java | 39 +++++--- src/protocolP2P/ProtocolP2PPacket.java | 7 ++ src/protocolP2P/ProtocolP2PPacketTCP.java | 12 +++ src/protocolP2P/ProtocolP2PPacketUDP.java | 13 ++- src/protocolP2P/RequestResponseCode.java | 7 +- src/remoteException/NotATracker.java | 7 ++ src/serverP2P/ServerManagementTCP.java | 25 ++++- src/serverP2P/ServerManagementUDP.java | 17 ++++ src/tools/BytesArrayTools.java | 31 ++++++ src/tools/HostItem.java | 14 +++ 14 files changed, 334 insertions(+), 17 deletions(-) create mode 100644 src/protocolP2P/DiscoverRequest.java create mode 100644 src/protocolP2P/DiscoverResponse.java create mode 100644 src/remoteException/NotATracker.java diff --git a/src/protocolP2P/CodeType.java b/src/protocolP2P/CodeType.java index e38de49..87f3e49 100644 --- a/src/protocolP2P/CodeType.java +++ b/src/protocolP2P/CodeType.java @@ -8,6 +8,7 @@ package protocolP2P; */ public enum CodeType { REQUEST, + REQUEST_TRACKER, RESPONSE, ERROR } diff --git a/src/protocolP2P/DiscoverRequest.java b/src/protocolP2P/DiscoverRequest.java new file mode 100644 index 0000000..b3a83aa --- /dev/null +++ b/src/protocolP2P/DiscoverRequest.java @@ -0,0 +1,65 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.BytesArrayTools; +import localException.InternalError; +import localException.SizeError; +import localException.ProtocolError; +import localException.TransmissionError; + +public class DiscoverRequest extends Payload { + + private String filename; + + /** Constructor with filename (typically used by client). If filename is null, it is initialized with "". + * @param filename Name of the file you want a server list of. + * @throws InternalError + */ + public DiscoverRequest(String filename) throws InternalError { + super(RequestResponseCode.DISCOVER_REQUEST); + if (filename == null) { + this.filename = ""; + } else { + this.filename = filename; + } + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected DiscoverRequest(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + filename = BytesArrayTools.readString(packet, Payload.PAYLOAD_START_POSITION, size); + } + + /** Returns a byte[] containing Packet with padding. + * This Packet is still incomplete and should not be send directly. + * ProtocolP2PPacket will use this method to generate the complete Packet. + * @return Packet with padding + * @throws InternalError + */ + protected byte[] toPacket() throws InternalError { + // compute total size + int size = PAYLOAD_START_POSITION + filename.length(); + byte[] packet = new byte[size + 1]; // java initialize all to zero + // set request/response code + packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; + // set Payload size + setPayloadSize(size - PAYLOAD_START_POSITION, packet); + // write filename to Packet + BytesArrayTools.write(packet, filename, PAYLOAD_START_POSITION); + return packet; + } + + /** Filename getter. + * @return filename + */ + public String getFilename() { + return filename; + } + +} diff --git a/src/protocolP2P/DiscoverResponse.java b/src/protocolP2P/DiscoverResponse.java new file mode 100644 index 0000000..b887dea --- /dev/null +++ b/src/protocolP2P/DiscoverResponse.java @@ -0,0 +1,111 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.HostItem; +import java.util.ArrayList; +import java.util.List; +import localException.InternalError; +import localException.SizeError; +import localException.ProtocolError; +import localException.TransmissionError; +import tools.BytesArrayTools; + +public class DiscoverResponse extends Payload { + + private List hostList; + private String filename; + private static final int FILENAME_SIZE_POSITION = PAYLOAD_START_POSITION; + private static final int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4; + + /** Constructor with filename (typically used by tracker). If filename is null, it is initialized with "". + * @param filename Name of the file related to the server list. + * @param hostList List of servers + * @throws InternalError + */ + public DiscoverResponse(String filename, List hostList) throws InternalError { + super(RequestResponseCode.DISCOVER_RESPONSE); + this.filename = filename; + this.hostList = hostList; + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected DiscoverResponse(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + /* Read filename size */ + int filenameSize = BytesArrayTools.readInt(packet, FILENAME_SIZE_POSITION); + + /* Read filename */ + filename = BytesArrayTools.readString(packet, FILENAME_POSITION, filenameSize); + + // TODO + hostList = new ArrayList<>(); + int i = FILENAME_POSITION + filenameSize; + while(i getHostList() { + return hostList; + } + + /** Filename getter. + * @return filename + */ + public String getFilename() { + return filename; + } +} diff --git a/src/protocolP2P/FilePart.java b/src/protocolP2P/FilePart.java index 0863c0b..c394b0f 100644 --- a/src/protocolP2P/FilePart.java +++ b/src/protocolP2P/FilePart.java @@ -83,7 +83,7 @@ public class FilePart extends Payload { // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; // set Payload size - setPayloadSize(size - OFFSET_POSITION, packet); + setPayloadSize(size - PAYLOAD_START_POSITION, packet); // write offset to Packet BytesArrayTools.write(packet, OFFSET_POSITION, offset); // write totalSize to Packet diff --git a/src/protocolP2P/Payload.java b/src/protocolP2P/Payload.java index f0dcb34..8a84384 100644 --- a/src/protocolP2P/Payload.java +++ b/src/protocolP2P/Payload.java @@ -5,6 +5,8 @@ import protocolP2P.FileList; import protocolP2P.LoadRequest; import protocolP2P.HashRequest; import protocolP2P.HashResponse; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; @@ -27,11 +29,13 @@ public class Payload { */ public Payload(RequestResponseCode requestResponseCode) throws InternalError { /* asserts to help debugging */ - assert requestResponseCode != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; - assert requestResponseCode != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; - assert requestResponseCode != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; - assert requestResponseCode != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class"; - assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; + assert requestResponseCode != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; + assert requestResponseCode != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; + assert requestResponseCode != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; + assert requestResponseCode != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class"; + assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; + assert requestResponseCode != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; + assert requestResponseCode != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; this.requestResponseCode = requestResponseCode; checkRequestResponseCode(); // this can throw InternalError } @@ -46,13 +50,17 @@ public class Payload { */ protected Payload(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { /* asserts to help debugging */ - assert getPayloadSize(packet) + 8 <= packet.length : "Payload is truncated"; - if (packet.length < getPayloadSize(packet) + 8) { + assert getPayloadSize(packet) + PAYLOAD_START_POSITION <= packet.length : "Payload is truncated"; + if (packet.length < getPayloadSize(packet) + PAYLOAD_START_POSITION) { throw new TransmissionError(); } - assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; - assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; - assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]); checkRequestResponseCode(); // this can throw InternalError } @@ -62,9 +70,14 @@ public class Payload { */ private void checkRequestResponseCode() throws InternalError { /* Incorrect use cases (use subclasses instead) */ - if ((requestResponseCode == RequestResponseCode.LIST_RESPONSE && !(this instanceof FileList)) - || (requestResponseCode == RequestResponseCode.LOAD_RESPONSE && !(this instanceof FilePart)) - || (requestResponseCode == RequestResponseCode.LOAD_REQUEST && !(this instanceof LoadRequest))) { + if ((requestResponseCode == RequestResponseCode.LIST_RESPONSE && !(this instanceof FileList)) + || (requestResponseCode == RequestResponseCode.LOAD_RESPONSE && !(this instanceof FilePart)) + || (requestResponseCode == RequestResponseCode.LOAD_REQUEST && !(this instanceof LoadRequest)) + || (requestResponseCode == RequestResponseCode.HASH_REQUEST && !(this instanceof HashRequest)) + || (requestResponseCode == RequestResponseCode.HASH_RESPONSE && !(this instanceof HashResponse)) + || (requestResponseCode == RequestResponseCode.DISCOVER_REQUEST && !(this instanceof DiscoverRequest)) + || (requestResponseCode == RequestResponseCode.DISCOVER_RESPONSE && !(this instanceof DiscoverResponse)) + ) { throw new InternalError(); } } diff --git a/src/protocolP2P/ProtocolP2PPacket.java b/src/protocolP2P/ProtocolP2PPacket.java index be23aec..037da9b 100644 --- a/src/protocolP2P/ProtocolP2PPacket.java +++ b/src/protocolP2P/ProtocolP2PPacket.java @@ -13,6 +13,7 @@ import remoteException.VersionRemoteError; import remoteException.EmptyFile; import java.net.InetAddress; import java.io.IOException; +import tools.HostItem; /** Representation of packet. * @author Louis Royer @@ -50,6 +51,12 @@ public abstract class ProtocolP2PPacket { */ public abstract void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException, SocketClosed; + /** Get hostItem of the sender + * @return hostItem of the sender + * @throws InternalError + */ + public abstract HostItem getHostItem() throws InternalError; + /** Receive a response * @throws EmptyFile * @throws NotFound diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index 7c80474..ddde5f3 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -12,6 +12,7 @@ import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; import tools.BytesArrayTools; +import tools.HostItem; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; @@ -319,4 +320,15 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { return packet; } + /** Get hostItem of the sender + * @return hostItem of the sender + * @throws InternalError + */ + public HostItem getHostItem() throws InternalError { + if (responseSocket == null) { + throw new InternalError(); + } + return new HostItem(responseSocket.getInetAddress().getHostName(), responseSocket.getPort()); + } + } diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index aea6dcc..db92d2f 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -12,6 +12,7 @@ import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; import tools.BytesArrayTools; +import tools.HostItem; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; @@ -353,7 +354,6 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @param packet full packet * @throws TransmissionError */ - private void checkCheckSum(byte [] packet) throws TransmissionError { try { int checksum = BytesArrayTools.readInt16Bits(packet, CHECKSUM_POSITION); @@ -365,4 +365,15 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { throw new TransmissionError(); } } + + /** Get hostItem of the sender + * @return hostItem of the sender + * @throws InternalError + */ + public HostItem getHostItem() throws InternalError { + if (responseSocket == null) { + throw new InternalError(); + } + return new HostItem(responseSocket.getInetAddress().getHostName(), responseSocket.getPort()); + } } diff --git a/src/protocolP2P/RequestResponseCode.java b/src/protocolP2P/RequestResponseCode.java index a6e68d3..f216d8c 100644 --- a/src/protocolP2P/RequestResponseCode.java +++ b/src/protocolP2P/RequestResponseCode.java @@ -15,15 +15,20 @@ public enum RequestResponseCode { LIST_REQUEST(CodeType.REQUEST, (byte)0x00), LOAD_REQUEST(CodeType.REQUEST, (byte)0x01), HASH_REQUEST(CodeType.REQUEST, (byte)0x02), + DISCOVER_REQUEST(CodeType.REQUEST_TRACKER, (byte)0x03), + REGISTER(CodeType.REQUEST_TRACKER, (byte)0x04), + UNREGISTER(CodeType.REQUEST_TRACKER, (byte)0x05), LIST_RESPONSE(CodeType.RESPONSE, (byte)0x80), LOAD_RESPONSE(CodeType.RESPONSE, (byte)0x81), HASH_RESPONSE(CodeType.RESPONSE, (byte)0x82), + DISCOVER_RESPONSE(CodeType.RESPONSE, (byte)0x83), VERSION_ERROR(CodeType.ERROR, (byte)0xC0), PROTOCOL_ERROR(CodeType.ERROR, (byte)0xC1), INTERNAL_ERROR(CodeType.ERROR, (byte)0xC2), EMPTY_DIRECTORY(CodeType.ERROR, (byte)0xC3), NOT_FOUND(CodeType.ERROR, (byte)0xC4), - EMPTY_FILE(CodeType.ERROR, (byte)0xC5); + EMPTY_FILE(CodeType.ERROR, (byte)0xC5), + NOT_A_TRACKER(CodeType.ERROR, (byte)0xC6); public final CodeType codeType; public final byte codeValue; diff --git a/src/remoteException/NotATracker.java b/src/remoteException/NotATracker.java new file mode 100644 index 0000000..dbccea2 --- /dev/null +++ b/src/remoteException/NotATracker.java @@ -0,0 +1,7 @@ +package remoteException; + +import exception.RemoteException; + +public class NotATracker extends exception.RemoteException { + private static final long serialVersionUID = 12L; +} diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 257fe3d..316143e 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -136,6 +136,18 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP(addr + "HASH_REQUEST", LogLevel.Action); sendHashResponse(pd); break; + case DISCOVER_REQUEST: + logger.writeTCP(addr + "DISCOVER_REQUEST", LogLevel.Action); + sendNotATracker(pd); + break; + case UNREGISTER: + logger.writeTCP(addr + "UNREGISTER", LogLevel.Action); + sendNotATracker(pd); + break; + case REGISTER: + logger.writeTCP(addr + "REGISTER", LogLevel.Action); + sendNotATracker(pd); + break; default: logger.writeTCP(addr + "Received grabbage", LogLevel.Action); sendInternalError(pd); @@ -198,7 +210,18 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP(e, LogLevel.Error); } } - + + /** Send a NotATracker error message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendNotATracker(ProtocolP2PPacketTCP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_A_TRACKER))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + /** Send response to list request * @param pd Request received */ diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 986e8d0..3289796 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -89,6 +89,12 @@ public class ServerManagementUDP implements Runnable { logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); sendHashResponse(pd); break; + case DISCOVER_REQUEST: + case UNREGISTER: + case REGISTER: + logger.writeUDP("Received Tracker request", LogLevel.Action); + sendNotATracker(pd); + break; default: sendInternalError(pd); } @@ -213,6 +219,17 @@ public class ServerManagementUDP implements Runnable { } } + /** Send a NotATracker error message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendNotATracker(ProtocolP2PPacketUDP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_A_TRACKER))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + /** Send hash response to hash request * @param pd Request received */ diff --git a/src/tools/BytesArrayTools.java b/src/tools/BytesArrayTools.java index 8f80fcb..f1cbe85 100644 --- a/src/tools/BytesArrayTools.java +++ b/src/tools/BytesArrayTools.java @@ -219,6 +219,37 @@ public class BytesArrayTools { } } + /** Read string from byte array + * @param array Byte array to read + * @param start start position in byte array + * @param endStr End string delimiter + * @return String read + * @throws InternalError + */ + public static String readString(byte[] array, int start, String endStr) throws InternalError { + boolean failed = false; + try { + int i = start; + while(true) { + for(byte b: endStr.getBytes()) { + if (b != array[i]) { + failed = true; + break; + } + } + if (failed) { + i++; + failed = false; + } else { + break; + } + } + return readString(array, start, i -1 - start); + } catch(IndexOutOfBoundsException e) { + throw new InternalError(); + } + } + /** Write byte Array to byte Array. * @param dst Destination byte Array * @param src Source byte Array diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index ffe2f58..9bba17b 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -79,10 +79,24 @@ public class HostItem { } return udpSocket; } + + /** Closes udp socket + */ public void closeUDPSocket() { if (udpSocket != null) { udpSocket.close(); } udpSocket = null; } + + /** Getter for hostname */ + public String getHostname() { + return hostname; + } + + /** Getter for port */ + public int getPort() { + return port; + } + } From 6d7fabaf1c811378747cb0f8154b159069623fb4 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 19 Mar 2020 22:58:57 +0100 Subject: [PATCH 12/40] Add tracker --- src/tools/HostItem.java | 7 + src/tracker/Tracker.java | 47 +++++ src/tracker/TrackerManagementTCP.java | 270 ++++++++++++++++++++++++++ src/tracker/TrackerManagementUDP.java | 221 +++++++++++++++++++++ 4 files changed, 545 insertions(+) create mode 100644 src/tracker/Tracker.java create mode 100644 src/tracker/TrackerManagementTCP.java create mode 100644 src/tracker/TrackerManagementUDP.java diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index 9bba17b..f2bfbf3 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -98,5 +98,12 @@ public class HostItem { public int getPort() { return port; } + + /** To string + * @return String representation + */ + public String toString() { + return getHostname() + " (port " + getPort() + ")"; + } } diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java new file mode 100644 index 0000000..bb82422 --- /dev/null +++ b/src/tracker/Tracker.java @@ -0,0 +1,47 @@ +package tracker; +import tracker.TrackerManagementTCP; +import tracker.TrackerManagementUDP; +import tools.Directories; +import tools.Logger; + +/** Tracker implementation + * First argument of main method is port listened by the tracker, and is mandatory. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class Tracker { + private int port; + private Directories directories; + private Logger logger; + + /** Constructor with portStr containing a port number. + * @param portStr String containing port number of listening. + */ + public Tracker(String portStr) { + port = Integer.valueOf(Integer.parseInt(portStr)); + directories = new Directories("P2P_JAVA_PROJECT_TRACKER_" + port); + logger = new Logger(directories.getDataHomeDirectory() + "tracker.log"); + System.out.println("Tracker will listen on port " + port + " and write logs into " + directories.getDataHomeDirectory()); + directories.askOpenDataHomeDirectory(null); + } + + /** Main program entry point + * first parameter is port number and is mandatory + * to test, run with: java -ea serverP2P.ServerP2P -- + * @param args parameters + */ + public static void main(String [] args) { + Tracker t = new Tracker(args[1]); + TrackerManagementUDP tmudp = new TrackerManagementUDP(t.port, t.logger); + TrackerManagementTCP tmtcp = new TrackerManagementTCP(t.port, t.logger); + Thread tudp = new Thread(tmudp); + tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(tmtcp); + ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); + ttcp.start(); + } + +} diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java new file mode 100644 index 0000000..91d7dab --- /dev/null +++ b/src/tracker/TrackerManagementTCP.java @@ -0,0 +1,270 @@ +package tracker; +import tools.Logger; +import tools.LogLevel; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import protocolP2P.ProtocolP2PPacketTCP; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.RequestResponseCode; +import protocolP2P.Payload; +import tools.HostItem; +import java.util.ArrayList; +import java.util.List; +import java.io.IOException; +import exception.LocalException; +import java.util.Map; +import java.util.HashMap; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; +import protocolP2P.FileList; +import protocolP2P.HashRequest; +import localException.InternalError; + + +/** Tracker management implementation with tcp + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class TrackerManagementTCP implements Runnable { + + private int port; + private Logger logger; + private ServerSocket socket; + private List hostList = new ArrayList<>(); + private Map> fileList = new HashMap<>(); + + /** Constructor with port and logger. + * @param port Port used to listen. + * @param logger Logger object + */ + public TrackerManagementTCP(int port, Logger logger) { + this.port = port; + this.logger = logger; + try { + socket = new ServerSocket(port); + } catch (SocketException e) { + logger.writeTCP("Error: cannot listen on port " + port, LogLevel.Error); + System.exit(-1); + } catch (IOException e) { + logger.writeTCP("Error: cannot openning socket", LogLevel.Error); + System.exit(-2); + } + } + + /** Implementation of runnable. This methods allows to run the server. + */ + public void run() { + logger.writeTCP("Tracker sucessfully started", LogLevel.Info); + do { + try { + Socket s = socket.accept(); + ClientHandler c = new ClientHandler(s); + (new Thread(c)).start(); + } catch (IOException e) { + logger.writeTCP("Error while accepting new connection", LogLevel.Warning); + } + } while(true); + } + + + /** Private runnable class allowing to serve one client. + */ + private class ClientHandler implements Runnable { + private Socket s; + private String addr; + /** Constructor with a socket. + * @param s Socket of this client + */ + public ClientHandler(Socket s) { + this.s = s; + this.addr = "[" +s.getInetAddress().getHostAddress() + "]:" + s.getPort() + " "; + } + + /** Implementation of runnable. This method allow to serve one client. + */ + public void run() { + + boolean end = false; + logger.writeTCP(addr + "New connection", LogLevel.Action); + do { + end = handleRequest(); + } while(!end); + logger.writeTCP(addr + "End of connection", LogLevel.Action); + } + + /** Respond to next request incomming on socket s. + * @param s Socket used to read request and send response + * @return true if cannot expect another request (ie, socket is closed) + */ + private boolean handleRequest() { + try { + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)socket); + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + logger.writeTCP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case LIST_REQUEST: + logger.writeTCP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); + sendEmptyDirectory(pd); + break; + case HASH_REQUEST: + logger.writeTCP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case REGISTER: + handleRegister(pd); + break; + case UNREGISTER: + handleUnregister(pd); + break; + case DISCOVER_REQUEST: + handleDiscover(pd); + break; + case LIST_RESPONSE: + handleListResponse(pd); + break; + default: + logger.writeTCP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + break; + } + } catch (IOException e) { + logger.writeTCP(e, LogLevel.Warning); + return true; + } catch (LocalException e) { + logger.writeTCP(e, LogLevel.Warning); + return true; + } + return false; + } + + /** Send a not found message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendNotFound(ProtocolP2PPacketTCP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Send an empty directory message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendEmptyDirectory(ProtocolP2PPacketTCP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Send an internal error message. + * @param pd ProtocolP2PPacketTCP to respond + */ + private void sendInternalError(ProtocolP2PPacketTCP pd) { + logger.writeTCP("Internal Error", LogLevel.Warning); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Handle Registering + * @param pd ProtocolP2PPacketTCP to respond + * @throws InternalError + */ + private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { + // add host to known host list + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + hostList.add(pd.getHostItem()); + } + // send a list request + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST))); + logger.writeTCP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + } catch (Exception e) { + // remove from list because list request could not be send + hostList.remove(host); + logger.writeTCP("Aborting the add of host " + host, LogLevel.Action); + logger.writeTCP(e, LogLevel.Error); + } + } + + /** Handle Unregistering + * @param pd ProtocolP2PPacketTCP to respond + * @throws InternalError + */ + private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { + HostItem host = pd.getHostItem(); + logger.writeTCP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + hostList.remove(host); + for(String f: fileList.keySet()) { + fileList.get(f).remove(host); + if(fileList.get(f).isEmpty()) { + fileList.remove(f); + } + } + } + + /** Handle Discover request + * @param pd ProtocolP2PPacketTCP to respond + * @throws InternalError + */ + private void handleDiscover(ProtocolP2PPacketTCP pd) throws InternalError { + logger.writeTCP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; + if (!(p instanceof DiscoverRequest)) { + sendInternalError(pd); + } else { + String filename = ((HashRequest)p).getFilename(); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + } + } + } + + /** Handle List Responses + * @param pd ProtocolP2PPacketTCP response + * @throws InternalError + */ + private void handleListResponse(ProtocolP2PPacketTCP pd) throws InternalError { + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + logger.writeTCP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + } else { + logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + sendInternalError(pd); + } else { + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } + } + } + } + } + } +} diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java new file mode 100644 index 0000000..f1448f8 --- /dev/null +++ b/src/tracker/TrackerManagementUDP.java @@ -0,0 +1,221 @@ +package tracker; +import tools.Logger; +import tools.LogLevel; +import java.net.DatagramSocket; +import protocolP2P.ProtocolP2PPacketUDP; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.RequestResponseCode; +import protocolP2P.Payload; +import tools.HostItem; +import java.util.ArrayList; +import java.util.List; +import java.io.IOException; +import java.net.SocketException; +import exception.LocalException; +import java.util.Map; +import java.util.HashMap; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; +import protocolP2P.FileList; +import protocolP2P.HashRequest; +import localException.InternalError; + +/** Tracker management implementation with udp + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class TrackerManagementUDP implements Runnable { + + private int port; + private Logger logger; + private DatagramSocket socket; + private List hostList = new ArrayList<>(); + private Map> fileList = new HashMap<>(); + + /** Constructor with port and logger. + * @param port Port used to listen. + * @param logger Logger object + */ + public TrackerManagementUDP(int port, Logger logger) { + this.port = port; + this.logger = logger; + try { + socket = new DatagramSocket(port); + } catch (SocketException e) { + logger.writeUDP("Error: cannot listen on port " + port, LogLevel.Error); + System.exit(-1); + } + } + + /** Implementation of runnable. This methods allows to run the tracker. + */ + public void run() { + logger.writeUDP("Tracker successfully started", LogLevel.Info); + while(true) { + try { + ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + logger.writeUDP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case LIST_REQUEST: + logger.writeUDP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); + sendEmptyDirectory(pd); + break; + case HASH_REQUEST: + logger.writeUDP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case REGISTER: + handleRegister(pd); + break; + case UNREGISTER: + handleUnregister(pd); + break; + case DISCOVER_REQUEST: + handleDiscover(pd); + break; + case LIST_RESPONSE: + handleListResponse(pd); + break; + default: + logger.writeUDP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + break; + } + } catch (IOException e) { + logger.writeUDP(e, LogLevel.Warning); + } catch (LocalException e) { + logger.writeUDP(e, LogLevel.Warning); + } + } + } + + /** Send a not found message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendNotFound(ProtocolP2PPacketUDP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Send an empty directory message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendEmptyDirectory(ProtocolP2PPacketUDP pd) { + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Send an internal error message. + * @param pd ProtocolP2PPacketUDP to respond + */ + private void sendInternalError(ProtocolP2PPacketUDP pd) { + logger.writeUDP("Internal Error", LogLevel.Warning); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Handle Registering + * @param pd ProtocolP2PPacketUDP to respond + * @throws InternalError + */ + private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { + // add host to known host list + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + hostList.add(pd.getHostItem()); + } + // send a list request + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST))); + logger.writeUDP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + } catch (Exception e) { + // remove from list because list request could not be send + hostList.remove(host); + logger.writeUDP("Aborting the add of host " + host, LogLevel.Action); + logger.writeUDP(e, LogLevel.Error); + } + } + + /** Handle Unregistering + * @param pd ProtocolP2PPacketUDP to respond + * @throws InternalError + */ + private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { + HostItem host = pd.getHostItem(); + logger.writeUDP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + hostList.remove(host); + for(String f: fileList.keySet()) { + fileList.get(f).remove(host); + if(fileList.get(f).isEmpty()) { + fileList.remove(f); + } + } + } + + /** Handle Discover request + * @param pd ProtocolP2PPacketUDP to respond + * @throws InternalError + */ + private void handleDiscover(ProtocolP2PPacketUDP pd) throws InternalError { + logger.writeUDP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; + if (!(p instanceof DiscoverRequest)) { + sendInternalError(pd); + } else { + String filename = ((HashRequest)p).getFilename(); + try { + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + } + } + } + + /** Handle List Responses + * @param pd ProtocolP2PPacketUDP response + * @throws InternalError + */ + private void handleListResponse(ProtocolP2PPacketUDP pd) throws InternalError { + HostItem host = pd.getHostItem(); + if (!hostList.contains(host)) { + logger.writeUDP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + } else { + logger.writeUDP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + sendInternalError(pd); + } else { + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } + } + } + } + } +} From 07d92762326fb3cb85dc8d57a8daa968da659a36 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 00:11:13 +0100 Subject: [PATCH 13/40] Changes in protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit À implémenter: Register + Unregister dans protocolP2P. Encore des erreurs: - [UDP] ICMP Port unreachable, c’est parce qu’on essaie de se connecter à un port qui est fermé. c’est pour ça qu’il faut donner le port dans register et dans unregister (sinon on a le mauvais HostItem). - [TCP] une autre erreur que je corrigerai demain --- doc/protocol.md | 10 ++++++++ src/clientP2P/ClientP2P.java | 6 +++-- src/protocolP2P/ProtocolP2PPacketUDP.java | 6 +++-- src/serverP2P/ServerManagementTCP.java | 27 +++++++++++++++++++++- src/serverP2P/ServerManagementUDP.java | 28 +++++++++++++++++++++-- src/serverP2P/ServerP2P.java | 14 +++++++----- src/tools/HostItem.java | 21 ++++++++++++++++- src/tracker/TrackerManagementTCP.java | 10 ++++---- src/tracker/TrackerManagementUDP.java | 8 +++---- 9 files changed, 107 insertions(+), 23 deletions(-) diff --git a/doc/protocol.md b/doc/protocol.md index a01a6c9..352078f 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -106,11 +106,21 @@ A algo hash bloc contains: #### Register Used by a server to register itself on a tracker. Server may want to do a free `DISCOVER` to check if they have been registered. +Payload contains: + +``` +2 bytes: [] +``` #### Unregister Used by a server to unregister itself from a tracker. No error is raised if the server was not registered. Server may want to do a free `DISCOVER` to check if they have been unregistered. +Payload contains: + +``` +2 bytes: [] +``` #### Discover request If payload size is null, lists all servers registered. diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 34a9519..e08c1fb 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -30,6 +30,7 @@ public class ClientP2P { private Directories directories; private List hostList; private static final int defaultPort = 20000; + private HostItem tracker; /** Initialize loggers if directories and logger are null, @@ -47,6 +48,7 @@ public class ClientP2P { * @param portStr String containing port for server listenning. */ public ClientP2P(String portStr) { + tracker = new HostItem("localhost", 30000); // TODO : make it configurable try{ port = Integer.valueOf(Integer.parseInt(portStr)); } catch (NumberFormatException e){ @@ -84,8 +86,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index db92d2f..500fa57 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -34,6 +34,7 @@ import java.io.IOException; public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { private final static int CHECKSUM_POSITION = 2; + private HostItem remoteHost; private SocketAddress responseSocketAddress; // socket address used when receptionning request and to sending response private DatagramSocket responseSocket; // socket used to recept request and send response private DatagramSocket requestSocket; // socket used to send request and to reception response @@ -113,6 +114,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { DatagramPacket reception = new DatagramPacket(packet, packet.length); ss.receive(reception); responseSocketAddress = reception.getSocketAddress(); + remoteHost = new HostItem(reception.getAddress().getHostName(), reception.getPort()); // contruction boolean protocolError = false; try { @@ -371,9 +373,9 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @throws InternalError */ public HostItem getHostItem() throws InternalError { - if (responseSocket == null) { + if (remoteHost == null) { throw new InternalError(); } - return new HostItem(responseSocket.getInetAddress().getHostName(), responseSocket.getPort()); + return remoteHost; } } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 316143e..6001cdf 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -32,6 +32,7 @@ import remoteException.EmptyFile; import java.util.Arrays; import tools.Logger; import tools.LogLevel; +import tools.HostItem; import java.util.HashMap; import java.util.Map; import protocolP2P.HashAlgorithm; @@ -53,12 +54,14 @@ public class ServerManagementTCP implements Runnable { private int TCPPort; private ServerSocket socket; private Logger logger; + private HostItem tracker; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. * @param baseDirectory the root directory where files are stored * @param TCPPort the server will listen on this port */ - public ServerManagementTCP(String baseDirectory, int TCPPort, Logger logger) { + public ServerManagementTCP(String baseDirectory, int TCPPort, Logger logger, HostItem tracker) { + this.tracker = tracker; this.logger = logger; this.baseDirectory = baseDirectory; this.TCPPort = TCPPort; @@ -79,6 +82,12 @@ public class ServerManagementTCP implements Runnable { */ public void run() { logger.writeTCP("Server sucessfully started", LogLevel.Info); + try { + registerTracker(); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + System.exit(-4); + } do { try { Socket s = socket.accept(); @@ -332,4 +341,20 @@ public class ServerManagementTCP implements Runnable { } } + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + public void registerTracker() throws InternalError, IOException, SocketClosed { + logger.writeTCP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.UNREGISTER)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.REGISTER)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering completed", LogLevel.Debug); + tracker.closeTCPSocket(); + } + } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 3289796..0de0ef7 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -36,6 +36,7 @@ import java.util.Map; import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; +import tools.HostItem; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. * @author Louis Royer @@ -51,15 +52,17 @@ public class ServerManagementUDP implements Runnable { private int UDPPort; private DatagramSocket socket; private Logger logger; + private HostItem tracker; /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. * @param baseDirectory the root directory where files are stored * @param UDPPort the server will listen on this port */ - public ServerManagementUDP(String baseDirectory, int UDPPort, Logger logger) { + public ServerManagementUDP(String baseDirectory, int UDPPort, Logger logger, HostItem tracker) { this.logger = logger; this.baseDirectory = baseDirectory; this.UDPPort = UDPPort; + this.tracker = tracker; initFileList(); initSha512(); try { @@ -74,6 +77,12 @@ public class ServerManagementUDP implements Runnable { */ public void run() { logger.writeUDP("Server sucessfully started", LogLevel.Info); + try { + registerTracker(); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + System.exit(-4); + } while(true) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); @@ -268,5 +277,20 @@ public class ServerManagementUDP implements Runnable { } } } - + + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + public void registerTracker() throws InternalError, IOException, SocketClosed { + logger.writeUDP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.UNREGISTER)); + p.sendRequest((Object)tracker.getUDPSocket()); + logger.writeUDP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.REGISTER)); + p.sendRequest((Object)tracker.getUDPSocket()); + tracker.closeUDPSocket(); + logger.writeUDP("Registering completed", LogLevel.Debug); + } } diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index be8bfec..abfdb66 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -3,6 +3,7 @@ import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; import tools.Directories; import tools.Logger; +import tools.HostItem; /** Server only implementation * First argument of main method is port listened by the server, and is mandatory. @@ -16,12 +17,14 @@ public class ServerP2P { private Directories directories; static private final String subdir = "seeded/"; private Logger logger; + private HostItem tracker; /** Constructor with portStr containing a port number. * @param portStr String containing port number of listening. */ - public ServerP2P(String portStr) { + public ServerP2P(String portStr, String trackerHostname, String trackerPortStr) { port = Integer.valueOf(Integer.parseInt(portStr)); + tracker = new HostItem(trackerHostname, Integer.valueOf(Integer.parseInt(trackerPortStr))); directories = new Directories("P2P_JAVA_PROJECT_SERVER_" + port); directories.createSubdir(subdir); logger = new Logger(directories.getDataHomeDirectory() + "server.log"); @@ -31,18 +34,17 @@ public class ServerP2P { /** Main program entry point * first parameter is port number and is mandatory - * to test, run with: java -ea serverP2P.ServerP2P -- + * to test, run with: java -ea serverP2P.ServerP2P -- * @param args parameters */ public static void main(String [] args) { - if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ System.out.println("usage : java -ea serveurP2P.ServeurP2P -- "); } else{ - ServerP2P s = new ServerP2P(args[1]); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger); + ServerP2P s = new ServerP2P(args[1], args[2], args[3]); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT"); tudp.start(); diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index f2bfbf3..fe15007 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -105,5 +105,24 @@ public class HostItem { public String toString() { return getHostname() + " (port " + getPort() + ")"; } - + + /** Override of equals method + * @param other Object to test equality with + * @return true if equals + */ + public boolean equals(Object other) { + boolean result = false; + if (other instanceof HostItem) { + HostItem that = (HostItem) other; + result = this.getHostname() == that.getHostname() && this.getPort() == that.getPort(); + } + return result; + } + + /** Override of hashCode method + * @return a hash code for this object. + */ + public int hashCode() { + return hostname.hashCode() ^ port; + } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 91d7dab..e8795d9 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -101,7 +101,7 @@ public class TrackerManagementTCP implements Runnable { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)socket); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -125,9 +125,6 @@ public class TrackerManagementTCP implements Runnable { case DISCOVER_REQUEST: handleDiscover(pd); break; - case LIST_RESPONSE: - handleListResponse(pd); - break; default: logger.writeTCP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); sendInternalError(pd); @@ -189,8 +186,11 @@ public class TrackerManagementTCP implements Runnable { } // send a list request try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST))); + ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); + pLReq.sendRequest((Object)host.getTCPSocket()); logger.writeTCP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse()); + host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index f1448f8..c11c54c 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -79,9 +79,6 @@ public class TrackerManagementUDP implements Runnable { case DISCOVER_REQUEST: handleDiscover(pd); break; - case LIST_RESPONSE: - handleListResponse(pd); - break; default: logger.writeUDP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); sendInternalError(pd); @@ -141,8 +138,11 @@ public class TrackerManagementUDP implements Runnable { } // send a list request try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST))); + ProtocolP2PPacket pLReq =(ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); + pLReq.sendRequest((Object)host.getUDPSocket()); logger.writeUDP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse()); + host.closeUDPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); From a2f505c167df9807c80490922c9c4bcd088342a6 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 10:21:28 +0100 Subject: [PATCH 14/40] Add Register/Unregister --- doc/protocol.md | 3 +- src/protocolP2P/DiscoverRequest.java | 6 ++ src/protocolP2P/DiscoverResponse.java | 6 ++ src/protocolP2P/Payload.java | 8 +++ src/protocolP2P/ProtocolP2PPacketTCP.java | 12 ++++ src/protocolP2P/ProtocolP2PPacketUDP.java | 12 ++++ src/protocolP2P/Register.java | 77 +++++++++++++++++++++++ src/protocolP2P/Unregister.java | 77 +++++++++++++++++++++++ src/serverP2P/ServerManagementTCP.java | 51 +++++++++------ src/serverP2P/ServerManagementUDP.java | 51 +++++++++------ src/tracker/TrackerManagementTCP.java | 64 ++++++++++--------- src/tracker/TrackerManagementUDP.java | 65 ++++++++++--------- 12 files changed, 335 insertions(+), 97 deletions(-) create mode 100644 src/protocolP2P/Register.java create mode 100644 src/protocolP2P/Unregister.java diff --git a/doc/protocol.md b/doc/protocol.md index 352078f..64dae57 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -120,6 +120,7 @@ Payload contains: ``` 2 bytes: [] +? bytes: [] ``` #### Discover request @@ -128,7 +129,7 @@ If payload contains a filename, list all servers having this file in their list. ``` ? bytes: [] - +? bytes: [] ``` #### Discover response diff --git a/src/protocolP2P/DiscoverRequest.java b/src/protocolP2P/DiscoverRequest.java index b3a83aa..7ef1751 100644 --- a/src/protocolP2P/DiscoverRequest.java +++ b/src/protocolP2P/DiscoverRequest.java @@ -6,6 +6,12 @@ import localException.SizeError; import localException.ProtocolError; import localException.TransmissionError; +/** Representation of payload for discover request. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ public class DiscoverRequest extends Payload { private String filename; diff --git a/src/protocolP2P/DiscoverResponse.java b/src/protocolP2P/DiscoverResponse.java index b887dea..4c73e36 100644 --- a/src/protocolP2P/DiscoverResponse.java +++ b/src/protocolP2P/DiscoverResponse.java @@ -9,6 +9,12 @@ import localException.ProtocolError; import localException.TransmissionError; import tools.BytesArrayTools; +/** Representation of payload for discover response. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ public class DiscoverResponse extends Payload { private List hostList; diff --git a/src/protocolP2P/Payload.java b/src/protocolP2P/Payload.java index 8a84384..990df6b 100644 --- a/src/protocolP2P/Payload.java +++ b/src/protocolP2P/Payload.java @@ -7,6 +7,8 @@ import protocolP2P.HashRequest; import protocolP2P.HashResponse; import protocolP2P.DiscoverRequest; import protocolP2P.DiscoverResponse; +import protocolP2P.Register; +import protocolP2P.Unregister; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; @@ -36,6 +38,8 @@ public class Payload { assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; assert requestResponseCode != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; assert requestResponseCode != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; + assert requestResponseCode != RequestResponseCode.REGISTER || (this instanceof Register) : "REGISTER must use Register class"; + assert requestResponseCode != RequestResponseCode.UNREGISTER || (this instanceof Unregister) : "UNREGISTER must use Unregister class"; this.requestResponseCode = requestResponseCode; checkRequestResponseCode(); // this can throw InternalError } @@ -61,6 +65,8 @@ public class Payload { assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class"; assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class"; assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.REGISTER || (this instanceof Register) : "REGISTER must use Register class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.UNREGISTER || (this instanceof Unregister) : "UNREGISTER must use Unregister class"; requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]); checkRequestResponseCode(); // this can throw InternalError } @@ -77,6 +83,8 @@ public class Payload { || (requestResponseCode == RequestResponseCode.HASH_RESPONSE && !(this instanceof HashResponse)) || (requestResponseCode == RequestResponseCode.DISCOVER_REQUEST && !(this instanceof DiscoverRequest)) || (requestResponseCode == RequestResponseCode.DISCOVER_RESPONSE && !(this instanceof DiscoverResponse)) + || (requestResponseCode == RequestResponseCode.REGISTER && !(this instanceof Register)) + || (requestResponseCode == RequestResponseCode.UNREGISTER && !(this instanceof Unregister)) ) { throw new InternalError(); } diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index ddde5f3..f2254f8 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -289,6 +289,18 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { case HASH_RESPONSE: payload = (Payload) new HashResponse(packet); break; + case REGISTER: + payload = (Payload) new Register(packet); + break; + case UNREGISTER: + payload = (Payload) new Unregister(packet); + break; + case DISCOVER_REQUEST: + payload = (Payload) new DiscoverRequest(packet); + break; + case DISCOVER_RESPONSE: + payload = (Payload) new DiscoverResponse(packet); + break; default: payload = new Payload(packet); // this can throw TransmissionError break; diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index 500fa57..4bc98bb 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -287,6 +287,18 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { case HASH_RESPONSE: payload = (Payload) new HashResponse(packet); break; + case REGISTER: + payload = (Payload) new Register(packet); + break; + case UNREGISTER: + payload = (Payload) new Unregister(packet); + break; + case DISCOVER_REQUEST: + payload = (Payload) new DiscoverRequest(packet); + break; + case DISCOVER_RESPONSE: + payload = (Payload) new DiscoverResponse(packet); + break; default: payload = new Payload(packet); // this can throw TransmissionError break; diff --git a/src/protocolP2P/Register.java b/src/protocolP2P/Register.java new file mode 100644 index 0000000..790ac2b --- /dev/null +++ b/src/protocolP2P/Register.java @@ -0,0 +1,77 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.HostItem; +import tools.BytesArrayTools; +import localException.SizeError; +import localException.InternalError; +import localException.TransmissionError; +import localException.ProtocolError; + +/** Representation of payload for unregister. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class Register extends Payload { + private HostItem hostItem; + private static final int HOSTNAME_START_POSITION = PAYLOAD_START_POSITION + 2; + + /** Constructor with hostItem (typically used by client) + * @param hostItem Host you want to register. + * @throws InternalError + */ + public Register(HostItem hostItem) throws InternalError { + super(RequestResponseCode.REGISTER); + this.hostItem = hostItem; + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected Register(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + int port = BytesArrayTools.readInt16Bits(packet, PAYLOAD_START_POSITION); + String hostname = BytesArrayTools.readString(packet, HOSTNAME_START_POSITION, size - HOSTNAME_START_POSITION + PAYLOAD_START_POSITION); + hostItem = new HostItem(hostname, port); + } + + /** Returns a byte[] containing Packet with padding. + * This Packet is still incomplete and should not be send directly. + * ProtocolP2PPacket will use this method to generate the complete Packet. + * @return Packet with padding + * @throws InternalError + */ + protected byte[] toPacket() throws InternalError { + String hostname = hostItem.getHostname(); + // compute total size + int size = HOSTNAME_START_POSITION + hostname.length(); + byte[] packet = new byte[size + 1]; // java initialize all to zero + // set request/response code + packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; + // set Payload size + setPayloadSize(size - PAYLOAD_START_POSITION, packet); + // write port to Packet + try { + BytesArrayTools.write16Bits(packet, PAYLOAD_START_POSITION, hostItem.getPort()); + } catch (SizeError e) { + throw new InternalError(); + } + // write hostname to Packet + BytesArrayTools.write(packet, hostname, HOSTNAME_START_POSITION); + return packet; + } + + /** HostItem getter. + * @return hostItem + */ + public HostItem getHostItem() { + return hostItem; + } + +} diff --git a/src/protocolP2P/Unregister.java b/src/protocolP2P/Unregister.java new file mode 100644 index 0000000..8307a5b --- /dev/null +++ b/src/protocolP2P/Unregister.java @@ -0,0 +1,77 @@ +package protocolP2P; +import protocolP2P.Payload; +import tools.HostItem; +import tools.BytesArrayTools; +import localException.SizeError; +import localException.InternalError; +import localException.TransmissionError; +import localException.ProtocolError; + +/** Representation of payload for unregister. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class Unregister extends Payload { + private HostItem hostItem; + private static final int HOSTNAME_START_POSITION = PAYLOAD_START_POSITION + 2; + + /** Constructor with hostItem (typically used by client) + * @param hostItem Host you want to register. + * @throws InternalError + */ + public Unregister(HostItem hostItem) throws InternalError { + super(RequestResponseCode.UNREGISTER); + this.hostItem = hostItem; + } + + /** Constructor (typically used by server) with a byte[] parameter containing the Packet received. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws ProtocolError + * @throws TransmissionError + */ + protected Unregister(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { + super(packet); + int size = getPayloadSize(packet); + int port = BytesArrayTools.readInt16Bits(packet, PAYLOAD_START_POSITION); + String hostname = BytesArrayTools.readString(packet, HOSTNAME_START_POSITION, size - HOSTNAME_START_POSITION + PAYLOAD_START_POSITION); + hostItem = new HostItem(hostname, port); + } + + /** Returns a byte[] containing Packet with padding. + * This Packet is still incomplete and should not be send directly. + * ProtocolP2PPacket will use this method to generate the complete Packet. + * @return Packet with padding + * @throws InternalError + */ + protected byte[] toPacket() throws InternalError { + String hostname = hostItem.getHostname(); + // compute total size + int size = HOSTNAME_START_POSITION + hostname.length(); + byte[] packet = new byte[size + 1]; // java initialize all to zero + // set request/response code + packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; + // set Payload size + setPayloadSize(size - PAYLOAD_START_POSITION, packet); + // write port to Packet + try { + BytesArrayTools.write16Bits(packet, PAYLOAD_START_POSITION, hostItem.getPort()); + } catch (SizeError e) { + throw new InternalError(); + } + // write hostname to Packet + BytesArrayTools.write(packet, hostname, HOSTNAME_START_POSITION); + return packet; + } + + /** HostItem getter. + * @return hostItem + */ + public HostItem getHostItem() { + return hostItem; + } + +} diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 6001cdf..a136574 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -38,6 +38,8 @@ import java.util.Map; import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; +import protocolP2P.Register; +import protocolP2P.Unregister; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for TCP. @@ -82,12 +84,7 @@ public class ServerManagementTCP implements Runnable { */ public void run() { logger.writeTCP("Server sucessfully started", LogLevel.Info); - try { - registerTracker(); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - System.exit(-4); - } + (new Thread(new TrackerRegisterer())).start(); do { try { Socket s = socket.accept(); @@ -341,20 +338,34 @@ public class ServerManagementTCP implements Runnable { } } - /** Register server on tracker - * @throws InternalError - * @throws IOException - * @throws SocketClosed - */ - public void registerTracker() throws InternalError, IOException, SocketClosed { - logger.writeTCP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.UNREGISTER)); - p.sendRequest((Object)tracker.getTCPSocket()); - logger.writeTCP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.REGISTER)); - p.sendRequest((Object)tracker.getTCPSocket()); - logger.writeTCP("Registering completed", LogLevel.Debug); - tracker.closeTCPSocket(); + /** Private runnable class allowing to initialize tracker while initializing server. */ + private class TrackerRegisterer implements Runnable { + + /** Runnable implementation */ + public void run() { + try { + registerTracker(); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + System.exit(-4); + } + } + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + private void registerTracker() throws InternalError, IOException, SocketClosed { + HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), TCPPort); + logger.writeTCP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(host)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(host)); + p.sendRequest((Object)tracker.getTCPSocket()); + logger.writeTCP("Registering completed", LogLevel.Debug); + tracker.closeTCPSocket(); + } } } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 0de0ef7..c082825 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -37,6 +37,8 @@ import protocolP2P.HashAlgorithm; import protocolP2P.HashRequest; import protocolP2P.HashResponse; import tools.HostItem; +import protocolP2P.Register; +import protocolP2P.Unregister; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. * @author Louis Royer @@ -77,12 +79,7 @@ public class ServerManagementUDP implements Runnable { */ public void run() { logger.writeUDP("Server sucessfully started", LogLevel.Info); - try { - registerTracker(); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - System.exit(-4); - } + (new Thread(new TrackerRegisterer())).start(); while(true) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); @@ -278,19 +275,33 @@ public class ServerManagementUDP implements Runnable { } } - /** Register server on tracker - * @throws InternalError - * @throws IOException - * @throws SocketClosed - */ - public void registerTracker() throws InternalError, IOException, SocketClosed { - logger.writeUDP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.UNREGISTER)); - p.sendRequest((Object)tracker.getUDPSocket()); - logger.writeUDP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.REGISTER)); - p.sendRequest((Object)tracker.getUDPSocket()); - tracker.closeUDPSocket(); - logger.writeUDP("Registering completed", LogLevel.Debug); +/** Private runnable class allowing to initialize tracker while initializing server. */ + private class TrackerRegisterer implements Runnable { + + /** Runnable implementation */ + public void run() { + try { + registerTracker(); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + System.exit(-4); + } + } + /** Register server on tracker + * @throws InternalError + * @throws IOException + * @throws SocketClosed + */ + private void registerTracker() throws InternalError, IOException, SocketClosed { + HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), UDPPort); + logger.writeUDP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(host)); + p.sendRequest((Object)tracker.getUDPSocket()); + logger.writeUDP("Registering into tracker", LogLevel.Info); + p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(host)); + p.sendRequest((Object)tracker.getUDPSocket()); + logger.writeUDP("Registering completed", LogLevel.Debug); + tracker.closeUDPSocket(); + } } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index e8795d9..33f8ad2 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -8,6 +8,8 @@ import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.ProtocolP2PPacket; import protocolP2P.RequestResponseCode; import protocolP2P.Payload; +import protocolP2P.Register; +import protocolP2P.Unregister; import tools.HostItem; import java.util.ArrayList; import java.util.List; @@ -179,8 +181,13 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Register : "payload must be an instance of Register"; + if (!(p instanceof Register)) { + throw new InternalError(); + } // add host to known host list - HostItem host = pd.getHostItem(); + HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { hostList.add(pd.getHostItem()); } @@ -188,8 +195,8 @@ public class TrackerManagementTCP implements Runnable { try { ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getTCPSocket()); - logger.writeTCP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse()); + logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send @@ -204,8 +211,14 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { - HostItem host = pd.getHostItem(); - logger.writeTCP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof Unregister : "payload must be an instance of Unregister"; + if (!(p instanceof Unregister)) { + sendInternalError(pd); + throw new InternalError(); + } + HostItem host = ((Unregister)p).getHostItem(); + logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); hostList.remove(host); for(String f: fileList.keySet()) { fileList.get(f).remove(host); @@ -239,30 +252,25 @@ public class TrackerManagementTCP implements Runnable { * @param pd ProtocolP2PPacketTCP response * @throws InternalError */ - private void handleListResponse(ProtocolP2PPacketTCP pd) throws InternalError { - HostItem host = pd.getHostItem(); - if (!hostList.contains(host)) { - logger.writeTCP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { + logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + throw new InternalError(); } else { - logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - sendInternalError(pd); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } } } } diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index c11c54c..3a93fe6 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -6,6 +6,8 @@ import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.ProtocolP2PPacket; import protocolP2P.RequestResponseCode; import protocolP2P.Payload; +import protocolP2P.Register; +import protocolP2P.Unregister; import tools.HostItem; import java.util.ArrayList; import java.util.List; @@ -131,8 +133,14 @@ public class TrackerManagementUDP implements Runnable { * @throws InternalError */ private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Register : "payload must be an instance of Register"; + if (!(p instanceof Register)) { + sendInternalError(pd); + throw new InternalError(); + } // add host to known host list - HostItem host = pd.getHostItem(); + HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { hostList.add(pd.getHostItem()); } @@ -140,8 +148,8 @@ public class TrackerManagementUDP implements Runnable { try { ProtocolP2PPacket pLReq =(ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getUDPSocket()); - logger.writeUDP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse()); + logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse(), host); host.closeUDPSocket(); } catch (Exception e) { // remove from list because list request could not be send @@ -156,8 +164,14 @@ public class TrackerManagementUDP implements Runnable { * @throws InternalError */ private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { - HostItem host = pd.getHostItem(); - logger.writeUDP("Received UNREGISTER. Removing host " + host, LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof Unregister : "payload must be an instance of Unregister"; + if (!(p instanceof Unregister)) { + sendInternalError(pd); + throw new InternalError(); + } + HostItem host = ((Unregister)p).getHostItem(); + logger.writeUDP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); hostList.remove(host); for(String f: fileList.keySet()) { fileList.get(f).remove(host); @@ -191,30 +205,25 @@ public class TrackerManagementUDP implements Runnable { * @param pd ProtocolP2PPacketUDP response * @throws InternalError */ - private void handleListResponse(ProtocolP2PPacketUDP pd) throws InternalError { - HostItem host = pd.getHostItem(); - if (!hostList.contains(host)) { - logger.writeUDP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action); + private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { + logger.writeUDP("Received LIST RESPONSE from host " + host, LogLevel.Action); + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + throw new InternalError(); } else { - logger.writeUDP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - sendInternalError(pd); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } } } } From 9b6258afd382c1ad17a2cb3f351ad4c03b939b38 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 11:27:57 +0100 Subject: [PATCH 15/40] Fix warnings / close scanners --- src/clientP2P/ClientDownloadPartTCP.java | 6 +++++- src/clientP2P/ClientDownloadPartUDP.java | 6 +++++- src/clientP2P/ClientDownloadTCP.java | 8 +++++++- src/clientP2P/ClientDownloadUDP.java | 8 +++++++- src/clientP2P/ClientManagementTCP.java | 11 +++++------ src/clientP2P/ClientManagementUDP.java | 12 +++++------- src/clientP2P/ClientP2P.java | 11 +++++------ src/localException/InternalError.java | 2 +- src/localException/ProtocolError.java | 2 +- src/localException/SizeError.java | 2 +- src/localException/SocketClosed.java | 2 +- src/localException/TransmissionError.java | 2 +- src/localException/VersionError.java | 2 +- src/protocolP2P/FileList.java | 2 -- src/protocolP2P/FilePart.java | 2 -- src/protocolP2P/HashRequest.java | 1 - src/protocolP2P/HashResponse.java | 1 - src/protocolP2P/LoadRequest.java | 1 - src/protocolP2P/ProtocolP2PPacket.java | 6 ++++-- src/protocolP2P/ProtocolP2PPacketTCP.java | 14 ++++++++------ src/protocolP2P/ProtocolP2PPacketUDP.java | 11 ++++++++--- src/remoteException/EmptyDirectory.java | 2 +- src/remoteException/EmptyFile.java | 2 +- src/remoteException/InternalRemoteError.java | 2 +- src/remoteException/NotATracker.java | 2 +- src/remoteException/NotFound.java | 2 +- src/remoteException/ProtocolRemoteError.java | 2 +- src/remoteException/VersionRemoteError.java | 2 +- src/serverP2P/ServerManagementTCP.java | 9 ++------- src/serverP2P/ServerManagementUDP.java | 18 ++++++------------ src/tools/Directories.java | 1 + src/tools/HostList.java | 1 + src/tracker/TrackerManagementTCP.java | 6 +++--- src/tracker/TrackerManagementUDP.java | 13 ++++++++++--- 34 files changed, 95 insertions(+), 79 deletions(-) diff --git a/src/clientP2P/ClientDownloadPartTCP.java b/src/clientP2P/ClientDownloadPartTCP.java index e6635cd..e4db082 100644 --- a/src/clientP2P/ClientDownloadPartTCP.java +++ b/src/clientP2P/ClientDownloadPartTCP.java @@ -5,7 +5,6 @@ import java.net.Socket; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Paths; import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; import protocolP2P.LoadRequest; @@ -22,6 +21,7 @@ import remoteException.InternalRemoteError; import remoteException.VersionRemoteError; import remoteException.ProtocolRemoteError; import remoteException.NotFound; +import remoteException.NotATracker; import tools.Logger; import tools.LogLevel; @@ -351,6 +351,10 @@ public class ClientDownloadPartTCP implements Runnable { System.err.println("Error: downloadPart SocketClosed"); logger.writeTCP("downloadPart SocketClosed", LogLevel.Error); return true; + } catch (NotATracker e) { + System.err.println("Error: downloadPart notATracker"); + logger.writeTCP("downloadPart notATracker", LogLevel.Error); + return true; } return false; } diff --git a/src/clientP2P/ClientDownloadPartUDP.java b/src/clientP2P/ClientDownloadPartUDP.java index b818553..84ef0f8 100644 --- a/src/clientP2P/ClientDownloadPartUDP.java +++ b/src/clientP2P/ClientDownloadPartUDP.java @@ -17,9 +17,9 @@ import remoteException.ProtocolRemoteError; import localException.VersionError; import localException.SizeError; import remoteException.NotFound; +import remoteException.NotATracker; import java.nio.file.Files; import java.io.File; -import java.nio.file.Paths; import java.io.IOException; import tools.Logger; import tools.LogLevel; @@ -336,6 +336,10 @@ public class ClientDownloadPartUDP implements Runnable { System.err.println("Error: downloadPart internalError"); logger.writeUDP("downloadPart internalError", LogLevel.Error); return true; + } catch (NotATracker e) { + System.err.println("Error: downloadPart notATracker"); + logger.writeUDP("downloadPart notATracker", LogLevel.Error); + return true; } return false; } diff --git a/src/clientP2P/ClientDownloadTCP.java b/src/clientP2P/ClientDownloadTCP.java index 92bbc43..bb8e932 100644 --- a/src/clientP2P/ClientDownloadTCP.java +++ b/src/clientP2P/ClientDownloadTCP.java @@ -7,7 +7,6 @@ import java.util.Random; import java.io.IOException; import java.io.File; import java.nio.file.Files; -import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.StandardCopyOption; import remoteException.EmptyDirectory; @@ -16,6 +15,7 @@ import remoteException.VersionRemoteError; import remoteException.ProtocolRemoteError; import remoteException.NotFound; import remoteException.InternalRemoteError; +import remoteException.NotATracker; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; @@ -239,6 +239,9 @@ public class ClientDownloadTCP implements Runnable { } catch (SizeError e) { logger.writeTCP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new InternalError(); } return hash; } catch (IOException e) { @@ -382,6 +385,9 @@ public class ClientDownloadTCP implements Runnable { } catch (NotFound e) { logger.writeTCP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new InternalError(); } } catch (IOException e) { logger.writeTCP(e, LogLevel.Error); diff --git a/src/clientP2P/ClientDownloadUDP.java b/src/clientP2P/ClientDownloadUDP.java index 87d6bab..932019b 100644 --- a/src/clientP2P/ClientDownloadUDP.java +++ b/src/clientP2P/ClientDownloadUDP.java @@ -7,7 +7,6 @@ import java.util.Random; import java.io.IOException; import java.io.File; import java.nio.file.Files; -import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.StandardCopyOption; import localException.ProtocolError; @@ -21,6 +20,7 @@ import remoteException.VersionRemoteError; import remoteException.ProtocolRemoteError; import remoteException.NotFound; import remoteException.InternalRemoteError; +import remoteException.NotATracker; import protocolP2P.HashAlgorithm; import protocolP2P.HashResponse; import protocolP2P.HashRequest; @@ -239,6 +239,9 @@ public class ClientDownloadUDP implements Runnable { } catch (SizeError e) { logger.writeUDP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new InternalError(); } return hash; } catch (IOException e) { @@ -378,6 +381,9 @@ public class ClientDownloadUDP implements Runnable { } catch (NotFound e) { logger.writeUDP(e, LogLevel.Error); throw new InternalError(); + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new InternalError(); } } catch (IOException e) { logger.writeUDP(e, LogLevel.Error); diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index f479df0..28fe131 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -4,9 +4,7 @@ import java.net.UnknownHostException; import java.util.Scanner; 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 java.security.MessageDigest; @@ -23,15 +21,12 @@ import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; +import remoteException.NotATracker; import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.FileList; -import protocolP2P.FilePart; -import protocolP2P.LoadRequest; import protocolP2P.HashAlgorithm; -import protocolP2P.HashRequest; -import protocolP2P.HashResponse; import clientP2P.ClientDownloadTCP; import tools.HostItem; import tools.Logger; @@ -74,6 +69,7 @@ public class ClientManagementTCP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); + scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeTCP("File " + f + " sucessfully downloaded", LogLevel.Info); @@ -203,6 +199,9 @@ public class ClientManagementTCP implements Runnable { System.err.println("listDirectory : SocketClosed"); logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); throw new ProtocolError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new ProtocolError(); } } diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index 914dc44..aa1da60 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -4,12 +4,9 @@ import java.util.Scanner; import java.util.Arrays; import java.util.List; import java.io.IOException; -import java.io.File; -import java.net.DatagramSocket; import java.net.UnknownHostException; import java.nio.file.Files; import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import localException.InternalError; @@ -23,15 +20,12 @@ import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; +import remoteException.NotATracker; import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.FileList; -import protocolP2P.FilePart; -import protocolP2P.LoadRequest; import protocolP2P.HashAlgorithm; -import protocolP2P.HashRequest; -import protocolP2P.HashResponse; import tools.HostItem; import tools.Logger; import tools.LogLevel; @@ -74,6 +68,7 @@ public class ClientManagementUDP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); + scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeUDP("File " + f + " sucessfully downloaded", LogLevel.Info); @@ -199,6 +194,9 @@ public class ClientManagementUDP implements Runnable { } catch (EmptyFile e) { logger.writeUDP(e, LogLevel.Error); throw new ProtocolError(); + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new ProtocolError(); } } diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index e08c1fb..139701f 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -6,7 +6,6 @@ import clientP2P.ClientManagementUDP; import clientP2P.ClientManagementTCP; import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; -import tools.Directories; import tools.Logger; import tools.LogLevel; import tools.Directories; @@ -21,8 +20,8 @@ import tools.HostList; */ public class ClientP2P { - static private final String subdir = "seeded/"; - static private String parts = ".parts"; + private String subdir = "seeded/"; + private String parts = ".parts"; private Logger loggerServer; private Logger loggerClient; private String host; @@ -86,8 +85,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + subdir, c.port, c.loggerServer, c.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); @@ -108,6 +107,7 @@ public class ClientP2P { System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]"); Scanner sc = new Scanner(System.in); String transportchoosen = sc.nextLine(); + sc.close(); Thread t; switch(transportchoosen){ case "UDP": @@ -127,7 +127,6 @@ public class ClientP2P { t = new Thread(cmtcp); break; } - t.setName("client P2P-JAVA-PROJECT"); t.start(); } diff --git a/src/localException/InternalError.java b/src/localException/InternalError.java index 08326f9..42794a5 100644 --- a/src/localException/InternalError.java +++ b/src/localException/InternalError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class InternalError extends exception.LocalException { +public class InternalError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/ProtocolError.java b/src/localException/ProtocolError.java index 8a8be52..14aeca8 100644 --- a/src/localException/ProtocolError.java +++ b/src/localException/ProtocolError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class ProtocolError extends exception.LocalException { +public class ProtocolError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SizeError.java b/src/localException/SizeError.java index cb927bc..bb13830 100644 --- a/src/localException/SizeError.java +++ b/src/localException/SizeError.java @@ -4,6 +4,6 @@ import exception.LocalException; /** Used on reception side when size as set in Packet is too big, and we cant store this in a int/long as usual. */ -public class SizeError extends exception.LocalException { +public class SizeError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/SocketClosed.java b/src/localException/SocketClosed.java index ceaac40..d3e68c5 100644 --- a/src/localException/SocketClosed.java +++ b/src/localException/SocketClosed.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class SocketClosed extends exception.LocalException { +public class SocketClosed extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/TransmissionError.java b/src/localException/TransmissionError.java index 38fca4f..d5a539b 100644 --- a/src/localException/TransmissionError.java +++ b/src/localException/TransmissionError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class TransmissionError extends exception.LocalException { +public class TransmissionError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/localException/VersionError.java b/src/localException/VersionError.java index c0cb7d4..a793e27 100644 --- a/src/localException/VersionError.java +++ b/src/localException/VersionError.java @@ -2,6 +2,6 @@ package localException; import exception.LocalException; -public class VersionError extends exception.LocalException { +public class VersionError extends LocalException { private static final long serialVersionUID = 12L; } diff --git a/src/protocolP2P/FileList.java b/src/protocolP2P/FileList.java index da31f08..b013bea 100644 --- a/src/protocolP2P/FileList.java +++ b/src/protocolP2P/FileList.java @@ -1,12 +1,10 @@ package protocolP2P; -import java.util.Arrays; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import localException.TransmissionError; import localException.ProtocolError; import localException.InternalError; import localException.SizeError; -import java.io.UnsupportedEncodingException; import tools.BytesArrayTools; /** Representation of payload for list response. diff --git a/src/protocolP2P/FilePart.java b/src/protocolP2P/FilePart.java index c394b0f..d168a05 100644 --- a/src/protocolP2P/FilePart.java +++ b/src/protocolP2P/FilePart.java @@ -6,8 +6,6 @@ import localException.InternalError; import localException.SizeError; import localException.TransmissionError; import tools.BytesArrayTools; -import java.util.Arrays; -import java.io.UnsupportedEncodingException; /** Representation of payload for load response. * @author Louis Royer diff --git a/src/protocolP2P/HashRequest.java b/src/protocolP2P/HashRequest.java index 452fd32..1eec671 100644 --- a/src/protocolP2P/HashRequest.java +++ b/src/protocolP2P/HashRequest.java @@ -1,7 +1,6 @@ package protocolP2P; import protocolP2P.Payload; import protocolP2P.HashAlgorithm; -import java.io.UnsupportedEncodingException; import localException.TransmissionError; import localException.SizeError; import localException.ProtocolError; diff --git a/src/protocolP2P/HashResponse.java b/src/protocolP2P/HashResponse.java index 769fbd7..52df91e 100644 --- a/src/protocolP2P/HashResponse.java +++ b/src/protocolP2P/HashResponse.java @@ -2,7 +2,6 @@ package protocolP2P; import protocolP2P.Payload; import java.util.HashMap; import java.util.Map; -import java.io.UnsupportedEncodingException; import localException.TransmissionError; import localException.SizeError; import localException.ProtocolError; diff --git a/src/protocolP2P/LoadRequest.java b/src/protocolP2P/LoadRequest.java index 251981d..1fa0aeb 100644 --- a/src/protocolP2P/LoadRequest.java +++ b/src/protocolP2P/LoadRequest.java @@ -6,7 +6,6 @@ import localException.ProtocolError; import localException.InternalError; import localException.SizeError; import tools.BytesArrayTools; -import java.io.UnsupportedEncodingException; /** Representation of payload for load request. * @author Louis Royer diff --git a/src/protocolP2P/ProtocolP2PPacket.java b/src/protocolP2P/ProtocolP2PPacket.java index 037da9b..74a1dcd 100644 --- a/src/protocolP2P/ProtocolP2PPacket.java +++ b/src/protocolP2P/ProtocolP2PPacket.java @@ -11,7 +11,7 @@ import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; -import java.net.InetAddress; +import remoteException.NotATracker; import java.io.IOException; import tools.HostItem; @@ -60,6 +60,7 @@ public abstract class ProtocolP2PPacket { /** Receive a response * @throws EmptyFile * @throws NotFound + * @throws NotATracker * @throws EmptyDirectory * @throws InternalRemoteError * @throws VersionRemoteError @@ -72,7 +73,7 @@ public abstract class ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed; + public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed; /** Receive a request, subclasses must overwrite this constructor. * @param socket socket used to get the request @@ -108,6 +109,7 @@ public abstract class ProtocolP2PPacket { */ protected void checkProtocolVersion() throws VersionError { if (PROTOCOL_VERSION != version) { + System.err.println("Error: wrong version in packet:" + version); throw new VersionError(); } } diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index f2254f8..9272ea6 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -5,21 +5,19 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import remoteException.NotATracker; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; import remoteException.ProtocolRemoteError; import remoteException.VersionRemoteError; import remoteException.EmptyFile; -import tools.BytesArrayTools; import tools.HostItem; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; import protocolP2P.FileList; import protocolP2P.FilePart; -import java.util.ArrayList; -import java.lang.Byte; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; @@ -68,9 +66,9 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { socket.close(); } catch (IOException e2) { System.err.println("Cannot close socket"); - } finally { throw new SocketClosed(); } + } } @@ -117,7 +115,6 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { ss.close(); } catch (IOException e2) { System.err.println("Cannot close socket"); - } finally { throw new SocketClosed(); } } @@ -139,6 +136,8 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { case LOAD_RESPONSE: case LIST_RESPONSE: case HASH_RESPONSE: + case DISCOVER_RESPONSE: + case NOT_A_TRACKER: // we were expecting a request, but we are receiving a response throw new ProtocolError(); default : @@ -189,6 +188,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { * @return ProtocolP2PPacket received * @throws EmptyFile * @throws NotFound + * @throws NotATracker * @throws EmptyDirectory * @throws InternalRemoteError * @throws VersionRemoteError @@ -201,7 +201,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed { + public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed { assert requestSocket != null : "Cannot receive response because request packet not sent."; if (requestSocket == null) { throw new InternalError(); @@ -226,6 +226,8 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { throw new NotFound(); case EMPTY_FILE: throw new EmptyFile(); + case NOT_A_TRACKER: + throw new NotATracker(); default : return (ProtocolP2PPacket)p; } diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index 4bc98bb..03ffd64 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -5,6 +5,7 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import remoteException.NotATracker; import remoteException.EmptyDirectory; import remoteException.InternalRemoteError; import remoteException.NotFound; @@ -18,8 +19,6 @@ import protocolP2P.RequestResponseCode; import protocolP2P.LoadRequest; import protocolP2P.FileList; import protocolP2P.FilePart; -import java.util.ArrayList; -import java.lang.Byte; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketAddress; @@ -133,6 +132,8 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { case LOAD_RESPONSE: case LIST_RESPONSE: case HASH_RESPONSE: + case DISCOVER_RESPONSE: + case NOT_A_TRACKER: // we were expecting a request, but we are receiving a response throw new ProtocolError(); default : @@ -186,6 +187,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @return ProtocolP2PPacket received * @throws EmptyFile * @throws NotFound + * @throws NotATracker * @throws EmptyDirectory * @throws InternalRemoteError * @throws VersionRemoteError @@ -197,7 +199,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @throws SizeError * @throws IOException */ - public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException { + public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException { assert requestSocket != null : "Cannot receive response because request packet not sent."; if (requestSocket == null) { throw new InternalError(); @@ -206,6 +208,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { byte[] packet = new byte[8192]; DatagramPacket reception = new DatagramPacket(packet, packet.length); requestSocket.receive(reception); + // contruction try { ProtocolP2PPacketUDP p = new ProtocolP2PPacketUDP(packet); @@ -223,6 +226,8 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { throw new NotFound(); case EMPTY_FILE: throw new EmptyFile(); + case NOT_A_TRACKER: + throw new NotATracker(); default : return (ProtocolP2PPacket)p; } diff --git a/src/remoteException/EmptyDirectory.java b/src/remoteException/EmptyDirectory.java index 12fce76..45e477a 100644 --- a/src/remoteException/EmptyDirectory.java +++ b/src/remoteException/EmptyDirectory.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class EmptyDirectory extends exception.RemoteException { +public class EmptyDirectory extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/EmptyFile.java b/src/remoteException/EmptyFile.java index cbc580f..e5911d9 100644 --- a/src/remoteException/EmptyFile.java +++ b/src/remoteException/EmptyFile.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class EmptyFile extends exception.RemoteException { +public class EmptyFile extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/InternalRemoteError.java b/src/remoteException/InternalRemoteError.java index 802ee05..1d2e92f 100644 --- a/src/remoteException/InternalRemoteError.java +++ b/src/remoteException/InternalRemoteError.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class InternalRemoteError extends exception.RemoteException { +public class InternalRemoteError extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/NotATracker.java b/src/remoteException/NotATracker.java index dbccea2..1f22ce0 100644 --- a/src/remoteException/NotATracker.java +++ b/src/remoteException/NotATracker.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class NotATracker extends exception.RemoteException { +public class NotATracker extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/NotFound.java b/src/remoteException/NotFound.java index f8002bc..c0e61d9 100644 --- a/src/remoteException/NotFound.java +++ b/src/remoteException/NotFound.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class NotFound extends exception.RemoteException { +public class NotFound extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/ProtocolRemoteError.java b/src/remoteException/ProtocolRemoteError.java index c0c6161..1560083 100644 --- a/src/remoteException/ProtocolRemoteError.java +++ b/src/remoteException/ProtocolRemoteError.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class ProtocolRemoteError extends exception.RemoteException { +public class ProtocolRemoteError extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/remoteException/VersionRemoteError.java b/src/remoteException/VersionRemoteError.java index 775d9cb..4e7a1d5 100644 --- a/src/remoteException/VersionRemoteError.java +++ b/src/remoteException/VersionRemoteError.java @@ -2,6 +2,6 @@ package remoteException; import exception.RemoteException; -public class VersionRemoteError extends exception.RemoteException { +public class VersionRemoteError extends RemoteException { private static final long serialVersionUID = 12L; } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index a136574..98ce3cd 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -23,12 +23,6 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; -import remoteException.EmptyDirectory; -import remoteException.InternalRemoteError; -import remoteException.NotFound; -import remoteException.ProtocolRemoteError; -import remoteException.VersionRemoteError; -import remoteException.EmptyFile; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -360,11 +354,12 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP("Unregistering from tracker", LogLevel.Info); ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(host)); p.sendRequest((Object)tracker.getTCPSocket()); + //tracker.closeTCPSocket(); logger.writeTCP("Registering into tracker", LogLevel.Info); p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(host)); p.sendRequest((Object)tracker.getTCPSocket()); logger.writeTCP("Registering completed", LogLevel.Debug); - tracker.closeTCPSocket(); + //tracker.closeTCPSocket(); } } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index c082825..7573bda 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -22,12 +22,6 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; -import remoteException.EmptyDirectory; -import remoteException.InternalRemoteError; -import remoteException.NotFound; -import remoteException.ProtocolRemoteError; -import remoteException.VersionRemoteError; -import remoteException.EmptyFile; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -86,10 +80,10 @@ public class ServerManagementUDP implements Runnable { Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: - LoadRequestManagement(logger, p, pd); + loadRequestManagement(p, pd); break; case LIST_REQUEST: - ListRequestManagement(logger, pd); + listRequestManagement(pd); break; case HASH_REQUEST: logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); @@ -160,7 +154,7 @@ public class ServerManagementUDP implements Runnable { } } - public void LoadRequestManagement(Logger logger, Payload p, ProtocolP2PPacketUDP pd){ + public void loadRequestManagement(Payload p, ProtocolP2PPacketUDP pd){ logger.writeUDP("Received LOAD_REQUEST", LogLevel.Action); assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; if (!(p instanceof LoadRequest)) { @@ -210,14 +204,14 @@ public class ServerManagementUDP implements Runnable { } } - public void ListRequestManagement(Logger logger, ProtocolP2PPacketUDP pd){ + public void listRequestManagement(ProtocolP2PPacketUDP pd) { logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); try { if (fileList.length == 0) { - logger.writeUDP("Sending EMPTY_DIRECTORY", LogLevel.Action); + logger.writeUDP("Sending EMPTY_DIRECTORY to host " + pd.getHostItem(), LogLevel.Action); pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); } else { - logger.writeUDP("Sending LIST_RESPONSE", LogLevel.Action); + logger.writeUDP("Sending LIST_RESPONSE to host " + pd.getHostItem(), LogLevel.Action); pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FileList(fileList)))); } } catch (Exception e2) { diff --git a/src/tools/Directories.java b/src/tools/Directories.java index 97ec091..8c9a86e 100644 --- a/src/tools/Directories.java +++ b/src/tools/Directories.java @@ -99,6 +99,7 @@ public class Directories { System.out.println("Do you want to open this directory? (y/N)"); Scanner scanner = new Scanner(System.in); String resp = scanner.nextLine(); + scanner.close(); if (resp.equals("y") || resp.equals("Y")) { System.out.println("Openning"); openDataHomeDirectory(subdir); diff --git a/src/tools/HostList.java b/src/tools/HostList.java index 510e3ba..eae5e4e 100644 --- a/src/tools/HostList.java +++ b/src/tools/HostList.java @@ -50,6 +50,7 @@ public class HostList { } } while (!servName.equals("stop")); + scanner.close(); return serverList; } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 33f8ad2..32f5394 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -189,7 +189,7 @@ public class TrackerManagementTCP implements Runnable { // add host to known host list HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { - hostList.add(pd.getHostItem()); + hostList.add(host); } // send a list request try { @@ -197,7 +197,7 @@ public class TrackerManagementTCP implements Runnable { pLReq.sendRequest((Object)host.getTCPSocket()); logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); - host.closeTCPSocket(); + //host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); @@ -253,7 +253,7 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { - logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action); + logger.writeTCP("Received LIST RESPONSE from host " + host, LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 3a93fe6..ee604c4 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -21,6 +21,7 @@ import protocolP2P.DiscoverResponse; import protocolP2P.FileList; import protocolP2P.HashRequest; import localException.InternalError; +import remoteException.EmptyDirectory; /** Tracker management implementation with udp * @author Louis Royer @@ -142,15 +143,21 @@ public class TrackerManagementUDP implements Runnable { // add host to known host list HostItem host = ((Register)p).getHostItem(); if (!hostList.contains(host)) { - hostList.add(pd.getHostItem()); + hostList.add(host); } // send a list request try { - ProtocolP2PPacket pLReq =(ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); + ProtocolP2PPacket pLReq = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getUDPSocket()); logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse(), host); + ProtocolP2PPacket resp = pLReq.receiveResponse(); + handleListResponse((ProtocolP2PPacketUDP)resp, host); + logger.writeUDP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); host.closeUDPSocket(); + } catch (EmptyDirectory e) { + logger.writeUDP("Empty Directory", LogLevel.Debug); + hostList.remove(host); + logger.writeUDP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); From cc06ccc3349ff82f6c50c9e272ab0aedc39853ed Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 14:50:01 +0100 Subject: [PATCH 16/40] Bind sur localhost --- src/serverP2P/ServerManagementTCP.java | 2 +- src/serverP2P/ServerManagementUDP.java | 6 +++++- src/tools/HostItem.java | 22 ++++++++++++++++++++++ src/tools/Logger.java | 1 + src/tracker/TrackerManagementTCP.java | 23 ++++++++++++----------- src/tracker/TrackerManagementUDP.java | 8 +++++--- 6 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 98ce3cd..69ce5d6 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -64,7 +64,7 @@ public class ServerManagementTCP implements Runnable { initFileList(); initSha512(); try { - socket = new ServerSocket(TCPPort); + socket = new ServerSocket(TCPPort, 10, InetAddress.getLocalHost()); } catch (SocketException e) { logger.writeTCP("Error: cannot listen on port " + TCPPort, LogLevel.Error); System.exit(-1); diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 7573bda..2050916 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -33,6 +33,7 @@ import protocolP2P.HashResponse; import tools.HostItem; import protocolP2P.Register; import protocolP2P.Unregister; +import java.net.UnknownHostException; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. * @author Louis Royer @@ -62,10 +63,13 @@ public class ServerManagementUDP implements Runnable { initFileList(); initSha512(); try { - socket = new DatagramSocket(UDPPort); + socket = new DatagramSocket(UDPPort, InetAddress.getLocalHost()); } catch (SocketException e) { logger.writeUDP("Error: cannot listen on port " + UDPPort, LogLevel.Error); System.exit(-1); + } catch (UnknownHostException e) { + logger.writeUDP(e, LogLevel.Error); + System.exit(-2); } } diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index fe15007..76dcb2d 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -17,6 +17,7 @@ public class HostItem { private int port; private Socket tcpSocket; private DatagramSocket udpSocket; + private InetAddress inetAddress; /** Constructor with hostname and port * @param hostname Hostname @@ -125,4 +126,25 @@ public class HostItem { public int hashCode() { return hostname.hashCode() ^ port; } + + public InetAddress getInetAddress() { + if (inetAddress == null) { + try { + inetAddress = InetAddress.getByName(getHostname()); + } catch (UnknownHostException e) { + System.err.println("Error: Unknown host."); + System.exit(-1); + } + } + return inetAddress; + } + + public HostItem(Socket s) { + tcpSocket = s; + inetAddress = s.getInetAddress(); + hostname = inetAddress.getCanonicalHostName(); + port = s.getPort(); + } + + } diff --git a/src/tools/Logger.java b/src/tools/Logger.java index 63c2107..4da4848 100644 --- a/src/tools/Logger.java +++ b/src/tools/Logger.java @@ -120,4 +120,5 @@ public class Logger { e.printStackTrace(); } + } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 32f5394..8ab4724 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -22,6 +22,8 @@ import protocolP2P.DiscoverResponse; import protocolP2P.FileList; import protocolP2P.HashRequest; import localException.InternalError; +import java.net.UnknownHostException; +import java.net.InetAddress; /** Tracker management implementation with tcp @@ -32,7 +34,7 @@ import localException.InternalError; */ public class TrackerManagementTCP implements Runnable { - private int port; + private HostItem tracker; private Logger logger; private ServerSocket socket; private List hostList = new ArrayList<>(); @@ -43,15 +45,15 @@ public class TrackerManagementTCP implements Runnable { * @param logger Logger object */ public TrackerManagementTCP(int port, Logger logger) { - this.port = port; + tracker = new HostItem("localhost", port); this.logger = logger; try { - socket = new ServerSocket(port); + socket = new ServerSocket(tracker.getPort(), 10, tracker.getInetAddress()); } catch (SocketException e) { - logger.writeTCP("Error: cannot listen on port " + port, LogLevel.Error); + logger.writeTCP("Error: cannot listen on" + tracker, LogLevel.Error); System.exit(-1); } catch (IOException e) { - logger.writeTCP("Error: cannot openning socket", LogLevel.Error); + logger.writeTCP("Error: cannot open socket", LogLevel.Error); System.exit(-2); } } @@ -76,13 +78,12 @@ public class TrackerManagementTCP implements Runnable { */ private class ClientHandler implements Runnable { private Socket s; - private String addr; + private HostItem addr; /** Constructor with a socket. * @param s Socket of this client */ public ClientHandler(Socket s) { - this.s = s; - this.addr = "[" +s.getInetAddress().getHostAddress() + "]:" + s.getPort() + " "; + this.addr = new HostItem(s); } /** Implementation of runnable. This method allow to serve one client. @@ -90,11 +91,11 @@ public class TrackerManagementTCP implements Runnable { public void run() { boolean end = false; - logger.writeTCP(addr + "New connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); do { end = handleRequest(); } while(!end); - logger.writeTCP(addr + "End of connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. @@ -103,7 +104,7 @@ public class TrackerManagementTCP implements Runnable { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)addr.getTCPSocket()); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index ee604c4..41ff8d8 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -22,6 +22,8 @@ import protocolP2P.FileList; import protocolP2P.HashRequest; import localException.InternalError; import remoteException.EmptyDirectory; +import java.net.InetAddress; +import java.net.UnknownHostException; /** Tracker management implementation with udp * @author Louis Royer @@ -31,7 +33,7 @@ import remoteException.EmptyDirectory; */ public class TrackerManagementUDP implements Runnable { - private int port; + private HostItem tracker; private Logger logger; private DatagramSocket socket; private List hostList = new ArrayList<>(); @@ -42,10 +44,10 @@ public class TrackerManagementUDP implements Runnable { * @param logger Logger object */ public TrackerManagementUDP(int port, Logger logger) { - this.port = port; + tracker = new HostItem("localhost", port); this.logger = logger; try { - socket = new DatagramSocket(port); + socket = new DatagramSocket(tracker.getPort(), tracker.getInetAddress()); } catch (SocketException e) { logger.writeUDP("Error: cannot listen on port " + port, LogLevel.Error); System.exit(-1); From 3387b90b14434d78ba95993032cfe643e6735680 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 16:30:42 +0100 Subject: [PATCH 17/40] HostItems dans le server --- src/clientP2P/ClientP2P.java | 5 ++--- src/serverP2P/ServerManagementTCP.java | 30 +++++++++++++------------- src/serverP2P/ServerManagementUDP.java | 23 ++++++++++---------- src/serverP2P/ServerP2P.java | 5 ++--- src/tracker/TrackerManagementTCP.java | 5 ++--- src/tracker/TrackerManagementUDP.java | 1 - 6 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 139701f..a1700b9 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -72,7 +72,6 @@ public class ClientP2P { * @param args server listenning port */ public static void main(String [] args) { - if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ System.out.println("usage : java -ea clientP2P.ClientP2P -- "); } @@ -85,8 +84,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + c.subdir, c.port, c.loggerServer, c.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + c.subdir, "localhost", c.port, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + c.subdir, "localhost", c.port, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 69ce5d6..d04b544 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -47,26 +47,29 @@ public class ServerManagementTCP implements Runnable { private String[] fileList; private Map sha512 = new HashMap<>(); private String baseDirectory; - private int TCPPort; private ServerSocket socket; private Logger logger; private HostItem tracker; + private HostItem server; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. * @param baseDirectory the root directory where files are stored + * @param hostName the server will bind on this address * @param TCPPort the server will listen on this port + * @param logger Logger item + * @param tracker Tracker */ - public ServerManagementTCP(String baseDirectory, int TCPPort, Logger logger, HostItem tracker) { + public ServerManagementTCP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { + server = new HostItem(hostName, port); this.tracker = tracker; this.logger = logger; this.baseDirectory = baseDirectory; - this.TCPPort = TCPPort; initFileList(); initSha512(); try { - socket = new ServerSocket(TCPPort, 10, InetAddress.getLocalHost()); + socket = new ServerSocket(server.getPort(), 10, server.getInetAddress()); } catch (SocketException e) { - logger.writeTCP("Error: cannot listen on port " + TCPPort, LogLevel.Error); + logger.writeTCP("Error: cannot listen on " + server, LogLevel.Error); System.exit(-1); } catch (IOException e) { logger.writeTCP("Error: cannot openning socket", LogLevel.Error); @@ -93,14 +96,12 @@ public class ServerManagementTCP implements Runnable { /** Private runnable class allowing to serve one client. */ private class ClientHandler implements Runnable { - private Socket s; - private String addr; + private HostItem addr; /** Constructor with a socket. * @param s Socket of this client */ public ClientHandler(Socket s) { - this.s = s; - this.addr = "[" +s.getInetAddress().getHostAddress() + "]:" + s.getPort() + " "; + addr = new HostItem(s); } /** Implementation of runnable. This method allow to serve one client. @@ -108,11 +109,11 @@ public class ServerManagementTCP implements Runnable { public void run() { boolean end = false; - logger.writeTCP(addr + "New connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); do { end = handleRequest(); } while(!end); - logger.writeTCP(addr + "End of connection", LogLevel.Action); + logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. @@ -121,7 +122,7 @@ public class ServerManagementTCP implements Runnable { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)addr.getTCPSocket()); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -350,13 +351,12 @@ public class ServerManagementTCP implements Runnable { * @throws SocketClosed */ private void registerTracker() throws InternalError, IOException, SocketClosed { - HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), TCPPort); logger.writeTCP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(host)); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server)); p.sendRequest((Object)tracker.getTCPSocket()); //tracker.closeTCPSocket(); logger.writeTCP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(host)); + p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); p.sendRequest((Object)tracker.getTCPSocket()); logger.writeTCP("Registering completed", LogLevel.Debug); //tracker.closeTCPSocket(); diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 2050916..e5f81db 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -46,30 +46,30 @@ public class ServerManagementUDP implements Runnable { private String[] fileList; private Map sha512 = new HashMap<>(); private String baseDirectory; - private int UDPPort; private DatagramSocket socket; private Logger logger; private HostItem tracker; + private HostItem server; /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. * @param baseDirectory the root directory where files are stored - * @param UDPPort the server will listen on this port + * @param hostName the server will bind on this address + * @param port the server will listen on this port + * @param logger Logger item + * @param tracker Tracker */ - public ServerManagementUDP(String baseDirectory, int UDPPort, Logger logger, HostItem tracker) { + public ServerManagementUDP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { + server = new HostItem(hostName, port); this.logger = logger; this.baseDirectory = baseDirectory; - this.UDPPort = UDPPort; this.tracker = tracker; initFileList(); initSha512(); try { - socket = new DatagramSocket(UDPPort, InetAddress.getLocalHost()); + socket = new DatagramSocket(server.getPort(), server.getInetAddress()); } catch (SocketException e) { - logger.writeUDP("Error: cannot listen on port " + UDPPort, LogLevel.Error); + logger.writeUDP("Error: cannot listen on " + server, LogLevel.Error); System.exit(-1); - } catch (UnknownHostException e) { - logger.writeUDP(e, LogLevel.Error); - System.exit(-2); } } @@ -291,12 +291,11 @@ public class ServerManagementUDP implements Runnable { * @throws SocketClosed */ private void registerTracker() throws InternalError, IOException, SocketClosed { - HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), UDPPort); logger.writeUDP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(host)); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(server)); p.sendRequest((Object)tracker.getUDPSocket()); logger.writeUDP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(host)); + p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(server)); p.sendRequest((Object)tracker.getUDPSocket()); logger.writeUDP("Registering completed", LogLevel.Debug); tracker.closeUDPSocket(); diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index abfdb66..1b57958 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -43,8 +43,8 @@ public class ServerP2P { } else{ ServerP2P s = new ServerP2P(args[1], args[2], args[3]); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.port, s.logger, s.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, "localhost", s.port, s.logger, s.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, "localhost", s.port, s.logger, s.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT"); tudp.start(); @@ -53,5 +53,4 @@ public class ServerP2P { ttcp.start(); } } - } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 8ab4724..491b883 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -77,7 +77,6 @@ public class TrackerManagementTCP implements Runnable { /** Private runnable class allowing to serve one client. */ private class ClientHandler implements Runnable { - private Socket s; private HostItem addr; /** Constructor with a socket. * @param s Socket of this client @@ -198,7 +197,8 @@ public class TrackerManagementTCP implements Runnable { pLReq.sendRequest((Object)host.getTCPSocket()); logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); - //host.closeTCPSocket(); + logger.writeTCP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); + host.closeTCPSocket(); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); @@ -254,7 +254,6 @@ public class TrackerManagementTCP implements Runnable { * @throws InternalError */ private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { - logger.writeTCP("Received LIST RESPONSE from host " + host, LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 41ff8d8..3a3cbc2 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -215,7 +215,6 @@ public class TrackerManagementUDP implements Runnable { * @throws InternalError */ private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { - logger.writeUDP("Received LIST RESPONSE from host " + host, LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { From ad2b79607130e1cf2c1d2c069b08505ed77af194 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 20 Mar 2020 17:41:24 +0100 Subject: [PATCH 18/40] Fix tcp --- src/protocolP2P/ProtocolP2PPacketTCP.java | 20 ++++++++++++++++++-- src/serverP2P/ServerManagementTCP.java | 14 ++++++++++---- src/tracker/TrackerManagementTCP.java | 5 +++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index 9272ea6..b99e83f 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -108,11 +108,14 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { Socket ss = (Socket)socket; byte[] packet = new byte[1024]; try { - System.err.println("Reading " + ss.getInputStream().read(packet) + " bytes"); + if (-1 == ss.getInputStream().read(packet)) { + throw new IOException(); + } } catch (IOException e) { // Error: cannot read request, closing socket try { ss.close(); + throw new SocketClosed(); } catch (IOException e2) { System.err.println("Cannot close socket"); throw new SocketClosed(); @@ -208,7 +211,20 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { } // reception byte[] packet = new byte[8192]; - requestSocket.getInputStream().read(packet); + try { + if (-1== requestSocket.getInputStream().read(packet)) { + throw new IOException(); + } + } catch (IOException e) { + // Error: cannot read request, closing socket + try { + requestSocket.close(); + throw new SocketClosed(); + } catch (IOException e2) { + System.err.println("Cannot close socket"); + throw new SocketClosed(); + } + } // contruction try { ProtocolP2PPacketTCP p = new ProtocolP2PPacketTCP(packet); diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index d04b544..359d616 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -109,11 +109,11 @@ public class ServerManagementTCP implements Runnable { public void run() { boolean end = false; - logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); + logger.writeTCP("[" + addr + "] New connection", LogLevel.Action); do { end = handleRequest(); } while(!end); - logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); + logger.writeTCP("[" + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. @@ -354,12 +354,18 @@ public class ServerManagementTCP implements Runnable { logger.writeTCP("Unregistering from tracker", LogLevel.Info); ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server)); p.sendRequest((Object)tracker.getTCPSocket()); - //tracker.closeTCPSocket(); + // FIXME: this is a hack + // ProtocolP2PPacketTCP reads 1024 bytes but if 2 request comes at the same time InputStream is cleared fully + // and we keep waiting forever on the other side + // a fix could be to read only the header first, and read the required size after + try { + Thread.sleep(100); + } catch (InterruptedException e) {} logger.writeTCP("Registering into tracker", LogLevel.Info); p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); p.sendRequest((Object)tracker.getTCPSocket()); logger.writeTCP("Registering completed", LogLevel.Debug); - //tracker.closeTCPSocket(); + tracker.closeTCPSocket(); } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 491b883..5f75aa2 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -24,6 +24,7 @@ import protocolP2P.HashRequest; import localException.InternalError; import java.net.UnknownHostException; import java.net.InetAddress; +import localException.SocketClosed; /** Tracker management implementation with tcp @@ -119,9 +120,11 @@ public class TrackerManagementTCP implements Runnable { sendNotFound(pd); break; case REGISTER: + logger.writeTCP("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); handleRegister(pd); break; case UNREGISTER: + logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); handleUnregister(pd); break; case DISCOVER_REQUEST: @@ -135,6 +138,8 @@ public class TrackerManagementTCP implements Runnable { } catch (IOException e) { logger.writeTCP(e, LogLevel.Warning); return true; + } catch (SocketClosed e) { + return true; } catch (LocalException e) { logger.writeTCP(e, LogLevel.Warning); return true; From 683529b21c3e72ea92d1a56e85c35c759b4ac071 Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 21 Mar 2020 14:29:29 +0100 Subject: [PATCH 19/40] Add javadoc on some methods --- src/serverP2P/ServerManagementUDP.java | 11 +++++++++-- src/tools/HostItem.java | 6 ++++++ src/tools/Logger.java | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index e5f81db..fbc0795 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -84,7 +84,7 @@ public class ServerManagementUDP implements Runnable { Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: - loadRequestManagement(p, pd); + loadRequestManagement(pd); break; case LIST_REQUEST: listRequestManagement(pd); @@ -158,7 +158,11 @@ public class ServerManagementUDP implements Runnable { } } - public void loadRequestManagement(Payload p, ProtocolP2PPacketUDP pd){ + /** Respond to LOAD requests + * @param pd ProtocolP2PPacketUDP + */ + public void loadRequestManagement(ProtocolP2PPacketUDP pd){ + Payload p = pd.getPayload(); logger.writeUDP("Received LOAD_REQUEST", LogLevel.Action); assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; if (!(p instanceof LoadRequest)) { @@ -208,6 +212,9 @@ public class ServerManagementUDP implements Runnable { } } + /** Respond to LIST requests + * @param pd ProtocolP2PPacketUDP + */ public void listRequestManagement(ProtocolP2PPacketUDP pd) { logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); try { diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index 76dcb2d..80b4f13 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -127,6 +127,9 @@ public class HostItem { return hostname.hashCode() ^ port; } + /** Get InetAddress associated to this HostItem. + * @return InetAddress + */ public InetAddress getInetAddress() { if (inetAddress == null) { try { @@ -139,6 +142,9 @@ public class HostItem { return inetAddress; } + /** Constructor from Socket. + * @param s socket + */ public HostItem(Socket s) { tcpSocket = s; inetAddress = s.getInetAddress(); diff --git a/src/tools/Logger.java b/src/tools/Logger.java index 4da4848..1fdb4ad 100644 --- a/src/tools/Logger.java +++ b/src/tools/Logger.java @@ -17,6 +17,9 @@ import java.sql.Timestamp; public class Logger { private Path logFile; + /** Constructor with logFile. + * @param logFile name of the file to store logs. + */ public Logger(String logFile) { assert logFile != null : "Logfile name is null"; this.logFile = Paths.get(logFile); From 3f21797b09c6e71b6f510c5fc19b0713ddc63cbe Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 21 Mar 2020 15:48:18 +0100 Subject: [PATCH 20/40] Client now asks servers to tracker ! --- src/clientP2P/ClientManagementTCP.java | 117 ++++++++++++++----------- src/clientP2P/ClientManagementUDP.java | 51 +++++++++-- src/clientP2P/ClientP2P.java | 20 +++-- src/serverP2P/ServerP2P.java | 5 +- src/tools/BytesArrayTools.java | 6 +- src/tools/Directories.java | 7 +- src/tools/HostItem.java | 12 +-- src/tools/HostList.java | 56 ------------ src/tracker/Tracker.java | 5 +- src/tracker/TrackerManagementTCP.java | 8 +- src/tracker/TrackerManagementUDP.java | 3 +- 11 files changed, 151 insertions(+), 139 deletions(-) delete mode 100644 src/tools/HostList.java diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index 28fe131..b52899c 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -31,6 +31,8 @@ import clientP2P.ClientDownloadTCP; import tools.HostItem; import tools.Logger; import tools.LogLevel; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; /** Implementation of P2P-JAVA-PROJECT CLIENT * @author Louis Royer @@ -42,26 +44,36 @@ public class ClientManagementTCP implements Runnable { private String baseDirectory; private String partsSubdir; private List hostList; + private HostItem tracker; private Logger logger; + private Scanner scanner; - /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. + /** Constructor for TCP implementation, with baseDirectory, tracker, partsSubdir, logger, and scanner parameters. * @param baseDirectory the root directory where files are stored - * @param host hostname of the server - * @param TCPPort the server will listen on this port + * @param tracker Tracker hostItem + * @param partsSubdir subdirectory to store file parts + * @param logger Loggger + * @param scanner Scanner used to read input */ - public ClientManagementTCP(String baseDirectory, List hostList, String partsSubdir, Logger logger) { + public ClientManagementTCP(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) { + this.scanner = scanner; this.baseDirectory = baseDirectory; - this.hostList = hostList; + this.tracker = tracker; this.partsSubdir = partsSubdir; this.logger = logger; + try { + initHostList(); + } catch (InternalError e) { + System.exit(-1); + } catch (ProtocolError e) { + System.exit(-2); + } } /** 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) { @@ -69,49 +81,35 @@ public class ClientManagementTCP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); - scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeTCP("File " + f + " sucessfully downloaded", LogLevel.Info); } catch (EmptyDirectory e) { - System.err.println("Error: Server has no file in directory"); - logger.writeTCP("Error: Server has no file in directory", LogLevel.Error); + logger.writeTCP("Server has no file in directory", LogLevel.Error); } catch (InternalError e) { - System.err.println("Error: Client internal error"); - logger.writeTCP("Error: Client internal error", LogLevel.Error); + logger.writeTCP("Client internal error", LogLevel.Error); } catch (UnknownHostException e) { - System.err.println("Error: Server host is unknown"); - logger.writeTCP("Error: Server host is unknown", LogLevel.Error); + logger.writeTCP("Server host is unknown", LogLevel.Error); } catch (IOException e) { - System.err.println("Error: Request cannot be send or response cannot be received"); - logger.writeTCP("Error: Request cannot be send or response cannot be received", LogLevel.Error); + logger.writeTCP("Request cannot be send or response cannot be received", LogLevel.Error); } catch (TransmissionError e) { - System.err.println("Error: Message received is too big"); - logger.writeTCP("Error: Message received is too big", LogLevel.Error); + logger.writeTCP("Message received is too big", LogLevel.Error); } catch (ProtocolError e) { - System.err.println("Error: Cannot decode server’s response"); - logger.writeTCP("Error: Cannot decode server’s response", LogLevel.Error); + logger.writeTCP("Cannot decode server’s response", LogLevel.Error); } catch (VersionError e) { - System.err.println("Error: Server’s response use bad version of the protocol"); - logger.writeTCP("Error: Server’s response use bad version of the protocol", LogLevel.Error); + logger.writeTCP("Server’s response use bad version of the protocol", LogLevel.Error); } catch (SizeError e) { - System.err.println("Error: Cannot handle this packets because of internal representation limitations of numbers on the client"); - logger.writeTCP("Error: Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); + logger.writeTCP("Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); } catch (InternalRemoteError e) { - System.err.println("Error: Server internal error"); - logger.writeTCP("Error: Server internal error", LogLevel.Error); + logger.writeTCP("Server internal error", LogLevel.Error); } catch (ProtocolRemoteError e) { - System.err.println("Error: Server cannot decode client’s request"); - logger.writeTCP("Error: Server cannot decode client’s request", LogLevel.Error); + logger.writeTCP("Server cannot decode client’s request", LogLevel.Error); } catch (VersionRemoteError e) { - System.err.println("Error: Server cannot decode this version of the protocol"); - logger.writeTCP("Error: Server cannot decode this version of the protocol", LogLevel.Error); + logger.writeTCP("Server cannot decode this version of the protocol", LogLevel.Error); } catch (NotFound e) { - System.err.println("Error: Server has not this file in directory"); - logger.writeTCP("Error: Server has not this file in directory", LogLevel.Error); + logger.writeTCP("Server has not this file in directory", LogLevel.Error); } catch (EmptyFile e) { - System.err.println("Error: File is empty"); - logger.writeTCP("Error: File is empty", LogLevel.Error); + logger.writeTCP("File is empty", LogLevel.Error); } } @@ -139,21 +137,18 @@ public class ClientManagementTCP implements Runnable { if (downLoader.getSuccess()) { byte[] hash512 = downLoader.getHashSum512(); if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) { - System.err.println("Error: Hashsum does not match"); - logger.writeTCP("Error: Hashsum does not match", LogLevel.Error); - System.err.println("Computed checksum:"); + logger.writeTCP("Hashsum does not match", LogLevel.Error); + String line = "Computed checksum:\n"; byte[] c = computeHashsum(filename, HashAlgorithm.SHA512); for (byte b: c) { - System.err.print(String.format("%02X", b)); - logger.writeTCP("Computed checksum:" + String.format("%02X", b), LogLevel.Info); + line += String.format("%02X", b); } - System.err.println(""); - System.err.println("Received checksum:"); + line += "\nReceived checksum:\n"; for (byte b: hash512) { - System.err.print(String.format("%02X", b)); - logger.writeTCP("Received checksum:" + String.format("%02X", b), LogLevel.Info); + line += String.format("%02X", b); } - System.err.println(""); + line += "\n"; + logger.writeTCP(line, LogLevel.Info); throw new InternalError(); } } else { @@ -196,7 +191,6 @@ public class ClientManagementTCP implements Runnable { logger.writeTCP(e, LogLevel.Error); throw new ProtocolError(); } catch (SocketClosed e){ - System.err.println("listDirectory : SocketClosed"); logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); throw new ProtocolError(); } catch (NotATracker e) { @@ -214,12 +208,37 @@ public class ClientManagementTCP implements Runnable { MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); return md.digest(Files.readAllBytes(Paths.get(baseDirectory + filename))); } catch (NoSuchAlgorithmException e) { - System.out.println("Error: " + h.getName() + " not supported"); - logger.writeTCP("Error: " + h.getName() + " not supported", LogLevel.Error); + logger.writeTCP(h.getName() + " not supported", LogLevel.Error); } catch (IOException e) { - System.out.println("Error: cannot read " + filename); - logger.writeTCP("Error: cannot read " + filename, LogLevel.Error); + logger.writeTCP("cannot read " + filename, LogLevel.Error); } return new byte[0]; } + + /** Initialize hostList from tracker + * @throws ProtocolError + * @throws InternalError + */ + private void initHostList() throws ProtocolError, InternalError { + ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new DiscoverRequest(null)); + try { + d.sendRequest((Object)tracker.getTCPSocket()); + Payload p = d.receiveResponse().getPayload(); + assert p instanceof DiscoverResponse : "This payload must be instance of Filelist"; + if (!(p instanceof DiscoverResponse)) { + throw new InternalError(); + } else { + hostList = ((DiscoverResponse)p).getHostList(); + } + } catch (SocketClosed e){ + logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); + throw new ProtocolError(); + } catch (NotATracker e) { + logger.writeTCP(e, LogLevel.Error); + throw new ProtocolError(); + } catch (Exception e) { + logger.writeTCP(e, LogLevel.Error); + throw new ProtocolError(); + } + } } diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index aa1da60..b298fc7 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -26,6 +26,8 @@ import protocolP2P.Payload; import protocolP2P.RequestResponseCode; import protocolP2P.FileList; import protocolP2P.HashAlgorithm; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; import tools.HostItem; import tools.Logger; import tools.LogLevel; @@ -41,26 +43,36 @@ public class ClientManagementUDP implements Runnable { private String baseDirectory; private String partsSubdir; private List hostList; + private HostItem tracker; private Logger logger; + private Scanner scanner; - /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. + /** Constructor for UDP implementation, with baseDirectory, tracker, partsSubdir, logger and scanner 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 + * @param tracker tracker HostItem + * @param partsSubdir subdirectory to store file parts + * @param logger Loggger + * @param scanner Scanner used to read input */ - public ClientManagementUDP(String baseDirectory, List hostList, String partsSubdir, Logger logger) { + public ClientManagementUDP(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) { + this.scanner = scanner; this.baseDirectory = baseDirectory; - this.hostList = hostList; + this.tracker = tracker; this.partsSubdir = partsSubdir; this.logger = logger; + try { + initHostList(); + } catch (InternalError e) { + System.exit(-1); + } catch (ProtocolError e) { + System.exit(-2); + } } /** 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) { @@ -68,7 +80,6 @@ public class ClientManagementUDP implements Runnable { } System.out.println("Name of the file to download:"); String f = scanner.nextLine(); - scanner.close(); download(f); System.out.println("File " + f + " sucessfully downloaded"); logger.writeUDP("File " + f + " sucessfully downloaded", LogLevel.Info); @@ -217,4 +228,28 @@ public class ClientManagementUDP implements Runnable { } return new byte[0]; } + + /** Initialize hostList from tracker + * @throws ProtocolError + * @throws InternalError + */ + private void initHostList() throws ProtocolError, InternalError { + ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new DiscoverRequest(null)); + try { + d.sendRequest((Object)tracker.getUDPSocket()); + Payload p = d.receiveResponse().getPayload(); + assert p instanceof DiscoverResponse : "This payload must be instance of Filelist"; + if (!(p instanceof DiscoverResponse)) { + throw new InternalError(); + } else { + hostList = ((DiscoverResponse)p).getHostList(); + } + } catch (NotATracker e) { + logger.writeUDP(e, LogLevel.Error); + throw new ProtocolError(); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); + throw new ProtocolError(); + } + } } diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index a1700b9..1d1b224 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -10,7 +10,6 @@ import tools.Logger; import tools.LogLevel; import tools.Directories; import tools.HostItem; -import tools.HostList; /** Client + Server implementation. * @author Louis Royer @@ -27,9 +26,9 @@ public class ClientP2P { private String host; private int port; private Directories directories; - private List hostList; private static final int defaultPort = 20000; private HostItem tracker; + private Scanner scanner; /** Initialize loggers if directories and logger are null, @@ -47,6 +46,7 @@ public class ClientP2P { * @param portStr String containing port for server listenning. */ public ClientP2P(String portStr) { + scanner = new Scanner(System.in); tracker = new HostItem("localhost", 30000); // TODO : make it configurable try{ port = Integer.valueOf(Integer.parseInt(portStr)); @@ -62,7 +62,7 @@ public class ClientP2P { directories.createSubdir(parts); host = "localhost"; System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory() + subdir); - directories.askOpenDataHomeDirectory(subdir); + directories.askOpenDataHomeDirectory(subdir, scanner); System.out.println("Please enter list of servers to use; first one will be used to ask list of files"); } @@ -102,11 +102,9 @@ public class ClientP2P { } // initialize Host lists - c.hostList = HostList.getServList(); System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]"); - Scanner sc = new Scanner(System.in); - String transportchoosen = sc.nextLine(); - sc.close(); + c.scanner.hasNextLine(); + String transportchoosen = c.scanner.nextLine(); Thread t; switch(transportchoosen){ case "UDP": @@ -114,7 +112,7 @@ public class ClientP2P { case "upd": // alias typo case "2" : System.out.println("Starting with UDP"); - ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); + ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient, c.scanner); t = new Thread(cmudp); break; case "TCP": @@ -122,12 +120,16 @@ public class ClientP2P { case "1": default: System.out.println("Starting with TCP"); - ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.hostList, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient); + ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient, c.scanner); t = new Thread(cmtcp); break; } t.setName("client P2P-JAVA-PROJECT"); t.start(); + try { + t.join(); + } catch (InterruptedException e) {} + c.scanner.close(); } } } diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index 1b57958..df0a3f1 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -4,6 +4,7 @@ import serverP2P.ServerManagementTCP; import tools.Directories; import tools.Logger; import tools.HostItem; +import java.util.Scanner; /** Server only implementation * First argument of main method is port listened by the server, and is mandatory. @@ -29,7 +30,9 @@ public class ServerP2P { directories.createSubdir(subdir); logger = new Logger(directories.getDataHomeDirectory() + "server.log"); System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory() + subdir); - directories.askOpenDataHomeDirectory(subdir); + Scanner scanner = new Scanner(System.in); + directories.askOpenDataHomeDirectory(subdir, scanner); + scanner.close(); } /** Main program entry point diff --git a/src/tools/BytesArrayTools.java b/src/tools/BytesArrayTools.java index f1cbe85..554bc3a 100644 --- a/src/tools/BytesArrayTools.java +++ b/src/tools/BytesArrayTools.java @@ -231,11 +231,13 @@ public class BytesArrayTools { try { int i = start; while(true) { + int j = i; for(byte b: endStr.getBytes()) { - if (b != array[i]) { + if (b != array[j]) { failed = true; break; } + j++; } if (failed) { i++; @@ -244,7 +246,7 @@ public class BytesArrayTools { break; } } - return readString(array, start, i -1 - start); + return readString(array, start, i - start); } catch(IndexOutOfBoundsException e) { throw new InternalError(); } diff --git a/src/tools/Directories.java b/src/tools/Directories.java index 8c9a86e..0ee49c6 100644 --- a/src/tools/Directories.java +++ b/src/tools/Directories.java @@ -70,6 +70,7 @@ public class Directories { } /** Opens dataHomeDirectory if supported. + * @param subdir Subdir to open (optional) */ private void openDataHomeDirectory(String subdir) { String d = dataHomeDirectory; @@ -93,13 +94,13 @@ public class Directories { } /** Asks the user to choose opening dataHomeDirectory or not. + * @param subdir subdirectory to open (optional) + * @param scanner Scanner to use for reading input */ - public void askOpenDataHomeDirectory(String subdir) { + public void askOpenDataHomeDirectory(String subdir, Scanner scanner) { if (os.equals("Linux") || os.equals("Mac") || os.equals("Mac OS X")) { System.out.println("Do you want to open this directory? (y/N)"); - Scanner scanner = new Scanner(System.in); String resp = scanner.nextLine(); - scanner.close(); if (resp.equals("y") || resp.equals("Y")) { System.out.println("Openning"); openDataHomeDirectory(subdir); diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index 80b4f13..231e6b7 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -36,13 +36,13 @@ public class HostItem { try { tcpSocket = new Socket(InetAddress.getByName(hostname), port); } catch (SocketException e) { - System.err.println("Error: No TCP socket available."); + System.err.println("getTCPSocket error: No TCP socket available."); System.exit(-1); } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); + System.err.println("getTCPSocket error: Unknown host (" + this + ")."); System.exit(-1); } catch (IOException e) { - System.err.println("Error: Cannot create TCP socket"); + System.err.println("getTCPSocket error: Cannot create TCP socket (" + this + ")."); System.exit(-1); } } @@ -71,10 +71,10 @@ public class HostItem { udpSocket = new DatagramSocket(); udpSocket.connect(InetAddress.getByName(hostname), port); } catch (SocketException e) { - System.err.println("Error: No UDP socket available."); + System.err.println("getUDPSocket error: No UDP socket available." ); System.exit(-1); } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); + System.err.println("getUDPSocket error: Unknown host (" + this + ")."); System.exit(-1); } } @@ -135,7 +135,7 @@ public class HostItem { try { inetAddress = InetAddress.getByName(getHostname()); } catch (UnknownHostException e) { - System.err.println("Error: Unknown host."); + System.err.println("getInetAddress error: Unknown host (" + this + ")."); System.exit(-1); } } diff --git a/src/tools/HostList.java b/src/tools/HostList.java deleted file mode 100644 index eae5e4e..0000000 --- a/src/tools/HostList.java +++ /dev/null @@ -1,56 +0,0 @@ -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")); - scanner.close(); - return serverList; - } -} diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index bb82422..8607610 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -3,6 +3,7 @@ import tracker.TrackerManagementTCP; import tracker.TrackerManagementUDP; import tools.Directories; import tools.Logger; +import java.util.Scanner; /** Tracker implementation * First argument of main method is port listened by the tracker, and is mandatory. @@ -24,7 +25,9 @@ public class Tracker { directories = new Directories("P2P_JAVA_PROJECT_TRACKER_" + port); logger = new Logger(directories.getDataHomeDirectory() + "tracker.log"); System.out.println("Tracker will listen on port " + port + " and write logs into " + directories.getDataHomeDirectory()); - directories.askOpenDataHomeDirectory(null); + Scanner scanner = new Scanner(System.in); + directories.askOpenDataHomeDirectory(null, scanner); + scanner.close(); } /** Main program entry point diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 5f75aa2..c26c9c9 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -20,8 +20,8 @@ import java.util.HashMap; import protocolP2P.DiscoverRequest; import protocolP2P.DiscoverResponse; import protocolP2P.FileList; -import protocolP2P.HashRequest; import localException.InternalError; +import remoteException.EmptyDirectory; import java.net.UnknownHostException; import java.net.InetAddress; import localException.SocketClosed; @@ -204,6 +204,10 @@ public class TrackerManagementTCP implements Runnable { handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); logger.writeTCP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); host.closeTCPSocket(); + } catch (EmptyDirectory e) { + logger.writeTCP("Empty Directory", LogLevel.Debug); + hostList.remove(host); + logger.writeTCP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); } catch (Exception e) { // remove from list because list request could not be send hostList.remove(host); @@ -245,7 +249,7 @@ public class TrackerManagementTCP implements Runnable { if (!(p instanceof DiscoverRequest)) { sendInternalError(pd); } else { - String filename = ((HashRequest)p).getFilename(); + String filename = ((DiscoverRequest)p).getFilename(); try { pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); } catch (Exception e) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 3a3cbc2..4d31c2f 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -19,7 +19,6 @@ import java.util.HashMap; import protocolP2P.DiscoverRequest; import protocolP2P.DiscoverResponse; import protocolP2P.FileList; -import protocolP2P.HashRequest; import localException.InternalError; import remoteException.EmptyDirectory; import java.net.InetAddress; @@ -201,7 +200,7 @@ public class TrackerManagementUDP implements Runnable { if (!(p instanceof DiscoverRequest)) { sendInternalError(pd); } else { - String filename = ((HashRequest)p).getFilename(); + String filename = ((DiscoverRequest)p).getFilename(); try { pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); } catch (Exception e) { From 5f48c9cbc1ad9ac09f109a4a24c90cc394634c52 Mon Sep 17 00:00:00 2001 From: Louis Royer Date: Sat, 21 Mar 2020 22:30:42 +0100 Subject: [PATCH 21/40] Fix #27 (#64) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #27 - [x] Faire un thread qui tous les X secondes (configurable) va comparer les fichiers dispo avec la liste et mettre à jour (penser à le logger). La mise à jour peut s’effectuer en faisant juste une REGISTER REQUEST. - [x] Télécharger dans le même dossier que celui où on seed - [x] Mettre les logs dans un dossier pas partagé Co-authored-by: Louis --- src/clientP2P/ClientP2P.java | 32 ++--- src/exception/LocalException.java | 2 +- src/exception/RemoteException.java | 2 +- src/serverP2P/ServerManagementTCP.java | 158 +++++++++++++++++-------- src/serverP2P/ServerManagementUDP.java | 148 ++++++++++++++++------- src/tools/HostItem.java | 13 ++ src/tracker/TrackerManagementUDP.java | 2 + 7 files changed, 248 insertions(+), 109 deletions(-) diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 1d1b224..f2ea80f 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -19,8 +19,8 @@ import tools.HostItem; */ public class ClientP2P { - private String subdir = "seeded/"; - private String parts = ".parts"; + private String logDir = "logs/"; + private String partsDir = ".parts/"; private Logger loggerServer; private Logger loggerClient; private String host; @@ -34,11 +34,13 @@ public class ClientP2P { /** Initialize loggers if directories and logger are null, * else fail silently. */ - public void initLogger() { + public void initDirectoriesAndLoggers() { if (directories == null && loggerServer == null && loggerClient == null) { directories = new Directories("P2P_JAVA_PROJECT_" + port); - loggerServer = new Logger(directories.getDataHomeDirectory() + "server.log"); - loggerClient = new Logger(directories.getDataHomeDirectory() + "client.log"); + directories.createSubdir(logDir); + loggerServer = new Logger(directories.getDataHomeDirectory() + logDir + "server.log"); + loggerClient = new Logger(directories.getDataHomeDirectory() + logDir + "client.log"); + directories.createSubdir(partsDir); } } @@ -53,16 +55,14 @@ public class ClientP2P { } catch (NumberFormatException e){ int oldPort = port; port = defaultPort; - initLogger(); + initDirectoriesAndLoggers(); System.err.println("Error incorrect port " + oldPort + " using default port " + defaultPort); loggerServer.write("incorrect port " + oldPort + " using default port " + defaultPort, LogLevel.Info); } - initLogger(); - directories.createSubdir(subdir); - directories.createSubdir(parts); + initDirectoriesAndLoggers(); host = "localhost"; - System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory() + subdir); - directories.askOpenDataHomeDirectory(subdir, scanner); + System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory()); + directories.askOpenDataHomeDirectory(null, scanner); System.out.println("Please enter list of servers to use; first one will be used to ask list of files"); } @@ -84,8 +84,8 @@ public class ClientP2P { } // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory() + c.subdir, "localhost", c.port, c.loggerServer, c.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory() + c.subdir, "localhost", c.port, c.loggerServer, c.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory(), "localhost", c.port, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory(), "localhost", c.port, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); tudp.start(); @@ -96,7 +96,7 @@ public class ClientP2P { // Wait a bit before printing client interface // This is not required, but allow to have a cleaner interface try { - Thread.sleep(100); + Thread.sleep(200); } catch(InterruptedException e) { Thread.currentThread().interrupt(); } @@ -112,7 +112,7 @@ public class ClientP2P { case "upd": // alias typo case "2" : System.out.println("Starting with UDP"); - ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient, c.scanner); + ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); t = new Thread(cmudp); break; case "TCP": @@ -120,7 +120,7 @@ public class ClientP2P { case "1": default: System.out.println("Starting with TCP"); - ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.parts + "/", c.loggerClient, c.scanner); + ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); t = new Thread(cmtcp); break; } diff --git a/src/exception/LocalException.java b/src/exception/LocalException.java index 5c115d5..2fbc0f2 100644 --- a/src/exception/LocalException.java +++ b/src/exception/LocalException.java @@ -1,5 +1,5 @@ package exception; -public class LocalException extends Exception { +public abstract class LocalException extends Exception { private static final long serialVersionUID = 12L; } diff --git a/src/exception/RemoteException.java b/src/exception/RemoteException.java index cfb2cd7..968c8db 100644 --- a/src/exception/RemoteException.java +++ b/src/exception/RemoteException.java @@ -1,5 +1,5 @@ package exception; -public class RemoteException extends Exception { +public abstract class RemoteException extends Exception { private static final long serialVersionUID = 12L; } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 359d616..5cbe8af 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -51,6 +51,8 @@ public class ServerManagementTCP implements Runnable { private Logger logger; private HostItem tracker; private HostItem server; + private FileListWatcher fileListWatcher; + private volatile boolean stop; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. * @param baseDirectory the root directory where files are stored @@ -60,12 +62,12 @@ public class ServerManagementTCP implements Runnable { * @param tracker Tracker */ public ServerManagementTCP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { + stop = false; server = new HostItem(hostName, port); + fileList = new String[0]; this.tracker = tracker; this.logger = logger; this.baseDirectory = baseDirectory; - initFileList(); - initSha512(); try { socket = new ServerSocket(server.getPort(), 10, server.getInetAddress()); } catch (SocketException e) { @@ -77,12 +79,26 @@ public class ServerManagementTCP implements Runnable { } } + /** Stop the thread */ + public void setStop() { + stop = true; + } + + /** Trigger a manual check of the file list + */ + public void updateFileList() { + if (fileListWatcher != null) { + fileListWatcher.trigger(); + } + } + /** Implementation of runnable. This methods allows to run the server. */ public void run() { logger.writeTCP("Server sucessfully started", LogLevel.Info); - (new Thread(new TrackerRegisterer())).start(); - do { + fileListWatcher = new FileListWatcher(10000); // checking every 10 seconds + (new Thread(fileListWatcher)).start(); + while(!stop) { try { Socket s = socket.accept(); ClientHandler c = new ClientHandler(s); @@ -90,7 +106,17 @@ public class ServerManagementTCP implements Runnable { } catch (IOException e) { logger.writeTCP("Error while accepting new connection", LogLevel.Warning); } - } while(true); + } + fileListWatcher.setStop(); + // unregistering from tracker + try { + logger.writeTCP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server)); + p.sendRequest((Object)tracker.getTCPSocket()); + } catch (Exception e) { + logger.writeTCP("Cannot unregister from tracker", LogLevel.Error); + logger.writeTCP(e, LogLevel.Error); + } } /** Private runnable class allowing to serve one client. @@ -167,22 +193,6 @@ public class ServerManagementTCP implements Runnable { } } - /** Initialize local list of all files allowed to be shared. - */ - private void initFileList() { - File folder = new File(baseDirectory); - Vector v = new Vector(); - File[] files = folder.listFiles(); - /* Add non-recursively files's names to fileList */ - for (File f : files) { - if (f.isFile()) { - v.add(f.getName()); - } - } - fileList = new String[v.size()]; - v.toArray(fileList); - Arrays.sort(fileList); - } /** Init sha512 map. */ @@ -333,39 +343,89 @@ public class ServerManagementTCP implements Runnable { } } - /** Private runnable class allowing to initialize tracker while initializing server. */ - private class TrackerRegisterer implements Runnable { - - /** Runnable implementation */ - public void run() { + /** Private runnable class allowing to keep the tracker informed about file list. */ + private class FileListWatcher implements Runnable { + private volatile boolean stop; + private long time; + private boolean force; + + /** Register server on tracker + */ + private void registerTracker() { try { - registerTracker(); + logger.writeTCP("Trying to into tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); + p.sendRequest((Object)tracker.tryGetTCPSocket()); + logger.writeTCP("Register request sent.", LogLevel.Debug); + tracker.closeTCPSocket(); } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - System.exit(-4); + // error, trying again at next iteration + force = true; + logger.writeTCP("Cannot contact tracker, trying again at next iteration (" + time + " milliseconds).", LogLevel.Error); } } - /** Register server on tracker - * @throws InternalError - * @throws IOException - * @throws SocketClosed + + /** Update fileList and returns true if different than old list. + * @return true if changed */ - private void registerTracker() throws InternalError, IOException, SocketClosed { - logger.writeTCP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server)); - p.sendRequest((Object)tracker.getTCPSocket()); - // FIXME: this is a hack - // ProtocolP2PPacketTCP reads 1024 bytes but if 2 request comes at the same time InputStream is cleared fully - // and we keep waiting forever on the other side - // a fix could be to read only the header first, and read the required size after - try { - Thread.sleep(100); - } catch (InterruptedException e) {} - logger.writeTCP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); - p.sendRequest((Object)tracker.getTCPSocket()); - logger.writeTCP("Registering completed", LogLevel.Debug); - tracker.closeTCPSocket(); + private boolean updateFileList() { + File folder = new File(baseDirectory); + Vector v = new Vector(); + File[] files = folder.listFiles(); + /* Add non-recursively files's names to fileList */ + for (File f : files) { + if (f.isFile()) { + v.add(f.getName()); + } + } + String[] newFileList = new String[v.size()]; + v.toArray(newFileList); + Arrays.sort(newFileList); + if (!Arrays.equals(newFileList, fileList)) { + fileList = newFileList; + initSha512(); + return true; + } else { + return false; + } + } + + /** Constructor with millis parameter + * @param millis interval of time between checks + */ + public FileListWatcher(long millis) { + this.stop = false; + this.time = millis; + } + + /** Ask the thread to stop + */ + public void setStop() { + stop = true; + } + + /** Allow a manual check + */ + public void trigger() { + if (updateFileList() || force) { + force = false; + logger.writeTCP("File list watcher detected changes. Informing tracker.", LogLevel.Info); + registerTracker(); + } + } + + /** Runnable implementation */ + public void run() { + logger.writeTCP("File list watcher started : delay " + time + " milliseconds.", LogLevel.Info); + while(!stop) { + trigger(); + try { + Thread.sleep(time); + } catch(InterruptedException e) { + logger.writeTCP("File list watcher interrupted", LogLevel.Error); + setStop(); + } + } } } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index fbc0795..25a988a 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -43,13 +43,15 @@ import java.net.UnknownHostException; */ public class ServerManagementUDP implements Runnable { - private String[] fileList; + private String[] fileList = new String[0]; private Map sha512 = new HashMap<>(); private String baseDirectory; private DatagramSocket socket; private Logger logger; private HostItem tracker; private HostItem server; + private FileListWatcher fileListWatcher; + private volatile boolean stop; /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. * @param baseDirectory the root directory where files are stored @@ -59,12 +61,11 @@ public class ServerManagementUDP implements Runnable { * @param tracker Tracker */ public ServerManagementUDP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { + stop = false; server = new HostItem(hostName, port); this.logger = logger; this.baseDirectory = baseDirectory; this.tracker = tracker; - initFileList(); - initSha512(); try { socket = new DatagramSocket(server.getPort(), server.getInetAddress()); } catch (SocketException e) { @@ -73,12 +74,26 @@ public class ServerManagementUDP implements Runnable { } } + /** Stop the thread */ + public void setStop() { + stop = true; + } + + /** Trigger a manual check of the file list + */ + public void updateFileList() { + if (fileListWatcher != null) { + fileListWatcher.trigger(); + } + } + /** Implementation of runnable. This methods allows to run the server. */ public void run() { logger.writeUDP("Server sucessfully started", LogLevel.Info); - (new Thread(new TrackerRegisterer())).start(); - while(true) { + fileListWatcher = new FileListWatcher(10000); // checking every 10 seconds + (new Thread(fileListWatcher)).start(); + while(!stop) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); Payload p = pd.getPayload(); @@ -111,23 +126,15 @@ public class ServerManagementUDP implements Runnable { } catch (SizeError e) { } } - } - - /** Initialize local list of all files allowed to be shared. - */ - private void initFileList() { - File folder = new File(baseDirectory); - Vector v = new Vector(); - File[] files = folder.listFiles(); - /* Add non-recursively files's names to fileList */ - for (File f : files) { - if (f.isFile()) { - v.add(f.getName()); - } + fileListWatcher.setStop(); + // unregistering from tracker + try { + logger.writeUDP("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(server)); + p.sendRequest((Object)tracker.getUDPSocket()); + } catch (Exception e) { + logger.writeUDP(e, LogLevel.Error); } - fileList = new String[v.size()]; - v.toArray(fileList); - Arrays.sort(fileList); } /** Init sha512 map. @@ -280,32 +287,89 @@ public class ServerManagementUDP implements Runnable { } } -/** Private runnable class allowing to initialize tracker while initializing server. */ - private class TrackerRegisterer implements Runnable { - - /** Runnable implementation */ - public void run() { + /** Private runnable class allowing to keep the tracker informed about file list. */ + private class FileListWatcher implements Runnable { + private volatile boolean stop; + private long time; + private boolean force; + + /** Register server on tracker + */ + private void registerTracker() { try { - registerTracker(); + logger.writeUDP("Trying to register into tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(server)); + p.sendRequest((Object)tracker.getUDPSocket()); + logger.writeUDP("Register request sent (but cannot ensure reception).", LogLevel.Debug); + tracker.closeUDPSocket(); } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - System.exit(-4); + force = true; + logger.writeUDP("Cannot contact tracker, trying again at next iteration (" + time + " milliseconds).", LogLevel.Error); } } - /** Register server on tracker - * @throws InternalError - * @throws IOException - * @throws SocketClosed + + /** Update fileList and returns true if different than old list. + * @return true if changed */ - private void registerTracker() throws InternalError, IOException, SocketClosed { - logger.writeUDP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(server)); - p.sendRequest((Object)tracker.getUDPSocket()); - logger.writeUDP("Registering into tracker", LogLevel.Info); - p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(server)); - p.sendRequest((Object)tracker.getUDPSocket()); - logger.writeUDP("Registering completed", LogLevel.Debug); - tracker.closeUDPSocket(); + private boolean updateFileList() { + File folder = new File(baseDirectory); + Vector v = new Vector(); + File[] files = folder.listFiles(); + /* Add non-recursively files's names to fileList */ + for (File f : files) { + if (f.isFile()) { + v.add(f.getName()); + } + } + String[] newFileList = new String[v.size()]; + v.toArray(newFileList); + Arrays.sort(newFileList); + if (!Arrays.equals(newFileList, fileList)) { + fileList = newFileList; + initSha512(); + return true; + } else { + return false; + } + } + + /** Constructor with millis parameter + * @param millis interval of time between checks + */ + public FileListWatcher(long millis) { + this.force = true; + this.stop = false; + this.time = millis; + } + + /** Ask the thread to stop + */ + public void setStop() { + stop = true; + } + + /** Allow a manual check + */ + public void trigger() { + if (updateFileList() || force) { + force = false; + logger.writeUDP("File list watcher detected changes. Informing tracker.", LogLevel.Info); + registerTracker(); + } + } + + /** Runnable implementation */ + public void run() { + logger.writeUDP("File list watcher started : delay " + time + " milliseconds.", LogLevel.Info); + while(!stop) { + trigger(); + try { + Thread.sleep(time); + } catch(InterruptedException e) { + logger.writeUDP("File list watcher interrupted", LogLevel.Error); + setStop(); + } + } } } } diff --git a/src/tools/HostItem.java b/src/tools/HostItem.java index 231e6b7..95960af 100644 --- a/src/tools/HostItem.java +++ b/src/tools/HostItem.java @@ -49,6 +49,19 @@ public class HostItem { return tcpSocket; } + /** Get TCP Socket. + * @return TCP Socket + * @throws SocketException + * @throws UnknownHostException + * @throws IOException + */ + public Socket tryGetTCPSocket() throws SocketException, UnknownHostException, IOException { + if (tcpSocket == null) { + tcpSocket = new Socket(InetAddress.getByName(hostname), port); + } + return tcpSocket; + } + /** Closes tcp socket */ public void closeTCPSocket() { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 4d31c2f..42d6445 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -75,9 +75,11 @@ public class TrackerManagementUDP implements Runnable { sendNotFound(pd); break; case REGISTER: + logger.writeUDP("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); handleRegister(pd); break; case UNREGISTER: + logger.writeUDP("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); handleUnregister(pd); break; case DISCOVER_REQUEST: From 33f1829cdc7b96c5acec87cbb458a2fcf400aff7 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 22 Mar 2020 09:38:56 +0100 Subject: [PATCH 22/40] Update Jenkinsfile to add tracker.jar generation --- Jenkinsfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 9e9770e..399f133 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,6 +11,10 @@ sh 'echo "BUILDING SERVER"' 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 'echo "BUILDING TRACKER"' + sh 'echo Main-Class: tracker/Tracker > MANIFEST.MF' + sh 'jar -cvmf MANIFEST.MF tracker.jar $(find bin/ -maxdepth 1 -mindepth 1 -printf "-C bin %f\n")' + sh 'echo "CREATING sources.tar.gz"' sh 'tar -zcvf sources.tar.gz src/' } } @@ -24,6 +28,7 @@ success { archiveArtifacts artifacts: 'client.jar', fingerprint: true archiveArtifacts artifacts: 'server.jar', fingerprint: true + archiveArtifacts artifacts: 'tracker.jar', fingerprint: true archiveArtifacts artifacts: 'sources.tar.gz', fingerprint: true } } From ef5484566e1ec8c27f67e5a22b2d9472e8e46f84 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 22 Mar 2020 12:23:56 +0100 Subject: [PATCH 23/40] Classes abstraites pour le Serveur Fix #40 --- src/clientP2P/ClientP2P.java | 3 + src/protocolP2P/ProtocolP2PPacket.java | 2 +- src/serverP2P/FileWatcher.java | 156 +++++++++++++ src/serverP2P/FileWatcherTCP.java | 65 ++++++ src/serverP2P/FileWatcherUDP.java | 64 ++++++ src/serverP2P/ServerManagement.java | 234 ++++++++++++++++++++ src/serverP2P/ServerManagementTCP.java | 289 +++---------------------- src/serverP2P/ServerManagementUDP.java | 289 +++---------------------- 8 files changed, 579 insertions(+), 523 deletions(-) create mode 100644 src/serverP2P/FileWatcher.java create mode 100644 src/serverP2P/FileWatcherTCP.java create mode 100644 src/serverP2P/FileWatcherUDP.java create mode 100644 src/serverP2P/ServerManagement.java diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index f2ea80f..28d1b67 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -130,6 +130,9 @@ public class ClientP2P { t.join(); } catch (InterruptedException e) {} c.scanner.close(); + smudp.setStop(); + smtcp.setStop(); + } } } diff --git a/src/protocolP2P/ProtocolP2PPacket.java b/src/protocolP2P/ProtocolP2PPacket.java index 74a1dcd..c0312c4 100644 --- a/src/protocolP2P/ProtocolP2PPacket.java +++ b/src/protocolP2P/ProtocolP2PPacket.java @@ -49,7 +49,7 @@ public abstract class ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public abstract void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException, SocketClosed; + public abstract void sendResponse(T response) throws InternalError, IOException, SocketClosed; /** Get hostItem of the sender * @return hostItem of the sender diff --git a/src/serverP2P/FileWatcher.java b/src/serverP2P/FileWatcher.java new file mode 100644 index 0000000..d6bf632 --- /dev/null +++ b/src/serverP2P/FileWatcher.java @@ -0,0 +1,156 @@ +package serverP2P; +import tools.Logger; +import tools.LogLevel; +import tools.HostItem; +import java.io.File; +import java.util.Vector; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import protocolP2P.HashAlgorithm; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.io.IOException; + +/** Class allowing to keep the tracker informed about file list + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public abstract class FileWatcher implements Runnable { + protected String[] fileList = new String[0]; + protected Logger logger; + protected volatile boolean stop; + protected long time; + protected boolean force; + protected HostItem server; + protected HostItem tracker; + protected String baseDirectory; + protected Map sha512 = new HashMap<>(); + + + /** Constructor + * @param logger Logger + * @param millis Time interval before recheck + * @param server HostItem for the server + * @param tracker HostItem for the tracker + * @param baseDirectory Directory to search files + */ + public FileWatcher(Logger logger, long millis, HostItem server, HostItem tracker, String baseDirectory) { + assert logger != null : "Logger is null"; + assert server != null : "Server is null"; + assert tracker != null : "Tracker is null"; + assert baseDirectory != null : "baseDirectory is null"; + this.logger = logger; + time = millis; + this.server = server; + this.tracker = tracker; + this.baseDirectory = baseDirectory; + } + + /** FileList getter + * @return fileList + */ + public String[] getFileList() { + return fileList; + } + + /** Sha512 map getter + * @return sha512 hashmap + */ + public Map getSha512Map() { + return sha512; + } + + /** Allow a manual check + */ + public void trigger() { + if (updateFileList() || force) { + force = false; + writeLog("File list watcher detected changes. Informing tracker.", LogLevel.Info); + registerTracker(); + } + } + + /** Runnable implementation */ + public void run() { + writeLog("File list watcher started : delay " + time + " milliseconds.", LogLevel.Info); + while(!stop) { + trigger(); + try { + Thread.sleep(time); + } catch(InterruptedException e) { + writeLog("File list watcher interrupted", LogLevel.Error); + setStop(); + } + } + } + + /** Register server on tracker + */ + protected abstract void registerTracker(); + + /** Update fileList and returns true if different than old list. + * @return true if changed + */ + protected boolean updateFileList() { + File folder = new File(baseDirectory); + Vector v = new Vector(); + File[] files = folder.listFiles(); + /* Add non-recursively files's names to fileList */ + for (File f : files) { + if (f.isFile()) { + v.add(f.getName()); + } + } + String[] newFileList = new String[v.size()]; + v.toArray(newFileList); + Arrays.sort(newFileList); + if (!Arrays.equals(newFileList, fileList)) { + fileList = newFileList; + initSha512(); + return true; + } else { + return false; + } + } + + + /** Ask the thread to stop + */ + public void setStop() { + stop = true; + } + + /** Init sha512 map. + */ + protected void initSha512() { + for(String f: fileList) { + try { + MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); + sha512.put(f, md.digest(Files.readAllBytes(Paths.get(baseDirectory + f)))); + md.reset(); + } catch (NoSuchAlgorithmException e) { + writeLog("sha512 not supported", LogLevel.Error); + } catch (IOException e) { + writeLog("cannot read " + f, LogLevel.Warning); + } + } + } + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected abstract void writeLog(String text, LogLevel logLevel); + + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected abstract void writeLog(Exception e, LogLevel logLevel); + +} diff --git a/src/serverP2P/FileWatcherTCP.java b/src/serverP2P/FileWatcherTCP.java new file mode 100644 index 0000000..9f3936c --- /dev/null +++ b/src/serverP2P/FileWatcherTCP.java @@ -0,0 +1,65 @@ +package serverP2P; +import tools.Logger; +import tools.LogLevel; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.ProtocolP2PPacketTCP; +import protocolP2P.Register; +import protocolP2P.Payload; +import tools.HostItem; + +/** Class allowing to keep the tracker informed about file list (TCP impl.) + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class FileWatcherTCP extends FileWatcher { + + /** Constructor + * @param logger Logger + * @param millis Time interval before recheck + * @param server HostItem for the server + * @param tracker HostItem for the tracker + * @param baseDirectory Directory to search files + */ + public FileWatcherTCP(Logger logger, long millis, HostItem server, HostItem tracker, String baseDirectory) { + super(logger, millis, server, tracker, baseDirectory); + assert logger != null : "Logger is null"; + assert server != null : "Server is null"; + assert tracker != null : "Tracker is null"; + assert baseDirectory != null : "baseDirectory is null"; + } + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected void writeLog(String text, LogLevel logLevel) { + logger.writeTCP(text, logLevel); + } + + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeTCP(e, logLevel); + } + + /** Register server on tracker + */ + protected void registerTracker() { + try { + writeLog("Trying to into tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); + p.sendRequest((Object)tracker.tryGetTCPSocket()); + writeLog("Register request sent.", LogLevel.Debug); + tracker.closeTCPSocket(); + } catch (Exception e) { + // error, trying again at next iteration + force = true; + writeLog("Cannot contact tracker, trying again at next iteration (" + time + " milliseconds).", LogLevel.Error); + } + } + +} diff --git a/src/serverP2P/FileWatcherUDP.java b/src/serverP2P/FileWatcherUDP.java new file mode 100644 index 0000000..9cc1021 --- /dev/null +++ b/src/serverP2P/FileWatcherUDP.java @@ -0,0 +1,64 @@ +package serverP2P; +import tools.Logger; +import tools.LogLevel; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.ProtocolP2PPacketUDP; +import protocolP2P.Register; +import protocolP2P.Payload; +import tools.HostItem; + +/** Class allowing to keep the tracker informed about file list (UDP impl.) + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class FileWatcherUDP extends FileWatcher { + + /** Constructor + * @param logger Logger + * @param millis Time interval before recheck + * @param server HostItem for the server + * @param tracker HostItem for the tracker + * @param baseDirectory Directory to search files + */ + public FileWatcherUDP(Logger logger, long millis, HostItem server, HostItem tracker, String baseDirectory) { + super(logger, millis, server, tracker, baseDirectory); + assert logger != null : "Logger is null"; + assert server != null : "Server is null"; + assert tracker != null : "Tracker is null"; + assert baseDirectory != null : "baseDirectory is null"; + } + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected void writeLog(String text, LogLevel logLevel) { + logger.writeUDP(text, logLevel); + } + + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeUDP(e, logLevel); + } + + /** Register server on tracker + */ + protected void registerTracker() { + try { + writeLog("Trying to register into tracker", LogLevel.Info); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(server)); + p.sendRequest((Object)tracker.getUDPSocket()); + writeLog("Register request sent (but cannot ensure reception).", LogLevel.Debug); + tracker.closeUDPSocket(); + } catch (Exception e) { + force = true; + writeLog("Cannot contact tracker, trying again at next iteration (" + time + " milliseconds).", LogLevel.Error); + } + } + +} diff --git a/src/serverP2P/ServerManagement.java b/src/serverP2P/ServerManagement.java new file mode 100644 index 0000000..3962b5f --- /dev/null +++ b/src/serverP2P/ServerManagement.java @@ -0,0 +1,234 @@ +package serverP2P; +import serverP2P.FileWatcher; +import tools.Logger; +import tools.LogLevel; +import tools.HostItem; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.Payload; +import protocolP2P.RequestResponseCode; +import protocolP2P.FileList; +import protocolP2P.FilePart; +import protocolP2P.LoadRequest; +import protocolP2P.HashRequest; +import protocolP2P.HashResponse; +import protocolP2P.HashAlgorithm; +import protocolP2P.Unregister; +import java.nio.file.Paths; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import java.io.IOException; + +/** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public abstract class ServerManagement implements Runnable { + + protected volatile boolean stop; + protected FileWatcher fileListWatcher; + protected Logger logger; + protected String baseDirectory; + protected HostItem server; + protected HostItem tracker; + + /** Constructor */ + public ServerManagement(String baseDirectory, HostItem server, HostItem tracker, Logger logger) { + assert baseDirectory != null : "baseDirectory is null"; + assert server != null : "server is null"; + assert tracker != null : "tracker is null"; + assert logger != null : "logger is null"; + stop = false; + this.baseDirectory = baseDirectory; + this.server = server; + this.tracker = tracker; + this.logger = logger; + } + + /** Stop the thread */ + public void setStop() { + stop = true; + } + + /** Trigger a manual check of the file list + */ + public void updateFileList() { + if (fileListWatcher != null) { + fileListWatcher.trigger(); + } + } + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected abstract void writeLog(String text, LogLevel logLevel); + + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected abstract void writeLog(Exception e, LogLevel logLevel); + + /** Create packets + * @param payload Payload + */ + protected abstract < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload); + + /** Send response to list request + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendListResponse(T pd) { + try { + String[] fileList = fileListWatcher.getFileList(); + if (fileList.length == 0) { + writeLog("Sending EMPTY_DIRECTORY to host " + pd.getHostItem(), LogLevel.Action); + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } else { + writeLog("Sending LIST_RESPONSE to host " + pd.getHostItem(), LogLevel.Action); + pd.sendResponse(createProtocolP2PPacket((Payload)(new FileList(fileList)))); + } + } catch (Exception e2) { + writeLog(e2, LogLevel.Error); + } + } + + /** Send a NotATracker error message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendNotATracker(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_A_TRACKER))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send an internal error message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendInternalError(T pd) { + writeLog("Internal Error", LogLevel.Warning); + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.INTERNAL_ERROR))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send hash response to hash request + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendHashResponse(T pd) { + Payload p = pd.getPayload(); + assert p instanceof HashRequest : "payload must be an instance of HashRequest"; + if (!(p instanceof HashRequest)) { + sendInternalError(pd); + } else { + String filename = ((HashRequest)p).getFilename(); + if (Arrays.binarySearch(fileListWatcher.getFileList(), filename) >= 0) { + Map hashes = new HashMap<>(); + for (HashAlgorithm h : ((HashRequest)p).getAlgoList()) { + switch (h) { + case SHA512: + hashes.put(h, fileListWatcher.getSha512Map().get(filename)); + break; + case MD5: + default: + hashes.put(h, new byte[0]); + break; + } + } + try { + pd.sendResponse(createProtocolP2PPacket((Payload)(new HashResponse(filename, hashes)))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } else { + // file not found + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + } + } + + /** Send response to load request + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendLoadResponse(T pd) { + Payload p = pd.getPayload(); + assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; + if (!(p instanceof LoadRequest)) { + sendInternalError(pd); + } else { + String filename = ((LoadRequest)p).getFilename(); + long offset = ((LoadRequest)p).getOffset(); + long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent(); + try { + byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename)); + long sizeToSend = 0; + if (fullLoad.length - offset < maxSizePartialContent) { + writeLog("Sending last partialContent", LogLevel.Debug); + sizeToSend = fullLoad.length - offset; + } else { + sizeToSend = maxSizePartialContent; + } + writeLog("maxSizePartialContent: " + maxSizePartialContent, LogLevel.Debug); + writeLog("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend), LogLevel.Debug); + byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend)); + String[] fileList = fileListWatcher.getFileList(); + if (Arrays.binarySearch(fileList, filename) >= 0) { + try { + if (load.length == 0) { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_FILE))); + } else { + pd.sendResponse(createProtocolP2PPacket((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); + } + } catch (Exception e2) { + writeLog(e2, LogLevel.Error); + } + } else { + writeLog("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename), LogLevel.Debug); + writeLog("File list:", LogLevel.Debug); + for (String f: fileList) { + writeLog("- " + f, LogLevel.Debug); + } + + throw new IOException(); // to send a NOT_FOUND in the catch block + } + } catch (IOException e) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e2) { + writeLog(e2, LogLevel.Debug); + } + } + } + } + + + /** Getter for tracker socket + */ + protected abstract Object getTrackerSocket(); + + /** Send unregister request to tracker + */ + protected void sendUnregisterRequest() { + // unregistering from tracker + try { + writeLog("Unregistering from tracker", LogLevel.Info); + ProtocolP2PPacket p = createProtocolP2PPacket((Payload)new Unregister(server)); + p.sendRequest(getTrackerSocket()); + } catch (Exception e) { + writeLog("Cannot unregister from tracker", LogLevel.Error); + writeLog(e, LogLevel.Error); + } + } + +} diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 5cbe8af..8fa5428 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -34,6 +34,8 @@ import protocolP2P.HashRequest; import protocolP2P.HashResponse; import protocolP2P.Register; import protocolP2P.Unregister; +import serverP2P.ServerManagement; +import serverP2P.FileWatcherTCP; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for TCP. @@ -42,17 +44,9 @@ import protocolP2P.Unregister; * @author JS Auge * @version 1.0 */ -public class ServerManagementTCP implements Runnable { +public class ServerManagementTCP extends ServerManagement { - private String[] fileList; - private Map sha512 = new HashMap<>(); - private String baseDirectory; private ServerSocket socket; - private Logger logger; - private HostItem tracker; - private HostItem server; - private FileListWatcher fileListWatcher; - private volatile boolean stop; /** Constructor for TCP implementation, with baseDirectory and TCPPort parameters. * @param baseDirectory the root directory where files are stored @@ -62,12 +56,11 @@ public class ServerManagementTCP implements Runnable { * @param tracker Tracker */ public ServerManagementTCP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { - stop = false; - server = new HostItem(hostName, port); - fileList = new String[0]; - this.tracker = tracker; - this.logger = logger; - this.baseDirectory = baseDirectory; + super(baseDirectory, new HostItem(hostName, port), tracker, logger); + assert baseDirectory != null : "baseDirectory is null"; + assert server != null : "server is null"; + assert tracker != null : "tracker is null"; + assert logger != null : "logger is null"; try { socket = new ServerSocket(server.getPort(), 10, server.getInetAddress()); } catch (SocketException e) { @@ -79,24 +72,12 @@ public class ServerManagementTCP implements Runnable { } } - /** Stop the thread */ - public void setStop() { - stop = true; - } - - /** Trigger a manual check of the file list - */ - public void updateFileList() { - if (fileListWatcher != null) { - fileListWatcher.trigger(); - } - } /** Implementation of runnable. This methods allows to run the server. */ public void run() { logger.writeTCP("Server sucessfully started", LogLevel.Info); - fileListWatcher = new FileListWatcher(10000); // checking every 10 seconds + fileListWatcher = (FileWatcher)new FileWatcherTCP(logger, 10000, server, tracker, baseDirectory); // checking every 10 seconds (new Thread(fileListWatcher)).start(); while(!stop) { try { @@ -108,15 +89,7 @@ public class ServerManagementTCP implements Runnable { } } fileListWatcher.setStop(); - // unregistering from tracker - try { - logger.writeTCP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server)); - p.sendRequest((Object)tracker.getTCPSocket()); - } catch (Exception e) { - logger.writeTCP("Cannot unregister from tracker", LogLevel.Error); - logger.writeTCP(e, LogLevel.Error); - } + sendUnregisterRequest(); } /** Private runnable class allowing to serve one client. @@ -193,240 +166,32 @@ public class ServerManagementTCP implements Runnable { } } - - /** Init sha512 map. + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - private void initSha512() { - for(String f: fileList) { - try { - MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); - sha512.put(f, md.digest(Files.readAllBytes(Paths.get(baseDirectory + f)))); - md.reset(); - } catch (NoSuchAlgorithmException e) { - logger.writeTCP("sha512 not supported", LogLevel.Error); - } catch (IOException e) { - logger.writeTCP("cannot read " + f, LogLevel.Warning); - } - } + protected void writeLog(String text, LogLevel logLevel) { + logger.writeTCP(text, logLevel); } - /** Send an internal error message. - * @param pd ProtocolP2PPacketTCP to respond - */ - private void sendInternalError(ProtocolP2PPacketTCP pd) { - logger.writeTCP("Internal Error", LogLevel.Warning); - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } - - /** Send a NotATracker error message. - * @param pd ProtocolP2PPacketTCP to respond + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - private void sendNotATracker(ProtocolP2PPacketTCP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_A_TRACKER))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } - - /** Send response to list request - * @param pd Request received - */ - private void sendListResponse(ProtocolP2PPacketTCP pd) { - try { - if (fileList.length == 0) { - logger.writeTCP("Sending EMPTY_DIRECTORY", LogLevel.Action); - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); - } else { - logger.writeTCP("Sending LIST_RESPONSE", LogLevel.Action); - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)(new FileList(fileList)))); - } - } catch (Exception e2) { - logger.writeTCP(e2, LogLevel.Error); - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeTCP(e, logLevel); } - /** Send hash response to hash request - * @param pd Request received + /** Create packets + * @param payload Payload */ - private void sendHashResponse(ProtocolP2PPacketTCP pd) { - Payload p = pd.getPayload(); - assert p instanceof HashRequest : "payload must be an instance of HashRequest"; - if (!(p instanceof HashRequest)) { - sendInternalError(pd); - } else { - String filename = ((HashRequest)p).getFilename(); - if (Arrays.binarySearch(fileList, filename) >= 0) { - Map hashes = new HashMap<>(); - for (HashAlgorithm h : ((HashRequest)p).getAlgoList()) { - switch (h) { - case SHA512: - hashes.put(h, sha512.get(filename)); - break; - case MD5: - default: - hashes.put(h, new byte[0]); - break; - } - } - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)(new HashResponse(filename, hashes)))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } else { - // file not found - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } - } + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload) payload); } - - /** Send response to load request - * @param pd Request received + /** Getter for tracker socket */ - private void sendLoadResponse(ProtocolP2PPacketTCP pd) { - Payload p = pd.getPayload(); - assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; - if (!(p instanceof LoadRequest)) { - sendInternalError(pd); - } else { - String filename = ((LoadRequest)p).getFilename(); - long offset = ((LoadRequest)p).getOffset(); - long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent(); - try { - byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename)); - long sizeToSend = 0; - if (fullLoad.length - offset < maxSizePartialContent) { - logger.writeTCP("Sending last partialContent", LogLevel.Debug); - sizeToSend = fullLoad.length - offset; - } else { - sizeToSend = maxSizePartialContent; - } - logger.writeTCP("maxSizePartialContent: " + maxSizePartialContent, LogLevel.Debug); - logger.writeTCP("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend), LogLevel.Debug); - byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend)); - if (Arrays.binarySearch(fileList, filename) >= 0) { - try { - if (load.length == 0) { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_FILE))); - } else { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); - } - } catch (Exception e2) { - logger.writeTCP(e2, LogLevel.Error); - } - } else { - logger.writeTCP("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename), LogLevel.Debug); - logger.writeTCP("File list:", LogLevel.Debug); - for (String f: fileList) { - logger.writeTCP("- " + f, LogLevel.Debug); - } - - throw new IOException(); // to send a NOT_FOUND in the catch block - } - } catch (IOException e) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e2) { - logger.writeTCP(e2, LogLevel.Debug); - } - } - } - } - - /** Private runnable class allowing to keep the tracker informed about file list. */ - private class FileListWatcher implements Runnable { - private volatile boolean stop; - private long time; - private boolean force; - - /** Register server on tracker - */ - private void registerTracker() { - try { - logger.writeTCP("Trying to into tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); - p.sendRequest((Object)tracker.tryGetTCPSocket()); - logger.writeTCP("Register request sent.", LogLevel.Debug); - tracker.closeTCPSocket(); - } catch (Exception e) { - // error, trying again at next iteration - force = true; - logger.writeTCP("Cannot contact tracker, trying again at next iteration (" + time + " milliseconds).", LogLevel.Error); - } - } - - /** Update fileList and returns true if different than old list. - * @return true if changed - */ - private boolean updateFileList() { - File folder = new File(baseDirectory); - Vector v = new Vector(); - File[] files = folder.listFiles(); - /* Add non-recursively files's names to fileList */ - for (File f : files) { - if (f.isFile()) { - v.add(f.getName()); - } - } - String[] newFileList = new String[v.size()]; - v.toArray(newFileList); - Arrays.sort(newFileList); - if (!Arrays.equals(newFileList, fileList)) { - fileList = newFileList; - initSha512(); - return true; - } else { - return false; - } - } - - /** Constructor with millis parameter - * @param millis interval of time between checks - */ - public FileListWatcher(long millis) { - this.stop = false; - this.time = millis; - } - - /** Ask the thread to stop - */ - public void setStop() { - stop = true; - } - - /** Allow a manual check - */ - public void trigger() { - if (updateFileList() || force) { - force = false; - logger.writeTCP("File list watcher detected changes. Informing tracker.", LogLevel.Info); - registerTracker(); - } - } - - /** Runnable implementation */ - public void run() { - logger.writeTCP("File list watcher started : delay " + time + " milliseconds.", LogLevel.Info); - while(!stop) { - trigger(); - try { - Thread.sleep(time); - } catch(InterruptedException e) { - logger.writeTCP("File list watcher interrupted", LogLevel.Error); - setStop(); - } - } - } + protected Object getTrackerSocket() { + return (Object)tracker.getTCPSocket(); } - } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 25a988a..7affa75 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -34,6 +34,7 @@ import tools.HostItem; import protocolP2P.Register; import protocolP2P.Unregister; import java.net.UnknownHostException; +import serverP2P.ServerManagement; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. * @author Louis Royer @@ -41,17 +42,9 @@ import java.net.UnknownHostException; * @author JS Auge * @version 1.0 */ -public class ServerManagementUDP implements Runnable { +public class ServerManagementUDP extends ServerManagement { - private String[] fileList = new String[0]; - private Map sha512 = new HashMap<>(); - private String baseDirectory; private DatagramSocket socket; - private Logger logger; - private HostItem tracker; - private HostItem server; - private FileListWatcher fileListWatcher; - private volatile boolean stop; /** Constructor for UDP implementation, with baseDirectory and UDPPort parameters. * @param baseDirectory the root directory where files are stored @@ -61,11 +54,11 @@ public class ServerManagementUDP implements Runnable { * @param tracker Tracker */ public ServerManagementUDP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { - stop = false; - server = new HostItem(hostName, port); - this.logger = logger; - this.baseDirectory = baseDirectory; - this.tracker = tracker; + super(baseDirectory, new HostItem(hostName, port), tracker, logger); + assert baseDirectory != null : "baseDirectory is null"; + assert server != null : "server is null"; + assert tracker != null : "tracker is null"; + assert logger != null : "logger is null"; try { socket = new DatagramSocket(server.getPort(), server.getInetAddress()); } catch (SocketException e) { @@ -74,24 +67,12 @@ public class ServerManagementUDP implements Runnable { } } - /** Stop the thread */ - public void setStop() { - stop = true; - } - - /** Trigger a manual check of the file list - */ - public void updateFileList() { - if (fileListWatcher != null) { - fileListWatcher.trigger(); - } - } /** Implementation of runnable. This methods allows to run the server. */ public void run() { logger.writeUDP("Server sucessfully started", LogLevel.Info); - fileListWatcher = new FileListWatcher(10000); // checking every 10 seconds + fileListWatcher = (FileWatcher)new FileWatcherUDP(logger, 10000, server, tracker, baseDirectory); // checking every 10 seconds (new Thread(fileListWatcher)).start(); while(!stop) { try { @@ -99,10 +80,11 @@ public class ServerManagementUDP implements Runnable { Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: - loadRequestManagement(pd); + sendLoadResponse(pd); break; case LIST_REQUEST: - listRequestManagement(pd); + logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); + sendListResponse(pd); break; case HASH_REQUEST: logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); @@ -127,249 +109,36 @@ public class ServerManagementUDP implements Runnable { } } fileListWatcher.setStop(); - // unregistering from tracker - try { - logger.writeUDP("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(server)); - p.sendRequest((Object)tracker.getUDPSocket()); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } - - /** Init sha512 map. - */ - private void initSha512() { - for(String f: fileList) { - try { - MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); - sha512.put(f, md.digest(Files.readAllBytes(Paths.get(baseDirectory + f)))); - md.reset(); - } catch (NoSuchAlgorithmException e) { - logger.writeUDP("sha512 not supported", LogLevel.Error); - } catch (IOException e) { - logger.writeUDP("cannot read " + f, LogLevel.Warning); - } - } + sendUnregisterRequest(); } - /** Send an internal error message. - * @param pd ProtocolP2PPacketUDP to respond - */ - private void sendInternalError(ProtocolP2PPacketUDP pd) { - logger.writeUDP("Internal Error", LogLevel.Warning); - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } - /** Respond to LOAD requests - * @param pd ProtocolP2PPacketUDP + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - public void loadRequestManagement(ProtocolP2PPacketUDP pd){ - Payload p = pd.getPayload(); - logger.writeUDP("Received LOAD_REQUEST", LogLevel.Action); - assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; - if (!(p instanceof LoadRequest)) { - sendInternalError(pd); - } else { - String filename = ((LoadRequest)p).getFilename(); - long offset = ((LoadRequest)p).getOffset(); - long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent(); - try { - byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename)); - long sizeToSend = 0; - if (fullLoad.length - offset < maxSizePartialContent) { - logger.writeUDP("Sending last partialContent", LogLevel.Debug); - sizeToSend = fullLoad.length - offset; - } else { - sizeToSend = maxSizePartialContent; - } - logger.writeUDP("maxSizePartialContent: " + maxSizePartialContent, LogLevel.Debug); - logger.writeUDP("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend), LogLevel.Debug); - byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend)); - if (Arrays.binarySearch(fileList, filename) >= 0) { - try { - if (load.length == 0) { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_FILE))); - } else { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); - } - } catch (Exception e2) { - logger.writeUDP(e2, LogLevel.Error); - } - } else { - logger.writeUDP("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename), LogLevel.Debug); - logger.writeUDP("File list:", LogLevel.Debug); - for (String f: fileList) { - logger.writeUDP("- " + f, LogLevel.Debug); - } - - throw new IOException(); // to send a NOT_FOUND in the catch block - } - } catch (IOException e) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e2) { - logger.writeUDP(e2, LogLevel.Error); - } - } - } + protected void writeLog(String text, LogLevel logLevel) { + logger.writeUDP(text, logLevel); } - /** Respond to LIST requests - * @param pd ProtocolP2PPacketUDP + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - public void listRequestManagement(ProtocolP2PPacketUDP pd) { - logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); - try { - if (fileList.length == 0) { - logger.writeUDP("Sending EMPTY_DIRECTORY to host " + pd.getHostItem(), LogLevel.Action); - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); - } else { - logger.writeUDP("Sending LIST_RESPONSE to host " + pd.getHostItem(), LogLevel.Action); - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FileList(fileList)))); - } - } catch (Exception e2) { - logger.writeUDP(e2, LogLevel.Error); - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeUDP(e, logLevel); } - /** Send a NotATracker error message. - * @param pd ProtocolP2PPacketUDP to respond + /** Create packets + * @param payload Payload */ - private void sendNotATracker(ProtocolP2PPacketUDP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_A_TRACKER))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload) payload); } - /** Send hash response to hash request - * @param pd Request received + /** Getter for tracker socket */ - private void sendHashResponse(ProtocolP2PPacketUDP pd) { - Payload p = pd.getPayload(); - assert p instanceof HashRequest : "payload must be an instance of HashRequest"; - if (!(p instanceof HashRequest)) { - sendInternalError(pd); - } else { - String filename = ((HashRequest)p).getFilename(); - if (Arrays.binarySearch(fileList, filename) >= 0) { - Map hashes = new HashMap<>(); - for (HashAlgorithm h : ((HashRequest)p).getAlgoList()) { - switch (h) { - case SHA512: - hashes.put(h, sha512.get(filename)); - break; - case MD5: - default: - hashes.put(h, new byte[0]); - break; - } - } - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new HashResponse(filename, hashes)))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } else { - // file not found - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } - } - } - - /** Private runnable class allowing to keep the tracker informed about file list. */ - private class FileListWatcher implements Runnable { - private volatile boolean stop; - private long time; - private boolean force; - - /** Register server on tracker - */ - private void registerTracker() { - try { - logger.writeUDP("Trying to register into tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(server)); - p.sendRequest((Object)tracker.getUDPSocket()); - logger.writeUDP("Register request sent (but cannot ensure reception).", LogLevel.Debug); - tracker.closeUDPSocket(); - } catch (Exception e) { - force = true; - logger.writeUDP("Cannot contact tracker, trying again at next iteration (" + time + " milliseconds).", LogLevel.Error); - } - } - - /** Update fileList and returns true if different than old list. - * @return true if changed - */ - private boolean updateFileList() { - File folder = new File(baseDirectory); - Vector v = new Vector(); - File[] files = folder.listFiles(); - /* Add non-recursively files's names to fileList */ - for (File f : files) { - if (f.isFile()) { - v.add(f.getName()); - } - } - String[] newFileList = new String[v.size()]; - v.toArray(newFileList); - Arrays.sort(newFileList); - if (!Arrays.equals(newFileList, fileList)) { - fileList = newFileList; - initSha512(); - return true; - } else { - return false; - } - } - - /** Constructor with millis parameter - * @param millis interval of time between checks - */ - public FileListWatcher(long millis) { - this.force = true; - this.stop = false; - this.time = millis; - } - - /** Ask the thread to stop - */ - public void setStop() { - stop = true; - } - - /** Allow a manual check - */ - public void trigger() { - if (updateFileList() || force) { - force = false; - logger.writeUDP("File list watcher detected changes. Informing tracker.", LogLevel.Info); - registerTracker(); - } - } - - /** Runnable implementation */ - public void run() { - logger.writeUDP("File list watcher started : delay " + time + " milliseconds.", LogLevel.Info); - while(!stop) { - trigger(); - try { - Thread.sleep(time); - } catch(InterruptedException e) { - logger.writeUDP("File list watcher interrupted", LogLevel.Error); - setStop(); - } - } - } + protected Object getTrackerSocket() { + return (Object)tracker.getUDPSocket(); } } From d1d79938646a86f1f408bf02f8495212fc3a7f3e Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 22 Mar 2020 13:44:08 +0100 Subject: [PATCH 24/40] Use generics --- src/clientP2P/ClientDownloadPartTCP.java | 8 +++--- src/clientP2P/ClientDownloadPartUDP.java | 8 +++--- src/clientP2P/ClientDownloadTCP.java | 4 +-- src/clientP2P/ClientDownloadUDP.java | 4 +-- src/clientP2P/ClientManagementTCP.java | 4 +-- src/clientP2P/ClientManagementUDP.java | 4 +-- src/protocolP2P/HashResponse.java | 4 +-- src/protocolP2P/LoadRequest.java | 6 ++--- src/protocolP2P/ProtocolP2PPacket.java | 10 +++---- src/protocolP2P/ProtocolP2PPacketTCP.java | 32 +++++++++++------------ src/protocolP2P/ProtocolP2PPacketUDP.java | 32 +++++++++++------------ src/serverP2P/FileWatcherTCP.java | 2 +- src/serverP2P/FileWatcherUDP.java | 2 +- src/serverP2P/ServerManagement.java | 15 +++++------ src/serverP2P/ServerManagementTCP.java | 6 ++--- src/serverP2P/ServerManagementUDP.java | 6 ++--- src/tracker/TrackerManagementTCP.java | 26 +++++++++--------- src/tracker/TrackerManagementUDP.java | 28 ++++++++++---------- 18 files changed, 100 insertions(+), 101 deletions(-) diff --git a/src/clientP2P/ClientDownloadPartTCP.java b/src/clientP2P/ClientDownloadPartTCP.java index e4db082..b2872e9 100644 --- a/src/clientP2P/ClientDownloadPartTCP.java +++ b/src/clientP2P/ClientDownloadPartTCP.java @@ -172,7 +172,7 @@ public class ClientDownloadPartTCP implements Runnable { if (!stop) { try { Long offset = toDoTasks.get(0); - ProtocolP2PPacketTCP p = reqPart(offset); + ProtocolP2PPacketTCP p = reqPart(offset); if (p == null) { stop = true; } @@ -197,7 +197,7 @@ public class ClientDownloadPartTCP implements Runnable { * @param offset Offset of the file part to download * @return ProtocolP2PPacketTCP used to send request */ - private ProtocolP2PPacketTCP reqPart(Long offset) { + private ProtocolP2PPacketTCP reqPart(Long offset) { System.err.println("New request: " + offset); logger.writeTCP("New request: " + offset, LogLevel.Info); // maintain tracking of tasks @@ -225,7 +225,7 @@ public class ClientDownloadPartTCP implements Runnable { } // send request try { - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, offset.longValue(), MAX_PARTIAL_SIZE)); + ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new LoadRequest(filename, offset.longValue(), MAX_PARTIAL_SIZE)); d.sendRequest((Object)socket); return d; } catch (InternalError e) { @@ -248,7 +248,7 @@ public class ClientDownloadPartTCP implements Runnable { * @param d request packet * @return true on failure, else false */ - public boolean downloadPart(ProtocolP2PPacketTCP d) { + public boolean downloadPart(ProtocolP2PPacketTCP d) { if (d == null) { System.err.println("Error: downloadPart -> d is null."); logger.writeTCP("downloadPart -> d is null.", LogLevel.Error); diff --git a/src/clientP2P/ClientDownloadPartUDP.java b/src/clientP2P/ClientDownloadPartUDP.java index 84ef0f8..2a2e4a7 100644 --- a/src/clientP2P/ClientDownloadPartUDP.java +++ b/src/clientP2P/ClientDownloadPartUDP.java @@ -166,7 +166,7 @@ public class ClientDownloadPartUDP implements Runnable { if (!stop) { try { Long offset = toDoTasks.get(0); - ProtocolP2PPacketUDP p = reqPart(offset); + ProtocolP2PPacketUDP p = reqPart(offset); if (p == null) { stop = true; } @@ -190,7 +190,7 @@ public class ClientDownloadPartUDP implements Runnable { * @param offset Offset of the file part to download * @return ProtocolP2PPacketTCP used to send request */ - private ProtocolP2PPacketUDP reqPart(Long offset) { + private ProtocolP2PPacketUDP reqPart(Long offset) { System.err.println("New request: "+ offset); logger.writeUDP("New request: "+ offset, LogLevel.Info); // maintain tracking of tasks @@ -218,7 +218,7 @@ public class ClientDownloadPartUDP implements Runnable { } // send request try { - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, offset.longValue(), MAX_PARTIAL_SIZE)); + ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new LoadRequest(filename, offset.longValue(), MAX_PARTIAL_SIZE)); d.sendRequest((Object)socket); return d; } catch (InternalError e) { @@ -237,7 +237,7 @@ public class ClientDownloadPartUDP implements Runnable { * @param d request packet * @return true on failure, else false */ - public boolean downloadPart(ProtocolP2PPacketUDP d) { + public boolean downloadPart(ProtocolP2PPacketUDP d) { if (d == null) { System.err.println("Error: downloadPart -> d is null."); logger.writeUDP("downloadPart -> d is null.", LogLevel.Error); diff --git a/src/clientP2P/ClientDownloadTCP.java b/src/clientP2P/ClientDownloadTCP.java index bb8e932..3bc8981 100644 --- a/src/clientP2P/ClientDownloadTCP.java +++ b/src/clientP2P/ClientDownloadTCP.java @@ -197,7 +197,7 @@ public class ClientDownloadTCP implements Runnable { byte[] hash; HashAlgorithm[] hashesAlgo = new HashAlgorithm[1]; hashesAlgo[0] = HashAlgorithm.SHA512; - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new HashRequest(filename, hashesAlgo)); + ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new HashRequest(filename, hashesAlgo)); try { d.sendRequest((Object)hostItem.getTCPSocket()); try { @@ -319,7 +319,7 @@ public class ClientDownloadTCP implements Runnable { * @throws InternalError */ private void setSize() throws InternalError { - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); + ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); try { d.sendRequest((Object)hostList.get(0).getTCPSocket()); try { diff --git a/src/clientP2P/ClientDownloadUDP.java b/src/clientP2P/ClientDownloadUDP.java index 932019b..9fa14d2 100644 --- a/src/clientP2P/ClientDownloadUDP.java +++ b/src/clientP2P/ClientDownloadUDP.java @@ -197,7 +197,7 @@ public class ClientDownloadUDP implements Runnable { byte[] hash; HashAlgorithm[] hashesAlgo = new HashAlgorithm[1]; hashesAlgo[0] = HashAlgorithm.SHA512; - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new HashRequest(filename, hashesAlgo)); + ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new HashRequest(filename, hashesAlgo)); try { d.sendRequest((Object)hostItem.getUDPSocket()); try { @@ -315,7 +315,7 @@ public class ClientDownloadUDP implements Runnable { * @throws InternalError */ private void setSize() throws InternalError { - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); + ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); try { d.sendRequest((Object)hostList.get(0).getUDPSocket()); try { diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index b52899c..b5263ec 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -174,7 +174,7 @@ public class ClientManagementTCP implements Runnable { * @throws VersionRemoteError */ private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); + ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.LIST_REQUEST)); try { d.sendRequest((Object)hostList.get(0).getTCPSocket()); Payload p = d.receiveResponse().getPayload(); @@ -220,7 +220,7 @@ public class ClientManagementTCP implements Runnable { * @throws InternalError */ private void initHostList() throws ProtocolError, InternalError { - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new DiscoverRequest(null)); + ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new DiscoverRequest(null)); try { d.sendRequest((Object)tracker.getTCPSocket()); Payload p = d.receiveResponse().getPayload(); diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index b298fc7..1f20484 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -189,7 +189,7 @@ public class ClientManagementUDP implements Runnable { * @throws VersionRemoteError */ private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); + ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.LIST_REQUEST)); d.sendRequest((Object)hostList.get(0).getUDPSocket()); try { Payload p = d.receiveResponse().getPayload(); @@ -234,7 +234,7 @@ public class ClientManagementUDP implements Runnable { * @throws InternalError */ private void initHostList() throws ProtocolError, InternalError { - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new DiscoverRequest(null)); + ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new DiscoverRequest(null)); try { d.sendRequest((Object)tracker.getUDPSocket()); Payload p = d.receiveResponse().getPayload(); diff --git a/src/protocolP2P/HashResponse.java b/src/protocolP2P/HashResponse.java index 52df91e..743b13e 100644 --- a/src/protocolP2P/HashResponse.java +++ b/src/protocolP2P/HashResponse.java @@ -111,14 +111,14 @@ public class HashResponse extends Payload { int bCount = FILENAME_POSITION + filename.length(); for(HashAlgorithm h : hashes.keySet()) { String s = h.getName(); - BytesArrayTools.write(packet, bCount, (int)s.length()); + BytesArrayTools.write(packet, bCount, s.length()); bCount += 4; // write algoname BytesArrayTools.write(packet, s, bCount); bCount += s.length(); // write hash size byte[] hashb = hashes.get(HashAlgorithm.fromName(s)); - BytesArrayTools.write(packet, bCount, (int)hashb.length); + BytesArrayTools.write(packet, bCount, hashb.length); bCount += 4; if (hashb.length != 0) { // write hash diff --git a/src/protocolP2P/LoadRequest.java b/src/protocolP2P/LoadRequest.java index 1fa0aeb..86f0b75 100644 --- a/src/protocolP2P/LoadRequest.java +++ b/src/protocolP2P/LoadRequest.java @@ -82,11 +82,11 @@ public class LoadRequest extends Payload { // set Payload size setPayloadSize(size - OFFSET_POSITION, packet); // Write offset - BytesArrayTools.write(packet, OFFSET_POSITION, (long)offset); + BytesArrayTools.write(packet, OFFSET_POSITION, offset); // Write maxSizePartialContent - BytesArrayTools.write(packet, MAX_SIZE_PARTIAL_CONTENT_POSITION, (long)maxSizePartialContent); + BytesArrayTools.write(packet, MAX_SIZE_PARTIAL_CONTENT_POSITION, maxSizePartialContent); // Write filenameSize - BytesArrayTools.write(packet, FILENAME_SIZE_POSITION, (int)filenameSize); + BytesArrayTools.write(packet, FILENAME_SIZE_POSITION, filenameSize); // Write filename BytesArrayTools.write(packet, filename, FILENAME_POSITION); return packet; diff --git a/src/protocolP2P/ProtocolP2PPacket.java b/src/protocolP2P/ProtocolP2PPacket.java index c0312c4..db9c4b4 100644 --- a/src/protocolP2P/ProtocolP2PPacket.java +++ b/src/protocolP2P/ProtocolP2PPacket.java @@ -21,7 +21,7 @@ import tools.HostItem; * @author JS Auge * @version 1.0 */ -public abstract class ProtocolP2PPacket { +public abstract class ProtocolP2PPacket < T extends Payload>{ private final static byte PROTOCOL_VERSION = 0x12; protected final static int VERSION_POSITION = 0; protected byte version; @@ -30,9 +30,9 @@ public abstract class ProtocolP2PPacket { /** Constructor with payload parameter (typically used when sending Packet). * @param payload the payload associated with the Packet to send */ - public ProtocolP2PPacket(Payload payload) { + public ProtocolP2PPacket (T payload) { version = PROTOCOL_VERSION; - this.payload = payload; + this.payload = (Payload)payload; } /** Send a request @@ -49,7 +49,7 @@ public abstract class ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public abstract void sendResponse(T response) throws InternalError, IOException, SocketClosed; + public abstract > void sendResponse(U response) throws InternalError, IOException, SocketClosed; /** Get hostItem of the sender * @return hostItem of the sender @@ -73,7 +73,7 @@ public abstract class ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed; + public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed; /** Receive a request, subclasses must overwrite this constructor. * @param socket socket used to get the request diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index b99e83f..708ee38 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -28,7 +28,7 @@ import java.net.Socket; * @author JS Auge * @version 1.0 */ -public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { +public class ProtocolP2PPacketTCP < T extends Payload > extends ProtocolP2PPacket < T > { private Socket responseSocket; // socket used to recept request and send response private Socket requestSocket; // socket used to send request and to reception response @@ -36,7 +36,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { /** Constructor with payload parameter (typically used when sending packet). * @param payload the payload associated with the packet to send */ - public ProtocolP2PPacketTCP(Payload payload) { + public ProtocolP2PPacketTCP(T payload) { super(payload); } @@ -147,19 +147,19 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { break; } } catch (TransmissionError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss); throw e; } catch (ProtocolError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(ss); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(ss); throw e; } catch (VersionError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.VERSION_ERROR))).send(ss); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.VERSION_ERROR))).send(ss); throw e; } catch (InternalError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss); throw e; } catch (SizeError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss); throw e; } if (protocolError) { @@ -173,10 +173,10 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException, SocketClosed { + public > void sendResponse(U response) throws InternalError, IOException, SocketClosed { assert response instanceof ProtocolP2PPacketTCP: "Wrong Packet type"; if (response instanceof ProtocolP2PPacketTCP) { - ProtocolP2PPacketTCP r = (ProtocolP2PPacketTCP) response; + ProtocolP2PPacketTCP r = (ProtocolP2PPacketTCP) response; assert responseSocket != null : "Cannot send response to a packet not received"; if (responseSocket == null) { throw new InternalError(); @@ -204,7 +204,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { * @throws IOException * @throws SocketClosed */ - public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed { + public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed { assert requestSocket != null : "Cannot receive response because request packet not sent."; if (requestSocket == null) { throw new InternalError(); @@ -227,7 +227,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { } // contruction try { - ProtocolP2PPacketTCP p = new ProtocolP2PPacketTCP(packet); + ProtocolP2PPacketTCP p = new ProtocolP2PPacketTCP<>(packet); Payload payload = p.getPayload(); switch (payload.getRequestResponseCode()) { case PROTOCOL_ERROR : @@ -248,19 +248,19 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket { return (ProtocolP2PPacket)p; } } catch (TransmissionError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); throw e; } catch (ProtocolError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(requestSocket); throw e; } catch (VersionError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.VERSION_ERROR))).send(requestSocket); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.VERSION_ERROR))).send(requestSocket); throw e; } catch (InternalError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); throw e; } catch (SizeError e) { - (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); throw e; } } diff --git a/src/protocolP2P/ProtocolP2PPacketUDP.java b/src/protocolP2P/ProtocolP2PPacketUDP.java index 03ffd64..a54733b 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -30,7 +30,7 @@ import java.io.IOException; * @author JS Auge * @version 1.0 */ -public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { +public class ProtocolP2PPacketUDP < T extends Payload> extends ProtocolP2PPacket < T > { private final static int CHECKSUM_POSITION = 2; private HostItem remoteHost; @@ -41,7 +41,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { /** Constructor with payload parameter (typically used when sending packet). * @param payload the payload associated with the packet to send */ - public ProtocolP2PPacketUDP(Payload payload) { + public ProtocolP2PPacketUDP(T payload) { super(payload); } @@ -140,19 +140,19 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { break; } } catch (TransmissionError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress); throw e; } catch (ProtocolError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(ss, responseSocketAddress); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(ss, responseSocketAddress); throw e; } catch (VersionError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.VERSION_ERROR))).send(ss, responseSocketAddress); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.VERSION_ERROR))).send(ss, responseSocketAddress); throw e; } catch (InternalError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress); throw e; } catch (SizeError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress); throw e; } if (protocolError) { @@ -165,10 +165,10 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @throws InternalError * @throws IOException */ - public void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException { + public >void sendResponse(U response) throws InternalError, IOException { assert response instanceof ProtocolP2PPacketUDP: "Wrong Packet type"; if (response instanceof ProtocolP2PPacketUDP) { - ProtocolP2PPacketUDP r = (ProtocolP2PPacketUDP) response; + ProtocolP2PPacketUDP r = (ProtocolP2PPacketUDP) response; assert responseSocket != null : "Cannot send response to a packet not received"; if (responseSocket == null) { throw new InternalError(); @@ -199,7 +199,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { * @throws SizeError * @throws IOException */ - public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException { + public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException { assert requestSocket != null : "Cannot receive response because request packet not sent."; if (requestSocket == null) { throw new InternalError(); @@ -211,7 +211,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { // contruction try { - ProtocolP2PPacketUDP p = new ProtocolP2PPacketUDP(packet); + ProtocolP2PPacketUDP p = new ProtocolP2PPacketUDP<>(packet); Payload payload = p.getPayload(); switch (payload.getRequestResponseCode()) { case PROTOCOL_ERROR : @@ -232,19 +232,19 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket { return (ProtocolP2PPacket)p; } } catch (TransmissionError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); throw e; } catch (ProtocolError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(requestSocket); throw e; } catch (VersionError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.VERSION_ERROR))).send(requestSocket); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.VERSION_ERROR))).send(requestSocket); throw e; } catch (InternalError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); throw e; } catch (SizeError e) { - (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); + (new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket); throw e; } } diff --git a/src/serverP2P/FileWatcherTCP.java b/src/serverP2P/FileWatcherTCP.java index 9f3936c..7aa9df7 100644 --- a/src/serverP2P/FileWatcherTCP.java +++ b/src/serverP2P/FileWatcherTCP.java @@ -51,7 +51,7 @@ public class FileWatcherTCP extends FileWatcher { protected void registerTracker() { try { writeLog("Trying to into tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server)); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Register(server)); p.sendRequest((Object)tracker.tryGetTCPSocket()); writeLog("Register request sent.", LogLevel.Debug); tracker.closeTCPSocket(); diff --git a/src/serverP2P/FileWatcherUDP.java b/src/serverP2P/FileWatcherUDP.java index 9cc1021..194039e 100644 --- a/src/serverP2P/FileWatcherUDP.java +++ b/src/serverP2P/FileWatcherUDP.java @@ -51,7 +51,7 @@ public class FileWatcherUDP extends FileWatcher { protected void registerTracker() { try { writeLog("Trying to register into tracker", LogLevel.Info); - ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(server)); + ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Register(server)); p.sendRequest((Object)tracker.getUDPSocket()); writeLog("Register request sent (but cannot ensure reception).", LogLevel.Debug); tracker.closeUDPSocket(); diff --git a/src/serverP2P/ServerManagement.java b/src/serverP2P/ServerManagement.java index 3962b5f..39f79d4 100644 --- a/src/serverP2P/ServerManagement.java +++ b/src/serverP2P/ServerManagement.java @@ -76,12 +76,12 @@ public abstract class ServerManagement implements Runnable { /** Create packets * @param payload Payload */ - protected abstract < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload); + protected abstract < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload); /** Send response to list request * @param pd Request received */ - protected < T extends ProtocolP2PPacket > void sendListResponse(T pd) { + protected < T extends ProtocolP2PPacket > void sendListResponse(T pd) { try { String[] fileList = fileListWatcher.getFileList(); if (fileList.length == 0) { @@ -99,7 +99,7 @@ public abstract class ServerManagement implements Runnable { /** Send a NotATracker error message. * @param pd Request received */ - protected < T extends ProtocolP2PPacket > void sendNotATracker(T pd) { + protected < T extends ProtocolP2PPacket > void sendNotATracker(T pd) { try { pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_A_TRACKER))); } catch (Exception e) { @@ -110,7 +110,7 @@ public abstract class ServerManagement implements Runnable { /** Send an internal error message. * @param pd Request received */ - protected < T extends ProtocolP2PPacket > void sendInternalError(T pd) { + protected < T extends ProtocolP2PPacket > void sendInternalError(T pd) { writeLog("Internal Error", LogLevel.Warning); try { pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.INTERNAL_ERROR))); @@ -122,7 +122,7 @@ public abstract class ServerManagement implements Runnable { /** Send hash response to hash request * @param pd Request received */ - protected < T extends ProtocolP2PPacket > void sendHashResponse(T pd) { + protected < T extends ProtocolP2PPacket > void sendHashResponse(T pd) { Payload p = pd.getPayload(); assert p instanceof HashRequest : "payload must be an instance of HashRequest"; if (!(p instanceof HashRequest)) { @@ -161,7 +161,7 @@ public abstract class ServerManagement implements Runnable { /** Send response to load request * @param pd Request received */ - protected < T extends ProtocolP2PPacket > void sendLoadResponse(T pd) { + protected < T extends ProtocolP2PPacket > void sendLoadResponse(T pd) { Payload p = pd.getPayload(); assert p instanceof LoadRequest : "payload must be an instance of LoadRequest"; if (!(p instanceof LoadRequest)) { @@ -223,8 +223,7 @@ public abstract class ServerManagement implements Runnable { // unregistering from tracker try { writeLog("Unregistering from tracker", LogLevel.Info); - ProtocolP2PPacket p = createProtocolP2PPacket((Payload)new Unregister(server)); - p.sendRequest(getTrackerSocket()); + createProtocolP2PPacket(new Unregister(server)).sendRequest(getTrackerSocket()); } catch (Exception e) { writeLog("Cannot unregister from tracker", LogLevel.Error); writeLog(e, LogLevel.Error); diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 8fa5428..e829fd8 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -121,7 +121,7 @@ public class ServerManagementTCP extends ServerManagement { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)addr.getTCPSocket()); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP<>((Object)addr.getTCPSocket()); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -185,8 +185,8 @@ public class ServerManagementTCP extends ServerManagement { /** Create packets * @param payload Payload */ - protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { - return (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload) payload); + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketTCP(payload); } /** Getter for tracker socket diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index 7affa75..a3cd1fc 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -76,7 +76,7 @@ public class ServerManagementUDP extends ServerManagement { (new Thread(fileListWatcher)).start(); while(!stop) { try { - ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); + ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP<>((Object)socket); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -132,8 +132,8 @@ public class ServerManagementUDP extends ServerManagement { /** Create packets * @param payload Payload */ - protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { - return (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload) payload); + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketUDP(payload); } /** Getter for tracker socket diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index c26c9c9..b7d9249 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -104,7 +104,7 @@ public class TrackerManagementTCP implements Runnable { */ private boolean handleRequest() { try { - ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)addr.getTCPSocket()); + ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP<>((Object)addr.getTCPSocket()); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -150,9 +150,9 @@ public class TrackerManagementTCP implements Runnable { /** Send a not found message. * @param pd ProtocolP2PPacketTCP to respond */ - private void sendNotFound(ProtocolP2PPacketTCP pd) { + private void sendNotFound(ProtocolP2PPacketTCP pd) { try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_FOUND))); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.NOT_FOUND))); } catch (Exception e) { logger.writeTCP(e, LogLevel.Error); } @@ -161,9 +161,9 @@ public class TrackerManagementTCP implements Runnable { /** Send an empty directory message. * @param pd ProtocolP2PPacketTCP to respond */ - private void sendEmptyDirectory(ProtocolP2PPacketTCP pd) { + private void sendEmptyDirectory(ProtocolP2PPacketTCP pd) { try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); } catch (Exception e) { logger.writeTCP(e, LogLevel.Error); } @@ -172,10 +172,10 @@ public class TrackerManagementTCP implements Runnable { /** Send an internal error message. * @param pd ProtocolP2PPacketTCP to respond */ - private void sendInternalError(ProtocolP2PPacketTCP pd) { + private void sendInternalError(ProtocolP2PPacketTCP pd) { logger.writeTCP("Internal Error", LogLevel.Warning); try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.INTERNAL_ERROR))); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.INTERNAL_ERROR))); } catch (Exception e) { logger.writeTCP(e, LogLevel.Error); } @@ -185,7 +185,7 @@ public class TrackerManagementTCP implements Runnable { * @param pd ProtocolP2PPacketTCP to respond * @throws InternalError */ - private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { + private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { Payload p = pd.getPayload(); assert p instanceof Register : "payload must be an instance of Register"; if (!(p instanceof Register)) { @@ -198,7 +198,7 @@ public class TrackerManagementTCP implements Runnable { } // send a list request try { - ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); + ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getTCPSocket()); logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); @@ -220,7 +220,7 @@ public class TrackerManagementTCP implements Runnable { * @param pd ProtocolP2PPacketTCP to respond * @throws InternalError */ - private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { + private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { Payload p = pd.getPayload(); assert p instanceof Unregister : "payload must be an instance of Unregister"; if (!(p instanceof Unregister)) { @@ -242,7 +242,7 @@ public class TrackerManagementTCP implements Runnable { * @param pd ProtocolP2PPacketTCP to respond * @throws InternalError */ - private void handleDiscover(ProtocolP2PPacketTCP pd) throws InternalError { + private void handleDiscover(ProtocolP2PPacketTCP pd) throws InternalError { logger.writeTCP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; @@ -251,7 +251,7 @@ public class TrackerManagementTCP implements Runnable { } else { String filename = ((DiscoverRequest)p).getFilename(); try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + pd.sendResponse(new ProtocolP2PPacketTCP(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); } catch (Exception e) { logger.writeTCP(e, LogLevel.Error); } @@ -262,7 +262,7 @@ public class TrackerManagementTCP implements Runnable { * @param pd ProtocolP2PPacketTCP response * @throws InternalError */ - private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { + private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 42d6445..a99636a 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -59,7 +59,7 @@ public class TrackerManagementUDP implements Runnable { logger.writeUDP("Tracker successfully started", LogLevel.Info); while(true) { try { - ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket); + ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP<>((Object)socket); Payload p = pd.getPayload(); switch (p.getRequestResponseCode()) { case LOAD_REQUEST: @@ -101,9 +101,9 @@ public class TrackerManagementUDP implements Runnable { /** Send a not found message. * @param pd ProtocolP2PPacketUDP to respond */ - private void sendNotFound(ProtocolP2PPacketUDP pd) { + private void sendNotFound(ProtocolP2PPacketUDP pd) { try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND))); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.NOT_FOUND))); } catch (Exception e) { logger.writeUDP(e, LogLevel.Error); } @@ -112,9 +112,9 @@ public class TrackerManagementUDP implements Runnable { /** Send an empty directory message. * @param pd ProtocolP2PPacketUDP to respond */ - private void sendEmptyDirectory(ProtocolP2PPacketUDP pd) { + private void sendEmptyDirectory(ProtocolP2PPacketUDP pd) { try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); } catch (Exception e) { logger.writeUDP(e, LogLevel.Error); } @@ -123,10 +123,10 @@ public class TrackerManagementUDP implements Runnable { /** Send an internal error message. * @param pd ProtocolP2PPacketUDP to respond */ - private void sendInternalError(ProtocolP2PPacketUDP pd) { + private void sendInternalError(ProtocolP2PPacketUDP pd) { logger.writeUDP("Internal Error", LogLevel.Warning); try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))); + pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.INTERNAL_ERROR))); } catch (Exception e) { logger.writeUDP(e, LogLevel.Error); } @@ -136,7 +136,7 @@ public class TrackerManagementUDP implements Runnable { * @param pd ProtocolP2PPacketUDP to respond * @throws InternalError */ - private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { + private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { Payload p = pd.getPayload(); assert p instanceof Register : "payload must be an instance of Register"; if (!(p instanceof Register)) { @@ -150,10 +150,10 @@ public class TrackerManagementUDP implements Runnable { } // send a list request try { - ProtocolP2PPacket pLReq = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); + ProtocolP2PPacket pLReq = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); pLReq.sendRequest((Object)host.getUDPSocket()); logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); - ProtocolP2PPacket resp = pLReq.receiveResponse(); + ProtocolP2PPacket resp = pLReq.receiveResponse(); handleListResponse((ProtocolP2PPacketUDP)resp, host); logger.writeUDP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); host.closeUDPSocket(); @@ -173,7 +173,7 @@ public class TrackerManagementUDP implements Runnable { * @param pd ProtocolP2PPacketUDP to respond * @throws InternalError */ - private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { + private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { Payload p = pd.getPayload(); assert p instanceof Unregister : "payload must be an instance of Unregister"; if (!(p instanceof Unregister)) { @@ -195,7 +195,7 @@ public class TrackerManagementUDP implements Runnable { * @param pd ProtocolP2PPacketUDP to respond * @throws InternalError */ - private void handleDiscover(ProtocolP2PPacketUDP pd) throws InternalError { + private void handleDiscover(ProtocolP2PPacketUDP pd) throws InternalError { logger.writeUDP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); Payload p = pd.getPayload(); assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; @@ -204,7 +204,7 @@ public class TrackerManagementUDP implements Runnable { } else { String filename = ((DiscoverRequest)p).getFilename(); try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + pd.sendResponse(new ProtocolP2PPacketUDP(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); } catch (Exception e) { logger.writeUDP(e, LogLevel.Error); } @@ -215,7 +215,7 @@ public class TrackerManagementUDP implements Runnable { * @param pd ProtocolP2PPacketUDP response * @throws InternalError */ - private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { + private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { Payload p = pd.getPayload(); assert p instanceof FileList: "payload must be an instance of FileList"; if (!(p instanceof FileList)) { From 275eb165b1cebc67f780d4eb3ef123909b6cf3b3 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 22 Mar 2020 14:53:23 +0100 Subject: [PATCH 25/40] Refactoring tracker + server --- src/serverP2P/ServerManagement.java | 87 +++++----- src/serverP2P/ServerManagementTCP.java | 42 +---- src/serverP2P/ServerManagementUDP.java | 31 +--- src/tools/ServeErrors.java | 82 ++++++++++ src/tracker/TrackerManagement.java | 194 ++++++++++++++++++++++ src/tracker/TrackerManagementTCP.java | 215 +++++-------------------- src/tracker/TrackerManagementUDP.java | 194 ++++------------------ 7 files changed, 398 insertions(+), 447 deletions(-) create mode 100644 src/tools/ServeErrors.java create mode 100644 src/tracker/TrackerManagement.java diff --git a/src/serverP2P/ServerManagement.java b/src/serverP2P/ServerManagement.java index 39f79d4..de4fdd2 100644 --- a/src/serverP2P/ServerManagement.java +++ b/src/serverP2P/ServerManagement.java @@ -3,6 +3,7 @@ import serverP2P.FileWatcher; import tools.Logger; import tools.LogLevel; import tools.HostItem; +import tools.ServeErrors; import protocolP2P.ProtocolP2PPacket; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; @@ -19,6 +20,7 @@ import java.util.Arrays; import java.util.Map; import java.util.HashMap; import java.io.IOException; +import exception.LocalException; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol. * @author Louis Royer @@ -26,7 +28,7 @@ import java.io.IOException; * @author JS Auge * @version 1.0 */ -public abstract class ServerManagement implements Runnable { +public abstract class ServerManagement extends ServeErrors implements Runnable { protected volatile boolean stop; protected FileWatcher fileListWatcher; @@ -37,6 +39,7 @@ public abstract class ServerManagement implements Runnable { /** Constructor */ public ServerManagement(String baseDirectory, HostItem server, HostItem tracker, Logger logger) { + super(); assert baseDirectory != null : "baseDirectory is null"; assert server != null : "server is null"; assert tracker != null : "tracker is null"; @@ -61,23 +64,6 @@ public abstract class ServerManagement implements Runnable { } } - /** Implementation of writeLog - * @param text Text to log - * @param logLevel level of logging - */ - protected abstract void writeLog(String text, LogLevel logLevel); - - /** Implementation of writeLog - * @param e exception to log - * @param logLevel level of logging - */ - protected abstract void writeLog(Exception e, LogLevel logLevel); - - /** Create packets - * @param payload Payload - */ - protected abstract < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload); - /** Send response to list request * @param pd Request received */ @@ -86,7 +72,7 @@ public abstract class ServerManagement implements Runnable { String[] fileList = fileListWatcher.getFileList(); if (fileList.length == 0) { writeLog("Sending EMPTY_DIRECTORY to host " + pd.getHostItem(), LogLevel.Action); - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + sendEmptyDirectory(pd); } else { writeLog("Sending LIST_RESPONSE to host " + pd.getHostItem(), LogLevel.Action); pd.sendResponse(createProtocolP2PPacket((Payload)(new FileList(fileList)))); @@ -96,28 +82,7 @@ public abstract class ServerManagement implements Runnable { } } - /** Send a NotATracker error message. - * @param pd Request received - */ - protected < T extends ProtocolP2PPacket > void sendNotATracker(T pd) { - try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_A_TRACKER))); - } catch (Exception e) { - writeLog(e, LogLevel.Error); - } - } - /** Send an internal error message. - * @param pd Request received - */ - protected < T extends ProtocolP2PPacket > void sendInternalError(T pd) { - writeLog("Internal Error", LogLevel.Warning); - try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - writeLog(e, LogLevel.Error); - } - } /** Send hash response to hash request * @param pd Request received @@ -150,7 +115,7 @@ public abstract class ServerManagement implements Runnable { } else { // file not found try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + sendNotFound(pd); } catch (Exception e) { writeLog(e, LogLevel.Error); } @@ -186,7 +151,7 @@ public abstract class ServerManagement implements Runnable { if (Arrays.binarySearch(fileList, filename) >= 0) { try { if (load.length == 0) { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_FILE))); + sendEmptyFile(pd); } else { pd.sendResponse(createProtocolP2PPacket((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); } @@ -204,7 +169,7 @@ public abstract class ServerManagement implements Runnable { } } catch (IOException e) { try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + sendNotFound(pd); } catch (Exception e2) { writeLog(e2, LogLevel.Debug); } @@ -230,4 +195,40 @@ public abstract class ServerManagement implements Runnable { } } + /** Handle request. + * @throws LocalException + */ + protected < T extends ProtocolP2PPacket > void handleRequest(T pd) throws LocalException { + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + writeLog("Received LOAD_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendLoadResponse(pd); + break; + case LIST_REQUEST: + writeLog("Received LIST_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendListResponse(pd); + break; + case HASH_REQUEST: + writeLog("Received HASH_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendHashResponse(pd); + break; + case DISCOVER_REQUEST: + writeLog("Received DISCOVER_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendNotATracker(pd); + break; + case UNREGISTER: + writeLog("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Action); + sendNotATracker(pd); + break; + case REGISTER: + writeLog("Received REGISTER from host " + pd.getHostItem(), LogLevel.Action); + sendNotATracker(pd); + break; + default: + writeLog("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + } + } + } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index e829fd8..455cbd3 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -23,6 +23,7 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import exception.LocalException; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -110,7 +111,7 @@ public class ServerManagementTCP extends ServerManagement { boolean end = false; logger.writeTCP("[" + addr + "] New connection", LogLevel.Action); do { - end = handleRequest(); + end = handleClientRequest(); } while(!end); logger.writeTCP("[" + addr + "] End of connection", LogLevel.Action); } @@ -119,49 +120,16 @@ public class ServerManagementTCP extends ServerManagement { * @param s Socket used to read request and send response * @return true if cannot expect another request (ie, socket is closed) */ - private boolean handleRequest() { + private boolean handleClientRequest() { try { ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP<>((Object)addr.getTCPSocket()); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - logger.writeTCP(addr + "LOAD_REQUEST", LogLevel.Action); - sendLoadResponse(pd); - break; - case LIST_REQUEST: - logger.writeTCP(addr + "LIST_REQUEST", LogLevel.Action); - sendListResponse(pd); - break; - case HASH_REQUEST: - logger.writeTCP(addr + "HASH_REQUEST", LogLevel.Action); - sendHashResponse(pd); - break; - case DISCOVER_REQUEST: - logger.writeTCP(addr + "DISCOVER_REQUEST", LogLevel.Action); - sendNotATracker(pd); - break; - case UNREGISTER: - logger.writeTCP(addr + "UNREGISTER", LogLevel.Action); - sendNotATracker(pd); - break; - case REGISTER: - logger.writeTCP(addr + "REGISTER", LogLevel.Action); - sendNotATracker(pd); - break; - default: - logger.writeTCP(addr + "Received grabbage", LogLevel.Action); - sendInternalError(pd); - } + handleRequest(pd); } catch (IOException e) { return true; } catch (SocketClosed e) { return true; } - catch (TransmissionError e) {} - catch (ProtocolError e) {} - catch (VersionError e) {} - catch (InternalError e) {} - catch (SizeError e) {} + catch (LocalException e) {} return false; } } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index a3cd1fc..bba1a5b 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -22,6 +22,7 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import exception.LocalException; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -77,35 +78,9 @@ public class ServerManagementUDP extends ServerManagement { while(!stop) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP<>((Object)socket); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - sendLoadResponse(pd); - break; - case LIST_REQUEST: - logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); - sendListResponse(pd); - break; - case HASH_REQUEST: - logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); - sendHashResponse(pd); - break; - case DISCOVER_REQUEST: - case UNREGISTER: - case REGISTER: - logger.writeUDP("Received Tracker request", LogLevel.Action); - sendNotATracker(pd); - break; - default: - sendInternalError(pd); - } + handleRequest(pd); } catch (IOException e) { - } catch (SocketClosed e) { - } catch (TransmissionError e) { - } catch (ProtocolError e) { - } catch (VersionError e) { - } catch (InternalError e) { - } catch (SizeError e) { + } catch (LocalException e) { } } fileListWatcher.setStop(); diff --git a/src/tools/ServeErrors.java b/src/tools/ServeErrors.java new file mode 100644 index 0000000..ff083f9 --- /dev/null +++ b/src/tools/ServeErrors.java @@ -0,0 +1,82 @@ +package tools; +import tools.LogLevel; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.Payload; +import protocolP2P.RequestResponseCode; + +public abstract class ServeErrors { + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected abstract void writeLog(String text, LogLevel logLevel); + + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected abstract void writeLog(Exception e, LogLevel logLevel); + + /** Create packets + * @param payload Payload + */ + protected abstract < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload); + + /** Send a NotATracker error message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendNotATracker(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_A_TRACKER))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send an internal error message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendInternalError(T pd) { + writeLog("Internal Error", LogLevel.Warning); + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.INTERNAL_ERROR))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send a not found message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendNotFound(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send an empty directory message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendEmptyDirectory(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send an empty file message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendEmptyFile(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_FILE))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + +} diff --git a/src/tracker/TrackerManagement.java b/src/tracker/TrackerManagement.java new file mode 100644 index 0000000..e28790d --- /dev/null +++ b/src/tracker/TrackerManagement.java @@ -0,0 +1,194 @@ +package tracker; +import tools.ServeErrors; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.Payload; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; +import protocolP2P.FileList; +import protocolP2P.Unregister; +import protocolP2P.Register; +import protocolP2P.RequestResponseCode; +import localException.InternalError; +import remoteException.EmptyDirectory; +import exception.LocalException; + +public abstract class TrackerManagement extends ServeErrors implements Runnable { + protected HostItem tracker; + protected Logger logger; + protected List hostList = new ArrayList<>(); + protected Map> fileList = new HashMap<>(); + protected volatile boolean stop; + + /** Constructor + * @param tracker Tracker HostItem + * @param logger Logger + */ + public TrackerManagement(HostItem tracker, Logger logger) { + stop = false; + this.tracker = tracker; + this.logger = logger; + } + + /** Handle Discover request + * @param pd Received request + * @throws InternalError + */ + protected < T extends ProtocolP2PPacket > void handleDiscover(T pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; + if (!(p instanceof DiscoverRequest)) { + sendInternalError(pd); + } else { + String filename = ((DiscoverRequest)p).getFilename(); + try { + pd.sendResponse(createProtocolP2PPacket(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + } + + /** Handle List Responses + * @param pd Received response + * @throws InternalError + */ + protected > void handleListResponse(T pd, HostItem host) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + throw new InternalError(); + } else { + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } + } + } + } + + /** Handle Unregistering + * @param pd Request received + * @throws InternalError + */ + protected < T extends ProtocolP2PPacket > void handleUnregister(T pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Unregister : "payload must be an instance of Unregister"; + if (!(p instanceof Unregister)) { + sendInternalError(pd); + throw new InternalError(); + } + HostItem host = ((Unregister)p).getHostItem(); + writeLog("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); + hostList.remove(host); + for(String f: fileList.keySet()) { + fileList.get(f).remove(host); + if(fileList.get(f).isEmpty()) { + fileList.remove(f); + } + } + } + + /** Getter for HostItem socket + * @param hostItem HostItem + */ + protected abstract Object getHostItemSocket(HostItem hostItem); + + /** Close HostItem socket + * @param hostItem HostItem + */ + protected abstract void closeHostItemSocket(HostItem hostItem); + + /** Handle Registering + * @param pd Received request + * @throws InternalError + */ + protected < T extends ProtocolP2PPacket > void handleRegister(T pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Register : "payload must be an instance of Register"; + if (!(p instanceof Register)) { + throw new InternalError(); + } + // add host to known host list + HostItem host = ((Register)p).getHostItem(); + if (!hostList.contains(host)) { + hostList.add(host); + } + // send a list request + try { + ProtocolP2PPacket pLReq = createProtocolP2PPacket(new Payload(RequestResponseCode.LIST_REQUEST)); + pLReq.sendRequest(getHostItemSocket(host)); + writeLog("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse(pLReq.receiveResponse(), host); + writeLog("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); + closeHostItemSocket(host); + } catch (EmptyDirectory e) { + writeLog("Empty Directory", LogLevel.Debug); + hostList.remove(host); + writeLog("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); + } catch (Exception e) { + // remove from list because list request could not be send + hostList.remove(host); + writeLog("Aborting the add of host " + host, LogLevel.Action); + writeLog(e, LogLevel.Error); + } + } + + + /** Handle requests + * @throws LocalException + */ + protected > void handleRequest(T pd) throws LocalException { + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + writeLog("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case LIST_REQUEST: + writeLog("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); + sendEmptyDirectory(pd); + break; + case HASH_REQUEST: + writeLog("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case REGISTER: + writeLog("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); + handleRegister(pd); + break; + case UNREGISTER: + writeLog("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); + handleUnregister(pd); + break; + case DISCOVER_REQUEST: + writeLog("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); + handleDiscover(pd); + break; + default: + writeLog("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + break; + } + } + + /** Stop the thread */ + public void setStop() { + stop = true; + } + +} diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index b7d9249..bf659f3 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -25,6 +25,7 @@ import remoteException.EmptyDirectory; import java.net.UnknownHostException; import java.net.InetAddress; import localException.SocketClosed; +import tracker.TrackerManagement; /** Tracker management implementation with tcp @@ -33,21 +34,15 @@ import localException.SocketClosed; * @author JS Auge * @version 1.0 */ -public class TrackerManagementTCP implements Runnable { - - private HostItem tracker; - private Logger logger; +public class TrackerManagementTCP extends TrackerManagement { private ServerSocket socket; - private List hostList = new ArrayList<>(); - private Map> fileList = new HashMap<>(); /** Constructor with port and logger. * @param port Port used to listen. * @param logger Logger object */ public TrackerManagementTCP(int port, Logger logger) { - tracker = new HostItem("localhost", port); - this.logger = logger; + super(new HostItem("localhost", port), logger); try { socket = new ServerSocket(tracker.getPort(), 10, tracker.getInetAddress()); } catch (SocketException e) { @@ -63,7 +58,7 @@ public class TrackerManagementTCP implements Runnable { */ public void run() { logger.writeTCP("Tracker sucessfully started", LogLevel.Info); - do { + while (!stop) { try { Socket s = socket.accept(); ClientHandler c = new ClientHandler(s); @@ -71,7 +66,7 @@ public class TrackerManagementTCP implements Runnable { } catch (IOException e) { logger.writeTCP("Error while accepting new connection", LogLevel.Warning); } - } while(true); + } } @@ -93,7 +88,7 @@ public class TrackerManagementTCP implements Runnable { boolean end = false; logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); do { - end = handleRequest(); + end = handleClientRequest(); } while(!end); logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); } @@ -102,39 +97,10 @@ public class TrackerManagementTCP implements Runnable { * @param s Socket used to read request and send response * @return true if cannot expect another request (ie, socket is closed) */ - private boolean handleRequest() { + private boolean handleClientRequest() { try { ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP<>((Object)addr.getTCPSocket()); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - logger.writeTCP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case LIST_REQUEST: - logger.writeTCP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); - sendEmptyDirectory(pd); - break; - case HASH_REQUEST: - logger.writeTCP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case REGISTER: - logger.writeTCP("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleRegister(pd); - break; - case UNREGISTER: - logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleUnregister(pd); - break; - case DISCOVER_REQUEST: - handleDiscover(pd); - break; - default: - logger.writeTCP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); - sendInternalError(pd); - break; - } + handleRequest(pd); } catch (IOException e) { logger.writeTCP(e, LogLevel.Warning); return true; @@ -146,142 +112,43 @@ public class TrackerManagementTCP implements Runnable { } return false; } - - /** Send a not found message. - * @param pd ProtocolP2PPacketTCP to respond - */ - private void sendNotFound(ProtocolP2PPacketTCP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } - - /** Send an empty directory message. - * @param pd ProtocolP2PPacketTCP to respond - */ - private void sendEmptyDirectory(ProtocolP2PPacketTCP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } + } - /** Send an internal error message. - * @param pd ProtocolP2PPacketTCP to respond - */ - private void sendInternalError(ProtocolP2PPacketTCP pd) { - logger.writeTCP("Internal Error", LogLevel.Warning); - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected void writeLog(String text, LogLevel logLevel) { + logger.writeTCP(text, logLevel); + } - /** Handle Registering - * @param pd ProtocolP2PPacketTCP to respond - * @throws InternalError - */ - private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Register : "payload must be an instance of Register"; - if (!(p instanceof Register)) { - throw new InternalError(); - } - // add host to known host list - HostItem host = ((Register)p).getHostItem(); - if (!hostList.contains(host)) { - hostList.add(host); - } - // send a list request - try { - ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); - pLReq.sendRequest((Object)host.getTCPSocket()); - logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); - logger.writeTCP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); - host.closeTCPSocket(); - } catch (EmptyDirectory e) { - logger.writeTCP("Empty Directory", LogLevel.Debug); - hostList.remove(host); - logger.writeTCP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); - } catch (Exception e) { - // remove from list because list request could not be send - hostList.remove(host); - logger.writeTCP("Aborting the add of host " + host, LogLevel.Action); - logger.writeTCP(e, LogLevel.Error); - } - } + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeTCP(e, logLevel); + } - /** Handle Unregistering - * @param pd ProtocolP2PPacketTCP to respond - * @throws InternalError - */ - private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Unregister : "payload must be an instance of Unregister"; - if (!(p instanceof Unregister)) { - sendInternalError(pd); - throw new InternalError(); - } - HostItem host = ((Unregister)p).getHostItem(); - logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); - hostList.remove(host); - for(String f: fileList.keySet()) { - fileList.get(f).remove(host); - if(fileList.get(f).isEmpty()) { - fileList.remove(f); - } - } - } + /** Create packets + * @param payload Payload + */ + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketTCP(payload); + } - /** Handle Discover request - * @param pd ProtocolP2PPacketTCP to respond - * @throws InternalError - */ - private void handleDiscover(ProtocolP2PPacketTCP pd) throws InternalError { - logger.writeTCP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; - if (!(p instanceof DiscoverRequest)) { - sendInternalError(pd); - } else { - String filename = ((DiscoverRequest)p).getFilename(); - try { - pd.sendResponse(new ProtocolP2PPacketTCP(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } - } + + /** Getter for HostItem socket + * @param hostItem HostItem + */ + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getTCPSocket(); + } - /** Handle List Responses - * @param pd ProtocolP2PPacketTCP response - * @throws InternalError - */ - private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - throw new InternalError(); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } - } - } + /** Close HostItem socket + * @param hostItem HostItem + */ + protected void closeHostItemSocket(HostItem hostItem) { + hostItem.closeTCPSocket(); } } diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index a99636a..6ed2235 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -23,6 +23,7 @@ import localException.InternalError; import remoteException.EmptyDirectory; import java.net.InetAddress; import java.net.UnknownHostException; +import tracker.TrackerManagement; /** Tracker management implementation with udp * @author Louis Royer @@ -30,21 +31,14 @@ import java.net.UnknownHostException; * @author JS Auge * @version 1.0 */ -public class TrackerManagementUDP implements Runnable { - - private HostItem tracker; - private Logger logger; +public class TrackerManagementUDP extends TrackerManagement { private DatagramSocket socket; - private List hostList = new ArrayList<>(); - private Map> fileList = new HashMap<>(); - /** Constructor with port and logger. * @param port Port used to listen. * @param logger Logger object */ public TrackerManagementUDP(int port, Logger logger) { - tracker = new HostItem("localhost", port); - this.logger = logger; + super(new HostItem("localhost", port), logger); try { socket = new DatagramSocket(tracker.getPort(), tracker.getInetAddress()); } catch (SocketException e) { @@ -57,39 +51,10 @@ public class TrackerManagementUDP implements Runnable { */ public void run() { logger.writeUDP("Tracker successfully started", LogLevel.Info); - while(true) { + while(!stop) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP<>((Object)socket); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - logger.writeUDP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case LIST_REQUEST: - logger.writeUDP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); - sendEmptyDirectory(pd); - break; - case HASH_REQUEST: - logger.writeUDP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case REGISTER: - logger.writeUDP("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleRegister(pd); - break; - case UNREGISTER: - logger.writeUDP("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleUnregister(pd); - break; - case DISCOVER_REQUEST: - handleDiscover(pd); - break; - default: - logger.writeUDP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); - sendInternalError(pd); - break; - } + handleRequest(pd); } catch (IOException e) { logger.writeUDP(e, LogLevel.Warning); } catch (LocalException e) { @@ -97,143 +62,42 @@ public class TrackerManagementUDP implements Runnable { } } } - - /** Send a not found message. - * @param pd ProtocolP2PPacketUDP to respond - */ - private void sendNotFound(ProtocolP2PPacketUDP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } - - /** Send an empty directory message. - * @param pd ProtocolP2PPacketUDP to respond - */ - private void sendEmptyDirectory(ProtocolP2PPacketUDP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } - - /** Send an internal error message. - * @param pd ProtocolP2PPacketUDP to respond + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - private void sendInternalError(ProtocolP2PPacketUDP pd) { - logger.writeUDP("Internal Error", LogLevel.Warning); - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } + protected void writeLog(String text, LogLevel logLevel) { + logger.writeUDP(text, logLevel); } - /** Handle Registering - * @param pd ProtocolP2PPacketUDP to respond - * @throws InternalError + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Register : "payload must be an instance of Register"; - if (!(p instanceof Register)) { - sendInternalError(pd); - throw new InternalError(); - } - // add host to known host list - HostItem host = ((Register)p).getHostItem(); - if (!hostList.contains(host)) { - hostList.add(host); - } - // send a list request - try { - ProtocolP2PPacket pLReq = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); - pLReq.sendRequest((Object)host.getUDPSocket()); - logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); - ProtocolP2PPacket resp = pLReq.receiveResponse(); - handleListResponse((ProtocolP2PPacketUDP)resp, host); - logger.writeUDP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); - host.closeUDPSocket(); - } catch (EmptyDirectory e) { - logger.writeUDP("Empty Directory", LogLevel.Debug); - hostList.remove(host); - logger.writeUDP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); - } catch (Exception e) { - // remove from list because list request could not be send - hostList.remove(host); - logger.writeUDP("Aborting the add of host " + host, LogLevel.Action); - logger.writeUDP(e, LogLevel.Error); - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeUDP(e, logLevel); } - /** Handle Unregistering - * @param pd ProtocolP2PPacketUDP to respond - * @throws InternalError + /** Create packets + * @param payload Payload */ - private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Unregister : "payload must be an instance of Unregister"; - if (!(p instanceof Unregister)) { - sendInternalError(pd); - throw new InternalError(); - } - HostItem host = ((Unregister)p).getHostItem(); - logger.writeUDP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); - hostList.remove(host); - for(String f: fileList.keySet()) { - fileList.get(f).remove(host); - if(fileList.get(f).isEmpty()) { - fileList.remove(f); - } - } + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketUDP(payload); } - /** Handle Discover request - * @param pd ProtocolP2PPacketUDP to respond - * @throws InternalError + + /** Getter for HostItem socket + * @param hostItem HostItem */ - private void handleDiscover(ProtocolP2PPacketUDP pd) throws InternalError { - logger.writeUDP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; - if (!(p instanceof DiscoverRequest)) { - sendInternalError(pd); - } else { - String filename = ((DiscoverRequest)p).getFilename(); - try { - pd.sendResponse(new ProtocolP2PPacketUDP(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getUDPSocket(); } - /** Handle List Responses - * @param pd ProtocolP2PPacketUDP response - * @throws InternalError + /** Close HostItem socket + * @param hostItem HostItem */ - private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - throw new InternalError(); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } - } + protected void closeHostItemSocket(HostItem hostItem) { + hostItem.closeUDPSocket(); } } From 1355ef14b18b0ca48b4461f91e22332a1fdbf150 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 22 Mar 2020 16:55:05 +0100 Subject: [PATCH 26/40] Fix #40 --- src/clientP2P/ClientDownload.java | 409 ++++++++++++++++++++++ src/clientP2P/ClientDownloadPart.java | 310 +++++++++++++++++ src/clientP2P/ClientDownloadPartTCP.java | 331 ++---------------- src/clientP2P/ClientDownloadPartUDP.java | 316 ++--------------- src/clientP2P/ClientDownloadTCP.java | 410 ++--------------------- src/clientP2P/ClientDownloadUDP.java | 401 ++-------------------- src/clientP2P/ClientManagement.java | 262 +++++++++++++++ src/clientP2P/ClientManagementTCP.java | 242 ++----------- src/clientP2P/ClientManagementUDP.java | 255 +++----------- src/serverP2P/ServerManagementTCP.java | 12 +- src/tracker/TrackerManagement.java | 7 + src/tracker/TrackerManagementTCP.java | 16 +- 12 files changed, 1199 insertions(+), 1772 deletions(-) create mode 100644 src/clientP2P/ClientDownload.java create mode 100644 src/clientP2P/ClientDownloadPart.java create mode 100644 src/clientP2P/ClientManagement.java diff --git a/src/clientP2P/ClientDownload.java b/src/clientP2P/ClientDownload.java new file mode 100644 index 0000000..ed58c3b --- /dev/null +++ b/src/clientP2P/ClientDownload.java @@ -0,0 +1,409 @@ +package clientP2P; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Random; +import java.io.IOException; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.nio.file.StandardCopyOption; +import exception.LocalException; +import exception.RemoteException; +import localException.SocketClosed; +import localException.ProtocolError; +import localException.InternalError; +import localException.TransmissionError; +import localException.SizeError; +import localException.VersionError; +import remoteException.EmptyDirectory; +import remoteException.EmptyFile; +import remoteException.VersionRemoteError; +import remoteException.ProtocolRemoteError; +import remoteException.NotFound; +import remoteException.InternalRemoteError; +import remoteException.NotATracker; +import protocolP2P.HashAlgorithm; +import protocolP2P.HashResponse; +import protocolP2P.HashRequest; +import protocolP2P.Payload; +import protocolP2P.FilePart; +import protocolP2P.LoadRequest; +import protocolP2P.ProtocolP2PPacket; +import clientP2P.ClientDownloadPart; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; +import tools.ServeErrors; + +/** Class to download file +* @author Louis Royer +* @author Flavien Haas +* @author JS Auge +* @version 1.0 +*/ +public abstract class ClientDownload extends ServeErrors implements Runnable { + protected List hostList; + protected String filename; + protected byte[] hash512; + protected List sockList = new ArrayList(); + protected List offsetsToAsk = new ArrayList(); + protected List offsetsPending = new ArrayList(); + protected boolean stop; + protected long size; + protected static final long MAX_PARTIAL_SIZE = 4096; + protected String partsSubdir; + protected String dirStorage; + protected boolean success = false; + protected Logger logger; + + /** Constructor with parameters: filename, list of hosts, parts subdirectory and dirStorage + * @param filename name of file to download + * @param hostList list of servers + * @param partsSubdir directory to store .part files + * @param dirStorage directory to write assembled file + * @param logger Logger + */ + public ClientDownload(String filename, List hostList, String partsSubdir, String dirStorage, Logger logger) { + this.partsSubdir = partsSubdir; + this.dirStorage = dirStorage; + this.filename = filename; + this.hostList = hostList; + this.logger = logger; + this.stop = false; + } + + /** Success getter. + * @return true when file have successfully been reassembled. + */ + public boolean getSuccess() { + return success; + } + + /** Getter for hash512sum + * @return hash512sum + */ + public byte[] getHashSum512() { + return hash512; + } + + /** Stop threads */ + protected void stopTasks() { + for(ClientDownloadPart c : sockList) { + try { + c.setStop(); + } catch (InterruptedException e) { + writeLog(e, LogLevel.Error); + } + } + } + + /** Asks thread to stop + */ + public void setStop() { + stop = true; + } + + /** Assign tasks randomly to threads. + * @throws InternalError + */ + protected void assignTasks() throws InternalError { + Random rand = new Random(); + for(long offset : offsetsToAsk) { + try { + sockList.get(rand.nextInt(sockList.size())).assignTask(offset); + offsetsPending.add(offset); + System.err.println("Assigned task "+ offset); + writeLog("Assigned task "+ offset, LogLevel.Info); + } catch(InterruptedException e) { + writeLog(e, LogLevel.Error); + throw new InternalError(); + } + } + offsetsToAsk.removeAll(offsetsPending); + } + + /** Create a clientDownloadPart + * @param filename name of the file to download + * @param hostItem Hostitem of the server + */ + protected abstract ClientDownloadPart createDownloadPart(String filename, HostItem hostItem); + + /** Starts threads for each server in hostList. + */ + protected void initThreads() { + for(HostItem hostItem: hostList) { + sockList.add(createDownloadPart(filename, hostItem)); + } + for(ClientDownloadPart c: sockList) { + Thread t = new Thread(c); + t.start(); + } + writeLog("Threads initialized", LogLevel.Info); + } + + /** Remove tasks from failed threads. Update done status. + * @throws InternalError + */ + protected void checkTasksStatus() throws InternalError { + try { + synchronized(this) { + this.wait(); + List sockListCpy = new ArrayList<>(sockList); + for(ClientDownloadPart c: sockListCpy) { + if (c.hasFailed() == true) { + sockList.remove(c); + offsetsPending.removeAll(c.getFailed()); + offsetsToAsk.addAll(c.getFailed()); + } + try { + offsetsPending.removeAll(c.getDone()); + } catch (InterruptedException e) { + throw new InternalError(); + } + } + writeLog("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending", LogLevel.Info); + if (offsetsToAsk.isEmpty() && offsetsPending.isEmpty()) { + stop = true; + } + if (sockList.size() == 0) { + logger.writeUDP("No thread working", LogLevel.Error); + throw new InternalError(); + } + } + } catch (InterruptedException e) { + throw new InternalError(); + } + } + + /** Get hashsum from server. + * @param hostItem server to ask hash + * @return hash512sum + * @throws InternalError + */ + protected byte[] getHashSum512(HostItem hostItem) throws InternalError { + byte[] hash; + HashAlgorithm[] hashesAlgo = new HashAlgorithm[1]; + hashesAlgo[0] = HashAlgorithm.SHA512; + ProtocolP2PPacket d = createProtocolP2PPacket(new HashRequest(filename, hashesAlgo)); + try { + d.sendRequest(getHostItemSocket(hostItem)); + try { + Payload pHash = d.receiveResponse().getPayload(); + assert pHash instanceof HashResponse : "This payload must be instance of HashResponse"; + if (!(pHash instanceof HashResponse)) { + throw new InternalError(); + } else { + hash = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512); + } + } catch (EmptyDirectory e) { + writeLog(e, LogLevel.Error); + hash = new byte[0]; + } catch (NotFound e) { + writeLog(e, LogLevel.Error); + hash = new byte[0]; + } catch (LocalException e) { + writeLog(e, LogLevel.Error); + throw new InternalError(); + } catch (RemoteException e) { + writeLog(e, LogLevel.Error); + throw new InternalError(); + } + return hash; + } catch (IOException e) { + writeLog(e, LogLevel.Error); + throw new InternalError(); + } catch (SocketClosed e){ + System.err.println("getHashSum512 : SocketClosed"); + writeLog("getHashSum512 : SocketClosed", LogLevel.Error); + throw new InternalError(); + } + } + + /** Removes servers not owning the correct file to download from list. + * This is done by comparing hash512sum. + * @throws InternalError + */ + protected void purgeList() throws InternalError { + List blackList = new ArrayList(); + boolean first = false; + byte[] hashsum; + for(HostItem host: hostList) { + // already have hashsum from 1st server + if (!first) { + first = true; + continue; + } + // ask hashsum + hashsum = getHashSum512(host); + if (!Arrays.equals(hash512, hashsum)) { + blackList.add(host); + } + } + // purge list + for(HostItem host: blackList) { + hostList.remove(host); + } + writeLog("Host list purge: done", LogLevel.Info); + } + + + /** Reassemble file from file parts. + * Set success to true if file is reassembled successfully. + */ + protected void reassembleFile() { + boolean firstPart = true; + boolean abort = false; + long nextOffset = 0; + do { + if (firstPart) { + writeLog("Reassembling: First part", LogLevel.Info); + try { + // create file + Files.copy(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath(), new File(dirStorage + filename).toPath(), StandardCopyOption.REPLACE_EXISTING); + nextOffset = (new File(dirStorage + filename)).length(); + firstPart = false; + } catch (IOException e) { + writeLog("Reassembling: aborting on first part", LogLevel.Warning); + abort = true; + } + } else if (nextOffset >= size) { + success = true; + writeLog("Reassembling: success", LogLevel.Info); + } else { + // append to file + try { + Files.write(new File(dirStorage + filename).toPath(), Files.readAllBytes(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath()), StandardOpenOption.APPEND); + nextOffset = (new File(dirStorage + filename)).length(); + } catch (IOException e) { + abort = true; + writeLog("Aborting: bad number " + nextOffset, LogLevel.Error); + } + } + } while((!success) && (!abort)); + } + + + /** Set size of file to download. Also download first file part. + * @throws InternalError + */ + protected void setSize() throws InternalError { + ProtocolP2PPacket d = createProtocolP2PPacket(new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); + try { + d.sendRequest(getHostItemSocket(hostList.get(0))); + try { + Payload p = d.receiveResponse().getPayload(); + assert p instanceof FilePart : "This payload must be instance of FilePart"; + if (!(p instanceof FilePart)) { + System.err.println("Error: cannot get size."); + writeLog("cannot get size.", LogLevel.Error); + throw new InternalError(); + } else { + FilePart fp = (FilePart)p; + if (!fp.getFilename().equals(filename)) { + System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); + writeLog("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); + throw new ProtocolError(); + } + if (fp.getOffset() == 0) { + try { + Files.write(new File(partsSubdir + filename + "_0.part").toPath(), fp.getPartialContent()); + } catch (IOException e) { + System.err.println("Error: cannot write file (" + partsSubdir + filename + "_0.part)"); + writeLog("cannot write file (" + partsSubdir + filename + "_0.part)", LogLevel.Error); + } + size = fp.getTotalSize(); + if (fp.getPartialContent().length == size) { + stop = true; + } + } else { + System.err.println("Error: wrong file part received."); + writeLog("wrong file part received.", LogLevel.Error); + throw new InternalError(); + } + } + } catch (EmptyDirectory e) { + System.err.println("Error: empty directory."); + writeLog("empty directory.", LogLevel.Error); + throw new InternalError(); + } catch (LocalException e) { + writeLog(e, LogLevel.Error); + throw new InternalError(); + } catch (RemoteException e) { + writeLog(e, LogLevel.Error); + throw new InternalError(); + } + } catch (IOException e) { + writeLog(e, LogLevel.Error); + throw new InternalError(); + } catch (SocketClosed e){ + System.err.println("setSize : SocketClosed"); + writeLog("setSize : SocketClosed", LogLevel.Error); + } + } + + /** Close HostItem socket + * @param hostItem HostItem + */ + protected abstract void closeHostItemSocket(HostItem hostItem); + + + /** Runnable implementation + */ + public void run() { + try { + init(); + if (stop) { + writeLog("File is smaller than part max size.", LogLevel.Info); + closeHostItemSocket(hostList.get(0)); + } else { + writeLog("File is bigger than part max size.", LogLevel.Info); + purgeList(); + initThreads(); + while(!stop) { + assignTasks(); + checkTasksStatus(); + + } + } + writeLog("Reassembling file parts.", LogLevel.Info); + reassembleFile(); + } catch(InternalError e) { + writeLog("Error while downloading file. Aborting.", LogLevel.Error); + } finally { + stopTasks(); + } + } + + /** Initialize infos about file to download (size, hash512sum, partslist to dl). + * Also download first partfile (to get size). + * @throws InternalError + */ + protected void init() throws InternalError { + // get size + setSize(); + + // get hashsum from 1st server in list + hash512 = getHashSum512(hostList.get(0)); + if (hash512.length == 0) { + writeLog("no hash512sum support.", LogLevel.Error); + throw new InternalError(); + } + + // Add tasks + if (!stop) { + for(long i=MAX_PARTIAL_SIZE; i toDoTasks; + protected List pendingTasks; + protected List tasksDone; + protected volatile boolean tasksListsLock; + protected volatile boolean stop; + protected volatile boolean failed; + protected String filename; + protected volatile boolean noTask; + protected String partsSubdir; + protected static final long MAX_PARTIAL_SIZE = 4096; + protected ClientDownload manager; + protected Logger logger; + + /** Constructor with filename, socket, and part subdir + * @param filename name of file to download + * @param socket socket to use + * @param partsSubdir directory to store .part files + * @param logger Logger + */ + public ClientDownloadPart(ClientDownload manager, String filename, String partsSubdir, Logger logger) { + this.manager = manager; + this.partsSubdir = partsSubdir; + this.filename = filename; + this.logger = logger; + stop = false; + failed = false; + pendingTasks = new ArrayList<>(); + toDoTasks = new ArrayList<>(); + tasksDone = new ArrayList<>(); + noTask = true; + tasksListsLock = false; + } + + /** True if thread has failed to get a file. + * @return true if thread has failed to get a file + */ + public boolean hasFailed() { + return failed; + } + + /** Asks to stop thread. + * @throws InterruptedException + */ + public synchronized void setStop() throws InterruptedException { + stop = true; + this.notifyAll(); + } + + /** Runnable implementation */ + public void run() { + while(!stop) { + try { + doTasks(); + synchronized(manager) { + manager.notify(); + } + } catch(InterruptedException e) { + try { + setStop(); + synchronized(manager) { + manager.notify(); + } + } catch (InterruptedException e2) { + } + } + } + writeLog("Closing socket", LogLevel.Info); + try{ + closeSocket(); + } catch(IOException e){ + writeLog("can't close socket", LogLevel.Error); + } + } + + /** Close the socket + */ + protected abstract void closeSocket() throws IOException; + + /** Get list of offsets that have not be downloaded if failed, else + * empty list. + * @return list of offsets + */ + public List getFailed() { + List ret = new ArrayList<>(); + if (failed) { + ret.addAll(pendingTasks); + ret.addAll(toDoTasks); + } + return ret; + } + + /** Get list of downloaded file parts offset, then clear this list. + * @return list of offsets + * @throws InterruptedException + */ + public List getDone() throws InterruptedException { + if (tasksDone.size() == 0) { + return new ArrayList<>(); + } else { + synchronized (this) { + while(tasksListsLock) { + this.wait(); + } + tasksListsLock = true; + List ret = new ArrayList<>(tasksDone); + tasksDone.clear(); + tasksListsLock = false; + this.notifyAll(); + return ret; + } + } + } + + /** Adds offset of files parts to download. + * @param task offset to download + * @throws InterruptedException + */ + public synchronized void assignTask(Long task) throws InterruptedException { + synchronized(this) { + while(tasksListsLock) { + this.wait(); + } + tasksListsLock = true; + toDoTasks.add(task); + noTask = false; + tasksListsLock = false; + this.notifyAll(); + } + } + + + /** Send one request and wait for one response. Blocks when no task. + * @throws InterruptedException + */ + public synchronized void doTasks() throws InterruptedException { + while(noTask && !stop) { + this.wait(); + } + if (!stop) { + try { + Long offset = toDoTasks.get(0); + ProtocolP2PPacket p = reqPart(offset); + if (p == null) { + stop = true; + } + + failed = downloadPart(p); + if (failed) { + System.err.println("Error: DownloadPart failed."); + writeLog("DownloadPart failed.", LogLevel.Error); + stop = true; + } else if (toDoTasks.isEmpty()) { + noTask = true; + } + } catch (IndexOutOfBoundsException e) { + writeLog(e, LogLevel.Error); + noTask = true; + } + } + } + + /** Send a request for a specific offset. + * @param offset Offset of the file part to download + * @return ProtocolP2PPacketTCP used to send request + */ + protected ProtocolP2PPacket reqPart(Long offset) { + writeLog("New request: " + offset, LogLevel.Info); + // maintain tracking of tasks + if (toDoTasks.contains(offset)) { + try { + synchronized (this) { + while(tasksListsLock) { + this.wait(); + } + tasksListsLock = true; + toDoTasks.remove(offset); + pendingTasks.add(offset); + tasksListsLock = false; + this.notifyAll(); + } + } catch(InterruptedException e) { + writeLog("reqPart interruptedException", LogLevel.Error); + return null; + } + } else { + writeLog("reqPart (offset " + offset + " not in toDoTasks)", LogLevel.Error); + return null; + } + // send request + try { + ProtocolP2PPacket d = createProtocolP2PPacket(new LoadRequest(filename, offset.longValue(), MAX_PARTIAL_SIZE)); + d.sendRequest(getSocket()); + return d; + } catch (InternalError e) { + writeLog("reqPart internalError", LogLevel.Error); + return null; + } catch (IOException e) { + writeLog("reqPart ioexception", LogLevel.Error); + writeLog(e, LogLevel.Error); + return null; + } catch (SocketClosed e){ + writeLog("reqPart SocketClosed", LogLevel.Error); + return null; + } + } + + /** Get the socket */ + protected abstract Object getSocket(); + + + /** Download file part associated to the request send (d). + * @param d request packet + * @return true on failure, else false + */ + public < T extends ProtocolP2PPacket > boolean downloadPart(T d) { + if (d == null) { + writeLog("downloadPart -> d is null.", LogLevel.Error); + return true; + } + try { + Payload p = d.receiveResponse().getPayload(); + assert p instanceof FilePart : "This payload must be instance of FilePart"; + if (!(p instanceof FilePart)) { + writeLog("cannot get size.", LogLevel.Error); + return true; + } else { + FilePart fp = (FilePart)p; + if (!fp.getFilename().equals(filename)) { + writeLog("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); + return true; + } + Long offset = Long.valueOf(fp.getOffset()); + if (pendingTasks.contains(offset)) { + try { + Files.write(new File(partsSubdir + filename + "_" + offset + ".part").toPath(), fp.getPartialContent()); + } catch (IOException e) { + writeLog("cannot write file (" + partsSubdir + filename + "_" + offset + ".part)", LogLevel.Error); + } + } else { + writeLog("wrong file part received.", LogLevel.Error); + return true; + } + try { + synchronized(this) { + while(tasksListsLock) { + this.wait(); + } + tasksListsLock = true; + pendingTasks.remove(offset); + tasksDone.add(offset); + tasksListsLock = false; + this.notifyAll(); + } + } catch(InterruptedException e) { + writeLog("DownloadPart Interrupted exception", LogLevel.Error); + return true; + } + } + } catch (LocalException e) { + writeLog(e, LogLevel.Error); + return true; + } catch (RemoteException e) { + writeLog(e, LogLevel.Error); + return true; + } catch (IOException e) { + System.err.println("Error: downloadPart ioexception"); + writeLog("downloadPart ioexception", LogLevel.Error); + return true; + } + return false; + } + + +} diff --git a/src/clientP2P/ClientDownloadPartTCP.java b/src/clientP2P/ClientDownloadPartTCP.java index b2872e9..7928735 100644 --- a/src/clientP2P/ClientDownloadPartTCP.java +++ b/src/clientP2P/ClientDownloadPartTCP.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import protocolP2P.ProtocolP2PPacketTCP; +import protocolP2P.ProtocolP2PPacket; import protocolP2P.Payload; import protocolP2P.LoadRequest; import protocolP2P.FilePart; @@ -24,6 +25,7 @@ import remoteException.NotFound; import remoteException.NotATracker; import tools.Logger; import tools.LogLevel; +import clientP2P.ClientDownloadPart; /** Class to download file parts on tcp. * @author Louis Royer @@ -31,332 +33,55 @@ import tools.LogLevel; * @author JS Auge * @version 1.0 */ -public class ClientDownloadPartTCP implements Runnable { +public class ClientDownloadPartTCP extends ClientDownloadPart { - private List toDoTasks; - private List pendingTasks; - private List tasksDone; - private volatile boolean tasksListsLock; - private volatile boolean stop; - private volatile boolean failed; - private String filename; private Socket socket; - private volatile boolean noTask; - private String partsSubdir; - private static final long MAX_PARTIAL_SIZE = 4096; - private ClientDownloadTCP manager; - private Logger logger; /** Constructor with filename, socket, and part subdir * @param filename name of file to download * @param socket socket to use * @param partsSubdir directory to store .part files + * @param logger Logger */ - public ClientDownloadPartTCP(ClientDownloadTCP manager, String filename, Socket socket, String partsSubdir, Logger logger) { - this.manager = manager; - this.partsSubdir = partsSubdir; - this.filename = filename; + public ClientDownloadPartTCP(ClientDownload manager, String filename, Socket socket, String partsSubdir, Logger logger) { + super(manager, filename, partsSubdir, logger); this.socket = socket; - this.logger = logger; - stop = false; - failed = false; - pendingTasks = new ArrayList<>(); - toDoTasks = new ArrayList<>(); - tasksDone = new ArrayList<>(); - noTask = true; - tasksListsLock = false; } - /** True if thread has failed to get a file. - * @return true if thread has failed to get a file - */ - public boolean hasFailed() { - return failed; - } - - /** Asks to stop thread. - * @throws InterruptedException - */ - public synchronized void setStop() throws InterruptedException { - stop = true; - this.notifyAll(); - } - - /** Runnable implementation */ - public void run() { - while(!stop) { - try { - doTasks(); - synchronized(manager) { - manager.notify(); - } - } catch(InterruptedException e) { - try { - setStop(); - synchronized(manager) { - manager.notify(); - } - } catch (InterruptedException e2) { - } - } - } - System.err.println("Closing socket"); - logger.writeTCP("Closing socket", LogLevel.Info); - try{ - socket.close(); - } catch(IOException e){ - System.err.println("can't close socket"); - logger.writeTCP("can't close socket", LogLevel.Error); - } - } - /** Get list of offsets that have not be downloaded if failed, else - * empty list. - * @return list of offsets - */ - public List getFailed() { - List ret = new ArrayList<>(); - if (failed) { - ret.addAll(pendingTasks); - ret.addAll(toDoTasks); - } - return ret; + + /** Get the socket */ + protected Object getSocket() { + return (Object) socket; } - - /** Get list of downloaded file parts offset, then clear this list. - * @return list of offsets - * @throws InterruptedException + + /** Close the socket */ - public List getDone() throws InterruptedException { - if (tasksDone.size() == 0) { - return new ArrayList<>(); - } else { - synchronized (this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - List ret = new ArrayList<>(tasksDone); - tasksDone.clear(); - tasksListsLock = false; - this.notifyAll(); - return ret; - } - } + protected void closeSocket() throws IOException { + socket.close(); } - /** Adds offset of files parts to download. - * @param task offset to download - * @throws InterruptedException + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - public synchronized void assignTask(Long task) throws InterruptedException { - synchronized(this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - toDoTasks.add(task); - noTask = false; - tasksListsLock = false; - this.notifyAll(); - } + protected void writeLog(String text, LogLevel logLevel) { + logger.writeTCP(text, logLevel); } - /** Send one request and wait for one response. Blocks when no task. - * @throws InterruptedException + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - public synchronized void doTasks() throws InterruptedException { - while(noTask && !stop) { - this.wait(); - } - if (!stop) { - try { - Long offset = toDoTasks.get(0); - ProtocolP2PPacketTCP p = reqPart(offset); - if (p == null) { - stop = true; - } - - failed = downloadPart(p); - if (failed) { - System.err.println("Error: DownloadPart failed."); - logger.writeTCP("DownloadPart failed.", LogLevel.Error); - stop = true; - } else if (toDoTasks.isEmpty()) { - noTask = true; - } - } catch (IndexOutOfBoundsException e) { - logger.writeTCP(e, LogLevel.Error); - noTask = true; - } - - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeTCP(e, logLevel); } - /** Send a request for a specific offset. - * @param offset Offset of the file part to download - * @return ProtocolP2PPacketTCP used to send request - */ - private ProtocolP2PPacketTCP reqPart(Long offset) { - System.err.println("New request: " + offset); - logger.writeTCP("New request: " + offset, LogLevel.Info); - // maintain tracking of tasks - if (toDoTasks.contains(offset)) { - try { - synchronized (this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - toDoTasks.remove(offset); - pendingTasks.add(offset); - tasksListsLock = false; - this.notifyAll(); - } - } catch(InterruptedException e) { - System.err.println("Error: reqPart interruptedException"); - logger.writeTCP("reqPart interruptedException", LogLevel.Error); - return null; - } - } else { - System.err.println("Error: reqPart (offset " + offset + " not in toDoTasks)"); - logger.writeTCP("reqPart (offset " + offset + " not in toDoTasks)", LogLevel.Error); - return null; - } - // send request - try { - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new LoadRequest(filename, offset.longValue(), MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); - return d; - } catch (InternalError e) { - System.err.println("Error: reqPart internalError"); - logger.writeTCP("reqPart internalError", LogLevel.Error); - return null; - } catch (IOException e) { - e.printStackTrace(); - System.err.println("Error: reqPart ioexception"); - logger.writeTCP("reqPart ioexception", LogLevel.Error); - return null; - } catch (SocketClosed e){ - System.err.println("Error: reqPart SocketClosed"); - logger.writeTCP("reqPart SocketClosed", LogLevel.Error); - return null; - } - } - /** Download file part associated to the request send (d). - * @param d request packet - * @return true on failure, else false + /** Create packets + * @param payload Payload */ - public boolean downloadPart(ProtocolP2PPacketTCP d) { - if (d == null) { - System.err.println("Error: downloadPart -> d is null."); - logger.writeTCP("downloadPart -> d is null.", LogLevel.Error); - return true; - } - try { - Payload p = d.receiveResponse().getPayload(); - assert p instanceof FilePart : "This payload must be instance of FilePart"; - if (!(p instanceof FilePart)) { - System.err.println("Error: cannot get size."); - logger.writeTCP("cannot get size.", LogLevel.Error); - return true; - } else { - FilePart fp = (FilePart)p; - if (!fp.getFilename().equals(filename)) { - System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); - logger.writeTCP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); - return true; - } - Long offset = Long.valueOf(fp.getOffset()); - if (pendingTasks.contains(offset)) { - try { - Files.write(new File(partsSubdir + filename + "_" + offset + ".part").toPath(), fp.getPartialContent()); - } catch (IOException e) { - System.err.println("Error: cannot write file (" + partsSubdir + filename + "_" + offset + ".part)"); - logger.writeTCP("cannot write file (" + partsSubdir + filename + "_" + offset + ".part)", LogLevel.Error); - } - } else { - System.err.println("Error: wrong file part received."); - logger.writeTCP("wrong file part received.", LogLevel.Error); - return true; - } - try { - synchronized(this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - pendingTasks.remove(offset); - tasksDone.add(offset); - tasksListsLock = false; - this.notifyAll(); - } - } catch(InterruptedException e) { - System.err.println("Error: DownloadPart Interrupted exception"); - logger.writeTCP("DownloadPart Interrupted exception", LogLevel.Error); - return true; - } - } - } catch (EmptyDirectory e) { - System.err.println("Error: empty directory."); - logger.writeTCP("empty directory.", LogLevel.Error); - return true; - } catch (EmptyFile e) { - System.err.println("Error: downloadPart emptyFile"); - logger.writeTCP("downloadPart emptyFile", LogLevel.Error); - // TODO: use more specific errors - return true; - } catch (ProtocolError e) { - System.err.println("Error: downloadPart protocolError"); - logger.writeTCP("downloadPart protocolError", LogLevel.Error); - return true; - } catch (InternalRemoteError e) { - System.err.println("Error: downloadPart internalRemoteError"); - logger.writeTCP("downloadPart internalRemoteError", LogLevel.Error); - return true; - } catch (VersionRemoteError e) { - System.err.println("Error: downloadPart versionRemoteError"); - logger.writeTCP("downloadPart versionRemoteError", LogLevel.Error); - return true; - } catch (ProtocolRemoteError e) { - System.err.println("Error: downloadPart protocolRemoteError"); - logger.writeTCP("downloadPart protocolRemoteError", LogLevel.Error); - return true; - } catch (TransmissionError e) { - System.err.println("Error: downloadPart transmissionError"); - logger.writeTCP("downloadPart transmissionError", LogLevel.Error); - return true; - } catch (VersionError e) { - System.err.println("Error: downloadPart versionError"); - logger.writeTCP("downloadPart versionError", LogLevel.Error); - return true; - } catch (SizeError e) { - System.err.println("Error: downloadPart sizeError"); - logger.writeTCP("downloadPart sizeError", LogLevel.Error); - return true; - } catch (NotFound e) { - System.err.println("Error: downloadPart notFound"); - logger.writeTCP("downloadPart notFound", LogLevel.Error); - return true; - } catch (IOException e) { - System.err.println("Error: downloadPart ioexception"); - logger.writeTCP("downloadPart ioexception", LogLevel.Error); - return true; - } catch (InternalError e) { - System.err.println("Error: downloadPart internalError"); - logger.writeTCP("downloadPart internalError", LogLevel.Error); - return true; - } catch (SocketClosed e){ - System.err.println("Error: downloadPart SocketClosed"); - logger.writeTCP("downloadPart SocketClosed", LogLevel.Error); - return true; - } catch (NotATracker e) { - System.err.println("Error: downloadPart notATracker"); - logger.writeTCP("downloadPart notATracker", LogLevel.Error); - return true; - } - return false; + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketTCP(payload); } - } diff --git a/src/clientP2P/ClientDownloadPartUDP.java b/src/clientP2P/ClientDownloadPartUDP.java index 2a2e4a7..0387c0c 100644 --- a/src/clientP2P/ClientDownloadPartUDP.java +++ b/src/clientP2P/ClientDownloadPartUDP.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.ArrayList; import java.net.DatagramSocket; import protocolP2P.ProtocolP2PPacketUDP; +import protocolP2P.ProtocolP2PPacket; import protocolP2P.Payload; import protocolP2P.LoadRequest; import protocolP2P.FilePart; @@ -23,6 +24,7 @@ import java.io.File; import java.io.IOException; import tools.Logger; import tools.LogLevel; +import clientP2P.ClientDownloadPart; /** Class to download file parts on udp. * @author Louis Royer @@ -30,318 +32,54 @@ import tools.LogLevel; * @author JS Auge * @version 1.0 */ -public class ClientDownloadPartUDP implements Runnable { +public class ClientDownloadPartUDP extends ClientDownloadPart { - private List toDoTasks; - private List pendingTasks; - private List tasksDone; - private volatile boolean tasksListsLock; - private volatile boolean stop; - private volatile boolean failed; - private String filename; private DatagramSocket socket; - private volatile boolean noTask; - private String partsSubdir; - private static final long MAX_PARTIAL_SIZE = 4096; - private ClientDownloadUDP manager; - private Logger logger; + /** Constructor with filename, socket, and part subdir * @param filename name of file to download * @param socket socket to use * @param partsSubdir directory to store .part files + * @param logger Logger */ - public ClientDownloadPartUDP(ClientDownloadUDP manager, String filename, DatagramSocket socket, String partsSubdir, Logger logger) { - this.manager = manager; - this.partsSubdir = partsSubdir; - this.filename = filename; + public ClientDownloadPartUDP(ClientDownload manager, String filename, DatagramSocket socket, String partsSubdir, Logger logger) { + super(manager, filename, partsSubdir, logger); this.socket = socket; - this.logger = logger; - stop = false; - failed = false; - pendingTasks = new ArrayList<>(); - toDoTasks = new ArrayList<>(); - tasksDone = new ArrayList<>(); - noTask = true; - tasksListsLock = false; } - /** True if thread has failed to get a file. - * @return true if thread has failed to get a file - */ - public boolean hasFailed() { - return failed; + /** Get the socket */ + protected Object getSocket() { + return (Object) socket; } - - /** Asks to stop thread. - * @throws InterruptedException + + /** Close the socket */ - public synchronized void setStop() throws InterruptedException { - stop = true; - this.notifyAll(); - } - - /** Runnable implementation */ - public void run() { - while(!stop) { - try { - doTasks(); - synchronized(manager) { - manager.notify(); - } - } catch(InterruptedException e) { - try { - setStop(); - synchronized(manager) { - manager.notify(); - } - } catch (InterruptedException e2) { - } - } - } - System.err.println("Closing socket"); - logger.writeUDP("Closing socket", LogLevel.Info); + protected void closeSocket() throws IOException { socket.close(); } - /** Get list of offsets that have not be downloaded if failed, else - * empty list. - * @return list of offsets - */ - public List getFailed() { - List ret = new ArrayList<>(); - if (failed) { - ret.addAll(pendingTasks); - ret.addAll(toDoTasks); - } - return ret; - } - - /** Get list of downloaded file parts offset, then clear this list. - * @return list of offsets - * @throws InterruptedException - */ - public List getDone() throws InterruptedException { - if (tasksDone.size() == 0) { - return new ArrayList<>(); - } else { - synchronized (this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - List ret = new ArrayList<>(tasksDone); - tasksDone.clear(); - tasksListsLock = false; - this.notifyAll(); - return ret; - } - } - } - - /** Adds offset of files parts to download. - * @param task offset to download - * @throws InterruptedException - */ - public synchronized void assignTask(Long task) throws InterruptedException { - synchronized(this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - toDoTasks.add(task); - noTask = false; - tasksListsLock = false; - this.notifyAll(); - } - } - /** Send one request and wait for one response. Blocks when no task. - * @throws InterruptedException + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - public synchronized void doTasks() throws InterruptedException { - while(noTask && !stop) { - this.wait(); - } - if (!stop) { - try { - Long offset = toDoTasks.get(0); - ProtocolP2PPacketUDP p = reqPart(offset); - if (p == null) { - stop = true; - } - - failed = downloadPart(p); - if (failed) { - System.err.println("Error: DownloadPart failed."); - stop = true; - } else if (toDoTasks.isEmpty()) { - noTask = true; - } - } catch (IndexOutOfBoundsException e) { - logger.writeUDP(e, LogLevel.Error); - noTask = true; - } - - } + protected void writeLog(String text, LogLevel logLevel) { + logger.writeUDP(text, logLevel); } - /** Send a request for a specific offset. - * @param offset Offset of the file part to download - * @return ProtocolP2PPacketTCP used to send request + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - private ProtocolP2PPacketUDP reqPart(Long offset) { - System.err.println("New request: "+ offset); - logger.writeUDP("New request: "+ offset, LogLevel.Info); - // maintain tracking of tasks - if (toDoTasks.contains(offset)) { - try { - synchronized (this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - toDoTasks.remove(offset); - pendingTasks.add(offset); - tasksListsLock = false; - this.notifyAll(); - } - } catch(InterruptedException e) { - System.err.println("Error: reqPart interruptedException"); - logger.writeUDP("reqPart interruptedException", LogLevel.Error); - return null; - } - } else { - System.err.println("Error: reqPart (offset " + offset + " not in toDoTasks)"); - logger.writeUDP("reqPart (offset " + offset + " not in toDoTasks)", LogLevel.Error); - return null; - } - // send request - try { - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new LoadRequest(filename, offset.longValue(), MAX_PARTIAL_SIZE)); - d.sendRequest((Object)socket); - return d; - } catch (InternalError e) { - System.err.println("Error: reqPart internalError"); - logger.writeUDP("reqPart internalError", LogLevel.Error); - return null; - } catch (IOException e) { - e.printStackTrace(); - System.err.println("Error: reqPart ioexception"); - logger.writeUDP("reqPart ioexception", LogLevel.Error); - return null; - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeUDP(e, logLevel); } - /** Download file part associated to the request send (d). - * @param d request packet - * @return true on failure, else false + /** Create packets + * @param payload Payload */ - public boolean downloadPart(ProtocolP2PPacketUDP d) { - if (d == null) { - System.err.println("Error: downloadPart -> d is null."); - logger.writeUDP("downloadPart -> d is null.", LogLevel.Error); - return true; - } - try { - Payload p = d.receiveResponse().getPayload(); - assert p instanceof FilePart : "This payload must be instance of FilePart"; - if (!(p instanceof FilePart)) { - System.err.println("Error: cannot get size."); - logger.writeUDP("cannot get size.", LogLevel.Error); - return true; - } else { - FilePart fp = (FilePart)p; - if (!fp.getFilename().equals(filename)) { - System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); - logger.writeUDP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); - return true; - } - Long offset = Long.valueOf(fp.getOffset()); - if (pendingTasks.contains(offset)) { - try { - Files.write(new File(partsSubdir + filename + "_" + offset + ".part").toPath(), fp.getPartialContent()); - } catch (IOException e) { - System.err.println("Error: cannot write file (" + partsSubdir + filename + "_" + offset + ".part)"); - logger.writeUDP("cannot write file (" + partsSubdir + filename + "_" + offset + ".part)", LogLevel.Error); - } - } else { - System.err.println("Error: wrong file part received."); - logger.writeUDP("wrong file part received.", LogLevel.Error); - return true; - } - try { - synchronized(this) { - while(tasksListsLock) { - this.wait(); - } - tasksListsLock = true; - pendingTasks.remove(offset); - tasksDone.add(offset); - tasksListsLock = false; - this.notifyAll(); - } - } catch(InterruptedException e) { - System.err.println("Error: DownloadPart Interrupted exception"); - logger.writeUDP("DownloadPart Interrupted exception", LogLevel.Error); - return true; - } - } - } catch (EmptyDirectory e) { - System.err.println("Error: empty directory."); - logger.writeUDP("empty directory.", LogLevel.Error); - return true; - } catch (EmptyFile e) { - System.err.println("Error: downloadPart emptyFile"); - logger.writeUDP("downloadPart emptyFile", LogLevel.Error); - // TODO: use more specific errors - return true; - } catch (ProtocolError e) { - System.err.println("Error: downloadPart protocolError"); - logger.writeUDP("downloadPart protocolError", LogLevel.Error); - return true; - } catch (InternalRemoteError e) { - System.err.println("Error: downloadPart internalRemoteError"); - logger.writeUDP("downloadPart internalRemoteError", LogLevel.Error); - return true; - } catch (VersionRemoteError e) { - System.err.println("Error: downloadPart versionRemoteError"); - logger.writeUDP("downloadPart versionRemoteError", LogLevel.Error); - return true; - } catch (ProtocolRemoteError e) { - System.err.println("Error: downloadPart protocolRemoteError"); - logger.writeUDP("downloadPart protocolRemoteError", LogLevel.Error); - return true; - } catch (TransmissionError e) { - System.err.println("Error: downloadPart transmissionError"); - logger.writeUDP("downloadPart transmissionError", LogLevel.Error); - return true; - } catch (VersionError e) { - System.err.println("Error: downloadPart versionError"); - logger.writeUDP("downloadPart versionError", LogLevel.Error); - return true; - } catch (SizeError e) { - System.err.println("Error: downloadPart sizeError"); - logger.writeUDP("downloadPart sizeError", LogLevel.Error); - return true; - } catch (NotFound e) { - System.err.println("Error: downloadPart notFound"); - logger.writeUDP("downloadPart notFound", LogLevel.Error); - return true; - } catch (IOException e) { - System.err.println("Error: downloadPart ioexception"); - logger.writeUDP("downloadPart ioexception", LogLevel.Error); - return true; - } catch (InternalError e) { - System.err.println("Error: downloadPart internalError"); - logger.writeUDP("downloadPart internalError", LogLevel.Error); - return true; - } catch (NotATracker e) { - System.err.println("Error: downloadPart notATracker"); - logger.writeUDP("downloadPart notATracker", LogLevel.Error); - return true; - } - return false; + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketUDP(payload); } - } diff --git a/src/clientP2P/ClientDownloadTCP.java b/src/clientP2P/ClientDownloadTCP.java index 3bc8981..5d32835 100644 --- a/src/clientP2P/ClientDownloadTCP.java +++ b/src/clientP2P/ClientDownloadTCP.java @@ -26,10 +26,12 @@ import protocolP2P.HashAlgorithm; import protocolP2P.HashResponse; import protocolP2P.HashRequest; import protocolP2P.ProtocolP2PPacketTCP; +import protocolP2P.ProtocolP2PPacket; import protocolP2P.Payload; import protocolP2P.FilePart; import protocolP2P.LoadRequest; import clientP2P.ClientDownloadPartTCP; +import clientP2P.ClientDownload; import tools.HostItem; import tools.Logger; import tools.LogLevel; @@ -40,407 +42,61 @@ import tools.LogLevel; * @author JS Auge * @version 1.0 */ -public class ClientDownloadTCP implements Runnable { - - private List hostList; - private String filename; - private byte[] hash512; - private List sockList = new ArrayList(); - private List offsetsToAsk = new ArrayList(); - private List offsetsPending = new ArrayList(); - private boolean stop; - private long size; - private static final long MAX_PARTIAL_SIZE = 4096; - private String partsSubdir; - private String dirStorage; - private boolean success = false; - private Logger logger; +public class ClientDownloadTCP extends ClientDownload { /** Constructor with parameters: filename, list of hosts, parts subdirectory and dirStorage * @param filename name of file to download * @param hostList list of servers * @param partsSubdir directory to store .part files * @param dirStorage directory to write assembled file + * @param logger Logger */ public ClientDownloadTCP(String filename, List hostList, String partsSubdir, String dirStorage, Logger logger) { - this.partsSubdir = partsSubdir; - this.dirStorage = dirStorage; - this.filename = filename; - this.hostList = hostList; - this.logger = logger; - this.stop = false; + super(filename, hostList, partsSubdir, dirStorage, logger); } - /** Asks thread to stop + /** Create a clientDownloadPart + * @param filename name of the file to download + * @param hostItem Hostitem of the server */ - public void setStop() { - stop = true; + protected ClientDownloadPart createDownloadPart(String filename, HostItem hostItem) { + return (ClientDownloadPart)new ClientDownloadPartTCP((ClientDownload)this, filename, hostItem.getTCPSocket(), partsSubdir, logger); } - - /** Runnable implementation + + /** Close HostItem socket + * @param hostItem HostItem */ - public void run() { - try { - init(); - if (stop) { - System.err.println("File is smaller than part max size."); - logger.writeTCP("File is smaller than part max size.", LogLevel.Info); - hostList.get(0).closeTCPSocket(); - } else { - System.err.println("File is bigger than part max size."); - logger.writeTCP("File is bigger than part max size.", LogLevel.Info); - purgeList(); - initThreads(); - while(!stop) { - assignTasks(); - checkTasksStatus(); - - } - } - System.err.println("Reassembling file parts."); - logger.writeTCP("Reassembling file parts.", LogLevel.Info); - reassembleFile(); - } catch(InternalError e) { - System.err.println("Error while downloading file. Aborting."); - logger.writeTCP("Error while downloading file. Aborting.", LogLevel.Error); - } finally { - stopTasks(); - } + protected void closeHostItemSocket(HostItem hostItem) { + hostItem.closeTCPSocket(); } - /** Starts threads for each server in hostList. + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - private void initThreads() { - for(HostItem hostItem: hostList) { - sockList.add(new ClientDownloadPartTCP(this, filename, hostItem.getTCPSocket(), partsSubdir, logger)); - } - for(ClientDownloadPartTCP c: sockList) { - Thread t = new Thread(c); - t.start(); - } - System.err.println("Threads initialized"); - logger.writeTCP("Threads initialized", LogLevel.Info); - } - - /** Remove tasks from failed threads. Update done status. - * @throws InternalError - */ - private void checkTasksStatus() throws InternalError { - try { - synchronized(this) { - this.wait(); - List sockListCpy = new ArrayList<>(sockList); - for(ClientDownloadPartTCP c: sockListCpy) { - if (c.hasFailed() == true) { - sockList.remove(c); - offsetsPending.removeAll(c.getFailed()); - offsetsToAsk.addAll(c.getFailed()); - } - try { - offsetsPending.removeAll(c.getDone()); - } catch (InterruptedException e) { - throw new InternalError(); - } - } - System.err.println("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending"); - logger.writeTCP("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending", LogLevel.Info); - if (offsetsToAsk.isEmpty() && offsetsPending.isEmpty()) { - stop = true; - } - if (sockList.size() == 0) { - System.err.println("No thread working"); - logger.writeTCP("No thread working", LogLevel.Error); - throw new InternalError(); - } - } - } catch (InterruptedException e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } - } - - /** Assign tasks randomly to threads. - * @throws InternalError - */ - private void assignTasks() throws InternalError { - Random rand = new Random(); - for(long offset : offsetsToAsk) { - try { - sockList.get(rand.nextInt(sockList.size())).assignTask(offset); - offsetsPending.add(offset); - System.err.println("Assigned task "+ offset); - } catch(InterruptedException e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } - } - offsetsToAsk.removeAll(offsetsPending); - } - - /** Stop threads */ - private void stopTasks() { - for(ClientDownloadPartTCP c : sockList) { - try { - c.setStop(); - } catch (InterruptedException e) { - logger.writeTCP(e, LogLevel.Error); - } - } - } - - /** Get hashsum from server. - * @param hostItem server to ask hash - * @return hash512sum - * @throws InternalError - */ - private byte[] getHashSum512(HostItem hostItem) throws InternalError { - byte[] hash; - HashAlgorithm[] hashesAlgo = new HashAlgorithm[1]; - hashesAlgo[0] = HashAlgorithm.SHA512; - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new HashRequest(filename, hashesAlgo)); - try { - d.sendRequest((Object)hostItem.getTCPSocket()); - try { - Payload pHash = d.receiveResponse().getPayload(); - assert pHash instanceof HashResponse : "This payload must be instance of HashResponse"; - if (!(pHash instanceof HashResponse)) { - throw new InternalError(); - } else { - hash = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512); - } - } catch (EmptyDirectory e) { - logger.writeTCP(e, LogLevel.Error); - hash = new byte[0]; - } catch (NotFound e) { - logger.writeTCP(e, LogLevel.Error); - hash = new byte[0]; - // TODO: use more specific errors - } catch (EmptyFile e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (ProtocolError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (InternalRemoteError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionRemoteError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (ProtocolRemoteError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (TransmissionError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (SizeError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (NotATracker e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } - return hash; - } catch (IOException e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (SocketClosed e){ - System.err.println("getHashSum512 : SocketClosed"); - logger.writeTCP("getHashSum512 : SocketClosed", LogLevel.Error); - throw new InternalError(); - } - } - - /** Removes servers not owning the correct file to download from list. - * This is done by comparing hash512sum. - * @throws InternalError - */ - private void purgeList() throws InternalError { - List blackList = new ArrayList(); - boolean first = false; - byte[] hashsum; - for(HostItem host: hostList) { - // already have hashsum from 1st server - if (!first) { - first = true; - continue; - } - // ask hashsum - hashsum = getHashSum512(host); - if (!Arrays.equals(hash512, hashsum)) { - blackList.add(host); - } - } - // purge list - for(HostItem host: blackList) { - hostList.remove(host); - } - System.err.println("Host list purge: done"); - logger.writeTCP("Host list purge: done", LogLevel.Info); - } - - /** Getter for hash512sum - * @return hash512sum - */ - public byte[] getHashSum512() { - return hash512; - } - - /** Initialize infos about file to download (size, hash512sum, partslist to dl). - * Also download first partfile (to get size). - * @throws InternalError - */ - private void init() throws InternalError { - // get size - setSize(); - - // get hashsum from 1st server in list - hash512 = getHashSum512(hostList.get(0)); - if (hash512.length == 0) { - System.err.println("Error: no hash512sum support."); - logger.writeTCP("no hash512sum support.", LogLevel.Error); - throw new InternalError(); - } - - // Add tasks - if (!stop) { - for(long i=MAX_PARTIAL_SIZE; i d = new ProtocolP2PPacketTCP<>(new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); - try { - d.sendRequest((Object)hostList.get(0).getTCPSocket()); - try { - Payload p = d.receiveResponse().getPayload(); - assert p instanceof FilePart : "This payload must be instance of FilePart"; - if (!(p instanceof FilePart)) { - System.err.println("Error: cannot get size."); - logger.writeTCP("cannot get size.", LogLevel.Error); - throw new InternalError(); - } else { - FilePart fp = (FilePart)p; - if (!fp.getFilename().equals(filename)) { - System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); - logger.writeTCP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); - throw new ProtocolError(); - } - if (fp.getOffset() == 0) { - try { - Files.write(new File(partsSubdir + filename + "_0.part").toPath(), fp.getPartialContent()); - } catch (IOException e) { - System.err.println("Error: cannot write file (" + partsSubdir + filename + "_0.part)"); - logger.writeTCP("cannot write file (" + partsSubdir + filename + "_0.part)", LogLevel.Error); - } - size = fp.getTotalSize(); - if (fp.getPartialContent().length == size) { - stop = true; - } - } else { - System.err.println("Error: wrong file part received."); - logger.writeTCP("wrong file part received.", LogLevel.Error); - throw new InternalError(); - } - } - } catch (EmptyDirectory e) { - System.err.println("Error: empty directory."); - logger.writeTCP("empty directory.", LogLevel.Error); - throw new InternalError(); - } catch (EmptyFile e) { - logger.writeTCP(e, LogLevel.Error); - // TODO: use more specific errors - throw new InternalError(); - } catch (ProtocolError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (InternalRemoteError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionRemoteError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (ProtocolRemoteError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (TransmissionError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (SizeError e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (NotFound e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (NotATracker e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } - } catch (IOException e) { - logger.writeTCP(e, LogLevel.Error); - throw new InternalError(); - } catch (SocketClosed e){ - System.err.println("setSize : SocketClosed"); - logger.writeTCP("setSize : SocketClosed", LogLevel.Error); - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeTCP(e, logLevel); } - /** Success getter. - * @return true when file have successfully been reassembled. + /** Create packets + * @param payload Payload */ - public boolean getSuccess() { - return success; + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketTCP(payload); } - /** Reassemble file from file parts. - * Set success to true if file is reassembled successfully. + /** Getter for HostItem socket + * @param hostItem HostItem */ - private void reassembleFile() { - boolean firstPart = true; - boolean abort = false; - long nextOffset = 0; - do { - if (firstPart) { - System.err.println("Reassembling: First part"); - logger.writeTCP("Reassembling: First part", LogLevel.Info); - try { - // create file - Files.copy(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath(), new File(dirStorage + filename).toPath(), StandardCopyOption.REPLACE_EXISTING); - nextOffset = (new File(dirStorage + filename)).length(); - firstPart = false; - } catch (IOException e) { - System.err.println("Reassembling: aborting on first part"); - logger.writeTCP("Reassembling: aborting on first part", LogLevel.Error); - abort = true; - } - } else if (nextOffset >= size) { - success = true; - System.err.println("Reassembling: success"); - logger.writeTCP("Reassembling: success", LogLevel.Info); - } else { - // append to file - try { - Files.write(new File(dirStorage + filename).toPath(), Files.readAllBytes(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath()), StandardOpenOption.APPEND); - nextOffset = (new File(dirStorage + filename)).length(); - } catch (IOException e) { - abort = true; - System.err.println("Aborting: bad number " + nextOffset); - logger.writeTCP("Aborting: bad number " + nextOffset, LogLevel.Error); - } - } - } while((!success) && (!abort)); + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getTCPSocket(); } } diff --git a/src/clientP2P/ClientDownloadUDP.java b/src/clientP2P/ClientDownloadUDP.java index 9fa14d2..008caaf 100644 --- a/src/clientP2P/ClientDownloadUDP.java +++ b/src/clientP2P/ClientDownloadUDP.java @@ -25,10 +25,12 @@ import protocolP2P.HashAlgorithm; import protocolP2P.HashResponse; import protocolP2P.HashRequest; import protocolP2P.ProtocolP2PPacketUDP; +import protocolP2P.ProtocolP2PPacket; import protocolP2P.Payload; import protocolP2P.FilePart; import protocolP2P.LoadRequest; import clientP2P.ClientDownloadPartUDP; +import clientP2P.ClientDownload; import tools.HostItem; import tools.Logger; import tools.LogLevel; @@ -40,400 +42,61 @@ import tools.LogLevel; * @author JS Auge * @version 1.0 */ -public class ClientDownloadUDP implements Runnable { - - private List hostList; - private String filename; - private byte[] hash512; - private List sockList = new ArrayList(); - private List offsetsToAsk = new ArrayList(); - private List offsetsPending = new ArrayList(); - private boolean stop; - private long size; - private static final long MAX_PARTIAL_SIZE = 4096; - private String partsSubdir; - private String dirStorage; - private boolean success = false; - private Logger logger; +public class ClientDownloadUDP extends ClientDownload { /** Constructor with parameters: filename, list of hosts, parts subdirectory and dirStorage * @param filename name of file to download * @param hostList list of servers * @param partsSubdir directory to store .part files * @param dirStorage directory to write assembled file + * @param logger Logger */ public ClientDownloadUDP(String filename, List hostList, String partsSubdir, String dirStorage, Logger logger) { - this.partsSubdir = partsSubdir; - this.dirStorage = dirStorage; - this.filename = filename; - this.hostList = hostList; - this.logger = logger; - this.stop = false; - } - - /** Asks thread to stop - */ - public void setStop() { - stop = true; - } - - /** Runnable implementation - */ - public void run() { - try { - init(); - if (stop) { - System.err.println("File is smaller than part max size."); - logger.writeUDP("File is smaller than part max size.", LogLevel.Info); - hostList.get(0).closeUDPSocket(); - } else { - System.err.println("File is bigger than part max size."); - logger.writeUDP("File is bigger than part max size.", LogLevel.Info); - purgeList(); - initThreads(); - while(!stop) { - assignTasks(); - checkTasksStatus(); - - } - } - System.err.println("Reassembling file parts."); - logger.writeUDP("Reassembling file parts.", LogLevel.Info); - reassembleFile(); - } catch(InternalError e) { - System.err.println("Error while downloading file. Aborting."); - logger.writeUDP("Error while downloading file. Aborting.", LogLevel.Error); - } finally { - stopTasks(); - } - } - - /** Starts threads for each server in hostList. - */ - private void initThreads() { - for(HostItem hostItem: hostList) { - sockList.add(new ClientDownloadPartUDP(this, filename, hostItem.getUDPSocket(), partsSubdir, logger)); - } - for(ClientDownloadPartUDP c: sockList) { - Thread t = new Thread(c); - t.start(); - } - System.err.println("Threads initialized"); - logger.writeUDP("Threads initialized", LogLevel.Error); - } - - /** Remove tasks from failed threads. Update done status. - * @throws InternalError - */ - private void checkTasksStatus() throws InternalError { - try { - synchronized(this) { - this.wait(); - List sockListCpy = new ArrayList<>(sockList); - for(ClientDownloadPartUDP c: sockListCpy) { - if (c.hasFailed() == true) { - sockList.remove(c); - offsetsPending.removeAll(c.getFailed()); - offsetsToAsk.addAll(c.getFailed()); - } - try { - offsetsPending.removeAll(c.getDone()); - } catch (InterruptedException e) { - throw new InternalError(); - } - } - System.err.println("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending"); - logger.writeUDP("Task check status: " + offsetsToAsk.size() + " to asks, " + offsetsPending.size() + " pending", LogLevel.Info); - if (offsetsToAsk.isEmpty() && offsetsPending.isEmpty()) { - stop = true; - } - if (sockList.size() == 0) { - System.err.println("No thread working"); - logger.writeUDP("No thread working", LogLevel.Error); - throw new InternalError(); - } - } - } catch (InterruptedException e) { - throw new InternalError(); - } - } - - /** Assign tasks randomly to threads. - * @throws InternalError - */ - private void assignTasks() throws InternalError { - Random rand = new Random(); - for(long offset : offsetsToAsk) { - try { - sockList.get(rand.nextInt(sockList.size())).assignTask(offset); - offsetsPending.add(offset); - System.err.println("Assigned task "+ offset); - logger.writeUDP("Assigned task "+ offset, LogLevel.Info); - } catch(InterruptedException e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } - } - offsetsToAsk.removeAll(offsetsPending); - } - - /** Stop threads */ - private void stopTasks() { - for(ClientDownloadPartUDP c : sockList) { - try { - c.setStop(); - } catch (InterruptedException e) { - logger.writeUDP(e, LogLevel.Error); - } - } - } - - /** Get hashsum from server. - * @param hostItem server to ask hash - * @return hash512sum - * @throws InternalError - */ - private byte[] getHashSum512(HostItem hostItem) throws InternalError { - byte[] hash; - HashAlgorithm[] hashesAlgo = new HashAlgorithm[1]; - hashesAlgo[0] = HashAlgorithm.SHA512; - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new HashRequest(filename, hashesAlgo)); - try { - d.sendRequest((Object)hostItem.getUDPSocket()); - try { - Payload pHash = d.receiveResponse().getPayload(); - assert pHash instanceof HashResponse : "This payload must be instance of HashResponse"; - if (!(pHash instanceof HashResponse)) { - throw new InternalError(); - } else { - hash = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512); - } - } catch (EmptyDirectory e) { - logger.writeUDP(e, LogLevel.Error); - hash = new byte[0]; - } catch (NotFound e) { - logger.writeUDP(e, LogLevel.Error); - hash = new byte[0]; - // TODO: use more specific errors - } catch (EmptyFile e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (ProtocolError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (InternalRemoteError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionRemoteError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (ProtocolRemoteError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (TransmissionError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (SizeError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (NotATracker e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } - return hash; - } catch (IOException e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } + super(filename, hostList, partsSubdir, dirStorage, logger); } - /** Removes servers not owning the correct file to download from list. - * This is done by comparing hash512sum. - * @throws InternalError + /** Create a clientDownloadPart + * @param filename name of the file to download + * @param hostItem Hostitem of the server */ - private void purgeList() throws InternalError { - List blackList = new ArrayList(); - boolean first = false; - byte[] hashsum; - for(HostItem host: hostList) { - // already have hashsum from 1st server - if (!first) { - first = true; - continue; - } - // ask hashsum - hashsum = getHashSum512(host); - if (!Arrays.equals(hash512, hashsum)) { - blackList.add(host); - } - } - // purge list - for(HostItem host: blackList) { - hostList.remove(host); - } - System.err.println("Host list purge: done"); - logger.writeUDP("Host list purge: done", LogLevel.Info); + protected ClientDownloadPart createDownloadPart(String filename, HostItem hostItem) { + return (ClientDownloadPart)new ClientDownloadPartUDP((ClientDownload)this, filename, hostItem.getUDPSocket(), partsSubdir, logger); } - /** Getter for hash512sum - * @return hash512sum + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - public byte[] getHashSum512() { - return hash512; + protected void writeLog(String text, LogLevel logLevel) { + logger.writeUDP(text, logLevel); } - /** Initialize infos about file to download (size, hash512sum, partslist to dl). - * Also download first partfile (to get size). - * @throws InternalError + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - private void init() throws InternalError { - // get size - setSize(); - - // get hashsum from 1st server in list - hash512 = getHashSum512(hostList.get(0)); - if (hash512.length == 0) { - System.err.println("Error: no hash512sum support."); - logger.writeUDP("no hash512sum support.", LogLevel.Error); - throw new InternalError(); - } - - // Add tasks - if (!stop) { - for(long i=MAX_PARTIAL_SIZE; i d = new ProtocolP2PPacketUDP<>(new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); - try { - d.sendRequest((Object)hostList.get(0).getUDPSocket()); - try { - Payload p = d.receiveResponse().getPayload(); - assert p instanceof FilePart : "This payload must be instance of FilePart"; - if (!(p instanceof FilePart)) { - System.err.println("Error: cannot get size."); - logger.writeUDP("cannot get size.", LogLevel.Error); - throw new InternalError(); - } else { - FilePart fp = (FilePart)p; - if (!fp.getFilename().equals(filename)) { - System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); - logger.writeUDP("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); - throw new ProtocolError(); - } - if (fp.getOffset() == 0) { - try { - Files.write(new File(partsSubdir + filename + "_0.part").toPath(), fp.getPartialContent()); - } catch (IOException e) { - System.err.println("Error: cannot write file (" + partsSubdir + filename + "_0.part)"); - logger.writeUDP("cannot write file (" + partsSubdir + filename + "_0.part)", LogLevel.Error); - } - size = fp.getTotalSize(); - if (fp.getPartialContent().length == size) { - stop = true; - } - } else { - System.err.println("Error: wrong file part received."); - logger.writeUDP("wrong file part received.", LogLevel.Error); - throw new InternalError(); - } - } - } catch (EmptyDirectory e) { - System.err.println("Error: empty directory."); - logger.writeUDP("empty directory.", LogLevel.Error); - throw new InternalError(); - } catch (EmptyFile e) { - logger.writeUDP(e, LogLevel.Error); - // TODO: use more specific errors - throw new InternalError(); - } catch (ProtocolError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (InternalRemoteError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionRemoteError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (ProtocolRemoteError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (TransmissionError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (VersionError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (SizeError e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (NotFound e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } catch (NotATracker e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } - } catch (IOException e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketUDP(payload); } - /** Success getter. - * @return true when file have successfully been reassembled. + /** Getter for HostItem socket + * @param hostItem HostItem */ - public boolean getSuccess() { - return success; + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getUDPSocket(); } - /** Reassemble file from file parts. - * Set success to true if file is reassembled successfully. + /** Close HostItem socket + * @param hostItem HostItem */ - private void reassembleFile() { - boolean firstPart = true; - boolean abort = false; - long nextOffset = 0; - do { - if (firstPart) { - System.err.println("Reassembling: First part"); - logger.writeUDP("Reassembling: First part", LogLevel.Info); - try { - // create file - Files.copy(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath(), new File(dirStorage + filename).toPath(), StandardCopyOption.REPLACE_EXISTING); - nextOffset = (new File(dirStorage + filename)).length(); - firstPart = false; - } catch (IOException e) { - System.err.println("Reassembling: aborting on first part"); - logger.writeUDP("Reassembling: aborting on first part", LogLevel.Warning); - abort = true; - } - } else if (nextOffset >= size) { - success = true; - System.err.println("Reassembling: success"); - logger.writeUDP("Reassembling: success", LogLevel.Info); - } else { - // append to file - try { - Files.write(new File(dirStorage + filename).toPath(), Files.readAllBytes(new File(partsSubdir + filename + "_" + nextOffset + ".part").toPath()), StandardOpenOption.APPEND); - nextOffset = (new File(dirStorage + filename)).length(); - } catch (IOException e) { - abort = true; - System.err.println("Aborting: bad number " + nextOffset); - logger.writeUDP("Aborting: bad number " + nextOffset, LogLevel.Error); - } - } - } while((!success) && (!abort)); + protected void closeHostItemSocket(HostItem hostItem) { + hostItem.closeUDPSocket(); } } diff --git a/src/clientP2P/ClientManagement.java b/src/clientP2P/ClientManagement.java new file mode 100644 index 0000000..cf1dad8 --- /dev/null +++ b/src/clientP2P/ClientManagement.java @@ -0,0 +1,262 @@ +package clientP2P; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; +import java.util.Scanner; +import java.util.List; +import localException.ProtocolError; +import tools.ServeErrors; +import protocolP2P.RequestResponseCode; +import protocolP2P.FileList; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; +import protocolP2P.Payload; +import protocolP2P.HashAlgorithm; +import localException.InternalError; +import localException.ProtocolError; +import localException.SizeError; +import localException.TransmissionError; +import localException.VersionError; +import localException.SocketClosed; +import remoteException.EmptyFile; +import remoteException.EmptyDirectory; +import remoteException.InternalRemoteError; +import remoteException.NotFound; +import remoteException.ProtocolRemoteError; +import remoteException.VersionRemoteError; +import remoteException.NotATracker; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.net.UnknownHostException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; + + +/** Implementation of P2P-JAVA-PROJECT CLIENT + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public abstract class ClientManagement extends ServeErrors implements Runnable { + protected String baseDirectory; + protected String partsSubdir; + protected List hostList; + protected HostItem tracker; + protected Logger logger; + protected Scanner scanner; + protected ClientDownload downLoader; + + /** Constructor with baseDirectory, tracker, partsSubdir, logger, and scanner parameters. + * @param baseDirectory the root directory where files are stored + * @param tracker Tracker hostItem + * @param partsSubdir subdirectory to store file parts + * @param logger Loggger + * @param scanner Scanner used to read input + */ + public ClientManagement(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) { + this.scanner = scanner; + this.baseDirectory = baseDirectory; + this.tracker = tracker; + this.partsSubdir = partsSubdir; + this.logger = logger; + try { + initHostList(); + } catch (InternalError e) { + System.exit(-1); + } catch (ProtocolError e) { + System.exit(-2); + } + } + + /** Getter for tracker socket + */ + protected abstract Object getTrackerSocket(); + + + /** Initialize hostList from tracker + * @throws ProtocolError + * @throws InternalError + */ + private void initHostList() throws ProtocolError, InternalError { + ProtocolP2PPacket d = createProtocolP2PPacket(new DiscoverRequest(null)); + try { + d.sendRequest(getTrackerSocket()); + Payload p = d.receiveResponse().getPayload(); + assert p instanceof DiscoverResponse : "This payload must be instance of Filelist"; + if (!(p instanceof DiscoverResponse)) { + throw new InternalError(); + } else { + hostList = ((DiscoverResponse)p).getHostList(); + } + } catch (SocketClosed e){ + writeLog("listDirectory : SocketClosed", LogLevel.Error); + throw new ProtocolError(); + } catch (NotATracker e) { + writeLog(e, LogLevel.Error); + throw new ProtocolError(); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + throw new ProtocolError(); + } + } + + /** Compute Hashsum of a file. + * @param filename + * @return hashsum + */ + protected byte[] computeHashsum(String filename, HashAlgorithm h) { + try { + MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); + return md.digest(Files.readAllBytes(Paths.get(baseDirectory + filename))); + } catch (NoSuchAlgorithmException e) { + writeLog(h.getName() + " not supported", LogLevel.Error); + } catch (IOException e) { + writeLog("cannot read " + filename, LogLevel.Error); + } + return new byte[0]; + } + + /** Getter for HostItem socket + * @param hostItem HostItem + */ + protected abstract Object getHostItemSocket(HostItem hostItem); + + /** list server’s directory content + * @return list of files + * @throws InternalError + * @throws UnknowHostException + * @throws IOException + * @throws TransmissionError + * @throws ProtocolError + * @throws VersionError + * @throws SizeError + * @throws EmptyDirectory + * @throws InternalRemoteError + * @throws ProtocolRemoteError + * @throws VersionRemoteError + */ + protected String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { + ProtocolP2PPacket d = createProtocolP2PPacket(new Payload(RequestResponseCode.LIST_REQUEST)); + try { + d.sendRequest(getHostItemSocket(hostList.get(0))); + Payload p = d.receiveResponse().getPayload(); + assert p instanceof FileList : "This payload must be instance of Filelist"; + if (!(p instanceof FileList)) { + throw new InternalError(); + } else { + return ((FileList)p).getFileList(); + } + } catch (NotFound e) { + writeLog(e, LogLevel.Error); + throw new ProtocolError(); + } catch (EmptyFile e) { + writeLog(e, LogLevel.Error); + throw new ProtocolError(); + } catch (SocketClosed e){ + writeLog("listDirectory : SocketClosed", LogLevel.Error); + throw new ProtocolError(); + } catch (NotATracker e) { + writeLog(e, LogLevel.Error); + throw new ProtocolError(); + } + } + + /** Initialize downloader + * @param filename Name of the file to download + */ + protected abstract void initDownloader(String filename); + + /** Try to download a file + * @param filename name of the file to download + * @throws NotFound + * @throws InternalError + * @throws UnknownHostException + * @throws IOException + * @throws TransmissionError + * @throws ProtocolError + * @throws VersionError + * @throws SizeError + * @throws InternalRemoteError + * @throws ProtocolRemoteError + * @throws VersionRemoteError + * @throws EmptyFile + */ + private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { + initDownloader(filename); + Thread t = new Thread(downLoader); + t.start(); + try { + t.join(); + if (downLoader.getSuccess()) { + byte[] hash512 = downLoader.getHashSum512(); + if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) { + writeLog("Hashsum does not match", LogLevel.Error); + String line = "Computed checksum:\n"; + byte[] c = computeHashsum(filename, HashAlgorithm.SHA512); + for (byte b: c) { + line += String.format("%02X", b); + } + line += "\nReceived checksum:\n"; + for (byte b: hash512) { + line += String.format("%02X", b); + } + line += "\n"; + writeLog(line, LogLevel.Info); + throw new InternalError(); + } + } else { + throw new InternalError(); + } + } catch (InterruptedException e) { + throw new InternalError(); + } + } + + /** Implementation of Runnable + */ + public void run() { + try { + 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:"); + String f = scanner.nextLine(); + download(f); + System.out.println("File " + f + " sucessfully downloaded"); + writeLog("File " + f + " sucessfully downloaded", LogLevel.Info); + } catch (EmptyDirectory e) { + writeLog("Server has no file in directory", LogLevel.Error); + } catch (InternalError e) { + writeLog("Client internal error", LogLevel.Error); + } catch (UnknownHostException e) { + writeLog("Server host is unknown", LogLevel.Error); + } catch (IOException e) { + writeLog("Request cannot be send or response cannot be received", LogLevel.Error); + } catch (TransmissionError e) { + writeLog("Message received is too big", LogLevel.Error); + } catch (ProtocolError e) { + writeLog("Cannot decode server’s response", LogLevel.Error); + } catch (VersionError e) { + writeLog("Server’s response use bad version of the protocol", LogLevel.Error); + } catch (SizeError e) { + writeLog("Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); + } catch (InternalRemoteError e) { + writeLog("Server internal error", LogLevel.Error); + } catch (ProtocolRemoteError e) { + writeLog("Server cannot decode client’s request", LogLevel.Error); + } catch (VersionRemoteError e) { + writeLog("Server cannot decode this version of the protocol", LogLevel.Error); + } catch (NotFound e) { + writeLog("Server has not this file in directory", LogLevel.Error); + } catch (EmptyFile e) { + writeLog("File is empty", LogLevel.Error); + } + } + +} diff --git a/src/clientP2P/ClientManagementTCP.java b/src/clientP2P/ClientManagementTCP.java index b5263ec..559fd71 100644 --- a/src/clientP2P/ClientManagementTCP.java +++ b/src/clientP2P/ClientManagementTCP.java @@ -1,38 +1,15 @@ package clientP2P; -import java.net.UnknownHostException; import java.util.Scanner; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.List; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import localException.InternalError; -import localException.ProtocolError; -import localException.SizeError; -import localException.TransmissionError; -import localException.VersionError; -import localException.SocketClosed; -import remoteException.EmptyFile; -import remoteException.EmptyDirectory; -import remoteException.InternalRemoteError; -import remoteException.NotFound; -import remoteException.ProtocolRemoteError; -import remoteException.VersionRemoteError; -import remoteException.NotATracker; -import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.Payload; -import protocolP2P.RequestResponseCode; -import protocolP2P.FileList; -import protocolP2P.HashAlgorithm; -import clientP2P.ClientDownloadTCP; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.ProtocolP2PPacketTCP; import tools.HostItem; import tools.Logger; import tools.LogLevel; -import protocolP2P.DiscoverRequest; -import protocolP2P.DiscoverResponse; +import clientP2P.ClientDownloadTCP; +import clientP2P.ClientManagement; + /** Implementation of P2P-JAVA-PROJECT CLIENT * @author Louis Royer @@ -40,14 +17,7 @@ import protocolP2P.DiscoverResponse; * @author JS Auge * @version 1.0 */ -public class ClientManagementTCP implements Runnable { - private String baseDirectory; - private String partsSubdir; - private List hostList; - private HostItem tracker; - private Logger logger; - private Scanner scanner; - +public class ClientManagementTCP extends ClientManagement { /** Constructor for TCP implementation, with baseDirectory, tracker, partsSubdir, logger, and scanner parameters. * @param baseDirectory the root directory where files are stored * @param tracker Tracker hostItem @@ -56,189 +26,51 @@ public class ClientManagementTCP implements Runnable { * @param scanner Scanner used to read input */ public ClientManagementTCP(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) { - this.scanner = scanner; - this.baseDirectory = baseDirectory; - this.tracker = tracker; - this.partsSubdir = partsSubdir; - this.logger = logger; - try { - initHostList(); - } catch (InternalError e) { - System.exit(-1); - } catch (ProtocolError e) { - System.exit(-2); - } + super(baseDirectory, tracker, partsSubdir, logger, scanner); } - /** Implementation of Runnable + /** Initialize downloader + * @param filename Name of the file to download + */ + protected void initDownloader(String filename) { + downLoader = (ClientDownload) new ClientDownloadTCP(filename, hostList, partsSubdir, baseDirectory, logger); + } + + + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - public void run() { - try { - 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:"); - String f = scanner.nextLine(); - download(f); - System.out.println("File " + f + " sucessfully downloaded"); - logger.writeTCP("File " + f + " sucessfully downloaded", LogLevel.Info); - } catch (EmptyDirectory e) { - logger.writeTCP("Server has no file in directory", LogLevel.Error); - } catch (InternalError e) { - logger.writeTCP("Client internal error", LogLevel.Error); - } catch (UnknownHostException e) { - logger.writeTCP("Server host is unknown", LogLevel.Error); - } catch (IOException e) { - logger.writeTCP("Request cannot be send or response cannot be received", LogLevel.Error); - } catch (TransmissionError e) { - logger.writeTCP("Message received is too big", LogLevel.Error); - } catch (ProtocolError e) { - logger.writeTCP("Cannot decode server’s response", LogLevel.Error); - } catch (VersionError e) { - logger.writeTCP("Server’s response use bad version of the protocol", LogLevel.Error); - } catch (SizeError e) { - logger.writeTCP("Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); - } catch (InternalRemoteError e) { - logger.writeTCP("Server internal error", LogLevel.Error); - } catch (ProtocolRemoteError e) { - logger.writeTCP("Server cannot decode client’s request", LogLevel.Error); - } catch (VersionRemoteError e) { - logger.writeTCP("Server cannot decode this version of the protocol", LogLevel.Error); - } catch (NotFound e) { - logger.writeTCP("Server has not this file in directory", LogLevel.Error); - } catch (EmptyFile e) { - logger.writeTCP("File is empty", LogLevel.Error); - } + protected void writeLog(String text, LogLevel logLevel) { + logger.writeTCP(text, logLevel); } - /** Try to download a file - * @param filename name of the file to download - * @throws NotFound - * @throws InternalError - * @throws UnknownHostException - * @throws IOException - * @throws TransmissionError - * @throws ProtocolError - * @throws VersionError - * @throws SizeError - * @throws InternalRemoteError - * @throws ProtocolRemoteError - * @throws VersionRemoteError - * @throws EmptyFile + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { - ClientDownloadTCP downLoader = new ClientDownloadTCP(filename, hostList, partsSubdir, baseDirectory, logger); - Thread t = new Thread(downLoader); - t.start(); - try { - t.join(); - if (downLoader.getSuccess()) { - byte[] hash512 = downLoader.getHashSum512(); - if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) { - logger.writeTCP("Hashsum does not match", LogLevel.Error); - String line = "Computed checksum:\n"; - byte[] c = computeHashsum(filename, HashAlgorithm.SHA512); - for (byte b: c) { - line += String.format("%02X", b); - } - line += "\nReceived checksum:\n"; - for (byte b: hash512) { - line += String.format("%02X", b); - } - line += "\n"; - logger.writeTCP(line, LogLevel.Info); - throw new InternalError(); - } - } else { - throw new InternalError(); - } - } catch (InterruptedException e) { - throw new InternalError(); - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeTCP(e, logLevel); } - /** list server’s directory content - * @return list of files - * @throws InternalError - * @throws UnknowHostException - * @throws IOException - * @throws TransmissionError - * @throws ProtocolError - * @throws VersionError - * @throws SizeError - * @throws EmptyDirectory - * @throws InternalRemoteError - * @throws ProtocolRemoteError - * @throws VersionRemoteError + /** Create packets + * @param payload Payload */ - private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.LIST_REQUEST)); - try { - d.sendRequest((Object)hostList.get(0).getTCPSocket()); - Payload p = d.receiveResponse().getPayload(); - assert p instanceof FileList : "This payload must be instance of Filelist"; - if (!(p instanceof FileList)) { - throw new InternalError(); - } else { - return ((FileList)p).getFileList(); - } - } catch (NotFound e) { - logger.writeTCP(e, LogLevel.Error); - throw new ProtocolError(); - } catch (EmptyFile e) { - logger.writeTCP(e, LogLevel.Error); - throw new ProtocolError(); - } catch (SocketClosed e){ - logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); - throw new ProtocolError(); - } catch (NotATracker e) { - logger.writeTCP(e, LogLevel.Error); - throw new ProtocolError(); - } + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketTCP(payload); } - /** Compute Hashsum of a file. - * @param filename - * @return hashsum + /** Getter for tracker socket */ - private byte[] computeHashsum(String filename, HashAlgorithm h) { - try { - MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); - return md.digest(Files.readAllBytes(Paths.get(baseDirectory + filename))); - } catch (NoSuchAlgorithmException e) { - logger.writeTCP(h.getName() + " not supported", LogLevel.Error); - } catch (IOException e) { - logger.writeTCP("cannot read " + filename, LogLevel.Error); - } - return new byte[0]; + protected Object getTrackerSocket() { + return (Object)tracker.getTCPSocket(); } - /** Initialize hostList from tracker - * @throws ProtocolError - * @throws InternalError + /** Getter for HostItem socket + * @param hostItem HostItem */ - private void initHostList() throws ProtocolError, InternalError { - ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP<>(new DiscoverRequest(null)); - try { - d.sendRequest((Object)tracker.getTCPSocket()); - Payload p = d.receiveResponse().getPayload(); - assert p instanceof DiscoverResponse : "This payload must be instance of Filelist"; - if (!(p instanceof DiscoverResponse)) { - throw new InternalError(); - } else { - hostList = ((DiscoverResponse)p).getHostList(); - } - } catch (SocketClosed e){ - logger.writeTCP("listDirectory : SocketClosed", LogLevel.Error); - throw new ProtocolError(); - } catch (NotATracker e) { - logger.writeTCP(e, LogLevel.Error); - throw new ProtocolError(); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - throw new ProtocolError(); - } + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getTCPSocket(); } } diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index 1f20484..19e7a0b 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -1,37 +1,14 @@ package clientP2P; import java.util.Scanner; -import java.util.Arrays; -import java.util.List; -import java.io.IOException; -import java.net.UnknownHostException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import localException.InternalError; -import localException.ProtocolError; -import localException.SizeError; -import localException.TransmissionError; -import localException.VersionError; -import remoteException.EmptyFile; -import remoteException.EmptyDirectory; -import remoteException.InternalRemoteError; -import remoteException.NotFound; -import remoteException.ProtocolRemoteError; -import remoteException.VersionRemoteError; -import remoteException.NotATracker; -import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.Payload; -import protocolP2P.RequestResponseCode; -import protocolP2P.FileList; -import protocolP2P.HashAlgorithm; -import protocolP2P.DiscoverRequest; -import protocolP2P.DiscoverResponse; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.ProtocolP2PPacketUDP; import tools.HostItem; import tools.Logger; import tools.LogLevel; import clientP2P.ClientDownloadUDP; +import clientP2P.ClientManagement; /** Implementation of P2P-JAVA-PROJECT CLIENT * @author Louis Royer @@ -39,14 +16,7 @@ import clientP2P.ClientDownloadUDP; * @author JS Auge * @version 1.0 */ -public class ClientManagementUDP implements Runnable { - private String baseDirectory; - private String partsSubdir; - private List hostList; - private HostItem tracker; - private Logger logger; - private Scanner scanner; - +public class ClientManagementUDP extends ClientManagement { /** Constructor for UDP implementation, with baseDirectory, tracker, partsSubdir, logger and scanner parameters. * @param baseDirectory the root directory where files are stored * @param tracker tracker HostItem @@ -55,201 +25,56 @@ public class ClientManagementUDP implements Runnable { * @param scanner Scanner used to read input */ public ClientManagementUDP(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) { - this.scanner = scanner; - this.baseDirectory = baseDirectory; - this.tracker = tracker; - this.partsSubdir = partsSubdir; - this.logger = logger; - try { - initHostList(); - } catch (InternalError e) { - System.exit(-1); - } catch (ProtocolError e) { - System.exit(-2); - } + super(baseDirectory, tracker, partsSubdir, logger, scanner); + } + + /** Initialize downloader + * @param filename Name of the file to download + */ + protected void initDownloader(String filename) { + downLoader = (ClientDownload) new ClientDownloadUDP(filename, hostList, partsSubdir, baseDirectory, logger); + } + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected void writeLog(String text, LogLevel logLevel) { + logger.writeUDP(text, logLevel); } - /** Implementation of Runnable + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - public void run() { - try { - 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:"); - String f = scanner.nextLine(); - download(f); - System.out.println("File " + f + " sucessfully downloaded"); - logger.writeUDP("File " + f + " sucessfully downloaded", LogLevel.Info); - } catch (EmptyDirectory e) { - System.err.println("Error: Server has no file in directory"); - logger.writeUDP("Error: Server has no file in directory", LogLevel.Error); - } catch (InternalError e) { - System.err.println("Error: Client internal error"); - logger.writeUDP("Error: Client internal error", LogLevel.Error); - } catch (UnknownHostException e) { - System.err.println("Error: Server host is unknown"); - logger.writeUDP("Error: Server host is unknown", LogLevel.Error); - } catch (IOException e) { - System.err.println("Error: Request cannot be send or response cannot be received"); - logger.writeUDP("Error: Request cannot be send or response cannot be received", LogLevel.Error); - } catch (TransmissionError e) { - System.err.println("Error: Message received is too big"); - logger.writeUDP("Error: Message received is too big", LogLevel.Error); - } catch (ProtocolError e) { - System.err.println("Error: Cannot decode server’s response"); - logger.writeUDP("Error: Cannot decode server’s response", LogLevel.Error); - } catch (VersionError e) { - System.err.println("Error: Server’s response use bad version of the protocol"); - logger.writeUDP("Error: Server’s response use bad version of the protocol", LogLevel.Error); - } catch (SizeError e) { - System.err.println("Error: Cannot handle this packets because of internal representation limitations of numbers on the client"); - logger.writeUDP("Error: Cannot handle this packets because of internal representation limitations of numbers on the client", LogLevel.Error); - } catch (InternalRemoteError e) { - System.err.println("Error: Server internal error"); - logger.writeUDP("Error: Server internal error", LogLevel.Error); - } catch (ProtocolRemoteError e) { - System.err.println("Error: Server cannot decode client’s request"); - logger.writeUDP("Error: Server cannot decode client’s request", LogLevel.Error); - } catch (VersionRemoteError e) { - System.err.println("Error: Server cannot decode this version of the protocol"); - logger.writeUDP("Error: Server cannot decode this version of the protocol", LogLevel.Error); - } catch (NotFound e) { - System.err.println("Error: Server has not this file in directory"); - logger.writeUDP("Error: Server has not this file in directory", LogLevel.Error); - } catch (EmptyFile e) { - System.err.println("Error: File is empty"); - logger.writeUDP("Error: File is empty", LogLevel.Error); - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeUDP(e, logLevel); } - /** Try to download a file - * @param filename name of the file to download - * @throws NotFound - * @throws InternalError - * @throws UnknownHostException - * @throws IOException - * @throws TransmissionError - * @throws ProtocolError - * @throws VersionError - * @throws SizeError - * @throws InternalRemoteError - * @throws ProtocolRemoteError - * @throws VersionRemoteError - * @throws EmptyFile + /** Create packets + * @param payload Payload */ - private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { - ClientDownloadUDP downLoader = new ClientDownloadUDP(filename, hostList, partsSubdir, baseDirectory, logger); - Thread t = new Thread(downLoader); - t.start(); - try { - t.join(); - if (downLoader.getSuccess()) { - byte[] hash512 = downLoader.getHashSum512(); - if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) { - System.err.println("Error: Hashsum does not match"); - System.err.println("Computed checksum:"); - byte[] c = computeHashsum(filename, HashAlgorithm.SHA512); - for (byte b: c) { - System.err.print(String.format("%02X", b)); - logger.writeUDP("Computed checksum:" + String.format("%02X", b), LogLevel.Info); - } - System.err.println(""); - System.err.println("Received checksum:"); - for (byte b: hash512) { - System.err.print(String.format("%02X", b)); - logger.writeUDP("Received checksum:" + String.format("%02X", b), LogLevel.Info); - } - System.err.println(""); - throw new InternalError(); - } - } else { - throw new InternalError(); - } - } catch (InterruptedException e) { - logger.writeUDP(e, LogLevel.Error); - throw new InternalError(); - } + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketUDP(payload); } - /** list server’s directory content - * @return list of files - * @throws InternalError - * @throws UnknowHostException - * @throws IOException - * @throws TransmissionError - * @throws ProtocolError - * @throws VersionError - * @throws SizeError - * @throws EmptyDirectory - * @throws InternalRemoteError - * @throws ProtocolRemoteError - * @throws VersionRemoteError + /** Getter for tracker socket */ - 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)hostList.get(0).getUDPSocket()); - try { - Payload p = d.receiveResponse().getPayload(); - assert p instanceof FileList : "This payload must be instance of Filelist"; - if (!(p instanceof FileList)) { - throw new InternalError(); - } else { - return ((FileList)p).getFileList(); - } - } catch (NotFound e) { - logger.writeUDP(e, LogLevel.Error); - throw new ProtocolError(); - } catch (EmptyFile e) { - logger.writeUDP(e, LogLevel.Error); - throw new ProtocolError(); - } catch (NotATracker e) { - logger.writeUDP(e, LogLevel.Error); - throw new ProtocolError(); - } + protected Object getTrackerSocket() { + return (Object)tracker.getUDPSocket(); } - /** Compute Hashsum of a file. - * @param filename - * @return hashsum + /** Getter for HostItem socket + * @param hostItem HostItem */ - private byte[] computeHashsum(String filename, HashAlgorithm h) { - try { - MessageDigest md = MessageDigest.getInstance(HashAlgorithm.SHA512.getName()); - return md.digest(Files.readAllBytes(Paths.get(baseDirectory + filename))); - } catch (NoSuchAlgorithmException e) { - System.out.println("Error: " + h.getName() + " not supported"); - logger.writeUDP("Error: " + h.getName() + " not supported", LogLevel.Error); - } catch (IOException e) { - System.out.println("Error: cannot read " + filename); - logger.writeUDP("Error: cannot read " + filename, LogLevel.Error); - } - return new byte[0]; + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getUDPSocket(); } - /** Initialize hostList from tracker - * @throws ProtocolError - * @throws InternalError + /** Close HostItem socket + * @param hostItem HostItem */ - private void initHostList() throws ProtocolError, InternalError { - ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP<>(new DiscoverRequest(null)); - try { - d.sendRequest((Object)tracker.getUDPSocket()); - Payload p = d.receiveResponse().getPayload(); - assert p instanceof DiscoverResponse : "This payload must be instance of Filelist"; - if (!(p instanceof DiscoverResponse)) { - throw new InternalError(); - } else { - hostList = ((DiscoverResponse)p).getHostList(); - } - } catch (NotATracker e) { - logger.writeUDP(e, LogLevel.Error); - throw new ProtocolError(); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - throw new ProtocolError(); - } + protected void closeHostItemSocket(HostItem hostItem) { + hostItem.closeUDPSocket(); } } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index 455cbd3..d44b79a 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -65,10 +65,10 @@ public class ServerManagementTCP extends ServerManagement { try { socket = new ServerSocket(server.getPort(), 10, server.getInetAddress()); } catch (SocketException e) { - logger.writeTCP("Error: cannot listen on " + server, LogLevel.Error); + writeLog("Error: cannot listen on " + server, LogLevel.Error); System.exit(-1); } catch (IOException e) { - logger.writeTCP("Error: cannot openning socket", LogLevel.Error); + writeLog("Error: cannot openning socket", LogLevel.Error); System.exit(-2); } } @@ -77,7 +77,7 @@ public class ServerManagementTCP extends ServerManagement { /** Implementation of runnable. This methods allows to run the server. */ public void run() { - logger.writeTCP("Server sucessfully started", LogLevel.Info); + writeLog("Server sucessfully started", LogLevel.Info); fileListWatcher = (FileWatcher)new FileWatcherTCP(logger, 10000, server, tracker, baseDirectory); // checking every 10 seconds (new Thread(fileListWatcher)).start(); while(!stop) { @@ -86,7 +86,7 @@ public class ServerManagementTCP extends ServerManagement { ClientHandler c = new ClientHandler(s); (new Thread(c)).start(); } catch (IOException e) { - logger.writeTCP("Error while accepting new connection", LogLevel.Warning); + writeLog("Error while accepting new connection", LogLevel.Warning); } } fileListWatcher.setStop(); @@ -109,11 +109,11 @@ public class ServerManagementTCP extends ServerManagement { public void run() { boolean end = false; - logger.writeTCP("[" + addr + "] New connection", LogLevel.Action); + writeLog("[" + addr + "] New connection", LogLevel.Action); do { end = handleClientRequest(); } while(!end); - logger.writeTCP("[" + addr + "] End of connection", LogLevel.Action); + writeLog("[" + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. diff --git a/src/tracker/TrackerManagement.java b/src/tracker/TrackerManagement.java index e28790d..37c3cbc 100644 --- a/src/tracker/TrackerManagement.java +++ b/src/tracker/TrackerManagement.java @@ -19,6 +19,13 @@ import localException.InternalError; import remoteException.EmptyDirectory; import exception.LocalException; + +/** Tracker management implementation + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ public abstract class TrackerManagement extends ServeErrors implements Runnable { protected HostItem tracker; protected Logger logger; diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index bf659f3..d124297 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -46,10 +46,10 @@ public class TrackerManagementTCP extends TrackerManagement { try { socket = new ServerSocket(tracker.getPort(), 10, tracker.getInetAddress()); } catch (SocketException e) { - logger.writeTCP("Error: cannot listen on" + tracker, LogLevel.Error); + writeLog("Error: cannot listen on" + tracker, LogLevel.Error); System.exit(-1); } catch (IOException e) { - logger.writeTCP("Error: cannot open socket", LogLevel.Error); + writeLog("Error: cannot open socket", LogLevel.Error); System.exit(-2); } } @@ -57,14 +57,14 @@ public class TrackerManagementTCP extends TrackerManagement { /** Implementation of runnable. This methods allows to run the server. */ public void run() { - logger.writeTCP("Tracker sucessfully started", LogLevel.Info); + writeLog("Tracker sucessfully started", LogLevel.Info); while (!stop) { try { Socket s = socket.accept(); ClientHandler c = new ClientHandler(s); (new Thread(c)).start(); } catch (IOException e) { - logger.writeTCP("Error while accepting new connection", LogLevel.Warning); + writeLog("Error while accepting new connection", LogLevel.Warning); } } } @@ -86,11 +86,11 @@ public class TrackerManagementTCP extends TrackerManagement { public void run() { boolean end = false; - logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); + writeLog("[ " + addr + "] New connection", LogLevel.Action); do { end = handleClientRequest(); } while(!end); - logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); + writeLog("[ " + addr + "] End of connection", LogLevel.Action); } /** Respond to next request incomming on socket s. @@ -102,12 +102,12 @@ public class TrackerManagementTCP extends TrackerManagement { ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP<>((Object)addr.getTCPSocket()); handleRequest(pd); } catch (IOException e) { - logger.writeTCP(e, LogLevel.Warning); + writeLog(e, LogLevel.Warning); return true; } catch (SocketClosed e) { return true; } catch (LocalException e) { - logger.writeTCP(e, LogLevel.Warning); + writeLog(e, LogLevel.Warning); return true; } return false; From 3edb0bf9e5a3ee9fe1593cdf9d1c76bd863d49f3 Mon Sep 17 00:00:00 2001 From: flavien Date: Sat, 21 Mar 2020 18:13:45 +0100 Subject: [PATCH 27/40] aide tracker --- README.md | 8 +++++- src/clientP2P/ClientP2P.java | 2 +- src/tools/TestPort.java | 27 ++++++++++++++++++ src/tracker/Tracker.java | 40 ++++++++++++++++++++------- src/tracker/TrackerManagementTCP.java | 29 +++++++++---------- 5 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 src/tools/TestPort.java diff --git a/README.md b/README.md index 3a7cac2..822bd25 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ Lien vers le [document original](https://stri-online.net/FTLV/mod/resource/view. **But** : le but de ce projet est de créer une application répartie en Java de téléchargement de fichier en mode P2P (peer to peer ou poste à poste). Les étapes suivantes sont conseillées. +# Usage + +tracker : java -ea tracker.Tracker, to specify port (default localhost:6969, range 6000 -> 6999): java -ea trackerP2P.trackerP2P -- +serveur : java -ea serveurP2P.ServeurP2P, to specify port and tracker (default for server localhost:7070 tracker localhost:6969, range 7000 -> 7999): java -ea serveurP2P.ServeurP2P -- +client/serveur : java -ea clientP2P.ClientP2P -- + ## Étape 1 : Téléchargement à la FTP La première étape doit permettre de télécharger un fichier en intégralité d'une machine vers une autre machine de façon similaire aux applications suivant le protocole FTP. @@ -47,4 +53,4 @@ Options : - Permettre la recherche de fichiers à partir de leur nom ou de toute autre caractéristique. À l'issu de la recherche on devra pouvoir connaître un ensemble d'application possédant le fichier et commencer le téléchargement. - Gérer le protocole d'une application de téléchargement P2P existante (bittorrent, emule ou autre). -Note : toute fonctionnalité supplémentaire ne sera prise en compte dans la notation que si toutes les étapes ont été correctement traitées. \ No newline at end of file +Note : toute fonctionnalité supplémentaire ne sera prise en compte dans la notation que si toutes les étapes ont été correctement traitées. diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 28d1b67..6c2814c 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -73,7 +73,7 @@ public class ClientP2P { */ public static void main(String [] args) { if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ - System.out.println("usage : java -ea clientP2P.ClientP2P -- "); + System.out.println("usage : java -ea clientP2P.ClientP2P -- "); } else{ ClientP2P c; diff --git a/src/tools/TestPort.java b/src/tools/TestPort.java new file mode 100644 index 0000000..9f5e351 --- /dev/null +++ b/src/tools/TestPort.java @@ -0,0 +1,27 @@ +package tools; + +/** Test ports. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class TestPort { + + public boolean testPortServer(int port) { + if((port > 7000) && (port < 7999)){ + return true; + } + return false; + } + + public boolean testPortTracker(int port) { + if((port > 6000) && (port < 6999)){ + return true; + } + return false; + } + + + +} diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 8607610..b274542 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -1,9 +1,12 @@ package tracker; + +import java.util.Scanner; import tracker.TrackerManagementTCP; import tracker.TrackerManagementUDP; import tools.Directories; import tools.Logger; -import java.util.Scanner; +import tools.LogLevel; +import tools.TestPort; /** Tracker implementation * First argument of main method is port listened by the tracker, and is mandatory. @@ -16,6 +19,7 @@ public class Tracker { private int port; private Directories directories; private Logger logger; + private static final int defaultPort = 6969; /** Constructor with portStr containing a port number. * @param portStr String containing port number of listening. @@ -36,15 +40,31 @@ public class Tracker { * @param args parameters */ public static void main(String [] args) { - Tracker t = new Tracker(args[1]); - TrackerManagementUDP tmudp = new TrackerManagementUDP(t.port, t.logger); - TrackerManagementTCP tmtcp = new TrackerManagementTCP(t.port, t.logger); - Thread tudp = new Thread(tmudp); - tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(tmtcp); - ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); - ttcp.start(); + if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ + System.out.println("usage : java -ea trackerP2P.trackerP2P, to specify port (default 6969, range 6000 -> 6999): java -ea trackerP2P.trackerP2P -- "); + } + else{ + Tracker t; + TestPort testPortTracker = new TestPort(); + if(testPortTracker.testPortTracker(Integer.parseInt(args[1]))){ + t = new Tracker(args[1]); + } + else { + System.out.println("Wrong port (6000 -> 6999), using default port 6969"); + t = new Tracker(String.valueOf(defaultPort)); + //t.logger.writeUDP("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); + //t.logger.writeTCP("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); + } + + TrackerManagementUDP tmudp = new TrackerManagementUDP(t.port, t.logger); + TrackerManagementTCP tmtcp = new TrackerManagementTCP(t.port, t.logger); + Thread tudp = new Thread(tmudp); + tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(tmtcp); + ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); + ttcp.start(); + } } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index d124297..064d594 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -1,32 +1,32 @@ package tracker; -import tools.Logger; -import tools.LogLevel; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; +import java.net.UnknownHostException; +import java.net.InetAddress; import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.ProtocolP2PPacket; import protocolP2P.RequestResponseCode; import protocolP2P.Payload; import protocolP2P.Register; import protocolP2P.Unregister; -import tools.HostItem; -import java.util.ArrayList; -import java.util.List; -import java.io.IOException; -import exception.LocalException; -import java.util.Map; -import java.util.HashMap; import protocolP2P.DiscoverRequest; import protocolP2P.DiscoverResponse; import protocolP2P.FileList; -import localException.InternalError; +import exception.LocalException; import remoteException.EmptyDirectory; -import java.net.UnknownHostException; -import java.net.InetAddress; +import localException.InternalError; import localException.SocketClosed; import tracker.TrackerManagement; - +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; /** Tracker management implementation with tcp * @author Louis Royer @@ -114,6 +114,7 @@ public class TrackerManagementTCP extends TrackerManagement { } } + /** Implementation of writeLog * @param text Text to log * @param logLevel level of logging @@ -144,7 +145,7 @@ public class TrackerManagementTCP extends TrackerManagement { protected Object getHostItemSocket(HostItem hostItem) { return (Object)hostItem.getTCPSocket(); } - + /** Close HostItem socket * @param hostItem HostItem */ From 60e0e3a7dab18c4ef471f12625cdf5d75eff511e Mon Sep 17 00:00:00 2001 From: flavien Date: Sat, 21 Mar 2020 19:45:07 +0100 Subject: [PATCH 28/40] modified usage help --- README.md | 6 +++--- src/clientP2P/ClientP2P.java | 2 +- src/serverP2P/ServerP2P.java | 2 +- src/tracker/Tracker.java | 5 ++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 822bd25..866870f 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Les étapes suivantes sont conseillées. # Usage -tracker : java -ea tracker.Tracker, to specify port (default localhost:6969, range 6000 -> 6999): java -ea trackerP2P.trackerP2P -- -serveur : java -ea serveurP2P.ServeurP2P, to specify port and tracker (default for server localhost:7070 tracker localhost:6969, range 7000 -> 7999): java -ea serveurP2P.ServeurP2P -- -client/serveur : java -ea clientP2P.ClientP2P -- +tracker : java tracker.Tracker or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999) +server : java serveurP2P.ServeurP2P or java serveurP2P.ServeurP2P -- (default for server localhost:7070 and tracker localhost:6969, range 7000 -> 7999) +client/serveur : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- (default for integratedServer localhost:7070 and tracker localhost:6969, range 7000 -> 7999) ## Étape 1 : Téléchargement à la FTP diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 6c2814c..e0bd9e3 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -73,7 +73,7 @@ public class ClientP2P { */ public static void main(String [] args) { if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ - System.out.println("usage : java -ea clientP2P.ClientP2P -- "); + System.out.println("usage : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- (default for integratedServer localhost:7070 and tracker localhost:6969, range 7000 -> 7999)"); } else{ ClientP2P c; diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index df0a3f1..7d607b9 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -42,7 +42,7 @@ public class ServerP2P { */ public static void main(String [] args) { if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ - System.out.println("usage : java -ea serveurP2P.ServeurP2P -- "); + System.out.println("usage : java serveurP2P.ServeurP2P or java serveurP2P.ServeurP2P -- (default for server localhost:7070 and tracker localhost:6969, range 7000 -> 7999)"); } else{ ServerP2P s = new ServerP2P(args[1], args[2], args[3]); diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index b274542..2ad06d4 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -41,7 +41,7 @@ public class Tracker { */ public static void main(String [] args) { if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ - System.out.println("usage : java -ea trackerP2P.trackerP2P, to specify port (default 6969, range 6000 -> 6999): java -ea trackerP2P.trackerP2P -- "); + System.out.println("usage : java tracker.Tracker or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999)"); } else{ Tracker t; @@ -52,8 +52,7 @@ public class Tracker { else { System.out.println("Wrong port (6000 -> 6999), using default port 6969"); t = new Tracker(String.valueOf(defaultPort)); - //t.logger.writeUDP("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); - //t.logger.writeTCP("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); + t.logger.write("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); } TrackerManagementUDP tmudp = new TrackerManagementUDP(t.port, t.logger); From f95f4245a58214dbbf4f30f701d3c962577bdf1d Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 23 Mar 2020 16:36:35 +0100 Subject: [PATCH 29/40] simplified cli usage of tracker --- src/tracker/Tracker.java | 63 ++++++++++++++++----------- src/tracker/TrackerManagementTCP.java | 4 +- src/tracker/TrackerManagementUDP.java | 4 +- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 2ad06d4..60ce316 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -19,7 +19,6 @@ public class Tracker { private int port; private Directories directories; private Logger logger; - private static final int defaultPort = 6969; /** Constructor with portStr containing a port number. * @param portStr String containing port number of listening. @@ -36,34 +35,48 @@ public class Tracker { /** Main program entry point * first parameter is port number and is mandatory - * to test, run with: java -ea serverP2P.ServerP2P -- + * to test, run with: java -ea serverP2P.ServerP2P * @param args parameters */ public static void main(String [] args) { - if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ - System.out.println("usage : java tracker.Tracker or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999)"); + final String defaultPort = "6969"; + final String defaultHostname = "localhost"; + Scanner scanner = new Scanner(System.in); + Tracker t; + + System.out.println("Tracker Server, enter hostname to bind : "); + String hostname = scanner.nextLine(); + if(hostname.equals("")){ + hostname = defaultHostname; + System.out.println("using default hostname : " + hostname); + } else{ + System.out.println("using hostname : " + hostname); + } + System.out.println("enter port : "); + String port = scanner.nextLine(); + if(port.equals("")){ + port = defaultPort; + System.out.println("using default port : " + port); + } else { + System.out.println("using port : " + hostname); + } + TestPort testPortTracker = new TestPort(); + if(testPortTracker.testPortTracker(Integer.parseInt(port))){ + t = new Tracker(port); + } + else { + System.out.println("Wrong port (6000 -> 6999), using default port 6969"); + t = new Tracker(defaultPort); + t.logger.write("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); } - else{ - Tracker t; - TestPort testPortTracker = new TestPort(); - if(testPortTracker.testPortTracker(Integer.parseInt(args[1]))){ - t = new Tracker(args[1]); - } - else { - System.out.println("Wrong port (6000 -> 6999), using default port 6969"); - t = new Tracker(String.valueOf(defaultPort)); - t.logger.write("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); - } - TrackerManagementUDP tmudp = new TrackerManagementUDP(t.port, t.logger); - TrackerManagementTCP tmtcp = new TrackerManagementTCP(t.port, t.logger); - Thread tudp = new Thread(tmudp); - tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(tmtcp); - ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); - ttcp.start(); + TrackerManagementUDP tmudp = new TrackerManagementUDP(hostname, t.port, t.logger); + TrackerManagementTCP tmtcp = new TrackerManagementTCP(hostname, t.port, t.logger); + Thread tudp = new Thread(tmudp); + tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(tmtcp); + ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); + ttcp.start(); } - } - } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index 064d594..afba7bd 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -41,8 +41,8 @@ public class TrackerManagementTCP extends TrackerManagement { * @param port Port used to listen. * @param logger Logger object */ - public TrackerManagementTCP(int port, Logger logger) { - super(new HostItem("localhost", port), logger); + public TrackerManagementTCP(String hostname, int port, Logger logger) { + super(new HostItem(hostname, port), logger); try { socket = new ServerSocket(tracker.getPort(), 10, tracker.getInetAddress()); } catch (SocketException e) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 6ed2235..6a07bcb 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -37,8 +37,8 @@ public class TrackerManagementUDP extends TrackerManagement { * @param port Port used to listen. * @param logger Logger object */ - public TrackerManagementUDP(int port, Logger logger) { - super(new HostItem("localhost", port), logger); + public TrackerManagementUDP(String hostname, int port, Logger logger) { + super(new HostItem(hostname, port), logger); try { socket = new DatagramSocket(tracker.getPort(), tracker.getInetAddress()); } catch (SocketException e) { From 2313b6799d309259d5c34d6b721292b9e3ad45a0 Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 23 Mar 2020 16:42:23 +0100 Subject: [PATCH 30/40] added commentary on default options --- src/tracker/Tracker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 60ce316..1dc03cd 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -44,7 +44,7 @@ public class Tracker { Scanner scanner = new Scanner(System.in); Tracker t; - System.out.println("Tracker Server, enter hostname to bind : "); + System.out.println("Tracker Server, enter hostname to bind (default = localhost): "); String hostname = scanner.nextLine(); if(hostname.equals("")){ hostname = defaultHostname; @@ -52,7 +52,7 @@ public class Tracker { } else{ System.out.println("using hostname : " + hostname); } - System.out.println("enter port : "); + System.out.println("enter port (default = 6969): "); String port = scanner.nextLine(); if(port.equals("")){ port = defaultPort; From 90872c8f7b697d5c0f520dc6934d1ad1c2f7ff77 Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 23 Mar 2020 16:55:46 +0100 Subject: [PATCH 31/40] changed a variable in display --- src/tracker/Tracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 1dc03cd..364ab73 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -58,7 +58,7 @@ public class Tracker { port = defaultPort; System.out.println("using default port : " + port); } else { - System.out.println("using port : " + hostname); + System.out.println("using port : " + port); } TestPort testPortTracker = new TestPort(); if(testPortTracker.testPortTracker(Integer.parseInt(port))){ From 226520e209aad5c5347e0fa5def4c06f19a5582a Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 23 Mar 2020 17:15:03 +0100 Subject: [PATCH 32/40] simplified cli usage of server --- src/serverP2P/ServerP2P.java | 78 +++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index 7d607b9..82dead1 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -1,10 +1,13 @@ package serverP2P; + +import java.util.Scanner; import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; import tools.Directories; import tools.Logger; import tools.HostItem; -import java.util.Scanner; +import tools.TestPort; + /** Server only implementation * First argument of main method is port listened by the server, and is mandatory. @@ -37,23 +40,70 @@ public class ServerP2P { /** Main program entry point * first parameter is port number and is mandatory - * to test, run with: java -ea serverP2P.ServerP2P -- + * to test, run with: java -ea serverP2P.ServerP2P * @param args parameters */ public static void main(String [] args) { - if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ - System.out.println("usage : java serveurP2P.ServeurP2P or java serveurP2P.ServeurP2P -- (default for server localhost:7070 and tracker localhost:6969, range 7000 -> 7999)"); + final String defaultHostname = "localhost"; + final String defaultPortServer = "7070"; + final String defaultPortTracker = "6969"; + Scanner scanner = new Scanner(System.in); + TestPort testPort = new TestPort(); + + System.out.println("Server, enter hostname to bind (default = localhost): "); + String hostnameServer = scanner.nextLine(); + if(hostnameServer.equals("")){ + hostnameServer = defaultHostname; + System.out.println("using default hostname : " + hostnameServer); + } else{ + System.out.println("using hostname : " + hostnameServer); + } + System.out.println("enter port (default = 7070): "); + String portServer = scanner.nextLine(); + if(portServer.equals("")){ + portServer = defaultPortServer; + System.out.println("using default port : " + portServer); } - else{ - ServerP2P s = new ServerP2P(args[1], args[2], args[3]); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, "localhost", s.port, s.logger, s.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, "localhost", s.port, s.logger, s.tracker); - Thread tudp = new Thread(smudp); - tudp.setName("server UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(smtcp); - ttcp.setName("server TCP P2P-JAVA-PROJECT"); - ttcp.start(); + else { + if(!testPort.testPortServer(Integer.parseInt(portServer))){ + System.out.println("Wrong port (7000 -> 7999), using default port 7070"); + portServer = defaultPortServer; + } else { + System.out.println("using port : " + portServer); + } } + + System.out.println("enter hostname of tracker (default = localhost): "); + String hostnameTracker = scanner.nextLine(); + if(hostnameTracker.equals("")){ + hostnameTracker = defaultHostname; + System.out.println("tracker default hostname : " + hostnameTracker); + } else{ + System.out.println("tracker hostname : " + hostnameTracker); + } + System.out.println("enter tracker's port (default = 6969): "); + String portTracker = scanner.nextLine(); + if(portTracker.equals("")){ + portTracker = defaultPortTracker; + System.out.println("using default port : " + portTracker); + } + else { + if(!testPort.testPortTracker(Integer.parseInt(portTracker))){ + System.out.println("Wrong port (6000 -> 6999), using default port 6969"); + portTracker = defaultPortTracker; + } else { + System.out.println("using port : " + portTracker); + } + } + + ServerP2P s = new ServerP2P(portServer, hostnameTracker, portTracker); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); + Thread tudp = new Thread(smudp); + tudp.setName("server UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(smtcp); + ttcp.setName("server TCP P2P-JAVA-PROJECT"); + ttcp.start(); } } From a0cbd9ef1423b6fd4ed2e109a3e66dc15a088b4a Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 23 Mar 2020 17:18:59 +0100 Subject: [PATCH 33/40] updated usage of programs in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 866870f..4c5d6d8 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Les étapes suivantes sont conseillées. # Usage -tracker : java tracker.Tracker or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999) -server : java serveurP2P.ServeurP2P or java serveurP2P.ServeurP2P -- (default for server localhost:7070 and tracker localhost:6969, range 7000 -> 7999) -client/serveur : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- (default for integratedServer localhost:7070 and tracker localhost:6969, range 7000 -> 7999) +tracker : java tracker.Tracker +server : java serveurP2P.ServeurP2P +client/serveur : java clientP2P.ClientP2P ## Étape 1 : Téléchargement à la FTP From 9c5bfc5430ac353fe5d4be620f73ea6de24f7110 Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 23 Mar 2020 18:07:26 +0100 Subject: [PATCH 34/40] added a method to test if hostnames are legitimate --- src/tools/TestLegitIP.java | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/tools/TestLegitIP.java diff --git a/src/tools/TestLegitIP.java b/src/tools/TestLegitIP.java new file mode 100644 index 0000000..aa271f3 --- /dev/null +++ b/src/tools/TestLegitIP.java @@ -0,0 +1,28 @@ +package tools; + +/** Test if IP are legitimate. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class TestLegitIP { + + public boolean TestIP(String hostname) { + if(hostname.equals("localhost")){ + return true; + } + else{ + String[] ipArray = hostname.split("\\."); + if(ipArray.length != 4){ + return false; + } + for(int i= 0; i < ipArray.length; i++){ + if((Integer.parseInt(ipArray[i]) > 255) || (Integer.parseInt(ipArray[i]) < 0)){ + return false; + } + } + } + return true; + } +} From d0eff567f54d9edf7dcc421c111c131cee8e3340 Mon Sep 17 00:00:00 2001 From: flavien Date: Mon, 23 Mar 2020 18:08:21 +0100 Subject: [PATCH 35/40] added support for tools/testlegitip --- src/tracker/Tracker.java | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 364ab73..7923024 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -7,6 +7,7 @@ import tools.Directories; import tools.Logger; import tools.LogLevel; import tools.TestPort; +import tools.TestLegitIP; /** Tracker implementation * First argument of main method is port listened by the tracker, and is mandatory. @@ -42,16 +43,20 @@ public class Tracker { final String defaultPort = "6969"; final String defaultHostname = "localhost"; Scanner scanner = new Scanner(System.in); + TestLegitIP testLegitIP = new TestLegitIP(); + TestPort testPortTracker = new TestPort(); Tracker t; - System.out.println("Tracker Server, enter hostname to bind (default = localhost): "); - String hostname = scanner.nextLine(); - if(hostname.equals("")){ - hostname = defaultHostname; - System.out.println("using default hostname : " + hostname); - } else{ - System.out.println("using hostname : " + hostname); - } + do{ + System.out.println("Tracker Server, enter hostname to bind (default = localhost): "); + String hostname = scanner.nextLine(); + if(hostname.equals("")){ + hostname = defaultHostname; + System.out.println("using default hostname : " + hostname); + } + } while (!testLegitIP.TestIP(hostname)) + System.out.println("using hostname : " + hostname); + System.out.println("enter port (default = 6969): "); String port = scanner.nextLine(); if(port.equals("")){ @@ -60,7 +65,6 @@ public class Tracker { } else { System.out.println("using port : " + port); } - TestPort testPortTracker = new TestPort(); if(testPortTracker.testPortTracker(Integer.parseInt(port))){ t = new Tracker(port); } From d4bcff6f8c80f03e4a4dc91f67202aa2115245ec Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 24 Mar 2020 11:32:42 +0100 Subject: [PATCH 36/40] retrieve support for agurments --- src/tools/TestLegitIP.java | 28 -------------- src/tracker/Tracker.java | 78 +++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 62 deletions(-) delete mode 100644 src/tools/TestLegitIP.java diff --git a/src/tools/TestLegitIP.java b/src/tools/TestLegitIP.java deleted file mode 100644 index aa271f3..0000000 --- a/src/tools/TestLegitIP.java +++ /dev/null @@ -1,28 +0,0 @@ -package tools; - -/** Test if IP are legitimate. - * @author Louis Royer - * @author Flavien Haas - * @author JS Auge - * @version 1.0 - */ -public class TestLegitIP { - - public boolean TestIP(String hostname) { - if(hostname.equals("localhost")){ - return true; - } - else{ - String[] ipArray = hostname.split("\\."); - if(ipArray.length != 4){ - return false; - } - for(int i= 0; i < ipArray.length; i++){ - if((Integer.parseInt(ipArray[i]) > 255) || (Integer.parseInt(ipArray[i]) < 0)){ - return false; - } - } - } - return true; - } -} diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 7923024..b81a671 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -7,7 +7,6 @@ import tools.Directories; import tools.Logger; import tools.LogLevel; import tools.TestPort; -import tools.TestLegitIP; /** Tracker implementation * First argument of main method is port listened by the tracker, and is mandatory. @@ -43,44 +42,55 @@ public class Tracker { final String defaultPort = "6969"; final String defaultHostname = "localhost"; Scanner scanner = new Scanner(System.in); - TestLegitIP testLegitIP = new TestLegitIP(); TestPort testPortTracker = new TestPort(); + String hostname; + String port; Tracker t; - do{ - System.out.println("Tracker Server, enter hostname to bind (default = localhost): "); - String hostname = scanner.nextLine(); - if(hostname.equals("")){ - hostname = defaultHostname; - System.out.println("using default hostname : " + hostname); - } - } while (!testLegitIP.TestIP(hostname)) - System.out.println("using hostname : " + hostname); + System.out.println("args.lenght : " + args.length); - System.out.println("enter port (default = 6969): "); - String port = scanner.nextLine(); - if(port.equals("")){ - port = defaultPort; - System.out.println("using default port : " + port); - } else { - System.out.println("using port : " + port); - } - if(testPortTracker.testPortTracker(Integer.parseInt(port))){ - t = new Tracker(port); - } - else { - System.out.println("Wrong port (6000 -> 6999), using default port 6969"); - t = new Tracker(defaultPort); - t.logger.write("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); + if ((args.length != 3) && (args.length != 0)){ + System.out.println("usage : java tracker.Tracker or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999)"); } + else{ + if(args.length == 3){ + hostname = args[1]; + port = args[2]; + } + else{ + System.out.println("Tracker Server, enter hostname to bind (default = localhost): "); + hostname = scanner.nextLine(); + if(hostname.equals("")){ + hostname = defaultHostname; + System.out.println("using default hostname : " + hostname); + } + System.out.println("enter port (default = 6969): "); + port = scanner.nextLine(); + if(port.equals("")){ + port = defaultPort; + System.out.println("using default port : " + port); + } + } - TrackerManagementUDP tmudp = new TrackerManagementUDP(hostname, t.port, t.logger); - TrackerManagementTCP tmtcp = new TrackerManagementTCP(hostname, t.port, t.logger); - Thread tudp = new Thread(tmudp); - tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(tmtcp); - ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); - ttcp.start(); + System.out.println("using hostname : " + hostname); + if(testPortTracker.testPortTracker(Integer.parseInt(port))){ + System.out.println("using port : " + port); + t = new Tracker(port); + } + else { + System.out.println("Wrong port (6000 -> 6999), using default port 6969"); + t = new Tracker(defaultPort); + t.logger.write("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); + } + + TrackerManagementUDP tmudp = new TrackerManagementUDP(hostname, t.port, t.logger); + TrackerManagementTCP tmtcp = new TrackerManagementTCP(hostname, t.port, t.logger); + Thread tudp = new Thread(tmudp); + tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(tmtcp); + ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); + ttcp.start(); + } } } From 702fb399c38b3d9c0f044bca61fb85718461f7bb Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 24 Mar 2020 12:11:06 +0100 Subject: [PATCH 37/40] return testport in method --- src/tools/TestPort.java | 11 +++++++---- src/tracker/Tracker.java | 10 ++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/tools/TestPort.java b/src/tools/TestPort.java index 9f5e351..8a31892 100644 --- a/src/tools/TestPort.java +++ b/src/tools/TestPort.java @@ -1,5 +1,7 @@ package tools; +import javafx.util.Pair; + /** Test ports. * @author Louis Royer * @author Flavien Haas @@ -8,18 +10,19 @@ package tools; */ public class TestPort { - public boolean testPortServer(int port) { + public boolean testPortServer(int port, String message) { if((port > 7000) && (port < 7999)){ return true; } + message = message + "Wrong port (7000 -> 7999), using default port 7070"; return false; } - public boolean testPortTracker(int port) { + public Pair testPortTracker(int port) { if((port > 6000) && (port < 6999)){ - return true; + return new Pair<>(0,""); } - return false; + return new Pair<>(1, "Wrong port (6000 -> 6999), using default port 6969"); } diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index b81a671..53658e1 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -1,6 +1,7 @@ package tracker; import java.util.Scanner; +import javafx.util.Pair; import tracker.TrackerManagementTCP; import tracker.TrackerManagementUDP; import tools.Directories; @@ -42,7 +43,7 @@ public class Tracker { final String defaultPort = "6969"; final String defaultHostname = "localhost"; Scanner scanner = new Scanner(System.in); - TestPort testPortTracker = new TestPort(); + TestPort testPort = new TestPort(); String hostname; String port; Tracker t; @@ -73,14 +74,15 @@ public class Tracker { } System.out.println("using hostname : " + hostname); - if(testPortTracker.testPortTracker(Integer.parseInt(port))){ + Pair PtestPortTracker = testPort.testPortTracker(Integer.parseInt(port)); + if(PtestPortTracker.getKey() == 0){ System.out.println("using port : " + port); t = new Tracker(port); } else { - System.out.println("Wrong port (6000 -> 6999), using default port 6969"); + System.out.println(PtestPortTracker.getValue()); t = new Tracker(defaultPort); - t.logger.write("Wrong port (6000 -> 6999), using default port 6969", LogLevel.Warning); + t.logger.write(PtestPortTracker.getValue(), LogLevel.Warning); } TrackerManagementUDP tmudp = new TrackerManagementUDP(hostname, t.port, t.logger); From 387a487d8370f1b6c54fc0f173d8a177af9b50ee Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 24 Mar 2020 14:00:24 +0100 Subject: [PATCH 38/40] reintroduce usage of arguments in serverP2P --- src/serverP2P/ServerP2P.java | 115 ++++++++++++++++++++--------------- src/tools/TestPort.java | 7 +-- src/tracker/Tracker.java | 4 +- 3 files changed, 70 insertions(+), 56 deletions(-) diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index 82dead1..04b3fbc 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -1,6 +1,7 @@ package serverP2P; import java.util.Scanner; +import javafx.util.Pair; import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; import tools.Directories; @@ -47,63 +48,79 @@ public class ServerP2P { final String defaultHostname = "localhost"; final String defaultPortServer = "7070"; final String defaultPortTracker = "6969"; + String hostnameServer = ""; + String portServer = ""; + String hostnameTracker = ""; + String portTracker = ""; Scanner scanner = new Scanner(System.in); TestPort testPort = new TestPort(); - System.out.println("Server, enter hostname to bind (default = localhost): "); - String hostnameServer = scanner.nextLine(); - if(hostnameServer.equals("")){ - hostnameServer = defaultHostname; - System.out.println("using default hostname : " + hostnameServer); - } else{ - System.out.println("using hostname : " + hostnameServer); - } - System.out.println("enter port (default = 7070): "); - String portServer = scanner.nextLine(); - if(portServer.equals("")){ - portServer = defaultPortServer; - System.out.println("using default port : " + portServer); + if ((args.length != 5) && (args.length != 0)){ + System.out.println("usage : java serveurP2P.ServeurP2P (interactive) or java serveurP2P.ServeurP2P -- "); } - else { - if(!testPort.testPortServer(Integer.parseInt(portServer))){ - System.out.println("Wrong port (7000 -> 7999), using default port 7070"); - portServer = defaultPortServer; - } else { - System.out.println("using port : " + portServer); + else{ + if(args.length == 5){ + hostnameServer = args[1]; + portServer = args[2]; + hostnameTracker = args[3]; + portTracker = args[4]; + } + else{ + System.out.println("Server, enter hostname to bind (default = localhost): "); + hostnameServer = scanner.nextLine(); + if(hostnameServer.equals("")){ + hostnameServer = defaultHostname; + System.out.println("using default hostname : " + hostnameServer); + } + System.out.println("enter port (default = 7070): "); + portServer = scanner.nextLine(); + if(portServer.equals("")){ + portServer = defaultPortServer; + System.out.println("using default port : " + portServer); + } + System.out.println("enter hostname of tracker (default = localhost): "); + hostnameTracker = scanner.nextLine(); + if(hostnameTracker.equals("")){ + hostnameTracker = defaultHostname; + System.out.println("tracker default hostname : " + hostnameTracker); + } + System.out.println("enter tracker's port (default = 6969): "); + portTracker = scanner.nextLine(); + if(portTracker.equals("")){ + portTracker = defaultPortTracker; + System.out.println("using default port : " + portTracker); + } } - } - System.out.println("enter hostname of tracker (default = localhost): "); - String hostnameTracker = scanner.nextLine(); - if(hostnameTracker.equals("")){ - hostnameTracker = defaultHostname; - System.out.println("tracker default hostname : " + hostnameTracker); - } else{ + System.out.println("using hostname : " + hostnameServer); + Pair PtestPortServer = testPort.testPortServer(Integer.parseInt(portServer)); + if(PtestPortServer.getKey() == 0){ + System.out.println("using port : " + portServer); + } + else { + System.out.println(PtestPortServer.getValue()); + portServer = defaultPortServer; + } System.out.println("tracker hostname : " + hostnameTracker); - } - System.out.println("enter tracker's port (default = 6969): "); - String portTracker = scanner.nextLine(); - if(portTracker.equals("")){ - portTracker = defaultPortTracker; - System.out.println("using default port : " + portTracker); - } - else { - if(!testPort.testPortTracker(Integer.parseInt(portTracker))){ - System.out.println("Wrong port (6000 -> 6999), using default port 6969"); - portTracker = defaultPortTracker; - } else { + + Pair PtestPortTracker = testPort.testPortTracker(Integer.parseInt(portTracker)); + if(PtestPortTracker.getKey() == 0){ System.out.println("using port : " + portTracker); } - } + else { + System.out.println(PtestPortTracker.getValue()); + portTracker = defaultPortTracker; + } - ServerP2P s = new ServerP2P(portServer, hostnameTracker, portTracker); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); - Thread tudp = new Thread(smudp); - tudp.setName("server UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(smtcp); - ttcp.setName("server TCP P2P-JAVA-PROJECT"); - ttcp.start(); - } + ServerP2P s = new ServerP2P(portServer, hostnameTracker, portTracker); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); + Thread tudp = new Thread(smudp); + tudp.setName("server UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(smtcp); + ttcp.setName("server TCP P2P-JAVA-PROJECT"); + ttcp.start(); + } + } } diff --git a/src/tools/TestPort.java b/src/tools/TestPort.java index 8a31892..ae71813 100644 --- a/src/tools/TestPort.java +++ b/src/tools/TestPort.java @@ -10,12 +10,11 @@ import javafx.util.Pair; */ public class TestPort { - public boolean testPortServer(int port, String message) { + public Pair testPortServer(int port) { if((port > 7000) && (port < 7999)){ - return true; + return new Pair<>(0,""); } - message = message + "Wrong port (7000 -> 7999), using default port 7070"; - return false; + return new Pair<>(1, "Wrong port (7000 -> 7999), using default port 7070"); } public Pair testPortTracker(int port) { diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 53658e1..787923c 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -48,10 +48,8 @@ public class Tracker { String port; Tracker t; - System.out.println("args.lenght : " + args.length); - if ((args.length != 3) && (args.length != 0)){ - System.out.println("usage : java tracker.Tracker or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999)"); + System.out.println("usage : java tracker.Tracker (interactive) or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999)"); } else{ if(args.length == 3){ From 64032e84c435d0261e443089bad941e0dfe5c697 Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 24 Mar 2020 16:04:10 +0100 Subject: [PATCH 39/40] finished work --- README.md | 6 +- src/clientP2P/ClientP2P.java | 141 +++++++++++++++++++++++------------ src/serverP2P/ServerP2P.java | 26 +++---- src/tools/TestPort.java | 10 ++- src/tracker/Tracker.java | 7 +- 5 files changed, 121 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 4c5d6d8..00e9a8c 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Les étapes suivantes sont conseillées. # Usage -tracker : java tracker.Tracker -server : java serveurP2P.ServeurP2P -client/serveur : java clientP2P.ClientP2P +tracker : java tracker.Tracker (interactive) or java trackerP2P.trackerP2P -- (default port 6969 (range 6000 -> 6999)) +server : java serveurP2P.ServeurP2P (interactive) or java serveurP2P.ServeurP2P -- (default server port: server 7070 (range 7000->7070) and tracker port 6969 (range 7000 -> 7999)) +client/serveur : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- (default tracker port 6969 (range 7000 -> 7999) and server port: server 7070 (range 7000->7070)) ## Étape 1 : Téléchargement à la FTP diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index e0bd9e3..c42aa9a 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -2,14 +2,17 @@ package clientP2P; import java.util.Scanner; import java.util.List; +import javafx.util.Pair; import clientP2P.ClientManagementUDP; import clientP2P.ClientManagementTCP; + import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; import tools.Logger; import tools.LogLevel; import tools.Directories; import tools.HostItem; +import tools.TestPort; /** Client + Server implementation. * @author Louis Royer @@ -23,20 +26,17 @@ public class ClientP2P { private String partsDir = ".parts/"; private Logger loggerServer; private Logger loggerClient; - private String host; - private int port; + private int portServer; private Directories directories; - private static final int defaultPort = 20000; private HostItem tracker; private Scanner scanner; - /** Initialize loggers if directories and logger are null, * else fail silently. */ public void initDirectoriesAndLoggers() { if (directories == null && loggerServer == null && loggerClient == null) { - directories = new Directories("P2P_JAVA_PROJECT_" + port); + directories = new Directories("P2P_JAVA_PROJECT_" + portServer); directories.createSubdir(logDir); loggerServer = new Logger(directories.getDataHomeDirectory() + logDir + "server.log"); loggerClient = new Logger(directories.getDataHomeDirectory() + logDir + "client.log"); @@ -44,26 +44,16 @@ public class ClientP2P { } } - /** Constructor with portStr as parameter. - * @param portStr String containing port for server listenning. + /** Constructor with portServerstr as parameter. + * @param portServerstr String containing port for server listenning. */ - public ClientP2P(String portStr) { + public ClientP2P(String portServerstr, String hostnameTracker, String portTracker) { scanner = new Scanner(System.in); - tracker = new HostItem("localhost", 30000); // TODO : make it configurable - try{ - port = Integer.valueOf(Integer.parseInt(portStr)); - } catch (NumberFormatException e){ - int oldPort = port; - port = defaultPort; - initDirectoriesAndLoggers(); - System.err.println("Error incorrect port " + oldPort + " using default port " + defaultPort); - loggerServer.write("incorrect port " + oldPort + " using default port " + defaultPort, LogLevel.Info); - } + portServer = Integer.valueOf(Integer.parseInt(portServerstr)); + tracker = new HostItem(hostnameTracker, Integer.valueOf(Integer.parseInt(portTracker))); initDirectoriesAndLoggers(); - host = "localhost"; - System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory()); + System.out.println("Server will listen on port " + portServer + " and serve files from " + directories.getDataHomeDirectory()); directories.askOpenDataHomeDirectory(null, scanner); - System.out.println("Please enter list of servers to use; first one will be used to ask list of files"); } /** Main program entry point. @@ -72,25 +62,86 @@ public class ClientP2P { * @param args server listenning port */ public static void main(String [] args) { - if (args[1].equals("help") || args[1].equals("-h") || args[1].equals("h")){ - System.out.println("usage : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- (default for integratedServer localhost:7070 and tracker localhost:6969, range 7000 -> 7999)"); + final String defaultHostname = "localhost"; + final String defaultPortServer = "7070"; + final String defaultPortTracker = "6969"; + String hostnameServer = ""; + String portServer = ""; + String hostnameTracker = ""; + String portTracker = ""; + String protocolClient = ""; + Scanner scanner = new Scanner(System.in); + TestPort testPort = new TestPort(); + + if ((args.length != 6) && (args.length != 0)){ + System.out.println("usage : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- (default tracker port 6969 (range 7000 -> 7999) and server port: server 7070 (range 7000->7070))"); } else{ - ClientP2P c; - try { - c = new ClientP2P(args[1]); - } catch (IndexOutOfBoundsException e){ - c = new ClientP2P("" + defaultPort); + if(args.length == 6){ + protocolClient = args[1]; + hostnameServer = args[2]; + portServer = args[3]; + hostnameTracker = args[4]; + portTracker = args[5]; + } + else{ + System.out.println("Client, wich transport protocol do you want to use (default = TCP): "); + protocolClient = scanner.nextLine(); + System.out.println("server side, enter hostname to bind (default = localhost): "); + hostnameServer = scanner.nextLine(); + if(hostnameServer.equals("")){ + hostnameServer = defaultHostname; + System.out.println("using default hostname : " + hostnameServer); + } + System.out.println("enter port (default = 7070): "); + portServer = scanner.nextLine(); + if(portServer.equals("")){ + portServer = defaultPortServer; + System.out.println("using default port : " + portServer); + } + System.out.println("enter hostname of tracker (default = localhost): "); + hostnameTracker = scanner.nextLine(); + if(hostnameTracker.equals("")){ + hostnameTracker = defaultHostname; + System.out.println("tracker default hostname : " + hostnameTracker); + } + System.out.println("enter tracker's port (default = 6969): "); + portTracker = scanner.nextLine(); + if(portTracker.equals("")){ + portTracker = defaultPortTracker; + System.out.println("using default port : " + portTracker); + } } - // Server threads - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory(), "localhost", c.port, c.loggerServer, c.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory(), "localhost", c.port, c.loggerServer, c.tracker); + System.out.println("using hostname : " + hostnameServer); + Pair PtestPortServer = testPort.testPortServer(Integer.parseInt(portServer)); + if(PtestPortServer.getKey() == 0){ + System.out.println("using port : " + portServer); + } + else { + System.out.println(PtestPortServer.getValue()); + portServer = defaultPortServer; + } + System.out.println("tracker hostname : " + hostnameTracker); + + Pair PtestPortTracker = testPort.testPortTracker(Integer.parseInt(portTracker)); + if(PtestPortTracker.getKey() == 0){ + System.out.println("using port : " + portTracker); + } + else { + System.out.println(PtestPortTracker.getValue()); + portTracker = defaultPortTracker; + } + + ClientP2P c = new ClientP2P(portServer, hostnameTracker, portTracker); + + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory(), hostnameServer, c.portServer, c.loggerServer, c.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory(), hostnameServer, c.portServer, c.loggerServer, c.tracker); Thread tudp = new Thread(smudp); - tudp.setName("server UDP P2P-JAVA-PROJECT (port: " + c.port + ")"); + tudp.setName("server UDP P2P-JAVA-PROJECT"); tudp.start(); Thread ttcp = new Thread(smtcp); - ttcp.setName("server TCP P2P-JAVA-PROJECT (port: " + c.port + ")"); + ttcp.setName("server TCP P2P-JAVA-PROJECT"); ttcp.start(); // Wait a bit before printing client interface @@ -101,19 +152,15 @@ public class ClientP2P { Thread.currentThread().interrupt(); } - // initialize Host lists - System.out.println("Client : Which transport protocol do you want to use? [TCP/udp]"); - c.scanner.hasNextLine(); - String transportchoosen = c.scanner.nextLine(); - Thread t; - switch(transportchoosen){ + Thread tclient; + switch(protocolClient){ case "UDP": case "udp": - case "upd": // alias typo + case "upd": case "2" : System.out.println("Starting with UDP"); ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); - t = new Thread(cmudp); + tclient = new Thread(cmudp); break; case "TCP": case "tcp": @@ -121,18 +168,16 @@ public class ClientP2P { default: System.out.println("Starting with TCP"); ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); - t = new Thread(cmtcp); + tclient = new Thread(cmtcp); break; - } - t.setName("client P2P-JAVA-PROJECT"); - t.start(); + } + tclient.setName("client P2P-JAVA-PROJECT"); + tclient.start(); try { - t.join(); + tclient.join(); } catch (InterruptedException e) {} - c.scanner.close(); smudp.setStop(); smtcp.setStop(); - } } } diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index 04b3fbc..5228a86 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -18,30 +18,30 @@ import tools.TestPort; * @version 1.0 */ public class ServerP2P { - private int port; + private int portServer; private Directories directories; static private final String subdir = "seeded/"; private Logger logger; private HostItem tracker; - /** Constructor with portStr containing a port number. - * @param portStr String containing port number of listening. + /** Constructor with portServerstr containing a port number. + * @param portServerstr String containing port number of listening. */ - public ServerP2P(String portStr, String trackerHostname, String trackerPortStr) { - port = Integer.valueOf(Integer.parseInt(portStr)); - tracker = new HostItem(trackerHostname, Integer.valueOf(Integer.parseInt(trackerPortStr))); - directories = new Directories("P2P_JAVA_PROJECT_SERVER_" + port); + public ServerP2P(String portServerstr, String hostnameTracker, String portTracker) { + Scanner scanner = new Scanner(System.in); + portServer = Integer.valueOf(Integer.parseInt(portServerstr)); + tracker = new HostItem(hostnameTracker, Integer.valueOf(Integer.parseInt(portTracker))); + directories = new Directories("P2P_JAVA_PROJECT_SERVER_" + portServer); directories.createSubdir(subdir); logger = new Logger(directories.getDataHomeDirectory() + "server.log"); - System.out.println("Server will listen on port " + port + " and serve files from " + directories.getDataHomeDirectory() + subdir); - Scanner scanner = new Scanner(System.in); + System.out.println("Server will listen on port " + portServer + " and serve files from " + directories.getDataHomeDirectory() + subdir); directories.askOpenDataHomeDirectory(subdir, scanner); scanner.close(); } /** Main program entry point * first parameter is port number and is mandatory - * to test, run with: java -ea serverP2P.ServerP2P + * to test, run with: java serverP2P.ServerP2P * @param args parameters */ public static void main(String [] args) { @@ -56,7 +56,7 @@ public class ServerP2P { TestPort testPort = new TestPort(); if ((args.length != 5) && (args.length != 0)){ - System.out.println("usage : java serveurP2P.ServeurP2P (interactive) or java serveurP2P.ServeurP2P -- "); + System.out.println("usage : java serveurP2P.ServeurP2P (interactive) or java serveurP2P.ServeurP2P -- (default server port: server 7070 (range 7000->7070) and tracker port 6969 (range 7000 -> 7999))"); } else{ if(args.length == 5){ @@ -113,8 +113,8 @@ public class ServerP2P { } ServerP2P s = new ServerP2P(portServer, hostnameTracker, portTracker); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.port, s.logger, s.tracker); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.portServer, s.logger, s.tracker); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.portServer, s.logger, s.tracker); Thread tudp = new Thread(smudp); tudp.setName("server UDP P2P-JAVA-PROJECT"); tudp.start(); diff --git a/src/tools/TestPort.java b/src/tools/TestPort.java index ae71813..d3ca845 100644 --- a/src/tools/TestPort.java +++ b/src/tools/TestPort.java @@ -10,15 +10,21 @@ import javafx.util.Pair; */ public class TestPort { + /** test if port given correspond a range : registered ports, can be used without superuser privileges + * @return Pair + */ public Pair testPortServer(int port) { - if((port > 7000) && (port < 7999)){ + if((port >= 7000) && (port <= 7999)){ return new Pair<>(0,""); } return new Pair<>(1, "Wrong port (7000 -> 7999), using default port 7070"); } + /** test if port given correspond a range : : registered ports, can be used without superuser privileges, 6969 correspond to the unofficial bittorent tracker + * @return Pair + */ public Pair testPortTracker(int port) { - if((port > 6000) && (port < 6999)){ + if((port >= 6000) && (port <= 6999)){ return new Pair<>(0,""); } return new Pair<>(1, "Wrong port (6000 -> 6999), using default port 6969"); diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 787923c..821ab50 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -32,11 +32,13 @@ public class Tracker { Scanner scanner = new Scanner(System.in); directories.askOpenDataHomeDirectory(null, scanner); scanner.close(); + + //t.logger.write(PtestPortTracker.getValue(), LogLevel.Warning); } /** Main program entry point * first parameter is port number and is mandatory - * to test, run with: java -ea serverP2P.ServerP2P + * to test, run with: java serverP2P.ServerP2P * @param args parameters */ public static void main(String [] args) { @@ -49,7 +51,7 @@ public class Tracker { Tracker t; if ((args.length != 3) && (args.length != 0)){ - System.out.println("usage : java tracker.Tracker (interactive) or java trackerP2P.trackerP2P -- (default localhost:6969, range 6000 -> 6999)"); + System.out.println("usage : java tracker.Tracker (interactive) or java trackerP2P.trackerP2P -- (default port 6969 (range 6000 -> 6999))"); } else{ if(args.length == 3){ @@ -80,7 +82,6 @@ public class Tracker { else { System.out.println(PtestPortTracker.getValue()); t = new Tracker(defaultPort); - t.logger.write(PtestPortTracker.getValue(), LogLevel.Warning); } TrackerManagementUDP tmudp = new TrackerManagementUDP(hostname, t.port, t.logger); From 7253a34e491562e305f0637bf4aeeb4e0d31f15e Mon Sep 17 00:00:00 2001 From: Louis Date: Tue, 24 Mar 2020 17:32:33 +0100 Subject: [PATCH 40/40] Refactoring --- src/clientP2P/ClientP2P.java | 230 +++++++++++++------------ src/serverP2P/ServerManagementTCP.java | 4 +- src/serverP2P/ServerManagementUDP.java | 4 +- src/serverP2P/ServerP2P.java | 138 +++++++-------- src/tools/PortRange.java | 49 ++++++ src/tools/ServerPortRange.java | 10 ++ src/tools/TestPort.java | 35 ---- src/tools/TrackerPortRange.java | 10 ++ src/tracker/Tracker.java | 110 ++++++------ src/tracker/TrackerManagementTCP.java | 6 +- src/tracker/TrackerManagementUDP.java | 8 +- 11 files changed, 327 insertions(+), 277 deletions(-) create mode 100644 src/tools/PortRange.java create mode 100644 src/tools/ServerPortRange.java delete mode 100644 src/tools/TestPort.java create mode 100644 src/tools/TrackerPortRange.java diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index c42aa9a..5985479 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -2,7 +2,6 @@ package clientP2P; import java.util.Scanner; import java.util.List; -import javafx.util.Pair; import clientP2P.ClientManagementUDP; import clientP2P.ClientManagementTCP; @@ -12,7 +11,9 @@ import tools.Logger; import tools.LogLevel; import tools.Directories; import tools.HostItem; -import tools.TestPort; +import tools.ServerPortRange; +import tools.TrackerPortRange; + /** Client + Server implementation. * @author Louis Royer @@ -26,17 +27,17 @@ public class ClientP2P { private String partsDir = ".parts/"; private Logger loggerServer; private Logger loggerClient; - private int portServer; private Directories directories; private HostItem tracker; + private HostItem server; private Scanner scanner; - + /** Initialize loggers if directories and logger are null, * else fail silently. */ public void initDirectoriesAndLoggers() { if (directories == null && loggerServer == null && loggerClient == null) { - directories = new Directories("P2P_JAVA_PROJECT_" + portServer); + directories = new Directories("P2P_JAVA_PROJECT_" + server.getPort()); directories.createSubdir(logDir); loggerServer = new Logger(directories.getDataHomeDirectory() + logDir + "server.log"); loggerClient = new Logger(directories.getDataHomeDirectory() + logDir + "client.log"); @@ -44,18 +45,36 @@ public class ClientP2P { } } - /** Constructor with portServerstr as parameter. - * @param portServerstr String containing port for server listenning. + /** Constructor. + * @param hostnameServer hostname to bind + * @param portServer port to bind + * @param hostnameTracker hostname of tracker + * @param portTracker port of tracker */ - public ClientP2P(String portServerstr, String hostnameTracker, String portTracker) { + public ClientP2P(String hostnameServer, int portServer, String hostnameTracker, int portTracker) { scanner = new Scanner(System.in); - portServer = Integer.valueOf(Integer.parseInt(portServerstr)); - tracker = new HostItem(hostnameTracker, Integer.valueOf(Integer.parseInt(portTracker))); + server = new HostItem(hostnameServer, portServer); + tracker = new HostItem(hostnameTracker, portTracker); initDirectoriesAndLoggers(); System.out.println("Server will listen on port " + portServer + " and serve files from " + directories.getDataHomeDirectory()); directories.askOpenDataHomeDirectory(null, scanner); } + /** Print cli usage + * @param serverPortRange range of server ports + * @param trackerPortRange range of tracker ports + */ + private static void printUsage(ServerPortRange serverPortRange, TrackerPortRange trackerPortRange) { + System.out.println("usage :"); + System.out.println("\tjava clientP2P.ClientP2P"); + System.out.println("or"); + System.out.println("java clientP2P.ClientP2P -- " + + " " + + " " + + " "); + System.out.println("(" + trackerPortRange + " and " + serverPortRange +")"); + } + /** Main program entry point. * 1rst parameter is optionnal, and is used to * define port used by the server module to listen. If not provided, default to another port. @@ -63,121 +82,120 @@ public class ClientP2P { */ public static void main(String [] args) { final String defaultHostname = "localhost"; - final String defaultPortServer = "7070"; - final String defaultPortTracker = "6969"; String hostnameServer = ""; - String portServer = ""; + int portServer = 0; String hostnameTracker = ""; - String portTracker = ""; + int portTracker = 0; String protocolClient = ""; Scanner scanner = new Scanner(System.in); - TestPort testPort = new TestPort(); + final ServerPortRange serverPortRange = new ServerPortRange(); + final TrackerPortRange trackerPortRange = new TrackerPortRange(); if ((args.length != 6) && (args.length != 0)){ - System.out.println("usage : java clientP2P.ClientP2P or java clientP2P.ClientP2P -- (default tracker port 6969 (range 7000 -> 7999) and server port: server 7070 (range 7000->7070))"); + ClientP2P.printUsage(serverPortRange, trackerPortRange); + System.exit(1); } - else{ - if(args.length == 6){ + else if(args.length == 6){ protocolClient = args[1]; hostnameServer = args[2]; - portServer = args[3]; + portServer = Integer.valueOf(Integer.parseInt(args[3])); hostnameTracker = args[4]; - portTracker = args[5]; + portTracker = Integer.valueOf(Integer.parseInt(args[5])); + } else{ + System.out.println("Client, wich transport protocol do you want to use (default = TCP): "); + protocolClient = scanner.nextLine(); + System.out.println("server side, enter hostname to bind (default = localhost): "); + hostnameServer = scanner.nextLine(); + if(hostnameServer.equals("")){ + hostnameServer = defaultHostname; + System.out.println("using default hostname : " + hostnameServer); } - else{ - System.out.println("Client, wich transport protocol do you want to use (default = TCP): "); - protocolClient = scanner.nextLine(); - System.out.println("server side, enter hostname to bind (default = localhost): "); - hostnameServer = scanner.nextLine(); - if(hostnameServer.equals("")){ - hostnameServer = defaultHostname; - System.out.println("using default hostname : " + hostnameServer); - } - System.out.println("enter port (default = 7070): "); - portServer = scanner.nextLine(); - if(portServer.equals("")){ - portServer = defaultPortServer; - System.out.println("using default port : " + portServer); - } - System.out.println("enter hostname of tracker (default = localhost): "); - hostnameTracker = scanner.nextLine(); - if(hostnameTracker.equals("")){ - hostnameTracker = defaultHostname; - System.out.println("tracker default hostname : " + hostnameTracker); - } - System.out.println("enter tracker's port (default = 6969): "); - portTracker = scanner.nextLine(); - if(portTracker.equals("")){ - portTracker = defaultPortTracker; - System.out.println("using default port : " + portTracker); - } + System.out.println("enter port (default = " + serverPortRange.getDefaultPort() +"): "); + String portServerStr = scanner.nextLine(); + if(portServerStr.equals("")){ + portServer = serverPortRange.getDefaultPort(); + System.out.println("using default port : " + portServer); + } else { + portServer = Integer.valueOf(Integer.parseInt(portServerStr)); } - - System.out.println("using hostname : " + hostnameServer); - Pair PtestPortServer = testPort.testPortServer(Integer.parseInt(portServer)); - if(PtestPortServer.getKey() == 0){ - System.out.println("using port : " + portServer); + System.out.println("enter hostname of tracker (default = localhost): "); + hostnameTracker = scanner.nextLine(); + if(hostnameTracker.equals("")){ + hostnameTracker = defaultHostname; + System.out.println("tracker default hostname : " + hostnameTracker); } - else { - System.out.println(PtestPortServer.getValue()); - portServer = defaultPortServer; + System.out.println("enter tracker's port (default = "+trackerPortRange.getDefaultPort() + "): "); + String portTrackerStr = scanner.nextLine(); + if(portTrackerStr.equals("")){ + portTracker = trackerPortRange.getDefaultPort(); + System.out.println("using default port : " + portTracker); + } else { + portTracker = Integer.valueOf(Integer.parseInt(portTrackerStr)); } - System.out.println("tracker hostname : " + hostnameTracker); + } - Pair PtestPortTracker = testPort.testPortTracker(Integer.parseInt(portTracker)); - if(PtestPortTracker.getKey() == 0){ - System.out.println("using port : " + portTracker); - } - else { - System.out.println(PtestPortTracker.getValue()); - portTracker = defaultPortTracker; - } + System.out.println("using hostname : " + hostnameServer); + if(serverPortRange.isPortInRange(portServer)){ + System.out.println("using port : " + portServer); + } + else { + System.out.println("Port not in range. " + serverPortRange); + portServer = serverPortRange.getDefaultPort(); + } + System.out.println("tracker hostname : " + hostnameTracker); + + if(trackerPortRange.isPortInRange(portTracker)){ + System.out.println("using port : " + portTracker); + } + else { + System.out.println("Port not in range. " + trackerPortRange); + portTracker = trackerPortRange.getDefaultPort(); + } - ClientP2P c = new ClientP2P(portServer, hostnameTracker, portTracker); + ClientP2P c = new ClientP2P(hostnameServer, portServer, hostnameTracker, portTracker); - ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory(), hostnameServer, c.portServer, c.loggerServer, c.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory(), hostnameServer, c.portServer, c.loggerServer, c.tracker); - Thread tudp = new Thread(smudp); - tudp.setName("server UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(smtcp); - ttcp.setName("server TCP P2P-JAVA-PROJECT"); - ttcp.start(); + ServerManagementUDP smudp = new ServerManagementUDP(c.directories.getDataHomeDirectory(), c.server, c.tracker, c.loggerServer); + ServerManagementTCP smtcp = new ServerManagementTCP(c.directories.getDataHomeDirectory(), c.server, c.tracker, c.loggerServer); + Thread tudp = new Thread(smudp); + tudp.setName("server UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(smtcp); + ttcp.setName("server TCP P2P-JAVA-PROJECT"); + ttcp.start(); - // Wait a bit before printing client interface - // This is not required, but allow to have a cleaner interface - try { - Thread.sleep(200); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + // Wait a bit before printing client interface + // This is not required, but allow to have a cleaner interface + try { + Thread.sleep(200); + } catch(InterruptedException e) { + Thread.currentThread().interrupt(); + } - Thread tclient; - switch(protocolClient){ - case "UDP": - case "udp": - case "upd": - case "2" : - System.out.println("Starting with UDP"); - ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); - tclient = new Thread(cmudp); - break; - case "TCP": - case "tcp": - case "1": - default: - System.out.println("Starting with TCP"); - ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); - tclient = new Thread(cmtcp); - break; - } - tclient.setName("client P2P-JAVA-PROJECT"); - tclient.start(); - try { - tclient.join(); - } catch (InterruptedException e) {} - smudp.setStop(); - smtcp.setStop(); + Thread tclient; + switch(protocolClient){ + case "UDP": + case "udp": + case "upd": // to avoid users typos + case "2" : + System.out.println("Starting with UDP"); + ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); + tclient = new Thread(cmudp); + break; + case "TCP": + case "tcp": + case "1": + default: + System.out.println("Starting with TCP"); + ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.tracker, c.directories.getDataHomeDirectory() + c.partsDir, c.loggerClient, c.scanner); + tclient = new Thread(cmtcp); + break; } + tclient.setName("client P2P-JAVA-PROJECT"); + tclient.start(); + try { + tclient.join(); + } catch (InterruptedException e) {} + smudp.setStop(); + smtcp.setStop(); } } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index d44b79a..fad6ddf 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -56,8 +56,8 @@ public class ServerManagementTCP extends ServerManagement { * @param logger Logger item * @param tracker Tracker */ - public ServerManagementTCP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { - super(baseDirectory, new HostItem(hostName, port), tracker, logger); + public ServerManagementTCP(String baseDirectory, HostItem server, HostItem tracker, Logger logger) { + super(baseDirectory, server, tracker, logger); assert baseDirectory != null : "baseDirectory is null"; assert server != null : "server is null"; assert tracker != null : "tracker is null"; diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index bba1a5b..7ea6b39 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -54,8 +54,8 @@ public class ServerManagementUDP extends ServerManagement { * @param logger Logger item * @param tracker Tracker */ - public ServerManagementUDP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) { - super(baseDirectory, new HostItem(hostName, port), tracker, logger); + public ServerManagementUDP(String baseDirectory, HostItem server, HostItem tracker, Logger logger) { + super(baseDirectory, server, tracker, logger); assert baseDirectory != null : "baseDirectory is null"; assert server != null : "server is null"; assert tracker != null : "tracker is null"; diff --git a/src/serverP2P/ServerP2P.java b/src/serverP2P/ServerP2P.java index 5228a86..7c5a3d3 100644 --- a/src/serverP2P/ServerP2P.java +++ b/src/serverP2P/ServerP2P.java @@ -1,13 +1,13 @@ package serverP2P; import java.util.Scanner; -import javafx.util.Pair; import serverP2P.ServerManagementUDP; import serverP2P.ServerManagementTCP; import tools.Directories; import tools.Logger; import tools.HostItem; -import tools.TestPort; +import tools.ServerPortRange; +import tools.TrackerPortRange; /** Server only implementation @@ -18,19 +18,22 @@ import tools.TestPort; * @version 1.0 */ public class ServerP2P { - private int portServer; private Directories directories; static private final String subdir = "seeded/"; private Logger logger; private HostItem tracker; + private HostItem server; /** Constructor with portServerstr containing a port number. - * @param portServerstr String containing port number of listening. + * @param hostnameServer binded hostname + * @param portServer binded port + * @param hostnameTracker tracker hostname + * @param portTracker tracker port */ - public ServerP2P(String portServerstr, String hostnameTracker, String portTracker) { + public ServerP2P(String hostnameServer, int portServer, String hostnameTracker, int portTracker) { Scanner scanner = new Scanner(System.in); - portServer = Integer.valueOf(Integer.parseInt(portServerstr)); - tracker = new HostItem(hostnameTracker, Integer.valueOf(Integer.parseInt(portTracker))); + server = new HostItem(hostnameServer, portServer); + tracker = new HostItem(hostnameTracker, portTracker); directories = new Directories("P2P_JAVA_PROJECT_SERVER_" + portServer); directories.createSubdir(subdir); logger = new Logger(directories.getDataHomeDirectory() + "server.log"); @@ -46,81 +49,80 @@ public class ServerP2P { */ public static void main(String [] args) { final String defaultHostname = "localhost"; - final String defaultPortServer = "7070"; - final String defaultPortTracker = "6969"; + final ServerPortRange serverPortRange = new ServerPortRange(); + final TrackerPortRange trackerPortRange = new TrackerPortRange(); String hostnameServer = ""; - String portServer = ""; + int portServer = 0; String hostnameTracker = ""; - String portTracker = ""; + int portTracker = 0; Scanner scanner = new Scanner(System.in); - TestPort testPort = new TestPort(); if ((args.length != 5) && (args.length != 0)){ - System.out.println("usage : java serveurP2P.ServeurP2P (interactive) or java serveurP2P.ServeurP2P -- (default server port: server 7070 (range 7000->7070) and tracker port 6969 (range 7000 -> 7999))"); + System.out.println("usage : java serveurP2P.ServeurP2P (interactive) or java serveurP2P.ServeurP2P -- (" + serverPortRange + " and " + trackerPortRange +")"); + System.exit(1); } - else{ - if(args.length == 5){ + else if(args.length == 5){ hostnameServer = args[1]; - portServer = args[2]; + portServer = Integer.valueOf(Integer.parseInt(args[2])); hostnameTracker = args[3]; - portTracker = args[4]; + portTracker = Integer.valueOf(Integer.parseInt(args[4])); + } else { + System.out.println("Server, enter hostname to bind (default = localhost): "); + hostnameServer = scanner.nextLine(); + if(hostnameServer.equals("")){ + hostnameServer = defaultHostname; + System.out.println("using default hostname : " + hostnameServer); } - else{ - System.out.println("Server, enter hostname to bind (default = localhost): "); - hostnameServer = scanner.nextLine(); - if(hostnameServer.equals("")){ - hostnameServer = defaultHostname; - System.out.println("using default hostname : " + hostnameServer); - } - System.out.println("enter port (default = 7070): "); - portServer = scanner.nextLine(); - if(portServer.equals("")){ - portServer = defaultPortServer; - System.out.println("using default port : " + portServer); - } - System.out.println("enter hostname of tracker (default = localhost): "); - hostnameTracker = scanner.nextLine(); - if(hostnameTracker.equals("")){ - hostnameTracker = defaultHostname; - System.out.println("tracker default hostname : " + hostnameTracker); - } - System.out.println("enter tracker's port (default = 6969): "); - portTracker = scanner.nextLine(); - if(portTracker.equals("")){ - portTracker = defaultPortTracker; - System.out.println("using default port : " + portTracker); - } + System.out.println("enter port (default = " + serverPortRange.getDefaultPort() + "): "); + String portServerStr = scanner.nextLine(); + if(portServerStr.equals("")){ + portServer = serverPortRange.getDefaultPort(); + System.out.println("using default port : " + portServer); + } else { + portServer = Integer.valueOf(Integer.parseInt(portServerStr)); } - - System.out.println("using hostname : " + hostnameServer); - Pair PtestPortServer = testPort.testPortServer(Integer.parseInt(portServer)); - if(PtestPortServer.getKey() == 0){ - System.out.println("using port : " + portServer); + System.out.println("enter hostname of tracker (default = localhost): "); + hostnameTracker = scanner.nextLine(); + if(hostnameTracker.equals("")){ + hostnameTracker = defaultHostname; + System.out.println("tracker default hostname : " + hostnameTracker); } - else { - System.out.println(PtestPortServer.getValue()); - portServer = defaultPortServer; + System.out.println("enter tracker's port (default = " + trackerPortRange.getDefaultPort() + "): "); + String portTrackerStr = scanner.nextLine(); + if(portTrackerStr.equals("")){ + portTracker = serverPortRange.getDefaultPort(); + System.out.println("using default port : " + portTracker); + } else { + portTracker = Integer.valueOf(Integer.parseInt(portTrackerStr)); } - System.out.println("tracker hostname : " + hostnameTracker); + } - Pair PtestPortTracker = testPort.testPortTracker(Integer.parseInt(portTracker)); - if(PtestPortTracker.getKey() == 0){ - System.out.println("using port : " + portTracker); - } - else { - System.out.println(PtestPortTracker.getValue()); - portTracker = defaultPortTracker; - } + System.out.println("using hostname : " + hostnameServer); + if(serverPortRange.isPortInRange(portServer)) { + System.out.println("using port : " + portServer); + } + else { + System.out.println("Port not in range. " + serverPortRange); + portServer = serverPortRange.getDefaultPort(); + } + System.out.println("tracker hostname : " + hostnameTracker); - ServerP2P s = new ServerP2P(portServer, hostnameTracker, portTracker); - ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.portServer, s.logger, s.tracker); - ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, hostnameServer, s.portServer, s.logger, s.tracker); - Thread tudp = new Thread(smudp); - tudp.setName("server UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(smtcp); - ttcp.setName("server TCP P2P-JAVA-PROJECT"); - ttcp.start(); + if(trackerPortRange.isPortInRange(portTracker)) { + System.out.println("using port : " + portTracker); } + else { + System.out.println("Port not in range. " + trackerPortRange); + portTracker = trackerPortRange.getDefaultPort(); + } + + ServerP2P s = new ServerP2P(hostnameServer, portServer, hostnameTracker, portTracker); + ServerManagementUDP smudp = new ServerManagementUDP(s.directories.getDataHomeDirectory() + subdir, s.server, s.tracker, s.logger); + ServerManagementTCP smtcp = new ServerManagementTCP(s.directories.getDataHomeDirectory() + subdir, s.server, s.tracker, s.logger); + Thread tudp = new Thread(smudp); + tudp.setName("server UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(smtcp); + ttcp.setName("server TCP P2P-JAVA-PROJECT"); + ttcp.start(); } } diff --git a/src/tools/PortRange.java b/src/tools/PortRange.java new file mode 100644 index 0000000..290cc94 --- /dev/null +++ b/src/tools/PortRange.java @@ -0,0 +1,49 @@ +package tools; + +/** Test ports. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class PortRange { + + protected int portMax; + protected int portMin; + protected int defaultPort; + protected String type; + + /** Port range constructor + * @param portMin minimum port + * @param portMax maximum port + * @param defaultPort default port + * @param type type of range + */ + public PortRange(int portMin, int portMax, int defaultPort, String type) { + this.portMax = portMax; + this.portMin = portMin; + this.defaultPort = defaultPort; + this.type = type; + } + + /** test if port given correspond a range : registered ports, can be used without superuser privileges + * @return true if port was valid + */ + public boolean isPortInRange(int port) { + return ((port >= portMin) && (port <= portMax)); + } + + /** To String + * @return String representation + */ + public String toString() { + return "default " + type + "port: " + defaultPort + "(range: " + portMin + " -> " + portMax + ")"; + } + + /** Default port getter + * @return default port + */ + public int getDefaultPort() { + return defaultPort; + } +} diff --git a/src/tools/ServerPortRange.java b/src/tools/ServerPortRange.java new file mode 100644 index 0000000..96722c5 --- /dev/null +++ b/src/tools/ServerPortRange.java @@ -0,0 +1,10 @@ +package tools; +import tools.PortRange; + +public class ServerPortRange extends PortRange { + + /** Constructor */ + public ServerPortRange() { + super(7000, 7999, 7070, "server"); + } +} diff --git a/src/tools/TestPort.java b/src/tools/TestPort.java deleted file mode 100644 index d3ca845..0000000 --- a/src/tools/TestPort.java +++ /dev/null @@ -1,35 +0,0 @@ -package tools; - -import javafx.util.Pair; - -/** Test ports. - * @author Louis Royer - * @author Flavien Haas - * @author JS Auge - * @version 1.0 - */ -public class TestPort { - - /** test if port given correspond a range : registered ports, can be used without superuser privileges - * @return Pair - */ - public Pair testPortServer(int port) { - if((port >= 7000) && (port <= 7999)){ - return new Pair<>(0,""); - } - return new Pair<>(1, "Wrong port (7000 -> 7999), using default port 7070"); - } - - /** test if port given correspond a range : : registered ports, can be used without superuser privileges, 6969 correspond to the unofficial bittorent tracker - * @return Pair - */ - public Pair testPortTracker(int port) { - if((port >= 6000) && (port <= 6999)){ - return new Pair<>(0,""); - } - return new Pair<>(1, "Wrong port (6000 -> 6999), using default port 6969"); - } - - - -} diff --git a/src/tools/TrackerPortRange.java b/src/tools/TrackerPortRange.java new file mode 100644 index 0000000..0ca491b --- /dev/null +++ b/src/tools/TrackerPortRange.java @@ -0,0 +1,10 @@ +package tools; +import tools.PortRange; + +public class TrackerPortRange extends PortRange { + + /** Constructor */ + public TrackerPortRange() { + super(6000, 6999, 6969, "tracker"); + } +} diff --git a/src/tracker/Tracker.java b/src/tracker/Tracker.java index 821ab50..92ff5f5 100644 --- a/src/tracker/Tracker.java +++ b/src/tracker/Tracker.java @@ -1,13 +1,13 @@ package tracker; import java.util.Scanner; -import javafx.util.Pair; import tracker.TrackerManagementTCP; import tracker.TrackerManagementUDP; import tools.Directories; import tools.Logger; import tools.LogLevel; -import tools.TestPort; +import tools.TrackerPortRange; +import tools.HostItem; /** Tracker implementation * First argument of main method is port listened by the tracker, and is mandatory. @@ -17,23 +17,22 @@ import tools.TestPort; * @version 1.0 */ public class Tracker { - private int port; + private HostItem tracker; private Directories directories; private Logger logger; /** Constructor with portStr containing a port number. - * @param portStr String containing port number of listening. + * @param hostname hostname to bind + * @param port port to bind */ - public Tracker(String portStr) { - port = Integer.valueOf(Integer.parseInt(portStr)); + public Tracker(String hostname, int port) { + tracker = new HostItem(hostname, port); directories = new Directories("P2P_JAVA_PROJECT_TRACKER_" + port); logger = new Logger(directories.getDataHomeDirectory() + "tracker.log"); System.out.println("Tracker will listen on port " + port + " and write logs into " + directories.getDataHomeDirectory()); Scanner scanner = new Scanner(System.in); directories.askOpenDataHomeDirectory(null, scanner); scanner.close(); - - //t.logger.write(PtestPortTracker.getValue(), LogLevel.Warning); } /** Main program entry point @@ -41,57 +40,54 @@ public class Tracker { * to test, run with: java serverP2P.ServerP2P * @param args parameters */ - public static void main(String [] args) { - final String defaultPort = "6969"; - final String defaultHostname = "localhost"; - Scanner scanner = new Scanner(System.in); - TestPort testPort = new TestPort(); - String hostname; - String port; - Tracker t; + public static void main(String [] args) { + final TrackerPortRange trackerPortRange = new TrackerPortRange(); + final String defaultHostname = "localhost"; + Scanner scanner = new Scanner(System.in); + String hostname = ""; + int port = 0; + Tracker t; - if ((args.length != 3) && (args.length != 0)){ - System.out.println("usage : java tracker.Tracker (interactive) or java trackerP2P.trackerP2P -- (default port 6969 (range 6000 -> 6999))"); + if ((args.length != 3) && (args.length != 0)){ + System.out.println("usage : java tracker.Tracker (interactive) or java trackerP2P.trackerP2P -- (" + trackerPortRange +")"); + System.exit(1); + } else if (args.length == 3){ + hostname = args[1]; + port = Integer.valueOf(Integer.parseInt(args[2])); + } else { + System.out.println("Tracker Server, enter hostname to bind (default = localhost): "); + hostname = scanner.nextLine(); + if(hostname.equals("")){ + hostname = defaultHostname; + System.out.println("using default hostname : " + hostname); } - else{ - if(args.length == 3){ - hostname = args[1]; - port = args[2]; - } - else{ - System.out.println("Tracker Server, enter hostname to bind (default = localhost): "); - hostname = scanner.nextLine(); - if(hostname.equals("")){ - hostname = defaultHostname; - System.out.println("using default hostname : " + hostname); - } - System.out.println("enter port (default = 6969): "); - port = scanner.nextLine(); - if(port.equals("")){ - port = defaultPort; - System.out.println("using default port : " + port); - } - } - - System.out.println("using hostname : " + hostname); - Pair PtestPortTracker = testPort.testPortTracker(Integer.parseInt(port)); - if(PtestPortTracker.getKey() == 0){ - System.out.println("using port : " + port); - t = new Tracker(port); - } - else { - System.out.println(PtestPortTracker.getValue()); - t = new Tracker(defaultPort); - } - - TrackerManagementUDP tmudp = new TrackerManagementUDP(hostname, t.port, t.logger); - TrackerManagementTCP tmtcp = new TrackerManagementTCP(hostname, t.port, t.logger); - Thread tudp = new Thread(tmudp); - tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); - tudp.start(); - Thread ttcp = new Thread(tmtcp); - ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); - ttcp.start(); + System.out.println("enter port (default = " + trackerPortRange.getDefaultPort() +"): "); + String portStr = scanner.nextLine(); + if(portStr.equals("")){ + port = trackerPortRange.getDefaultPort(); + System.out.println("using default port : " + port); + } else { + port = Integer.valueOf(Integer.parseInt(portStr)); } } + + System.out.println("using hostname : " + hostname); + if(trackerPortRange.isPortInRange(port)) { + System.out.println("using port : " + port); + t = new Tracker(hostname, port); + } + else { + System.out.println("Port not in range. " + trackerPortRange); + t = new Tracker(hostname, trackerPortRange.getDefaultPort()); + } + + TrackerManagementUDP tmudp = new TrackerManagementUDP(t.tracker, t.logger); + TrackerManagementTCP tmtcp = new TrackerManagementTCP(t.tracker, t.logger); + Thread tudp = new Thread(tmudp); + tudp.setName("Tracker UDP P2P-JAVA-PROJECT"); + tudp.start(); + Thread ttcp = new Thread(tmtcp); + ttcp.setName("Tracker TCP P2P-JAVA-PROJECT"); + ttcp.start(); + } } diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index afba7bd..603bab5 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -38,11 +38,11 @@ public class TrackerManagementTCP extends TrackerManagement { private ServerSocket socket; /** Constructor with port and logger. - * @param port Port used to listen. + * @param tracker hostitem of the tracker. * @param logger Logger object */ - public TrackerManagementTCP(String hostname, int port, Logger logger) { - super(new HostItem(hostname, port), logger); + public TrackerManagementTCP(HostItem tracker, Logger logger) { + super(tracker, logger); try { socket = new ServerSocket(tracker.getPort(), 10, tracker.getInetAddress()); } catch (SocketException e) { diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index 6a07bcb..cdfb890 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -34,15 +34,15 @@ import tracker.TrackerManagement; public class TrackerManagementUDP extends TrackerManagement { private DatagramSocket socket; /** Constructor with port and logger. - * @param port Port used to listen. + * @param tracker hostitem of the tracker. * @param logger Logger object */ - public TrackerManagementUDP(String hostname, int port, Logger logger) { - super(new HostItem(hostname, port), logger); + public TrackerManagementUDP(HostItem tracker, Logger logger) { + super(tracker, logger); try { socket = new DatagramSocket(tracker.getPort(), tracker.getInetAddress()); } catch (SocketException e) { - logger.writeUDP("Error: cannot listen on port " + port, LogLevel.Error); + logger.writeUDP("Error: cannot listen on " + tracker, LogLevel.Error); System.exit(-1); } }