From 01bd4ba693bc89b1eb136549436d46d1ec828aee Mon Sep 17 00:00:00 2001 From: Tinsae Date: Mon, 22 Dec 2025 00:26:19 +0100 Subject: [PATCH] task 5 started. --- week3_TinsaeGhilay/Task 2/README.md | 115 +++++++++++++++++- .../Task 2/out/client/Client.class | Bin 2547 -> 2587 bytes .../Task 2/out/server/Server.class | Bin 2003 -> 2003 bytes .../Task 2/src/client/Client.java | 12 +- .../Task 2/src/server/Server.java | 6 +- .../Task 5/out/client/Client.class | Bin 0 -> 2884 bytes .../Task 5/out/common/ClientInterface.class | Bin 0 -> 261 bytes .../Task 5/out/common/ServerInterface.class | Bin 0 -> 590 bytes .../Task 5/out/server/Server.class | Bin 0 -> 3360 bytes .../Task 5/src/client/Client.java | 66 ++++++++++ .../Task 5/src/common/ClientInterface.java | 16 +++ .../Task 5/src/common/ServerInterface.java | 23 ++++ .../Task 5/src/server/Server.java | 69 +++++++++++ 13 files changed, 293 insertions(+), 14 deletions(-) create mode 100644 week3_TinsaeGhilay/Task 5/out/client/Client.class create mode 100644 week3_TinsaeGhilay/Task 5/out/common/ClientInterface.class create mode 100644 week3_TinsaeGhilay/Task 5/out/common/ServerInterface.class create mode 100644 week3_TinsaeGhilay/Task 5/out/server/Server.class create mode 100644 week3_TinsaeGhilay/Task 5/src/client/Client.java create mode 100644 week3_TinsaeGhilay/Task 5/src/common/ClientInterface.java create mode 100644 week3_TinsaeGhilay/Task 5/src/common/ServerInterface.java create mode 100644 week3_TinsaeGhilay/Task 5/src/server/Server.java 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 b6f4f8978f3c8455122a531b96555e74dc8003ed..51180a4bad43b4f2e93fc3cc3ea65c6fddf3914a 100644 GIT binary patch delta 1200 zcmY*Y-%}e^6#j0K&2E<4(g~%SVN8=Yg+LNgrO*f6Iy!cX_Svzz_eeuOt^~LeUzo9QaIK;D?Cue8wJ?FdU?D@`j&wbo- zZ?F36&i0Q0hVk{L`k0Mw?wpLZ;wcV4_A^LEar#_}VNbX-wWM9q;sxD^6EdK}iy+4V z928^h5IZDFtZP>YP8A`9IXclLYHYYYN~w0z%htt#T`e-lS2$@MO!ZA^=@rp!74J$aRSea-yKP%7fFs& z7!g5dt9z7V4C7+ZdBA;!V*-<6!Fj|pg>y2_bEL(6XQ*d}p~YsE*9zHqda+!*s$I(K zDrCICaRF{>Jd-b02${x<92fDD_{SNWdHH{N$<>TrGIGU&2P!mgBSBdRySo z@hbW0;SmOJLp;0Od83>wWJ$nzEOO+qB(A%{p1j3%nccpXGSE;LRQ zTo)&#o;_ml#K}Ho3#VI^ZKMDbXKQuyOvJ=&4W5Z;%*0&u zr_>f+*+PcU>^3f2QPr~#;6xMF=$j_lZeX2uV1vGSYS3z8jGhFrpQ1u&K|2njgC;$U z!-%1uWEdhVN#j0=9-6VE$Pl`W1g_DPuTkCxj^j2(eM@g~o&GcgX~%javJ7ukMyO7N z9Wrha0w!a+PP?<=lV?Lxoy4QFTh=m9lGEdA$cZemv@W8Pn)en=l)6k*?xKmdtAjPP zSnxHHgZwvUYxTd{zN6qqV}8h0a!x_P2%2#kdohY9FixCP)Z?VhRv~@%{flNsQSUXb zmva2}#nJ_PtKTE@fDmSD)wu9B%6Z=|^8r4jeK!^Sgd#q&*W37! zHHjO3uH{nRsIt5St0pN@WjuMXEH7U5;MrqNS{CE$p~{2ZRd4x!?|pCk-sd~-7CAp{ zZGI1Q^XZy%R}HRh_1H1WT`H*5^Qy+UPf??PS2cwW9^ruOb*W*W{#kYJt5fWlNuEzO zFJ-1@o5%dg%zWCRHn3}?$s+EupJv?_I$Y2~t3{j30S@X*p$@y2LoN@{p*KUdyALaz z#pK+=tiOM8X)XxTK3|Pj&e+4Pp2|t$=M}e5w5H6kK)kl@-Tfm8Lo=- zy9{t#Ukx9K4l!);sLKicV|cGRss9Y`**)s=I1z<8IXl1TJB%>y@&u=Jxe-@S>f^?q zT~E6_L!Vskr_)iX;EYR>XZ5mCZcp%>i_cm8wNV#27et!YzZhMu&nsfRsf?fYk||Hp z^QZiD!gCm6&Lu^e#9K%U?qIRt@&akyWtJ3WT$X~0tdxH-)1S)NT+mZy+m1^vmpQ92 z0^H_`{>B_tuj-sR(sWgE&*(YdlLmRyiwRHJTo*$nQelL59Ny(Ui}!=n*7TLguj)g6 z!fG%+R#fOeA|?7x#L{0_?#V_%GH+>kP@71G$R-h?FN#(!TnRTDZlZ4F4PO!(978ct zR(N^aRE>*kRM4;V-8}HOjs)plDS*mYSD@uLBXuL&3yP2nvQlr?s#r;{@MT%@o z@mQkN$kLgxO06Gg$?{OUy+Kd0y~!hxWpF*09cs+-*gDbSrg)aIraOZhJhj1TK_@qv z%3IxFB}{>|?y`(^S#n$z4%g(LkaB|x28anQ6RS#!FvO~P~->@qrdhkVJ%inSO|I;oJ hpV#Fy#2dUR{9cjX7LT{`^co)s=7_HOh)+V4{tIjH(FOnj diff --git a/week3_TinsaeGhilay/Task 2/out/server/Server.class b/week3_TinsaeGhilay/Task 2/out/server/Server.class index e23b68bd14bc9a24bf7ffd3fc71f65da4f6a71d8..d9a40013be552d9ae242c1705c713869ae0a936a 100644 GIT binary patch delta 63 zcmcc2f0=&+7rU+$12=;-g8+jJg9L*tg93vbgDQhOgC>w=&Y;L(&!EEK#Gu6B%%IE= R%Ah*goZXR8V{#>X6aWJKgE^3A&!EiU#GuIF%%H>& R%AhjYoZXR8eR3sx6aW)e2)O_N 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 0000000000000000000000000000000000000000..6ecca478d51f8467ee08029357221583a9909ac3 GIT binary patch literal 2884 zcma)8X;%|h7=CUDOb7!=P!zY0bpsMet*uLfT8&au0hJ&YscnbJHH=JV;>?7li`{Lt z`+92sfS>EBSoEB>pZh=hBYI9x>3e4qNKESSK<4J&dEe(UXMH6p5u1>f~jk&kQ@4o|h{>P9@Hsiw(o5%{w* z_TxE*fG)IGBTSoxVmZPv;y57M_#kyq37SKqSM&=W$Vl3k;7V z-J{GFmAS}pX3{DuRCR?K(smV%Ty|+pD5f<(po}jTxL>rq&qqg@=7u$&@ZazS-Bnym zF|3?ILW%HEkP?77l=p_-KDn`S0 z(HokKteBdOnqfIy!j*F8dn0aq#N~;;K=BzYmS7sD5TYX@|$AywKteGuFvt+ff~%Kg3(<) zQ?-ohouG7OTveMLQ45|e3GY)*>WGpP8Dg`>hjigli|_n^aD<9`!m?cAj#?Pu?u?an zLim^(dx~97C@h4V1nJ8wyqsft(cXkl!}tuJOZY;h@k@qXUSM9vbaT#{<)vH9AEiU8 z=30WFKUQYDBYhtSBs)X+twm)8!QtHQr9Ym43XIUg^fDOrY3Xh(w*}p@c_ig2m`$fJSH>N3f4> z!u@m?9l%8#go;BnRTD6fB-}wl-c5K%32_j&NcuK)&AWtn9?dKCkR-e(AueIc`yZ7M zkwnh^5$n_nD9OGAFeHJmKoY-qeH9KyM~#1josclwPUZT5fCKmtAJN)I-)>PMZg|g6 Q@D-hfY5z68#rNp`4>$Mdj{pDw literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..64b7d85b707ebc7d86b3ccf81e5f063b917b4260 GIT binary patch literal 261 zcmX^0Z`VEs1_nn4K6VBsMh3Cu{M_99JbmY!%+$OR&%Bb1RCWdyMh1bb#Ii*F zoW#6zegCAa)Z`L&1~x_pez0g!Zl-=vYHof>DkB45QEGB(W?8ClYH@L5I#57e!v~=? zxTGjEFWnkbL^F($fy=cbIkli9Ge57Goq?N?K?2QixHM2{aDHh~a;jTq4$uY>H23O( l^Z^~m$iNK5tUwPk0zJUazyaiO0(mSznhS_|fNUlPUI1`~Me6_n literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..2ade5dfd6281bd5ee5dcde0035c91a07fcdecbc2 GIT binary patch literal 590 zcma)3!A`M;W;s=;02kjMuF)>CHlNu76crWYFEVf&-U5MZ2!4L4Gj8i~J z3I`6G*?Bu}-t4@e->+`~cj&lq1UfQH(@gsznJJkkZOM!xNiHe^&2co1{3Oz`KNyZl zS{Hi)jTvfE<-bsxSrVulidD|c`$Unp0+$!TiW*v@bleXXLi3uXP`~>s;5~dw`mid~ zxr>^>X-Q)FEKtiyzdci)M=>j3ZxULUUPB7e+AzuF`~S%2TXiaUt(fd!G)k1F#T>c7 z*#>%dzJ!TYi68KO`U2HZ#X7PR!?X9cpxmtQ@s`_oVKy<69#z79+9m6*ir=zN0y}(m p+3N~>>0+O=YLRjD7&*XU38|w|LYg>&vtpsed{s0^ip{D=< literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c058fa583d21f6c08be7a15d3fe5464eda19dd13 GIT binary patch literal 3360 zcmb7G`BxiN6#iZk7)Ykjf?cqcVr?l9Ant8Ri&AP^Y@k{y)w&MJ0|t_rI5WZGTK9e5 z>b~o*>TxOd9FITwgMWp8hsW)EGZT`O)N}j+GIQtM`@Zkq@80)*`}?P#0gT|QI3kE@ zi0NoRqrheJ#-fpO3TDcc&Z2Zuw^(M@aJ^%)V0-fD^t{Y^0*!l3%k+i?qCLG+8kz*w z`Fv2sqZW@#*EMFPtG->NW4-#;GM%@x3o;i5N?;>4Y3R^#F*b9TnxF(-ERny$B$LpZEqOvjBlBCx)anNd5Rr_4>; zq9mJSq3A8KzN~pU4StGgN^2Oekr!CN%U^$fpDYLt87>{KZ?T%@FPQpfEIThz$q6xNd} z4|nOf8}|q_`(%~MD3uzv%9f6^<)U$9k<%b`%wSfa%g>t{7>=CfB4;U;v58q83tw5@ ztRrg-TYJXBg4FnxJ&P~h8GNq1Qw9jP|#t)7PxrzmStC82GgdMJ5L5RSyGz@ z^DNyv)r@=LXmE9SDAfvj$@OG`nX=WmSRbU*v{N@x=N8c@9Oer>i1uIm@RuKSpHw$l?G8_s1twKk96?=L}J5SFi>pN&XHGZhC_d%RG5~| zabr49OZEb5D9kc7gc} z_fBw{=fWdMU{AehKANhLSa)*qc<|4xGOji?_G=F~f$ep|S5JArDbG8}%F3y#!UfC4 z0bk&FQisRwtL37^_hwnQKA)<@#wYEPla&WeRggp=%t6JREwtaZJ=b%L;<)tY?3~+# zce#@o>JqJuct4I0@S%o})R_C294qNEtwno5rUC}R2A;1_Cl#xC)riZY8;O*6=j{})tRVsdW0cHjeLHRr!QMaAG0haFvE4FtKl<&9jiFi zgR0>RfzJP4%6S&>;*}!7o0`DGi1L@WDL$X(aS_3z{NoL2<^3_f^H#L-{x}*DQ@1_x%XbcMjTZKce}2#4C?$E068paHYVL{J()Qz@1`P!{{x%TeV^b+VK>v zF|K)<7@x&+;V$3O*2pjOecvIT>|e%)C{FOXJ$VjWxMSxswg#59v}~hg`!aS!@e6t; z2A0t$Fcj;EEn`sN9c)ogR||gJJ=Du(8d87oB38}h1-uwCIU6!rQ0V*5 z;$Vm~qX2U6i3kzKzEM0$^H_u^_YF04H2jLzj)o+;D5OX!r2Q*Q%iPNzJ;{Nea0{@E z+iIwEqnSW=FzwwWu#*IOF@Qea=8_o3AnzF|%;O55PAj5+qEkcWPi)n&FImIqC0_P} z`X3^nD1+`)d{$MXos4`A8A7`w#1aUg#do`gSgs|ST{Yof#w+})taXFVtTy4ZH^e{qxcrZ zw#6TC>U@b_&+?B@ocme+QI`6^%0_Q6;9LGyZ{rMqn+W7R{=I`w_!j5Wr}!LSqT^qH Cy>XEM literal 0 HcmV?d00001 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..."); + } +}