Projet_JAVA_P2P_STRI2A/src/clientP2P/ClientManagementUDP.java

256 lines
9.5 KiB
Java
Raw Normal View History

2020-01-14 11:10:11 +01:00
package clientP2P;
2020-03-19 17:49:39 +01:00
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;
2020-03-19 13:48:39 +01:00
import localException.InternalError;
import localException.ProtocolError;
import localException.SizeError;
import localException.TransmissionError;
import localException.VersionError;
2020-01-25 21:25:36 +01:00
import remoteException.EmptyFile;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
import remoteException.NotFound;
import remoteException.ProtocolRemoteError;
import remoteException.VersionRemoteError;
2020-03-20 11:27:57 +01:00
import remoteException.NotATracker;
import protocolP2P.ProtocolP2PPacketUDP;
import protocolP2P.Payload;
import protocolP2P.RequestResponseCode;
import protocolP2P.FileList;
2020-03-04 22:29:54 +01:00
import protocolP2P.HashAlgorithm;
2020-03-21 15:48:18 +01:00
import protocolP2P.DiscoverRequest;
import protocolP2P.DiscoverResponse;
2020-03-19 17:49:39 +01:00
import tools.HostItem;
import tools.Logger;
import tools.LogLevel;
2020-03-12 17:52:31 +01:00
import clientP2P.ClientDownloadUDP;
2020-01-12 23:29:49 +01:00
/** Implementation of P2P-JAVA-PROJECT CLIENT
2020-01-12 23:29:49 +01:00
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
2020-01-14 11:10:11 +01:00
public class ClientManagementUDP implements Runnable {
2020-01-12 23:29:49 +01:00
private String baseDirectory;
2020-03-12 17:52:31 +01:00
private String partsSubdir;
private List<HostItem> hostList;
2020-03-21 15:48:18 +01:00
private HostItem tracker;
2020-03-19 17:49:39 +01:00
private Logger logger;
2020-03-21 15:48:18 +01:00
private Scanner scanner;
2020-01-12 23:29:49 +01:00
2020-03-21 15:48:18 +01:00
/** Constructor for UDP implementation, with baseDirectory, tracker, partsSubdir, logger and scanner parameters.
2020-01-12 23:29:49 +01:00
* @param baseDirectory the root directory where files are stored
2020-03-21 15:48:18 +01:00
* @param tracker tracker HostItem
* @param partsSubdir subdirectory to store file parts
* @param logger Loggger
* @param scanner Scanner used to read input
2020-01-12 23:29:49 +01:00
*/
2020-03-21 15:48:18 +01:00
public ClientManagementUDP(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, Scanner scanner) {
this.scanner = scanner;
2020-01-12 23:29:49 +01:00
this.baseDirectory = baseDirectory;
2020-03-21 15:48:18 +01:00
this.tracker = tracker;
2020-03-12 17:52:31 +01:00
this.partsSubdir = partsSubdir;
2020-03-19 17:49:39 +01:00
this.logger = logger;
2020-03-21 15:48:18 +01:00
try {
initHostList();
} catch (InternalError e) {
System.exit(-1);
} catch (ProtocolError e) {
System.exit(-2);
}
2020-01-12 23:29:49 +01:00
}
/** 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);
}
2020-01-12 23:29:49 +01:00
System.out.println("Name of the file to download:");
2020-01-14 11:10:11 +01:00
String f = scanner.nextLine();
download(f);
2020-03-19 17:49:39 +01:00
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");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Server has no file in directory", LogLevel.Error);
} catch (InternalError e) {
System.err.println("Error: Client internal error");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Client internal error", LogLevel.Error);
} catch (UnknownHostException e) {
System.err.println("Error: Server host is unknown");
2020-03-19 17:49:39 +01:00
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");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Request cannot be send or response cannot be received", LogLevel.Error);
2020-01-14 11:10:11 +01:00
} catch (TransmissionError e) {
System.err.println("Error: Message received is too big");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Message received is too big", LogLevel.Error);
2020-01-12 23:29:49 +01:00
} catch (ProtocolError e) {
System.err.println("Error: Cannot decode servers response");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Cannot decode servers response", LogLevel.Error);
} catch (VersionError e) {
System.err.println("Error: Servers response use bad version of the protocol");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Servers 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");
2020-03-19 17:49:39 +01:00
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");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Server internal error", LogLevel.Error);
} catch (ProtocolRemoteError e) {
System.err.println("Error: Server cannot decode clients request");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Server cannot decode clients request", LogLevel.Error);
} catch (VersionRemoteError e) {
System.err.println("Error: Server cannot decode this version of the protocol");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Server cannot decode this version of the protocol", LogLevel.Error);
2020-01-12 23:29:49 +01:00
} catch (NotFound e) {
2020-01-25 21:25:36 +01:00
System.err.println("Error: Server has not this file in directory");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: Server has not this file in directory", LogLevel.Error);
2020-01-25 21:25:36 +01:00
} catch (EmptyFile e) {
System.err.println("Error: File is empty");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: File is empty", LogLevel.Error);
2020-01-12 23:29:49 +01:00
}
}
/** 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
2020-01-25 21:25:36 +01:00
* @throws EmptyFile
2020-01-12 23:29:49 +01:00
*/
2020-01-25 21:25:36 +01:00
private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
2020-03-19 17:49:39 +01:00
ClientDownloadUDP downLoader = new ClientDownloadUDP(filename, hostList, partsSubdir, baseDirectory, logger);
2020-03-12 17:52:31 +01:00
Thread t = new Thread(downLoader);
t.start();
2020-03-04 22:29:54 +01:00
try {
2020-03-12 17:52:31 +01:00
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));
2020-03-19 17:49:39 +01:00
logger.writeUDP("Computed checksum:" + String.format("%02X", b), LogLevel.Info);
2020-02-26 11:10:34 +01:00
}
2020-03-12 17:52:31 +01:00
System.err.println("");
System.err.println("Received checksum:");
for (byte b: hash512) {
System.err.print(String.format("%02X", b));
2020-03-19 17:49:39 +01:00
logger.writeUDP("Received checksum:" + String.format("%02X", b), LogLevel.Info);
2020-02-26 11:10:34 +01:00
}
2020-03-12 17:52:31 +01:00
System.err.println("");
throw new InternalError();
}
2020-03-12 17:52:31 +01:00
} else {
throw new InternalError();
2020-03-05 16:35:33 +01:00
}
2020-03-12 17:52:31 +01:00
} catch (InterruptedException e) {
2020-03-19 17:49:39 +01:00
logger.writeUDP(e, LogLevel.Error);
2020-03-04 22:29:54 +01:00
throw new InternalError();
}
2020-01-12 23:29:49 +01:00
}
2020-01-14 11:10:11 +01:00
/** list servers directory content
* @return list of files
* @throws InternalError
* @throws UnknowHostException
* @throws IOException
* @throws TransmissionError
2020-01-12 23:29:49 +01:00
* @throws ProtocolError
* @throws VersionError
* @throws SizeError
* @throws EmptyDirectory
* @throws InternalRemoteError
* @throws ProtocolRemoteError
* @throws VersionRemoteError
2020-01-12 23:29:49 +01:00
*/
private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
2020-03-22 13:44:08 +01:00
ProtocolP2PPacketUDP<Payload> 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) {
2020-03-19 17:49:39 +01:00
logger.writeUDP(e, LogLevel.Error);
2020-01-14 11:10:11 +01:00
throw new ProtocolError();
2020-01-25 21:25:36 +01:00
} catch (EmptyFile e) {
2020-03-19 17:49:39 +01:00
logger.writeUDP(e, LogLevel.Error);
2020-01-25 21:25:36 +01:00
throw new ProtocolError();
2020-03-20 11:27:57 +01:00
} catch (NotATracker e) {
logger.writeUDP(e, LogLevel.Error);
throw new ProtocolError();
2020-01-12 23:29:49 +01:00
}
}
2020-03-04 22:29:54 +01:00
/** Compute Hashsum of a file.
* @param filename
* @return hashsum
*/
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");
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: " + h.getName() + " not supported", LogLevel.Error);
2020-03-04 22:29:54 +01:00
} catch (IOException e) {
System.out.println("Error: cannot read " + filename);
2020-03-19 17:49:39 +01:00
logger.writeUDP("Error: cannot read " + filename, LogLevel.Error);
2020-03-04 22:29:54 +01:00
}
return new byte[0];
}
2020-03-21 15:48:18 +01:00
/** Initialize hostList from tracker
* @throws ProtocolError
* @throws InternalError
*/
private void initHostList() throws ProtocolError, InternalError {
2020-03-22 13:44:08 +01:00
ProtocolP2PPacketUDP<DiscoverRequest> d = new ProtocolP2PPacketUDP<>(new DiscoverRequest(null));
2020-03-21 15:48:18 +01:00
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();
}
}
2020-01-12 23:29:49 +01:00
}