All checks were successful
flavien's git/Projet_JAVA_P2P_STRI2A/pipeline/head This commit looks good
121 lines
5.5 KiB
Java
121 lines
5.5 KiB
Java
package protocolP2P;
|
||
import protocolP2P.RequestResponseCode;
|
||
import protocolP2P.FilePart;
|
||
import protocolP2P.FileList;
|
||
import protocolP2P.LoadRequest;
|
||
import protocolP2P.HashRequest;
|
||
import protocolP2P.HashResponse;
|
||
import localException.ProtocolError;
|
||
import localException.InternalError;
|
||
import localException.TransmissionError;
|
||
import localException.SizeError;
|
||
import tools.BytesArrayTools;
|
||
/** Representation of payload. If payload has a size, use subclasses instead.
|
||
* @author Louis Royer
|
||
* @author Flavien Haas
|
||
* @author JS Auge
|
||
* @version 1.0
|
||
*/
|
||
public class Payload {
|
||
protected RequestResponseCode requestResponseCode;
|
||
protected final static int PAYLOAD_SIZE_POSITION = 4;
|
||
protected final static int PAYLOAD_START_POSITION = 8;
|
||
|
||
/** Consructor used to create Payload with a payload size of zero using a RRCode.
|
||
* @param requestResponseCode Request/Response code associated with the payload
|
||
* @throws InternalError
|
||
*/
|
||
public Payload(RequestResponseCode requestResponseCode) throws InternalError {
|
||
/* asserts to help debugging */
|
||
assert requestResponseCode != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class";
|
||
assert requestResponseCode != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class";
|
||
assert requestResponseCode != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class";
|
||
assert requestResponseCode != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class";
|
||
assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class";
|
||
this.requestResponseCode = requestResponseCode;
|
||
checkRequestResponseCode(); // this can throw InternalError
|
||
}
|
||
|
||
/** Constructor used to create a Payload (when no more specific subclasses exists) using packet as parameter.
|
||
* If payload size is not empty, using subclass is required.
|
||
* @param packet the full packet received
|
||
* @throws ProtocolError
|
||
* @throws InternalError
|
||
* @throws TransmissionError
|
||
* @throws SizeError
|
||
*/
|
||
protected Payload(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError {
|
||
/* asserts to help debugging */
|
||
assert getPayloadSize(packet) + 8 <= packet.length : "Payload is truncated";
|
||
if (packet.length < getPayloadSize(packet) + 8) {
|
||
throw new TransmissionError();
|
||
}
|
||
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class";
|
||
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class";
|
||
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class";
|
||
requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]);
|
||
checkRequestResponseCode(); // this can throw InternalError
|
||
}
|
||
|
||
/** Used to check RRCode used is compatible with this class use, or if a more specific subclass is required.
|
||
* @throws InternalError
|
||
*/
|
||
private void checkRequestResponseCode() throws InternalError {
|
||
/* Incorrect use cases (use subclasses instead) */
|
||
if ((requestResponseCode == RequestResponseCode.LIST_RESPONSE && !(this instanceof FileList))
|
||
|| (requestResponseCode == RequestResponseCode.LOAD_RESPONSE && !(this instanceof FilePart))
|
||
|| (requestResponseCode == RequestResponseCode.LOAD_REQUEST && !(this instanceof LoadRequest))) {
|
||
throw new InternalError();
|
||
}
|
||
}
|
||
|
||
/** 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 {
|
||
// InternalError is impossible in this method on Payload class but still on subclasses
|
||
byte [] packet = new byte[8]; // java initialize all to zero
|
||
// size is zero (and this is the default)
|
||
// set request/response code
|
||
packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||
// bits 16-31 are reserved for future use
|
||
// payload size is 0 (this is what java have initialized Packet)
|
||
return packet;
|
||
}
|
||
|
||
/** Set payload’s size in a Packet.
|
||
* @param size integer representing payload size
|
||
* @param packet Packet to be completed
|
||
* @throws InternalError
|
||
*/
|
||
protected static void setPayloadSize(int size, byte[] packet) throws InternalError {
|
||
/* assert to help debugging */
|
||
assert size >= 0: "Payload size cannot be negative";
|
||
if (size < 0) {
|
||
// We don't throw SizeError
|
||
// because this is only for reception side
|
||
throw new InternalError();
|
||
}
|
||
BytesArrayTools.write(packet, PAYLOAD_SIZE_POSITION, size);
|
||
}
|
||
|
||
/** Get payload’s size from a Packet.
|
||
* @param packet the full Packet received
|
||
* @return integer representing payload size
|
||
* @throws SizeError
|
||
*/
|
||
protected static int getPayloadSize(byte[] packet) throws SizeError {
|
||
return BytesArrayTools.readInt(packet, PAYLOAD_SIZE_POSITION);
|
||
}
|
||
|
||
/** RRCode getter.
|
||
* @return Request/Response code
|
||
*/
|
||
public RequestResponseCode getRequestResponseCode() {
|
||
return requestResponseCode;
|
||
}
|
||
}
|