Add hashsum

pull/25/head
Louis Royer 5 years ago
parent 710ce03921
commit 9493a8cb30

@ -21,12 +21,18 @@ import java.nio.file.Files;
import java.io.File; import java.io.File;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.ProtocolP2PPacketTCP;
import protocolP2P.Payload; import protocolP2P.Payload;
import protocolP2P.RequestResponseCode; import protocolP2P.RequestResponseCode;
import protocolP2P.FileList; import protocolP2P.FileList;
import protocolP2P.FilePart; import protocolP2P.FilePart;
import protocolP2P.LoadRequest; import protocolP2P.LoadRequest;
import protocolP2P.HashAlgorithm;
import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/** Implementation of P2P-JAVA-PROJECT CLIENT /** Implementation of P2P-JAVA-PROJECT CLIENT
* @author Louis Royer * @author Louis Royer
@ -134,8 +140,30 @@ public class ClientManagementTCP implements Runnable {
* @throws EmptyFile * @throws EmptyFile
*/ */
private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, SocketClosed, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, SocketClosed, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
byte [] hash512;
final long MAX_PARTIAL_SIZE = 4096; final long MAX_PARTIAL_SIZE = 4096;
ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); HashAlgorithm[] hashesAlgo = new HashAlgorithm[1];
hashesAlgo[0] = HashAlgorithm.SHA512;
ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new HashRequest(filename, hashesAlgo));
d.sendRequest((Object)socket);
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 {
hash512 = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512);
if (hash512.length == 0) {
System.err.println("Error: server do not support sha512 hashes");
throw new InternalError();
}
}
} catch (EmptyDirectory e) {
System.err.println("Error: empty directory, but request was not LIST_REQUEST");
throw new ProtocolError();
}
d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE));
d.sendRequest((Object)socket); d.sendRequest((Object)socket);
boolean fileFullyWritten = false; boolean fileFullyWritten = false;
long offset = 0; long offset = 0;
@ -199,6 +227,10 @@ public class ClientManagementTCP implements Runnable {
throw new ProtocolError(); throw new ProtocolError();
} }
} while(!fileFullyWritten); } while(!fileFullyWritten);
if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) {
System.err.println("Error: Hashsum does not match");
throw new InternalError();
}
socket.close(); socket.close();
} }
@ -234,4 +266,20 @@ public class ClientManagementTCP implements Runnable {
throw new ProtocolError(); 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");
} catch (IOException e) {
System.out.println("Error: cannot read " + filename);
}
return new byte[0];
}
} }

