From b6351d30d3b4f4008d14b7eeb2c1883c2a50592e Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Feb 2020 00:19:50 +0100 Subject: [PATCH] Change to ProtocolP2PPacket, should be easier to implement tcp --- src/clientP2P/ClientManagementUDP.java | 26 +- src/clientP2P/ClientP2P.java | 14 +- src/exception/SizeError.java | 2 +- src/protocolP2P/FileList.java | 48 +-- src/protocolP2P/FilePart.java | 110 +++---- src/protocolP2P/LoadRequest.java | 51 +-- src/protocolP2P/Payload.java | 52 ++-- src/protocolP2P/ProtocolP2PDatagram.java | 298 ------------------ src/protocolP2P/ProtocolP2PPacket.java | 102 ++++++ src/protocolP2P/ProtocolP2PPacketUDP.java | 359 ++++++++++++++++++++++ src/protocolP2P/RequestResponseCode.java | 6 +- src/serverP2P/ServerManagementUDP.java | 28 +- 12 files changed, 632 insertions(+), 464 deletions(-) delete mode 100644 src/protocolP2P/ProtocolP2PDatagram.java create mode 100644 src/protocolP2P/ProtocolP2PPacket.java create mode 100644 src/protocolP2P/ProtocolP2PPacketUDP.java diff --git a/src/clientP2P/ClientManagementUDP.java b/src/clientP2P/ClientManagementUDP.java index 7916d5a..daf0a8f 100644 --- a/src/clientP2P/ClientManagementUDP.java +++ b/src/clientP2P/ClientManagementUDP.java @@ -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(); diff --git a/src/clientP2P/ClientP2P.java b/src/clientP2P/ClientP2P.java index 5deb0ea..8adc662 100644 --- a/src/clientP2P/ClientP2P.java +++ b/src/clientP2P/ClientP2P.java @@ -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(); } diff --git a/src/exception/SizeError.java b/src/exception/SizeError.java index 2108c64..ccf9ef1 100644 --- a/src/exception/SizeError.java +++ b/src/exception/SizeError.java @@ -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; } diff --git a/src/protocolP2P/FileList.java b/src/protocolP2P/FileList.java index 1dc0887..bc2ca69 100644 --- a/src/protocolP2P/FileList.java +++ b/src/protocolP2P/FileList.java @@ -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. diff --git a/src/protocolP2P/FilePart.java b/src/protocolP2P/FilePart.java index 3abf910..2e2a211 100644 --- a/src/protocolP2P/FilePart.java +++ b/src/protocolP2P/FilePart.java @@ -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(); } diff --git a/src/protocolP2P/LoadRequest.java b/src/protocolP2P/LoadRequest.java index 82c4a5f..39c4952 100644 --- a/src/protocolP2P/LoadRequest.java +++ b/src/protocolP2P/LoadRequest.java @@ -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. diff --git a/src/protocolP2P/Payload.java b/src/protocolP2P/Payload.java index c3638f6..6868b56 100644 --- a/src/protocolP2P/Payload.java +++ b/src/protocolP2P/Payload.java @@ -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. diff --git a/src/protocolP2P/ProtocolP2PDatagram.java b/src/protocolP2P/ProtocolP2PDatagram.java deleted file mode 100644 index ace1dfe..0000000 --- a/src/protocolP2P/ProtocolP2PDatagram.java +++ /dev/null @@ -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= 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); }