diff --git a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/CTnewRecSendB.java b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/CTnewRecSendB.java
new file mode 100644
index 0000000000000000000000000000000000000000..05cd493af782f2bbafa5567d7aae13a42bf5a199
--- /dev/null
+++ b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/CTnewRecSendB.java
@@ -0,0 +1,97 @@
+
+package MV3500Cohort2018JulySeptember.FinalProject.CainThomersonFinal;
+
+import java.net.*;
+import java.util.*;
+import edu.nps.moves.disutil.*;
+import edu.nps.moves.dis.*;
+import java.io.IOException;
+
+/**
+ *
+ * @author danielcain
+ */
+public class CTnewRecSendB {
+
+ /** Max size of a PDU in binary format that we can receive. This is actually
+     * somewhat outdated--PDUs can be larger--but this is a reasonable starting point.
+     */
+    public static final int MAX_PDU_SIZE = 8192;
+    
+    /** Default multicast group address we send on. */
+    public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.9";
+	
+    /** Default multicast port used, matches Wireshark DIS capture default */
+    public static final int    DEFAULT_MULTICAST_PORT    = 2800;
+
+    public static void main(String args[])
+	{
+		System.out.println("DisExamples.EspduReceiver started...");
+                	
+        MulticastSocket socket;
+        DatagramPacket packet;
+        InetAddress address;
+        PduFactory pduFactory = new PduFactory();
+
+        try {
+            // Specify the socket to receive data
+            socket = new MulticastSocket(DEFAULT_MULTICAST_PORT);
+            socket.setBroadcast(true);
+
+            while (true) // Loop infinitely, receiving datagrams
+			{
+                byte buffer[] = new byte[MAX_PDU_SIZE];
+                packet = new DatagramPacket(buffer, buffer.length);
+
+                socket.receive(packet);
+
+                List<Pdu> pduBundle = pduFactory.getPdusFromBundle(packet.getData());
+                System.out.println("\nBundle size is " + pduBundle.size());
+                
+                Iterator iterator = pduBundle.iterator();
+
+                while(iterator.hasNext())
+                {
+                    Pdu aPdu = (Pdu)iterator.next();
+                
+                    System.out.print("Recieved PDU of type: " + aPdu.getClass().getName());
+                    if(aPdu instanceof EntityStatePdu)
+                    {
+                        EntityID eid = ((EntityStatePdu)aPdu).getEntityID();
+                        Vector3Double position = ((EntityStatePdu)aPdu).getEntityLocation();
+                        System.out.print("\nEID: [" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
+                        System.out.printf("\nResupply source location for x,y,z coordinates: %.2f " , position.getX() );
+                        System.out.printf(" %.2f " , position.getY() );
+                        System.out.printf(" %.2f " , position.getZ() );
+                        //System.out.print(" FARP WTF recieving location: [" + newPos.getX() + ", " + newPos.getY() + ", " + newPos.getZ() + "]");                        
+                    }
+                    
+                    if(aPdu instanceof ServiceRequestPdu)
+                    {
+                        EntityID eid = ((ServiceRequestPdu)aPdu).getRequestingEntityID();
+                        short serviceType = ((ServiceRequestPdu)aPdu).getServiceTypeRequested();
+                        String serviceReqestTypeString = "null";
+                        if (serviceType == 0)
+                            serviceReqestTypeString = "Other";
+                        if (serviceType == 1)
+                            serviceReqestTypeString = "Resupply";
+                         if (serviceType == 2)
+                            serviceReqestTypeString = "Repair";
+                         
+                        List<SupplyQuantity> supplies = ((ServiceRequestPdu)aPdu).getSupplies();
+                        
+                        System.out.println(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
+                        System.out.println(" Service Type Requested: [" + serviceType + ", " + serviceReqestTypeString + "]");
+                        System.out.println(" Supply Quantity: [" + supplies.toString() + "]\n\n");                        
+                    }
+                } // end trop through PDU bundle
+            } // end while
+        } // End try
+        catch (IOException e)
+		{
+            System.out.println("Problem with DisExamples.EspduReceiver, see exception trace:");
+            System.out.println(e);
+        }
+    } // end main
+} // end class
+
diff --git a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/CTnewSendRecA.java b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/CTnewSendRecA.java
new file mode 100644
index 0000000000000000000000000000000000000000..563e260c9de04ac41d0744e05319be4525272754
--- /dev/null
+++ b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/CTnewSendRecA.java
@@ -0,0 +1,272 @@
+
+package MV3500Cohort2018JulySeptember.FinalProject.CainThomersonFinal;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.CoordinateConversions;
+import edu.nps.moves.disutil.DisTime;
+
+/**
+ *
+ * @author danielcain
+ */
+public class CTnewSendRecA {
+
+	public static final int NUMBER_TO_SEND = 100;
+
+	public enum NetworkMode {
+		UNICAST, MULTICAST, BROADCAST
+	};
+
+	/**
+	 * Default multicast group address we send on.
+	 */
+	public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.9";
+
+	/**
+	 * Default multicast port used, matches Wireshark DIS capture default
+	 */
+	public static final int DEFAULT_MULTICAST_PORT = 2800;
+
+	/**
+	 * @param args
+	 */
+	public static void main(String args[])
+	{
+		System.out.println("DisExamples.EspduSender started... send " + NUMBER_TO_SEND + " ESPDUs, initial index=0");
+		
+                //Establish the Requesting Unit EnityState PDU
+		EntityStatePdu requestingUnitEsPdu = new EntityStatePdu();
+                
+                //Initialize the MulticastSocket to null
+		MulticastSocket socket = null;
+                
+                //Initialize the DIS time (this will be used later in the code
+		DisTime disTime = DisTime.getInstance(); // TODO explain
+		//int alternator = -1;
+
+		// Lat and Long Coordinates that will be used for the location of the Requesting Unit
+		double lat = 36.59;
+		double lon = -121.87;
+
+		// Initialize the Port, Mode, and Destination IP
+		int port = DEFAULT_MULTICAST_PORT;
+		NetworkMode mode = NetworkMode.BROADCAST;
+		InetAddress destinationIp = null;
+
+                //Use a try/catch to ensure the you can connect to the Destination IP
+		try {
+			destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS);
+		} catch (UnknownHostException e) {
+			System.out.println(e + " Cannot create multicast address");
+			System.exit(0);
+		}
+
+		// All system properties, passed in on the command line via -Dattribute=value
+		Properties systemProperties = System.getProperties();
+		// IP address we send to
+		String destinationIpString = systemProperties.getProperty("destinationIp");
+		// Port we send to, and local port we open the socket on
+		String portString = systemProperties.getProperty("port");
+		// Network mode: unicast, multicast, broadcast
+		String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+
+		// Set up a socket to send information
+		try {
+			// Port we send to
+			if (portString != null) 
+			{
+				port = Integer.parseInt(portString);
+			}
+
+			socket = new MulticastSocket(port);
+
+			// Where we send packets to, the destination IP address
+			if (destinationIpString != null) 
+			{
+				destinationIp = InetAddress.getByName(destinationIpString);
+			}
+
+			// Type of transport: unicast, broadcast, or multicast
+			if (networkModeString != null) {
+				if (networkModeString.equalsIgnoreCase("unicast")) 
+				{
+					mode = NetworkMode.UNICAST;
+				} 
+				else if (networkModeString.equalsIgnoreCase("broadcast")) {
+					mode = NetworkMode.BROADCAST;
+				} 
+				else if (networkModeString.equalsIgnoreCase("multicast")) {
+					mode = NetworkMode.MULTICAST;
+					if (!destinationIp.isMulticastAddress())
+					{
+						throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+					}
+					socket.joinGroup(destinationIp);
+				}
+			}
+		}
+		catch (IOException | RuntimeException e)
+		{
+			System.out.println("Unable to initialize networking. Exiting.");
+			System.out.println(e);
+			System.exit(-1);
+		}
+
+		// Initialize values in the Entity State PDU object. 
+                //The exercise ID is a way to differentiate between different virtual worlds on one network.
+		requestingUnitEsPdu.setExerciseID((short) 1);
+
+		// The EID is the unique identifier for objects in the world.
+		EntityID entityID = requestingUnitEsPdu.getEntityID();
+		entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+		entityID.setApplication(1);
+		entityID.setEntity(2);
+
+		// Set the entity type. (Check SISO for a list of enumerations) 
+		EntityType entityType = requestingUnitEsPdu.getEntityType();
+		entityType.setEntityKind((short) 1);      // Platform (vs lifeform, munition, sensor, etc.)
+		entityType.setCountry(222);              // USA
+		entityType.setDomain((short) 1);          // Land (vs air, surface, subsurface, space)
+		entityType.setCategory((short) 1);        // Tank
+		entityType.setSubcategory((short) 1);     // M1 Abrams
+		entityType.setSpec((short) 3);            // M1A2 Abrams
+
+		Set<InetAddress> broadcastAddresses;
+		// Loop through sending N ESPDUs
+		try
+		{
+			System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+			
+			for (int index = 0; index < NUMBER_TO_SEND; index++) {
+			        //DIS Time must be used for this because DIS requires it.
+				int timestamp = disTime.getDisAbsoluteTimestamp();
+				requestingUnitEsPdu.setTimestamp(timestamp);
+
+				//Set up longitude to be changing throughout the running of the program
+				double direction = Math.pow((double) (-1.0), (double) (index));
+				lon = lon + (direction * 0.00006);
+
+				//Convert the lat and long coordinates to cartisian coordinates required by DIS
+                                double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
+				Vector3Double location = requestingUnitEsPdu.getEntityLocation();
+				location.setX(disCoordinates[0]);
+				location.setY(disCoordinates[1]);
+				location.setZ(disCoordinates[2]);
+
+				// You can set other ESPDU values here, such as the velocity, acceleration,
+				// and so on.
+				// Marshal out the espdu object to a byte array, then send a datagram
+				// packet with that data in it.
+				ByteArrayOutputStream baos = new ByteArrayOutputStream();
+				DataOutputStream dos = new DataOutputStream(baos);
+				requestingUnitEsPdu.marshal(dos);
+                                
+                                //SERVICE_REQUEST
+                                ServiceRequestPdu serviceRequest = new ServiceRequestPdu();
+                                serviceRequest.setRequestingEntityID(entityID);
+                                serviceRequest.setServiceTypeRequested((short) 1); //Resupply
+                                List<SupplyQuantity> pSupplies = new ArrayList<SupplyQuantity>();
+                                pSupplies.add(new SupplyQuantity());
+                                serviceRequest.setSupplies(pSupplies);
+                                
+                                //RESUPPLY_OFFER
+                                ResupplyOfferPdu resupplyOffer = new ResupplyOfferPdu();
+                                
+                                byte[] serviceRequestArray = serviceRequest.marshal();
+				//FirePdu fire = new FirePdu();
+				//byte[] fireArray = fire.marshal();
+
+				// The byte array here is the packet in DIS format. We put that into a 
+				// datagram and send it.
+				byte[] data = baos.toByteArray();
+
+				broadcastAddresses = getBroadcastAddresses();
+				Iterator iterator = broadcastAddresses.iterator();
+				while (iterator.hasNext())
+				{
+					InetAddress broadcast = (InetAddress) iterator.next();
+					System.out.println("\nSending broadcast datagram packet to " + broadcast);
+					DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, port);
+					socket.send(packet);
+					// TODO experiment with these!  8)
+					//packet = new DatagramPacket(fireArray, fireArray.length, broadcast, port); // alternate
+                                        packet = new DatagramPacket(serviceRequestArray, serviceRequestArray.length, broadcast, port); // alternate
+					socket.send(packet);
+				}
+
+				// Send every 1 sec. Otherwise all this will be all over in a fraction of a second.
+				Thread.sleep(1000); // msec
+
+				location = requestingUnitEsPdu.getEntityLocation();
+
+				System.out.println("Espdu #" + index + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+				System.out.printf("DIS coordinates location: %.2f" , location.getX());
+                        	System.out.printf(" %.2f" , location.getY() );
+                                System.out.printf(" %.2f" ,  location.getZ());
+			}
+		}
+		catch (IOException | InterruptedException e)
+		{
+            System.out.println("Problem with DisExamples.EspduSender, see exception trace:");
+			System.out.println(e);
+		}
+	}
+
+	/**
+	 * A number of sites get all snippy about using 255.255.255.255 for a
+	 * broadcast address; it trips their security software and they kick you off
+	 * their network. (Comcast, NPS.) This determines the broadcast address for
+	 * all connected interfaces, based on the IP and subnet mask. If you have a
+	 * dual-homed host it will return a broadcast address for both. If you have
+	 * some VMs running on your host this will pick up the addresses for those
+	 * as well--e.g. running VMWare on your laptop with a local IP this will also
+	 * pick up a 192.168 address assigned to the VM by the host OS.
+	 *
+	 * @return set of all broadcast addresses
+	 */
+	public static Set<InetAddress> getBroadcastAddresses()
+	{
+		Set<InetAddress> broadcastAddresses = new HashSet<>();
+		Enumeration interfaces;
+
+		try {
+			interfaces = NetworkInterface.getNetworkInterfaces();
+
+			while (interfaces.hasMoreElements())
+			{
+				NetworkInterface anInterface = (NetworkInterface) interfaces.nextElement();
+
+				if (anInterface.isUp())
+				{
+					Iterator iterator = anInterface.getInterfaceAddresses().iterator();
+					while (iterator.hasNext())
+					{
+						InterfaceAddress anAddress = (InterfaceAddress) iterator.next();
+						if ((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
+						{
+							continue;
+						}
+
+						//System.out.println("Getting broadcast address for " + anAddress);
+						InetAddress broadcastAddress = anAddress.getBroadcast();
+						if (broadcastAddress != null)
+						{
+							broadcastAddresses.add(broadcastAddress);
+						}
+					}
+				}
+			}
+		}
+		catch (SocketException e) 
+		{
+            System.out.println("Problem with DisExamples.EspduSender.getBroadcastAddresses(), see exception trace:");
+			System.out.println(e);
+		}
+		return broadcastAddresses;
+	}
+}
+
diff --git a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduReceiverA.java b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduReceiverA.java
index 79f2250868f2450910c007b08e1aef4ab14f3a41..d9f2fb3e882cdcd50480258ab716ae4ae3b80dc4 100644
--- a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduReceiverA.java
+++ b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduReceiverA.java
@@ -14,6 +14,7 @@ import java.io.IOException;
  */
 public class C_T_EspduReceiverA
 {
+    public static final int NUMBER_TO_SEND = 5000;
     /** Max size of a PDU in binary format that we can receive. This is actually
      * somewhat outdated--PDUs can be larger--but this is a reasonable starting point.
      */
diff --git a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduRequestingUnit.java b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduRequestingUnit.java
new file mode 100644
index 0000000000000000000000000000000000000000..d75c71d30cf532a208ed0fed9b9a54fa93226917
--- /dev/null
+++ b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduRequestingUnit.java
@@ -0,0 +1,250 @@
+package MV3500Cohort2018JulySeptember.FinalProject.CainThomersonFinal;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.CoordinateConversions;
+import edu.nps.moves.disutil.DisTime;
+import edu.nps.moves.disutil.PduFactory;
+
+/**
+ * Creates and sends ESPDUs in IEEE binary format. Adapted from OpenDIS library
+ * example package edu.nps.moves.examples
+ *
+ * @author DMcG
+ */
+public class C_T_EspduRequestingUnit {
+
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode {
+        UNICAST, MULTICAST, BROADCAST
+    };
+
+    public static final int MAX_PDU_SIZE = 8192;
+    
+    public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3";
+
+    public static final int DEFAULT_MULTICAST_PORT = 3000;
+
+    public static void main(String args[]) {
+   
+        System.out.println("\nREQUESTING UNIT:\n\tProgram started\n");
+
+        //Initialize the MulticastSocket to null
+        MulticastSocket socket = null;
+
+        //Initialize the DIS time (this will be used later in the code
+        DisTime disTime = DisTime.getInstance();
+
+        // Initialize the Port, Mode, and Destination IP
+        int port = DEFAULT_MULTICAST_PORT;
+        NetworkMode mode = NetworkMode.BROADCAST;
+        InetAddress destinationIp = null;
+
+        //Receiving
+        DatagramPacket receivingPacket;
+        InetAddress receivingAddress;
+        PduFactory pduFactory = new PduFactory();
+        
+        //Use a try/catch to ensure the you can connect to the Destination IP
+        try {
+            destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS);
+        } catch (UnknownHostException e) {
+            System.out.println(e + " Cannot create multicast address");
+            System.exit(0);
+        }
+
+        // All system properties, passed in on the command line via -Dattribute=value
+        Properties systemProperties = System.getProperties();
+        // IP address we send to
+        String destinationIpString = systemProperties.getProperty("destinationIp");
+        // Port we send to, and local port we open the socket on
+        String portString = systemProperties.getProperty("port");
+        // Network mode: unicast, multicast, broadcast
+        String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+
+        // Set up a socket to send information
+        try {
+            // Port we send to
+            if (portString != null) {
+                port = Integer.parseInt(portString);
+            }
+
+            socket = new MulticastSocket(port);
+
+            // Where we send packets to, the destination IP address
+            if (destinationIpString != null) {
+                destinationIp = InetAddress.getByName(destinationIpString);
+            }
+
+            // Type of transport: unicast, broadcast, or multicast
+            if (networkModeString != null) {
+                if (networkModeString.equalsIgnoreCase("unicast")) {
+                    mode = NetworkMode.UNICAST;
+                } else if (networkModeString.equalsIgnoreCase("broadcast")) {
+                    mode = NetworkMode.BROADCAST;
+                } else if (networkModeString.equalsIgnoreCase("multicast")) {
+                    mode = NetworkMode.MULTICAST;
+                    if (!destinationIp.isMulticastAddress()) {
+                        throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                    }
+                    socket.joinGroup(destinationIp);
+                }
+            }
+        } catch (IOException | RuntimeException e) {
+            System.out.println("Unable to initialize networking. Exiting.");
+            System.out.println(e);
+            System.exit(-1);
+        }
+        
+        //Establish the Requesting Unit EnityState PDU
+        EntityStatePdu requestingUnitEsPdu = new EntityStatePdu();
+        
+        // Initialize values in the Entity State PDU object. 
+        //The exercise ID is a way to differentiate between different virtual worlds on one network.
+        requestingUnitEsPdu.setExerciseID((short) 1);
+
+        // The EID is the unique identifier for objects in the world.
+        EntityID entityID = requestingUnitEsPdu.getEntityID();
+        entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+        entityID.setApplication(1);
+        entityID.setEntity(2);
+
+        // Set the entity type. (Check SISO for a list of enumerations) 
+        EntityType entityType = requestingUnitEsPdu.getEntityType();
+        entityType.setEntityKind((short) 1);      // Platform (vs lifeform, munition, sensor, etc.)
+        entityType.setCountry(225);              // USA
+        entityType.setDomain((short) 1);          // Land (vs air, surface, subsurface, space)
+        entityType.setCategory((short) 1);        // Tank
+        entityType.setSubcategory((short) 1);     // M1 Abrams
+        entityType.setSpec((short) 3);            // M1A2 Abrams
+        
+        // Lat and Long Coordinates that will be used for the location of the Requesting Unit
+        double lat = 36.595517;
+        double lon = -121.877000;
+        //Boolean for the initial connection
+        boolean connectionMade = false;
+        
+        Set<InetAddress> broadcastAddresses;
+        try {
+            while (true) {
+                System.out.println("\nREQUESTING UNIT:\n\tListening\n");
+                
+                int timestamp = disTime.getDisAbsoluteTimestamp();
+                
+                // Marshal out the espdu object to a byte array, then send a datagram
+                // packet with that data in it.
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                DataOutputStream dos = new DataOutputStream(baos);
+                requestingUnitEsPdu.marshal(dos);
+                
+                
+                //While we have not recieved an acknowledgement from the receiving unit keep sending the entity state information
+                while(!connectionMade) {
+                    //DIS Time must be used for this because DIS requires it.
+                    timestamp = disTime.getDisAbsoluteTimestamp();
+                    requestingUnitEsPdu.setTimestamp(timestamp);
+                    
+                    //The byte array here is the packet in DIS format. We put that into a 
+                    // datagram and send it.
+                    byte[] data = baos.toByteArray();
+                    
+                    broadcastAddresses = getBroadcastAddresses();
+                    Iterator broadcastIterator = broadcastAddresses.iterator();
+                    
+                    while (broadcastIterator.hasNext()) {
+                        InetAddress broadcast = (InetAddress) broadcastIterator.next();
+                        System.out.println("Sending broadcast datagram packet to " + broadcast);
+                        DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, port);
+                        socket.send(packet);
+                    }
+                    // Send every 1 sec. Otherwise all this will be all over in a fraction of a second.
+                    Thread.sleep(1000); // msec
+                    
+                    System.out.println("SENDING ENTITY STATE INFORMATION");
+                    System.out.println("\tEID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+                    
+                    //Prepare to receive a package
+                    byte buffer[] = new byte[MAX_PDU_SIZE];
+                    receivingPacket = new DatagramPacket(buffer, buffer.length);
+                    socket.receive(receivingPacket);
+                    List<Pdu> pduBundle = pduFactory.getPdusFromBundle(receivingPacket.getData());
+                    System.out.println("Bundle size is " + pduBundle.size());
+                    
+                    //Iterate through the bundle
+                    Iterator iterator = pduBundle.iterator();
+                    while (iterator.hasNext()) {
+                        
+                        Pdu aPdu = (Pdu) iterator.next();
+                        System.out.println("got PDU of type: " + aPdu.getClass().getName());
+                        
+                        if (aPdu instanceof EntityStatePdu) {
+                            EntityID eid = ((EntityStatePdu) aPdu).getEntityID();
+                            EntityType eType = ((EntityStatePdu) aPdu).getEntityType();
+                            Vector3Double position = ((EntityStatePdu) aPdu).getEntityLocation();
+                            
+                            if(eType.getEntityKind() != requestingUnitEsPdu.getEntityType().getEntityKind()) {
+                                connectionMade = true;
+                                System.out.println("RECEIVED PACKET");
+                                System.out.println("\tEID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
+                                System.out.println("\tEntity Location: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
+                                System.out.println("\tEntity Type: " + eType.getEntityKind() + "\n");
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (IOException | InterruptedException e) {
+            System.out.println("Problem with DisExamples.EspduSender, see exception trace:");
+            System.out.println(e);
+        }
+    }
+
+    /**
+     * A number of sites get all snippy about using 255.255.255.255 for a
+     * broadcast address; it trips their security software and they kick you off
+     * their network. (Comcast, NPS.) This determines the broadcast address for
+     * all connected interfaces, based on the IP and subnet mask. If you have a
+     * dual-homed host it will return a broadcast address for both. If you have
+     * some VMs running on your host this will pick up the addresses for those
+     * as well--e.g. running VMWare on your laptop with a local IP this will
+     * also pick up a 192.168 address assigned to the VM by the host OS.
+     *
+     * @return set of all broadcast addresses
+     */
+    public static Set<InetAddress> getBroadcastAddresses() {
+        Set<InetAddress> broadcastAddresses = new HashSet<>();
+        Enumeration interfaces;
+
+        try {
+            interfaces = NetworkInterface.getNetworkInterfaces();
+
+            while (interfaces.hasMoreElements()) {
+                NetworkInterface anInterface = (NetworkInterface) interfaces.nextElement();
+
+                if (anInterface.isUp()) {
+                    Iterator iterator = anInterface.getInterfaceAddresses().iterator();
+                    while (iterator.hasNext()) {
+                        InterfaceAddress anAddress = (InterfaceAddress) iterator.next();
+                        if ((anAddress == null || anAddress.getAddress().isLinkLocalAddress())) {
+                            continue;
+                        }
+
+                        //System.out.println("Getting broadcast address for " + anAddress);
+                        InetAddress broadcastAddress = anAddress.getBroadcast();
+                        if (broadcastAddress != null) {
+                            broadcastAddresses.add(broadcastAddress);
+                        }
+                    }
+                }
+            }
+        } catch (SocketException e) {
+            System.out.println("Problem with DisExamples.EspduSender.getBroadcastAddresses(), see exception trace:");
+            System.out.println(e);
+        }
+        return broadcastAddresses;
+    }
+}
diff --git a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduSenderA.java b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduSenderA.java
index 95b29a5e1cf1bf7a2d10ac0f89d483d63c974c76..4e5a0cdcd105fb6e88f0f43f461b7fbe3e4d4840 100644
--- a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduSenderA.java
+++ b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduSenderA.java
@@ -1,4 +1,4 @@
-package MV3500Cohort2018JulySeptember.FinalProject.CainThomersonFinal; 
+package MV3500Cohort2018JulySeptember.FinalProject.CainThomersonFinal;
 
 import java.io.*;
 import java.net.*;
@@ -16,263 +16,230 @@ import edu.nps.moves.disutil.DisTime;
  */
 public class C_T_EspduSenderA {
 
-	public static final int NUMBER_TO_SEND = 5000;
-
-	public enum NetworkMode {
-		UNICAST, MULTICAST, BROADCAST
-	};
-
-	/**
-	 * Default multicast group address we send on.
-	 */
-	public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3";
-
-	/**
-	 * Default multicast port used, matches Wireshark DIS capture default
-	 */
-	public static final int DEFAULT_MULTICAST_PORT = 3000;
-
-	/**
-	 * Possible system properties, passed in via -Dattr=val networkMode:
-	 * unicast, broadcast, multicast destinationIp: where to send the packet. If
-	 * in multicast mode, this can be multicast. To determine broadcast
-	 * destination IP, use an online broadcast address calculator, for example
-	 * http://www.remotemonitoringsystems.ca/broadcast.php If in multicast mode,
-	 * a join() will be done on the multicast address. port: port used for both
-	 * source and destination.
-	 *
-	 * @param args
-	 */
-	public static void main(String args[])
-	{
-		System.out.println("DisExamples.EspduSender started... send " + NUMBER_TO_SEND + " ESPDUs, initial index=0");
-		
-                //Establish the Requesting Unit EnityState PDU
-		EntityStatePdu requestingUnitEsPdu = new EntityStatePdu();
-                
-                //Initialize the MulticastSocket to null
-		MulticastSocket socket = null;
-                
-                //Initialize the DIS time (this will be used later in the code
-		DisTime disTime = DisTime.getInstance(); // TODO explain
-		//int alternator = -1;
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode {
+        UNICAST, MULTICAST, BROADCAST
+    };
+
+    public static final int MAX_PDU_SIZE = 8192;
+    
+    public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3";
+
+    public static final int DEFAULT_MULTICAST_PORT = 3000;
+
+    public static void main(String args[]) {
+   
+        System.out.println("\nREQUESTING UNIT:\n\tProgram started\n");
 
 		// Lat and Long Coordinates that will be used for the location of the Requesting Unit
 		double lat = 36.59;
 		double lon = -121.87;
 
-		// Initialize the Port, Mode, and Destination IP
-		int port = DEFAULT_MULTICAST_PORT;
-		NetworkMode mode = NetworkMode.BROADCAST;
-		InetAddress destinationIp = null;
-
-                //Use a try/catch to ensure the you can connect to the Destination IP
-		try {
-			destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS);
-		} catch (UnknownHostException e) {
-			System.out.println(e + " Cannot create multicast address");
-			System.exit(0);
-		}
-
-		// All system properties, passed in on the command line via -Dattribute=value
-		Properties systemProperties = System.getProperties();
-		// IP address we send to
-		String destinationIpString = systemProperties.getProperty("destinationIp");
-		// Port we send to, and local port we open the socket on
-		String portString = systemProperties.getProperty("port");
-		// Network mode: unicast, multicast, broadcast
-		String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
-
-		// Set up a socket to send information
-		try {
-			// Port we send to
-			if (portString != null) 
-			{
-				port = Integer.parseInt(portString);
-			}
-
-			socket = new MulticastSocket(port);
-
-			// Where we send packets to, the destination IP address
-			if (destinationIpString != null) 
-			{
-				destinationIp = InetAddress.getByName(destinationIpString);
-			}
-
-			// Type of transport: unicast, broadcast, or multicast
-			if (networkModeString != null) {
-				if (networkModeString.equalsIgnoreCase("unicast")) 
-				{
-					mode = NetworkMode.UNICAST;
-				} 
-				else if (networkModeString.equalsIgnoreCase("broadcast")) {
-					mode = NetworkMode.BROADCAST;
-				} 
-				else if (networkModeString.equalsIgnoreCase("multicast")) {
-					mode = NetworkMode.MULTICAST;
-					if (!destinationIp.isMulticastAddress())
-					{
-						throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
-					}
-					socket.joinGroup(destinationIp);
-				}
-			}
-		}
-		catch (IOException | RuntimeException e)
-		{
-			System.out.println("Unable to initialize networking. Exiting.");
-			System.out.println(e);
-			System.exit(-1);
-		}
-
-		// Initialize values in the Entity State PDU object. 
-                //The exercise ID is a way to differentiate between different virtual worlds on one network.
-		requestingUnitEsPdu.setExerciseID((short) 1);
-
-		// The EID is the unique identifier for objects in the world.
-		EntityID entityID = requestingUnitEsPdu.getEntityID();
-		entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
-		entityID.setApplication(1);
-		entityID.setEntity(2);
-
-		// Set the entity type. (Check SISO for a list of enumerations) 
-		EntityType entityType = requestingUnitEsPdu.getEntityType();
-		entityType.setEntityKind((short) 1);      // Platform (vs lifeform, munition, sensor, etc.)
-		entityType.setCountry(225);              // USA
-		entityType.setDomain((short) 1);          // Land (vs air, surface, subsurface, space)
-		entityType.setCategory((short) 1);        // Tank
-		entityType.setSubcategory((short) 1);     // M1 Abrams
-		entityType.setSpec((short) 3);            // M1A2 Abrams
-
-		Set<InetAddress> broadcastAddresses;
-		// Loop through sending N ESPDUs
-		try
-		{
-			System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
-			
-			for (int index = 0; index < NUMBER_TO_SEND; index++) {
-			        //DIS Time must be used for this because DIS requires it.
-				int timestamp = disTime.getDisAbsoluteTimestamp();
-				requestingUnitEsPdu.setTimestamp(timestamp);
-
-				//Set up longitude to be changing throughout the running of the program
-				double direction = Math.pow((double) (-1.0), (double) (index));
-				lon = lon + (direction * 0.00006);
-
-				//Convert the lat and long coordinates to cartisian coordinates required by DIS
-                                double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
-				Vector3Double location = requestingUnitEsPdu.getEntityLocation();
-				location.setX(disCoordinates[0]);
-				location.setY(disCoordinates[1]);
-				location.setZ(disCoordinates[2]);
-
-				// You can set other ESPDU values here, such as the velocity, acceleration,
-				// and so on.
-				// Marshal out the espdu object to a byte array, then send a datagram
-				// packet with that data in it.
-				ByteArrayOutputStream baos = new ByteArrayOutputStream();
-				DataOutputStream dos = new DataOutputStream(baos);
-				requestingUnitEsPdu.marshal(dos);
-                                
-                                //SERVICE_REQUEST
-                                ServiceRequestPdu serviceRequest = new ServiceRequestPdu();
-                                serviceRequest.setRequestingEntityID(entityID);
-                                serviceRequest.setServiceTypeRequested((short) 1); //Resupply
-                                List<SupplyQuantity> pSupplies = new ArrayList<SupplyQuantity>();
-                                pSupplies.add(new SupplyQuantity());
-                                serviceRequest.setSupplies(pSupplies);
-                                
-                                //RESUPPLY_OFFER
-                                ResupplyOfferPdu resupplyOffer = new ResupplyOfferPdu();
-                                
-                                byte[] serviceRequestArray = serviceRequest.marshal();
-				//FirePdu fire = new FirePdu();
-				//byte[] fireArray = fire.marshal();
-
-				// The byte array here is the packet in DIS format. We put that into a 
-				// datagram and send it.
-				byte[] data = baos.toByteArray();
-
-				broadcastAddresses = getBroadcastAddresses();
-				Iterator iterator = broadcastAddresses.iterator();
-				while (iterator.hasNext())
-				{
-					InetAddress broadcast = (InetAddress) iterator.next();
-					System.out.println("Sending broadcast datagram packet to " + broadcast);
-					DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, port);
-					socket.send(packet);
-					// TODO experiment with these!  8)
-					//packet = new DatagramPacket(fireArray, fireArray.length, broadcast, port); // alternate
-                                        packet = new DatagramPacket(serviceRequestArray, serviceRequestArray.length, broadcast, port); // alternate
-					socket.send(packet);
-				}
-
-				// Send every 1 sec. Otherwise all this will be all over in a fraction of a second.
-				Thread.sleep(1000); // msec
-
-				location = requestingUnitEsPdu.getEntityLocation();
-
-				System.out.println("Espdu #" + index + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
-				System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
-			}
-		}
-		catch (IOException | InterruptedException e)
-		{
+        //Initialize the DIS time (this will be used later in the code
+        DisTime disTime = DisTime.getInstance();
+
+        
+
+        // Initialize the Port, Mode, and Destination IP
+        int port = DEFAULT_MULTICAST_PORT;
+        NetworkMode mode = NetworkMode.BROADCAST;
+        InetAddress destinationIp = null;
+
+        //Use a try/catch to ensure the you can connect to the Destination IP
+        try {
+            destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS);
+        } catch (UnknownHostException e) {
+            System.out.println(e + " Cannot create multicast address");
+            System.exit(0);
+        }
+
+        // All system properties, passed in on the command line via -Dattribute=value
+        Properties systemProperties = System.getProperties();
+        // IP address we send to
+        String destinationIpString = systemProperties.getProperty("destinationIp");
+        // Port we send to, and local port we open the socket on
+        String portString = systemProperties.getProperty("port");
+        // Network mode: unicast, multicast, broadcast
+        String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+
+        // Set up a socket to send information
+        try {
+            // Port we send to
+            if (portString != null) {
+                port = Integer.parseInt(portString);
+            }
+
+            socket = new MulticastSocket(port);
+
+            // Where we send packets to, the destination IP address
+            if (destinationIpString != null) {
+                destinationIp = InetAddress.getByName(destinationIpString);
+            }
+
+            // Type of transport: unicast, broadcast, or multicast
+            if (networkModeString != null) {
+                if (networkModeString.equalsIgnoreCase("unicast")) {
+                    mode = NetworkMode.UNICAST;
+                } else if (networkModeString.equalsIgnoreCase("broadcast")) {
+                    mode = NetworkMode.BROADCAST;
+                } else if (networkModeString.equalsIgnoreCase("multicast")) {
+                    mode = NetworkMode.MULTICAST;
+                    if (!destinationIp.isMulticastAddress()) {
+                        throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                    }
+                    socket.joinGroup(destinationIp);
+                }
+            }
+        } catch (IOException | RuntimeException e) {
+            System.out.println("Unable to initialize networking. Exiting.");
+            System.out.println(e);
+            System.exit(-1);
+        }
+        
+        //Establish the Requesting Unit EnityState PDU
+        EntityStatePdu requestingUnitEsPdu = new EntityStatePdu();
+        
+        // Initialize values in the Entity State PDU object. 
+        //The exercise ID is a way to differentiate between different virtual worlds on one network.
+        requestingUnitEsPdu.setExerciseID((short) 1);
+
+        // The EID is the unique identifier for objects in the world.
+        EntityID entityID = requestingUnitEsPdu.getEntityID();
+        entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+        entityID.setApplication(1);
+        entityID.setEntity(2);
+
+        // Set the entity type. (Check SISO for a list of enumerations) 
+        EntityType entityType = requestingUnitEsPdu.getEntityType();
+        entityType.setEntityKind((short) 1);      // Platform (vs lifeform, munition, sensor, etc.)
+        entityType.setCountry(225);              // USA
+        entityType.setDomain((short) 1);          // Land (vs air, surface, subsurface, space)
+        entityType.setCategory((short) 1);        // Tank
+        entityType.setSubcategory((short) 1);     // M1 Abrams
+        entityType.setSpec((short) 3);            // M1A2 Abrams
+        
+        // Lat and Long Coordinates that will be used for the location of the Requesting Unit
+        double lat = 36.595517;
+        double lon = -121.877000;
+        
+        Set<InetAddress> broadcastAddresses;
+        // Loop through sending N ESPDUs
+        try {
+            System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+
+            for (int index = 0; index < NUMBER_TO_SEND; index++) {
+                //DIS Time must be used for this because DIS requires it.
+                int timestamp = disTime.getDisAbsoluteTimestamp();
+                requestingUnitEsPdu.setTimestamp(timestamp);
+
+                //Set up longitude to be changing throughout the running of the program
+                double direction = Math.pow((double) (-1.0), (double) (index));
+                lon = lon + (direction * 0.00006);
+
+                //Convert the lat and long coordinates to cartisian coordinates required by DIS
+                double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
+                Vector3Double location = requestingUnitEsPdu.getEntityLocation();
+                location.setX(disCoordinates[0]);
+                location.setY(disCoordinates[1]);
+                location.setZ(disCoordinates[2]);
+
+                // You can set other ESPDU values here, such as the velocity, acceleration,
+                // and so on.
+                // Marshal out the espdu object to a byte array, then send a datagram
+                // packet with that data in it.
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                DataOutputStream dos = new DataOutputStream(baos);
+                requestingUnitEsPdu.marshal(dos);
+
+                //SERVICE_REQUEST
+                ServiceRequestPdu serviceRequest = new ServiceRequestPdu();
+                serviceRequest.setRequestingEntityID(entityID);
+                serviceRequest.setServiceTypeRequested((short) 1); //Resupply
+                List<SupplyQuantity> pSupplies = new ArrayList<SupplyQuantity>();
+                pSupplies.add(new SupplyQuantity());
+                serviceRequest.setSupplies(pSupplies);
+
+                //RESUPPLY_OFFER
+                ResupplyOfferPdu resupplyOffer = new ResupplyOfferPdu();
+
+                byte[] serviceRequestArray = serviceRequest.marshal();
+                //FirePdu fire = new FirePdu();
+                //byte[] fireArray = fire.marshal();
+
+                // The byte array here is the packet in DIS format. We put that into a 
+                // datagram and send it.
+                byte[] data = baos.toByteArray();
+
+                broadcastAddresses = getBroadcastAddresses();
+                Iterator iterator = broadcastAddresses.iterator();
+                while (iterator.hasNext()) {
+                    InetAddress broadcast = (InetAddress) iterator.next();
+                    System.out.println("Sending broadcast datagram packet to " + broadcast);
+                    DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, port);
+                    socket.send(packet);
+                    // TODO experiment with these!  8)
+                    //packet = new DatagramPacket(fireArray, fireArray.length, broadcast, port); // alternate
+                    packet = new DatagramPacket(serviceRequestArray, serviceRequestArray.length, broadcast, port); // alternate
+                    socket.send(packet);
+                }
+
+                // Send every 1 sec. Otherwise all this will be all over in a fraction of a second.
+                Thread.sleep(1000); // msec
+
+                location = requestingUnitEsPdu.getEntityLocation();
+
+                System.out.println("Espdu #" + index + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+                System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
+            }
+        } catch (IOException | InterruptedException e) {
             System.out.println("Problem with DisExamples.EspduSender, see exception trace:");
-			System.out.println(e);
-		}
-	}
-
-	/**
-	 * A number of sites get all snippy about using 255.255.255.255 for a
-	 * broadcast address; it trips their security software and they kick you off
-	 * their network. (Comcast, NPS.) This determines the broadcast address for
-	 * all connected interfaces, based on the IP and subnet mask. If you have a
-	 * dual-homed host it will return a broadcast address for both. If you have
-	 * some VMs running on your host this will pick up the addresses for those
-	 * as well--e.g. running VMWare on your laptop with a local IP this will also
-	 * pick up a 192.168 address assigned to the VM by the host OS.
-	 *
-	 * @return set of all broadcast addresses
-	 */
-	public static Set<InetAddress> getBroadcastAddresses()
-	{
-		Set<InetAddress> broadcastAddresses = new HashSet<>();
-		Enumeration interfaces;
-
-		try {
-			interfaces = NetworkInterface.getNetworkInterfaces();
-
-			while (interfaces.hasMoreElements())
-			{
-				NetworkInterface anInterface = (NetworkInterface) interfaces.nextElement();
-
-				if (anInterface.isUp())
-				{
-					Iterator iterator = anInterface.getInterfaceAddresses().iterator();
-					while (iterator.hasNext())
-					{
-						InterfaceAddress anAddress = (InterfaceAddress) iterator.next();
-						if ((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
-						{
-							continue;
-						}
-
-						//System.out.println("Getting broadcast address for " + anAddress);
-						InetAddress broadcastAddress = anAddress.getBroadcast();
-						if (broadcastAddress != null)
-						{
-							broadcastAddresses.add(broadcastAddress);
-						}
-					}
-				}
-			}
-		}
-		catch (SocketException e) 
-		{
+            System.out.println(e);
+        }
+    }
+
+    /**
+     * A number of sites get all snippy about using 255.255.255.255 for a
+     * broadcast address; it trips their security software and they kick you off
+     * their network. (Comcast, NPS.) This determines the broadcast address for
+     * all connected interfaces, based on the IP and subnet mask. If you have a
+     * dual-homed host it will return a broadcast address for both. If you have
+     * some VMs running on your host this will pick up the addresses for those
+     * as well--e.g. running VMWare on your laptop with a local IP this will
+     * also pick up a 192.168 address assigned to the VM by the host OS.
+     *
+     * @return set of all broadcast addresses
+     */
+    public static Set<InetAddress> getBroadcastAddresses() {
+        Set<InetAddress> broadcastAddresses = new HashSet<>();
+        Enumeration interfaces;
+
+        try {
+            interfaces = NetworkInterface.getNetworkInterfaces();
+
+            while (interfaces.hasMoreElements()) {
+                NetworkInterface anInterface = (NetworkInterface) interfaces.nextElement();
+
+                if (anInterface.isUp()) {
+                    Iterator iterator = anInterface.getInterfaceAddresses().iterator();
+                    while (iterator.hasNext()) {
+                        InterfaceAddress anAddress = (InterfaceAddress) iterator.next();
+                        if ((anAddress == null || anAddress.getAddress().isLinkLocalAddress())) {
+                            continue;
+                        }
+
+                        //System.out.println("Getting broadcast address for " + anAddress);
+                        InetAddress broadcastAddress = anAddress.getBroadcast();
+                        if (broadcastAddress != null) {
+                            broadcastAddresses.add(broadcastAddress);
+                        }
+                    }
+                }
+            }
+        } catch (SocketException e) {
             System.out.println("Problem with DisExamples.EspduSender.getBroadcastAddresses(), see exception trace:");
-			System.out.println(e);
-		}
-		return broadcastAddresses;
-	}
+            System.out.println(e);
+        }
+        return broadcastAddresses;
+    }
 }
diff --git a/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduSupplyerUnit.java b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduSupplyerUnit.java
new file mode 100644
index 0000000000000000000000000000000000000000..2597251fb70d7d21223a01d48560518eeb4f7c01
--- /dev/null
+++ b/deliverables/src/MV3500Cohort2018JulySeptember/FinalProject/CainThomersonFinal/C_T_EspduSupplyerUnit.java
@@ -0,0 +1,221 @@
+package MV3500Cohort2018JulySeptember.FinalProject.CainThomersonFinal;
+
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.disutil.*;
+
+import edu.nps.moves.dis.*;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Receives PDUs from the network in IEEE DIS format. Adapted from OpenDIS
+ * library example package edu.nps.moves.examples
+ *
+ * @author DMcG
+ * @version $Id:$
+ */
+public class C_T_EspduSupplyerUnit {
+
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode {
+        UNICAST, MULTICAST, BROADCAST
+    };
+
+    public static final int MAX_PDU_SIZE = 8192;
+
+    public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3";
+
+    public static final int DEFAULT_MULTICAST_PORT = 3000;
+
+    public static void main(String args[]) {
+        
+        System.out.println("\nSUPPLYER UNIT:\n\tProgram started\n");
+
+        //Initialize the MulticastSocket to null
+        MulticastSocket socket = null;
+
+        //Initialize the DIS time (this will be used later in the code
+        DisTime disTime = DisTime.getInstance();
+        
+        // Initialize the Port, Mode, and Destination IP
+        int port = DEFAULT_MULTICAST_PORT;
+        NetworkMode mode = NetworkMode.BROADCAST;
+        InetAddress destinationIp = null;
+        
+        //Receiving
+        DatagramPacket receivingPacket;
+        InetAddress receivingAddress;
+        PduFactory pduFactory = new PduFactory();
+
+        //Use a try/catch to ensure the you can connect to the Destination IP
+        try {
+            destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS);
+        } catch (UnknownHostException e) {
+            System.out.println(e + " Cannot create multicast address");
+            System.exit(0);
+        }
+        
+        // All system properties, passed in on the command line via -Dattribute=value
+        Properties systemProperties = System.getProperties();
+        // IP address we send to
+        String destinationIpString = systemProperties.getProperty("destinationIp");
+        // Port we send to, and local port we open the socket on
+        String portString = systemProperties.getProperty("port");
+        // Network mode: unicast, multicast, broadcast
+        String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+
+        
+        try {
+            // Port we send to
+            if (portString != null) {
+                port = Integer.parseInt(portString);
+            }
+
+            socket = new MulticastSocket(port);
+
+            // Where we send packets to, the destination IP address
+            if (destinationIpString != null) {
+                destinationIp = InetAddress.getByName(destinationIpString);
+            }
+
+            // Type of transport: unicast, broadcast, or multicast
+            if (networkModeString != null) {
+                if (networkModeString.equalsIgnoreCase("unicast")) {
+                    mode = NetworkMode.UNICAST;
+                } else if (networkModeString.equalsIgnoreCase("broadcast")) {
+                    mode = NetworkMode.BROADCAST;
+                } else if (networkModeString.equalsIgnoreCase("multicast")) {
+                    mode = NetworkMode.MULTICAST;
+                    if (!destinationIp.isMulticastAddress()) {
+                        throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                    }
+                    socket.joinGroup(destinationIp);
+                }
+            }
+        } catch (IOException | RuntimeException e) {
+            System.out.println("Unable to initialize networking. Exiting.");
+            System.out.println(e);
+            System.exit(-1);
+        }
+        
+        //Establish the Requesting Unit EnityState PDU
+        EntityStatePdu supplyerUnitEsPdu = new EntityStatePdu();
+        
+        // Initialize values in the Entity State PDU object. 
+        //The exercise ID is a way to differentiate between different virtual worlds on one network.
+        supplyerUnitEsPdu.setExerciseID((short) 1);
+
+        // The EID is the unique identifier for objects in the world.
+        EntityID entityID = supplyerUnitEsPdu.getEntityID();
+        entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+        entityID.setApplication(1);
+        entityID.setEntity(2);
+
+        // Set the entity type. (Check SISO for a list of enumerations) 
+        EntityType entityType = supplyerUnitEsPdu.getEntityType();
+        entityType.setEntityKind((short) 7);      // Supply (vs lifeform, munition, sensor, etc.)
+        entityType.setCountry(225);              // USA
+        entityType.setDomain((short) 1);          // Land (vs air, surface, subsurface, space)
+        entityType.setCategory((short) 34);        // Command Facility
+        
+        // Lat and Long Coordinates that will be used for the location of the Requesting Unit
+        double lat = 75.123456;
+        double lon = -200.877000;
+        
+        Set<InetAddress> broadcastAddresses;
+        Set<Pdu> receivedMessages = new HashSet<>();
+        try{
+            while (true) // Loop infinitely, receiving datagrams
+            {
+                System.out.println("\nSUPPYER UNIT:\n\tListening\n");
+                
+                int timestamp = disTime.getDisAbsoluteTimestamp();
+                
+                // Marshal out the espdu object to a byte array, then send a datagram
+                // packet with that data in it.
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                DataOutputStream dos = new DataOutputStream(baos);
+                supplyerUnitEsPdu.marshal(dos);
+                byte[] data = baos.toByteArray();
+                broadcastAddresses = getBroadcastAddresses();
+                Iterator broadcastIterator = broadcastAddresses.iterator();
+                
+                //Receiving Set Up
+                byte buffer[] = new byte[MAX_PDU_SIZE];
+                receivingPacket = new DatagramPacket(buffer, buffer.length);
+                socket.receive(receivingPacket);
+                List<Pdu> pduBundle = pduFactory.getPdusFromBundle(receivingPacket.getData());
+                System.out.println("Bundle size is " + pduBundle.size());
+
+                Iterator receivingIterator = pduBundle.iterator();
+
+                while (receivingIterator.hasNext()) {
+                    Pdu aPdu = (Pdu) receivingIterator.next();
+                    if (!receivedMessages.contains(aPdu)) {
+                        System.out.println("got PDU of type: " + aPdu.getClass().getName());
+                        if (aPdu instanceof EntityStatePdu) {
+                            EntityID eid = ((EntityStatePdu) aPdu).getEntityID();
+                            EntityType eType = ((EntityStatePdu) aPdu).getEntityType();
+                            Vector3Double position = ((EntityStatePdu) aPdu).getEntityLocation();
+                            System.out.println("RECEIVED PACKET");
+                            System.out.println("\tEID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
+                            System.out.println("\tEntity Location: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
+                            System.out.println("\tEntity Type: " + eType.getEntityKind() + "\n");
+
+                            if (eType.getEntityKind() != supplyerUnitEsPdu.getEntityType().getEntityKind()) {
+                                while (broadcastIterator.hasNext()) {
+                                    InetAddress broadcast = (InetAddress) broadcastIterator.next();
+                                    System.out.println("Sending broadcast datagram packet to " + broadcast);
+                                    DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, port);
+                                    socket.send(packet);
+                                }
+                            }
+                        }
+                        receivedMessages.add(aPdu);
+                    }
+                }
+            } // end while
+        } // End try
+        catch (IOException e) {
+            System.out.println("Problem with DisExamples.EspduReceiver, see exception trace:");
+            System.out.println(e);
+        }
+    } // end main
+    
+    public static Set<InetAddress> getBroadcastAddresses() {
+        Set<InetAddress> broadcastAddresses = new HashSet<>();
+        Enumeration interfaces;
+
+        try {
+            interfaces = NetworkInterface.getNetworkInterfaces();
+
+            while (interfaces.hasMoreElements()) {
+                NetworkInterface anInterface = (NetworkInterface) interfaces.nextElement();
+
+                if (anInterface.isUp()) {
+                    Iterator iterator = anInterface.getInterfaceAddresses().iterator();
+                    while (iterator.hasNext()) {
+                        InterfaceAddress anAddress = (InterfaceAddress) iterator.next();
+                        if ((anAddress == null || anAddress.getAddress().isLinkLocalAddress())) {
+                            continue;
+                        }
+
+                        //System.out.println("Getting broadcast address for " + anAddress);
+                        InetAddress broadcastAddress = anAddress.getBroadcast();
+                        if (broadcastAddress != null) {
+                            broadcastAddresses.add(broadcastAddress);
+                        }
+                    }
+                }
+            }
+        } catch (SocketException e) {
+            System.out.println("Problem with DisExamples.EspduSender.getBroadcastAddresses(), see exception trace:");
+            System.out.println(e);
+        }
+        return broadcastAddresses;
+    }
+} // end class