diff --git a/doc/protocol.md b/doc/protocol.md index c5e5460..f8d5b94 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -22,6 +22,7 @@ x bytes: [(bytes 8-?): PAYLOAD] - `UNREGISTER` (0x05) - `RATIO` (0x06) - `UPDATE RATIO` (0x07) + - `SIZE` (0x08) - RESPONSES (msb is 1): - `LIST` (0x80) @@ -30,6 +31,7 @@ x bytes: [(bytes 8-?): PAYLOAD] - `DISCOVER` (0x83) - `RATIO` (0x86) - `DENIED` (0x87) + - `SIZE` (0x88) - `VERSION ERROR` (0xC0) - `PROTOCOL ERROR` (0xC1) - `INTERNAL ERROR` (0xC2) @@ -59,7 +61,6 @@ Payload contains ```text 8 bytes: [(bytes 8-15): OFFSET OF FILE CONTENT IN BYTES] -8 bytes: [(bytes 16-23): TOTAL FILESIZE] 4 bytes: [(bytes 24-27): FILENAME SIZE] (cannot be > to PAYLOAD_SIZE - 20 or be zero) y bytes: [] z bytes: [PARTIAL CONTENT] @@ -78,6 +79,23 @@ y bytes: [] ``` Possible responses: Load Response, or Denied +### Size +#### Size request +Payload contains + +```text +? bytes: filename +``` +Possible responses: Size response, EmptyFile or NotFound + +#### Size response +Payload contains + +```text +8 bytes: file size +? bytes: filename +``` + ### Hash #### Hash request Get hash of a file. Payload contains diff --git a/src/clientP2P/ClientDownload.java b/src/clientP2P/ClientDownload.java index c4405c3..99aabbd 100644 --- a/src/clientP2P/ClientDownload.java +++ b/src/clientP2P/ClientDownload.java @@ -29,7 +29,8 @@ import protocolP2P.HashResponse; import protocolP2P.HashRequest; import protocolP2P.Payload; import protocolP2P.FilePart; -import protocolP2P.LoadRequest; +import protocolP2P.SizeRequest; +import protocolP2P.SizeResponse; import protocolP2P.ProtocolP2PPacket; import clientP2P.ClientDownloadPart; import tools.HostItem; @@ -291,39 +292,22 @@ public abstract class ClientDownload extends ServeErrors implements Runnable { * @throws InternalError */ protected void setSize() throws InternalError { - ProtocolP2PPacket d = createProtocolP2PPacket(new LoadRequest(filename, 0, MAX_PARTIAL_SIZE, client)); + ProtocolP2PPacket d = createProtocolP2PPacket(new SizeRequest(filename)); 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."); + assert p instanceof SizeResponse : "This payload must be instance of SizeResponse"; + if (!(p instanceof SizeResponse)) { writeLog("cannot get size.", LogLevel.Error); throw new InternalError(); } else { - FilePart fp = (FilePart)p; + SizeResponse fp = (SizeResponse)p; if (!fp.getFilename().equals(filename)) { - System.err.println("Error: wrong file received: `" + fp.getFilename() + "`"); - writeLog("wrong file received: `" + fp.getFilename() + "`", LogLevel.Error); + writeLog("wrong file size 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(); - } + size = fp.getTotalSize(); } } catch (EmptyDirectory e) { System.err.println("Error: empty directory."); @@ -395,7 +379,7 @@ public abstract class ClientDownload extends ServeErrors implements Runnable { // 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 totalSize >= partialContent.length : "totalSize must be greater than partialContent.length"; assert offset >= 0 : "offset cannot be negative"; assert filename != null : "filename is required"; - if (totalSize < 0 || partialContent.length == 0 || totalSize < partialContent.length - || offset < 0 || filename == null) { + if (partialContent.length == 0 || offset < 0 || filename == null) { throw new InternalError(); } this.filename = filename; - this.totalSize = totalSize; this.offset = offset; this.partialContent = partialContent; } @@ -63,7 +57,6 @@ public class FilePart extends Payload { throw new InternalError(); } setOffset(packet); // this can throw SizeError - setTotalSize(packet); // this can throw SizeError setFilename(packet); // this can throw ProtocolError, SizeError setPartialContent(packet); // this can throw SizeError } @@ -84,8 +77,6 @@ public class FilePart extends Payload { setPayloadSize(size - PAYLOAD_START_POSITION, packet); // write offset to Packet BytesArrayTools.write(packet, OFFSET_POSITION, offset); - // write totalSize to Packet - BytesArrayTools.write(packet, TOTAL_FILESIZE_POSITION, totalSize); // write filename’s size to Packet BytesArrayTools.write(packet, FILENAME_SIZE_POSITION, filename.length()); // write filename to Packet @@ -102,13 +93,6 @@ public class FilePart extends Payload { private void setOffset(byte[] packet) throws SizeError { offset = BytesArrayTools.readLong(packet, OFFSET_POSITION); } - /** Write from Packet into totalSize. - * @param packet received Packet - * @throws SizeError - */ - private void setTotalSize(byte[] packet) throws SizeError { - totalSize = BytesArrayTools.readLong(packet, TOTAL_FILESIZE_POSITION); - } /** Read filename’s size from Packet. * @param packet received Packet @@ -171,11 +155,4 @@ public class FilePart extends Payload { public long getOffset() { return offset; } - - /** totalSize getter. - * @return totalSize - */ - public long getTotalSize() { - return totalSize; - } } diff --git a/src/protocolP2P/LoadRequest.java b/src/protocolP2P/LoadRequest.java index b6622a0..a662f62 100644 --- a/src/protocolP2P/LoadRequest.java +++ b/src/protocolP2P/LoadRequest.java @@ -86,7 +86,7 @@ public class LoadRequest extends Payload { // compute size int filenameSize = filename.length(); String hostname = hostItem.getHostname(); - int size = 1 + FILENAME_POSITION + filenameSize + 2 + hostname.length(); + int size = FILENAME_POSITION + filenameSize + 2 + hostname.length(); byte[] packet = new byte[size]; // java initialize all to zero // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; diff --git a/src/protocolP2P/Payload.java b/src/protocolP2P/Payload.java index e41f94c..6fca87d 100644 --- a/src/protocolP2P/Payload.java +++ b/src/protocolP2P/Payload.java @@ -13,6 +13,8 @@ import protocolP2P.RatioRequest; import protocolP2P.RatioResponse; import protocolP2P.UpdateRatio; import protocolP2P.Denied; +import protocolP2P.SizeRequest; +import protocolP2P.SizeResponse; import localException.ProtocolError; import localException.InternalError; import localException.TransmissionError; @@ -48,6 +50,8 @@ public class Payload { assert requestResponseCode != RequestResponseCode.RATIO_RESPONSE || (this instanceof RatioResponse) : "RATIO_RESPONSE must use RatioResponse class"; assert requestResponseCode != RequestResponseCode.UPDATE_RATIO || (this instanceof UpdateRatio) : "UPDATE_RATIO must use UpdateRatio class"; assert requestResponseCode != RequestResponseCode.DENIED || (this instanceof Denied) : "DENIED must use Denied class"; + assert requestResponseCode != RequestResponseCode.SIZE_REQUEST || (this instanceof SizeRequest) : "SIZE_REQUEST must use SizeRequest class"; + assert requestResponseCode != RequestResponseCode.SIZE_RESPONSE || (this instanceof SizeResponse) : "SIZE_RESPONSE must use SizeResponse class"; this.requestResponseCode = requestResponseCode; checkRequestResponseCode(); // this can throw InternalError } @@ -79,6 +83,8 @@ public class Payload { assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.RATIO_RESPONSE || (this instanceof RatioResponse) : "RATIO_RESPONSE must use RatioResponse class"; assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.UPDATE_RATIO || (this instanceof UpdateRatio) : "UPDATE_RATIO must use UpdateRatio class"; assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DENIED || (this instanceof Denied) : "DENIED must use Denied class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.SIZE_REQUEST || (this instanceof SizeRequest) : "SIZE_REQUEST must use SizeRequest class"; + assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.SIZE_RESPONSE || (this instanceof SizeResponse) : "SIZE_RESPONSE must use SizeResponse class"; requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]); checkRequestResponseCode(); // this can throw InternalError } @@ -101,6 +107,8 @@ public class Payload { || (requestResponseCode == RequestResponseCode.RATIO_RESPONSE && !(this instanceof RatioResponse)) || (requestResponseCode == RequestResponseCode.UPDATE_RATIO && !(this instanceof UpdateRatio)) || (requestResponseCode == RequestResponseCode.DENIED && !(this instanceof Denied)) + || (requestResponseCode == RequestResponseCode.SIZE_REQUEST && !(this instanceof SizeRequest)) + || (requestResponseCode == RequestResponseCode.SIZE_RESPONSE && !(this instanceof SizeResponse)) ) { throw new InternalError(); } diff --git a/src/protocolP2P/ProtocolP2PPacketTCP.java b/src/protocolP2P/ProtocolP2PPacketTCP.java index 0c348e5..52da813 100644 --- a/src/protocolP2P/ProtocolP2PPacketTCP.java +++ b/src/protocolP2P/ProtocolP2PPacketTCP.java @@ -22,6 +22,8 @@ import protocolP2P.RatioRequest; import protocolP2P.RatioResponse; import protocolP2P.UpdateRatio; import protocolP2P.Denied; +import protocolP2P.SizeRequest; +import protocolP2P.SizeResponse; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; @@ -147,6 +149,7 @@ public class ProtocolP2PPacketTCP < T extends Payload > extends ProtocolP2PPacke case NOT_A_TRACKER: case RATIO_RESPONSE: case DENIED: + case SIZE_RESPONSE: // we were expecting a request, but we are receiving a response throw new ProtocolError(); default : @@ -337,6 +340,12 @@ public class ProtocolP2PPacketTCP < T extends Payload > extends ProtocolP2PPacke case DENIED: payload = (Payload) new Denied(packet); break; + case SIZE_REQUEST: + payload = (Payload) new SizeRequest(packet); + break; + case SIZE_RESPONSE: + payload = (Payload) new SizeResponse(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 894be60..5073d0e 100644 --- a/src/protocolP2P/ProtocolP2PPacketUDP.java +++ b/src/protocolP2P/ProtocolP2PPacketUDP.java @@ -23,6 +23,8 @@ import protocolP2P.RatioRequest; import protocolP2P.RatioResponse; import protocolP2P.UpdateRatio; import protocolP2P.Denied; +import protocolP2P.SizeRequest; +import protocolP2P.SizeResponse; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketAddress; @@ -140,6 +142,7 @@ public class ProtocolP2PPacketUDP < T extends Payload> extends ProtocolP2PPacket case NOT_A_TRACKER: case RATIO_RESPONSE: case DENIED: + case SIZE_RESPONSE: // we were expecting a request, but we are receiving a response throw new ProtocolError(); default : @@ -322,6 +325,12 @@ public class ProtocolP2PPacketUDP < T extends Payload> extends ProtocolP2PPacket case DENIED: payload = (Payload) new Denied(packet); break; + case SIZE_REQUEST: + payload = (Payload) new SizeRequest(packet); + break; + case SIZE_RESPONSE: + payload = (Payload) new SizeResponse(packet); + break; default: payload = new Payload(packet); // this can throw TransmissionError break; diff --git a/src/protocolP2P/RatioRequest.java b/src/protocolP2P/RatioRequest.java index 87e76bf..ace53c7 100644 --- a/src/protocolP2P/RatioRequest.java +++ b/src/protocolP2P/RatioRequest.java @@ -50,7 +50,7 @@ public class RatioRequest extends Payload { protected byte[] toPacket() throws InternalError { String hostname = hostItem.getHostname(); // compute total size - int size = 1 + HOSTNAME_START_POSITION + hostname.length(); + int size = HOSTNAME_START_POSITION + hostname.length(); byte[] packet = new byte[size]; // java initialize all to zero // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; diff --git a/src/protocolP2P/RatioResponse.java b/src/protocolP2P/RatioResponse.java index 05e07ca..b59d7f6 100644 --- a/src/protocolP2P/RatioResponse.java +++ b/src/protocolP2P/RatioResponse.java @@ -61,7 +61,7 @@ public class RatioResponse extends Payload { protected byte[] toPacket() throws InternalError { String hostname = hostItem.getHostname(); // compute total size - int size = 1 + HOSTNAME_START_POSITION + hostname.length(); + int size = HOSTNAME_START_POSITION + hostname.length(); byte[] packet = new byte[size]; // java initialize all to zero // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; diff --git a/src/protocolP2P/Register.java b/src/protocolP2P/Register.java index 4f49022..3de3328 100644 --- a/src/protocolP2P/Register.java +++ b/src/protocolP2P/Register.java @@ -50,7 +50,7 @@ public class Register extends Payload { protected byte[] toPacket() throws InternalError { String hostname = hostItem.getHostname(); // compute total size - int size = 1 + HOSTNAME_START_POSITION + hostname.length(); + int size = HOSTNAME_START_POSITION + hostname.length(); byte[] packet = new byte[size]; // java initialize all to zero // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; diff --git a/src/protocolP2P/RequestResponseCode.java b/src/protocolP2P/RequestResponseCode.java index 1941870..7a51a7d 100644 --- a/src/protocolP2P/RequestResponseCode.java +++ b/src/protocolP2P/RequestResponseCode.java @@ -20,12 +20,14 @@ public enum RequestResponseCode { UNREGISTER(CodeType.REQUEST_TRACKER, (byte)0x05), RATIO_REQUEST(CodeType.REQUEST_TRACKER, (byte)0x06), UPDATE_RATIO(CodeType.REQUEST_TRACKER, (byte)0x07), + SIZE_REQUEST(CodeType.REQUEST, (byte)0x08), LIST_RESPONSE(CodeType.RESPONSE, (byte)0x80), LOAD_RESPONSE(CodeType.RESPONSE, (byte)0x81), HASH_RESPONSE(CodeType.RESPONSE, (byte)0x82), DISCOVER_RESPONSE(CodeType.RESPONSE, (byte)0x83), RATIO_RESPONSE(CodeType.RESPONSE, (byte)0x86), DENIED(CodeType.RESPONSE, (byte)0x87), + SIZE_RESPONSE(CodeType.RESPONSE, (byte)0x88), VERSION_ERROR(CodeType.ERROR, (byte)0xC0), PROTOCOL_ERROR(CodeType.ERROR, (byte)0xC1), INTERNAL_ERROR(CodeType.ERROR, (byte)0xC2), diff --git a/src/protocolP2P/SizeRequest.java b/src/protocolP2P/SizeRequest.java new file mode 100644 index 0000000..0e23b5c --- /dev/null +++ b/src/protocolP2P/SizeRequest.java @@ -0,0 +1,70 @@ +package protocolP2P; +import protocolP2P.Payload; +import protocolP2P.RequestResponseCode; +import localException.TransmissionError; +import localException.ProtocolError; +import localException.InternalError; +import localException.SizeError; +import tools.BytesArrayTools; +import tools.HostItem; + +/** Representation of payload for load request. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class SizeRequest extends Payload { + private String filename; + /** Constructor (typically used by the client) with a filename parameter. + * @param filename name of the file to download. Must not be empty. + */ + public SizeRequest(String filename) throws InternalError { + super(RequestResponseCode.SIZE_REQUEST); + /* assert to help debugging */ + assert filename.length() != 0 : "Payload size of LoadRequest must not be empty"; + if (filename.length() == 0) { + throw new InternalError(); + } + 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 SizeRequest(byte[] packet) throws TransmissionError, SizeError, ProtocolError, InternalError { + super(packet); + /* Read filename */ + int size = getPayloadSize(packet); + filename = BytesArrayTools.readString(packet, 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 { + int size = PAYLOAD_START_POSITION + filename.length(); + byte[] packet = new byte[size]; // 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 + BytesArrayTools.write(packet, filename, PAYLOAD_START_POSITION); + return packet; + } + + /** filename getter. + * @return filename + */ + public String getFilename() { + return filename; + } +} diff --git a/src/protocolP2P/SizeResponse.java b/src/protocolP2P/SizeResponse.java new file mode 100644 index 0000000..f02b01b --- /dev/null +++ b/src/protocolP2P/SizeResponse.java @@ -0,0 +1,86 @@ +package protocolP2P; +import protocolP2P.Payload; +import protocolP2P.RequestResponseCode; +import localException.ProtocolError; +import localException.InternalError; +import localException.SizeError; +import localException.TransmissionError; +import tools.BytesArrayTools; + +/** Representation of payload for size response. + * @author Louis Royer + * @author Flavien Haas + * @author JS Auge + * @version 1.0 + */ +public class SizeResponse extends Payload { + private String filename; + private long totalSize; + static final private int TOTAL_SIZE_POSITION = PAYLOAD_START_POSITION; + static final private int FILENAME_POSITION = TOTAL_SIZE_POSITION + 8; + + /** Constructor (typically used by server) with informations about file part to send as parameters. + * @param filename name of the file + * @param totalSize size of the file + * @throws InternalError + */ + public SizeResponse(String filename, long totalSize) throws InternalError { + super(RequestResponseCode.SIZE_RESPONSE); + /* asserts to help debugging */ + assert totalSize >= 0 : "offset cannot be negative"; + assert filename != null : "filename is required"; + if (filename == null || totalSize < 0) { + throw new InternalError(); + } + this.filename = filename; + this.totalSize = totalSize; + } + + /** Constructor (typically used by client) with Packet received as parameter. + * @param packet the full Packet received + * @throws SizeError + * @throws InternalError + * @throws TransmissionError + */ + protected SizeResponse(byte[] packet) throws TransmissionError, SizeError, ProtocolError, InternalError { + super(packet); + int filenameSize = getPayloadSize(packet) - FILENAME_POSITION + PAYLOAD_START_POSITION; + totalSize = BytesArrayTools.readLong(packet, TOTAL_SIZE_POSITION); + filename = BytesArrayTools.readString(packet, FILENAME_POSITION, filenameSize); + } + + /** 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 = FILENAME_POSITION + filename.length(); + byte[] packet = new byte[size]; // 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 totalSize to Packet + BytesArrayTools.write(packet, TOTAL_SIZE_POSITION, totalSize); + // write filename to Packet + BytesArrayTools.write(packet, filename, FILENAME_POSITION); + return packet; + } + + /** filename getter. + * @return String + */ + public String getFilename() { + return filename; + } + + /** totalSize getter. + * @return totalSize + */ + public long getTotalSize() { + return totalSize; + } +} diff --git a/src/protocolP2P/Unregister.java b/src/protocolP2P/Unregister.java index 35e34a8..88294f9 100644 --- a/src/protocolP2P/Unregister.java +++ b/src/protocolP2P/Unregister.java @@ -50,7 +50,7 @@ public class Unregister extends Payload { protected byte[] toPacket() throws InternalError { String hostname = hostItem.getHostname(); // compute total size - int size = 1 + HOSTNAME_START_POSITION + hostname.length(); + int size = HOSTNAME_START_POSITION + hostname.length(); byte[] packet = new byte[size]; // java initialize all to zero // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; diff --git a/src/protocolP2P/UpdateRatio.java b/src/protocolP2P/UpdateRatio.java index b373623..334cda0 100644 --- a/src/protocolP2P/UpdateRatio.java +++ b/src/protocolP2P/UpdateRatio.java @@ -62,7 +62,7 @@ public class UpdateRatio extends Payload { protected byte[] toPacket() throws InternalError { String[] hostnames = { server.getHostname(), client.getHostname()}; // compute total size - int size = 1 + HOSTNAMES_START_POSITION + BytesArrayTools.computeStringArraySize(hostnames, "\n"); + int size = HOSTNAMES_START_POSITION + BytesArrayTools.computeStringArraySize(hostnames, "\n"); byte[] packet = new byte[size]; // java initialize all to zero // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; diff --git a/src/serverP2P/ServerManagement.java b/src/serverP2P/ServerManagement.java index de4fdd2..e9f8fcc 100644 --- a/src/serverP2P/ServerManagement.java +++ b/src/serverP2P/ServerManagement.java @@ -14,8 +14,11 @@ import protocolP2P.HashRequest; import protocolP2P.HashResponse; import protocolP2P.HashAlgorithm; import protocolP2P.Unregister; +import protocolP2P.SizeRequest; +import protocolP2P.SizeResponse; import java.nio.file.Paths; import java.nio.file.Files; +import java.io.File; import java.util.Arrays; import java.util.Map; import java.util.HashMap; @@ -153,7 +156,7 @@ public abstract class ServerManagement extends ServeErrors implements Runnable { if (load.length == 0) { sendEmptyFile(pd); } else { - pd.sendResponse(createProtocolP2PPacket((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); + pd.sendResponse(createProtocolP2PPacket((Payload)(new FilePart(filename, offset, load)))); } } catch (Exception e2) { writeLog(e2, LogLevel.Error); @@ -177,6 +180,42 @@ public abstract class ServerManagement extends ServeErrors implements Runnable { } } + /** Send response to size request + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendSizeResponse(T pd) { + Payload p = pd.getPayload(); + assert p instanceof SizeRequest : "payload must be an instance of SizeRequest"; + if (!(p instanceof SizeRequest)) { + sendInternalError(pd); + } else { + String filename = ((SizeRequest)p).getFilename(); + try { + long size = (new File(baseDirectory + filename)).length(); + String[] fileList = fileListWatcher.getFileList(); + if (Arrays.binarySearch(fileList, filename) >= 0) { + try { + if (size == 0) { + sendEmptyFile(pd); + } else { + pd.sendResponse(createProtocolP2PPacket((new SizeResponse(filename, size)))); + } + } catch (Exception e2) { + writeLog(e2, LogLevel.Error); + } + } else { + throw new IOException(); // to send a NOT_FOUND in the catch block + } + } catch (IOException e) { + try { + sendNotFound(pd); + } catch (Exception e2) { + writeLog(e2, LogLevel.Debug); + } + } + } + } + /** Getter for tracker socket */ @@ -205,6 +244,10 @@ public abstract class ServerManagement extends ServeErrors implements Runnable { writeLog("Received LOAD_REQUEST from host " + pd.getHostItem(), LogLevel.Action); sendLoadResponse(pd); break; + case SIZE_REQUEST: + writeLog("Received SIZE_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendSizeResponse(pd); + break; case LIST_REQUEST: writeLog("Received LIST_REQUEST from host " + pd.getHostItem(), LogLevel.Action); sendListResponse(pd);