package nxm.sys.inc;

/** Covers the Remote Midas InterFace protocol (RMIF). <br>
    <br>
    The RMIF protocol is a take-off on Java's RMI (Remote Method Invocation).
    <br>
    <br>
    Java's RMI is designed to make objects at a remote site accessible
    as if they are local objects.  A local reference to the remote object is
    created and method calls on the local reference are passed to the
    remote object via a transport layer, usually TCP/IP.  The method name
    and its arguments are serialized, sent to the remote processor, and
    executed.  The optional resulting object is serialized, sent back to
    the local processor and reconstructed in the objects local reference.<br>
    <br>
    The main purpose of the RMIF protocol is to allow NeXtMidas GUI's to control
    Midas applications at remote sites.  While the protocol may be applied to
    other problems, it's primary goal is to minimize link bandwidth for data
    displays and respond robustly to network drop-outs common to real-world
    long-distance multi-hop links.<br>
    <br>
    RMI was not used directly for a number of reasons:
    <ol>
      <li>
        The server side applications are not typically Java based
        (C, C++, and FORTRAN are typical).
      </li>
      <li>
        The standard RMI implementation is layered on TCP, which severely
        limits throughput and robustness over real-world links.
      </li>
      <li>
        Object serialization requires unnecessary over-head and
        data conversions to/from network ordering for data displays.
      </li>
    </ol>
    The RMI reference was kept to make it easier for developers that may have
    experience with Java RMI.  The concepts and methodology were paralleled
    wherever possible.<br>
    <br>
    <br>
    <h2><a id="rmif_packet">RMIF Packets</a></h2>
    <br>
    The current implementation of RMIF is layered on top of UDP.  All routing
    to and from remote objects is handled by the UDP header. There is no
    subrouting within the RMIF protocol.  An RMIF object is defined by a node
    name (or network address) and a port number.<br>
    <br>
    The UDP payload begins with an 8-byte RMIF header. The RMIF protocol uses
    the 8-byte header to, in effect, compress the overhead that would be
    necessary to serialize a method call.  The header bytes (in order) are:
    <table style="margin-left:auto;margin-right:auto;width:80%" border="1">
      <caption style="visibility:hidden">""</caption>
      <tr>
        <th>Byte Number</th>
        <th>Name</th>
        <th>Significance</th>
      </tr>
      <tr>
        <td style="text-align:center;"> 0 </td>
        <td style="text-align:center;"> {@link #FUNC} </td>
        <td>
          Indicates the function that this packet is performing. (The value of
          this field is defined in the <a href="#rmif_functions">RMIF
          Functions</a> section.)
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 1 </td>
        <td style="text-align:center;"> {@link #FLAG} </td>
        <td>
          Indicates the protocol version number and options mask.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 2 </td>
        <td style="text-align:center;"> {@link #INFO} </td>
        <td>
          Indicates the channel number for fast routing of monitored properties.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 3 </td>
        <td style="text-align:center;"> {@link #REP} </td>
        <td>
          Indicates the byte representation (VAX/IEEE/EEEI) that is used for the
          values that are contained in this packet.  By setting this, a machine
          that receives a packet that is the same representation as the sending
          machine does not have to do anything to understand the data.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 4 </td>
        <td style="text-align:center;"> {@link #SEQ} </td>
        <td>
          The sequence number of this packet within a sequence (0-127).  This is
          implemented in order to perform byte ordering.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 5 </td>
        <td style="text-align:center;"> {@link #TRY} </td>
        <td>
          Indicates the number of resends for Reliable packets.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 6 </td>
        <td style="text-align:center;"> {@link #RPT} </td>
        <td>
          Indicates the report sequence number.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 7 </td>
        <td style="text-align:center;"> {@link #ADJ} </td>
        <td>
          Indicates the number of additional bytes that are consumed by header.
          In normal operation of this protocol this will be set to 0.  By
          setting this to a number greater than 0 additional header information
          can be added to the packet without interfering with legacy
          applications.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> 8 </td>
        <td style="text-align:center;"> {@link #DATA} </td>
        <td>
          The normal start of the data section. If the value of the {@link #ADJ}
          byte is zero, then the data of the packet will start at this byte. If
          the value of the {@link #ADJ} byte is non-zero then the first
          <code><i>ADJ</i></code>-bytes of this section are additional header
          information and the data will start at byte number
          <code>8 + <i>ADJ</i></code>.
        </td>
      </tr>
    </table><br>
    <br>
    <h2><a id="rmif_functions">RMIF Functions</a></h2>
    <br>
    The size of the data portion of the payload is the UDP packet size minus the
    8-byte header and the adjunct header if <code>ADJ &gt; 0</code>. <br>
    <br>
    The currently supported functions (or method calls) are:
    <table style="margin-left:auto;margin-right:auto;width:80%" border="1">
      <caption style="visibility:hidden">""</caption>
      <tr>
        <th>Function</th>
        <th>Significance</th>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #GET} </td>
        <td>
          Requests the value of a named property.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #RET} </td>
        <td>
          Return the value of a named property in response to a {@link #GET}
          request.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #SET} </td>
        <td>
          Sets the value of a named property.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #ACK} </td>
        <td>
          Acknowledges the receipt of a {@link #SET} request.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #OPEN} </td>
        <td>
          Opens a connection to a remote or a channel to one of its properties.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #OPENED} </td>
        <td>
          Acknowledges the receipt of a {@link #OPEN} request.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #CLOSE} </td>
        <td>
          Closes a connection to a remote or a channel to one of its properties.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #CLOSED} </td>
        <td>
          Acknowledges the receipt of a {@link #CLOSE} request.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #MODIFY} </td>
        <td>
          Modifies a channel connection.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #PING} </td>
        <td>
          Requests keep-alive status. When sending a {@link #PING} packet, the
          packet must not contain any data or this will result in the receiver
          not sending a {@link #PONG}. When a packet of this type is received
          a {@link #PONG} must be sent back to the sender.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #PONG} </td>
        <td>
          Returns the keep-alive status. A packet of this type must be sent in
          response to receiving a {@link #PING}.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #DHDR} </td>
        <td>
          Process the data header.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #DBUF} </td>
        <td>
          Process the data buffer.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #DBUFC} </td>
        <td>
          Process the compressed data buffer.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #DBUFD} </td>
        <td>
          Process the compressed data buffer.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #GETPROP} </td>
        <td>
          Requests the list of published properties.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #RETPROP} </td>
        <td>
          Returns the number of properties or property names.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #RECEIPT} </td>
        <td>
          Acknowledges the receipt of a reliable packet.
        </td>
      </tr>
      <tr>
        <td style="text-align:center;"> {@link #MFTP} </td>
        <td>
          Command for the Midas File Transfer Protocol.
        </td>
      </tr>
    </table><br>
    <br>
    <h2><a id="rmif_using">Using RMIF</a></h2>
    <br>
    The RMI'ish components of the protocol are accomplished with the
    {@link #GET}, {@link #RET}, {@link #SET}, and {@link #ACK} functions.
    The Java language suggests (and JavaBeans require) that public methods
    with names beginning "<code>set</code>" and "<code>get</code>"
    ("<code>is</code>" is substituted for "<code>get</code>" if the return
    type is <code>boolean</code>) to provide a common interface to an object's
    public properties.  To allow combining multiple {@link #SET}'s or
    {@link #GET}'s in a single network packet, the data portion of the
    {@link #GET}/{@link #RET}/{@link #SET}/{@link #ACK} packet is a
    serialized table class.  The key for each table entry is the body of the
    method name, and the value for each key is the method's argument.  For
    example, to call the <code>setFreq(...)</code>, <code>setAmp(...)</code>,
    and <code>setOptions(...)</code> methods on a remote object the data portion
    of a RMIF packet with the <code>FUNC&nbsp;=&nbsp;SET</code> would be:
    <pre>
      {FREQ=1.3E6,AMP=1,OPTIONS={MODE=1,AXIS=NONE}}
    </pre>
    The syntax is all ASCII to allow using off-the-shelf tools or XML parsers
    to monitoring network traffic.  Note that the <code>setOptions(...)</code>
    method has more than one argument.  To do this, the arguments are expressed
    as another table, with each argument being named. This again aids in
    monitoring/debugging.<br>
    <br>
    This takes considerably less bandwidth than RMI's serialization of these
    three function calls.  Remember, TCP socket writes eventually end up in
    TCP packets that have more overhead than UDP.  In addition, when and where
    socket writes get broken into TCP packets is not under the application's
    control.  If network dropouts cause a TCP packet to be dropped, this may
    or may not lie on a functional boundary for a method call making graceful
    recovery difficult.<br>
    <br>
    Another benefit of UDP is throughput.  In TCP, system drivers usually
    limit the number of outstanding packets to <code>12</code>. This means
    that until the remote connection receives the packet and acknowledges
    receipt, the local socket will hold-off outgoing packets. Using typical
    a typical maximum  transfer unit, MTU, of <code>1500&nbsp;bytes</code>
    and roundtrip delay of <code>500&nbsp;ms</code>, we can calculate a
    maximum sustained transfer rate of
    <code>12&nbsp;*&nbsp;1500&nbsp;/&nbsp;.5&nbsp;=&nbsp;36&nbsp;kby/sec</code>.
    <br>
    <br>
    The RMIF protocol implements the reliable portion of the TCP layer in the
    application, allowing the application to set the maximum number of
    outstanding packets (<code>default&nbsp;=&nbsp;12</code>,
    <code>max&nbsp;=&nbsp;128</code>) and which packets to send reliably or
    unreliably. Typically, data display packets are sent unreliably, and all
    others reliably. Unreliable packets set the {@link #SEQ} header byte to
    <code>-1</code>.  Reliable packets have {@link #SEQ} set to a one-up
    counter (<code>0&nbsp;-&nbsp;127</code>) by the sender, along with a retry
    count {@link #TRY}. If the sender does not get a receipt after a tunable
    tolerance plus the last measured round trip delay, it will resend the
    packet. By combining the reliable and unreliable streams in the same
    socket, we can implement priority schemes that, for instance, favor
    controls over data.<br>
    <br>
    Another benefit of UDP is that it is connectionless. A UDP port on a
    machine is basically a bucket on a node to catch network packets that
    are thrown at it. They can be thrown from anywhere, from any number of
    sources, in any order. Each packet contains the network address and port
    number of who threw the packet, so you can throw something back if called
    for. Then you're done. No opens, no closes. Network problems cannot cause
    connections to hang in an unknown state, because there never is a
    connection. This leaves the timing out and recovery to the application,
    where appropriate tuning may be applied.<br>
    <br>
    Most of the protocol handling will be administered by an RMIF primitive or
    component on each end of the connection.  This primitive should insulate the
    framework from the RMIF protocol and convert the method calls to appropriate
    constructs for that framework.

    @author Jeff Schoen
*/
public interface RmifProtocol {
  /** Indicates that the packet is in binary mode. */
  byte BINARY=1;

