Update server to punish clients
All checks were successful
flavien's git/Projet_JAVA_P2P_STRI2A/pipeline/pr-etape5 This commit looks good
All checks were successful
flavien's git/Projet_JAVA_P2P_STRI2A/pipeline/pr-etape5 This commit looks good
This commit is contained in:
parent
f33b91dccd
commit
e02386453b
@ -126,8 +126,7 @@ public abstract class ClientDownload extends ServeErrors implements Runnable {
|
|||||||
try {
|
try {
|
||||||
sockList.get(rand.nextInt(sockList.size())).assignTask(offset);
|
sockList.get(rand.nextInt(sockList.size())).assignTask(offset);
|
||||||
offsetsPending.add(offset);
|
offsetsPending.add(offset);
|
||||||
System.err.println("Assigned task "+ offset);
|
writeLog("Assigned task: #"+ offset, LogLevel.Info);
|
||||||
writeLog("Assigned task "+ offset, LogLevel.Info);
|
|
||||||
} catch(InterruptedException e) {
|
} catch(InterruptedException e) {
|
||||||
writeLog(e, LogLevel.Error);
|
writeLog(e, LogLevel.Error);
|
||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
@ -232,7 +231,6 @@ public abstract class ClientDownload extends ServeErrors implements Runnable {
|
|||||||
writeLog(e, LogLevel.Error);
|
writeLog(e, LogLevel.Error);
|
||||||
hash = new byte[0];
|
hash = new byte[0];
|
||||||
} catch (NotFound e) {
|
} catch (NotFound e) {
|
||||||
writeLog(e, LogLevel.Error);
|
|
||||||
hash = new byte[0];
|
hash = new byte[0];
|
||||||
} catch (LocalException e) {
|
} catch (LocalException e) {
|
||||||
writeLog(e, LogLevel.Error);
|
writeLog(e, LogLevel.Error);
|
||||||
@ -258,6 +256,7 @@ public abstract class ClientDownload extends ServeErrors implements Runnable {
|
|||||||
*/
|
*/
|
||||||
protected void purgeList() throws InternalError {
|
protected void purgeList() throws InternalError {
|
||||||
List<HostItem> blackList = new ArrayList<HostItem>();
|
List<HostItem> blackList = new ArrayList<HostItem>();
|
||||||
|
writeLog("Potential peers (before purge): " + hostList.size(), LogLevel.Debug);
|
||||||
boolean first = false;
|
boolean first = false;
|
||||||
byte[] hashsum;
|
byte[] hashsum;
|
||||||
for(HostItem host: hostList) {
|
for(HostItem host: hostList) {
|
||||||
@ -276,6 +275,7 @@ public abstract class ClientDownload extends ServeErrors implements Runnable {
|
|||||||
for(HostItem host: blackList) {
|
for(HostItem host: blackList) {
|
||||||
hostList.remove(host);
|
hostList.remove(host);
|
||||||
}
|
}
|
||||||
|
writeLog("Peers (after purge): " + hostList.size(), LogLevel.Debug);
|
||||||
writeLog("Host list purge: done", LogLevel.Info);
|
writeLog("Host list purge: done", LogLevel.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,17 +368,11 @@ public abstract class ClientDownload extends ServeErrors implements Runnable {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
init();
|
init();
|
||||||
if (stop) {
|
purgeList();
|
||||||
writeLog("File is smaller than part max size.", LogLevel.Info);
|
initThreads();
|
||||||
closeHostItemSocket(hostList.get(0));
|
while(!stop) {
|
||||||
} else {
|
assignTasks();
|
||||||
writeLog("File is bigger than part max size.", LogLevel.Info);
|
checkTasksStatus();
|
||||||
purgeList();
|
|
||||||
initThreads();
|
|
||||||
while(!stop) {
|
|
||||||
assignTasks();
|
|
||||||
checkTasksStatus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
writeLog("Reassembling file parts.", LogLevel.Info);
|
writeLog("Reassembling file parts.", LogLevel.Info);
|
||||||
reassembleFile();
|
reassembleFile();
|
||||||
|
@ -8,6 +8,7 @@ import protocolP2P.ProtocolP2PPacket;
|
|||||||
import protocolP2P.Payload;
|
import protocolP2P.Payload;
|
||||||
import protocolP2P.LoadRequest;
|
import protocolP2P.LoadRequest;
|
||||||
import protocolP2P.FilePart;
|
import protocolP2P.FilePart;
|
||||||
|
import protocolP2P.Denied;
|
||||||
import localException.InternalError;
|
import localException.InternalError;
|
||||||
import localException.ProtocolError;
|
import localException.ProtocolError;
|
||||||
import localException.TransmissionError;
|
import localException.TransmissionError;
|
||||||
@ -203,7 +204,6 @@ public abstract class ClientDownloadPart extends ServeErrors implements Runnable
|
|||||||
if (p == null) {
|
if (p == null) {
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
failed = downloadPart(p);
|
failed = downloadPart(p);
|
||||||
if (failed) {
|
if (failed) {
|
||||||
System.err.println("Error: DownloadPart failed.");
|
System.err.println("Error: DownloadPart failed.");
|
||||||
@ -224,7 +224,7 @@ public abstract class ClientDownloadPart extends ServeErrors implements Runnable
|
|||||||
* @return ProtocolP2PPacketTCP used to send request
|
* @return ProtocolP2PPacketTCP used to send request
|
||||||
*/
|
*/
|
||||||
protected ProtocolP2PPacket<?> reqPart(Long offset) {
|
protected ProtocolP2PPacket<?> reqPart(Long offset) {
|
||||||
writeLog("New request: " + offset, LogLevel.Info);
|
writeLog("New request: #" + offset, LogLevel.Info);
|
||||||
// maintain tracking of tasks
|
// maintain tracking of tasks
|
||||||
if (toDoTasks.contains(offset)) {
|
if (toDoTasks.contains(offset)) {
|
||||||
try {
|
try {
|
||||||
@ -279,6 +279,22 @@ public abstract class ClientDownloadPart extends ServeErrors implements Runnable
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Payload p = d.receiveResponse().getPayload();
|
Payload p = d.receiveResponse().getPayload();
|
||||||
|
if (p instanceof Denied) {
|
||||||
|
Denied denied = (Denied)p;
|
||||||
|
if (!denied.getFilename().equals(filename)) {
|
||||||
|
writeLog("wrong file deny response received: `" + denied.getFilename() + "`", LogLevel.Error);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Long offset = Long.valueOf(denied.getOffset());
|
||||||
|
if (pendingTasks.contains(offset)) {
|
||||||
|
pendingTasks.remove(offset);
|
||||||
|
toDoTasks.add(offset);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
writeLog("wrong file offset deny received: " + offset, LogLevel.Error);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
assert p instanceof FilePart : "This payload must be instance of FilePart";
|
assert p instanceof FilePart : "This payload must be instance of FilePart";
|
||||||
if (!(p instanceof FilePart)) {
|
if (!(p instanceof FilePart)) {
|
||||||
writeLog("cannot get size.", LogLevel.Error);
|
writeLog("cannot get size.", LogLevel.Error);
|
||||||
|
@ -26,6 +26,7 @@ import remoteException.NotFound;
|
|||||||
import remoteException.ProtocolRemoteError;
|
import remoteException.ProtocolRemoteError;
|
||||||
import remoteException.VersionRemoteError;
|
import remoteException.VersionRemoteError;
|
||||||
import remoteException.NotATracker;
|
import remoteException.NotATracker;
|
||||||
|
import remoteException.UnknownHost;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
@ -165,6 +166,9 @@ public abstract class ClientManagement extends ServeErrors implements Runnable {
|
|||||||
} catch (NotATracker e) {
|
} catch (NotATracker e) {
|
||||||
writeLog(e, LogLevel.Error);
|
writeLog(e, LogLevel.Error);
|
||||||
throw new ProtocolError();
|
throw new ProtocolError();
|
||||||
|
} catch (UnknownHost e) {
|
||||||
|
writeLog(e, LogLevel.Error);
|
||||||
|
throw new ProtocolError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +216,7 @@ public abstract class ClientManagement extends ServeErrors implements Runnable {
|
|||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
} else {
|
} else {
|
||||||
downLoader.sendRatioUpdate();
|
downLoader.sendRatioUpdate();
|
||||||
|
writeLog("Ratio updates sent.", LogLevel.Info);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
|
@ -56,7 +56,7 @@ public class DiscoverResponse extends Payload {
|
|||||||
int port = BytesArrayTools.readInt16Bits(packet, i);
|
int port = BytesArrayTools.readInt16Bits(packet, i);
|
||||||
i += 2;
|
i += 2;
|
||||||
String hostname = BytesArrayTools.readString(packet, i, "\n");
|
String hostname = BytesArrayTools.readString(packet, i, "\n");
|
||||||
i += hostname.length();
|
i += hostname.length() + 1; // 1 for the "\n"
|
||||||
hostList.add(new HostItem(hostname, port));
|
hostList.add(new HostItem(hostname, port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ public class LoadRequest extends Payload {
|
|||||||
/* Read hostItem */
|
/* Read hostItem */
|
||||||
int portPosition = FILENAME_POSITION + size;
|
int portPosition = FILENAME_POSITION + size;
|
||||||
int hostnameStartPosition = portPosition + 2;
|
int hostnameStartPosition = portPosition + 2;
|
||||||
int hostnameSize = getPayloadSize(packet) - hostnameStartPosition;
|
int hostnameSize = getPayloadSize(packet) - hostnameStartPosition + PAYLOAD_START_POSITION;
|
||||||
hostItem = new HostItem(BytesArrayTools.readString(packet, hostnameStartPosition, hostnameSize), BytesArrayTools.readInt16Bits(packet, portPosition));
|
hostItem = new HostItem(BytesArrayTools.readString(packet, hostnameStartPosition, hostnameSize), BytesArrayTools.readInt16Bits(packet, portPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import remoteException.ProtocolRemoteError;
|
|||||||
import remoteException.VersionRemoteError;
|
import remoteException.VersionRemoteError;
|
||||||
import remoteException.EmptyFile;
|
import remoteException.EmptyFile;
|
||||||
import remoteException.NotATracker;
|
import remoteException.NotATracker;
|
||||||
|
import remoteException.UnknownHost;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import tools.HostItem;
|
import tools.HostItem;
|
||||||
|
|
||||||
@ -72,8 +73,9 @@ public abstract class ProtocolP2PPacket < T extends Payload>{
|
|||||||
* @throws SizeError
|
* @throws SizeError
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws SocketClosed
|
* @throws SocketClosed
|
||||||
|
* @throws UnknownHost
|
||||||
*/
|
*/
|
||||||
public abstract ProtocolP2PPacket<?> receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed;
|
public abstract ProtocolP2PPacket<?> receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed, UnknownHost;
|
||||||
|
|
||||||
/** Receive a request, subclasses must overwrite this constructor.
|
/** Receive a request, subclasses must overwrite this constructor.
|
||||||
* @param socket socket used to get the request
|
* @param socket socket used to get the request
|
||||||
|
@ -12,6 +12,7 @@ import remoteException.NotFound;
|
|||||||
import remoteException.ProtocolRemoteError;
|
import remoteException.ProtocolRemoteError;
|
||||||
import remoteException.VersionRemoteError;
|
import remoteException.VersionRemoteError;
|
||||||
import remoteException.EmptyFile;
|
import remoteException.EmptyFile;
|
||||||
|
import remoteException.UnknownHost;
|
||||||
import tools.HostItem;
|
import tools.HostItem;
|
||||||
import protocolP2P.Payload;
|
import protocolP2P.Payload;
|
||||||
import protocolP2P.RequestResponseCode;
|
import protocolP2P.RequestResponseCode;
|
||||||
@ -212,8 +213,9 @@ public class ProtocolP2PPacketTCP < T extends Payload > extends ProtocolP2PPacke
|
|||||||
* @throws SizeError
|
* @throws SizeError
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws SocketClosed
|
* @throws SocketClosed
|
||||||
|
* @throws UnknownHost
|
||||||
*/
|
*/
|
||||||
public ProtocolP2PPacket<?> receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed {
|
public ProtocolP2PPacket<?> receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, SocketClosed, UnknownHost {
|
||||||
assert requestSocket != null : "Cannot receive response because request packet not sent.";
|
assert requestSocket != null : "Cannot receive response because request packet not sent.";
|
||||||
if (requestSocket == null) {
|
if (requestSocket == null) {
|
||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
@ -253,6 +255,8 @@ public class ProtocolP2PPacketTCP < T extends Payload > extends ProtocolP2PPacke
|
|||||||
throw new EmptyFile();
|
throw new EmptyFile();
|
||||||
case NOT_A_TRACKER:
|
case NOT_A_TRACKER:
|
||||||
throw new NotATracker();
|
throw new NotATracker();
|
||||||
|
case UNKNOWN_HOST:
|
||||||
|
throw new UnknownHost();
|
||||||
default :
|
default :
|
||||||
return (ProtocolP2PPacket)p;
|
return (ProtocolP2PPacket)p;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import remoteException.NotFound;
|
|||||||
import remoteException.ProtocolRemoteError;
|
import remoteException.ProtocolRemoteError;
|
||||||
import remoteException.VersionRemoteError;
|
import remoteException.VersionRemoteError;
|
||||||
import remoteException.EmptyFile;
|
import remoteException.EmptyFile;
|
||||||
|
import remoteException.UnknownHost;
|
||||||
import tools.BytesArrayTools;
|
import tools.BytesArrayTools;
|
||||||
import tools.HostItem;
|
import tools.HostItem;
|
||||||
import protocolP2P.Payload;
|
import protocolP2P.Payload;
|
||||||
@ -207,8 +208,9 @@ public class ProtocolP2PPacketUDP < T extends Payload> extends ProtocolP2PPacket
|
|||||||
* @throws InternalError
|
* @throws InternalError
|
||||||
* @throws SizeError
|
* @throws SizeError
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
* @throws UnknownHost
|
||||||
*/
|
*/
|
||||||
public ProtocolP2PPacket<?> receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException {
|
public ProtocolP2PPacket<?> receiveResponse() throws EmptyFile, NotFound, NotATracker, EmptyDirectory, InternalRemoteError, VersionRemoteError, ProtocolRemoteError, TransmissionError, ProtocolError, VersionError, InternalError, SizeError, IOException, UnknownHost {
|
||||||
assert requestSocket != null : "Cannot receive response because request packet not sent.";
|
assert requestSocket != null : "Cannot receive response because request packet not sent.";
|
||||||
if (requestSocket == null) {
|
if (requestSocket == null) {
|
||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
@ -237,6 +239,8 @@ public class ProtocolP2PPacketUDP < T extends Payload> extends ProtocolP2PPacket
|
|||||||
throw new EmptyFile();
|
throw new EmptyFile();
|
||||||
case NOT_A_TRACKER:
|
case NOT_A_TRACKER:
|
||||||
throw new NotATracker();
|
throw new NotATracker();
|
||||||
|
case UNKNOWN_HOST:
|
||||||
|
throw new UnknownHost();
|
||||||
default :
|
default :
|
||||||
return (ProtocolP2PPacket)p;
|
return (ProtocolP2PPacket)p;
|
||||||
}
|
}
|
||||||
|
177
src/serverP2P/RatioWatcher.java
Normal file
177
src/serverP2P/RatioWatcher.java
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package serverP2P;
|
||||||
|
import tools.Logger;
|
||||||
|
import tools.LogLevel;
|
||||||
|
import tools.HostItem;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.io.IOException;
|
||||||
|
import exception.RemoteException;
|
||||||
|
import exception.LocalException;
|
||||||
|
import protocolP2P.RatioRequest;
|
||||||
|
import protocolP2P.RatioResponse;
|
||||||
|
import protocolP2P.Payload;
|
||||||
|
import protocolP2P.ProtocolP2PPacket;
|
||||||
|
import remoteException.UnknownHost;
|
||||||
|
import remoteException.NotATracker;
|
||||||
|
import localException.InternalError;
|
||||||
|
|
||||||
|
/** Class allowing to keep the tracker informed about ratios
|
||||||
|
* @author Louis Royer
|
||||||
|
* @author Flavien Haas
|
||||||
|
* @author JS Auge
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public abstract class RatioWatcher implements Runnable {
|
||||||
|
final static double punishmentFactor = 1.2;
|
||||||
|
protected Logger logger;
|
||||||
|
protected volatile boolean stop;
|
||||||
|
protected long time;
|
||||||
|
protected boolean force;
|
||||||
|
protected HostItem tracker;
|
||||||
|
protected Thread thread;
|
||||||
|
protected Map<HostItem, Double> cachePunishmentProbability = new HashMap<>();
|
||||||
|
protected boolean lock;
|
||||||
|
|
||||||
|
|
||||||
|
/** Constructor
|
||||||
|
* @param logger Logger
|
||||||
|
* @param millis Time interval before recheck
|
||||||
|
* @param tracker HostItem for the tracker
|
||||||
|
*/
|
||||||
|
public RatioWatcher(Logger logger, long millis, HostItem tracker) {
|
||||||
|
assert logger != null : "Logger is null";
|
||||||
|
assert tracker != null : "Tracker is null";
|
||||||
|
this.logger = logger;
|
||||||
|
time = millis;
|
||||||
|
this.tracker = tracker;
|
||||||
|
lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Runnable implementation */
|
||||||
|
public void run() {
|
||||||
|
writeLog("Ratio watcher started : delay " + time + " milliseconds.", LogLevel.Info);
|
||||||
|
while(!stop) {
|
||||||
|
try {
|
||||||
|
clean();
|
||||||
|
Thread.sleep(time);
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
writeLog("Ratio watcher interrupted", LogLevel.Info);
|
||||||
|
setStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Invalidate the cache by cleaning all hashmaps
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
protected synchronized void clean() throws InterruptedException{
|
||||||
|
while(lock) {
|
||||||
|
this.wait();
|
||||||
|
}
|
||||||
|
lock = true;
|
||||||
|
cachePunishmentProbability.clear();
|
||||||
|
lock = false;
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Get Up-ratio for an applications
|
||||||
|
* @param application HostItem of the application
|
||||||
|
* @return Punishment Probability
|
||||||
|
* @throws UnknownHost
|
||||||
|
*/
|
||||||
|
protected synchronized double getPunishmentProbability(HostItem application) throws InternalError, UnknownHost {
|
||||||
|
try {
|
||||||
|
while(lock) {
|
||||||
|
this.wait();
|
||||||
|
}
|
||||||
|
lock = true;
|
||||||
|
if (!cachePunishmentProbability.containsKey(application)) {
|
||||||
|
// update if not in cache
|
||||||
|
try {
|
||||||
|
ProtocolP2PPacket<?> p = createProtocolP2PPacket(new RatioRequest(application));
|
||||||
|
p.sendRequest(getTrackerSocket());
|
||||||
|
Payload resp = p.receiveResponse().getPayload();
|
||||||
|
if (!(resp instanceof RatioResponse)) {
|
||||||
|
throw new InternalError();
|
||||||
|
}
|
||||||
|
RatioResponse rresp = (RatioResponse)resp;
|
||||||
|
if (!rresp.getHostItem().equals(application)) {
|
||||||
|
writeLog("Ratio response host is not the expected one. Expected : "
|
||||||
|
+ application + ". Received : " + rresp.getHostItem(), LogLevel.Debug);
|
||||||
|
throw new InternalError();
|
||||||
|
}
|
||||||
|
long up = rresp.getTotalUp();
|
||||||
|
long down = rresp.getTotalDown();
|
||||||
|
assert punishmentFactor > 1 : "The punishment factor must be greater than 1";
|
||||||
|
if (down == 0 || (punishmentFactor * up) >= down) {
|
||||||
|
cachePunishmentProbability.put(application, Double.valueOf(0));
|
||||||
|
} else {
|
||||||
|
cachePunishmentProbability.put(application, Double.valueOf((down - up)/(down * punishmentFactor)));
|
||||||
|
}
|
||||||
|
} catch (UnknownHost e) {
|
||||||
|
throw e;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InternalError();
|
||||||
|
} catch (LocalException e) {
|
||||||
|
writeLog(e, LogLevel.Error);
|
||||||
|
throw new InternalError();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
writeLog(e, LogLevel.Error);
|
||||||
|
throw new InternalError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double ret = cachePunishmentProbability.get(application);
|
||||||
|
lock = false;
|
||||||
|
this.notifyAll();
|
||||||
|
return ret;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new InternalError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Ask the thread to stop
|
||||||
|
*/
|
||||||
|
public void setStop() {
|
||||||
|
stop = true;
|
||||||
|
if (thread != null) {
|
||||||
|
thread.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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);
|
||||||
|
|
||||||
|
/** Set thread
|
||||||
|
* @param thread Thread
|
||||||
|
*/
|
||||||
|
public void setThread(Thread thread) {
|
||||||
|
this.thread = thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create packets
|
||||||
|
* @param payload Payload
|
||||||
|
*/
|
||||||
|
protected abstract < T extends Payload > ProtocolP2PPacket<?> createProtocolP2PPacket(T payload);
|
||||||
|
|
||||||
|
/** Tracker socket getter
|
||||||
|
* @return tracker socket
|
||||||
|
*/
|
||||||
|
protected abstract Object getTrackerSocket();
|
||||||
|
|
||||||
|
/** Closes tracker socket
|
||||||
|
*/
|
||||||
|
protected abstract void closeTrackerSocket();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
66
src/serverP2P/RatioWatcherTCP.java
Normal file
66
src/serverP2P/RatioWatcherTCP.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package serverP2P;
|
||||||
|
import tools.Logger;
|
||||||
|
import tools.LogLevel;
|
||||||
|
import protocolP2P.ProtocolP2PPacket;
|
||||||
|
import protocolP2P.ProtocolP2PPacketTCP;
|
||||||
|
import protocolP2P.Payload;
|
||||||
|
import tools.HostItem;
|
||||||
|
import serverP2P.RatioWatcher;
|
||||||
|
|
||||||
|
/** Class allowing to keep the tracker informed about file list (TCP impl.)
|
||||||
|
* @author Louis Royer
|
||||||
|
* @author Flavien Haas
|
||||||
|
* @author JS Auge
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class RatioWatcherTCP extends RatioWatcher {
|
||||||
|
|
||||||
|
/** Constructor
|
||||||
|
* @param logger Logger
|
||||||
|
* @param millis Time interval before recheck
|
||||||
|
* @param tracker HostItem for the tracker
|
||||||
|
*/
|
||||||
|
public RatioWatcherTCP(Logger logger, long millis, HostItem tracker) {
|
||||||
|
super(logger, millis, tracker);
|
||||||
|
assert logger != null : "Logger is null";
|
||||||
|
assert tracker != null : "Tracker is null";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Implementation of writeLog
|
||||||
|
* @param text Text to log
|
||||||
|
* @param logLevel level of logging
|
||||||
|
*/
|
||||||
|
protected void writeLog(String text, LogLevel logLevel) {
|
||||||
|
logger.writeTCP(text, logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Implementation of writeLog
|
||||||
|
* @param e exception to log
|
||||||
|
* @param logLevel level of logging
|
||||||
|
*/
|
||||||
|
protected void writeLog(Exception e, LogLevel logLevel) {
|
||||||
|
logger.writeTCP(e, logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create packets
|
||||||
|
* @param payload Payload
|
||||||
|
*/
|
||||||
|
protected < T extends Payload > ProtocolP2PPacket<T> createProtocolP2PPacket(T payload) {
|
||||||
|
return (ProtocolP2PPacket<T>)new ProtocolP2PPacketTCP<T>(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tracker socket getter
|
||||||
|
* @return tracker socket
|
||||||
|
*/
|
||||||
|
protected Object getTrackerSocket() {
|
||||||
|
return tracker.getTCPSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Closes tracker socket
|
||||||
|
*/
|
||||||
|
protected void closeTrackerSocket() {
|
||||||
|
tracker.closeTCPSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
64
src/serverP2P/RatioWatcherUDP.java
Normal file
64
src/serverP2P/RatioWatcherUDP.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package serverP2P;
|
||||||
|
import tools.Logger;
|
||||||
|
import tools.LogLevel;
|
||||||
|
import protocolP2P.ProtocolP2PPacket;
|
||||||
|
import protocolP2P.ProtocolP2PPacketUDP;
|
||||||
|
import protocolP2P.Payload;
|
||||||
|
import tools.HostItem;
|
||||||
|
import serverP2P.RatioWatcher;
|
||||||
|
|
||||||
|
/** Class allowing to keep the tracker informed about file list (UDP impl.)
|
||||||
|
* @author Louis Royer
|
||||||
|
* @author Flavien Haas
|
||||||
|
* @author JS Auge
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class RatioWatcherUDP extends RatioWatcher {
|
||||||
|
|
||||||
|
/** Constructor
|
||||||
|
* @param logger Logger
|
||||||
|
* @param millis Time interval before recheck
|
||||||
|
* @param tracker HostItem for the tracker
|
||||||
|
*/
|
||||||
|
public RatioWatcherUDP(Logger logger, long millis, HostItem tracker) {
|
||||||
|
super(logger, millis, tracker);
|
||||||
|
assert logger != null : "Logger is null";
|
||||||
|
assert tracker != null : "Tracker is null";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Implementation of writeLog
|
||||||
|
* @param text Text to log
|
||||||
|
* @param logLevel level of logging
|
||||||
|
*/
|
||||||
|
protected void writeLog(String text, LogLevel logLevel) {
|
||||||
|
logger.writeUDP(text, logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Implementation of writeLog
|
||||||
|
* @param e exception to log
|
||||||
|
* @param logLevel level of logging
|
||||||
|
*/
|
||||||
|
protected void writeLog(Exception e, LogLevel logLevel) {
|
||||||
|
logger.writeUDP(e, logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create packets
|
||||||
|
* @param payload Payload
|
||||||
|
*/
|
||||||
|
protected < T extends Payload > ProtocolP2PPacket<T> createProtocolP2PPacket(T payload) {
|
||||||
|
return (ProtocolP2PPacket<T>)new ProtocolP2PPacketUDP<T>(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tracker socket getter
|
||||||
|
* @return tracker socket
|
||||||
|
*/
|
||||||
|
protected Object getTrackerSocket() {
|
||||||
|
return tracker.getUDPSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Closes tracker socket
|
||||||
|
*/
|
||||||
|
protected void closeTrackerSocket() {
|
||||||
|
tracker.closeUDPSocket();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package serverP2P;
|
package serverP2P;
|
||||||
import serverP2P.FileWatcher;
|
import serverP2P.FileWatcher;
|
||||||
|
import serverP2P.RatioWatcher;
|
||||||
import tools.Logger;
|
import tools.Logger;
|
||||||
import tools.LogLevel;
|
import tools.LogLevel;
|
||||||
import tools.HostItem;
|
import tools.HostItem;
|
||||||
@ -16,14 +17,18 @@ import protocolP2P.HashAlgorithm;
|
|||||||
import protocolP2P.Unregister;
|
import protocolP2P.Unregister;
|
||||||
import protocolP2P.SizeRequest;
|
import protocolP2P.SizeRequest;
|
||||||
import protocolP2P.SizeResponse;
|
import protocolP2P.SizeResponse;
|
||||||
|
import protocolP2P.Denied;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Random;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import exception.LocalException;
|
import exception.LocalException;
|
||||||
|
import localException.InternalError;
|
||||||
|
import remoteException.UnknownHost;
|
||||||
|
|
||||||
/** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol.
|
/** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol.
|
||||||
* @author Louis Royer
|
* @author Louis Royer
|
||||||
@ -39,6 +44,8 @@ public abstract class ServerManagement extends ServeErrors implements Runnable {
|
|||||||
protected String baseDirectory;
|
protected String baseDirectory;
|
||||||
protected HostItem server;
|
protected HostItem server;
|
||||||
protected HostItem tracker;
|
protected HostItem tracker;
|
||||||
|
protected Random punisher = new Random();
|
||||||
|
protected RatioWatcher ratioWatcher;
|
||||||
|
|
||||||
/** Constructor */
|
/** Constructor */
|
||||||
public ServerManagement(String baseDirectory, HostItem server, HostItem tracker, Logger logger) {
|
public ServerManagement(String baseDirectory, HostItem server, HostItem tracker, Logger logger) {
|
||||||
@ -58,6 +65,7 @@ public abstract class ServerManagement extends ServeErrors implements Runnable {
|
|||||||
public void setStop() {
|
public void setStop() {
|
||||||
stop = true;
|
stop = true;
|
||||||
fileListWatcher.setStop();
|
fileListWatcher.setStop();
|
||||||
|
ratioWatcher.setStop();
|
||||||
sendUnregisterRequest();
|
sendUnregisterRequest();
|
||||||
closeSocket();
|
closeSocket();
|
||||||
}
|
}
|
||||||
@ -145,27 +153,48 @@ public abstract class ServerManagement extends ServeErrors implements Runnable {
|
|||||||
long offset = ((LoadRequest)p).getOffset();
|
long offset = ((LoadRequest)p).getOffset();
|
||||||
long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent();
|
long maxSizePartialContent = ((LoadRequest)p).getMaxSizePartialContent();
|
||||||
try {
|
try {
|
||||||
byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename));
|
|
||||||
long sizeToSend = 0;
|
|
||||||
if (fullLoad.length - offset < maxSizePartialContent) {
|
|
||||||
writeLog("Sending last partialContent", LogLevel.Debug);
|
|
||||||
sizeToSend = fullLoad.length - offset;
|
|
||||||
} else {
|
|
||||||
sizeToSend = maxSizePartialContent;
|
|
||||||
}
|
|
||||||
writeLog("maxSizePartialContent: " + maxSizePartialContent, LogLevel.Debug);
|
|
||||||
writeLog("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend), LogLevel.Debug);
|
|
||||||
byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend));
|
|
||||||
String[] fileList = fileListWatcher.getFileList();
|
String[] fileList = fileListWatcher.getFileList();
|
||||||
if (Arrays.binarySearch(fileList, filename) >= 0) {
|
if (Arrays.binarySearch(fileList, filename) >= 0) {
|
||||||
try {
|
try {
|
||||||
if (load.length == 0) {
|
double proba = ratioWatcher.getPunishmentProbability(((LoadRequest)p).getHostItem());
|
||||||
sendEmptyFile(pd);
|
if (punisher.nextDouble() <= proba) {
|
||||||
|
writeLog("Sending punishment", LogLevel.Debug);
|
||||||
|
pd.sendResponse(createProtocolP2PPacket(new Denied(filename, offset)));
|
||||||
} else {
|
} else {
|
||||||
pd.sendResponse(createProtocolP2PPacket((Payload)(new FilePart(filename, offset, load))));
|
byte[] fullLoad = Files.readAllBytes(Paths.get(baseDirectory + filename));
|
||||||
|
long sizeToSend = 0;
|
||||||
|
if (fullLoad.length - offset < maxSizePartialContent) {
|
||||||
|
writeLog("Sending last partialContent", LogLevel.Debug);
|
||||||
|
sizeToSend = fullLoad.length - offset;
|
||||||
|
} else {
|
||||||
|
sizeToSend = maxSizePartialContent;
|
||||||
|
}
|
||||||
|
writeLog("maxSizePartialContent: " + maxSizePartialContent, LogLevel.Debug);
|
||||||
|
writeLog("Sending " + filename + " from " + offset + " to " + (offset + sizeToSend), LogLevel.Debug);
|
||||||
|
byte[] load = Arrays.copyOfRange(fullLoad, (int)offset, (int)(offset + sizeToSend));
|
||||||
|
try {
|
||||||
|
if (load.length == 0) {
|
||||||
|
sendEmptyFile(pd);
|
||||||
|
} else {
|
||||||
|
pd.sendResponse(createProtocolP2PPacket((Payload)(new FilePart(filename, offset, load))));
|
||||||
|
}
|
||||||
|
} catch (Exception e2) {
|
||||||
|
writeLog(e2, LogLevel.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e2) {
|
} catch (InternalError e) {
|
||||||
writeLog(e2, LogLevel.Error);
|
writeLog("InternalError", LogLevel.Debug);
|
||||||
|
writeLog(e, LogLevel.Debug);
|
||||||
|
sendInternalError(pd);
|
||||||
|
return;
|
||||||
|
} catch (UnknownHost e) {
|
||||||
|
writeLog("Unknown host: " + ((LoadRequest)p).getHostItem(), LogLevel.Debug);
|
||||||
|
writeLog(e, LogLevel.Debug);
|
||||||
|
sendInternalError(pd);
|
||||||
|
return;
|
||||||
|
} catch(LocalException e) {
|
||||||
|
sendInternalError(pd);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writeLog("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename), LogLevel.Debug);
|
writeLog("File requested not found: `" + filename + "` " + Arrays.binarySearch(fileList, filename), LogLevel.Debug);
|
||||||
|
@ -82,6 +82,10 @@ public class ServerManagementTCP extends ServerManagement {
|
|||||||
Thread flwt = new Thread(fileListWatcher);
|
Thread flwt = new Thread(fileListWatcher);
|
||||||
flwt.start();
|
flwt.start();
|
||||||
fileListWatcher.setThread(flwt);
|
fileListWatcher.setThread(flwt);
|
||||||
|
ratioWatcher = (RatioWatcher)new RatioWatcherTCP(logger, 10000, tracker);
|
||||||
|
Thread rwt = new Thread(ratioWatcher);
|
||||||
|
rwt.start();
|
||||||
|
ratioWatcher.setThread(rwt);
|
||||||
while(!stop) {
|
while(!stop) {
|
||||||
try {
|
try {
|
||||||
Socket s = socket.accept();
|
Socket s = socket.accept();
|
||||||
|
@ -77,6 +77,10 @@ public class ServerManagementUDP extends ServerManagement {
|
|||||||
Thread flwt = new Thread(fileListWatcher);
|
Thread flwt = new Thread(fileListWatcher);
|
||||||
flwt.start();
|
flwt.start();
|
||||||
fileListWatcher.setThread(flwt);
|
fileListWatcher.setThread(flwt);
|
||||||
|
ratioWatcher = (RatioWatcher)new RatioWatcherUDP(logger, 10000, tracker);
|
||||||
|
Thread rwt = new Thread(ratioWatcher);
|
||||||
|
rwt.start();
|
||||||
|
ratioWatcher.setThread(rwt);
|
||||||
while(!stop) {
|
while(!stop) {
|
||||||
try {
|
try {
|
||||||
ProtocolP2PPacketUDP<?> pd = new ProtocolP2PPacketUDP<>((Object)socket);
|
ProtocolP2PPacketUDP<?> pd = new ProtocolP2PPacketUDP<>((Object)socket);
|
||||||
|
@ -128,7 +128,7 @@ public class HostItem {
|
|||||||
boolean result = false;
|
boolean result = false;
|
||||||
if (other instanceof HostItem) {
|
if (other instanceof HostItem) {
|
||||||
HostItem that = (HostItem) other;
|
HostItem that = (HostItem) other;
|
||||||
result = this.getHostname() == that.getHostname() && this.getPort() == that.getPort();
|
result = this.getHostname().equals(that.getHostname()) && this.getPort() == that.getPort();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,14 @@ public abstract class TrackerManagement extends ServeErrors implements Runnable
|
|||||||
sendInternalError(pd);
|
sendInternalError(pd);
|
||||||
} else {
|
} else {
|
||||||
HostItem host = ((RatioRequest)p).getHostItem();
|
HostItem host = ((RatioRequest)p).getHostItem();
|
||||||
|
writeLog("Ratio request for host " + host, LogLevel.Debug);
|
||||||
try {
|
try {
|
||||||
if (!hostList.contains(host)) {
|
if (!hostList.contains(host)) {
|
||||||
|
String l = "";
|
||||||
|
for (HostItem h: hostList) {
|
||||||
|
l += h + " ";
|
||||||
|
}
|
||||||
|
writeLog(host + " is not in hostlist [ " + l + "]", LogLevel.Debug);
|
||||||
pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.UNKNOWN_HOST)));
|
pd.sendResponse(createProtocolP2PPacket(new Payload(RequestResponseCode.UNKNOWN_HOST)));
|
||||||
} else {
|
} else {
|
||||||
pd.sendResponse(createProtocolP2PPacket(new RatioResponse(host,
|
pd.sendResponse(createProtocolP2PPacket(new RatioResponse(host,
|
||||||
|
Loading…
Reference in New Issue
Block a user