Add Register/Unregister

pull/48/head
Louis Royer 4 years ago
parent 07d9276232
commit a2f505c167

@ -120,6 +120,7 @@ Payload contains:
```
2 bytes: [<PORT NUMBER>]
? bytes: [<HOSTNAME>]
```
#### Discover request
@ -128,7 +129,7 @@ If payload contains a filename, list all servers having this file in their list.
```
? bytes: [<FILENAME>]
? bytes: [<HOSTNAME>]
```
#### Discover response

@ -6,6 +6,12 @@ import localException.SizeError;
import localException.ProtocolError;
import localException.TransmissionError;
/** Representation of payload for discover request.
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public class DiscoverRequest extends Payload {
private String filename;

@ -9,6 +9,12 @@ import localException.ProtocolError;
import localException.TransmissionError;
import tools.BytesArrayTools;
/** Representation of payload for discover response.
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public class DiscoverResponse extends Payload {
private List<HostItem> hostList;

@ -7,6 +7,8 @@ import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
import protocolP2P.DiscoverRequest;
import protocolP2P.DiscoverResponse;
import protocolP2P.Register;
import protocolP2P.Unregister;
import localException.ProtocolError;
import localException.InternalError;
import localException.TransmissionError;
@ -36,6 +38,8 @@ public class Payload {
assert requestResponseCode != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class";
assert requestResponseCode != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class";
assert requestResponseCode != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class";
assert requestResponseCode != RequestResponseCode.REGISTER || (this instanceof Register) : "REGISTER must use Register class";
assert requestResponseCode != RequestResponseCode.UNREGISTER || (this instanceof Unregister) : "UNREGISTER must use Unregister class";
this.requestResponseCode = requestResponseCode;
checkRequestResponseCode(); // this can throw InternalError
}
@ -61,6 +65,8 @@ public class Payload {
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.HASH_RESPONSE || (this instanceof HashResponse) : "HASH_RESPONSE must use HashResponse class";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_REQUEST || (this instanceof DiscoverRequest) : "DISCOVER_REQUEST must use DiscoverRequest class";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.DISCOVER_RESPONSE || (this instanceof DiscoverResponse) : "DISCOVER_RESPONSE must use DiscoverResponse class";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.REGISTER || (this instanceof Register) : "REGISTER must use Register class";
assert RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]) != RequestResponseCode.UNREGISTER || (this instanceof Unregister) : "UNREGISTER must use Unregister class";
requestResponseCode = RequestResponseCode.fromCode(packet[RequestResponseCode.RRCODE_POSITION]);
checkRequestResponseCode(); // this can throw InternalError
}
@ -77,6 +83,8 @@ public class Payload {
|| (requestResponseCode == RequestResponseCode.HASH_RESPONSE && !(this instanceof HashResponse))
|| (requestResponseCode == RequestResponseCode.DISCOVER_REQUEST && !(this instanceof DiscoverRequest))
|| (requestResponseCode == RequestResponseCode.DISCOVER_RESPONSE && !(this instanceof DiscoverResponse))
|| (requestResponseCode == RequestResponseCode.REGISTER && !(this instanceof Register))
|| (requestResponseCode == RequestResponseCode.UNREGISTER && !(this instanceof Unregister))
) {
throw new InternalError();
}

@ -289,6 +289,18 @@ public class ProtocolP2PPacketTCP extends ProtocolP2PPacket {
case HASH_RESPONSE:
payload = (Payload) new HashResponse(packet);
break;
case REGISTER:
payload = (Payload) new Register(packet);
break;
case UNREGISTER:
payload = (Payload) new Unregister(packet);
break;
case DISCOVER_REQUEST:
payload = (Payload) new DiscoverRequest(packet);
break;
case DISCOVER_RESPONSE:
payload = (Payload) new DiscoverResponse(packet);
break;
default:
payload = new Payload(packet); // this can throw TransmissionError
break;

@ -287,6 +287,18 @@ public class ProtocolP2PPacketUDP extends ProtocolP2PPacket {
case HASH_RESPONSE:
payload = (Payload) new HashResponse(packet);
break;
case REGISTER:
payload = (Payload) new Register(packet);
break;
case UNREGISTER:
payload = (Payload) new Unregister(packet);
break;
case DISCOVER_REQUEST:
payload = (Payload) new DiscoverRequest(packet);
break;
case DISCOVER_RESPONSE:
payload = (Payload) new DiscoverResponse(packet);
break;
default:
payload = new Payload(packet); // this can throw TransmissionError
break;

@ -0,0 +1,77 @@
package protocolP2P;
import protocolP2P.Payload;
import tools.HostItem;
import tools.BytesArrayTools;
import localException.SizeError;
import localException.InternalError;
import localException.TransmissionError;
import localException.ProtocolError;
/** Representation of payload for unregister.
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public class Register extends Payload {
private HostItem hostItem;
private static final int HOSTNAME_START_POSITION = PAYLOAD_START_POSITION + 2;
/** Constructor with hostItem (typically used by client)
* @param hostItem Host you want to register.
* @throws InternalError
*/
public Register(HostItem hostItem) throws InternalError {
super(RequestResponseCode.REGISTER);
this.hostItem = hostItem;
}
/** Constructor (typically used by server) with a byte[] parameter containing the Packet received.
* @param packet the full Packet received
* @throws SizeError
* @throws InternalError
* @throws ProtocolError
* @throws TransmissionError
*/
protected Register(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError {
super(packet);
int size = getPayloadSize(packet);
int port = BytesArrayTools.readInt16Bits(packet, PAYLOAD_START_POSITION);
String hostname = BytesArrayTools.readString(packet, HOSTNAME_START_POSITION, size - HOSTNAME_START_POSITION + PAYLOAD_START_POSITION);
hostItem = new HostItem(hostname, port);
}
/** Returns a byte[] containing Packet with padding.
* This Packet is still incomplete and should not be send directly.
* ProtocolP2PPacket will use this method to generate the complete Packet.
* @return Packet with padding
* @throws InternalError
*/
protected byte[] toPacket() throws InternalError {
String hostname = hostItem.getHostname();
// compute total size
int size = HOSTNAME_START_POSITION + hostname.length();
byte[] packet = new byte[size + 1]; // java initialize all to zero
// set request/response code
packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
// set Payload size
setPayloadSize(size - PAYLOAD_START_POSITION, packet);
// write port to Packet
try {
BytesArrayTools.write16Bits(packet, PAYLOAD_START_POSITION, hostItem.getPort());
} catch (SizeError e) {
throw new InternalError();
}
// write hostname to Packet
BytesArrayTools.write(packet, hostname, HOSTNAME_START_POSITION);
return packet;
}
/** HostItem getter.
* @return hostItem
*/
public HostItem getHostItem() {
return hostItem;
}
}

