@ -5,6 +5,8 @@ import exception.ProtocolError;
import exception.InternalError ;
import exception.SizeError ;
import tools.BytesArrayTools ;
import java.util.Arrays ;
import java.io.UnsupportedEncodingException ;
/ * * Representation of payload for load response .
* @author Louis Royer
@ -13,7 +15,6 @@ import tools.BytesArrayTools;
* @version 1.0
* /
public class FilePart extends Payload {
private static final RequestResponseCode requestResponseCode = RequestResponseCode . LOAD_RESPONSE ;
private String filename ;
private long totalSize ;
private long offset ;
@ -27,10 +28,15 @@ public class FilePart extends Payload {
* @throws InternalError
* /
public FilePart ( String filename , long totalSize , long offset , byte [ ] partialContent ) throws InternalError {
super ( RequestResponseCode . LOAD_RESPONSE ) ;
/* asserts to help debugging */
assert totalSize > = 0 : "totalSize cannot be negative" ;
assert partialContent . length ! = 0 : "partialContent.length cannot be zero" ;
assert totalSize > = partialContent . length : "totalSize must be greater than partialContent.length" ;
assert offset > = 0 : "offset cannot be negative" ;
if ( totalSize < 0 | | offset < 0 ) {
assert filename ! = null : "filename is required" ;
if ( totalSize < 0 | | partialContent . length = = 0 | | totalSize < partialContent . length
| | offset < 0 | | filename = = null ) {
throw new InternalError ( ) ;
}
this . filename = filename ;
@ -45,64 +51,113 @@ public class FilePart extends Payload {
* @throws InternalError
* /
protected FilePart ( byte [ ] datagram ) throws SizeError , ProtocolError , InternalError {
super ( datagram ) ;
/* assert to help debugging */
assert RequestResponseCode. f romCode( datagram [ R equestResponseCode. RRCODE_POSITION ] ) = = RequestResponseCode . LOAD_RESPONSE : "FilePart subclass is incompatible with this datagram, request/response code must be checked before using this constructor" ;
assert requestResponseCode = = RequestResponseCode . LOAD_RESPONSE : "FilePart subclass is incompatible with this datagram, request/response code must be checked before using this constructor" ;
/* InternalErrorException */
if ( RequestResponseCode. f romCode( datagram [ R equestResponseCode. RRCODE_POSITION ] ) ! = RequestResponseCode . LOAD_RESPONSE ) {
if ( requestResponseCode ! = RequestResponseCode . LOAD_RESPONSE ) {
throw new InternalError ( ) ;
}
setOffset ( datagram ) ; // this can throw SizeError
setTotalFileSize ( datagram ) ; // this can throw SizeError
int size = getPayloadSize ( datagram ) ; // this can throw SizeError
int partialContentStart = setFilename ( datagram , size ) + 1 ; // this can throw ProtocolError
setPartialContent ( datagram , partialContentStart , size ) ;
setTotalSize ( datagram ) ; // this can throw SizeError
setFilename ( datagram ) ; // this can throw ProtocolError, SizeError
setPartialContent ( datagram ) ; // this can throw SizeError
}
/ * * Returns a byte [ ] containing datagram with padding .
* This datagram is still incomplete and should not be send directly .
* ProtocolP2PDatagram will use this method to generate the complete datagram .
* @return datagram with padding
* @throws InternalError
* /
protected byte [ ] toDatagram ( ) {
protected byte [ ] toDatagram ( ) throws InternalError {
//TODO : calculate payload size
int size = 24 + filename . length + 1 ;
int size = 24 + filename . length ( ) + 1 ;
byte [ ] datagram = new byte [ size ] ; // 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
datagram = setPayloadSize ( size , datagram ) ;
//TODO : write offset to datagram
//TODO : write totalFileSize to datagram
//TODO : write filename\n to datagram
setPayloadSize ( size , datagram ) ;
// write offset to datagram (Byte 8)
BytesArrayTools . write ( datagram , 8 , offset ) ;
// write totalSize to datagram (Byte 16)
BytesArrayTools . write ( datagram , 16 , totalSize ) ;
// write filename’ s size to datagram
BytesArrayTools . write ( datagram , 24 , filename . length ( ) ) ;
//TODO : write filename to datagram
try {
byte [ ] bFilename = filename . getBytes ( "UTF-8" ) ;
} catch ( UnsupportedEncodingException e ) {
throw new InternalError ( ) ;
}
//TODO : write partialContent to datagram
return datagram ;
}
/ * * Write from bytes 8 to 15 of datagram into offset .
* @param datagram received datagram
* @throws SizeError
* /
private setOffset ( byte [ ] datagram ) throws SizeError {
private void setOffset ( byte [ ] datagram ) throws SizeError {
offset = BytesArrayTools . readLong ( datagram , 8 ) ;
}
/ * * Write from bytes 16 to 23 of datagram into totalSize .
* @param datagram received datagram
* @throws SizeError
* /
private setTotal File Size( byte [ ] datagram ) throw SizeError {
private void setTotal Size( byte [ ] datagram ) throws SizeError {
totalSize = BytesArrayTools . readLong ( datagram , 16 ) ;
}
private int setFilename ( byte [ ] datagram , int payloadSize ) throws ProtocolError {
// TODO: copy datagram from byte 24 to the first \n (excluded)
// into filename unless we excess size
// (in this case the wrong size has been
// set by the emitter, it is a protocolerror)
// return position of the \n
/ * * Read filename ’ s size from bytes 24 to 28 of datagram .
* @param datagram received datagram
* @throws ProtocolError
* @throws SizeError
* @return filename ’ s size
* /
private int getFilenameSize ( byte [ ] datagram ) throws SizeError , ProtocolError {
int size = BytesArrayTools . readInt ( datagram , 24 ) ; // this can throw SizeError
// filename size cannot be zero
if ( size = = 0 ) {
throw new ProtocolError ( ) ;
}
// offset (8B) + totalSize (8B) + filenameSize (4B) = 20B
if ( ( 20 + size ) > getPayloadSize ( datagram ) ) {
throw new ProtocolError ( ) ;
}
return size ;
}
/ * * Write filename from byte 24 to byte ( 24 + ( filenameSize - 1 ) ) of datagram .
* @param datagram received datagram
* @throws ProtocolError
* @throws SizeError
* @throws InternalError
* /
private void setFilename ( byte [ ] datagram ) throws ProtocolError , SizeError , InternalError {
int filenameSize = getFilenameSize ( datagram ) ; // this can throw ProtocolError or SizeError
try {
filename = new String ( datagram , 24 , filenameSize , "UTF-8" ) ;
} catch ( UnsupportedEncodingException e ) {
throw new InternalError ( ) ;
}
}
/ * * Write partialContent from byte ( 24 + filenameSize ) to byte ( 8 + payloadSize ) of datagram .
* @param datagram received datagram
* @throws SizeError
* @throws ProtocolError
* /
private void setPartialContent ( byte [ ] datagram ) throws ProtocolError , SizeError {
int start = 24 + getFilenameSize ( datagram ) ; // this can throw SizeError or ProtocolError
int end = 8 + getPayloadSize ( datagram ) ; // this can throw SizeError
try {
partialContent = Arrays . copyOfRange ( datagram , start , end + 1 ) ;
} catch ( ArrayIndexOutOfBoundsException e ) {
throw new ProtocolError ( ) ;
}
private setPartialContent ( byte [ ] datagram , int start , int payloadSize ) {
// TODO: copy datagram from start to size into partialContent
}
}