Projet_JAVA_P2P_STRI2A/src/protocolP2P/FilePart.java

164 lines
5.9 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 protocolP2P;
import protocolP2P.Payload;
import protocolP2P.RequestResponseCode;
import exception.ProtocolError;
import exception.InternalError;
import exception.SizeError;
import tools.BytesArrayTools;
import java.util.Arrays;
import java.io.UnsupportedEncodingException;
/** 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;
/** 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";
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 datagram received as parameter.
* @param datagram the full datagram received
* @throws SizeError
* @throws InternalError
*/
protected FilePart(byte[] datagram) throws SizeError, ProtocolError, InternalError {
super(datagram);
/* assert to help debugging */
assert requestResponseCode == RequestResponseCode.LOAD_RESPONSE : "FilePart subclass is incompatible with this datagram, request/response code must be checked before using this constructor";
/* InternalErrorException */
if (requestResponseCode != RequestResponseCode.LOAD_RESPONSE) {
throw new InternalError();
}
setOffset(datagram); // this can throw SizeError
setTotalSize(datagram); // this can throw SizeError
setFilename(datagram); // this can throw ProtocolError, SizeError
setPartialContent(datagram); // this can throw SizeError
}
/** Returns a byte[] containing datagram with padding.
* This datagram is still incomplete and should not be send directly.
* ProtocolP2PDatagram will use this method to generate the complete datagram.
* @return datagram with padding
* @throws InternalError
*/
protected byte[] toDatagram() throws InternalError {
//TODO : calculate payload size
int size = 24 + filename.length() + 1;
byte[] datagram = new byte[size]; // java initialize all to zero
// size is keep blank (ProtocolP2PDatagram will handle it)
// set request/response code
datagram[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
// bits 16-31 are reserved for future use
setPayloadSize(size, datagram);
// write offset to datagram (Byte 8)
BytesArrayTools.write(datagram, 8, offset);
// write totalSize to datagram (Byte 16)
BytesArrayTools.write(datagram, 16, totalSize);
// write filenames size to datagram
BytesArrayTools.write(datagram, 24, filename.length());
//TODO : write filename to datagram
try {
byte[] bFilename = filename.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new InternalError();
}
//TODO : write partialContent to datagram
return datagram;
}
/** Write from bytes 8 to 15 of datagram into offset.
* @param datagram received datagram
* @throws SizeError
*/
private void setOffset(byte[] datagram) throws SizeError {
offset = BytesArrayTools.readLong(datagram, 8);
}
/** Write from bytes 16 to 23 of datagram into totalSize.
* @param datagram received datagram
* @throws SizeError
*/
private void setTotalSize(byte[] datagram) throws SizeError {
totalSize = BytesArrayTools.readLong(datagram, 16);
}
/** Read filenames size from bytes 24 to 28 of datagram.
* @param datagram received datagram
* @throws ProtocolError
* @throws SizeError
* @return filenames size
*/
private int getFilenameSize(byte[] datagram) throws SizeError, ProtocolError {
int size = BytesArrayTools.readInt(datagram, 24); // this can throw SizeError
// filename size cannot be zero
if (size == 0) {
throw new ProtocolError();
}
// offset (8B) + totalSize (8B) + filenameSize (4B) = 20B
if ((20 + size) > getPayloadSize(datagram)) {
throw new ProtocolError();
}
return size;
}
/** Write filename from byte 24 to byte (24 + (filenameSize - 1)) of datagram.
* @param datagram received datagram
* @throws ProtocolError
* @throws SizeError
* @throws InternalError
*/
private void setFilename(byte[] datagram) throws ProtocolError, SizeError, InternalError {
int filenameSize = getFilenameSize(datagram); // this can throw ProtocolError or SizeError
try {
filename = new String(datagram, 24, filenameSize, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new InternalError();
}
}
/** Write partialContent from byte (24 + filenameSize) to byte (8 + payloadSize) of datagram.
* @param datagram received datagram
* @throws SizeError
* @throws ProtocolError
*/
private void setPartialContent(byte[] datagram) throws ProtocolError, SizeError {
int start = 24 + getFilenameSize(datagram); // this can throw SizeError or ProtocolError
int end = 8 + getPayloadSize(datagram); // this can throw SizeError
try {
partialContent = Arrays.copyOfRange(datagram, start, end+1);
} catch (ArrayIndexOutOfBoundsException e) {
throw new ProtocolError();
}
}
}