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:
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 (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.
|
||||
|
5
src/protocolP2P/CodeType.java
Normal file
5
src/protocolP2P/CodeType.java
Normal file
@ -0,0 +1,5 @@
|
||||
package protocolP2P;
|
||||
public enum CodeType {
|
||||
REQUEST,
|
||||
RESPONSE
|
||||
}
|
36
src/protocolP2P/FileList.java
Normal file
36
src/protocolP2P/FileList.java
Normal 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
|
||||
}
|
||||
}
|
41
src/protocolP2P/FilePart.java
Normal file
41
src/protocolP2P/FilePart.java
Normal 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
|
||||
}
|
||||
|
||||
}
|
34
src/protocolP2P/Payload.java
Normal file
34
src/protocolP2P/Payload.java
Normal 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)
|
||||
}
|
||||
}
|
53
src/protocolP2P/ProtocolP2PDatagram.java
Normal file
53
src/protocolP2P/ProtocolP2PDatagram.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
62
src/protocolP2P/RequestResponseCode.java
Normal file
62
src/protocolP2P/RequestResponseCode.java
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user