NetworkServerUDP: introduce _uniqueID, simplify logging, deserialize using packet...
authorEddie <dev@fun2be.me>
Sat, 6 Jun 2015 09:17:36 +0000 (10:17 +0100)
committerEddie <dev@fun2be.me>
Sat, 6 Jun 2015 09:37:56 +0000 (10:37 +0100)
 * Introduce _uniqueID
 * Simplify logging
 * Use packet length when deserializing
 * No longer update ServiceAddressMap

Introduce _uniqueID. Tag each outgoing NetworkMessage with this
service's unique ID to provide accurate loopback detection in receiver.

Use the super class simplified logging.

Pass the received DatagramPacket length when deserializing
NetworkMessage.

Do not try to update ServiceAddressMap. Leave to the NetworkMessageEventListener
which can access the messages contained within the NetworkMessage wrapper.

src/uk/ac/ntu/n0521366/wsyd/libs/net/NetworkServerUDP.java

index 5763d54..0358b94 100644 (file)
@@ -23,7 +23,6 @@
  */
 package uk.ac.ntu.n0521366.wsyd.libs.net;
 
-import java.text.MessageFormat;
 import java.io.IOException;
 import java.io.ObjectStreamException;
 import java.net.InetSocketAddress;
@@ -55,6 +54,15 @@ public class NetworkServerUDP extends NetworkServerAbstract {
      */
     public static final int UDP_PAYLOAD_SIZE_MAX =  65507;
 
+    /**
+     * Buffer for received Datagram payload.
+     */
+    protected byte[] dataReceive = new byte[UDP_PAYLOAD_SIZE_MAX];
+    /**
+     * Uniquely identifies this sender (in order to detect and ignore loopback messages)
+     */
+    private final int _uniqueID;
+
     /**
      * Thread safe First In, First Out Queue of NetworkMessage objects waiting to be sent.
      * 
@@ -75,6 +83,7 @@ public class NetworkServerUDP extends NetworkServerAbstract {
      */
     public NetworkServerUDP(WSYD_SocketAddress socketAddress, String title, ServiceAddressMap serviceToHostMap, Logger logger) {
         super(socketAddress, title, serviceToHostMap, logger);
+        this._uniqueID = new java.util.Random().nextInt();
     }
 
     /**
@@ -87,7 +96,7 @@ public class NetworkServerUDP extends NetworkServerAbstract {
      * @param serviceToHostMap the map object used for host <> InetSocketAddress lookups
      */
     public NetworkServerUDP(WSYD_SocketAddress socketAddress, String title, ServiceAddressMap serviceToHostMap) {
-        super(socketAddress, title, serviceToHostMap);
+        this(socketAddress, title, serviceToHostMap, null);
     }
 
     /**
@@ -112,7 +121,7 @@ public class NetworkServerUDP extends NetworkServerAbstract {
         _datagramSocket = new DatagramSocket(_socketAddress.getPort(), _socketAddress.getAddress());
         _datagramSocket.setSoTimeout(100); // 1/10th second blocking timeout on receive()
 
-        if (_socketAddress.getPort() == Network.PORTS_EPHEMERAL) {
+        if (_socketAddress.getAddress() == Network.IPv4_WILDCARD || _socketAddress.getPort() == Network.PORTS_EPHEMERAL) {
             // reflect the actual port in use if an ephermal port was requested
             InetSocketAddress actualSA = (InetSocketAddress)_datagramSocket.getLocalSocketAddress();
             _socketAddress.setAddress(actualSA.getAddress());
@@ -142,7 +151,6 @@ public class NetworkServerUDP extends NetworkServerAbstract {
     @Override
     public boolean serverListen() {
         boolean result = false;
-        byte[] dataReceive = new byte[UDP_PAYLOAD_SIZE_MAX];
         DatagramPacket packetReceive = new DatagramPacket(dataReceive, dataReceive.length);
         NetworkMessage messageReceived;
         try {
@@ -155,16 +163,11 @@ public class NetworkServerUDP extends NetworkServerAbstract {
                 throw new SocketTimeoutException("No socket available!");
             
             // packet was received
-            messageReceived = NetworkMessage.deserialize(packetReceive.getData());
+            messageReceived = NetworkMessage.deserialize(packetReceive.getData(), packetReceive.getLength());
             
             // prevent loopbacks
-            if (!messageReceived.getSender().equals(_title)) {
-            
-                // add or update the last-seen time of the Sender host in the known services map
-                ServiceAddressMap.LastSeenHost host = new ServiceAddressMap.LastSeenHost((InetSocketAddress)packetReceive.getSocketAddress());
-                this._serviceToHostMap.put(messageReceived.getSender(), host);
-                log(Level.FINEST, _title, MessageFormat.format("Added \"{0}\" to service map", messageReceived.getSender()));
-
+            if (messageReceived._sendersUniqueID != this._uniqueID) {
+                messageReceived._receivedFrom = new WSYD_SocketAddress((InetSocketAddress)packetReceive.getSocketAddress(), WSYD_SocketAddress.Protocol.UDP);
                 // pass the message to the process() method in the Owner Thread
                 publish(messageReceived);
 
@@ -182,20 +185,8 @@ public class NetworkServerUDP extends NetworkServerAbstract {
                 result = true;
             }
             
-        } catch (ObjectStreamException e) {
-            /* order of these Exception catches is important
-             * Deeper sub-classes must be listed before their super classes
-             */
-            // TODO: serverListen() add ObjectStreamException handler
-            System.err.println("ObjectStreamException");
-
-        } catch (IOException e) {
-            // TODO: serverListen() add IOException handler
-            System.err.println("IOException");
-
-        } catch (ClassNotFoundException e) {
-            // TODO: serverListen() add ClassNotFoundException handler
-            System.err.println("ClassNotFoundException");
+        } catch (IOException ex) {
+            logp(Level.WARNING, "NetworkServerUDP*.serverListen(): ", ex.toString());
         }
 
         return result;
