Fixes #19, Fixes #13

pull/20/head
Louis Royer 4 years ago
parent e6d950d16b
commit 11901db822

@ -4,6 +4,7 @@ import exception.ProtocolError;
import exception.SizeError;
import exception.TransmissionError;
import exception.VersionError;
import exception.SocketClosed;
import remoteException.EmptyFile;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
@ -84,6 +85,8 @@ public class ClientManagementTCP implements Runnable {
System.err.println("Error: Client internal error");
} catch (UnknownHostException e) {
System.err.println("Error: Server host is unknown");
} catch (SocketClosed e) {
System.err.println("Error: Request cannot be send or response cannot be received");
} catch (IOException e) {
System.err.println("Error: Request cannot be send or response cannot be received");
} catch (TransmissionError e) {
@ -104,6 +107,13 @@ public class ClientManagementTCP implements Runnable {
System.err.println("Error: Server has not this file in directory");
} catch (EmptyFile e) {
System.err.println("Error: File is empty");
} finally {
try {
System.err.println("Closing socket");
socket.close();
} catch (IOException e2) {
System.err.println("Error: cannot close socket");
}
}
}
@ -113,6 +123,7 @@ public class ClientManagementTCP implements Runnable {
* @throws InternalError
* @throws UnknownHostException
* @throws IOException
* @throws SocketClosed
* @throws TransmissionError
* @throws ProtocolError
* @throws VersionError
@ -122,7 +133,7 @@ public class ClientManagementTCP implements Runnable {
* @throws VersionRemoteError
* @throws EmptyFile
*/
private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
private void download(String filename) throws EmptyFile, NotFound, InternalError, UnknownHostException, IOException, SocketClosed, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
final long MAX_PARTIAL_SIZE = 4096;
ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP((Payload) new LoadRequest(filename, 0, MAX_PARTIAL_SIZE));
d.sendRequest((Object)socket);
@ -195,6 +206,7 @@ public class ClientManagementTCP implements Runnable {
* @return list of files
* @throws InternalError
* @throws UnknowHostException
* @throws SocketClosed
* @throws IOException
* @throws TransmissionError
* @throws ProtocolError
@ -205,7 +217,7 @@ public class ClientManagementTCP implements Runnable {
* @throws ProtocolRemoteError
* @throws VersionRemoteError
*/
private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
private String[] listDirectory() throws EmptyDirectory, InternalError, UnknownHostException, SocketClosed, IOException, TransmissionError, ProtocolError, VersionError, SizeError, InternalRemoteError, ProtocolRemoteError, VersionRemoteError {
ProtocolP2PPacketTCP d = new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST));
d.sendRequest((Object)socket);
try {

@ -0,0 +1,4 @@
package exception;
public class SocketClosed extends Exception {
private static final long serialVersionUID = 12L;
}

@ -4,6 +4,7 @@ import exception.ProtocolError;
import exception.SizeError;
import exception.TransmissionError;
import exception.VersionError;
import exception.SocketClosed;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
import remoteException.NotFound;
@ -37,15 +38,17 @@ public abstract class ProtocolP2PPacket {
* @param socket Socket used to send packet.
* @throws InternalError
* @throws IOException
* @throws SocketClosed
*/
public abstract void sendRequest(Object socket) throws InternalError, IOException;
public abstract void sendRequest(Object socket) throws InternalError, IOException, SocketClosed;
/** Send a response
* @param response Response to send.
* @throws InternalError
* @throws IOException
* @throws SocketClosed
*/
public abstract void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException;
public abstract void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException, SocketClosed;
/** Receive a response
* @throws EmptyFile
@ -60,8 +63,9 @@ public abstract class ProtocolP2PPacket {
* @throws InternalError
* @throws SizeError
* @throws IOException
* @throws SocketClosed
*/
public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException;
public abstract ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed;
/** Receive a request, subclasses must overwrite this constructor.
* @param socket socket used to get the request
@ -71,8 +75,9 @@ public abstract class ProtocolP2PPacket {
* @throws InternalError
* @throws SizeError
* @throws IOException
* @throws SocketClosed
*/
protected ProtocolP2PPacket(Object socket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {}
protected ProtocolP2PPacket(Object socket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed {}
/** Construct a packet from byte[], subclasses must overwrite this constructor.
* @param packet Packet received

@ -4,6 +4,7 @@ import exception.ProtocolError;
import exception.SizeError;
import exception.TransmissionError;
import exception.VersionError;
import exception.SocketClosed;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
import remoteException.NotFound;
@ -44,9 +45,10 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
/** Send a Packet. Socket must be set and connected.
* @param socket Socket used to send Packet.
* @throws InternalError
* @throws SocketClosed
* @throws IOException
*/
protected void send(Socket socket) throws InternalError, IOException {
protected void send(Socket socket) throws InternalError, SocketClosed, IOException {
assert socket != null : "Trying to send a Packet but no socket defined";
assert socket.isConnected() : "Trying to send a Packet but socket not connected";
if (socket == null || (!socket.isConnected())) {
@ -55,17 +57,30 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
// generate Packet
byte[] packet = toPacket();
// send it
OutputStream outputStream = socket.getOutputStream();
outputStream.write(packet);
outputStream.flush();
try {
OutputStream outputStream = socket.getOutputStream();
outputStream.write(packet);
outputStream.flush();
} catch (IOException e) {
// closing socket
System.err.println("Error: cannot send response, closing socket");
try {
socket.close();
} catch (IOException e2) {
System.err.println("Cannot close socket");
} finally {
throw new SocketClosed();
}
}
}
/** Send a Request throught socket. Socket must be connected (typically used from client).
* @param socket Socket. Must be connected.
* @throws InternalError
* @throws SocketClosed
* @throws IOException
*/
public void sendRequest(Object socket) throws InternalError, IOException {
public void sendRequest(Object socket) throws InternalError, IOException, SocketClosed {
assert socket instanceof Socket: "Wrong socket type";
if (socket instanceof Socket) {
requestSocket = (Socket)socket;
@ -82,10 +97,11 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
* @throws VersionError
* @throws InternalError
* @throws SizeError
* @throws SocketClosed
* @throws IOException
* @return ProtocolP2PPacket received.
*/
public ProtocolP2PPacketTCP(Object socket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {
public ProtocolP2PPacketTCP(Object socket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, SocketClosed, IOException {
super(socket);
assert socket instanceof Socket : "Wrong socket type";
if (!(socket instanceof Socket)) {
@ -93,7 +109,18 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
}
Socket ss = (Socket)socket;
byte[] packet = new byte[1024];
ss.getInputStream().read(packet);
try {
System.err.println("Reading " + ss.getInputStream().read(packet) + " bytes");
} catch (IOException e) {
System.err.println("Error: cannot read request, closing socket");
try {
ss.close();
} catch (IOException e2) {
System.err.println("Cannot close socket");
} finally {
throw new SocketClosed();
}
}
// contruction
boolean protocolError = false;
try {
@ -141,8 +168,9 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
* @param response Packet to send as a response.
* @throws InternalError
* @throws IOException
* @throws SocketClosed
*/
public void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException {
public void sendResponse(ProtocolP2PPacket response) throws InternalError, IOException, SocketClosed {
assert response instanceof ProtocolP2PPacketTCP: "Wrong Packet type";
if (response instanceof ProtocolP2PPacketTCP) {
ProtocolP2PPacketTCP r = (ProtocolP2PPacketTCP) response;
@ -170,8 +198,9 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
* @throws InternalError
* @throws SizeError
* @throws IOException
* @throws SocketClosed
*/
public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {
public ProtocolP2PPacket receiveResponse() throws EmptyFile, NotFound, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed {
assert requestSocket != null : "Cannot receive response because request packet not sent.";
if (requestSocket == null) {
throw new InternalError();

@ -4,6 +4,7 @@ import exception.ProtocolError;
import exception.SizeError;
import exception.TransmissionError;
import exception.VersionError;
import exception.SocketClosed;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
import remoteException.NotFound;
@ -97,9 +98,10 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket {
* @throws InternalError
* @throws SizeError
* @throws IOException
* @throws SocketClosed
* @return ProtocolP2PPacket received.
*/
public ProtocolP2PPacketUDP(Object socket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {
public ProtocolP2PPacketUDP(Object socket) throws TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed {
super(socket);
assert socket instanceof DatagramSocket : "Wrong socket type";
if (!(socket instanceof DatagramSocket)) {

@ -20,6 +20,7 @@ import exception.ProtocolError;
import exception.SizeError;
import exception.TransmissionError;
import exception.VersionError;
import exception.SocketClosed;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
import remoteException.NotFound;
@ -64,93 +65,37 @@ public class ServerManagementTCP implements Runnable {
/** Implementation of runnable. This methods allows to run the server.
*/
public void run() {
// TODO: handling multiple clients
try {
Socket s = socket.accept();
System.err.println("Accepting new connection");
do {
try {
ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s);
Payload p = pd.getPayload();
switch (p.getRequestResponseCode()) {
case LOAD_REQUEST:
System.out.println("Received LOAD_REQUEST");
assert p instanceof LoadRequest : "payload must be an instance of LoadRequest";
if (!(p instanceof LoadRequest)) {
sendInternalError(pd);
} else {
String filename = ((LoadRequest)p).getFilename();
long offset = ((LoadRequest)p).getOffset();
long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent();
try {
byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename));
long sizeToSend = 0;
if (fullLoad.length - offset < maxSizePartialContent) {
System.out.println("Sending last partialContent");
sizeToSend = fullLoad.length - offset;
} else {
sizeToSend = maxSizePartialContent;
}
System.out.println("maxSizePartialContent: " + maxSizePartialContent);
System.out.println("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend));
byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend));
if (Arrays.binarySearch(fileList, filename) >= 0) {
try {
if (load.length == 0) {
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_FILE)));
} else {
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)(new FilePart(filename, fullLoad.length, offset, load))));
}
} catch (Exception e2) {
System.err.println(e2);
}
} else {
System.err.println("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename));
System.err.println("File list:");
for (String f: fileList) {
System.err.println("- " + f);
}
do {
try {
Socket s = socket.accept();
System.err.println("Accepting new connection");
ClientHandler c = new ClientHandler(s);
(new Thread(c)).start();
} catch (IOException e) {
System.err.println("Error while accepting new connection");
}
} while(true);
}
throw new IOException(); // to send a NOT_FOUND in the catch block
}
} catch (IOException e) {
try {
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_FOUND)));
} catch (Exception e2) {
System.err.println(e2);
}
}
}
break;
case LIST_REQUEST:
System.out.println("Received LIST_REQUEST");
try {
if (fileList.length == 0) {
System.err.println("Sending EMPTY_DIRECTORY");
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_DIRECTORY)));
} else {
System.out.println("Sending LIST_RESPONSE");
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)(new FileList(fileList))));
}
} catch (Exception e2) {
System.err.println(e2);
}
break;
default:
sendInternalError(pd);
}
} catch (SocketException e) {
System.out.println("connection closed");
s.close();
}
catch (IOException e) {}
catch (TransmissionError e) {}
catch (ProtocolError e) {}
catch (VersionError e) {}
catch (InternalError e) {}
catch (SizeError e) {}
} while(true);
} catch (IOException e) {
/** Private runnable class allowing to serve one client.
*/
private class ClientHandler implements Runnable {
Socket s;
/** Constructor with a socket.
* @param s Socket of this client
*/
public ClientHandler(Socket s) {
this.s = s;
}
/** Implementation of runnable. This method allow to serve one client.
*/
public void run() {
boolean end = false;
do {
end = handleRequest(s);
} while(!end);
System.err.println("End of thread");
}
}
@ -182,4 +127,107 @@ public class ServerManagementTCP implements Runnable {
}
}
/** Send response to list request
* @param pd Request received
*/
private void sendListResponse(ProtocolP2PPacketTCP pd) {
try {
if (fileList.length == 0) {
System.err.println("Sending EMPTY_DIRECTORY");
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_DIRECTORY)));
} else {
System.out.println("Sending LIST_RESPONSE");
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)(new FileList(fileList))));
}
} catch (Exception e2) {
System.err.println(e2);
}
}
/** Send response to load request
* @param pd Request received
*/
private void sendLoadResponse(ProtocolP2PPacketTCP pd) {
Payload p = pd.getPayload();
assert p instanceof LoadRequest : "payload must be an instance of LoadRequest";
if (!(p instanceof LoadRequest)) {
sendInternalError(pd);
} else {
String filename = ((LoadRequest)p).getFilename();
long offset = ((LoadRequest)p).getOffset();
long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent();
try {
byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename));
long sizeToSend = 0;
if (fullLoad.length - offset < maxSizePartialContent) {
System.out.println("Sending last partialContent");
sizeToSend = fullLoad.length - offset;
} else {
sizeToSend = maxSizePartialContent;
}
System.out.println("maxSizePartialContent: " + maxSizePartialContent);
System.out.println("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend));
byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend));
if (Arrays.binarySearch(fileList, filename) >= 0) {
try {
if (load.length == 0) {
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.EMPTY_FILE)));
} else {
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)(new FilePart(filename, fullLoad.length, offset, load))));
}
} catch (Exception e2) {
System.err.println(e2);
}
} else {
System.err.println("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename));
System.err.println("File list:");
for (String f: fileList) {
System.err.println("- " + f);
}
throw new IOException(); // to send a NOT_FOUND in the catch block
}
} catch (IOException e) {
try {
pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.NOT_FOUND)));
} catch (Exception e2) {
System.err.println(e2);
}
}
}
}
/** Respond to next request incomming on socket s.
* @param s Socket used to read request and send response
* @return true if cannot expect another request (ie, socket is closed)
*/
private boolean handleRequest(Socket s) {
try {
ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP((Object)s);
Payload p = pd.getPayload();
switch (p.getRequestResponseCode()) {
case LOAD_REQUEST:
System.out.println("Received LOAD_REQUEST");
sendLoadResponse(pd);
break;
case LIST_REQUEST:
System.out.println("Received LIST_REQUEST");
sendListResponse(pd);
break;
default:
sendInternalError(pd);
}
} catch (IOException e) {
return true;
} catch (SocketClosed e) {
return true;
}
catch (TransmissionError e) {}
catch (ProtocolError e) {}
catch (VersionError e) {}
catch (InternalError e) {}
catch (SizeError e) {}
return false;
}
}

@ -19,6 +19,7 @@ import exception.ProtocolError;
import exception.SizeError;
import exception.TransmissionError;
import exception.VersionError;
import exception.SocketClosed;
import remoteException.EmptyDirectory;
import remoteException.InternalRemoteError;
import remoteException.NotFound;
@ -132,6 +133,7 @@ public class ServerManagementUDP implements Runnable {
sendInternalError(pd);
}
} catch (IOException e) {
} catch (SocketClosed e) {
} catch (TransmissionError e) {
} catch (ProtocolError e) {
} catch (VersionError e) {

@ -23,6 +23,7 @@ public class ServerP2P {
Thread ttcp = new Thread(smtcp);
ttcp.setName("server TCP P2P-JAVA-PROJECT");
ttcp.start();
System.out.println("Server started.");
}
}

Loading…
Cancel
Save