@ -0,0 +1,77 @@
package protocolP2P;
import protocolP2P.Payload;
import tools.HostItem;
import tools.BytesArrayTools;
import localException.SizeError;
import localException.InternalError;
import localException.TransmissionError;
import localException.ProtocolError;
/** Representation of payload for unregister.
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public class Unregister extends Payload {
private HostItem hostItem;
private static final int HOSTNAME_START_POSITION = PAYLOAD_START_POSITION + 2;
/** Constructor with hostItem (typically used by client)
* @param hostItem Host you want to register.
* @throws InternalError
*/
public Unregister(HostItem hostItem) throws InternalError {
super(RequestResponseCode.UNREGISTER);
this.hostItem = hostItem;
}
/** Constructor (typically used by server) with a byte[] parameter containing the Packet received.
* @param packet the full Packet received
* @throws SizeError
* @throws InternalError
* @throws ProtocolError
* @throws TransmissionError
*/
protected Unregister(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError {
super(packet);
int size = getPayloadSize(packet);
int port = BytesArrayTools.readInt16Bits(packet, PAYLOAD_START_POSITION);
String hostname = BytesArrayTools.readString(packet, HOSTNAME_START_POSITION, size - HOSTNAME_START_POSITION + PAYLOAD_START_POSITION);
hostItem = new HostItem(hostname, port);
}
/** Returns a byte[] containing Packet with padding.
* This Packet is still incomplete and should not be send directly.
* ProtocolP2PPacket will use this method to generate the complete Packet.
* @return Packet with padding
* @throws InternalError
*/
protected byte[] toPacket() throws InternalError {
String hostname = hostItem.getHostname();
// compute total size
int size = HOSTNAME_START_POSITION + hostname.length();
byte[] packet = new byte[size + 1]; // java initialize all to zero
// set request/response code
packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
// set Payload size
setPayloadSize(size - PAYLOAD_START_POSITION, packet);
// write port to Packet
try {
BytesArrayTools.write16Bits(packet, PAYLOAD_START_POSITION, hostItem.getPort());
} catch (SizeError e) {
throw new InternalError();
}
// write hostname to Packet
BytesArrayTools.write(packet, hostname, HOSTNAME_START_POSITION);
return packet;
}
/** HostItem getter.
* @return hostItem
*/
public HostItem getHostItem() {
return hostItem;
}
}