  /** Indicates that the packet is in XML mode. */
  byte XML=2;

  /** Indicates that the packet is in ASCII mode. */
  byte ASCII=3;


  /** The identifier indicating that the packet wishes to set the value of a named property.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte SET=101;

  /** The identifier indicating that the packet wishes to get the value of a named property.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte GET=102;

  /** The identifier indicating that the packet is returning the value of a
      named property in response to a {@link #GET} request.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte RET=103;

  /** The identifier indicating that the packet wishes to acknowledges the
      receipt of a {@link #SET} request.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte ACK=104;

  /** The identifier indicating that the packet wishes to open a connection to
      a remote or a channel to one of its properties.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte OPEN=105;

  /** The identifier indicating that the packet wishes to close a connection to
      a remote or a channel to one of its properties.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte CLOSE=106;

  /** The identifier indicating that the packet ???.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte SEND=107;

  /** The identifier indicating that the packet ???.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte RECV=108;

  /** The identifier indicating that the packet requests the keep-alive status.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte PING=109;

  /** The identifier indicating that the packet is returning the keep-alive status.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte PONG=110;

  /** The identifier indicating that the packet requests processing of the data header.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DHDR=111;

  /** The identifier indicating that the packet requests processing of the data buffer.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DBUF=112;

  /** The identifier indicating that the packet ???.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte ADDR=113;

  /** The identifier indicating that the packet wishes to modifies a channel
      connection.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte MODIFY=114;

  /** The identifier indicating that the packet acknowledges the receipt of an
      {@link #OPEN} request.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte OPENED=115;

  /** The identifier indicating that the packet acknowledges the receipt of an
      {@link #CLOSE} request.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte CLOSED=116;

  /** The identifier indicating that the packet requests processing of the
      compressed data buffer.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DBUFC=117;

  /** The identifier indicating that the packet requests processing of the
      compressed data buffer.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DBUFD=118;

  /** The identifier indicating that the packet requests processing of the ???.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DBUFZ=119;

  /** The identifier indicating that the packet requests processing of the ???.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DBUFX=120;

  /** The identifier indicating that the packet requests the list of published properties.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte GETPROP=121;

  /** The identifier indicating that the packet returns the number of properties
      or property names.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte RETPROP=122;

  /** The identifier indicating that the packet acknowledges the receipt of a reliable packet.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte RECEIPT=123;

  /** The identifier indicating that the packet ???.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte LINKTEST=124;

  /** The identifier indicating that the packet contains a command for the Midas
      File Transfer Protocol.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte MFTP=125;

  /** The identifier indicating that the packet was dropped.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DROPPED=0;

  /** The index of the highest numbered function.  */
  int MAX_FUNCTION_INDEX = 125;

