Projet_JAVA_P2P_STRI2A/src/clientP2P/ClientManagement.java
Louis Royer 4ee09dfc74
All checks were successful
flavien's git/Projet_JAVA_P2P_STRI2A/pipeline/head This commit looks good
flavien's git/Projet_JAVA_P2P_STRI2A/pipeline/pr-fix103 This commit looks good
Split ClientManagement
into ClientInterface and ClientManagement
2020-04-08 12:29:16 +02:00

258 lines
8.0 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.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import localException.ProtocolError;
import localException.InternalError;
import localException.ProtocolError;
import localException.SizeError;
import localException.TransmissionError;
import localException.VersionError;
import localException.SocketClosed;
import protocolP2P.RequestResponseCode;
import protocolP2P.FileList;
import protocolP2P.ProtocolP2PPacket;
import protocolP2P.DiscoverRequest;
import protocolP2P.DiscoverResponse;
import protocolP2P.Payload;
import protocolP2P.HashAlgorithm;
import remoteException.EmptyFile;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
import remoteException.NotFound;
import remoteException.ProtocolRemoteError;
import remoteException.VersionRemoteError;
import remoteException.NotATracker;
import remoteException.UnknownHost;
import exception.RemoteException;
import exception.LocalException;
import tools.ServeErrors;
import tools.HostItem;
import tools.Logger;
import tools.LogLevel;
import java.net.SocketException;
/** Implementation of P2P-JAVA-PROJECT CLIENT
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public abstract class ClientManagement extends ServeErrors {
protected String baseDirectory;
protected String partsSubdir;
protected List<HostItem> hostList = new ArrayList<>();
protected HostItem tracker;
protected HostItem client;
protected Logger logger;
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 client HostItem of the application
*/
public ClientManagement(String baseDirectory, HostItem tracker, String partsSubdir, Logger logger, HostItem client) {
this.baseDirectory = baseDirectory;
this.tracker = tracker;
this.partsSubdir = partsSubdir;
this.logger = logger;
this.client = client;
}
/** Getter for tracker socket
* @return Tracker's socket
* @throws SocketException
* @throws UnknownHostException
* @throws IOException
*/
protected abstract Object getTrackerSocket() throws SocketException, UnknownHostException, IOException;
/** Close Tracker socket
*/
protected abstract void closeTrackerSocket();
/** Initialize hostList from tracker
* @throws ProtocolError
* @throws InternalError
* @throws SocketException
* @throws UnknownHostException
* @throws IOException
*/
public void initHostList() throws ProtocolError, InternalError, SocketException, UnknownHostException, IOException {
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();
}
closeTrackerSocket();
} catch (SocketClosed e){
writeLog("listDirectory : SocketClosed", LogLevel.Error);
throw new ProtocolError();
} catch (LocalException e) {
writeLog(e, LogLevel.Error);
throw new ProtocolError();
} catch (RemoteException e) {
writeLog(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) {
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);
/** Close HostItem socket
* @param hostItem HostItem
*/
protected abstract void closeHostItemSocket(HostItem hostItem);
/** 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
*/
public String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
if (hostList.size() == 0) {
return new String[0];
}
ProtocolP2PPacket<?> d = createProtocolP2PPacket(new Payload(RequestResponseCode.LIST_REQUEST));
try {
d.sendRequest(getHostItemSocket(hostList.get(0)));
Payload p = d.receiveResponse().getPayload();
closeHostItemSocket(hostList.get(0));
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();
} catch (UnknownHost 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
*/
public 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 {
downLoader.sendRatioUpdate();
writeLog("Ratio updates sent.", LogLevel.Info);
}
} else {
throw new InternalError();
}
} catch (InterruptedException e) {
throw new InternalError();
}
}
/** 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);
}