@@ -219,7 +210,9 @@ public class NetworkServerUDP extends NetworkServerAbstract {
             if (host != null) {
                 InetSocketAddress address = host.address;
                 if (address != null) {
-                    message.setSender(_title);
+                    if (message.getSender() == null)
+                        message.setSender(_title);
+                    message._sendersUniqueID = this._uniqueID; // help prevent loopback messages
                     try {
                         byte[] dataSend = NetworkMessage.serialize(message);
                         DatagramPacket packetSend = new DatagramPacket(dataSend, dataSend.length);
@@ -227,26 +220,23 @@ public class NetworkServerUDP extends NetworkServerAbstract {
                         packetSend.setAddress(address.getAddress());
                         packetSend.setPort(address.getPort());
 
-                        // acknowledge receipt
                         this.getSocket().send(packetSend);
-                        log(Level.FINEST, _title,
-                            MessageFormat.format("Sending packet for {0} to {1} ({3}:{4,number,#####}) from {2}",
+                        logp(Level.FINEST, "Sending packet for {0} to {1} ({3}:{4,number,#####}) from {2}",
                                 message.getIntent(),
                                 message.getTarget(),
                                 message.getSender(),
                                 packetSend.getAddress().getHostAddress(),
                                 packetSend.getPort()
-                            )
                         );
 
                         result = true; // successful
                     } catch (IOException e) {
                         // TODO: serverSend() add IOException handler
-                        e.printStackTrace();
+                        logp(Level.SEVERE, "NetworkServerUDP*.serverSend(): {0}", e.toString());
                     }
                 }
             } else {
-                log(Level.WARNING, _title, MessageFormat.format("Unable to send message for \"{0}\" to unknown target \"{1}\"", message.getIntent(), message.getTarget()));
+                logp(Level.WARNING, "Unable to send message for \"{0}\" to unknown target \"{1}\"", message.getIntent(), message.getTarget());
             }
         }
         return result;
@@ -301,8 +291,7 @@ public class NetworkServerUDP extends NetworkServerAbstract {
                 temp = NetworkMessage.clone(message);
                 result = this._sendMessageQueue.add(temp);
             } catch (CloneNotSupportedException e) {
-                // TODO: queueMessage() log CloneNotSupportedException
-                e.printStackTrace();
+                logp(Level.SEVERE, "NetworkServerUDP*.queueMessage() {0}", e.toString());
             }
         }
         return result;