Skip to content

Commit 427ba72

Browse files
authored
Merge pull request #44 from omjadas/ValidateExpectedResponses
Validate expected responses
2 parents 4f32128 + d412cd0 commit 427ba72

19 files changed

+360
-146
lines changed

src/main/java/unimelb/bitbox/Client.java

+96-28
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
import java.net.ConnectException;
77
import java.net.Socket;
88
import java.net.SocketException;
9-
import java.util.ArrayList;
9+
import java.util.Collections;
10+
import java.util.HashMap;
1011
import java.util.HashSet;
12+
import java.util.Set;
13+
import java.util.concurrent.ConcurrentHashMap;
1114
import java.util.logging.Logger;
1215

1316
import unimelb.bitbox.actions.Action;
@@ -37,22 +40,45 @@
3740

3841
public class Client extends Thread {
3942
private static Logger log = Logger.getLogger(Client.class.getName());
40-
public static HashSet<Client> establishedClients = new HashSet<Client>();
43+
public static Set<Client> establishedClients = Collections.newSetFromMap(new ConcurrentHashMap<Client, Boolean>());
4144
private Socket socket;
4245
private String host;
4346
private long port;
4447
private FileSystemManager fileSystemManager;
4548
private boolean isIncomingConnection = false;
49+
50+
private Set<Action> waitingActions;
4651

47-
public Client(String host, int port, FileSystemManager fileSystemManager) {
52+
public static HashMap<String, String> responseToRequest;
53+
public static HashSet<String> validCommandsBeforeConnectionEstablished;
54+
55+
static {
56+
responseToRequest = new HashMap<>();
57+
58+
responseToRequest.put("FILE_CREATE_RESPONSE", "FILE_CREATE_REQUEST");
59+
responseToRequest.put("FILE_DELETE_RESPONSE", "FILE_DELETE_REQUEST");
60+
responseToRequest.put("FILE_MODIFY_RESPONSE", "FILE_MODIFY_REQUEST");
61+
responseToRequest.put("DIRECTORY_CREATE_RESPONSE", "DIRECTORY_CREATE_REQUEST");
62+
responseToRequest.put("DIRECTORY_DELETE_RESPONSE", "DIRECTORY_DELETE_REQUEST");
63+
responseToRequest.put("FILE_BYTES_RESPONSE", "FILE_BYTES_REQUEST");
64+
65+
validCommandsBeforeConnectionEstablished = new HashSet<>();
66+
67+
validCommandsBeforeConnectionEstablished.add("HANDSHAKE_REQUEST");
68+
validCommandsBeforeConnectionEstablished.add("HANDSHAKE_RESPONSE");
69+
validCommandsBeforeConnectionEstablished.add("CONNECTION_REFUSED");
70+
}
71+
72+
public Client(String host, int port, FileSystemManager fileSystemManager) {
73+
waitingActions = Collections.newSetFromMap(new ConcurrentHashMap<Action, Boolean>());
4874
this.host = host;
4975
this.port = port;
5076
this.fileSystemManager = fileSystemManager;
5177
try {
5278
this.socket = new Socket(host, port);
5379
HandshakeRequest requestAction = new HandshakeRequest(this.socket,
5480
Configuration.getConfigurationValue("advertisedName"),
55-
Long.parseLong(Configuration.getConfigurationValue("port")));
81+
Long.parseLong(Configuration.getConfigurationValue("port")), this);
5682
requestAction.send();
5783
this.start();
5884
} catch (ConnectException e) {
@@ -63,11 +89,12 @@ public Client(String host, int port, FileSystemManager fileSystemManager) {
6389
}
6490

6591
public Client(Socket socket, FileSystemManager fileSystemManager) {
92+
waitingActions = Collections.newSetFromMap(new ConcurrentHashMap<Action, Boolean>());
6693
this.socket = socket;
6794
this.fileSystemManager = fileSystemManager;
6895

6996
if (Client.getNumberIncomingEstablishedConnections() == Peer.maximumIncommingConnections) {
70-
new ConnectionRefused(socket, "connection limit reached").send();
97+
new ConnectionRefused(socket, "connection limit reached", this).send();
7198
return;
7299
}
73100

@@ -130,7 +157,44 @@ public void setPort(long port) {
130157
* @return Boolean indication whether the message is valid
131158
*/
132159
private boolean validateRequest(Document message) {
133-
return SchemaValidator.validateSchema(message);
160+
if (!SchemaValidator.validateSchema(message)) {
161+
return false;
162+
}
163+
164+
String command = message.getString("command");
165+
166+
if (!Client.establishedClients.contains(this)) {
167+
if (!validCommandsBeforeConnectionEstablished.contains(command)) {
168+
return false;
169+
}
170+
171+
if (command == "HANDSHAKE_RESPONSE" || command == "CONNECTION_REFUSED") {
172+
return checkIfExpectingResponse(message);
173+
}
174+
} else {
175+
if (responseToRequest.containsKey(command)) {
176+
return checkIfExpectingResponse(message);
177+
} else if (!responseToRequest.containsValue(command)) {
178+
return false;
179+
}
180+
}
181+
182+
return true;
183+
}
184+
185+
private boolean checkIfExpectingResponse(Document message) {
186+
for (Action action : waitingActions) {
187+
if (action.compare(message)) {
188+
waitingActions.remove(action);
189+
return true;
190+
}
191+
}
192+
193+
return false;
194+
}
195+
196+
public void addToWaitingActions(Action action) {
197+
waitingActions.add(action);
134198
}
135199

136200
/**
@@ -143,17 +207,17 @@ public void processEvent(FileSystemEvent fileSystemEvent) {
143207

144208
if (fileSystemEvent.event == EVENT.FILE_CREATE) {
145209
action = new FileCreateRequest(socket, new FileDescriptor(fileSystemEvent.fileDescriptor),
146-
fileSystemEvent.pathName);
210+
fileSystemEvent.pathName, this);
147211
} else if (fileSystemEvent.event == EVENT.FILE_DELETE) {
148212
action = new FileDeleteRequest(socket, new FileDescriptor(fileSystemEvent.fileDescriptor),
149-
fileSystemEvent.pathName);
213+
fileSystemEvent.pathName, this);
150214
} else if (fileSystemEvent.event == EVENT.FILE_MODIFY) {
151215
action = new FileModifyRequest(socket, new FileDescriptor(fileSystemEvent.fileDescriptor),
152-
fileSystemEvent.pathName);
216+
fileSystemEvent.pathName, this);
153217
} else if (fileSystemEvent.event == EVENT.DIRECTORY_CREATE) {
154-
action = new DirectoryCreateRequest(socket, fileSystemEvent.pathName);
218+
action = new DirectoryCreateRequest(socket, fileSystemEvent.pathName, this);
155219
} else if (fileSystemEvent.event == EVENT.DIRECTORY_DELETE) {
156-
action = new DirectoryDeleteRequest(socket, fileSystemEvent.pathName);
220+
action = new DirectoryDeleteRequest(socket, fileSystemEvent.pathName, this);
157221
}
158222

159223
action.send();
@@ -163,44 +227,44 @@ public void processEvent(FileSystemEvent fileSystemEvent) {
163227
* Return an appropriate action for the received message
164228
*
165229
* @param message The received message
166-
* @return An action corresponding to the revceived message
230+
* @return An action corresponding to the received message
167231
*/
168232
private Action getAction(Document message) {
169233
Action action = null;
170234
String command = message.getString("command");
171235

172236
if (command.equals("INVALID_PROTOCOL")) {
173-
action = new InvalidProtocol(socket, message);
237+
action = new InvalidProtocol(socket, message, this);
174238
} else if (command.equals("CONNECTION_REFUSED")) {
175-
action = new ConnectionRefused(socket, message);
239+
action = new ConnectionRefused(socket, message, this);
176240
} else if (command.equals("HANDSHAKE_REQUEST")) {
177241
action = new HandshakeRequest(socket, message, this);
178242
} else if (command.equals("HANDSHAKE_RESPONSE")) {
179243
action = new HandshakeResponse(socket, message, this);
180244
} else if (command.equals("FILE_CREATE_REQUEST")) {
181-
action = new FileCreateRequest(socket, message);
245+
action = new FileCreateRequest(socket, message, this);
182246
} else if (command.equals("FILE_CREATE_RESPONSE")) {
183-
action = new FileCreateResponse(socket, message);
247+
action = new FileCreateResponse(socket, message, this);
184248
} else if (command.equals("FILE_DELETE_REQUEST")) {
185-
action = new FileDeleteRequest(socket, message);
249+
action = new FileDeleteRequest(socket, message, this);
186250
} else if (command.equals("FILE_DELETE_RESPONSE")) {
187-
action = new FileDeleteResponse(socket, message);
251+
action = new FileDeleteResponse(socket, message, this);
188252
} else if (command.equals("FILE_MODIFY_REQUEST")) {
189-
action = new FileModifyRequest(socket, message);
253+
action = new FileModifyRequest(socket, message, this);
190254
} else if (command.equals("FILE_MODIFY_RESPONSE")) {
191-
action = new FileModifyResponse(socket, message);
255+
action = new FileModifyResponse(socket, message, this);
192256
} else if (command.equals("DIRECTORY_CREATE_REQUEST")) {
193-
action = new DirectoryCreateRequest(socket, message);
257+
action = new DirectoryCreateRequest(socket, message, this);
194258
} else if (command.equals("DIRECTORY_CREATE_RESPONSE")) {
195-
action = new DirectoryCreateResponse(socket, message);
259+
action = new DirectoryCreateResponse(socket, message, this);
196260
} else if (command.equals("DIRECTORY_DELETE_REQUEST")) {
197-
action = new DirectoryDeleteRequest(socket, message);
261+
action = new DirectoryDeleteRequest(socket, message, this);
198262
} else if (command.equals("DIRECTORY_DELETE_RESPONSE")) {
199-
action = new DirectoryDeleteResponse(socket, message);
263+
action = new DirectoryDeleteResponse(socket, message, this);
200264
} else if (command.equals("FILE_BYTES_REQUEST")) {
201-
action = new FileBytesRequest(socket, message);
265+
action = new FileBytesRequest(socket, message, this);
202266
} else if (command.equals("FILE_BYTES_RESPONSE")) {
203-
action = new FileBytesResponse(socket, message);
267+
action = new FileBytesResponse(socket, message, this);
204268
}
205269

206270
return action;
@@ -212,13 +276,17 @@ public void run() {
212276

213277
String inputLine;
214278
while ((inputLine = in.readLine()) != null) {
215-
System.out.println(inputLine);
216-
279+
log.info("Received from " + this.host + ":" + this.port + ": " + inputLine);
280+
281+
217282
Document message = Document.parse(inputLine);
218283

219284
if (validateRequest(message)) {
220285
Action action = getAction(message);
221286
action.execute(fileSystemManager);
287+
} else {
288+
Action invalid = new InvalidProtocol(socket, "Could not validate message:" + message.toJson(), this);
289+
invalid.send();
222290
}
223291
}
224292

src/main/java/unimelb/bitbox/FileDescriptor.java

+4
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,8 @@ public Document toDoc() {
5555
doc.append("fileSize", fileSize);
5656
return doc;
5757
}
58+
59+
public boolean compare(FileDescriptor fd) {
60+
return (fd.md5.equals(this.md5) && fd.lastModified == this.lastModified && fd.fileSize == this.fileSize);
61+
}
5862
}

src/main/java/unimelb/bitbox/actions/Action.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.logging.Logger;
44

5+
import unimelb.bitbox.util.Document;
56
import unimelb.bitbox.util.FileSystemManager;
67

78
public interface Action {
@@ -18,7 +19,7 @@ public interface Action {
1819
* @param action The action to compare against
1920
* @return
2021
*/
21-
public int compare(Action action);
22+
public boolean compare(Document message);
2223

2324
/**
2425
* Send the action to the corresponding client

src/main/java/unimelb/bitbox/actions/ConnectionRefused.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import java.io.OutputStreamWriter;
66
import java.net.Socket;
77
import java.util.ArrayList;
8-
import java.util.logging.Logger;
9-
108
import unimelb.bitbox.Client;
119
import unimelb.bitbox.ClientSearcher;
1210
import unimelb.bitbox.Peer;
@@ -20,13 +18,16 @@ public class ConnectionRefused implements Action {
2018
private static final String command = "CONNECTION_REFUSED";
2119
private String message;
2220
private Document parsedJSON;
21+
private Client client;
2322

24-
public ConnectionRefused(Socket socket, String message) {
23+
public ConnectionRefused(Socket socket, String message, Client client) {
24+
this.client = client;
2525
this.socket = socket;
2626
this.message = message;
2727
}
2828

29-
public ConnectionRefused(Socket socket, Document message) {
29+
public ConnectionRefused(Socket socket, Document message, Client client) {
30+
this.client = client;
3031
this.socket = socket;
3132
this.message = message.getString("message");
3233
this.parsedJSON = message;
@@ -42,7 +43,6 @@ public void execute(FileSystemManager fileSystemManager) {
4243

4344
HostPort clientHostPort = new HostPort(host, (int) port);
4445
ClientSearcher.potentialClients.add(clientHostPort);
45-
System.out.println(ClientSearcher.potentialClients.toString());
4646
synchronized(Peer.getClientSearchLock()) {
4747
Peer.getClientSearchLock().notifyAll();
4848
}
@@ -51,8 +51,8 @@ public void execute(FileSystemManager fileSystemManager) {
5151
}
5252

5353
@Override
54-
public int compare(Action action) {
55-
return 0;
54+
public boolean compare(Document message) {
55+
return true;
5656
}
5757

5858
@Override
@@ -62,6 +62,7 @@ public void send() {
6262
out.write(toJSON());
6363
out.newLine();
6464
out.flush();
65+
log.info("Sent to " + this.client.getHost() + ":" + this.client.getPort() + ": " + toJSON());
6566
try {
6667
Thread.sleep(500);
6768
} catch (InterruptedException e) {}

src/main/java/unimelb/bitbox/actions/DirectoryCreateRequest.java

+19-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.io.IOException;
55
import java.io.OutputStreamWriter;
66
import java.net.Socket;
7+
8+
import unimelb.bitbox.Client;
79
import unimelb.bitbox.util.Document;
810
import unimelb.bitbox.util.FileSystemManager;
911

@@ -12,13 +14,16 @@ public class DirectoryCreateRequest implements Action {
1214
private Socket socket;
1315
private static final String command = "DIRECTORY_CREATE_REQUEST";
1416
private String pathName;
17+
private Client client;
1518

16-
public DirectoryCreateRequest(Socket socket, String pathName) {
19+
public DirectoryCreateRequest(Socket socket, String pathName, Client client) {
20+
this.client = client;
1721
this.socket = socket;
1822
this.pathName = pathName;
1923
}
2024

21-
public DirectoryCreateRequest(Socket socket, Document message) {
25+
public DirectoryCreateRequest(Socket socket, Document message, Client client) {
26+
this.client = client;
2227
this.socket = socket;
2328
this.pathName = message.getString("pathName");
2429
}
@@ -38,13 +43,20 @@ public void execute(FileSystemManager fileSystemManager) {
3843
message = "there was a problem creating the directory";
3944
}
4045

41-
Action response = new DirectoryCreateResponse(socket, pathName, message, status);
46+
Action response = new DirectoryCreateResponse(socket, pathName, message, status, client);
4247
response.send();
4348
}
4449

4550
@Override
46-
public int compare(Action action) {
47-
return 0;
51+
public boolean compare(Document message) {
52+
boolean correctCommand = message.getString("command").equals("DIRECTORY_CREATE_RESPONSE");
53+
if (!correctCommand) {
54+
return false;
55+
}
56+
57+
boolean matchingPath = message.getString("pathName").equals(this.pathName);
58+
59+
return correctCommand && matchingPath;
4860
}
4961

5062
@Override
@@ -54,6 +66,8 @@ public void send() {
5466
out.write(toJSON());
5567
out.newLine();
5668
out.flush();
69+
log.info("Sent to " + this.client.getHost() + ":" + this.client.getPort() + ": " + toJSON());
70+
this.client.addToWaitingActions(this);
5771
} catch (IOException e) {
5872
log.info("Socket was closed while sending message");
5973
}

0 commit comments

Comments
 (0)