Début de l’implémentation du protocole binaire

Reste des TODO dans FileList.java et dans FilePart.java + la
documentation à faire.

Ça ne compile pas encore, et c’est normal (à cause des TODOs).
This commit is contained in:
Louis Royer 2020-01-21 23:47:43 +01:00
parent f4e318dfe5
commit 026008473a
7 changed files with 238 additions and 4 deletions

View File

@ -26,7 +26,7 @@ All messages begins with `P2P-JAVA-PROJECT VERSION 1.0\n` (this version of the p
## Requests and responses codes
- REQUESTS (msb is 0):
- `LIST` (0x00)
- `DOWNLOAD` (0x01)
- `LOAD` (0x01)
- RESPONSES (msb is 1):
- `LIST` (0x80)
@ -39,10 +39,10 @@ All messages begins with `P2P-JAVA-PROJECT VERSION 1.0\n` (this version of the p
Payload size for list request is always zero.
Payload for list response is filenames separated by `\n`.
### Download
### Load
#### Not found
Response when the file requested is not found on the server.
Payload size for Not found is zero
Payload size for Not found is zero.
#### Protocol error
Response when the request cannot be interpreted.
@ -50,7 +50,7 @@ Payload size for Protocol error is zero
#### Internal error
Response in internal failure case.
Payload size for Internal error is zero
Payload size for Internal error is zero.
#### Load response
Payload contains
@ -61,3 +61,6 @@ Payload contains
[<FILENAME>\n]
[FILE CONTENT]
```
#### Load request
Payload contains only the name of the file to load.

View File

@ -0,0 +1,5 @@
package protocolP2P;
public enum CodeType {
REQUEST,
RESPONSE
}

View File

@ -0,0 +1,36 @@
package protocolP2P;
import java.util.ArrayList;
import protocolP2P.Payload;
import protocolP2P.RequestResponseCode;
import exception.ProtocolError;
public class FileList extends Payload {
private final static RequestResponseCode requestResponseCode = RequestResponseCode.LIST_RESPONSE;
private ArrayList<String> content;
public FileList(ArrayList<String> content) {
this.content = content;
}
public FileList(byte[] datagram) throws ProtocolError {
//TODO
assert RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]) == RequestResponseCode.LIST_RESPONSE : "FileList subclass is incompatible with this datagram, request/response code must be checked before using this constructor";
int size = (datagram[PAYLOAD_SIZE_POSITON] << (8*3)) | (datagram[PAYLOAD_SIZE_POSITON+1] << (8*2)) | (datagram[PAYLOAD_SIZE_POSITON+2] << 8) | datagram[PAYLOAD_SIZE_POSITON+3];
}
/** To datagram with padding */
public byte[] toDatagram() {
byte[] datagram; // 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
//TODO size
int size = ;
for(i=0;i<4;i++) {
datagram[Payload.PAYLOAD_SIZE_POSITON + i] = (byte) (size >> (8 * (3 - i)) & 0xFF);
}
//TODO content
}
}

View File

@ -0,0 +1,41 @@
package protocolP2P;
import protocolP2P.Payload;
import protocolP2P.RequestResponseCode;
import exception.ProtocolError;
public class FilePart extends Payload {
private static final RequestResponseCode requestResponseCode = RequestResponseCode.LOAD_RESPONSE;
private String filename;
private int totalSize;
private int offset;
private byte[] partialContent;
public FilePart(String filename, int totalSize, int offset, byte[] partialContent) {
this.filename = filename;
this.totalSize = totalSize;
this.offset = offset;
this.partialContent = partialContent;
}
public FilePart(byte[] datagram) throws ProtocolError {
//TODO
assert RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]) == RequestResponseCode.LOAD_RESPONSE : "FilePart subclass is incompatible with this datagram, request/response code must be checked before using this constructor";
int size = (datagram[PAYLOAD_SIZE_POSITON] << (8*3)) | (datagram[PAYLOAD_SIZE_POSITON+1] << (8*2)) | (datagram[PAYLOAD_SIZE_POSITON+2] << 8) | datagram[PAYLOAD_SIZE_POSITON+3];
}
/** To datagram with padding */
public byte[] toDatagram() {
byte[] datagram; // 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
//TODO size
int size = ;
for(i=0;i<4;i++) {
datagram[Payload.PAYLOAD_SIZE_POSITON + i] = (byte) (size >> (8 * (3 - i)) & 0xFF);
}
//TODO content
}
}

View File

@ -0,0 +1,34 @@
package protocolP2P;
import protocolP2P.RequestResponseCode;
import protocolP2P.FilePart;
import protocolP2P.FileList;
import exception.ProtocolError;
public class Payload {
private RequestResponseCode requestResponseCode;
protected final static int PAYLOAD_SIZE_POSITON = 4;
protected final static int PAYLOAD_START_POSITION = 8;
/** To create request/response with a payload size of zero */
public Payload(RequestResponseCode requestResponseCode) {
assert requestResponseCode != requestResponseCode.LIST_RESPONSE : "LIST_RESPONSE must use FilePart class";
assert requestResponseCode != requestResponseCode.LOAD_RESPONSE : "LOAD_RESPONSE must use FileList class";
this.requestResponseCode = requestResponseCode;
}
public Payload(byte[] datagram) throws ProtocolError {
assert RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LIST_RESPONSE : "LIST_RESPONSE must use FilePart class";
assert RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_RESPONSE : "LOAD_RESPONSE must use FileList class";
requestResponseCode = RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]);
}
/** Payload with padding */
public byte[] toDatagram() {
byte [] datagram = new byte[8]; // 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
// payload size is 0 (this is what java have initialized datagram)
}
}

View File

@ -0,0 +1,53 @@
package protocolP2P;
import exception.ProtocolError;
import protocolP2P.Payload;
import protocolP2P.RequestResponseCode;
import java.util.ArrayList;
import java.lang.Byte;
public class ProtocolP2PDatagram {
private final static byte PROTOCOL_VERSION = 0x11;
private final static int VERSION_POSITON = 0;
private byte version;
private Payload payload;
public ProtocolP2PDatagram(Payload payload) {
version = PROTOCOL_VERSION;
this.payload = payload;
}
public ProtocolP2PDatagram(byte[] datagram) throws ProtocolError {
// unwrap version
version = datagram[VERSION_POSITON];
checkProtocolVersion(); // this can throw ProtocolError
RequestResponseCode r = RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]); // this can throw ProtocolError
switch (r) {
case RequestResponseCode.LIST_RESPONSE:
payload = (Payload) new FileList(datagram);
break;
case RequestResponseCode.LOAD_RESPONSE:
payload = (Payload) new FilePart(datagram);
break;
default:
payload = new Payload(datagram);
break;
}
}
public byte[] toDatagram() {
byte[] datagram = payload.toDatagram();
datagram[VERSION_POSITON] = version;
return datagram;
}
public Payload getPayload() {
return payload;
}
private void checkProtocolVersion() throws ProtocolError {
if (PROTOCOL_VERSION != version) {
throw new ProtocolError();
}
}
}

View File

@ -0,0 +1,62 @@
package protocolP2P;
import protocolP2P.CodeType;
import exception.ProtocolError;
import java.util.HashMap;
import java.util.Map;
import java.lang.Byte;
/** Request/Response code enum.
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public enum RequestResponseCode {
LIST_REQUEST(CodeType.REQUEST, (byte)0x00),
LOAD_REQUEST(CodeType.REQUEST, (byte)0x01),
LIST_RESPONSE(CodeType.RESPONSE, (byte)0x80),
LOAD_RESPONSE(CodeType.RESPONSE, (byte)0x81),
NOT_FOUND(CodeType.RESPONSE, (byte)0x82),
PROTOCOL_ERROR(CodeType.RESPONSE, (byte)0x83),
INTERNAL_ERROR(CodeType.RESPONSE, (byte)0x84);
public final CodeType codeType;
public final byte codeValue;
protected final static int RRCODE_POSITION = 1;
/* To be able to convert code to enum */
private static final Map<Byte, RequestResponseCode> BY_CODE = new HashMap<>();
/* Initialization of HashMap */
static {
for (RequestResponseCode r: values()) {
assert !BY_CODE.containsKey(Byte.valueOf(r.codeValue)) : "Duplicate in " + RequestResponseCode.class.getCanonicalName();
BY_CODE.put(Byte.valueOf(r.codeValue), r);
}
}
/** Private constructor
* @param codeType type of code (request or response)
* @param codeValue value of the element in datagram
* @return enum element
*/
private RequestResponseCode(CodeType codeType, byte codeValue) {
this.codeType = codeType;
this.codeValue = codeValue;
}
/** Gives enum from datagram code.
* @param code value of the element in datagram
* @return enum element
*/
public static RequestResponseCode fromCode(byte code) throws ProtocolError {
byte code = BY_CODE.get(Byte.valueOf(code));
if (code == null) {
throw new ProtocolError();
}
return code;
}
}