Projet_JAVA_P2P_STRI2A/src/protocolP2P/Payload.java
Louis 5c89bc6957 Add protocol elements for tracker
Needs to implements tracker now.
2020-03-20 18:23:59 +01:00

134 lines
7.2 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.RequestResponseCode;
import protocolP2P.FilePart;
import protocolP2P.FileList;
import protocolP2P.LoadRequest;
import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
import protocolP2P.DiscoverRequest;
import protocolP2P.DiscoverResponse;
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";
assert requestResponseCode != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class";
assert requestResponseCode != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse 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) + PAYLOAD_START_POSITION <= packet.length : "Payload is truncated";
if (packet.length < getPayloadSize(packet) + PAYLOAD_START_POSITION) {
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";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_REQUEST || (this instanceof HashRequest) : "HASH_REQUEST must use HashRequest class";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse 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))
|| (requestResponseCode == RequestResponseCode.HASH_REQUEST && !(this instanceof HashRequest))
|| (requestResponseCode == RequestResponseCode.HASH_RESPONSE && !(this instanceof HashResponse))
|| (requestResponseCode == RequestResponseCode.DISCOVER_REQUEST && !(this instanceof DiscoverRequest))
|| (requestResponseCode == RequestResponseCode.DISCOVER_RESPONSE && !(this instanceof DiscoverResponse))
) {
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 payloads 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 payloads 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;
}
}