|
|
|
@ -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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|