  /** Array of strings for the different function types. The mapping of the
      function enumeration to the array is that if the function is DROPPED
      then its the 0 element, otherwise its the function name minus 100.

      The principal use of this array is to provide a means to print out the
      packet information in a human readable form. The string "UNSPECIFIED" is
      used for those packet numbers that don't have assigned functions.
      Receipt of a packet of this type is an error.
  */
  String[] FUNCTION_NAMES = {
    "DROPPED", "SET", "GET", "RET", "ACK", "OPEN", "CLOSE",
    "SEND", "RECV", "PING", "PONG", "DHDR", "DBUF",
    "ADDR", "MODIFY", "OPENED", "CLOSED", "DBUFC",
    "DBUFD", "<UNSPECIFIED>", "<UNSPECIFIED>", "GETPROP",
    "RETPROP", "RECEIPT", "LINKTEST"
  };

  /** Specifies the number of distinct functions that are defined in the
      standard RMIF protocol. Care should be taken when adding new functions
      to ensure that this is always equal to the number of available functions.
  */
  int NUM_FUNCTIONS = 25;

  /** Enumeration to indicate all functions.  */
  int ALL_FUNCTIONS = -1;

  /** String that indicates all functions. */
  String ALL_FUNCTIONS_STRING = "ALL";

  /** Enumeration to indicate null functions. */
  int NULL_FUNCTIONS = -2;

