*/
package uk.ac.ntu.n0521366.wsyd.libs.net;
-import java.text.MessageFormat;
import java.io.IOException;
import java.io.ObjectStreamException;
import java.net.InetSocketAddress;
*/
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.
*
*/
public NetworkServerUDP(WSYD_SocketAddress socketAddress, String title, ServiceAddressMap serviceToHostMap, Logger logger) {
super(socketAddress, title, serviceToHostMap, logger);
+ this._uniqueID = new java.util.Random().nextInt();
}
/**
* @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);
}
/**
_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());
@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 {
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);
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;
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);
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;
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;