From 4a7550e3e9137261c156d3cdedefa64323d2dda3 Mon Sep 17 00:00:00 2001
From: Kim Mundel <kim.mundel@student.reutlingen-university.de>
Date: Fri, 5 May 2023 20:09:59 +0000
Subject: [PATCH] Slight Changes to Protocol

---
 src/main/java/slp/SLPProtocol.java | 323 +++++++++++++++++++++--------
 1 file changed, 232 insertions(+), 91 deletions(-)

diff --git a/src/main/java/slp/SLPProtocol.java b/src/main/java/slp/SLPProtocol.java
index 2592f2d..dce4565 100644
--- a/src/main/java/slp/SLPProtocol.java
+++ b/src/main/java/slp/SLPProtocol.java
@@ -2,120 +2,261 @@ package slp;
 
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Socket;
 import java.net.SocketTimeoutException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.zip.CRC32;
+import java.util.zip.Checksum;
 
-import core.Configuration;
 import core.Msg;
+import core.Configuration;
 import core.Protocol;
 import phy.PhyConfiguration;
+import phy.PhyMsg;
 import phy.PhyProtocol;
 import exceptions.*;
 
+import javax.xml.crypto.Data;
 
 public class SLPProtocol extends Protocol {
-	private static final int SLPTIMEOUT = 2000;
-	private int myID;
-	private final PhyProtocol phy;
-	private final boolean isSwitch;
-	private boolean isRegistered;
-	private boolean useTimeout;
-	// Switches map slp id to virtual link
-	private Map<Integer, PhyConfiguration> systems;
-	PhyConfiguration phyConfig;
-
-	// Constructor
-	public SLPProtocol(int id, boolean isSwitch, PhyProtocol proto) throws IWProtocolException {
-		if(isSwitch == true && id < 5000) {
-			systems = new HashMap<>();
-		} else {
-			if(SLPRegMsg.validateAddress(id)  == false )
-				throw new IllegalAddrException();
-			this.myID = id;
-			this.isRegistered = false;
-		}
-		this.isSwitch = isSwitch;
-		this.phy = proto;
-	}
-	
-	/*
-	 * Enable/disable the use of timeout when reading from socket
-	 */
-	private void enableTimeout() {
-		this.useTimeout = true;
-	}
-	private void disableTimeout() {
-		this.useTimeout = false;
-	}
+    private static final int SLPTIMEOUT = 2000;
+    private int myID;
+    private final PhyProtocol phy;
+    private final boolean isSwitch;
+    private boolean isRegistered;
+    private boolean useTimeout;
+    // Switches map slp id to virtual link
+    private Map<Integer, PhyConfiguration> systems;
+    PhyConfiguration phyConfig;
+
+
+    // Constructor
+    public SLPProtocol(int id, boolean isSwitch, PhyProtocol proto) throws IWProtocolException {
+        if (isSwitch && id < 5000) {
+            systems = new HashMap<>();
+        } else {
+            if (SLPRegMsg.validateAddress(id) == false)
+                throw new IllegalAddrException();
+            this.myID = id;
+            this.isRegistered = false;
+        }
+        this.isSwitch = isSwitch;
+        this.phy = proto;
+    }
+
+    /*
+     * Enable/disable the use of timeout when reading from socket
+     */
+    public void enableTimeout() {
+        this.useTimeout = true;
+    }
+
+    public void disableTimeout() {
+        this.useTimeout = false;
+    }
 	
-	// Register an end systems 
-	public void register(InetAddress rname, int rp) throws IWProtocolException, IOException {
-		// Create registration message object 
-		SLPRegMsg reg = new SLPRegMsg();
-		// Fill registration message fields
-		reg.create(Integer.toString(this.myID));
-		// Create configuration object
-		this.phyConfig = new PhyConfiguration(rname, rp);
-
-		/* -- Remove for task 4 -- */
-		// Send registration request via phy layer
-		phy.send(new String(reg.getDataBytes()), this.phyConfig);
-		SLPMsg in = new SLPMsg();
-		;
-		Msg inBasic;
-		try {
-			// Receive response from phy layer - timeout 2s
-			inBasic = this.phy.receive(2000);
-			// Get data from msg object
-			String sentence = inBasic.getData();
-			// Parse response
-			in = (SLPMsg) in.parse(sentence);
-		} catch (SocketTimeoutException e) {
-			System.out.println("No response received");
-			throw new RegistrationFailedException();
-		}catch (IllegalMsgException e) {
-			System.out.println("Cannot parse response");
-			throw new RegistrationFailedException();
-		}
-		// If any other message than a registration response message was received or
-		// the registration response indicates failure throw exception
-		if (!(in instanceof SLPRegResponseMsg) || (((SLPRegResponseMsg)in).getRegResponse() == false)) {
-			// A registration non-acknowledgement is signaled by throwing an exception
-			throw new RegistrationFailedException();
-		}
-		/* -- End remove for task 4 -- */
-
-		this.isRegistered = true;
+	// Combine setting the Timeouts
+	public void setTimeout(boolean newTimeout){
+		this.useTimeout = newTimeout;
 	}
+
+    // Register an end systems
+    public void register(InetAddress rname, int rp) throws IWProtocolException, IOException {
+
+        /* ------------ CODE FROM TASK 2
+        // Create registration message object
+        SLPRegMsg reg = new SLPRegMsg();
+        // Fill registration message fields
+        reg.create(Integer.toString(this.myID));
+        // Create configuration object
+        this.phyConfig = new PhyConfiguration(rname, rp);
+
+        phy.send(new String(reg.getDataBytes()), this.phyConfig);
+
+        // Subtask 2: Receive response message, parse it, and inform app
+        boolean msgRegResponse;
+
+        // Parse message if error occurs throw RegistrationFailedExceoption
+        try {
+            SLPMsg msg = new SLPMsg();
+            msg = (SLPMsg) msg.parse(phy.receive(SLPTIMEOUT).getData());
+            msgRegResponse = ((SLPRegResponseMsg) msg).getRegResponse();
+        } catch (IllegalMsgException | SocketTimeoutException e) {
+            throw new RegistrationFailedException();
+        }
+
+        // If RegResponse was true conclude register else throw RegistrationFailedExceoption
+        if (msgRegResponse) {
+            this.isRegistered = true;
+        } else {
+            throw new RegistrationFailedException();
+        }
+        return;
+		------------ CODE FROM TASK 2*/
+        
+
+        // Updated registration using timeout
+        SLPRegMsg reg = new SLPRegMsg();
+        // Fill registration message fields
+        reg.create(Integer.toString(this.myID));
+        // Create configuration object
+        this.phyConfig = new PhyConfiguration(rname, rp);
+        // Counter for attempting registration
+        int attempt = 0;
+
+        while (attempt < 3) {
+
+            phy.send(new String(reg.getDataBytes()), this.phyConfig);
+
+            // Receive response message, parse it, and inform app
+            boolean msgRegResponse = false;
+
+            // Parse message if error occurs printStackTrace
+            try {
+                SLPMsg msg = new SLPMsg();
+                msg = (SLPMsg) msg.parse(phy.receive(SLPTIMEOUT).getData());
+                msgRegResponse = ((SLPRegResponseMsg) msg).getRegResponse();
+            } catch (IllegalMsgException | SocketTimeoutException e) {
+                e.printStackTrace();
+            }
+
+            // If RegResponse was true conclude register else increase number of attempts
+            if (msgRegResponse) {
+                this.isRegistered = true;
+                return;
+            }
+            attempt++;
+        }
+        throw new RegistrationFailedException();
+    }
 	
-	// Create SLPDataMsg object (subtask 3.3) and send
+    // Create SLPDataMsg object (subtask 3.3) and send
 	// Subtask 2.1
-	@Override
-	public void send(String s, Configuration config) throws IOException, IWProtocolException {
-		
+    @Override
+    public void send(String sentence, Configuration config) throws IOException, IWProtocolException {
 
-	}
+        // Send the message, if the Client has been registered
+        if (isRegistered) {
+            SLPDataMsg msg = new SLPDataMsg((SLPConfiguration) config, myID);
+            msg.create(sentence);
+            phy.send(new String(msg.getDataBytes()), phyConfig);
+        } else {
+            throw new RegistrationFailedException();
+        }
+    }
 
-	// Receive message from underlying protocol, parse and process
+    // Receive message from underlying protocol, parse and process
 	// Subtask 2.2
-	@Override
-	public Msg receive() throws IOException, IWProtocolException {
-		SLPMsg in = null;
+    @Override
+    public Msg receive() throws IOException, IWProtocolException {
 
+        SLPMsg respMsg;
+        Boolean isRunning = true;
+        // Check if the Client has been registered
+        if (isRegistered || isSwitch) {
+            while (isRunning) {
+                try {
+                    Msg phyMsg;
+                    if(useTimeout){
+                        phyMsg = phy.receive(SLPTIMEOUT);
+                    } else {
+                        phyMsg = phy.receive();
+                    }
+					
+                    // Receive message and parse it
+                    respMsg = new SLPMsg();
+                    respMsg = (SLPMsg) respMsg.parse(phyMsg.getData());
 
-		return in;
-	}
+                    /* Is the parsed message a registration message?
+					   If it is and it's a switch, register the Client. */
+                    if (respMsg instanceof SLPRegMsg) {
+                        if (!isSwitch) {
+                            System.out.println("Client ist already registered -> Discard Message");
+                            throw new IllegalMsgException();
+                        } else {
+                            registration((SLPRegMsg) respMsg, phyMsg.getConfiguration());
+                            return null;
+                        }
+                    }
+                    /* Was the message meant to be sent to client?
+					   Drop it silently, if not. */
+                    if (!isSwitch && ((SLPDataMsg) respMsg).getReceiverId() != this.myID) {
+                        System.out.println(((SLPDataMsg) respMsg).getReceiverId() + " is someone else. I am " +this.myID);
+                        throw new IllegalReceiveException();
+                    }
 
+                    return respMsg;
 
-	public void storeAndForward() throws IOException {
-		while (true) {
-			forward();
-		}
-	}
+                } catch (BadChecksumException | IllegalMsgException | RegistrationFailedException |
+                         IllegalReceiveException e) {
+                    e.printStackTrace();
+                } catch (SocketTimeoutException e) {
+                    isRunning = false;
+                }
+            }
+            throw new SocketTimeoutException();
+        } else {
+            throw new RegistrationFailedException();
+        }
 
-	public void forward() throws IOException {
-		// Subtask 3.2
 
-	}
+    }
+
+    public void storeAndForward() throws IOException, IWProtocolException {
+        while (true) {
+            forward();
+        }
+    }
+
+    public void forward() throws IWProtocolException, IOException {
+
+        // Receive a message and if it was a registration message dont foward it
+        SLPMsg datMsg = (SLPMsg) this.receive();
+        if (datMsg == null) {
+            return;
+        }
+
+        // Get the PhyConfig of the receiver and sender by their IDs
+        PhyConfiguration receiverConfig = this.systems.get(((SLPDataMsg) datMsg).getReceiverId());
+        PhyConfiguration senderConfig = this.systems.get(((SLPDataMsg) datMsg).getSenderID());
+
+        // In case one of the clients isn't registered dont send the message else forwad it to the receiver
+        if (receiverConfig == null || senderConfig == null) {
+            System.out.println("Discarding message some clients not registered");
+        } else {
+            System.out.println("Forwarding message: '" + datMsg.getData() + "' with sender: " + ((SLPDataMsg) datMsg).getSenderID() + " and receiver: " + ((SLPDataMsg) datMsg).getReceiverId());
+            phy.send(((SLPDataMsg) datMsg).getreceivedMessage(), receiverConfig);
+        }
+
+
+    }
+
+    // Registration Method which is used by the switch to register new Clients to its Hashmap
+    private void registration(SLPRegMsg regMsg, Configuration config) throws IWProtocolException, IOException {
+        try {
+
+            SLPRegResponseMsg regResponseMsg = new SLPRegResponseMsg();
+
+            // Check whether Client is already registered to the ID if not put him into the Hashmap with his PhyConfig
+            if (this.systems.containsKey(regMsg.getSlpId())) {
+                regResponseMsg.setRegResponse(false);
+            } else {
+                this.systems.put(regMsg.getSlpId(), (PhyConfiguration) config);
+                regResponseMsg.setRegResponse(true);
+                System.out.println("Registered: " + regMsg.getSlpId());
+            }
+
+            // Create corresponding SLPRegResponseMsg and send it to the Client
+            regResponseMsg.create(Integer.toString(regMsg.getSlpId()));
+            phy.send(new String(regResponseMsg.getDataBytes()), config);
+
+        } catch (IllegalMsgException e) {
+            throw new RegistrationFailedException();
+        }
+    }
+
+    public PhyProtocol getPhy() {
+        return phy;
+    }
 }
-- 
GitLab