@ -38,6 +38,8 @@ import java.util.Map;
import protocolP2P.HashAlgorithm;
import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
import protocolP2P.Register;
import protocolP2P.Unregister;
/** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for TCP.
@ -82,12 +84,7 @@ public class ServerManagementTCP implements Runnable {
*/
public void run() {
logger.writeTCP("Server sucessfully started", LogLevel.Info);
try {
registerTracker();
} catch (Exception e) {
logger.writeTCP(e, LogLevel.Error);
System.exit(-4);
}
(new Thread(new TrackerRegisterer())).start();
do {
try {
Socket s = socket.accept();
@ -341,20 +338,34 @@ public class ServerManagementTCP implements Runnable {
}
}
/** Register server on tracker
* @throws InternalError
* @throws IOException
* @throws SocketClosed
*/
public void registerTracker() throws InternalError, IOException, SocketClosed {
logger.writeTCP("Unregistering from tracker", LogLevel.Info);
ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.UNREGISTER));
p.sendRequest((Object)tracker.getTCPSocket());
logger.writeTCP("Registering into tracker", LogLevel.Info);
p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.REGISTER));
p.sendRequest((Object)tracker.getTCPSocket());
logger.writeTCP("Registering completed", LogLevel.Debug);
tracker.closeTCPSocket();
/** Private runnable class allowing to initialize tracker while initializing server. */
private class TrackerRegisterer implements Runnable {
/** Runnable implementation */
public void run() {
try {
registerTracker();
} catch (Exception e) {
logger.writeTCP(e, LogLevel.Error);
System.exit(-4);
}
}
/** Register server on tracker
* @throws InternalError
* @throws IOException
* @throws SocketClosed
*/
private void registerTracker() throws InternalError, IOException, SocketClosed {
HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), TCPPort);
logger.writeTCP("Unregistering from tracker", LogLevel.Info);
ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Unregister(host));
p.sendRequest((Object)tracker.getTCPSocket());
logger.writeTCP("Registering into tracker", LogLevel.Info);
p = (ProtocolP2PPacket)new ProtocolP2PPacketTCP((Payload)new Register(host));
p.sendRequest((Object)tracker.getTCPSocket());
logger.writeTCP("Registering completed", LogLevel.Debug);
tracker.closeTCPSocket();
}
}
}

