Change to ProtocolP2PPacket, should be easier to implement tcp
This commit is contained in:
parent
c17a7e6cd5
commit
b6351d30d3
@ -20,7 +20,7 @@ import java.nio.file.Files;
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import protocolP2P.ProtocolP2PDatagram;
|
||||
import protocolP2P.ProtocolP2PPacketUDP;
|
||||
import protocolP2P.Payload;
|
||||
import protocolP2P.RequestResponseCode;
|
||||
import protocolP2P.FileList;
|
||||
@ -52,9 +52,13 @@ public class ClientManagementUDP implements Runnable {
|
||||
this.UDPPort = UDPPort;
|
||||
try {
|
||||
socket = new DatagramSocket();
|
||||
socket.connect(InetAddress.getByName(host), UDPPort);
|
||||
} catch (SocketException e) {
|
||||
System.err.println("Error: No socket available.");
|
||||
System.exit(-1);
|
||||
} catch (UnknownHostException e) {
|
||||
System.err.println("Error: Unknown host.");
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,13 +122,13 @@ public class ClientManagementUDP implements Runnable {
|
||||
*/
|
||||
private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
|
||||
final long MAX_PARTIAL_SIZE = 1024;
|
||||
ProtocolP2PDatagram d = new ProtocolP2PDatagram((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE));
|
||||
d.send(socket, host, UDPPort);
|
||||
ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE));
|
||||
d.sendRequest((Object)socket);
|
||||
boolean fileFullyWritten = false;
|
||||
long offset = 0;
|
||||
do {
|
||||
try {
|
||||
Payload p = ProtocolP2PDatagram.receive(socket).getPayload();
|
||||
Payload p = d.receiveResponse().getPayload();
|
||||
assert p instanceof FilePart : "This payload must be instance of FilePart";
|
||||
if (!(p instanceof FilePart)) {
|
||||
throw new InternalError();
|
||||
@ -148,8 +152,8 @@ public class ClientManagementUDP implements Runnable {
|
||||
// next partialContentRequest
|
||||
if (offset != fp.getTotalSize()) {
|
||||
System.err.println("Sending following request with offset: " + offset + " maxpartialsize: " + MAX_PARTIAL_SIZE);
|
||||
d = new ProtocolP2PDatagram((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE));
|
||||
d.send(socket, host, UDPPort);
|
||||
d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE));
|
||||
d.sendRequest((Object)socket);
|
||||
} else {
|
||||
fileFullyWritten = true;
|
||||
}
|
||||
@ -168,8 +172,8 @@ public class ClientManagementUDP implements Runnable {
|
||||
fileFullyWritten = true;
|
||||
} else {
|
||||
// next partialContentRequest
|
||||
d = new ProtocolP2PDatagram((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE));
|
||||
d.send(socket, host, UDPPort);
|
||||
d = new ProtocolP2PPacketUDP((Payload) new LoadRequest(filename, offset, MAX_PARTIAL_SIZE));
|
||||
d.sendRequest((Object)socket);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -199,10 +203,10 @@ public class ClientManagementUDP implements Runnable {
|
||||
* @throws VersionRemoteError
|
||||
*/
|
||||
private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
|
||||
ProtocolP2PDatagram d = new ProtocolP2PDatagram(new Payload(RequestResponseCode.LIST_REQUEST));
|
||||
d.send(socket, host, UDPPort);
|
||||
ProtocolP2PPacketUDP d = new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST));
|
||||
d.sendRequest((Object)socket);
|
||||
try {
|
||||
Payload p = ProtocolP2PDatagram.receive(socket).getPayload();
|
||||
Payload p = d.receiveResponse().getPayload();
|
||||
assert p instanceof FileList : "This payload must be instance of Filelist";
|
||||
if (!(p instanceof FileList)) {
|
||||
throw new InternalError();
|
||||
|
@ -1,6 +1,6 @@
|
||||
package clientP2P;
|
||||
import clientP2P.ClientManagementUDP;
|
||||
import clientP2P.ClientManagementTCP;
|
||||
//import clientP2P.ClientManagementTCP;
|
||||
import tools.Directories;
|
||||
import java.util.Scanner;
|
||||
|
||||
@ -21,20 +21,24 @@ public class ClientP2P {
|
||||
System.out.println("Which transport protocol do you want to use? [TCP/udp]");
|
||||
Scanner sc = new Scanner(System.in);
|
||||
String transportchoosen = sc.nextLine();
|
||||
Thread t;
|
||||
switch(transportchoosen){
|
||||
case "UDP":
|
||||
case "udp":
|
||||
case "2" :
|
||||
ClientManagementUDP cm = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.host, c.port);
|
||||
ClientManagementUDP cmudp = new ClientManagementUDP(c.directories.getDataHomeDirectory(), c.host, c.port);
|
||||
t = new Thread(cmudp);
|
||||
break;
|
||||
case "TCP":
|
||||
case "tcp":
|
||||
case "1":
|
||||
default:
|
||||
ClientManagementTCP cm = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.host, c.port);
|
||||
break;
|
||||
//ClientManagementTCP cmtcp = new ClientManagementTCP(c.directories.getDataHomeDirectory(), c.host, c.port);
|
||||
//t = new Thread(cmtcp);
|
||||
//break;
|
||||
throw new java.lang.UnsupportedOperationException();
|
||||
}
|
||||
Thread t = new Thread(cm);
|
||||
|
||||
t.setName("client P2P-JAVA-PROJECT");
|
||||
t.start();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
package exception;
|
||||
/** Used on reception side when size as set in datagram is too big, and we cant store this in a int/long as usual. */
|
||||
/** Used on reception side when size as set in Packet is too big, and we cant store this in a int/long as usual. */
|
||||
public class SizeError extends Exception {
|
||||
private static final long serialVersionUID = 12L;
|
||||
}
|
||||
|
@ -32,54 +32,54 @@ public class FileList extends Payload {
|
||||
this.fileList = fileList;
|
||||
}
|
||||
|
||||
/** Constructor (typically used by client) with a byte[] parameter containing the datagram received.
|
||||
* @param datagram the full datagram received
|
||||
/** Constructor (typically used by client) with a byte[] parameter containing the Packet received.
|
||||
* @param packet the full packet received
|
||||
* @throws SizeError
|
||||
* @throws InternalError
|
||||
* @throws ProtocolError
|
||||
* @throws TransmissionError
|
||||
*/
|
||||
protected FileList(byte[] datagram) throws TransmissionError, SizeError, ProtocolError, InternalError {
|
||||
super(datagram);
|
||||
protected FileList(byte[] packet) throws TransmissionError, SizeError, ProtocolError, InternalError {
|
||||
super(packet);
|
||||
/* assert to help debugging */
|
||||
assert requestResponseCode == RequestResponseCode.LIST_RESPONSE : "FileList subclass is incompatible with this datagram, request/response code must be checked before using this constructor";
|
||||
assert requestResponseCode == RequestResponseCode.LIST_RESPONSE : "FileList subclass is incompatible with this Packet, request/response code must be checked before using this constructor";
|
||||
/* InternalErrorException */
|
||||
if (requestResponseCode!= RequestResponseCode.LIST_RESPONSE) {
|
||||
throw new InternalError();
|
||||
}
|
||||
int size = getPayloadSize(datagram);
|
||||
int size = getPayloadSize(packet);
|
||||
try {
|
||||
fileList = (new String(datagram, 8, size, "UTF-8")).split("\n");
|
||||
fileList = (new String(packet, PAYLOAD_START_POSITION, size, "UTF-8")).split("\n");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** 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
|
||||
/** 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[] toDatagram() throws InternalError {
|
||||
protected byte[] toPacket() throws InternalError {
|
||||
// compute size
|
||||
int size = 8;
|
||||
int size = PAYLOAD_START_POSITION;
|
||||
for (String s : fileList) {
|
||||
size += s.length();
|
||||
size += 1;
|
||||
size += 1; // size for '\n'
|
||||
}
|
||||
size -=1;
|
||||
byte[] datagram = new byte[size]; // java initialize all to zero
|
||||
size -=1; // remove trailing '\n'
|
||||
byte[] packet = new byte[size]; // java initialize all to zero
|
||||
// set request/response code
|
||||
datagram[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
// bits 16-31 are reserved for future use
|
||||
setPayloadSize(size - 8, datagram);
|
||||
packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
// set payload size
|
||||
setPayloadSize(size - PAYLOAD_START_POSITION, packet);
|
||||
// Write fileList
|
||||
int bCount = 8;
|
||||
int bCount = PAYLOAD_START_POSITION;
|
||||
for(String s : fileList) {
|
||||
if (bCount != 8) { // not on first iteration
|
||||
if (bCount != PAYLOAD_START_POSITION) { // not on first iteration
|
||||
try {
|
||||
datagram[bCount] = "\n".getBytes("UTF-8")[0]; // separator
|
||||
packet[bCount] = "\n".getBytes("UTF-8")[0]; // separator
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
@ -89,7 +89,7 @@ public class FileList extends Payload {
|
||||
try {
|
||||
byte[] sb = s.getBytes("UTF-8");
|
||||
for(byte b : sb) {
|
||||
datagram[bCount] = b;
|
||||
packet[bCount] = b;
|
||||
bCount += 1;
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
@ -97,7 +97,7 @@ public class FileList extends Payload {
|
||||
}
|
||||
|
||||
}
|
||||
return datagram;
|
||||
return packet;
|
||||
}
|
||||
|
||||
/** fileList getter.
|
||||
|
@ -20,7 +20,7 @@ public class FilePart extends Payload {
|
||||
private long totalSize;
|
||||
private long offset;
|
||||
private byte[] partialContent;
|
||||
static final private int OFFSET_POSITION = 8;
|
||||
static final private int OFFSET_POSITION = PAYLOAD_START_POSITION;
|
||||
static final private int TOTAL_FILESIZE_POSITION = OFFSET_POSITION + 8;
|
||||
static final private int FILENAME_SIZE_POSITION = TOTAL_FILESIZE_POSITION + 8;
|
||||
static final private int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4;
|
||||
@ -50,123 +50,123 @@ public class FilePart extends Payload {
|
||||
this.partialContent = partialContent;
|
||||
}
|
||||
|
||||
/** Constructor (typically used by client) with datagram received as parameter.
|
||||
* @param datagram the full datagram received
|
||||
/** Constructor (typically used by client) with Packet received as parameter.
|
||||
* @param packet the full Packet received
|
||||
* @throws SizeError
|
||||
* @throws InternalError
|
||||
* @throws TransmissionError
|
||||
*/
|
||||
protected FilePart(byte[] datagram) throws TransmissionError, SizeError, ProtocolError, InternalError {
|
||||
super(datagram);
|
||||
protected FilePart(byte[] packet) throws TransmissionError, SizeError, ProtocolError, InternalError {
|
||||
super(packet);
|
||||
/* assert to help debugging */
|
||||
assert requestResponseCode == 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 Packet, request/response code must be checked before using this constructor";
|
||||
/* InternalErrorException */
|
||||
if (requestResponseCode != RequestResponseCode.LOAD_RESPONSE) {
|
||||
throw new InternalError();
|
||||
}
|
||||
setOffset(datagram); // this can throw SizeError
|
||||
setTotalSize(datagram); // this can throw SizeError
|
||||
setFilename(datagram); // this can throw ProtocolError, SizeError
|
||||
setPartialContent(datagram); // this can throw SizeError
|
||||
setOffset(packet); // this can throw SizeError
|
||||
setTotalSize(packet); // this can throw SizeError
|
||||
setFilename(packet); // this can throw ProtocolError, SizeError
|
||||
setPartialContent(packet); // 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
|
||||
/** 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[] toDatagram() throws InternalError {
|
||||
protected byte[] toPacket() throws InternalError {
|
||||
// compute total size
|
||||
int size = FILENAME_POSITION + filename.length() + partialContent.length;
|
||||
byte[] datagram = new byte[size + 1]; // java initialize all to zero
|
||||
byte[] packet = new byte[size + 1]; // java initialize all to zero
|
||||
// set request/response code
|
||||
datagram[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
// bits 16-31 are reserved for future use
|
||||
setPayloadSize(size - OFFSET_POSITION, datagram);
|
||||
// write offset to datagram
|
||||
BytesArrayTools.write(datagram, OFFSET_POSITION, (long)offset);
|
||||
// write totalSize to datagram
|
||||
BytesArrayTools.write(datagram, TOTAL_FILESIZE_POSITION, (long)totalSize);
|
||||
// write filename’s size to datagram
|
||||
BytesArrayTools.write(datagram, FILENAME_SIZE_POSITION, (int)filename.length());
|
||||
packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
// set Payload size
|
||||
setPayloadSize(size - OFFSET_POSITION, packet);
|
||||
// write offset to Packet
|
||||
BytesArrayTools.write(packet, OFFSET_POSITION, offset);
|
||||
// write totalSize to Packet
|
||||
BytesArrayTools.write(packet, TOTAL_FILESIZE_POSITION, totalSize);
|
||||
// write filename’s size to Packet
|
||||
BytesArrayTools.write(packet, FILENAME_SIZE_POSITION, filename.length());
|
||||
try {
|
||||
// write filename to datagram
|
||||
// write filename to Packet
|
||||
int i = FILENAME_POSITION;
|
||||
for (byte b : filename.getBytes("UTF-8")) {
|
||||
datagram[i] = b;
|
||||
packet[i] = b;
|
||||
i += 1;
|
||||
}
|
||||
// write partialContent to datagram
|
||||
// write partialContent to Packet
|
||||
for (byte b: partialContent) {
|
||||
datagram[i] = b;
|
||||
packet[i] = b;
|
||||
i += 1;
|
||||
}
|
||||
return datagram;
|
||||
return packet;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Write from datagram into offset.
|
||||
* @param datagram received datagram
|
||||
/** Write from Packet into offset.
|
||||
* @param packet received Packet
|
||||
* @throws SizeError
|
||||
*/
|
||||
private void setOffset(byte[] datagram) throws SizeError {
|
||||
offset = BytesArrayTools.readLong(datagram, OFFSET_POSITION);
|
||||
private void setOffset(byte[] packet) throws SizeError {
|
||||
offset = BytesArrayTools.readLong(packet, OFFSET_POSITION);
|
||||
}
|
||||
/** Write from datagram into totalSize.
|
||||
* @param datagram received datagram
|
||||
/** Write from Packet into totalSize.
|
||||
* @param packet received Packet
|
||||
* @throws SizeError
|
||||
*/
|
||||
private void setTotalSize(byte[] datagram) throws SizeError {
|
||||
totalSize = BytesArrayTools.readLong(datagram, TOTAL_FILESIZE_POSITION);
|
||||
private void setTotalSize(byte[] packet) throws SizeError {
|
||||
totalSize = BytesArrayTools.readLong(packet, TOTAL_FILESIZE_POSITION);
|
||||
}
|
||||
|
||||
/** Read filename’s size from datagram.
|
||||
* @param datagram received datagram
|
||||
/** Read filename’s size from Packet.
|
||||
* @param packet received Packet
|
||||
* @throws ProtocolError
|
||||
* @throws SizeError
|
||||
* @return filename’s size
|
||||
*/
|
||||
private int getFilenameSize(byte[] datagram) throws SizeError, ProtocolError {
|
||||
int size = BytesArrayTools.readInt(datagram, FILENAME_SIZE_POSITION); // this can throw SizeError
|
||||
private int getFilenameSize(byte[] packet) throws SizeError, ProtocolError {
|
||||
int size = BytesArrayTools.readInt(packet, FILENAME_SIZE_POSITION); // this can throw SizeError
|
||||
// filename size cannot be zero
|
||||
if (size == 0) {
|
||||
throw new ProtocolError();
|
||||
}
|
||||
// cannot excess datagram size
|
||||
if ((FILENAME_POSITION + size) > (getPayloadSize(datagram) + OFFSET_POSITION)) {
|
||||
// cannot excess packet size
|
||||
if ((FILENAME_POSITION + size) > (getPayloadSize(packet) + OFFSET_POSITION)) {
|
||||
throw new ProtocolError();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Write from datagram into filename.
|
||||
* @param datagram received datagram
|
||||
/** Write from Packet into filename.
|
||||
* @param packet received Packet
|
||||
* @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
|
||||
private void setFilename(byte[] packet) throws ProtocolError, SizeError, InternalError {
|
||||
int filenameSize = getFilenameSize(packet); // this can throw ProtocolError or SizeError
|
||||
try {
|
||||
filename = new String(datagram, FILENAME_POSITION, filenameSize, "UTF-8");
|
||||
filename = new String(packet, FILENAME_POSITION, filenameSize, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Write from datagram into partialContent.
|
||||
* @param datagram received datagram
|
||||
/** Write from Packet into partialContent.
|
||||
* @param packet received Packet
|
||||
* @throws SizeError
|
||||
* @throws ProtocolError
|
||||
*/
|
||||
private void setPartialContent(byte[] datagram) throws ProtocolError, SizeError {
|
||||
int start = FILENAME_POSITION + getFilenameSize(datagram); // this can throw SizeError or ProtocolError
|
||||
int end = OFFSET_POSITION + getPayloadSize(datagram); // this can throw SizeError
|
||||
private void setPartialContent(byte[] packet) throws ProtocolError, SizeError {
|
||||
int start = FILENAME_POSITION + getFilenameSize(packet); // this can throw SizeError or ProtocolError
|
||||
int end = OFFSET_POSITION + getPayloadSize(packet); // this can throw SizeError
|
||||
try {
|
||||
partialContent = Arrays.copyOfRange(datagram, start, end);
|
||||
partialContent = Arrays.copyOfRange(packet, start, end);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new ProtocolError();
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public class LoadRequest extends Payload {
|
||||
private String filename;
|
||||
private long maxSizePartialContent;
|
||||
private long offset;
|
||||
static final private int OFFSET_POSITION = 8;
|
||||
static final private int OFFSET_POSITION = PAYLOAD_START_POSITION;
|
||||
static final private int MAX_SIZE_PARTIAL_CONTENT_POSITION = OFFSET_POSITION + 8;
|
||||
static final private int FILENAME_SIZE_POSITION = MAX_SIZE_PARTIAL_CONTENT_POSITION + 8;
|
||||
static final private int FILENAME_POSITION = FILENAME_SIZE_POSITION + 4;
|
||||
@ -41,74 +41,75 @@ public class LoadRequest extends Payload {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/** Constructor (typically used by client) with a byte[] parameter containing the datagram received.
|
||||
* @param datagram the full datagram received
|
||||
/** Constructor (typically used by client) with a byte[] parameter containing the Packet received.
|
||||
* @param packet the full Packet received
|
||||
* @throws SizeError
|
||||
* @throws InternalError
|
||||
* @throws ProtocolError
|
||||
* @throws TransmissionError
|
||||
*/
|
||||
protected LoadRequest(byte[] datagram) throws TransmissionError, SizeError, ProtocolError, InternalError {
|
||||
super(datagram);
|
||||
protected LoadRequest(byte[] packet) throws TransmissionError, SizeError, ProtocolError, InternalError {
|
||||
super(packet);
|
||||
/* assert to help debugging */
|
||||
assert requestResponseCode == RequestResponseCode.LOAD_REQUEST : "LoadRequest subclass is incompatible with this datagram, request/response code must be checked before using this constructor";
|
||||
assert requestResponseCode == RequestResponseCode.LOAD_REQUEST : "LoadRequest subclass is incompatible with this Packet, request/response code must be checked before using this constructor";
|
||||
/* InternalErrorException */
|
||||
if (requestResponseCode!= RequestResponseCode.LOAD_REQUEST) {
|
||||
throw new InternalError();
|
||||
}
|
||||
/* Read offset */
|
||||
offset = BytesArrayTools.readLong(datagram, OFFSET_POSITION);
|
||||
offset = BytesArrayTools.readLong(packet, OFFSET_POSITION);
|
||||
|
||||
/* Read maxSizePartialContent */
|
||||
maxSizePartialContent = BytesArrayTools.readLong(datagram, MAX_SIZE_PARTIAL_CONTENT_POSITION);
|
||||
maxSizePartialContent = BytesArrayTools.readLong(packet, MAX_SIZE_PARTIAL_CONTENT_POSITION);
|
||||
|
||||
/* Read filename */
|
||||
int size = BytesArrayTools.readInt(datagram, FILENAME_SIZE_POSITION);
|
||||
int size = BytesArrayTools.readInt(packet, FILENAME_SIZE_POSITION);
|
||||
try {
|
||||
filename = new String(datagram, FILENAME_POSITION, size, "UTF-8");
|
||||
filename = new String(packet, FILENAME_POSITION, size, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** 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
|
||||
/** 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[] toDatagram() throws InternalError {
|
||||
protected byte[] toPacket() throws InternalError {
|
||||
// compute size
|
||||
int filenameSize = filename.length();
|
||||
int size = FILENAME_POSITION + filenameSize;
|
||||
byte[] datagram = new byte[size + 1]; // java initialize all to zero
|
||||
byte[] packet = new byte[size + 1]; // java initialize all to zero
|
||||
|
||||
// set request/response code
|
||||
datagram[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
// bits 16-31 are reserved for future use
|
||||
// 8 bytes for headers
|
||||
setPayloadSize(size - OFFSET_POSITION, datagram);
|
||||
packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
|
||||
// set Payload size
|
||||
setPayloadSize(size - OFFSET_POSITION, packet);
|
||||
|
||||
// Write offset
|
||||
BytesArrayTools.write(datagram, OFFSET_POSITION, (long)offset);
|
||||
BytesArrayTools.write(packet, OFFSET_POSITION, (long)offset);
|
||||
|
||||
// Write maxSizePartialContent
|
||||
BytesArrayTools.write(datagram, MAX_SIZE_PARTIAL_CONTENT_POSITION, (long)maxSizePartialContent);
|
||||
BytesArrayTools.write(packet, MAX_SIZE_PARTIAL_CONTENT_POSITION, (long)maxSizePartialContent);
|
||||
|
||||
// Write filenameSize
|
||||
BytesArrayTools.write(datagram, FILENAME_SIZE_POSITION, (int)filenameSize);
|
||||
BytesArrayTools.write(packet, FILENAME_SIZE_POSITION, (int)filenameSize);
|
||||
|
||||
// Write filename
|
||||
int bCount = FILENAME_POSITION;
|
||||
try {
|
||||
byte[] sb = filename.getBytes("UTF-8");
|
||||
for(byte b : sb) {
|
||||
datagram[bCount] = b;
|
||||
packet[bCount] = b;
|
||||
bCount += 1;
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
return datagram;
|
||||
return packet;
|
||||
}
|
||||
|
||||
/** filename getter.
|
||||
|
@ -32,24 +32,24 @@ public class Payload {
|
||||
checkRequestResponseCode(); // this can throw InternalError
|
||||
}
|
||||
|
||||
/** Constructor used to create a Payload (when no more specific subclasses exists) using datagram as parameter.
|
||||
/** 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 datagram the full datagram received
|
||||
* @param packet the full packet received
|
||||
* @throws ProtocolError
|
||||
* @throws InternalError
|
||||
* @throws TransmissionError
|
||||
* @throws SizeError
|
||||
*/
|
||||
protected Payload(byte[] datagram) throws SizeError, ProtocolError, InternalError, TransmissionError {
|
||||
protected Payload(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError {
|
||||
/* asserts to help debugging */
|
||||
assert getPayloadSize(datagram) + 8 <= datagram.length : "Payload is truncated";
|
||||
if (datagram.length < getPayloadSize(datagram) + 8) {
|
||||
assert getPayloadSize(packet) + 8 <= packet.length : "Payload is truncated";
|
||||
if (packet.length < getPayloadSize(packet) + 8) {
|
||||
throw new TransmissionError();
|
||||
}
|
||||
assert RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LIST_RESPONSE || (this instanceof FileList) : "LIST_RESPONSE must use FilePart class";
|
||||
assert RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_RESPONSE || (this instanceof FilePart) : "LOAD_RESPONSE must use FileList class";
|
||||
assert RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.LOAD_REQUEST || (this instanceof LoadRequest) : "LOAD_REQUEST must use LoadRequest class";
|
||||
requestResponseCode = RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]);
|
||||
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";
|
||||
requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]);
|
||||
checkRequestResponseCode(); // this can throw InternalError
|
||||
}
|
||||
|
||||
@ -65,29 +65,29 @@ public class Payload {
|
||||
}
|
||||
}
|
||||
|
||||
/** 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
|
||||
/** 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[] toDatagram() throws InternalError {
|
||||
protected byte[] toPacket() throws InternalError {
|
||||
// InternalError is impossible in this method on Payload class but still on subclasses
|
||||
byte [] datagram = new byte[8]; // java initialize all to zero
|
||||
byte [] packet = new byte[8]; // java initialize all to zero
|
||||
// size is zero (and this is the default)
|
||||
// set request/response code
|
||||
datagram[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
|
||||
// bits 16-31 are reserved for future use
|
||||
// payload size is 0 (this is what java have initialized datagram)
|
||||
return datagram;
|
||||
// payload size is 0 (this is what java have initialized Packet)
|
||||
return packet;
|
||||
}
|
||||
|
||||
/** Set payload’s size in a datagram.
|
||||
/** Set payload’s size in a Packet.
|
||||
* @param size integer representing payload size
|
||||
* @param datagram datagram to be completed
|
||||
* @param packet Packet to be completed
|
||||
* @throws InternalError
|
||||
*/
|
||||
protected static void setPayloadSize(int size, byte[] datagram) 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) {
|
||||
@ -95,16 +95,16 @@ public class Payload {
|
||||
// because this is only for reception side
|
||||
throw new InternalError();
|
||||
}
|
||||
BytesArrayTools.write(datagram, PAYLOAD_SIZE_POSITION, size);
|
||||
BytesArrayTools.write(packet, PAYLOAD_SIZE_POSITION, size);
|
||||
}
|
||||
|
||||
/** Get payload’s size from a datagram.
|
||||
* @param datagram the full datagram received
|
||||
/** Get payload’s size from a Packet.
|
||||
* @param packet the full Packet received
|
||||
* @return integer representing payload size
|
||||
* @throws SizeError
|
||||
*/
|
||||
protected static int getPayloadSize(byte[] datagram) throws SizeError {
|
||||
return BytesArrayTools.readInt(datagram, PAYLOAD_SIZE_POSITION);
|
||||
protected static int getPayloadSize(byte[] packet) throws SizeError {
|
||||
return BytesArrayTools.readInt(packet, PAYLOAD_SIZE_POSITION);
|
||||
}
|
||||
|
||||
/** RRCode getter.
|
||||
|
@ -1,298 +0,0 @@
|
||||
package protocolP2P;
|
||||
import exception.InternalError;
|
||||
import exception.ProtocolError;
|
||||
import exception.SizeError;
|
||||
import exception.TransmissionError;
|
||||
import exception.VersionError;
|
||||
import remoteException.EmptyDirectory;
|
||||
import remoteException.InternalRemoteError;
|
||||
import remoteException.NotFound;
|
||||
import remoteException.ProtocolRemoteError;
|
||||
import remoteException.VersionRemoteError;
|
||||
import remoteException.EmptyFile;
|
||||
import tools.BytesArrayTools;
|
||||
import protocolP2P.Payload;
|
||||
import protocolP2P.RequestResponseCode;
|
||||
import protocolP2P.LoadRequest;
|
||||
import protocolP2P.FileList;
|
||||
import protocolP2P.FilePart;
|
||||
import java.util.ArrayList;
|
||||
import java.lang.Byte;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/** Representation of datagram.
|
||||
* @author Louis Royer
|
||||
* @author Flavien Haas
|
||||
* @author JS Auge
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ProtocolP2PDatagram {
|
||||
private final static byte PROTOCOL_VERSION = 0x12;
|
||||
private final static int VERSION_POSITON = 0;
|
||||
private byte version;
|
||||
private Payload payload;
|
||||
private InetAddress hostR;
|
||||
private int portR;
|
||||
private final static int CHECKSUM_POSITION = 2;
|
||||
|
||||
/** Constructor with payload parameter (typically used when sending datagram).
|
||||
* @param payload the payload associated with the datagram to send
|
||||
*/
|
||||
public ProtocolP2PDatagram(Payload payload) {
|
||||
version = PROTOCOL_VERSION;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
/** Send datagram on socket (from client)
|
||||
* @param socket DatagramSocket used to send datagram.
|
||||
* @param host host to send datagram (null if this is a response)
|
||||
* @param port port to send datagram (null if this is a response)
|
||||
* @throws InternalError
|
||||
* @throws UnknownHostException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void send(DatagramSocket socket, String host, int port) throws InternalError, UnknownHostException, IOException {
|
||||
InetAddress dst = InetAddress.getByName(host);
|
||||
byte[] datagram = toDatagram();
|
||||
// generate DatagramPacket
|
||||
DatagramPacket datagramPacket = new DatagramPacket(datagram, datagram.length, dst, port);
|
||||
// send it
|
||||
socket.send(datagramPacket);
|
||||
}
|
||||
|
||||
/** Send datagram on socket (from server, as a response)
|
||||
* @param socket DatagramSocket used to send datagram.
|
||||
* @param received datagram to respond (aka request)
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
public void send(DatagramSocket socket, ProtocolP2PDatagram received) throws InternalError, IOException {
|
||||
assert received.getPortR() != 0 && received.getHostR() != null : "This method should be used only as response to a request";
|
||||
if (received.getPortR() == 0 || received.getHostR() == null) {
|
||||
throw new InternalError();
|
||||
}
|
||||
byte[] datagram = toDatagram();
|
||||
// generate DatagramPacket
|
||||
DatagramPacket datagramPacket = new DatagramPacket(datagram, datagram.length, received.getHostR(), received.getPortR());
|
||||
socket.send(datagramPacket);
|
||||
}
|
||||
|
||||
/** Send a response.
|
||||
* @param socket DatagramSocket used to send response
|
||||
* @param host host to send response
|
||||
* @param port port to send response
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void sendResponse(DatagramSocket socket, InetAddress host, int port) throws InternalError, IOException {
|
||||
assert port != 0 && host != null : "This method should be used only as response to a request";
|
||||
if (port == 0 || host == null) {
|
||||
throw new InternalError();
|
||||
}
|
||||
byte[] datagram = toDatagram();
|
||||
DatagramPacket datagramPacket = new DatagramPacket(datagram, datagram.length, host, port);
|
||||
socket.send(datagramPacket);
|
||||
}
|
||||
|
||||
/** Receive datagram on socket
|
||||
* @param socket DatagramSocket used to receive datagram
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
* @throws ProtocolRemoteError
|
||||
* @throws VersionRemoteError
|
||||
* @throws InternalRemoteError
|
||||
* @throws EmptyDirectory
|
||||
* @throws NotFound
|
||||
* @throws IOException
|
||||
* @throws EmptyFile
|
||||
*/
|
||||
public static ProtocolP2PDatagram receive(DatagramSocket socket) throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {
|
||||
// reception
|
||||
byte[] datagram = new byte[4096*2];
|
||||
DatagramPacket reception = new DatagramPacket(datagram, datagram.length);
|
||||
socket.receive(reception);
|
||||
// contruction
|
||||
try {
|
||||
ProtocolP2PDatagram p = new ProtocolP2PDatagram(datagram);
|
||||
p.setHostR(reception.getAddress());
|
||||
p.setPortR(reception.getPort());
|
||||
Payload payload = p.getPayload();
|
||||
switch (payload.getRequestResponseCode()) {
|
||||
case PROTOCOL_ERROR :
|
||||
throw new ProtocolRemoteError();
|
||||
case VERSION_ERROR :
|
||||
throw new VersionRemoteError();
|
||||
case INTERNAL_ERROR :
|
||||
throw new InternalRemoteError();
|
||||
case EMPTY_DIRECTORY :
|
||||
throw new EmptyDirectory();
|
||||
case NOT_FOUND :
|
||||
throw new NotFound();
|
||||
case EMPTY_FILE:
|
||||
throw new EmptyFile();
|
||||
default :
|
||||
return p;
|
||||
}
|
||||
} catch (TransmissionError e) {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.INTERNAL_ERROR))).sendResponse(socket, reception.getAddress(), reception.getPort());
|
||||
throw e;
|
||||
} catch (ProtocolError e) {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.PROTOCOL_ERROR))).sendResponse(socket, reception.getAddress(), reception.getPort());
|
||||
throw e;
|
||||
} catch (VersionError e) {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.VERSION_ERROR))).sendResponse(socket, reception.getAddress(), reception.getPort());
|
||||
throw e;
|
||||
} catch (InternalError e) {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.INTERNAL_ERROR))).sendResponse(socket, reception.getAddress(), reception.getPort());
|
||||
throw e;
|
||||
} catch (SizeError e) {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.INTERNAL_ERROR))).sendResponse(socket, reception.getAddress(), reception.getPort());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
/** Private constructor with datagram as byte[] parameter (typically used when receiving datagram).
|
||||
* @param datagram the full datagram received
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
*/
|
||||
private ProtocolP2PDatagram(byte[] datagram) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError {
|
||||
// unwrap version
|
||||
version = datagram[VERSION_POSITON];
|
||||
checkProtocolVersion(); // this can throw VersionError
|
||||
checkCheckSum(datagram);
|
||||
RequestResponseCode r = RequestResponseCode.fromCode(datagram[RequestResponseCode.RRCODE_POSITION]); // this can throw ProtocolError
|
||||
switch (r) {
|
||||
case LIST_RESPONSE:
|
||||
payload = (Payload) new FileList(datagram);
|
||||
break;
|
||||
case LOAD_RESPONSE:
|
||||
payload = (Payload) new FilePart(datagram);
|
||||
break;
|
||||
case LOAD_REQUEST:
|
||||
payload = (Payload) new LoadRequest(datagram);
|
||||
break;
|
||||
default:
|
||||
payload = new Payload(datagram); // this can throw TransmissionError
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a byte[] containing full datagram (typically used when sending datagram).
|
||||
* This datagram is still complete and ready to be send.
|
||||
* @return the full datagram to send
|
||||
* @throws InternalError
|
||||
*/
|
||||
protected byte[] toDatagram() throws InternalError {
|
||||
byte[] datagram = payload.toDatagram();
|
||||
datagram[VERSION_POSITON] = version;
|
||||
setCheckSum(datagram);
|
||||
return datagram;
|
||||
}
|
||||
|
||||
/** Returns Payload associated with the datagram.
|
||||
* @return payload associated with the datagram
|
||||
*/
|
||||
public Payload getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
/** Used to check protocol version when a datagram is constructed from bytes[].
|
||||
* @throws VersionError
|
||||
*/
|
||||
private void checkProtocolVersion() throws VersionError {
|
||||
if (PROTOCOL_VERSION != version) {
|
||||
throw new VersionError();
|
||||
}
|
||||
}
|
||||
|
||||
/** portR getter.
|
||||
* @return portR
|
||||
*/
|
||||
protected int getPortR() {
|
||||
return portR;
|
||||
}
|
||||
|
||||
/** portR setter.
|
||||
* @param portR portR
|
||||
*/
|
||||
protected void setPortR(int portR) {
|
||||
this.portR = portR;
|
||||
}
|
||||
|
||||
/** hostR getter.
|
||||
* @return hostR
|
||||
*/
|
||||
protected InetAddress getHostR() {
|
||||
return hostR;
|
||||
}
|
||||
|
||||
/** hostH setter.
|
||||
* @param hostR hostR
|
||||
*/
|
||||
protected void setHostR(InetAddress hostR) {
|
||||
this.hostR = hostR;
|
||||
}
|
||||
|
||||
/** Used to compute Checksum of a specific datagram
|
||||
* @param datagram full datagram
|
||||
* @return checksum
|
||||
* @throws SizeError
|
||||
*/
|
||||
|
||||
private int computeCheckSum(byte [] datagram) throws SizeError {
|
||||
/*
|
||||
* The checksum field is the 16 bit one’s complement of the one’s complement sum of all 16-bit words
|
||||
* in the header and text. If a segment contains an odd number of header and text octets to be checksummed,
|
||||
* the last octet is padded on the right with zeros to form a 16-bit word for checksum purposes.
|
||||
* The pad is not transmitted as part of the segment. While computing the checksum, the checksum field
|
||||
* itself is replaced with zeros.
|
||||
*/
|
||||
int checksum = 0;
|
||||
for (int i=CHECKSUM_POSITION+2; i<CHECKSUM_POSITION+2+4+Payload.getPayloadSize(datagram); ++i) {
|
||||
checksum += BytesArrayTools.readInt16Bits(datagram,i);
|
||||
checksum &= 0xffff;
|
||||
}
|
||||
return checksum ^ 0xffff;
|
||||
}
|
||||
|
||||
/** Used to set checksum into datagram
|
||||
* @param datagram full datagram
|
||||
* @throws InternalError
|
||||
*/
|
||||
|
||||
private void setCheckSum(byte [] datagram) throws InternalError {
|
||||
try {
|
||||
int checksum = computeCheckSum(datagram);
|
||||
BytesArrayTools.write16Bits(datagram,CHECKSUM_POSITION,checksum);
|
||||
} catch (SizeError e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to check if the checksum is correct
|
||||
* @param datagram full datagram
|
||||
* @throws TransmissionError
|
||||
*/
|
||||
|
||||
private void checkCheckSum(byte [] datagram) throws TransmissionError {
|
||||
try {
|
||||
int checksum = BytesArrayTools.readInt16Bits(datagram,CHECKSUM_POSITION);
|
||||
int computedCheckSum = computeCheckSum(datagram);
|
||||
if (computedCheckSum != checksum){
|
||||
throw new TransmissionError();
|
||||
}
|
||||
} catch(SizeError e) {
|
||||
throw new TransmissionError();
|
||||
}
|
||||
}
|
||||
}
|
102
src/protocolP2P/ProtocolP2PPacket.java
Normal file
102
src/protocolP2P/ProtocolP2PPacket.java
Normal file
@ -0,0 +1,102 @@
|
||||
package protocolP2P;
|
||||
import exception.InternalError;
|
||||
import exception.ProtocolError;
|
||||
import exception.SizeError;
|
||||
import exception.TransmissionError;
|
||||
import exception.VersionError;
|
||||
import remoteException.EmptyDirectory;
|
||||
import remoteException.InternalRemoteError;
|
||||
import remoteException.NotFound;
|
||||
import remoteException.ProtocolRemoteError;
|
||||
import remoteException.VersionRemoteError;
|
||||
import remoteException.EmptyFile;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
|
||||
/** Representation of packet.
|
||||
* @author Louis Royer
|
||||
* @author Flavien Haas
|
||||
* @author JS Auge
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class ProtocolP2PPacket {
|
||||
private final static byte PROTOCOL_VERSION = 0x12;
|
||||
protected final static int VERSION_POSITION = 0;
|
||||
protected byte version;
|
||||
protected Payload payload;
|
||||
|
||||
/** Constructor with payload parameter (typically used when sending Packet).
|
||||
* @param payload the payload associated with the Packet to send
|
||||
*/
|
||||
public ProtocolP2PPacket(Payload payload) {
|
||||
version = PROTOCOL_VERSION;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
/** Send a request
|
||||
* @param socket Socket used to send packet.
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract void sendRequest(Object socket) throws InternalError, IOException;
|
||||
|
||||
/** Send a response
|
||||
* @param response Response to send.
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException;
|
||||
|
||||
/** Receive a response
|
||||
* @throws EmptyFile
|
||||
* @throws NotFound
|
||||
* @throws EmptyDirectory
|
||||
* @throws InternalRemoteError
|
||||
* @throws VersionRemoteError
|
||||
* @throws ProtocolRemoteError
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException;
|
||||
|
||||
/** Receive a request, subclasses must overwrite this constructor.
|
||||
* @param serverSocket socket used to get the request
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
* @throws IOException
|
||||
*/
|
||||
protected ProtocolP2PPacket(Object serverSocket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {}
|
||||
|
||||
/** Construct a packet from byte[], subclasses must overwrite this constructor.
|
||||
* @param packet Packet received
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
*/
|
||||
protected ProtocolP2PPacket(byte[] packet) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError {}
|
||||
|
||||
/** Returns Payload associated with the Packet.
|
||||
* @return payload associated with the Packet.
|
||||
*/
|
||||
public Payload getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
/** Used to check protocol version when a Packet is constructed from bytes[].
|
||||
* @throws VersionError
|
||||
*/
|
||||
protected void checkProtocolVersion() throws VersionError {
|
||||
if (PROTOCOL_VERSION != version) {
|
||||
throw new VersionError();
|
||||
}
|
||||
}
|
||||
}
|
359
src/protocolP2P/ProtocolP2PPacketUDP.java
Normal file
359
src/protocolP2P/ProtocolP2PPacketUDP.java
Normal file
@ -0,0 +1,359 @@
|
||||
package protocolP2P;
|
||||
import exception.InternalError;
|
||||
import exception.ProtocolError;
|
||||
import exception.SizeError;
|
||||
import exception.TransmissionError;
|
||||
import exception.VersionError;
|
||||
import remoteException.EmptyDirectory;
|
||||
import remoteException.InternalRemoteError;
|
||||
import remoteException.NotFound;
|
||||
import remoteException.ProtocolRemoteError;
|
||||
import remoteException.VersionRemoteError;
|
||||
import remoteException.EmptyFile;
|
||||
import tools.BytesArrayTools;
|
||||
import protocolP2P.Payload;
|
||||
import protocolP2P.RequestResponseCode;
|
||||
import protocolP2P.LoadRequest;
|
||||
import protocolP2P.FileList;
|
||||
import protocolP2P.FilePart;
|
||||
import java.util.ArrayList;
|
||||
import java.lang.Byte;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
|
||||
/** Representation of packet.
|
||||
* @author Louis Royer
|
||||
* @author Flavien Haas
|
||||
* @author JS Auge
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ProtocolP2PPacketUDP extends ProtocolP2PPacket {
|
||||
|
||||
private final static int CHECKSUM_POSITION = 2;
|
||||
private SocketAddress responseSocketAddress; // socket address used when receptionning request and to sending response
|
||||
private DatagramSocket responseSocket; // socket used to recept request and send response
|
||||
private DatagramSocket requestSocket; // socket used to send request and to reception response
|
||||
|
||||
/** Constructor with payload parameter (typically used when sending packet).
|
||||
* @param payload the payload associated with the packet to send
|
||||
*/
|
||||
public ProtocolP2PPacketUDP(Payload payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
/** Send a Packet. Socket must be set and connected.
|
||||
* @param socket DatagramSocket used to send Packet.
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void send(DatagramSocket socket) throws InternalError, IOException {
|
||||
send(socket, null);
|
||||
}
|
||||
|
||||
/** Send a Packet. Socket must be set and connected, or an addr can be given.
|
||||
* @param socket DatagramSocket used to send Packet.
|
||||
* @param addr SocketAddress used to send Packet.
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void send(DatagramSocket socket, SocketAddress addr) throws InternalError, IOException {
|
||||
assert socket != null : "Trying to send a Packet but no socket defined";
|
||||
assert socket.isConnected() || addr != null : "Trying to send a Packet but socket not connected, and no socketAddress given";
|
||||
if (socket == null || ((!socket.isConnected()) && (addr == null))) {
|
||||
throw new InternalError();
|
||||
}
|
||||
// generate DatagramPacket
|
||||
byte[] packet = toPacket();
|
||||
DatagramPacket datagramPacket = new DatagramPacket(packet, packet.length);
|
||||
if (addr != null) {
|
||||
datagramPacket.setSocketAddress(addr);
|
||||
}
|
||||
// send it
|
||||
socket.send(datagramPacket);
|
||||
}
|
||||
|
||||
/** Send a Request throught socket. Socket must be connected (typically used from client).
|
||||
* @param socket DatagramSocket. Must be connected.
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
public void sendRequest(Object socket) throws InternalError, IOException {
|
||||
assert socket instanceof DatagramSocket: "Wrong socket type";
|
||||
if (socket instanceof DatagramSocket) {
|
||||
requestSocket = (DatagramSocket)socket;
|
||||
send(requestSocket);
|
||||
} else {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Receive Request (typically used from server).
|
||||
* @param serverSocket socket used to receive request
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
* @throws IOException
|
||||
* @return ProtocolP2PPacket received.
|
||||
*/
|
||||
public ProtocolP2PPacketUDP(Object serverSocket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {
|
||||
super(serverSocket);
|
||||
assert serverSocket instanceof DatagramSocket : "Wrong socket type";
|
||||
if (!(serverSocket instanceof DatagramSocket)) {
|
||||
throw new InternalError();
|
||||
}
|
||||
DatagramSocket ss = (DatagramSocket)serverSocket;
|
||||
byte[] packet = new byte[1024];
|
||||
DatagramPacket reception = new DatagramPacket(packet, packet.length);
|
||||
ss.receive(reception);
|
||||
responseSocketAddress = reception.getSocketAddress();
|
||||
// contruction
|
||||
boolean protocolError = false;
|
||||
try {
|
||||
constructPacket(packet, ss);
|
||||
Payload payload = getPayload();
|
||||
switch (payload.getRequestResponseCode()) {
|
||||
case PROTOCOL_ERROR :
|
||||
// we do not want to create an infinite loop of protocolError message exchange.
|
||||
protocolError = true;
|
||||
break;
|
||||
case VERSION_ERROR :
|
||||
case INTERNAL_ERROR :
|
||||
case EMPTY_DIRECTORY :
|
||||
case NOT_FOUND :
|
||||
case EMPTY_FILE:
|
||||
case LOAD_RESPONSE:
|
||||
case LIST_RESPONSE:
|
||||
// we were expecting a request, but we are receiving a response
|
||||
throw new ProtocolError();
|
||||
default :
|
||||
break;
|
||||
}
|
||||
} catch (TransmissionError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress);
|
||||
throw e;
|
||||
} catch (ProtocolError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(ss, responseSocketAddress);
|
||||
throw e;
|
||||
} catch (VersionError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.VERSION_ERROR))).send(ss, responseSocketAddress);
|
||||
throw e;
|
||||
} catch (InternalError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress);
|
||||
throw e;
|
||||
} catch (SizeError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(ss, responseSocketAddress);
|
||||
throw e;
|
||||
}
|
||||
if (protocolError) {
|
||||
throw new ProtocolError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Send a Response to a Request (typically used from server).
|
||||
* @param response Packet to send as a response.
|
||||
* @throws InternalError
|
||||
* @throws IOException
|
||||
*/
|
||||
public void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException {
|
||||
assert response instanceof ProtocolP2PPacketUDP: "Wrong Packet type";
|
||||
if (response instanceof ProtocolP2PPacketUDP) {
|
||||
ProtocolP2PPacketUDP r = (ProtocolP2PPacketUDP) response;
|
||||
assert responseSocket != null : "Cannot send response to a packet not received";
|
||||
if (responseSocket == null) {
|
||||
throw new InternalError();
|
||||
}
|
||||
assert responseSocketAddress != null : "Cannot send response because address of client has not been saved";
|
||||
if (responseSocketAddress == null) {
|
||||
throw new InternalError();
|
||||
}
|
||||
r.send(responseSocket, responseSocketAddress);
|
||||
} else {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Receive response (typically used by client).
|
||||
* @return ProtocolP2PPacket received
|
||||
* @throws EmptyFile
|
||||
* @throws NotFound
|
||||
* @throws EmptyDirectory
|
||||
* @throws InternalRemoteError
|
||||
* @throws VersionRemoteError
|
||||
* @throws ProtocolRemoteError
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
* @throws IOException
|
||||
*/
|
||||
public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {
|
||||
assert requestSocket != null : "Cannot receive response because request packet not sent.";
|
||||
if (requestSocket == null) {
|
||||
throw new InternalError();
|
||||
}
|
||||
// reception
|
||||
byte[] packet = new byte[8192];
|
||||
DatagramPacket reception = new DatagramPacket(packet, packet.length);
|
||||
requestSocket.receive(reception);
|
||||
// contruction
|
||||
try {
|
||||
ProtocolP2PPacketUDP p = new ProtocolP2PPacketUDP(packet);
|
||||
Payload payload = p.getPayload();
|
||||
switch (payload.getRequestResponseCode()) {
|
||||
case PROTOCOL_ERROR :
|
||||
throw new ProtocolRemoteError();
|
||||
case VERSION_ERROR :
|
||||
throw new VersionRemoteError();
|
||||
case INTERNAL_ERROR :
|
||||
throw new InternalRemoteError();
|
||||
case EMPTY_DIRECTORY :
|
||||
throw new EmptyDirectory();
|
||||
case NOT_FOUND :
|
||||
throw new NotFound();
|
||||
case EMPTY_FILE:
|
||||
throw new EmptyFile();
|
||||
default :
|
||||
return (ProtocolP2PPacket)p;
|
||||
}
|
||||
} catch (TransmissionError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket);
|
||||
throw e;
|
||||
} catch (ProtocolError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.PROTOCOL_ERROR))).send(requestSocket);
|
||||
throw e;
|
||||
} catch (VersionError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.VERSION_ERROR))).send(requestSocket);
|
||||
throw e;
|
||||
} catch (InternalError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket);
|
||||
throw e;
|
||||
} catch (SizeError e) {
|
||||
(new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(requestSocket);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/** Private constructor with packet as byte[] parameter (typically used when receiving Packet response).
|
||||
* @param packet the full Packet received
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
*/
|
||||
private ProtocolP2PPacketUDP(byte[] packet) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError {
|
||||
super(packet);
|
||||
constructPacket(packet);
|
||||
}
|
||||
|
||||
/** Private constructor helper with packet as byte[] parameter (typically used when receiving Packet response/request).
|
||||
* @param packet the full Packet received
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
*/
|
||||
private void constructPacket(byte[] packet) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError {
|
||||
// unwrap version
|
||||
version = packet[VERSION_POSITION];
|
||||
checkProtocolVersion(); // this can throw VersionError
|
||||
checkCheckSum(packet);
|
||||
RequestResponseCode r = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]); // this can throw ProtocolError
|
||||
switch (r) {
|
||||
case LIST_RESPONSE:
|
||||
payload = (Payload) new FileList(packet);
|
||||
break;
|
||||
case LOAD_RESPONSE:
|
||||
payload = (Payload) new FilePart(packet);
|
||||
break;
|
||||
case LOAD_REQUEST:
|
||||
payload = (Payload) new LoadRequest(packet);
|
||||
break;
|
||||
default:
|
||||
payload = new Payload(packet); // this can throw TransmissionError
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Private constructor helper with packet as byte[] parameter and (typically used when receiving Packet request).
|
||||
* @param packet the full Packet received
|
||||
* @param responseSocket socket address used to reception this request (use this one to respond)
|
||||
* @throws TransmissionError
|
||||
* @throws ProtocolError
|
||||
* @throws VersionError
|
||||
* @throws InternalError
|
||||
* @throws SizeError
|
||||
*/
|
||||
private void constructPacket(byte[] packet, DatagramSocket responseSocket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError {
|
||||
constructPacket(packet);
|
||||
this.responseSocket = responseSocket;
|
||||
}
|
||||
|
||||
/** Returns a byte[] containing full packet (typically used when sending packet).
|
||||
* This packet is complete and ready to be send.
|
||||
* @return the full packet to send
|
||||
* @throws InternalError
|
||||
*/
|
||||
protected byte[] toPacket() throws InternalError {
|
||||
byte[] packet = payload.toPacket();
|
||||
packet[VERSION_POSITION] = version;
|
||||
setCheckSum(packet);
|
||||
return packet;
|
||||
}
|
||||
|
||||
/** Compute checksum associated to packet.
|
||||
* @param packet the full packet received
|
||||
* @throws SizeError
|
||||
*/
|
||||
private int computeCheckSum(byte [] packet) throws SizeError {
|
||||
/*
|
||||
* The checksum field is the 16 bit one’s complement of the one’s complement sum of all 16-bit words
|
||||
* in the header and text. If a segment contains an odd number of header and text octets to be checksummed,
|
||||
* the last octet is padded on the right with zeros to form a 16-bit word for checksum purposes.
|
||||
* The pad is not transmitted as part of the segment. While computing the checksum, the checksum field
|
||||
* itself is replaced with zeros.
|
||||
*/
|
||||
int checksum = 0;
|
||||
for (int i=CHECKSUM_POSITION+2; i<CHECKSUM_POSITION+2+4+Payload.getPayloadSize(packet); ++i) {
|
||||
checksum += BytesArrayTools.readInt16Bits(packet, i);
|
||||
checksum &= 0xffff;
|
||||
}
|
||||
return checksum ^ 0xffff;
|
||||
}
|
||||
|
||||
/** Used to set checksum into packet
|
||||
* @param packet full packet
|
||||
* @throws InternalError
|
||||
*/
|
||||
private void setCheckSum(byte [] packet) throws InternalError {
|
||||
try {
|
||||
int checksum = computeCheckSum(packet);
|
||||
BytesArrayTools.write16Bits(packet, CHECKSUM_POSITION, checksum);
|
||||
} catch (SizeError e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to check if the checksum is correct
|
||||
* @param packet full packet
|
||||
* @throws TransmissionError
|
||||
*/
|
||||
|
||||
private void checkCheckSum(byte [] packet) throws TransmissionError {
|
||||
try {
|
||||
int checksum = BytesArrayTools.readInt16Bits(packet, CHECKSUM_POSITION);
|
||||
int computedCheckSum = computeCheckSum(packet);
|
||||
if (computedCheckSum != checksum){
|
||||
throw new TransmissionError();
|
||||
}
|
||||
} catch(SizeError e) {
|
||||
throw new TransmissionError();
|
||||
}
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ public enum RequestResponseCode {
|
||||
|
||||
/** Private constructor
|
||||
* @param codeType type of code (request or response)
|
||||
* @param codeValue value of the element in datagram
|
||||
* @param codeValue value of the element in Packet
|
||||
* @return enum element
|
||||
*/
|
||||
private RequestResponseCode(CodeType codeType, byte codeValue) {
|
||||
@ -47,8 +47,8 @@ public enum RequestResponseCode {
|
||||
this.codeValue = codeValue;
|
||||
}
|
||||
|
||||
/** Gives enum from datagram code.
|
||||
* @param code value of the element in datagram
|
||||
/** Gives enum from Packet code.
|
||||
* @param code value of the element in packet
|
||||
* @return enum element
|
||||
*/
|
||||
protected static RequestResponseCode fromCode(byte code) throws ProtocolError {
|
||||
|
@ -3,10 +3,12 @@ import java.util.Vector;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.Files;
|
||||
import protocolP2P.ProtocolP2PDatagram;
|
||||
import protocolP2P.ProtocolP2PPacketUDP;
|
||||
import protocolP2P.ProtocolP2PPacket;
|
||||
import protocolP2P.RequestResponseCode;
|
||||
import protocolP2P.Payload;
|
||||
import protocolP2P.LoadRequest;
|
||||
@ -60,7 +62,7 @@ public class ServerManagementUDP implements Runnable {
|
||||
public void run() {
|
||||
while(true) {
|
||||
try {
|
||||
ProtocolP2PDatagram pd = ProtocolP2PDatagram.receive(socket);
|
||||
ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket);
|
||||
Payload p = pd.getPayload();
|
||||
switch (p.getRequestResponseCode()) {
|
||||
case LOAD_REQUEST:
|
||||
@ -87,9 +89,9 @@ public class ServerManagementUDP implements Runnable {
|
||||
if (Arrays.binarySearch(fileList, filename) >= 0) {
|
||||
try {
|
||||
if (load.length == 0) {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.EMPTY_FILE))).send(socket, pd);
|
||||
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_FILE)));
|
||||
} else {
|
||||
(new ProtocolP2PDatagram((Payload)(new FilePart(filename, fullLoad.length, offset, load)))).send(socket, pd);
|
||||
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FilePart(filename, fullLoad.length, offset, load))));
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
System.err.println(e2);
|
||||
@ -105,7 +107,7 @@ public class ServerManagementUDP implements Runnable {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.NOT_FOUND))).send(socket, pd);
|
||||
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.NOT_FOUND)));
|
||||
} catch (Exception e2) {
|
||||
System.err.println(e2);
|
||||
}
|
||||
@ -117,10 +119,10 @@ public class ServerManagementUDP implements Runnable {
|
||||
try {
|
||||
if (fileList.length == 0) {
|
||||
System.err.println("Sending EMPTY_DIRECTORY");
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.EMPTY_DIRECTORY))).send(socket, pd);
|
||||
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.EMPTY_DIRECTORY)));
|
||||
} else {
|
||||
System.out.println("Sending LIST_RESPONSE");
|
||||
(new ProtocolP2PDatagram((Payload)(new FileList(fileList)))).send(socket, pd);
|
||||
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)(new FileList(fileList))));
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
System.err.println(e2);
|
||||
@ -129,18 +131,12 @@ public class ServerManagementUDP implements Runnable {
|
||||
default:
|
||||
sendInternalError(pd);
|
||||
}
|
||||
} catch (NotFound e) {
|
||||
} catch (EmptyDirectory e) {
|
||||
} catch (InternalRemoteError e) {
|
||||
} catch (VersionRemoteError e) {
|
||||
} catch (ProtocolRemoteError e) {
|
||||
} catch (IOException e) {
|
||||
} catch (TransmissionError e) {
|
||||
} catch (ProtocolError e) {
|
||||
} catch (VersionError e) {
|
||||
} catch (InternalError e) {
|
||||
} catch (SizeError e) {
|
||||
} catch (EmptyFile e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,11 +161,11 @@ public class ServerManagementUDP implements Runnable {
|
||||
|
||||
|
||||
/** Send an internal error message.
|
||||
* @param pd ProtocolP2PDatagram to respond
|
||||
* @param pd ProtocolP2PPacketUDP to respond
|
||||
*/
|
||||
private void sendInternalError(ProtocolP2PDatagram pd) {
|
||||
private void sendInternalError(ProtocolP2PPacketUDP pd) {
|
||||
try {
|
||||
(new ProtocolP2PDatagram(new Payload(RequestResponseCode.INTERNAL_ERROR))).send(socket, pd);
|
||||
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.INTERNAL_ERROR)));
|
||||
} catch (Exception e) {
|
||||
System.err.println(e);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user