182 lines
6.4 KiB
Java
182 lines
6.4 KiB
Java
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 load response.
|
||
* @author Louis Royer
|
||
* @author Flavien Haas
|
||
* @author JS Auge
|
||
* @version 1.0
|
||
*/
|
||
public class FilePart extends Payload {
|
||
private String filename;
|
||
private long totalSize;
|
||
private long offset;
|
||
private byte[] partialContent;
|
||
static final private int OFFSET_POSITION = PAYLOAD_START_POSITION;
|
||
static final private int TOTAL_FILESIZE_POSITION = OFFSET_POSITION + 8;
|
||
static final private int FILENAME_SIZE_POSITION = TOTAL_FILESIZE_POSITION + 8;
|
||
static final private int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4;
|
||
|
||
/** Constructor (typically used by server) with informations about file part to send as parameters.
|
||
* @param filename name of the file to send
|
||
* @param totalSize total size of the file to send
|
||
* @param offset where in the file begins the part we are sending
|
||
* @param partialContent content of the file we send
|
||
* @throws InternalError
|
||
*/
|
||
public FilePart(String filename, long totalSize, long offset, byte[] partialContent) throws InternalError {
|
||
super(RequestResponseCode.LOAD_RESPONSE);
|
||
/* asserts to help debugging */
|
||
assert totalSize >= 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) {
|
||
throw new InternalError();
|
||
}
|
||
this.filename = filename;
|
||
this.totalSize = totalSize;
|
||
this.offset = offset;
|
||
this.partialContent = partialContent;
|
||
}
|
||
|
||
/** Constructor (typically used by client) with Packet received as parameter.
|
||
* @param packet the full Packet received
|
||
* @throws SizeError
|
||
* @throws InternalError
|
||
* @throws TransmissionError
|
||
*/
|
||
protected FilePart(byte[] packet) throws TransmissionError, SizeError, ProtocolError, InternalError {
|
||
super(packet);
|
||
/* assert to help debugging */
|
||
assert requestResponseCode == RequestResponseCode.LOAD_RESPONSE : "FilePart subclass is incompatible with this Packet, request/response code must be checked before using this constructor";
|
||
/* InternalErrorException */
|
||
if (requestResponseCode != RequestResponseCode.LOAD_RESPONSE) {
|
||
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
|
||
}
|
||
|
||
/** 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() + partialContent.length;
|
||
byte[] packet = new byte[size + 1]; // 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 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
|
||
BytesArrayTools.write(packet, filename, FILENAME_POSITION);
|
||
// write partialContent to Packet
|
||
BytesArrayTools.write(packet, partialContent, FILENAME_POSITION + filename.length());
|
||
return packet;
|
||
}
|
||
|
||
/** Write from Packet into offset.
|
||
* @param packet received Packet
|
||
* @throws SizeError
|
||
*/
|
||
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
|
||
* @throws ProtocolError
|
||
* @throws SizeError
|
||
* @return filename’s size
|
||
*/
|
||
private int getFilenameSize(byte[] packet) throws SizeError, ProtocolError {
|
||
int size = BytesArrayTools.readInt(packet, FILENAME_SIZE_POSITION); // this can throw SizeError
|
||
// filename size cannot be zero
|
||
if (size == 0) {
|
||
throw new ProtocolError();
|
||
}
|
||
// cannot excess packet size
|
||
if ((FILENAME_POSITION + size) > (getPayloadSize(packet) + OFFSET_POSITION)) {
|
||
throw new ProtocolError();
|
||
}
|
||
return size;
|
||
}
|
||
|
||
/** Write from Packet into filename.
|
||
* @param packet received Packet
|
||
* @throws ProtocolError
|
||
* @throws SizeError
|
||
* @throws InternalError
|
||
*/
|
||
private void setFilename(byte[] packet) throws ProtocolError, SizeError, InternalError {
|
||
int filenameSize = getFilenameSize(packet); // this can throw ProtocolError or SizeError
|
||
filename = BytesArrayTools.readString(packet, FILENAME_POSITION, filenameSize);
|
||
}
|
||
|
||
/** Write from Packet into partialContent.
|
||
* @param packet received Packet
|
||
* @throws SizeError
|
||
* @throws ProtocolError
|
||
*/
|
||
private void setPartialContent(byte[] packet) throws ProtocolError, SizeError {
|
||
int start = FILENAME_POSITION + getFilenameSize(packet); // this can throw SizeError or ProtocolError
|
||
int end = OFFSET_POSITION + getPayloadSize(packet); // this can throw SizeError
|
||
partialContent = BytesArrayTools.readByteArray(packet, start, end);
|
||
}
|
||
|
||
/** partialContent getter.
|
||
* @return partialcontent
|
||
*/
|
||
public byte[] getPartialContent() {
|
||
return partialContent;
|
||
}
|
||
|
||
/** filename getter.
|
||
* @return String
|
||
*/
|
||
public String getFilename() {
|
||
return filename;
|
||
}
|
||
|
||
/** offset getter.
|
||
* @return offset
|
||
*/
|
||
public long getOffset() {
|
||
return offset;
|
||
}
|
||
|
||
/** totalSize getter.
|
||
* @return totalSize
|
||
*/
|
||
public long getTotalSize() {
|
||
return totalSize;
|
||
}
|
||
}
|