@ -20,12 +20,18 @@ import java.nio.file.Files;
import java.io.File; import java.io.File;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.ProtocolP2PPacketUDP;
import protocolP2P.Payload; import protocolP2P.Payload;
import protocolP2P.RequestResponseCode; import protocolP2P.RequestResponseCode;
import protocolP2P.FileList; import protocolP2P.FileList;
import protocolP2P.FilePart; import protocolP2P.FilePart;
import protocolP2P.LoadRequest; import protocolP2P.LoadRequest;
import protocolP2P.HashAlgorithm;
import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/** Implementation of P2P-JAVA-PROJECT CLIENT /** Implementation of P2P-JAVA-PROJECT CLIENT
* @author Louis Royer * @author Louis Royer
@ -121,8 +127,30 @@ public class ClientManagementUDP implements Runnable {
* @throws EmptyFile * @throws EmptyFile
*/ */
private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError { private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
byte[] hash512;
final long MAX_PARTIAL_SIZE = 4096; final long MAX_PARTIAL_SIZE = 4096;
ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE)); HashAlgorithm[] hashesAlgo = new HashAlgorithm[1];
hashesAlgo[0] = HashAlgorithm.SHA512;
ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new HashRequest(filename, hashesAlgo));
d.sendRequest((Object)socket);
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 {
hash512 = ((HashResponse)pHash).getHash(HashAlgorithm.SHA512);
if (hash512.length == 0) {
System.err.println("Error: server do not support sha512 hashes");
throw new InternalError();
}
}
} catch (EmptyDirectory e) {
System.err.println("Error: empty directory, but request was not LIST_REQUEST");
throw new ProtocolError();
}
d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE));
d.sendRequest((Object)socket); d.sendRequest((Object)socket);
boolean fileFullyWritten = false; boolean fileFullyWritten = false;
long offset = 0; long offset = 0;
@ -186,6 +214,10 @@ public class ClientManagementUDP implements Runnable {
throw new ProtocolError(); throw new ProtocolError();
} }
} while(!fileFullyWritten); } while(!fileFullyWritten);
if (!Arrays.equals(hash512, computeHashsum(filename, HashAlgorithm.SHA512))) {
System.err.println("Error: Hashsum does not match");
throw new InternalError();
}
} }
/** list servers directory content /** list servers directory content
@ -219,4 +251,20 @@ public class ClientManagementUDP implements Runnable {
throw new ProtocolError(); 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");
} catch (IOException e) {
System.out.println("Error: cannot read " + filename);
}
return new byte[0];
}
} }

@ -1,6 +1,7 @@
package protocolP2P; package protocolP2P;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import tools.BytesArrayTools;
/** HashAlgorithm enum. /** HashAlgorithm enum.
* @author Louis Royer * @author Louis Royer
@ -14,16 +15,16 @@ public enum HashAlgorithm {
private String name; private String name;
/* To be able to convert name to enum */ /* To be able to convert name to enum */
private static final Map<Byte, HashAlgorithm> BY_CODE = new HashMap<>(); private static final Map<String, HashAlgorithm> BY_NAME = new HashMap<>();
/* Initialization of HashMap */ /* Initialization of HashMap */
static { static {
for (HashAlgorithm h: values()) { for (HashAlgorithm h: values()) {
assert !BY_CODE.containsKey(Byte.valueOf(h.name)) : "Duplicate in " + HashAlgorithm.class.getCanonicalName(); assert !BY_NAME.containsKey(h.name) : "Duplicate in " + HashAlgorithm.class.getCanonicalName();
BY_CODE.put(Byte.valueOf(h.name), h); BY_NAME.put(h.name, h);
} }
} }
HashAlgorithm(String name) { private HashAlgorithm(String name) {
this.name = name; this.name = name;
} }
@ -37,11 +38,13 @@ public enum HashAlgorithm {
* @throws InterlanError * @throws InterlanError
*/ */
protected static HashAlgorithm fromName(String name) throws InternalError { protected static HashAlgorithm fromName(String name) throws InternalError {
HashAlgorithm h = BY_CODE.get(Byte.valueOf(name)); HashAlgorithm h = BY_NAME.get(BytesArrayTools.cleanStrings(name));
assert h != null : "Bad algorithm name: " + name;
if (h == null) { if (h == null) {
throw new InternalError(); throw new InternalError();
} }
return h; return h;
} }
} }

