|
|
|
@ -51,6 +51,8 @@ public class ServerManagementTCP implements Runnable {
|
|
|
|
|
private Logger logger;
|
|
|
|
|
private HostItem tracker;
|
|
|
|
|
private HostItem server;
|
|
|
|
|
private FileListWatcher fileListWatcher;
|
|
|
|
|
private volatile boolean stop;
|
|
|
|
|
|
|
|
|
|
/** Constructor for TCP implementation, with baseDirectory and TCPPort parameters.
|
|
|
|
|
* @param baseDirectory the root directory where files are stored
|
|
|
|
@ -60,12 +62,12 @@ public class ServerManagementTCP implements Runnable {
|
|
|
|
|
* @param tracker Tracker
|
|
|
|
|
*/
|
|
|
|
|
public ServerManagementTCP(String baseDirectory, String hostName, int port, Logger logger, HostItem tracker) {
|
|
|
|
|
stop = false;
|
|
|
|
|
server = new HostItem(hostName, port);
|
|
|
|
|
fileList = new String[0];
|
|
|
|
|
this.tracker = tracker;
|
|
|
|
|
this.logger = logger;
|
|
|
|
|
this.baseDirectory = baseDirectory;
|
|
|
|
|
initFileList();
|
|
|
|
|
initSha512();
|
|
|
|
|
try {
|
|
|
|
|
socket = new ServerSocket(server.getPort(), 10, server.getInetAddress());
|
|
|
|
|
} catch (SocketException e) {
|
|
|
|
@ -77,12 +79,26 @@ public class ServerManagementTCP implements Runnable {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Stop the thread */
|
|
|
|
|
public void setStop() {
|
|
|
|
|
stop = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Trigger a manual check of the file list
|
|
|
|
|
*/
|
|
|
|
|
public void updateFileList() {
|
|
|
|
|
if (fileListWatcher != null) {
|
|
|
|
|
fileListWatcher.trigger();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Implementation of runnable. This methods allows to run the server.
|
|
|
|
|
*/
|
|
|
|
|
public void run() {
|
|
|
|
|
logger.writeTCP("Server sucessfully started", LogLevel.Info);
|
|
|
|
|
(new Thread(new TrackerRegisterer())).start();
|
|
|
|
|
do {
|
|
|
|
|
fileListWatcher = new FileListWatcher(10000); // checking every 10 seconds
|
|
|
|
|
(new Thread(fileListWatcher)).start();
|
|
|
|
|
while(!stop) {
|
|
|
|
|
try {
|
|
|
|
|
Socket s = socket.accept();
|
|
|
|
|
ClientHandler c = new ClientHandler(s);
|
|
|
|
@ -90,7 +106,17 @@ public class ServerManagementTCP implements Runnable {
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
logger.writeTCP("Error while accepting new connection", LogLevel.Warning);
|
|
|
|
|
}
|
|
|
|
|
} while(true);
|
|
|
|
|
}
|
|
|
|
|
fileListWatcher.setStop();
|
|
|
|
|
// unregistering from tracker
|
|
|
|
|
try {
|
|
|
|
|
logger.writeTCP("Unregistering from tracker", LogLevel.Info);
|
|
|
|
|
ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server));
|
|
|
|
|
p.sendRequest((Object)tracker.getTCPSocket());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
logger.writeTCP("Cannot unregister from tracker", LogLevel.Error);
|
|
|
|
|
logger.writeTCP(e, LogLevel.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Private runnable class allowing to serve one client.
|
|
|
|
@ -167,22 +193,6 @@ public class ServerManagementTCP implements Runnable {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Initialize local list of all files allowed to be shared.
|
|
|
|
|
*/
|
|
|
|
|
private void initFileList() {
|
|
|
|
|
File folder = new File(baseDirectory);
|
|
|
|
|
Vector<String> v = new Vector<String>();
|
|
|
|
|
File[] files = folder.listFiles();
|
|
|
|
|
/* Add non-recursively files's names to fileList */
|
|
|
|
|
for (File f : files) {
|
|
|
|
|
if (f.isFile()) {
|
|
|
|
|
v.add(f.getName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fileList = new String[v.size()];
|
|
|
|
|
v.toArray(fileList);
|
|
|
|
|
Arrays.sort(fileList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Init sha512 map.
|
|
|
|
|
*/
|
|
|
|
@ -333,39 +343,89 @@ public class ServerManagementTCP implements Runnable {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Private runnable class allowing to initialize tracker while initializing server. */
|
|
|
|
|
private class TrackerRegisterer implements Runnable {
|
|
|
|
|
|
|
|
|
|
/** Runnable implementation */
|
|
|
|
|
public void run() {
|
|
|
|
|
/** Private runnable class allowing to keep the tracker informed about file list. */
|
|
|
|
|
private class FileListWatcher implements Runnable {
|
|
|
|
|
private volatile boolean stop;
|
|
|
|
|
private long time;
|
|
|
|
|
private boolean force;
|
|
|
|
|
|
|
|
|
|
/** Register server on tracker
|
|
|
|
|
*/
|
|
|
|
|
private void registerTracker() {
|
|
|
|
|
try {
|
|
|
|
|
registerTracker();
|
|
|
|
|
logger.writeTCP("Trying to into tracker", LogLevel.Info);
|
|
|
|
|
ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server));
|
|
|
|
|
p.sendRequest((Object)tracker.tryGetTCPSocket());
|
|
|
|
|
logger.writeTCP("Register request sent.", LogLevel.Debug);
|
|
|
|
|
tracker.closeTCPSocket();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
logger.writeTCP(e, LogLevel.Error);
|
|
|
|
|
System.exit(-4);
|
|
|
|
|
// error, trying again at next iteration
|
|
|
|
|
force = true;
|
|
|
|
|
logger.writeTCP("Cannot contact tracker, trying again at next iteration (" + time + " milliseconds).", LogLevel.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/** Register server on tracker
|
|
|
|
|
* @throws InternalError
|
|
|
|
|
* @throws IOException
|
|
|
|
|
* @throws SocketClosed
|
|
|
|
|
|
|
|
|
|
/** Update fileList and returns true if different than old list.
|
|
|
|
|
* @return true if changed
|
|
|
|
|
*/
|
|
|
|
|
private void registerTracker() throws InternalError, IOException, SocketClosed {
|
|
|
|
|
logger.writeTCP("Unregistering from tracker", LogLevel.Info);
|
|
|
|
|
ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(server));
|
|
|
|
|
p.sendRequest((Object)tracker.getTCPSocket());
|
|
|
|
|
// FIXME: this is a hack
|
|
|
|
|
// ProtocolP2PPacketTCP reads 1024 bytes but if 2 request comes at the same time InputStream is cleared fully
|
|
|
|
|
// and we keep waiting forever on the other side
|
|
|
|
|
// a fix could be to read only the header first, and read the required size after
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(100);
|
|
|
|
|
} catch (InterruptedException e) {}
|
|
|
|
|
logger.writeTCP("Registering into tracker", LogLevel.Info);
|
|
|
|
|
p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(server));
|
|
|
|
|
p.sendRequest((Object)tracker.getTCPSocket());
|
|
|
|
|
logger.writeTCP("Registering completed", LogLevel.Debug);
|
|
|
|
|
tracker.closeTCPSocket();
|
|
|
|
|
private boolean updateFileList() {
|
|
|
|
|
File folder = new File(baseDirectory);
|
|
|
|
|
Vector<String> v = new Vector<String>();
|
|
|
|
|
File[] files = folder.listFiles();
|
|
|
|
|
/* Add non-recursively files's names to fileList */
|
|
|
|
|
for (File f : files) {
|
|
|
|
|
if (f.isFile()) {
|
|
|
|
|
v.add(f.getName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
String[] newFileList = new String[v.size()];
|
|
|
|
|
v.toArray(newFileList);
|
|
|
|
|
Arrays.sort(newFileList);
|
|
|
|
|
if (!Arrays.equals(newFileList, fileList)) {
|
|
|
|
|
fileList = newFileList;
|
|
|
|
|
initSha512();
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Constructor with millis parameter
|
|
|
|
|
* @param millis interval of time between checks
|
|
|
|
|
*/
|
|
|
|
|
public FileListWatcher(long millis) {
|
|
|
|
|
this.stop = false;
|
|
|
|
|
this.time = millis;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Ask the thread to stop
|
|
|
|
|
*/
|
|
|
|
|
public void setStop() {
|
|
|
|
|
stop = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Allow a manual check
|
|
|
|
|
*/
|
|
|
|
|
public void trigger() {
|
|
|
|
|
if (updateFileList() || force) {
|
|
|
|
|
force = false;
|
|
|
|
|
logger.writeTCP("File list watcher detected changes. Informing tracker.", LogLevel.Info);
|
|
|
|
|
registerTracker();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Runnable implementation */
|
|
|
|
|
public void run() {
|
|
|
|
|
logger.writeTCP("File list watcher started : delay " + time + " milliseconds.", LogLevel.Info);
|
|
|
|
|
while(!stop) {
|
|
|
|
|
trigger();
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(time);
|
|
|
|
|
} catch(InterruptedException e) {
|
|
|
|
|
logger.writeTCP("File list watcher interrupted", LogLevel.Error);
|
|
|
|
|
setStop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|