@ -37,6 +37,8 @@ import protocolP2P.HashAlgorithm;
import protocolP2P.HashRequest;
import protocolP2P.HashResponse;
import tools.HostItem;
import protocolP2P.Register;
import protocolP2P.Unregister;
/** Implementation of P2P-JAVA-PROJECT VERSION 1.0 protocol for UDP.
* @author Louis Royer
@ -77,12 +79,7 @@ public class ServerManagementUDP implements Runnable {
*/
public void run() {
logger.writeUDP("Server sucessfully started", LogLevel.Info);
try {
registerTracker();
} catch (Exception e) {
logger.writeUDP(e, LogLevel.Error);
System.exit(-4);
}
(new Thread(new TrackerRegisterer())).start();
while(true) {
try {
ProtocolP2PPacketUDP pd = new ProtocolP2PPacketUDP((Object)socket);
@ -278,19 +275,33 @@ public class ServerManagementUDP implements Runnable {
}
}
/** Register server on tracker
* @throws InternalError
* @throws IOException
* @throws SocketClosed
*/
public void registerTracker() throws InternalError, IOException, SocketClosed {
logger.writeUDP("Unregistering from tracker", LogLevel.Info);
ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.UNREGISTER));
p.sendRequest((Object)tracker.getUDPSocket());
logger.writeUDP("Registering into tracker", LogLevel.Info);
p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.REGISTER));
p.sendRequest((Object)tracker.getUDPSocket());
tracker.closeUDPSocket();
logger.writeUDP("Registering completed", LogLevel.Debug);
/** Private runnable class allowing to initialize tracker while initializing server. */
private class TrackerRegisterer implements Runnable {
/** Runnable implementation */
public void run() {
try {
registerTracker();
} catch (Exception e) {
logger.writeUDP(e, LogLevel.Error);
System.exit(-4);
}
}
/** Register server on tracker
* @throws InternalError
* @throws IOException
* @throws SocketClosed
*/
private void registerTracker() throws InternalError, IOException, SocketClosed {
HostItem host = new HostItem(InetAddress.getLocalHost().getCanonicalHostName(), UDPPort);
logger.writeUDP("Unregistering from tracker", LogLevel.Info);
ProtocolP2PPacket p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Unregister(host));
p.sendRequest((Object)tracker.getUDPSocket());
logger.writeUDP("Registering into tracker", LogLevel.Info);
p = (ProtocolP2PPacket)new ProtocolP2PPacketUDP((Payload)new Register(host));
p.sendRequest((Object)tracker.getUDPSocket());
logger.writeUDP("Registering completed", LogLevel.Debug);
tracker.closeUDPSocket();
}
}
}

