From fa8350833707afc82175dc6a119b653e543a489e Mon Sep 17 00:00:00 2001 From: Don Brutzman <brutzman@nps.edu> Date: Sun, 15 Nov 2020 15:58:13 -0800 Subject: [PATCH] added javadoc to clear warnings --- .../dis7/examples/AlphabeticalPduSender.java | 8 + .../EntityStateEntityIdExampleUse.java | 6 +- .../moves/dis7/examples/EspduReceiver.java | 3 + .../moves/dis7/examples/EspduReceiverNIO.java | 3 + .../nps/moves/dis7/examples/EspduSender.java | 9 +- .../moves/dis7/examples/EspduSenderNIO.java | 3 + .../moves/dis7/examples/PduListenerSaver.java | 3 + .../moves/dis7/examples/PduReaderPlayer.java | 3 + .../dis7/examples/ThreadedNetExample.java | 3 + .../nps/moves/dis7/examples/package-info.java | 6 + .../dis7/utilities/CoordinateConversions.java | 2 + .../DisThreadedNetworkInterface.java | 847 +++++++++--------- ...TrialDisMulticastNetworkingDeprecated.java | 11 +- .../moves/dis7/utilities/package-info.java | 6 + .../dis7/utilities/stream/PduPlayer.java | 19 +- .../dis7/utilities/stream/PduRecorder.java | 8 +- .../dis7/utilities/stream/X3dCoordinates.java | 24 + .../stream/X3dCreateInterpolators.java | 2 + .../dis7/utilities/stream/package-info.java | 6 + src/edu/nps/moves/spatial/package-info.java | 6 + 20 files changed, 557 insertions(+), 421 deletions(-) create mode 100644 src/edu/nps/moves/dis7/examples/package-info.java create mode 100644 src/edu/nps/moves/dis7/utilities/package-info.java create mode 100644 src/edu/nps/moves/dis7/utilities/stream/package-info.java create mode 100644 src/edu/nps/moves/spatial/package-info.java diff --git a/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java b/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java index 985b1da260..c7ad7ce61b 100644 --- a/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java +++ b/src/edu/nps/moves/dis7/examples/AlphabeticalPduSender.java @@ -31,6 +31,10 @@ public class AlphabeticalPduSender private int port; InetAddress multicastAddress; + /** Constructor + * @param port socket port number + * @param multicast multicast address + */ public AlphabeticalPduSender(int port, String multicast) { try { @@ -45,6 +49,7 @@ public class AlphabeticalPduSender } } + /** Invocable run method for this object */ public void run() { try { @@ -323,6 +328,9 @@ public class AlphabeticalPduSender } } + /** Command-line invocation (CLI) + * @param args command-line arguments + */ public static void main(String args[]) { AlphabeticalPduSender sender; diff --git a/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java b/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java index 6cab74715c..4463022f71 100644 --- a/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java +++ b/src/edu/nps/moves/dis7/examples/EntityStateEntityIdExampleUse.java @@ -126,7 +126,11 @@ public class EntityStateEntityIdExampleUse // Do something here with the pdu you received System.out.println("Received "+pdu.getClass().getSimpleName()); } - + + /** Command-line invocation (CLI) + * @param args command-line arguments + * @throws java.lang.Exception if fails + */ public static void main(String[] args) throws Exception { EntityStateEntityIdExampleUse.exampleUse(); // run example showing use diff --git a/src/edu/nps/moves/dis7/examples/EspduReceiver.java b/src/edu/nps/moves/dis7/examples/EspduReceiver.java index ec05a3ad1d..60c4a61bf2 100644 --- a/src/edu/nps/moves/dis7/examples/EspduReceiver.java +++ b/src/edu/nps/moves/dis7/examples/EspduReceiver.java @@ -28,6 +28,9 @@ import java.util.List; */ public class EspduReceiver { + /** Command-line invocation (CLI) + * @param args command-line arguments + */ public static void main(String args[]) { MulticastSocket socket; diff --git a/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java b/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java index 307e80d2b4..c1a6c0df09 100644 --- a/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java +++ b/src/edu/nps/moves/dis7/examples/EspduReceiverNIO.java @@ -21,6 +21,9 @@ import java.net.MulticastSocket; */ public class EspduReceiverNIO { + /** Command-line invocation (CLI) + * @param args command-line arguments + */ public static void main(String args[]) { MulticastSocket socket; diff --git a/src/edu/nps/moves/dis7/examples/EspduSender.java b/src/edu/nps/moves/dis7/examples/EspduSender.java index 2acf953010..da12f792fa 100644 --- a/src/edu/nps/moves/dis7/examples/EspduSender.java +++ b/src/edu/nps/moves/dis7/examples/EspduSender.java @@ -22,11 +22,18 @@ import java.util.*; */ public class EspduSender { + /** default value avoids unterminated zombie senders */ public static final int NUMBER_TO_SEND = 5000; + /** TCP/IP network modes */ public enum NetworkMode { - UNICAST, MULTICAST, BROADCAST + /** unicast socket */ + UNICAST, + /** multicast socket */ + MULTICAST, + /** broadcast socket */ + BROADCAST }; /** diff --git a/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java b/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java index b986118ad8..20ab58b793 100644 --- a/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java +++ b/src/edu/nps/moves/dis7/examples/EspduSenderNIO.java @@ -24,6 +24,9 @@ import java.net.MulticastSocket; */ public class EspduSenderNIO { + /** Command-line invocation (CLI) + * @param args command-line arguments + */ public static void main(String args[]) { MulticastSocket socket; diff --git a/src/edu/nps/moves/dis7/examples/PduListenerSaver.java b/src/edu/nps/moves/dis7/examples/PduListenerSaver.java index 38dc5134d9..9fffe28a41 100644 --- a/src/edu/nps/moves/dis7/examples/PduListenerSaver.java +++ b/src/edu/nps/moves/dis7/examples/PduListenerSaver.java @@ -28,6 +28,9 @@ public class PduListenerSaver PAUSED; } + /** Command-line invocation (CLI) + * @param args command-line arguments + */ public static void main(String[] args) { String outputDirectoryPath = DEFAULT_OUTPUT_DIRECTORY; diff --git a/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java b/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java index 9525e97c4b..28a8d2eaff 100644 --- a/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java +++ b/src/edu/nps/moves/dis7/examples/PduReaderPlayer.java @@ -29,6 +29,9 @@ public class PduReaderPlayer PAUSED; } + /** Command-line invocation (CLI) + * @param args command-line arguments + */ public static void main(String[] args) { String outDir = DEFAULT_OUTPUTDIR; diff --git a/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java b/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java index b2b3975122..ed8315a1e6 100644 --- a/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java +++ b/src/edu/nps/moves/dis7/examples/ThreadedNetExample.java @@ -20,6 +20,9 @@ import edu.nps.moves.dis7.utilities.PduFactory; */ public class ThreadedNetExample { + /** Command-line invocation (CLI) + * @param args command-line arguments + */ public static void main(String[] args) { // Create an instance of DisThreadedNetworkInterface using default port 3000, mcast 225.4.5.6, use other constructor to specific port and ip diff --git a/src/edu/nps/moves/dis7/examples/package-info.java b/src/edu/nps/moves/dis7/examples/package-info.java new file mode 100644 index 0000000000..8421454dce --- /dev/null +++ b/src/edu/nps/moves/dis7/examples/package-info.java @@ -0,0 +1,6 @@ +/** + * Example classes using edu.nps.moves.dis7 library. + */ +// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java + +package edu.nps.moves.dis7.examples; diff --git a/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java b/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java index 4ed7996cb6..f13f050a77 100644 --- a/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java +++ b/src/edu/nps/moves/dis7/utilities/CoordinateConversions.java @@ -12,7 +12,9 @@ package edu.nps.moves.dis7.utilities; */ public class CoordinateConversions { + /** conversion factor */ public static final double RADIANS_TO_DEGREES = 180.0/Math.PI; + /** conversion factor */ public static final double DEGREES_TO_RADIANS = Math.PI/180.0; private CoordinateConversions() diff --git a/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java b/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java index 3d6f1c9df0..091c9933b1 100644 --- a/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java +++ b/src/edu/nps/moves/dis7/utilities/DisThreadedNetworkInterface.java @@ -1,407 +1,440 @@ -/** - * Copyright (c) 2008-2020, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. - * This work is provided under a BSD open-source license, see project license.html and license.txt - */ -package edu.nps.moves.dis7.utilities; - -import edu.nps.moves.dis7.pdus.Pdu; -import edu.nps.moves.dis7.pdus.DisTime; -import edu.nps.moves.dis7.enumerations.DISPDUType; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; - -import java.io.IOException; -import java.net.*; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * This is a thread-safe, multicast DIS network interface class. - * - * @author Mike Bailey, jmbailey@nps.edu - * @since Jul 29, 2019 - */ -public class DisThreadedNetworkInterface -{ - public static String DEFAULT_MULTICAST_ADDRESS = "225.4.5.6"; - public static int DEFAULT_DIS_PORT = 3000; - - private static final String TRACE_PREFIX = "[" + DisThreadedNetworkInterface.class.getName() + "] "; - private boolean verbose = true; - - /** Pdu listener interface */ - public interface PduListener - { - void incomingPdu(Pdu pdu); - } - - /** Raw pdu listener class and interface */ - public interface RawPduListener - { - void incomingPdu(ByteArrayBufferAndLength bAndL); - } - - /** - * Stores data for further processing - */ - public class ByteArrayBufferAndLength - { - public byte[] bufferByteArray; - public int length; - - /** - * Default constructor for data storage - * @param bufferByteArray the data buffer to store - * @param length the length of the data buffer - */ - public ByteArrayBufferAndLength(byte[] bufferByteArray, int length) - { - this.bufferByteArray = bufferByteArray; - this.length = length; - } - } - - /************ Begin class ***************/ - - /** MTU 8192: TODO this has actually been superseded by a larger buffer size, but good enough for now */ - public static final int MAX_DIS_PDU_SIZE = 8192; - - /** MTU 1500: size of an Ethernet frame, common value to avoid packet segmentation */ - public static final int MAX_TRANSMISSION_UNIT_SIZE = 1500; - - private int disPort; - private String multicastAddress; - private boolean killed = false; - - private InetAddress inetAddress; - private InetSocketAddress inetSocket; - private NetworkInterface networkInterface; - private DatagramSocket socket = null; - - /** - * Default constructor using default port 3000 and multicast address 225.4.5.6 - */ - public DisThreadedNetworkInterface() - { - this(DEFAULT_MULTICAST_ADDRESS, DEFAULT_DIS_PORT); - } - - /** - * Constructor - * @param multicastGroup the multicast group address to utilize - * @param port the multicast port to utilize - */ - public DisThreadedNetworkInterface(String multicastGroup, int port) - { - disPort = port; - multicastAddress = multicastGroup; - try { - inetAddress = InetAddress.getByName(multicastAddress); - } catch (UnknownHostException ex) { - Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex); - } - inetSocket = new InetSocketAddress(inetAddress, disPort); - networkInterface = findIpv4Interface(); - init(); - } - - /* *********** queues and lists and public methods ************** */ - private final List<PduListener> everyTypeListeners = new ArrayList<>(); - private final Map<DISPDUType, List<PduListener>> typeListeners = new HashMap<>(); - private final List<RawPduListener> rawListeners = new ArrayList<>(); - private final LinkedBlockingQueue<Pdu> pdus2send = new LinkedBlockingQueue<>(); - - /** - * Add a listener to accept only pdus of a given type - * @param lis listener instance implementing the RawPduListener interface - * @param typ Pdu type - */ - public void addListener(PduListener lis, DISPDUType typ) - { - if (typ == null) - addListener(lis); - else { - List<PduListener> arLis = typeListeners.get(typ); - if (arLis == null) { - arLis = new ArrayList<>(); - typeListeners.put(typ, arLis); - } - arLis.add(lis); - } - } - - /** - * Add a listener to accept all pdu types - * @param lis listener instance implementing the RawPduListener interface - */ - public void addListener(PduListener lis) - { - everyTypeListeners.add(lis); - } - - /** - * Remove previously added listener - * @param lis listener instance implementing the RawPduListener interface - */ - public void removeListener(PduListener lis) - { - everyTypeListeners.remove(lis); - - typeListeners.entrySet().forEach(entry -> { - List<PduListener> arLis = entry.getValue(); - if (arLis.contains(lis)) - arLis.remove(lis); - }); - } - - /** - * Add a listener to accept pdus of all types in the form of a byte array - * @param lis listener instance implementing the RawPduListener interface - */ - public void addRawListener(RawPduListener lis) - { - rawListeners.add(lis); - } - - /** - * Remove previously added raw listener - * @param lis listener instance implementing the RawPduListener interface - */ - public void removeRawListener(RawPduListener lis) - { - rawListeners.remove(lis); - } - - public int getDisPort() - { - return disPort; - } - - public String getMcastGroup() - { - return multicastAddress; - } - - /** - * Send the given pdu to the network using the ip and port given to the constructor - * @param pdu the pdu to send - */ - public void send(Pdu pdu) - { - pdus2send.add(pdu); - } - - /* *************** networking i/o ************* */ - private PduFactory pduFactory = new PduFactory(); - - private Thread sender; - private Thread receiver; - - private void init() - { - receiver = new Thread(receiveThread, "DisThreadedNetIF receive thread"); - receiver.setDaemon(true); - receiver.setPriority(Thread.NORM_PRIORITY); - receiver.start(); - - sender = new Thread(sendThread, "DisThreadedNetIF send thread"); - sender.setDaemon(true); - sender.setPriority(Thread.NORM_PRIORITY); - sender.start(); - } - - private Runnable receiveThread = () -> { - - int counter = 0; - - // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now - // The raw listeners will strip off any extra padding and process what is - // required - ByteBuffer byteBuffer = ByteBuffer.allocate(MAX_TRANSMISSION_UNIT_SIZE); - DatagramPacket packet = new DatagramPacket(byteBuffer.array(), byteBuffer.capacity()); - Pdu pdu; - - while (!killed) { // keep trying on error - - // If something trips up with the socket, this thread will attempt to - // re-establish for both send/receive threads - try { - - // The initial value of the SO_BROADCAST socket option is FALSE - socket = new MulticastSocket(getDisPort()); - ((MulticastSocket)socket).joinGroup(inetSocket, networkInterface); - - while (!killed) { - - socket.receive(packet); // blocks here waiting for next DIS pdu to be received on multicast IP and specified port - toRawListeners(packet.getData(), packet.getLength()); - - pdu = pduFactory.createPdu(byteBuffer); - - if (pdu != null) - { - counter++; // TODO experimental, add to generator as a commented-out diagnostic; consider adding diagnostic mode - if (isVerbose()) - { - System.out.println(TRACE_PREFIX + counter + ". received " + pdu.getPduType().toString() - + " (timestamp " + DisTime.timeStampToString(pdu.getTimestamp()) - + ", size " + pdu.getMarshalledSize() + " bytes)"); - System.out.flush(); - } - toListeners(pdu); - } - byteBuffer.clear(); - } - } - catch (IOException ex) { - System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF receive thread: " + ex.getLocalizedMessage()); - System.err.println(TRACE_PREFIX + "Retrying new socket in 1 second"); - } - finally { - if (socket != null && !socket.isClosed()) { - try { - ((MulticastSocket)socket).leaveGroup(inetSocket, networkInterface); - } catch (IOException ex) { - Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex); - } - socket.close(); - socket = null; - } - } -// if (!killed) -// sleep(250); - } - }; - - private final Runnable sendThread = () -> { - - Pdu pdu; - - // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now - ByteArrayOutputStream baos = new ByteArrayOutputStream(MAX_TRANSMISSION_UNIT_SIZE); - DataOutputStream dos = new DataOutputStream(baos); - DatagramPacket packet = new DatagramPacket(baos.toByteArray(), baos.size(), inetSocket); - - while (!killed) { // keep trying on error - try { - while (!killed) { - pdu = pdus2send.take(); - - pdu.marshal(dos); - packet.setData(baos.toByteArray()); - socket.send(packet); - - dos.flush(); // immediately force pdu write - baos.reset(); - } - } - catch (Exception ex) - { - System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF send thread: " + ex.getLocalizedMessage()); - } - } - try { - dos.close(); - } catch (IOException e) {} - }; - - private void toListeners(Pdu pdu) { - if (everyTypeListeners.isEmpty()) { - return; - } - - if (pdu != null) { - everyTypeListeners.forEach(lis -> lis.incomingPdu(pdu)); - - if (typeListeners.isEmpty()) { - return; - } - - List<PduListener> arLis = typeListeners.get(pdu.getPduType()); - if (arLis != null) { - arLis.forEach(lis -> lis.incomingPdu(pdu)); - } - } - } - - private void toRawListeners(byte[] data, int len) - { - if(rawListeners.isEmpty()) - return; - - ByteArrayBufferAndLength bl = new ByteArrayBufferAndLength(data, len); - rawListeners.forEach(lis->lis.incomingPdu(bl)); - } - - public void kill() - { - killed = true; - } - - private void sleep(long ms) - { - try { - Thread.sleep(ms); - } - catch (InterruptedException ex) {} - } - - /** - * Find proper IPV4 interface - * - * @return a network interface to use to join a multicast group - */ - public static NetworkInterface findIpv4Interface() { - try { - Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); - NetworkInterface nif; - Enumeration<InetAddress> addresses; - InetAddress addr; - - while (ifaces != null && ifaces.hasMoreElements()) { - nif = ifaces.nextElement(); - if (nif.isUp()) { - addresses = nif.getInetAddresses(); - while (addresses.hasMoreElements()) { - addr = addresses.nextElement(); - if (addr instanceof Inet4Address && !addr.isLoopbackAddress() && !addr.isLinkLocalAddress()) - { - System.out.println(TRACE_PREFIX + "Using network interface " + nif.getDisplayName()); - return nif; - } - } - } - } - } catch (SocketException ex) { - Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex); - } - return null; - } - - /** - * @return the verbose - */ - public boolean isVerbose() - { - return verbose; - } - - /** - * @param verbose the verbose to set - */ - public void setVerbose(boolean verbose) - { - this.verbose = verbose; - } - - /** - * @param disPort the disPort value to set - */ - public void setDisPort(int disPort) - { - this.disPort = disPort; - } -} +/** + * Copyright (c) 2008-2020, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.utilities; + +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.DisTime; +import edu.nps.moves.dis7.enumerations.DISPDUType; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; + +import java.io.IOException; +import java.net.*; +import java.nio.ByteBuffer; +import java.util.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This is a thread-safe, multicast DIS network interface class. + * + * @author Mike Bailey, jmbailey@nps.edu + * @since Jul 29, 2019 + */ +public class DisThreadedNetworkInterface +{ + /** Default value */ + public static String DEFAULT_MULTICAST_ADDRESS = "225.4.5.6"; + + /** Default value */ + public static int DEFAULT_DIS_PORT = 3000; + + private static final String TRACE_PREFIX = "[" + DisThreadedNetworkInterface.class.getName() + "] "; + private boolean verbose = true; + private boolean verboseIncludesTimestamp = false; + + /** Pdu listener interface */ + public interface PduListener + { + /** Callback method + * @param pdu received pdu*/ + void incomingPdu(Pdu pdu); + } + + /** Raw pdu listener class and interface */ + public interface RawPduListener + { + /** Callback method + * @param bAndL exposed buffer to receive incoming pdu*/ + void incomingPdu(ByteArrayBufferAndLength bAndL); + } + + /** + * Stores data for further processing + */ + public class ByteArrayBufferAndLength + { + /** Active ByteArray buffer */ + public byte[] bufferByteArray; + /** Active ByteArray buffer length */ + public int length; + + /** + * Default constructor for data storage + * @param bufferByteArray the data buffer to store + * @param length the length of the data buffer + */ + public ByteArrayBufferAndLength(byte[] bufferByteArray, int length) + { + this.bufferByteArray = bufferByteArray; + this.length = length; + } + } + + /************ Begin class ***************/ + + /** MTU 8192: TODO this has actually been superseded by a larger buffer size, but good enough for now */ + public static final int MAX_DIS_PDU_SIZE = 8192; + + /** MTU 1500: size of an Ethernet frame, common value to avoid packet segmentation */ + public static final int MAX_TRANSMISSION_UNIT_SIZE = 1500; + + private int disPort; + private String multicastAddress; + private boolean killed = false; + + private InetAddress inetAddress; + private InetSocketAddress inetSocket; + private NetworkInterface networkInterface; + private DatagramSocket socket = null; + + /** + * Default constructor using default port 3000 and multicast address 225.4.5.6 + */ + public DisThreadedNetworkInterface() + { + this(DEFAULT_MULTICAST_ADDRESS, DEFAULT_DIS_PORT); + } + + /** + * Constructor + * @param multicastGroup the multicast group address to utilize + * @param port the multicast port to utilize + */ + public DisThreadedNetworkInterface(String multicastGroup, int port) + { + disPort = port; + multicastAddress = multicastGroup; + try { + inetAddress = InetAddress.getByName(multicastAddress); + } catch (UnknownHostException ex) { + Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex); + } + inetSocket = new InetSocketAddress(inetAddress, disPort); + networkInterface = findIpv4Interface(); + init(); + } + + /* *********** queues and lists and public methods ************** */ + private final List<PduListener> everyTypeListeners = new ArrayList<>(); + private final Map<DISPDUType, List<PduListener>> typeListeners = new HashMap<>(); + private final List<RawPduListener> rawListeners = new ArrayList<>(); + private final LinkedBlockingQueue<Pdu> pdus2send = new LinkedBlockingQueue<>(); + + /** + * Add a listener to accept only pdus of a given type + * @param lis listener instance implementing the RawPduListener interface + * @param typ Pdu type + */ + public void addListener(PduListener lis, DISPDUType typ) + { + if (typ == null) + addListener(lis); + else { + List<PduListener> arLis = typeListeners.get(typ); + if (arLis == null) { + arLis = new ArrayList<>(); + typeListeners.put(typ, arLis); + } + arLis.add(lis); + } + } + + /** + * Add a listener to accept all pdu types + * @param lis listener instance implementing the RawPduListener interface + */ + public void addListener(PduListener lis) + { + everyTypeListeners.add(lis); + } + + /** + * Remove previously added listener + * @param lis listener instance implementing the RawPduListener interface + */ + public void removeListener(PduListener lis) + { + everyTypeListeners.remove(lis); + + typeListeners.entrySet().forEach(entry -> { + List<PduListener> arLis = entry.getValue(); + if (arLis.contains(lis)) + arLis.remove(lis); + }); + } + + /** + * Add a listener to accept pdus of all types in the form of a byte array + * @param lis listener instance implementing the RawPduListener interface + */ + public void addRawListener(RawPduListener lis) + { + rawListeners.add(lis); + } + + /** + * Remove previously added raw listener + * @param lis listener instance implementing the RawPduListener interface + */ + public void removeRawListener(RawPduListener lis) + { + rawListeners.remove(lis); + } + + /** Get current port value + * @return current port value */ + public int getDisPort() + { + return disPort; + } + + /** Get current multicast address value + * @return current multicast address value */ + public String getMcastGroup() + { + return multicastAddress; + } + + /** + * Send the given pdu to the network using the ip and port given to the constructor + * @param pdu the pdu to send + */ + public void send(Pdu pdu) + { + pdus2send.add(pdu); + } + + /* *************** networking i/o ************* */ + private PduFactory pduFactory = new PduFactory(); + + private Thread sender; + private Thread receiver; + + private void init() + { + receiver = new Thread(receiveThread, "DisThreadedNetIF receive thread"); + receiver.setDaemon(true); + receiver.setPriority(Thread.NORM_PRIORITY); + receiver.start(); + + sender = new Thread(sendThread, "DisThreadedNetIF send thread"); + sender.setDaemon(true); + sender.setPriority(Thread.NORM_PRIORITY); + sender.start(); + } + + private Runnable receiveThread = () -> { + + int counter = 0; + + // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now + // The raw listeners will strip off any extra padding and process what is + // required + ByteBuffer byteBuffer = ByteBuffer.allocate(MAX_TRANSMISSION_UNIT_SIZE); + DatagramPacket packet = new DatagramPacket(byteBuffer.array(), byteBuffer.capacity()); + Pdu pdu; + + while (!killed) { // keep trying on error + + // If something trips up with the socket, this thread will attempt to + // re-establish for both send/receive threads + try { + // The initial value of the SO_BROADCAST socket option is FALSE + socket = new MulticastSocket(getDisPort()); + ((MulticastSocket)socket).joinGroup(inetSocket, networkInterface); + + while (!killed) { + + socket.receive(packet); // blocks here waiting for next DIS pdu to be received on multicast IP and specified port + toRawListeners(packet.getData(), packet.getLength()); + + pdu = pduFactory.createPdu(byteBuffer); + + if (pdu != null) + { + counter++; // TODO experimental, add to generator as a commented-out diagnostic; consider adding diagnostic mode + if (isVerbose()) + { + String message = TRACE_PREFIX + counter + ". received " + pdu.getPduType().toString(); + if (isVerboseIncludesTimestamp()) + message += " (timestamp " + DisTime.timeStampToString(pdu.getTimestamp()); + message +=", size " + pdu.getMarshalledSize() + " bytes)"; + System.out.println(message); + System.out.flush(); + } + toListeners(pdu); + } + byteBuffer.clear(); + } + } + catch (IOException ex) { + System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF receive thread: " + ex.getLocalizedMessage()); + System.err.println(TRACE_PREFIX + "Retrying new socket in 1 second"); + } + finally { + if (socket != null && !socket.isClosed()) { + try { + ((MulticastSocket)socket).leaveGroup(inetSocket, networkInterface); + } catch (IOException ex) { + Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex); + } + socket.close(); + socket = null; + } + } +// if (!killed) +// sleep(250); + } + }; + + private final Runnable sendThread = () -> { + + Pdu pdu; + + // The capacity could go up to MAX_DIS_PDU_SIZE, but this should be good for now + ByteArrayOutputStream baos = new ByteArrayOutputStream(MAX_TRANSMISSION_UNIT_SIZE); + DataOutputStream dos = new DataOutputStream(baos); + DatagramPacket packet = new DatagramPacket(baos.toByteArray(), baos.size(), inetSocket); + + while (!killed) { // keep trying on error + try { + while (!killed) { + pdu = pdus2send.take(); + + pdu.marshal(dos); + packet.setData(baos.toByteArray()); + socket.send(packet); + + dos.flush(); // immediately force pdu write + baos.reset(); + } + } + catch (Exception ex) + { + System.err.println(TRACE_PREFIX + "Exception in DisThreadedNetIF send thread: " + ex.getLocalizedMessage()); + } + } + try { + dos.close(); + } catch (IOException e) {} + }; + + private void toListeners(Pdu pdu) { + if (everyTypeListeners.isEmpty()) { + return; + } + + if (pdu != null) { + everyTypeListeners.forEach(lis -> lis.incomingPdu(pdu)); + + if (typeListeners.isEmpty()) { + return; + } + + List<PduListener> arLis = typeListeners.get(pdu.getPduType()); + if (arLis != null) { + arLis.forEach(lis -> lis.incomingPdu(pdu)); + } + } + } + + private void toRawListeners(byte[] data, int len) + { + if(rawListeners.isEmpty()) + return; + + ByteArrayBufferAndLength bl = new ByteArrayBufferAndLength(data, len); + rawListeners.forEach(lis->lis.incomingPdu(bl)); + } + + /** Terminate the instance */ + public void kill() + { + killed = true; + } + + /** Thread sleep for indicated interval */ + private void sleep(long ms) + { + try { + Thread.sleep(ms); + } + catch (InterruptedException ex) {} + } + + /** + * Find proper IPV4 interface + * + * @return a network interface to use to join a multicast group + */ + public static NetworkInterface findIpv4Interface() { + try { + Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); + NetworkInterface nif; + Enumeration<InetAddress> addresses; + InetAddress addr; + + while (ifaces != null && ifaces.hasMoreElements()) { + nif = ifaces.nextElement(); + if (nif.isUp()) { + addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + addr = addresses.nextElement(); + if (addr instanceof Inet4Address && !addr.isLoopbackAddress() && !addr.isLinkLocalAddress()) + { + System.out.println(TRACE_PREFIX + "Using network interface " + nif.getDisplayName()); + return nif; + } + } + } + } + } catch (SocketException ex) { + Logger.getLogger(DisThreadedNetworkInterface.class.getName()).log(Level.SEVERE, null, ex); + } + return null; + } + + /** + * @return the verbose + */ + public boolean isVerbose() + { + return verbose; + } + + /** + * @param verbose the verbose to set + */ + public void setVerbose(boolean verbose) + { + this.verbose = verbose; + } + + /** + * @return the verboseIncludesTimestamp value + */ + public boolean isVerboseIncludesTimestamp() + { + return verboseIncludesTimestamp; + } + + /** + * @param verboseIncludesTimestamp the value to set + */ + public void setVerboseIncludesTimestamp(boolean verboseIncludesTimestamp) + { + this.verboseIncludesTimestamp = verboseIncludesTimestamp; + } + + /** + * @param disPort the disPort value to set + */ + public void setDisPort(int disPort) + { + this.disPort = disPort; + } +} diff --git a/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java b/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java index ecb8166656..dc5fe9842f 100644 --- a/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java +++ b/src/edu/nps/moves/dis7/utilities/TrialDisMulticastNetworkingDeprecated.java @@ -24,11 +24,13 @@ import java.util.logging.Logger; @Deprecated(since="dis7") public class TrialDisMulticastNetworkingDeprecated { + /** deprecated */ public class ByteArrayBufferAndLength { public byte[] bufferByteArray; public int length; + /* deprecated do not use */ public ByteArrayBufferAndLength(byte[] bufferByteArray, int length) { this.bufferByteArray = bufferByteArray; @@ -46,11 +48,13 @@ public class TrialDisMulticastNetworkingDeprecated private InetSocketAddress group; private NetworkInterface ni; + /* deprecated do not use */ public TrialDisMulticastNetworkingDeprecated() { this(DisThreadedNetworkInterface.DEFAULT_DIS_PORT, DisThreadedNetworkInterface.DEFAULT_MULTICAST_ADDRESS); } + /* deprecated do not use */ public TrialDisMulticastNetworkingDeprecated(int port, String mcastgroup) { DIS_PORT = port; @@ -66,16 +70,19 @@ public class TrialDisMulticastNetworkingDeprecated dos = new DataOutputStream(baos); } + /* deprecated do not use */ public int getPort() { return DIS_PORT; } + /* deprecated do not use */ public String getIp() { return MCAST_GROUP; } + /* deprecated do not use */ public void stop() { if(rsocket != null) { @@ -88,7 +95,8 @@ public class TrialDisMulticastNetworkingDeprecated ssocket = null; } } - + + /* deprecated do not use */ public Pdu receivePdu() throws IOException { PduFactory pduFactory = new PduFactory(); @@ -99,6 +107,7 @@ public class TrialDisMulticastNetworkingDeprecated private MulticastSocket rsocket; byte buffer[]; DatagramPacket packet; + /* deprecated do not use */ public ByteArrayBufferAndLength receiveRawPdu() throws IOException { rsocket = new MulticastSocket(DIS_PORT); diff --git a/src/edu/nps/moves/dis7/utilities/package-info.java b/src/edu/nps/moves/dis7/utilities/package-info.java new file mode 100644 index 0000000000..9cf044a2b9 --- /dev/null +++ b/src/edu/nps/moves/dis7/utilities/package-info.java @@ -0,0 +1,6 @@ +/** + * Utility classes supporting edu.nps.moves.dis7 library. + */ +// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java + +package edu.nps.moves.dis7.utilities; diff --git a/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java b/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java index 921ecd83d7..e83fd6949c 100644 --- a/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java +++ b/src/edu/nps/moves/dis7/utilities/stream/PduPlayer.java @@ -29,6 +29,7 @@ public class PduPlayer { /** PDU listener interface */ public interface RawListener { + /** callback */ void receiveBytes(byte[] ba); } @@ -37,15 +38,15 @@ public class PduPlayer { private int port; private Thread thrd; - static final String ENCODING_BASE64 = "ENCODING_BASE64"; - static final String ENCODING_PLAINTEXT = "ENCODING_PLAINTEXT"; - static final String ENCODING_BINARY = "ENCODING_BINARY"; // TODO likely requires different code path - static final String ENCODING_XML = "ENCODING_XML"; // TODO, repeat Open-DIS version 4 effort - static final String ENCODING_EXI = "ENCODING_EXI"; // TODO, use Exificient or Nagasena libraries - static final String ENCODING_JSON = "ENCODING_JSON"; // TODO, repeat Open-DIS version 4 effort + static final String ENCODING_BASE64 = "ENCODING_BASE64"; + static final String ENCODING_PLAINTEXT = "ENCODING_PLAINTEXT"; + static final String ENCODING_BINARY = "ENCODING_BINARY"; // TODO likely requires different code path + static final String ENCODING_XML = "ENCODING_XML"; // TODO, repeat Open-DIS version 4 effort + static final String ENCODING_EXI = "ENCODING_EXI"; // TODO, use Exificient or Nagasena libraries + static final String ENCODING_JSON = "ENCODING_JSON"; // TODO, repeat Open-DIS version 4 effort + static final String ENCODING_CDIS = "ENCODING_CDIS"; // future work based on new SISO standard static final String ENCODING_MAK_DATA_LOGGER = "ENCODING_MAK_DATA_LOGGER"; // verbose pretty-print. perhaps output only (MAK format itself is binary) static final String ENCODING_WIRESHARK_DATA_LOGGER = "ENCODING_WIRESHARK_DATA_LOGGER"; // - static final String ENCODING_CDIS = "ENCODING_CDIS"; // future work based on new SISO standard private static String pduLogEncoding = ENCODING_PLAINTEXT; // TODO use Java enumerations, generalize/share across library @@ -392,15 +393,17 @@ public class PduPlayer { } return returnValue; } - + /** Start or resume this instance */ public void startResume() { paused = false; } + /** Stop or pause this instance */ public void stopPause() { paused = true; } + /** End operation of this instance */ public void end() { closer(); } diff --git a/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java b/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java index a7d9bb1ce8..f0ab341b95 100644 --- a/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java +++ b/src/edu/nps/moves/dis7/utilities/stream/PduRecorder.java @@ -28,6 +28,7 @@ import org.apache.commons.io.FilenameUtils; */ public class PduRecorder implements PduReceiver { + /** Character sentinel indicating remainder of line is a comment */ public static final String COMMENT_MARKER = "#"; static String outputDirectoryPath = "./pduLog"; @@ -126,17 +127,18 @@ public class PduRecorder implements PduReceiver public static void setPduLogEncoding(String newPduLogEncoding) { pduLogEncoding = newPduLogEncoding; } - + + /** Start or resume this instance */ public void startResume() { running = true; } - + /** Stop or pause this instance */ public void stopPause() { running = false; } - + /** End operation of this instance */ public File end() { running = false; diff --git a/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java b/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java index 9f64f1c298..d83e7966c6 100644 --- a/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java +++ b/src/edu/nps/moves/dis7/utilities/stream/X3dCoordinates.java @@ -38,50 +38,74 @@ public class X3dCoordinates { this.theta = theta; } + /** accessor method for angle of rotation + * @return current value */ public double getPhi() { return phi; } + /** accessor method to set angle of rotation + * @param phi new angle value */ public void setPhi(double phi) { this.phi = phi; } + /** accessor method for angle of rotation + * @return current value */ public double getPsi() { return psi; } + /** accessor method to set angle of rotation + * @param psi new angle value */ public void setPsi(double psi) { this.psi = psi; } + /** accessor method for angle of rotation + * @return current value */ public double getTheta() { return theta; } + /** accessor method to set angle of rotation + * @param theta new angle value */ public void setTheta(double theta) { this.theta = theta; } + /** accessor method to get coordinate x value + * @return current value */ public double getX() { return x; } + /** accessor method to set coordinate x value + * @param x coordinate value to set */ public void setX(double x) { this.x = x; } + /** accessor method to get coordinate y value + * @return current value */ public double getY() { return y; } + /** accessor method to set coordinate y value + * @param y coordinate value to set */ public void setY(double y) { this.y = y; } + /** accessor method to get coordinate z value + * @return current value */ public double getZ() { return z; } + /** accessor method to set coordinate z value + * @param z coordinate value to set */ public void setZ(double z) { this.z = z; } diff --git a/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java b/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java index dc308f2412..3079b02e17 100644 --- a/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java +++ b/src/edu/nps/moves/dis7/utilities/stream/X3dCreateInterpolators.java @@ -35,6 +35,8 @@ public class X3dCreateInterpolators { private NumberFormat coordinateNumberFormat = NumberFormat.getInstance(new Locale("en", "US")); // -------------------- End Variables for Position Interpolator + + /** Default Constructor */ public X3dCreateInterpolators() { //3 significant digits equals milimeter position accuracy and 0.001 radians = 0.0572963266634555‬ degrees diff --git a/src/edu/nps/moves/dis7/utilities/stream/package-info.java b/src/edu/nps/moves/dis7/utilities/stream/package-info.java new file mode 100644 index 0000000000..b1aef3bc3a --- /dev/null +++ b/src/edu/nps/moves/dis7/utilities/stream/package-info.java @@ -0,0 +1,6 @@ +/** + * Streaming utility classes supporting edu.nps.moves.dis7 library. + */ +// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java + +package edu.nps.moves.dis7.utilities.stream; diff --git a/src/edu/nps/moves/spatial/package-info.java b/src/edu/nps/moves/spatial/package-info.java new file mode 100644 index 0000000000..24678d3243 --- /dev/null +++ b/src/edu/nps/moves/spatial/package-info.java @@ -0,0 +1,6 @@ +/** + * Spatial utility classes supporting edu.nps.moves.dis7 library. + */ +// https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java + +package edu.nps.moves.spatial; -- GitLab