Projet_JAVA_P2P_STRI2A/src/clientP2P/ClientManagementUDP.java
2020-03-22 13:44:08 +01:00

256 lines
9.5 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 tools.HostItem;
import tools.Logger;
import tools.LogLevel;
import clientP2P.ClientDownloadUDP;
/** Implementation of P2P-JAVA-PROJECT CLIENT
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public class ClientManagementUDP implements Runnable {
private String baseDirectory;
private String partsSubdir;
private List<HostItem> hostList;
private HostItem tracker;
private Logger logger;
private Scanner scanner;
/** 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
* @param partsSubdir subdirectory to store file parts
* @param logger Loggger
* @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);
}
}
/** 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");
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 servers response");
logger.writeUDP("Error: Cannot decode servers response", LogLevel.Error);
} catch (VersionError e) {
System.err.println("Error: Servers response use bad version of the protocol");
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");
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 clients request");
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");
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);
}
}
/** 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 {
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();
}
}
/** list servers 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
*/
private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
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) {
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();
}
}
/** 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");
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];
}
/** Initialize hostList from tracker
* @throws ProtocolError
* @throws InternalError
*/
private void initHostList() throws ProtocolError, InternalError {
ProtocolP2PPacketUDP<DiscoverRequest> 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();
}
}
}