@ -8,6 +8,8 @@ import protocolP2P.ProtocolP2PPacketTCP;
import protocolP2P.ProtocolP2PPacket;
import protocolP2P.RequestResponseCode;
import protocolP2P.Payload;
import protocolP2P.Register;
import protocolP2P.Unregister;
import tools.HostItem;
import java.util.ArrayList;
import java.util.List;
@ -179,8 +181,13 @@ public class TrackerManagementTCP implements Runnable {
* @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 = pd.getHostItem();
HostItem host = ((Register)p).getHostItem();
if (!hostList.contains(host)) {
hostList.add(pd.getHostItem());
}
@ -188,8 +195,8 @@ public class TrackerManagementTCP implements Runnable {
try {
ProtocolP2PPacket pLReq = (ProtocolP2PPacket) new ProtocolP2PPacketTCP(new Payload(RequestResponseCode.LIST_REQUEST));
pLReq.sendRequest((Object)host.getTCPSocket());
logger.writeTCP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action);
handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse());
logger.writeTCP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action);
handleListResponse((ProtocolP2PPacketTCP)pLReq.receiveResponse(), host);
host.closeTCPSocket();
} catch (Exception e) {
// remove from list because list request could not be send
@ -204,8 +211,14 @@ public class TrackerManagementTCP implements Runnable {
* @throws InternalError
*/
private void handleUnregister(ProtocolP2PPacketTCP pd) throws InternalError {
HostItem host = pd.getHostItem();
logger.writeTCP("Received UNREGISTER. Removing host " + host, LogLevel.Action);
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);
@ -239,30 +252,25 @@ public class TrackerManagementTCP implements Runnable {
* @param pd ProtocolP2PPacketTCP response
* @throws InternalError
*/
private void handleListResponse(ProtocolP2PPacketTCP pd) throws InternalError {
HostItem host = pd.getHostItem();
if (!hostList.contains(host)) {
logger.writeTCP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action);
private void handleListResponse(ProtocolP2PPacketTCP pd, HostItem host) throws InternalError {
logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action);
Payload p = pd.getPayload();
assert p instanceof FileList: "payload must be an instance of FileList";
if (!(p instanceof FileList)) {
throw new InternalError();
} else {
logger.writeTCP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action);
Payload p = pd.getPayload();
assert p instanceof FileList: "payload must be an instance of FileList";
if (!(p instanceof FileList)) {
sendInternalError(pd);
} else {
String[] f = ((FileList)p).getFileList();
for (String file: f) {
List<HostItem> h = fileList.get(file);
if (h != null) {
if (!h.contains(host)) {
h.add(host);
}
} else {
List<HostItem> emptyH = new ArrayList<>();
emptyH.add(host);
fileList.put(file, emptyH);
}
}
String[] f = ((FileList)p).getFileList();
for (String file: f) {
List<HostItem> h = fileList.get(file);
if (h != null) {
if (!h.contains(host)) {
h.add(host);
}
} else {
List<HostItem> emptyH = new ArrayList<>();
emptyH.add(host);
fileList.put(file, emptyH);
}
}
}
}

@ -6,6 +6,8 @@ import protocolP2P.ProtocolP2PPacketUDP;
import protocolP2P.ProtocolP2PPacket;
import protocolP2P.RequestResponseCode;
import protocolP2P.Payload;
import protocolP2P.Register;
import protocolP2P.Unregister;
import tools.HostItem;
import java.util.ArrayList;
import java.util.List;
@ -131,8 +133,14 @@ public class TrackerManagementUDP implements Runnable {
* @throws InternalError
*/
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 = pd.getHostItem();
HostItem host = ((Register)p).getHostItem();
if (!hostList.contains(host)) {
hostList.add(pd.getHostItem());
}
@ -140,8 +148,8 @@ public class TrackerManagementUDP implements Runnable {
try {
ProtocolP2PPacket pLReq =(ProtocolP2PPacket)new ProtocolP2PPacketUDP(new Payload(RequestResponseCode.LIST_REQUEST));
pLReq.sendRequest((Object)host.getUDPSocket());
logger.writeUDP("Received REGISTER. Adding host " + host + " to list. Sending List request", LogLevel.Action);
handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse());
logger.writeUDP("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action);
handleListResponse((ProtocolP2PPacketUDP)pLReq.receiveResponse(), host);
host.closeUDPSocket();
} catch (Exception e) {
// remove from list because list request could not be send
@ -156,8 +164,14 @@ public class TrackerManagementUDP implements Runnable {
* @throws InternalError
*/
private void handleUnregister(ProtocolP2PPacketUDP pd) throws InternalError {
HostItem host = pd.getHostItem();
logger.writeUDP("Received UNREGISTER. Removing host " + host, LogLevel.Action);
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);
@ -191,30 +205,25 @@ public class TrackerManagementUDP implements Runnable {
* @param pd ProtocolP2PPacketUDP response
* @throws InternalError
*/
private void handleListResponse(ProtocolP2PPacketUDP pd) throws InternalError {
HostItem host = pd.getHostItem();
if (!hostList.contains(host)) {
logger.writeUDP("Received LIST RESPONSE from host " + host + " but it is not registered.", LogLevel.Action);
private void handleListResponse(ProtocolP2PPacketUDP pd, HostItem host) throws InternalError {
logger.writeUDP("Received LIST RESPONSE from host " + host, LogLevel.Action);
Payload p = pd.getPayload();
assert p instanceof FileList: "payload must be an instance of FileList";
if (!(p instanceof FileList)) {
throw new InternalError();
} else {
logger.writeUDP("Received LIST RESPONSE from host " + host + ": registered host.", LogLevel.Action);
Payload p = pd.getPayload();
assert p instanceof FileList: "payload must be an instance of FileList";
if (!(p instanceof FileList)) {
sendInternalError(pd);
} else {
String[] f = ((FileList)p).getFileList();
for (String file: f) {
List<HostItem> h = fileList.get(file);
if (h != null) {
if (!h.contains(host)) {
h.add(host);
}
} else {
List<HostItem> emptyH = new ArrayList<>();
emptyH.add(host);
fileList.put(file, emptyH);
}
}
String[] f = ((FileList)p).getFileList();
for (String file: f) {
List<HostItem> h = fileList.get(file);
if (h != null) {
if (!h.contains(host)) {
h.add(host);
}
} else {
List<HostItem> emptyH = new ArrayList<>();
emptyH.add(host);
fileList.put(file, emptyH);
}
}
}
}

Loading…
Cancel
Save