diff --git a/week3_TinsaeGhilay/Task 2/README.md b/week3_TinsaeGhilay/Task 2/README.md index c6cc28c..d18472e 100644 --- a/week3_TinsaeGhilay/Task 2/README.md +++ b/week3_TinsaeGhilay/Task 2/README.md @@ -22,4 +22,117 @@ 3. And finaly we run the client as such ```bash java -cp "out:lib/*" client.Client - ``` \ No newline at end of file + ``` + + + ### inspecting packets using wireshark. + *** + #### Normal functions + *** + + I installed wireshark-cli and run + ```bash + sudo tshark -i lo -f "tcp port 8080" -z follow,tcp,ascii,0 + ``` + In Client program the interaction looked like this + ``` + Enter an integer: 4 + Enter an integer: 6 + The sum is: 10 + ``` + And the output of wireshark was as follows + + ```xml + POST /RPC2 HTTP/1.1 + Content-Type: text/xml + User-Agent: Apache XML RPC 3.0 (Sun HTTP Transport) + Cache-Control: no-cache + Pragma: no-cache + Host: localhost:8080 + Accept: */* + Connection: keep-alive + Content-Length: 195 + + + + sample.sum + + + 4 + + + 6 + + + + + HTTP/1.1 200 OK + Server: Apache XML-RPC 1.0 + Connection: close + Content-Type: text/xml + Content-Length: 129 + + + + + + 10 + + + + ``` + I believe this is the expected result. + + *** + #### Intentional error + I changed the messge call string to `sample.add` instead of the correct `sample.sum` and run the program. obviously it threw an exception. the http response from wireguard was as follows + ```xml + POST /RPC2 HTTP/1.1 + Content-Type: text/xml + User-Agent: Apache XML RPC 3.0 (Sun HTTP Transport) + Cache-Control: no-cache + Pragma: no-cache + Host: localhost:8080 + Accept: */* + Connection: keep-alive + Content-Length: 196 + + + + sample.add + + + 23 + + + 4 + + + + + HTTP/1.1 200 OK + Server: Apache XML-RPC 1.0 + Connection: close + Content-Type: text/xml + Content-Length: 265 + + + + + + + + faultCode + 0 + + + faultString + No such handler: sample.add + + + + + + ``` + Again the expected results. I only tested it in one machine. so time will be done may be another time. + diff --git a/week3_TinsaeGhilay/Task 2/out/client/Client.class b/week3_TinsaeGhilay/Task 2/out/client/Client.class index b6f4f89..51180a4 100644 Binary files a/week3_TinsaeGhilay/Task 2/out/client/Client.class and b/week3_TinsaeGhilay/Task 2/out/client/Client.class differ diff --git a/week3_TinsaeGhilay/Task 2/out/server/Server.class b/week3_TinsaeGhilay/Task 2/out/server/Server.class index e23b68b..d9a4001 100644 Binary files a/week3_TinsaeGhilay/Task 2/out/server/Server.class and b/week3_TinsaeGhilay/Task 2/out/server/Server.class differ diff --git a/week3_TinsaeGhilay/Task 2/src/client/Client.java b/week3_TinsaeGhilay/Task 2/src/client/Client.java index b72dcdd..f76540b 100644 --- a/week3_TinsaeGhilay/Task 2/src/client/Client.java +++ b/week3_TinsaeGhilay/Task 2/src/client/Client.java @@ -4,6 +4,7 @@ package client; import java.util.Vector; import java.util.Scanner; import java.net.URL; +import java.net.URI; /** * Client class for XML-RPC communication @@ -33,16 +34,11 @@ public class Client { // URL can be any valid URL. the default port for XML-RPC is 80 // but here we use 8080 since 80 may need root privileges XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); - config.setServerURL(URI.create("http://localhost:8080/RPC2").toURL()); + // config.setServerURL(new URL("http://localhost:8080/RPC2")); + config.setServerURL(new URI("http://localhost:8080/RPC2").toURL()); XmlRpcClient client = new XmlRpcClient(); client.setConfig(config); - // Logging of XML-RPC messages between server and client - XmlRpcCommonsTransportFactory factory = new XmlRpcCommonsTransportFactory(client); - // enable logging - factory.setEnableLogging(true); - client.setTransportFactory(factory); - while (true) { // create parameters to be sent to server method in a vector // and populate it @@ -56,7 +52,7 @@ public class Client { // make the remote method call // the result of the remot call must be an Object // and be casted to the appropriate type - Object result = client.execute("sample.sum", params); + Object result = client.execute("sample.add", params); // process the result int sum = ((Integer) result).intValue(); System.out.println("The sum is: " + sum); diff --git a/week3_TinsaeGhilay/Task 2/src/server/Server.java b/week3_TinsaeGhilay/Task 2/src/server/Server.java index 6f61774..f5b3423 100644 --- a/week3_TinsaeGhilay/Task 2/src/server/Server.java +++ b/week3_TinsaeGhilay/Task 2/src/server/Server.java @@ -14,11 +14,6 @@ import java.net.URL; import org.apache.xmlrpc.server.PropertyHandlerMapping; import org.apache.xmlrpc.server.XmlRpcServer; -// logging imports -import java.util.logging.ConsoleHandler; -import java.util.logging.Level; -import java.util.logging.Logger; - public class Server { private static String TAG = "Server"; @@ -26,6 +21,7 @@ public class Server { public static void main(String[] args) { try { + // start XML-RPC server at port 8080 WebServer server = new WebServer(8080); XmlRpcServer xmlRpcServer = server.getXmlRpcServer(); diff --git a/week3_TinsaeGhilay/Task 5/out/client/Client.class b/week3_TinsaeGhilay/Task 5/out/client/Client.class new file mode 100644 index 0000000..6ecca47 Binary files /dev/null and b/week3_TinsaeGhilay/Task 5/out/client/Client.class differ diff --git a/week3_TinsaeGhilay/Task 5/out/common/ClientInterface.class b/week3_TinsaeGhilay/Task 5/out/common/ClientInterface.class new file mode 100644 index 0000000..64b7d85 Binary files /dev/null and b/week3_TinsaeGhilay/Task 5/out/common/ClientInterface.class differ diff --git a/week3_TinsaeGhilay/Task 5/out/common/ServerInterface.class b/week3_TinsaeGhilay/Task 5/out/common/ServerInterface.class new file mode 100644 index 0000000..2ade5df Binary files /dev/null and b/week3_TinsaeGhilay/Task 5/out/common/ServerInterface.class differ diff --git a/week3_TinsaeGhilay/Task 5/out/server/Server.class b/week3_TinsaeGhilay/Task 5/out/server/Server.class new file mode 100644 index 0000000..c058fa5 Binary files /dev/null and b/week3_TinsaeGhilay/Task 5/out/server/Server.class differ diff --git a/week3_TinsaeGhilay/Task 5/src/client/Client.java b/week3_TinsaeGhilay/Task 5/src/client/Client.java new file mode 100644 index 0000000..f40bff3 --- /dev/null +++ b/week3_TinsaeGhilay/Task 5/src/client/Client.java @@ -0,0 +1,66 @@ +package client; + +import java.rmi.server.UnicastRemoteObject; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.util.Scanner; +import common.ClientInterface; +import common.ServerInterface; + +public class Client extends UnicastRemoteObject implements ClientInterface { + private String clientId; + private ServerInterface server; + + protected Client(String clientId, ServerInterface server) throws RemoteException { + super(); + this.clientId = clientId; + this.server = server; + server.registerClient(clientId, this); + } + + public void sendMessage(String toId, String message) throws RemoteException { + server.sendMessage(clientId, toId, message); + } + + public void blockClient(String blockedId) throws RemoteException { + server.blockClient(clientId, blockedId); + } + + @Override + public void receiveMessage(String fromId, String message) throws RemoteException { + System.out.println("[" + fromId + "]: " + message); + } + + // entry point + public static void main(String[] args) { + try (Scanner scanner = new Scanner(System.in)) { + // get client ID and server info + System.out.print("Enter your client ID: "); + String clientId = scanner.nextLine(); + + // get recipient ID + System.out.print("Enter recipient ID: "); + String toId = scanner.nextLine(); + + Registry registry = LocateRegistry.getRegistry("localhost", 1099); + ServerInterface server = (ServerInterface) registry.lookup("ChatServer"); + + Client client = new Client(clientId, server); + + System.out.print("You can start chatting now. Type your messages below: Type exit to log out\n"); + + while (true) { + String msg = scanner.nextLine(); + if (msg.equalsIgnoreCase("exit")) { + System.out.println("Logging out..."); + break; + } + client.sendMessage(toId, msg); + } + } catch (Exception e) { + System.err.println("Client exception: " + e.getMessage()); + } + } + +} diff --git a/week3_TinsaeGhilay/Task 5/src/common/ClientInterface.java b/week3_TinsaeGhilay/Task 5/src/common/ClientInterface.java new file mode 100644 index 0000000..e7e532d --- /dev/null +++ b/week3_TinsaeGhilay/Task 5/src/common/ClientInterface.java @@ -0,0 +1,16 @@ +package common; + +/** + * ClientInterface interface + * + * @author Tinsae Ghilay + * + */ +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface ClientInterface extends Remote { + + void receiveMessage(String fromId, String message) throws RemoteException; + +} diff --git a/week3_TinsaeGhilay/Task 5/src/common/ServerInterface.java b/week3_TinsaeGhilay/Task 5/src/common/ServerInterface.java new file mode 100644 index 0000000..54a17db --- /dev/null +++ b/week3_TinsaeGhilay/Task 5/src/common/ServerInterface.java @@ -0,0 +1,23 @@ +package common; + +/** + * ClientInterface interface + * + * @author Tinsae Ghilay + * + */ +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.util.List; + +public interface ServerInterface extends Remote { + + void registerClient(String clientId, ClientInterface client) throws RemoteException; + + void sendMessage(String fromId, String toId, String message) throws RemoteException; + + void blockClient(String clientId, String blockedId) throws RemoteException; + + List getOfflineMessages(String clientId) throws RemoteException; + +} diff --git a/week3_TinsaeGhilay/Task 5/src/server/Server.java b/week3_TinsaeGhilay/Task 5/src/server/Server.java new file mode 100644 index 0000000..1a093c3 --- /dev/null +++ b/week3_TinsaeGhilay/Task 5/src/server/Server.java @@ -0,0 +1,69 @@ +package server; + +import java.rmi.server.UnicastRemoteObject; +import java.rmi.RemoteException; +import java.util.*; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +// import interfaces +import common.ClientInterface; +import common.ServerInterface; + +public class Server extends UnicastRemoteObject implements ServerInterface { + private Map onlineClients = new HashMap<>(); + private Map> offlineMessages = new HashMap<>(); + private Map> blockedClients = new HashMap<>(); + + protected Server() throws RemoteException { + super(); + } + + @Override + public synchronized void registerClient(String clientId, ClientInterface client) throws RemoteException { + onlineClients.put(clientId, client); + blockedClients.putIfAbsent(clientId, new HashSet<>()); + + // Send any offline messages + List messages = offlineMessages.getOrDefault(clientId, new ArrayList<>()); + for (String msg : messages) { + client.receiveMessage("Offline", msg); + } + offlineMessages.remove(clientId); + } + + @Override + public synchronized void sendMessage(String fromId, String toId, String message) throws RemoteException { + // Check if recipient blocked sender + Set blocked = blockedClients.getOrDefault(toId, Collections.emptySet()); + if (blocked.contains(fromId)) + return; + + ClientInterface recipient = onlineClients.get(toId); + if (recipient != null) { + recipient.receiveMessage(fromId, message); + } else { + // Store message for offline delivery + offlineMessages.putIfAbsent(toId, new ArrayList<>()); + offlineMessages.get(toId).add(fromId + ": " + message); + } + } + + @Override + public synchronized void blockClient(String clientId, String blockedId) throws RemoteException { + blockedClients.putIfAbsent(clientId, new HashSet<>()); + blockedClients.get(clientId).add(blockedId); + } + + @Override + public synchronized List getOfflineMessages(String clientId) throws RemoteException { + return offlineMessages.getOrDefault(clientId, Collections.emptyList()); + } + + // entry point + public static void main(String[] args) throws Exception { + Server server = new Server(); + Registry registry = LocateRegistry.createRegistry(1099); + registry.rebind("ChatServer", server); + System.out.println("Chat server running..."); + } +}