From 275eb165b1cebc67f780d4eb3ef123909b6cf3b3 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 22 Mar 2020 14:53:23 +0100 Subject: [PATCH] Refactoring tracker + server --- src/serverP2P/ServerManagement.java | 87 +++++----- src/serverP2P/ServerManagementTCP.java | 42 +---- src/serverP2P/ServerManagementUDP.java | 31 +--- src/tools/ServeErrors.java | 82 ++++++++++ src/tracker/TrackerManagement.java | 194 ++++++++++++++++++++++ src/tracker/TrackerManagementTCP.java | 215 +++++-------------------- src/tracker/TrackerManagementUDP.java | 194 ++++------------------ 7 files changed, 398 insertions(+), 447 deletions(-) create mode 100644 src/tools/ServeErrors.java create mode 100644 src/tracker/TrackerManagement.java diff --git a/src/serverP2P/ServerManagement.java b/src/serverP2P/ServerManagement.java index 39f79d4..de4fdd2 100644 --- a/src/serverP2P/ServerManagement.java +++ b/src/serverP2P/ServerManagement.java @@ -3,6 +3,7 @@ import serverP2P.FileWatcher; import tools.Logger; import tools.LogLevel; import tools.HostItem; +import tools.ServeErrors; import protocolP2P.ProtocolP2PPacket; import protocolP2P.Payload; import protocolP2P.RequestResponseCode; @@ -19,6 +20,7 @@ import java.util.Arrays; import java.util.Map; import java.util.HashMap; import java.io.IOException; +import exception.LocalException; /** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol. * @author Louis Royer @@ -26,7 +28,7 @@ import java.io.IOException; * @author JS Auge * @version 1.0 */ -public abstract class ServerManagement implements Runnable { +public abstract class ServerManagement extends ServeErrors implements Runnable { protected volatile boolean stop; protected FileWatcher fileListWatcher; @@ -37,6 +39,7 @@ public abstract class ServerManagement implements Runnable { /** Constructor */ public ServerManagement(String baseDirectory, HostItem server, HostItem tracker, Logger logger) { + super(); assert baseDirectory != null : "baseDirectory is null"; assert server != null : "server is null"; assert tracker != null : "tracker is null"; @@ -61,23 +64,6 @@ public abstract class ServerManagement implements Runnable { } } - /** Implementation of writeLog - * @param text Text to log - * @param logLevel level of logging - */ - protected abstract void writeLog(String text, LogLevel logLevel); - - /** Implementation of writeLog - * @param e exception to log - * @param logLevel level of logging - */ - protected abstract void writeLog(Exception e, LogLevel logLevel); - - /** Create packets - * @param payload Payload - */ - protected abstract < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload); - /** Send response to list request * @param pd Request received */ @@ -86,7 +72,7 @@ public abstract class ServerManagement implements Runnable { String[] fileList = fileListWatcher.getFileList(); if (fileList.length == 0) { writeLog("Sending EMPTY_DIRECTORY to host " + pd.getHostItem(), LogLevel.Action); - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + sendEmptyDirectory(pd); } else { writeLog("Sending LIST_RESPONSE to host " + pd.getHostItem(), LogLevel.Action); pd.sendResponse(createProtocolP2PPacket((Payload)(new FileList(fileList)))); @@ -96,28 +82,7 @@ public abstract class ServerManagement implements Runnable { } } - /** Send a NotATracker error message. - * @param pd Request received - */ - protected < T extends ProtocolP2PPacket > void sendNotATracker(T pd) { - try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_A_TRACKER))); - } catch (Exception e) { - writeLog(e, LogLevel.Error); - } - } - /** Send an internal error message. - * @param pd Request received - */ - protected < T extends ProtocolP2PPacket > void sendInternalError(T pd) { - writeLog("Internal Error", LogLevel.Warning); - try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - writeLog(e, LogLevel.Error); - } - } /** Send hash response to hash request * @param pd Request received @@ -150,7 +115,7 @@ public abstract class ServerManagement implements Runnable { } else { // file not found try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + sendNotFound(pd); } catch (Exception e) { writeLog(e, LogLevel.Error); } @@ -186,7 +151,7 @@ public abstract class ServerManagement implements Runnable { if (Arrays.binarySearch(fileList, filename) >= 0) { try { if (load.length == 0) { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_FILE))); + sendEmptyFile(pd); } else { pd.sendResponse(createProtocolP2PPacket((Payload)(new FilePart(filename, fullLoad.length, offset, load)))); } @@ -204,7 +169,7 @@ public abstract class ServerManagement implements Runnable { } } catch (IOException e) { try { - pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + sendNotFound(pd); } catch (Exception e2) { writeLog(e2, LogLevel.Debug); } @@ -230,4 +195,40 @@ public abstract class ServerManagement implements Runnable { } } + /** Handle request. + * @throws LocalException + */ + protected < T extends ProtocolP2PPacket > void handleRequest(T pd) throws LocalException { + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + writeLog("Received LOAD_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendLoadResponse(pd); + break; + case LIST_REQUEST: + writeLog("Received LIST_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendListResponse(pd); + break; + case HASH_REQUEST: + writeLog("Received HASH_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendHashResponse(pd); + break; + case DISCOVER_REQUEST: + writeLog("Received DISCOVER_REQUEST from host " + pd.getHostItem(), LogLevel.Action); + sendNotATracker(pd); + break; + case UNREGISTER: + writeLog("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Action); + sendNotATracker(pd); + break; + case REGISTER: + writeLog("Received REGISTER from host " + pd.getHostItem(), LogLevel.Action); + sendNotATracker(pd); + break; + default: + writeLog("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + } + } + } diff --git a/src/serverP2P/ServerManagementTCP.java b/src/serverP2P/ServerManagementTCP.java index e829fd8..455cbd3 100644 --- a/src/serverP2P/ServerManagementTCP.java +++ b/src/serverP2P/ServerManagementTCP.java @@ -23,6 +23,7 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import exception.LocalException; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -110,7 +111,7 @@ public class ServerManagementTCP extends ServerManagement { boolean end = false; logger.writeTCP("[" + addr + "] New connection", LogLevel.Action); do { - end = handleRequest(); + end = handleClientRequest(); } while(!end); logger.writeTCP("[" + addr + "] End of connection", LogLevel.Action); } @@ -119,49 +120,16 @@ public class ServerManagementTCP extends ServerManagement { * @param s Socket used to read request and send response * @return true if cannot expect another request (ie, socket is closed) */ - private boolean handleRequest() { + private boolean handleClientRequest() { try { ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP<>((Object)addr.getTCPSocket()); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - logger.writeTCP(addr + "LOAD_REQUEST", LogLevel.Action); - sendLoadResponse(pd); - break; - case LIST_REQUEST: - logger.writeTCP(addr + "LIST_REQUEST", LogLevel.Action); - sendListResponse(pd); - break; - case HASH_REQUEST: - logger.writeTCP(addr + "HASH_REQUEST", LogLevel.Action); - sendHashResponse(pd); - break; - case DISCOVER_REQUEST: - logger.writeTCP(addr + "DISCOVER_REQUEST", LogLevel.Action); - sendNotATracker(pd); - break; - case UNREGISTER: - logger.writeTCP(addr + "UNREGISTER", LogLevel.Action); - sendNotATracker(pd); - break; - case REGISTER: - logger.writeTCP(addr + "REGISTER", LogLevel.Action); - sendNotATracker(pd); - break; - default: - logger.writeTCP(addr + "Received grabbage", LogLevel.Action); - sendInternalError(pd); - } + handleRequest(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) {} + catch (LocalException e) {} return false; } } diff --git a/src/serverP2P/ServerManagementUDP.java b/src/serverP2P/ServerManagementUDP.java index a3cd1fc..bba1a5b 100644 --- a/src/serverP2P/ServerManagementUDP.java +++ b/src/serverP2P/ServerManagementUDP.java @@ -22,6 +22,7 @@ import localException.SizeError; import localException.TransmissionError; import localException.VersionError; import localException.SocketClosed; +import exception.LocalException; import java.util.Arrays; import tools.Logger; import tools.LogLevel; @@ -77,35 +78,9 @@ public class ServerManagementUDP extends ServerManagement { while(!stop) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP<>((Object)socket); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - sendLoadResponse(pd); - break; - case LIST_REQUEST: - logger.writeUDP("Received LIST_REQUEST", LogLevel.Action); - sendListResponse(pd); - break; - case HASH_REQUEST: - logger.writeUDP("Received HASH_REQUEST", LogLevel.Action); - sendHashResponse(pd); - break; - case DISCOVER_REQUEST: - case UNREGISTER: - case REGISTER: - logger.writeUDP("Received Tracker request", LogLevel.Action); - sendNotATracker(pd); - break; - default: - sendInternalError(pd); - } + handleRequest(pd); } catch (IOException e) { - } catch (SocketClosed e) { - } catch (TransmissionError e) { - } catch (ProtocolError e) { - } catch (VersionError e) { - } catch (InternalError e) { - } catch (SizeError e) { + } catch (LocalException e) { } } fileListWatcher.setStop(); diff --git a/src/tools/ServeErrors.java b/src/tools/ServeErrors.java new file mode 100644 index 0000000..ff083f9 --- /dev/null +++ b/src/tools/ServeErrors.java @@ -0,0 +1,82 @@ +package tools; +import tools.LogLevel; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.Payload; +import protocolP2P.RequestResponseCode; + +public abstract class ServeErrors { + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected abstract void writeLog(String text, LogLevel logLevel); + + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected abstract void writeLog(Exception e, LogLevel logLevel); + + /** Create packets + * @param payload Payload + */ + protected abstract < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload); + + /** Send a NotATracker error message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendNotATracker(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_A_TRACKER))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send an internal error message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendInternalError(T pd) { + writeLog("Internal Error", LogLevel.Warning); + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.INTERNAL_ERROR))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send a not found message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendNotFound(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.NOT_FOUND))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send an empty directory message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendEmptyDirectory(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + + /** Send an empty file message. + * @param pd Request received + */ + protected < T extends ProtocolP2PPacket > void sendEmptyFile(T pd) { + try { + pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.EMPTY_FILE))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + +} diff --git a/src/tracker/TrackerManagement.java b/src/tracker/TrackerManagement.java new file mode 100644 index 0000000..e28790d --- /dev/null +++ b/src/tracker/TrackerManagement.java @@ -0,0 +1,194 @@ +package tracker; +import tools.ServeErrors; +import tools.HostItem; +import tools.Logger; +import tools.LogLevel; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; +import protocolP2P.ProtocolP2PPacket; +import protocolP2P.Payload; +import protocolP2P.DiscoverRequest; +import protocolP2P.DiscoverResponse; +import protocolP2P.FileList; +import protocolP2P.Unregister; +import protocolP2P.Register; +import protocolP2P.RequestResponseCode; +import localException.InternalError; +import remoteException.EmptyDirectory; +import exception.LocalException; + +public abstract class TrackerManagement extends ServeErrors implements Runnable { + protected HostItem tracker; + protected Logger logger; + protected List hostList = new ArrayList<>(); + protected Map> fileList = new HashMap<>(); + protected volatile boolean stop; + + /** Constructor + * @param tracker Tracker HostItem + * @param logger Logger + */ + public TrackerManagement(HostItem tracker, Logger logger) { + stop = false; + this.tracker = tracker; + this.logger = logger; + } + + /** Handle Discover request + * @param pd Received request + * @throws InternalError + */ + protected < T extends ProtocolP2PPacket > void handleDiscover(T pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; + if (!(p instanceof DiscoverRequest)) { + sendInternalError(pd); + } else { + String filename = ((DiscoverRequest)p).getFilename(); + try { + pd.sendResponse(createProtocolP2PPacket(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + } + + /** Handle List Responses + * @param pd Received response + * @throws InternalError + */ + protected > void handleListResponse(T pd, HostItem host) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof FileList: "payload must be an instance of FileList"; + if (!(p instanceof FileList)) { + throw new InternalError(); + } else { + String[] f = ((FileList)p).getFileList(); + for (String file: f) { + List h = fileList.get(file); + if (h != null) { + if (!h.contains(host)) { + h.add(host); + } + } else { + List emptyH = new ArrayList<>(); + emptyH.add(host); + fileList.put(file, emptyH); + } + } + } + } + + /** Handle Unregistering + * @param pd Request received + * @throws InternalError + */ + protected < T extends ProtocolP2PPacket > void handleUnregister(T pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Unregister : "payload must be an instance of Unregister"; + if (!(p instanceof Unregister)) { + sendInternalError(pd); + throw new InternalError(); + } + HostItem host = ((Unregister)p).getHostItem(); + writeLog("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); + hostList.remove(host); + for(String f: fileList.keySet()) { + fileList.get(f).remove(host); + if(fileList.get(f).isEmpty()) { + fileList.remove(f); + } + } + } + + /** Getter for HostItem socket + * @param hostItem HostItem + */ + protected abstract Object getHostItemSocket(HostItem hostItem); + + /** Close HostItem socket + * @param hostItem HostItem + */ + protected abstract void closeHostItemSocket(HostItem hostItem); + + /** Handle Registering + * @param pd Received request + * @throws InternalError + */ + protected < T extends ProtocolP2PPacket > void handleRegister(T pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof Register : "payload must be an instance of Register"; + if (!(p instanceof Register)) { + throw new InternalError(); + } + // add host to known host list + HostItem host = ((Register)p).getHostItem(); + if (!hostList.contains(host)) { + hostList.add(host); + } + // send a list request + try { + ProtocolP2PPacket pLReq = createProtocolP2PPacket(new Payload(RequestResponseCode.LIST_REQUEST)); + pLReq.sendRequest(getHostItemSocket(host)); + writeLog("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); + handleListResponse(pLReq.receiveResponse(), host); + writeLog("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); + closeHostItemSocket(host); + } catch (EmptyDirectory e) { + writeLog("Empty Directory", LogLevel.Debug); + hostList.remove(host); + writeLog("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); + } catch (Exception e) { + // remove from list because list request could not be send + hostList.remove(host); + writeLog("Aborting the add of host " + host, LogLevel.Action); + writeLog(e, LogLevel.Error); + } + } + + + /** Handle requests + * @throws LocalException + */ + protected > void handleRequest(T pd) throws LocalException { + Payload p = pd.getPayload(); + switch (p.getRequestResponseCode()) { + case LOAD_REQUEST: + writeLog("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case LIST_REQUEST: + writeLog("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); + sendEmptyDirectory(pd); + break; + case HASH_REQUEST: + writeLog("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); + sendNotFound(pd); + break; + case REGISTER: + writeLog("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); + handleRegister(pd); + break; + case UNREGISTER: + writeLog("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); + handleUnregister(pd); + break; + case DISCOVER_REQUEST: + writeLog("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); + handleDiscover(pd); + break; + default: + writeLog("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); + sendInternalError(pd); + break; + } + } + + /** Stop the thread */ + public void setStop() { + stop = true; + } + +} diff --git a/src/tracker/TrackerManagementTCP.java b/src/tracker/TrackerManagementTCP.java index b7d9249..bf659f3 100644 --- a/src/tracker/TrackerManagementTCP.java +++ b/src/tracker/TrackerManagementTCP.java @@ -25,6 +25,7 @@ import remoteException.EmptyDirectory; import java.net.UnknownHostException; import java.net.InetAddress; import localException.SocketClosed; +import tracker.TrackerManagement; /** Tracker management implementation with tcp @@ -33,21 +34,15 @@ import localException.SocketClosed; * @author JS Auge * @version 1.0 */ -public class TrackerManagementTCP implements Runnable { - - private HostItem tracker; - private Logger logger; +public class TrackerManagementTCP extends TrackerManagement { private ServerSocket socket; - private List hostList = new ArrayList<>(); - private Map> fileList = new HashMap<>(); /** Constructor with port and logger. * @param port Port used to listen. * @param logger Logger object */ public TrackerManagementTCP(int port, Logger logger) { - tracker = new HostItem("localhost", port); - this.logger = logger; + super(new HostItem("localhost", port), logger); try { socket = new ServerSocket(tracker.getPort(), 10, tracker.getInetAddress()); } catch (SocketException e) { @@ -63,7 +58,7 @@ public class TrackerManagementTCP implements Runnable { */ public void run() { logger.writeTCP("Tracker sucessfully started", LogLevel.Info); - do { + while (!stop) { try { Socket s = socket.accept(); ClientHandler c = new ClientHandler(s); @@ -71,7 +66,7 @@ public class TrackerManagementTCP implements Runnable { } catch (IOException e) { logger.writeTCP("Error while accepting new connection", LogLevel.Warning); } - } while(true); + } } @@ -93,7 +88,7 @@ public class TrackerManagementTCP implements Runnable { boolean end = false; logger.writeTCP("[ " + addr + "] New connection", LogLevel.Action); do { - end = handleRequest(); + end = handleClientRequest(); } while(!end); logger.writeTCP("[ " + addr + "] End of connection", LogLevel.Action); } @@ -102,39 +97,10 @@ public class TrackerManagementTCP implements Runnable { * @param s Socket used to read request and send response * @return true if cannot expect another request (ie, socket is closed) */ - private boolean handleRequest() { + private boolean handleClientRequest() { try { ProtocolP2PPacketTCP pd = new ProtocolP2PPacketTCP<>((Object)addr.getTCPSocket()); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - logger.writeTCP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case LIST_REQUEST: - logger.writeTCP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); - sendEmptyDirectory(pd); - break; - case HASH_REQUEST: - logger.writeTCP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case REGISTER: - logger.writeTCP("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleRegister(pd); - break; - case UNREGISTER: - logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleUnregister(pd); - break; - case DISCOVER_REQUEST: - handleDiscover(pd); - break; - default: - logger.writeTCP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); - sendInternalError(pd); - break; - } + handleRequest(pd); } catch (IOException e) { logger.writeTCP(e, LogLevel.Warning); return true; @@ -146,142 +112,43 @@ public class TrackerManagementTCP implements Runnable { } return false; } - - /** Send a not found message. - * @param pd ProtocolP2PPacketTCP to respond - */ - private void sendNotFound(ProtocolP2PPacketTCP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } - - /** Send an empty directory message. - * @param pd ProtocolP2PPacketTCP to respond - */ - private void sendEmptyDirectory(ProtocolP2PPacketTCP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } + } - /** Send an internal error message. - * @param pd ProtocolP2PPacketTCP to respond - */ - private void sendInternalError(ProtocolP2PPacketTCP pd) { - logger.writeTCP("Internal Error", LogLevel.Warning); - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketTCP<>(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging + */ + protected void writeLog(String text, LogLevel logLevel) { + logger.writeTCP(text, logLevel); + } - /** Handle Registering - * @param pd ProtocolP2PPacketTCP to respond - * @throws InternalError - */ - private void handleRegister(ProtocolP2PPacketTCP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Register : "payload must be an instance of Register"; - if (!(p instanceof Register)) { - throw new InternalError(); - } - // add host to known host list - HostItem host = ((Register)p).getHostItem(); - if (!hostList.contains(host)) { - hostList.add(host); - } - // send a list request - try { - ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST)); - pLReq.sendRequest((Object)host.getTCPSocket()); - logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); - handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host); - logger.writeTCP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); - host.closeTCPSocket(); - } catch (EmptyDirectory e) { - logger.writeTCP("Empty Directory", LogLevel.Debug); - hostList.remove(host); - logger.writeTCP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); - } catch (Exception e) { - // remove from list because list request could not be send - hostList.remove(host); - logger.writeTCP("Aborting the add of host " + host, LogLevel.Action); - logger.writeTCP(e, LogLevel.Error); - } - } + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging + */ + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeTCP(e, logLevel); + } - /** Handle Unregistering - * @param pd ProtocolP2PPacketTCP to respond - * @throws InternalError - */ - private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Unregister : "payload must be an instance of Unregister"; - if (!(p instanceof Unregister)) { - sendInternalError(pd); - throw new InternalError(); - } - HostItem host = ((Unregister)p).getHostItem(); - logger.writeTCP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); - hostList.remove(host); - for(String f: fileList.keySet()) { - fileList.get(f).remove(host); - if(fileList.get(f).isEmpty()) { - fileList.remove(f); - } - } - } + /** Create packets + * @param payload Payload + */ + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketTCP(payload); + } - /** Handle Discover request - * @param pd ProtocolP2PPacketTCP to respond - * @throws InternalError - */ - private void handleDiscover(ProtocolP2PPacketTCP pd) throws InternalError { - logger.writeTCP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; - if (!(p instanceof DiscoverRequest)) { - sendInternalError(pd); - } else { - String filename = ((DiscoverRequest)p).getFilename(); - try { - pd.sendResponse(new ProtocolP2PPacketTCP(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); - } catch (Exception e) { - logger.writeTCP(e, LogLevel.Error); - } - } - } + + /** Getter for HostItem socket + * @param hostItem HostItem + */ + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getTCPSocket(); + } - /** Handle List Responses - * @param pd ProtocolP2PPacketTCP response - * @throws InternalError - */ - private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - throw new InternalError(); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } - } - } + /** Close HostItem socket + * @param hostItem HostItem + */ + protected void closeHostItemSocket(HostItem hostItem) { + hostItem.closeTCPSocket(); } } diff --git a/src/tracker/TrackerManagementUDP.java b/src/tracker/TrackerManagementUDP.java index a99636a..6ed2235 100644 --- a/src/tracker/TrackerManagementUDP.java +++ b/src/tracker/TrackerManagementUDP.java @@ -23,6 +23,7 @@ import localException.InternalError; import remoteException.EmptyDirectory; import java.net.InetAddress; import java.net.UnknownHostException; +import tracker.TrackerManagement; /** Tracker management implementation with udp * @author Louis Royer @@ -30,21 +31,14 @@ import java.net.UnknownHostException; * @author JS Auge * @version 1.0 */ -public class TrackerManagementUDP implements Runnable { - - private HostItem tracker; - private Logger logger; +public class TrackerManagementUDP extends TrackerManagement { private DatagramSocket socket; - private List hostList = new ArrayList<>(); - private Map> fileList = new HashMap<>(); - /** Constructor with port and logger. * @param port Port used to listen. * @param logger Logger object */ public TrackerManagementUDP(int port, Logger logger) { - tracker = new HostItem("localhost", port); - this.logger = logger; + super(new HostItem("localhost", port), logger); try { socket = new DatagramSocket(tracker.getPort(), tracker.getInetAddress()); } catch (SocketException e) { @@ -57,39 +51,10 @@ public class TrackerManagementUDP implements Runnable { */ public void run() { logger.writeUDP("Tracker successfully started", LogLevel.Info); - while(true) { + while(!stop) { try { ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP<>((Object)socket); - Payload p = pd.getPayload(); - switch (p.getRequestResponseCode()) { - case LOAD_REQUEST: - logger.writeUDP("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case LIST_REQUEST: - logger.writeUDP("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action); - sendEmptyDirectory(pd); - break; - case HASH_REQUEST: - logger.writeUDP("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action); - sendNotFound(pd); - break; - case REGISTER: - logger.writeUDP("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleRegister(pd); - break; - case UNREGISTER: - logger.writeUDP("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug); - handleUnregister(pd); - break; - case DISCOVER_REQUEST: - handleDiscover(pd); - break; - default: - logger.writeUDP("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); - sendInternalError(pd); - break; - } + handleRequest(pd); } catch (IOException e) { logger.writeUDP(e, LogLevel.Warning); } catch (LocalException e) { @@ -97,143 +62,42 @@ public class TrackerManagementUDP implements Runnable { } } } - - /** Send a not found message. - * @param pd ProtocolP2PPacketUDP to respond - */ - private void sendNotFound(ProtocolP2PPacketUDP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.NOT_FOUND))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } - - /** Send an empty directory message. - * @param pd ProtocolP2PPacketUDP to respond - */ - private void sendEmptyDirectory(ProtocolP2PPacketUDP pd) { - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.EMPTY_DIRECTORY))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } - - /** Send an internal error message. - * @param pd ProtocolP2PPacketUDP to respond + + /** Implementation of writeLog + * @param text Text to log + * @param logLevel level of logging */ - private void sendInternalError(ProtocolP2PPacketUDP pd) { - logger.writeUDP("Internal Error", LogLevel.Warning); - try { - pd.sendResponse((ProtocolP2PPacket)new ProtocolP2PPacketUDP<>(new Payload(RequestResponseCode.INTERNAL_ERROR))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } + protected void writeLog(String text, LogLevel logLevel) { + logger.writeUDP(text, logLevel); } - /** Handle Registering - * @param pd ProtocolP2PPacketUDP to respond - * @throws InternalError + /** Implementation of writeLog + * @param e exception to log + * @param logLevel level of logging */ - private void handleRegister(ProtocolP2PPacketUDP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Register : "payload must be an instance of Register"; - if (!(p instanceof Register)) { - sendInternalError(pd); - throw new InternalError(); - } - // add host to known host list - HostItem host = ((Register)p).getHostItem(); - if (!hostList.contains(host)) { - hostList.add(host); - } - // send a list request - try { - ProtocolP2PPacket pLReq = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST)); - pLReq.sendRequest((Object)host.getUDPSocket()); - logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action); - ProtocolP2PPacket resp = pLReq.receiveResponse(); - handleListResponse((ProtocolP2PPacketUDP)resp, host); - logger.writeUDP("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action); - host.closeUDPSocket(); - } catch (EmptyDirectory e) { - logger.writeUDP("Empty Directory", LogLevel.Debug); - hostList.remove(host); - logger.writeUDP("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action); - } catch (Exception e) { - // remove from list because list request could not be send - hostList.remove(host); - logger.writeUDP("Aborting the add of host " + host, LogLevel.Action); - logger.writeUDP(e, LogLevel.Error); - } + protected void writeLog(Exception e, LogLevel logLevel) { + logger.writeUDP(e, logLevel); } - /** Handle Unregistering - * @param pd ProtocolP2PPacketUDP to respond - * @throws InternalError + /** Create packets + * @param payload Payload */ - private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof Unregister : "payload must be an instance of Unregister"; - if (!(p instanceof Unregister)) { - sendInternalError(pd); - throw new InternalError(); - } - HostItem host = ((Unregister)p).getHostItem(); - logger.writeUDP("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action); - hostList.remove(host); - for(String f: fileList.keySet()) { - fileList.get(f).remove(host); - if(fileList.get(f).isEmpty()) { - fileList.remove(f); - } - } + protected < T extends Payload > ProtocolP2PPacket createProtocolP2PPacket(T payload) { + return (ProtocolP2PPacket)new ProtocolP2PPacketUDP(payload); } - /** Handle Discover request - * @param pd ProtocolP2PPacketUDP to respond - * @throws InternalError + + /** Getter for HostItem socket + * @param hostItem HostItem */ - private void handleDiscover(ProtocolP2PPacketUDP pd) throws InternalError { - logger.writeUDP("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action); - Payload p = pd.getPayload(); - assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest"; - if (!(p instanceof DiscoverRequest)) { - sendInternalError(pd); - } else { - String filename = ((DiscoverRequest)p).getFilename(); - try { - pd.sendResponse(new ProtocolP2PPacketUDP(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList)))); - } catch (Exception e) { - logger.writeUDP(e, LogLevel.Error); - } - } + protected Object getHostItemSocket(HostItem hostItem) { + return (Object)hostItem.getUDPSocket(); } - /** Handle List Responses - * @param pd ProtocolP2PPacketUDP response - * @throws InternalError + /** Close HostItem socket + * @param hostItem HostItem */ - private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError { - Payload p = pd.getPayload(); - assert p instanceof FileList: "payload must be an instance of FileList"; - if (!(p instanceof FileList)) { - throw new InternalError(); - } else { - String[] f = ((FileList)p).getFileList(); - for (String file: f) { - List h = fileList.get(file); - if (h != null) { - if (!h.contains(host)) { - h.add(host); - } - } else { - List emptyH = new ArrayList<>(); - emptyH.add(host); - fileList.put(file, emptyH); - } - } - } + protected void closeHostItemSocket(HostItem hostItem) { + hostItem.closeUDPSocket(); } }