@ -70,6 +70,7 @@ public class HashRequest extends Payload {
try { try {
String[] l = (new String(packet, FILENAME_POSITION + filenameSize, size, "UTF-8")).split("\n"); String[] l = (new String(packet, FILENAME_POSITION + filenameSize, size, "UTF-8")).split("\n");
int i = 0; int i = 0;
algoList = new HashAlgorithm[l.length];
for(String algo : l) { for(String algo : l) {
algoList[i] = HashAlgorithm.fromName(algo); algoList[i] = HashAlgorithm.fromName(algo);
i++; i++;
@ -90,6 +91,9 @@ public class HashRequest extends Payload {
int filenameSize = filename.length(); int filenameSize = filename.length();
int size = FILENAME_POSITION + filenameSize; int size = FILENAME_POSITION + filenameSize;
for (HashAlgorithm h : algoList) { for (HashAlgorithm h : algoList) {
if (h == null) {
continue;
}
size += h.getName().length(); size += h.getName().length();
size += 1; // size for '\n' size += 1; // size for '\n'
} }
@ -117,6 +121,9 @@ public class HashRequest extends Payload {
} }
boolean firstIter = true; boolean firstIter = true;
for(HashAlgorithm h : algoList) { for(HashAlgorithm h : algoList) {
if (h == null) {
continue;
}
String s = h.getName(); String s = h.getName();
if (!firstIter) { if (!firstIter) {
firstIter = false; firstIter = false;

@ -8,10 +8,7 @@ import exception.SizeError;
import exception.ProtocolError; import exception.ProtocolError;
import exception.InternalError; import exception.InternalError;
import tools.BytesArrayTools; import tools.BytesArrayTools;
import java.security.MessageDigest;
import java.security.DigestInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
/** Representation of payload for hash response. /** Representation of payload for hash response.
* @author Louis Royer * @author Louis Royer
@ -22,7 +19,7 @@ import java.nio.file.Paths;
public class HashResponse extends Payload { public class HashResponse extends Payload {
private String filename; private String filename;
private Map<HashAlgorithm, String> hashes; private Map<HashAlgorithm, byte[]> hashes = new HashMap<>();
private static final int FILENAME_SIZE_POSITION = PAYLOAD_START_POSITION; private static final int FILENAME_SIZE_POSITION = PAYLOAD_START_POSITION;
private static final int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4; private static final int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4;
@ -32,7 +29,7 @@ public class HashResponse extends Payload {
* @throws InternalError * @throws InternalError
* *
*/ */
public HashResponse(String filename, Map<HashAlgorithm, String> hashes) throws InternalError { public HashResponse(String filename, Map<HashAlgorithm, byte[]> hashes) throws InternalError {
super(RequestResponseCode.HASH_RESPONSE); super(RequestResponseCode.HASH_RESPONSE);
/* assert to help debugging */ /* assert to help debugging */
assert filename.length() != 0 : "Size of filename in HashResponse must not be empty"; assert filename.length() != 0 : "Size of filename in HashResponse must not be empty";
@ -81,9 +78,13 @@ public class HashResponse extends Payload {
String algoName = new String(packet, start, algoNameSize, "UTF-8"); String algoName = new String(packet, start, algoNameSize, "UTF-8");
start += algoNameSize; start += algoNameSize;
int hashSize = BytesArrayTools.readInt(packet, start); int hashSize = BytesArrayTools.readInt(packet, start);
start += 8; start += 4;
if (hashSize != 0) { if (hashSize != 0) {
hashes.put(HashAlgorithm.fromName(algoName), new String(packet, start, hashSize, "UTF-8")); byte[] b = new byte[hashSize];
for (int i=0;i<hashSize;i++) {
b[i] = packet[start+i];
}
hashes.put(HashAlgorithm.fromName(algoName), b);
} }
start += hashSize; start += hashSize;
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
@ -106,8 +107,8 @@ public class HashResponse extends Payload {
for (HashAlgorithm h : hashes.keySet()) { for (HashAlgorithm h : hashes.keySet()) {
size += 4 + h.getName().length(); size += 4 + h.getName().length();
} }
for (String s : hashes.values()) { for (byte[] s : hashes.values()) {
size += 4 + s.length(); size += 4 + s.length;
} }
byte[] packet = new byte[size + 1]; // java initialize all to zero byte[] packet = new byte[size + 1]; // java initialize all to zero
@ -144,23 +145,18 @@ public class HashResponse extends Payload {
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new InternalError(); throw new InternalError();
} }
s = hashes.get(s); byte[] hashb = hashes.get(HashAlgorithm.fromName(s));
if (s == null) { if (hashb.length == 0) {
BytesArrayTools.write(packet, bCount, (int)0); BytesArrayTools.write(packet, bCount, (int)0);
bCount += 4; bCount += 4;
} else { } else {
BytesArrayTools.write(packet, bCount, (int)s.length()); BytesArrayTools.write(packet, bCount, (int)hashb.length);
bCount +=4; bCount +=4;
// copy hash // copy hash
try { for(byte b : hashb) {
byte[] sb = s.getBytes("UTF-8");
for(byte b : sb) {
packet[bCount] = b; packet[bCount] = b;
bCount += 1; bCount += 1;
} }
} catch (UnsupportedEncodingException e) {
throw new InternalError();
}
} }
} }
return packet; return packet;
@ -170,8 +166,13 @@ public class HashResponse extends Payload {
* @param hashAlgo HashAlgorithm to return hash from * @param hashAlgo HashAlgorithm to return hash from
* @return hash * @return hash
*/ */
public String getHash(HashAlgorithm hashAlgo) { public byte[] getHash(HashAlgorithm hashAlgo) {
return hashes.get(hashAlgo); byte[] b = hashes.get(hashAlgo);
if (b == null) {
return new byte[0];
} else {
return b;
}
} }
/** filename getter. /** filename getter.

@ -137,6 +137,7 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
case EMPTY_FILE: case EMPTY_FILE:
case LOAD_RESPONSE: case LOAD_RESPONSE:
case LIST_RESPONSE: case LIST_RESPONSE:
case HASH_RESPONSE:
// we were expecting a request, but we are receiving a response // we were expecting a request, but we are receiving a response
throw new ProtocolError(); throw new ProtocolError();
default : default :
@ -281,6 +282,12 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
case LOAD_REQUEST: case LOAD_REQUEST:
payload = (Payload) new LoadRequest(packet); payload = (Payload) new LoadRequest(packet);
break; break;
case HASH_REQUEST:
payload = (Payload) new HashRequest(packet);
break;
case HASH_RESPONSE:
payload = (Payload) new HashResponse(packet);
break;
default: default:
payload = new Payload(packet); // this can throw TransmissionError payload = new Payload(packet); // this can throw TransmissionError
break; break;

@ -129,6 +129,7 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket {
case EMPTY_FILE: case EMPTY_FILE:
case LOAD_RESPONSE: case LOAD_RESPONSE:
case LIST_RESPONSE: case LIST_RESPONSE:
case HASH_RESPONSE:
// we were expecting a request, but we are receiving a response // we were expecting a request, but we are receiving a response
throw new ProtocolError(); throw new ProtocolError();
default : default :
@ -277,6 +278,12 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket {
case LOAD_REQUEST: case LOAD_REQUEST:
payload = (Payload) new LoadRequest(packet); payload = (Payload) new LoadRequest(packet);
break; break;
case HASH_REQUEST:
payload = (Payload) new HashRequest(packet);
break;
case HASH_RESPONSE:
payload = (Payload) new HashResponse(packet);
break;
default: default:
payload = new Payload(packet); // this can throw TransmissionError payload = new Payload(packet); // this can throw TransmissionError
break; break;

@ -6,6 +6,8 @@ import java.net.InetAddress;
import java.net.SocketException; import java.net.SocketException;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.Files; import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import protocolP2P.ProtocolP2PPacketTCP; import protocolP2P.ProtocolP2PPacketTCP;
@ -30,6 +32,11 @@ import remoteException.EmptyFile;
import java.util.Arrays; import java.util.Arrays;
import tools.Logger; import tools.Logger;
import tools.LogLevel; import tools.LogLevel;
import java.util.HashMap;
import java.util.Map;
import protocolP2P.HashAlgorithm;
import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
/** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for TCP. /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for TCP.
@ -41,6 +48,7 @@ import tools.LogLevel;
public class ServerManagementTCP implements Runnable { public class ServerManagementTCP implements Runnable {
private String[] fileList; private String[] fileList;
private Map<String, byte[]> sha512 = new HashMap<>();
private String baseDirectory; private String baseDirectory;
private int TCPPort; private int TCPPort;
private ServerSocket socket; private ServerSocket socket;
@ -55,6 +63,7 @@ public class ServerManagementTCP implements Runnable {
this.baseDirectory = baseDirectory; this.baseDirectory = baseDirectory;
this.TCPPort = TCPPort; this.TCPPort = TCPPort;
initFileList(); initFileList();
initSha512();
try { try {
socket = new ServerSocket(TCPPort); socket = new ServerSocket(TCPPort);
} catch (SocketException e) { } catch (SocketException e) {
@ -123,6 +132,10 @@ public class ServerManagementTCP implements Runnable {
logger.writeTCP(addr + "LIST_REQUEST", LogLevel.Action); logger.writeTCP(addr + "LIST_REQUEST", LogLevel.Action);
sendListResponse(pd); sendListResponse(pd);
break; break;
case HASH_REQUEST:
logger.writeTCP(addr + "HASH_REQUEST", LogLevel.Action);
sendHashResponse(pd);
break;
default: default:
logger.writeTCP(addr + "Received grabbage", LogLevel.Action); logger.writeTCP(addr + "Received grabbage", LogLevel.Action);
sendInternalError(pd); sendInternalError(pd);
@ -158,6 +171,22 @@ public class ServerManagementTCP implements Runnable {
Arrays.sort(fileList); Arrays.sort(fileList);
} }
/** 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.writeTCP("sha512 not supported", LogLevel.Error);
} catch (IOException e) {
logger.writeTCP("cannot read " + f, LogLevel.Warning);
}
}
}
/** Send an internal error message. /** Send an internal error message.
* @param pd ProtocolP2PPacketTCP to respond * @param pd ProtocolP2PPacketTCP to respond
*/ */
@ -187,6 +216,46 @@ public class ServerManagementTCP implements Runnable {
} }
} }
/** Send hash response to hash request
* @param pd Request received
*/
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<HashAlgorithm, byte[]> 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);
}
}
}
}
/** Send response to load request /** Send response to load request
* @param pd Request received * @param pd Request received
*/ */

@ -7,6 +7,8 @@ import java.net.InetAddress;
import java.net.SocketException; import java.net.SocketException;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.Files; import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import protocolP2P.ProtocolP2PPacketUDP; import protocolP2P.ProtocolP2PPacketUDP;
import protocolP2P.ProtocolP2PPacket; import protocolP2P.ProtocolP2PPacket;
import protocolP2P.RequestResponseCode; import protocolP2P.RequestResponseCode;
@ -29,7 +31,11 @@ import remoteException.EmptyFile;
import java.util.Arrays; import java.util.Arrays;
import tools.Logger; import tools.Logger;
import tools.LogLevel; import tools.LogLevel;
import java.util.HashMap;
import java.util.Map;
import protocolP2P.HashAlgorithm;
import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
/** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP. /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP.
* @author Louis Royer * @author Louis Royer
@ -40,6 +46,7 @@ import tools.LogLevel;
public class ServerManagementUDP implements Runnable { public class ServerManagementUDP implements Runnable {
private String[] fileList; private String[] fileList;
private Map<String, byte[]> sha512 = new HashMap<>();
private String baseDirectory; private String baseDirectory;
private int UDPPort; private int UDPPort;
private DatagramSocket socket; private DatagramSocket socket;
@ -54,6 +61,7 @@ public class ServerManagementUDP implements Runnable {
this.baseDirectory = baseDirectory; this.baseDirectory = baseDirectory;
this.UDPPort = UDPPort; this.UDPPort = UDPPort;
initFileList(); initFileList();
initSha512();
try { try {
socket = new DatagramSocket(UDPPort); socket = new DatagramSocket(UDPPort);
} catch (SocketException e) { } catch (SocketException e) {
@ -134,6 +142,10 @@ public class ServerManagementUDP implements Runnable {
logger.writeUDP(e2, LogLevel.Error); logger.writeUDP(e2, LogLevel.Error);
} }
break; break;
case HASH_REQUEST:
logger.writeUDP("Received HASH_REQUEST", LogLevel.Action);
sendHashResponse(pd);
break;
default: default:
sendInternalError(pd); sendInternalError(pd);
} }
@ -165,7 +177,21 @@ public class ServerManagementUDP implements Runnable {
Arrays.sort(fileList); Arrays.sort(fileList);
} }
/** 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);
}
}
}
/** Send an internal error message. /** Send an internal error message.
* @param pd ProtocolP2PPacketUDP to respond * @param pd ProtocolP2PPacketUDP to respond
@ -179,5 +205,44 @@ public class ServerManagementUDP implements Runnable {
} }
} }
/** Send hash response to hash request
* @param pd Request received
*/
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<HashAlgorithm, byte[]> 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);
}
}
}
}
} }

@ -100,4 +100,20 @@ public class BytesArrayTools {
return size; return size;
} }
/** Remove trailing null bytes from string.
* @param str input string
* @return str without trailing null bytes
*/
public static String cleanStrings(String str) {
int i = 0;
int cpt = 0;
byte[] bArray = str.getBytes();
for (byte b : bArray) {
if (b != 0) {
cpt = i;
}
i++;
}
return new String(bArray, 0, cpt + 1);
}
} }

@ -98,6 +98,7 @@ public class Logger {
*/ */
public void writeTCP(Exception e, LogLevel logLevel) { public void writeTCP(Exception e, LogLevel logLevel) {
writeTCP(e.toString(), logLevel); writeTCP(e.toString(), logLevel);
e.printStackTrace();
} }
/** Appends log to filelog and print to stderr. /** Appends log to filelog and print to stderr.
@ -116,6 +117,7 @@ public class Logger {
*/ */
public void writeUDP(Exception e, LogLevel logLevel) { public void writeUDP(Exception e, LogLevel logLevel) {
writeUDP(e.toString(), logLevel); writeUDP(e.toString(), logLevel);
e.printStackTrace();
} }
} }

Loading…
Cancel
Save