  /** The byte-offset into the packet header required to access the function identifier.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF
           Packets</a>
  */
  byte FUNC=0;

  /** The byte-offset into the packet header required to access the flags which
      indicate protocol version number and options mask.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF
           Packets</a>
  */
  byte FLAG=1;

  /** The byte-offset into the packet header required to access the channel
      number for fast routing of monitored properties.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF
           Packets</a>
  */
  byte INFO=2;

  /** The byte-offset into the packet header required to access the
      representation identifier (VAX|IEEE|EEEI).
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF Packets</a>
  */
  byte REP=3;

  /** The byte-offset into the packet header required to access the sequence
      number (for reliable packets).
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF Packets</a>
  */
  byte SEQ=4;

  /** The byte-offset into the packet header required to access the number of
      re-send attempts to make.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF Packets</a>
  */
  byte TRY=5;

  /** The byte-offset into the packet header required to access the report sequence number.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF Packets</a>
  */
  byte RPT=6;

  /** The byte-offset into the packet header required to access the number of bytes in adjunct header.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF Packets</a>
  */
  byte ADJ=7;

  /** The byte-offset into the packet header required to begin accessing the
      data portion of the packet.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_packet">RMIF Packets</a>
  */
  byte DATA=8;

  /** Indicates that the channel type to be opened is a pipe. */
  byte PIPE=1;

  /** Indicates that the channel type to be opened is a result. */
  byte RESULT=2;

  /** Indicates that the channel type to be opened is a key. */
  byte KEY=3;

  /** Indicates that the channel type to be opened is a message. */
  byte MESSAGE=4;

  /** Indicates packet compression mode for raw compression.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DC_RAW=91;

  /** Indicates packet compression mode for band compression.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DC_BAND=92;

  /** Indicates packet compression mode for constant compression.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DC_CONST=93;

  /** Indicates packet compression mode for packet compression.
    @see <a href="../../../nxm/sys/inc/RmifProtocol.html#rmif_functions">RMIF Functions</a>
  */
  byte DC_PACK=94;

  /** Indicates that RDP should be used to ensure packet reliability. */
  byte RDP=0;

  /** Indicates that UDP should be used to ensure packet reliability. */
  byte UDP=1;
}
