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).
pull/1/head
Louis Royer 5 years ago
parent f4e318dfe5
commit 026008473a

@ -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 and responses codes
- REQUESTS (msb is 0): - REQUESTS (msb is 0):
- `LIST` (0x00) - `LIST` (0x00)
- `DOWNLOAD` (0x01) - `LOAD` (0x01)
- RESPONSES (msb is 1): - RESPONSES (msb is 1):
- `LIST` (0x80) - `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 size for list request is always zero.
Payload for list response is filenames separated by `\n`. Payload for list response is filenames separated by `\n`.
### Download ### Load
#### Not found #### Not found
Response when the file requested is not found on the server. 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 #### Protocol error
Response when the request cannot be interpreted. Response when the request cannot be interpreted.
@ -50,7 +50,7 @@ Payload size for Protocol error is zero
#### Internal error #### Internal error
Response in internal failure case. Response in internal failure case.
Payload size for Internal error is zero Payload size for Internal error is zero.
#### Load response #### Load response
Payload contains Payload contains
@ -61,3 +61,6 @@ Payload contains
[<FILENAME>\n] [<FILENAME>\n]
[FILE CONTENT] [FILE CONTENT]
``` ```
#### Load request
Payload contains only the name of the file to load.

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

@ -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
}
}

@ -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
}
}

@ -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)
}
}

@ -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();
}
}
}

@ -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;
}
}
Loading…
Cancel
Save