/*****************************************************************************/
/* File name: Message.java                                                   */
/* Purpose: to decode a RPC message                                          */
/*                                                                           */
/* Last modified: 27.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*                                                                           */
/* This program is distributed in the hope that it will be useful, but       */
/* WITHOUT ANY WARRANTY; without even the implied warranty of                */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General */
/* Public License for more details.                                          */
/*                                                                           */
/* This software is distributed under the terms                              */
/* of the GNU General Public License as published                            */
/* by the Free Software Foundation; either version 2, or (at your option)    */
/* any later version.                                                        */
/* See file COPYING for your rights (GNU GPL)                                */
/*****************************************************************************/

package rpc;


import java.net.*;
import java.io.*;
import xdr.*;


public
class

Message
{

  private final static String RCSID = "$Header: /d/NFS/rpc/RCS/Message.java,v 1.8 1999/06/27 19:11:07 vklimov Exp $";


  private DatagramPacket rpcMessageUDPPacket = null;
  private byte[] data = null;
  private int currentIndexInData = 0;
  private InetAddress inetAddress = null;
  private int port = 0;


  public

  Message( DatagramPacket rpcMessageUDPPacket )
/*****************************************************************************/
/* Function name: Message                                                    */
/* File name: Message.java                                                   */
/* Purpose: constructor for the Message class                                */
/* Parameters: rpcMessageUDPPacket                                           */
/* Returns:                                                                  */
/* Last modified: 27.05.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* Message */
/*---------------------------------------------------------------------------*/

      this.rpcMessageUDPPacket = rpcMessageUDPPacket;
      data = rpcMessageUDPPacket.getData();
      inetAddress = rpcMessageUDPPacket.getAddress();
      port = rpcMessageUDPPacket.getPort();

    }
/*end of Message*/


  public

  Message( byte[] data )
/*****************************************************************************/
/* Function name: Message                                                    */
/* File name: Message.java                                                   */
/* Purpose: constructor for the Message class                                */
/* Parameters: data                                                          */
/* Returns:                                                                  */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* Message */
/*---------------------------------------------------------------------------*/

      this.data = data;

    }
/*end of Message*/


  public
  long

  getUnsignedInteger()
/*****************************************************************************/
/* Function name: getUnsignedInteger                                         */
/* File name: Message.java                                                   */
/* Purpose: to get a next unsigned integer value from the data byte array    */
/*          in RPC an unsigned integer is defined by XDR as a 32 bit datum   */
/* Parameters:                                                               */
/* Returns: the next unsigned integer value                                  */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      long byteToConvert;
      long unsignedInteger = 0;
                                                    /* getUnsignedInteger */
/*---------------------------------------------------------------------------*/


      for (i=0;i<Constants.XDR_UNSIGNED_INT_LENGTH;i++)
        {
          byteToConvert = (long) data[currentIndexInData+i];
          if (byteToConvert < 0)
            {
              byteToConvert = byteToConvert + 0x100;
            }
          else
            ;
        /*end of if*/

          unsignedInteger = unsignedInteger * 0x100;
          unsignedInteger = unsignedInteger + byteToConvert;

        }
    /*end of for-loop*/

      currentIndexInData += Constants.XDR_UNSIGNED_INT_LENGTH;

      return unsignedInteger;

    }
/*end of getUnsignedInteger*/


  public
  String

  getString()
/*****************************************************************************/
/* Function name: getString                                                  */
/* File name: Message.java                                                   */
/* Purpose: to get a next string datum                                       */
/*          in RPC a string datum is defined by XDR as an unsigned integer   */
/*          containing number of bytes in the string, followed               */
/*          by corresponding number of bytes of the string itself.           */
/*          If the number of bytes is not multiple of four, then the string  */
/*          is padded by additional null bytes on the right to make it       */
/*          multiple of four.                                                */
/* Parameters:                                                               */
/* Returns: the next string                                                  */
/* Last modified: 11.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      long length;
      String result;
      int remainder;
                                                       /* getString */
/*---------------------------------------------------------------------------*/

      length = getUnsignedInteger();

      result = new String( data,
                           currentIndexInData,
                           (int) length        );

      remainder = ( (int) length ) %
        Constants.XDR_UNSIGNED_INT_LENGTH;

      currentIndexInData += ((int) length);

      if (remainder != 0)
        currentIndexInData +=
          (Constants.XDR_UNSIGNED_INT_LENGTH - remainder);
      else
        ;
    /*end of if*/

      return result;

    }
/*end of getString*/


  public
  VariableLengthOpaque

  getXDRVariableLengthOpaque() throws ArrayIndexOutOfBoundsException
/*****************************************************************************/
/* Function name: getXDRVariableLengthOpaque                                 */
/* File name: Message.java                                                   */
/* Purpose: to get a next opaque datum of variable length                    */
/*          in RPC an opaque datum of variable length is defined by XDR      */
/*          as an unsigned integer containing number of bytes in the datum,  */
/*          followed by corresponding number of bytes of the datum itself    */
/* Throws: ArrayIndexOutOfBoundsException                                    */
/* Parameters:                                                               */
/* Returns: the next opaque datum of variable length                         */
/* Last modified: 11.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      long length;
      VariableLengthOpaque variableLengthOpaque;

                                            /* getXDRVariableLengthOpaque */
/*---------------------------------------------------------------------------*/

      length = getUnsignedInteger();

      variableLengthOpaque =
        new VariableLengthOpaque( length );

      for (i=0;i<length;i++)
        {
          variableLengthOpaque.addByte(
            data[currentIndexInData+i]  );
        }
    /*end of for-loop*/

      currentIndexInData += ((int) length);

      return variableLengthOpaque;

    }
/*end of getXDRVariableLengthOpaque*/


  public
  OpaqueAuthentication

  getOpaqueAuthentication() throws ArrayIndexOutOfBoundsException
/*****************************************************************************/
/* Function name: getOpaqueAuthentication                                    */
/* File name: Message.java                                                   */
/* Purpose: to get a next opaque authentication field                        */
/*          in RPC an opaque authentication field is defined                 */
/*          as an 32-bit enumeration containing authentication flavor        */
/*          followed by VariableLengthOpaque                                 */
/* Throws: ArrayIndexOutOfBoundsException                                    */
/* Parameters:                                                               */
/* Returns: the next opaque authentication field object                      */
/* Last modified: 31.05.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      long flavor;
      OpaqueAuthentication opaqueAuthentication;
      VariableLengthOpaque variableLengthOpaque;

                                            /* getOpaqueAuthentication */
/*---------------------------------------------------------------------------*/

      flavor = getUnsignedInteger();

      variableLengthOpaque = getXDRVariableLengthOpaque();

      opaqueAuthentication =
        new OpaqueAuthentication( flavor,
                                  variableLengthOpaque );

      return opaqueAuthentication;

    }
/*end of getOpaqueAuthentication*/


  public
  byte[]

  getUnparsedData()
/*****************************************************************************/
/* Function name: getUnparsedData                                            */
/* File name: Message.java                                                   */
/* Purpose: to return this RPC message UDP packet data, that is not yet      */
/*          parsed in as a byte array                                        */
/* Parameters:                                                               */
/* Returns: the byte array                                                   */
/* Last modified: 02.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i,j;
      int lengthUnparsedData;
      byte[] result;
                                                    /* getUnparsedData */
/*---------------------------------------------------------------------------*/

      lengthUnparsedData =
        data.length -
        currentIndexInData;
      result = new byte[ lengthUnparsedData ];

      for (j=0,i=currentIndexInData;i<data.length;i++,j++)
        {
          result[j] = data[i];
        }
    /*end of for-loop*/

      return result;

    }
/*end of getUnparsedData*/


  public
  byte[]

  getFixedLengthOpaque( int length )

                                        throws ArrayIndexOutOfBoundsException,
                                         ArrayStoreException
/*****************************************************************************/
/* Function name: getFixedLengthOpaque                                       */
/* File name: Message.java                                                   */
/* Purpose: to get an opaque datum repesented in a byte array from the byte  */
/*          array of the message                                             */
/*          in RPC a fixed length opaque datum is defined by XDR             */
/*          as a sequence of n bytes, where n is the length of the datum     */
/*          if it is a multiple of four; if it is not then the datum is      */
/*          padded on the right with from 1 to 3 null bytes to make          */
/*          total length to be multiple of four                              */
/* Parameters: length                                                        */
/* Throws: ArrayIndexOutOfBoundsException                                    */
/*         ArrayStoreException                                               */
/* Returns: the byte array                                                   */
/* Last modified: 16.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      byte[] result;
      int nAdditionalBytes;
      int remainder;
                                                    /* getFixedLengthOpaque */
/*---------------------------------------------------------------------------*/

      result = new byte[ length ];

      System.arraycopy( data, currentIndexInData,
                        result, 0,
                        length                     );

      currentIndexInData += length;

      remainder = length %
        Constants.XDR_UNSIGNED_INT_LENGTH;

      if (remainder != 0)
        {
          nAdditionalBytes =
            Constants.XDR_UNSIGNED_INT_LENGTH -
            remainder;

          currentIndexInData += nAdditionalBytes;

        }
      else
        ;
    /*end of if*/

      return result;

    }
/*end of getFixedLengthOpaque*/


  public
  void

  putString( String stringToPut ) throws ArrayIndexOutOfBoundsException,
                                         ArrayStoreException
/*****************************************************************************/
/* Function name: putString                                                  */
/* File name: Message.java                                                   */
/* Purpose: to put a string into the byte array of the message               */
/*          in RPC a string datum is defined by XDR as an unsigned integer   */
/*          containing number of bytes in the string, followed               */
/*          by corresponding number of bytes of the string itself.           */
/*          If the number of bytes is not multiple of four, then the string  */
/*          is padded by additional null bytes on the right to make it       */
/*          multiple of four.                                                */
/* Throws:  ArrayIndexOutOfBoundsException                                   */
/*          ArrayStoreException                                              */
/* Parameters: stringToPut                                                   */
/* Returns:                                                                  */
/* Last modified: 16.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      int nBytesToAppend;
      byte[] intermediaryByteArray;
      long length;
      int remainder;
                                                       /* putString */
/*---------------------------------------------------------------------------*/

      intermediaryByteArray = stringToPut.getBytes();

      length = (long) intermediaryByteArray.length;

      putUnsignedInteger( length );


      System.arraycopy( intermediaryByteArray, 0,
                        data, currentIndexInData,
                        intermediaryByteArray.length );

      remainder = intermediaryByteArray.length %
        Constants.XDR_UNSIGNED_INT_LENGTH;

      currentIndexInData += intermediaryByteArray.length;

      if (remainder != 0)
        {
          nBytesToAppend =
            Constants.XDR_UNSIGNED_INT_LENGTH -
            remainder;

          for (i=0;i<nBytesToAppend;i++)
            data[currentIndexInData+i] = (byte) 0;
        /*end of for-loop*/

          currentIndexInData += nBytesToAppend;

        }
      else
        ;
    /*end of if*/

    }
/*end of putString*/


  public
  void

  putString( String stringToPut,
             int maxNumberOfBytes ) throws ArrayIndexOutOfBoundsException,
                                           ArrayStoreException
/*****************************************************************************/
/* Function name: putString                                                  */
/* File name: Message.java                                                   */
/* Purpose: to put a string into the byte array of the message               */
/*          in RPC a string datum is defined by XDR as an unsigned integer   */
/*          containing number of bytes in the string, followed               */
/*          by corresponding number of bytes of the string itself.           */
/*          If the number of bytes is not multiple of four, then the string  */
/*          is padded by additional null bytes on the right to make it       */
/*          multiple of four.                                                */
/* Throws:  ArrayIndexOutOfBoundsException                                   */
/*          ArrayStoreException                                              */
/* Parameters: stringToPut                                                   */
/*             maxNumberOfBytes                                              */
/* Returns:                                                                  */
/* Last modified: 22.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      int nBytesToAppend;
      byte[] intermediaryByteArray;
      long length;
      int remainder;
                                                       /* putString */
/*---------------------------------------------------------------------------*/

      intermediaryByteArray = stringToPut.getBytes();

      length = (long) intermediaryByteArray.length;
      if ( (int) length > maxNumberOfBytes )
        length = (long) maxNumberOfBytes;
      else
        ;
    /*end of if*/

      putUnsignedInteger( length );


      System.arraycopy( intermediaryByteArray, 0,
                        data, currentIndexInData,
                        (int) length              );

      remainder = ((int) length) %
        Constants.XDR_UNSIGNED_INT_LENGTH;

      currentIndexInData += length;

      if (remainder != 0)
        {
          nBytesToAppend =
            Constants.XDR_UNSIGNED_INT_LENGTH -
            remainder;

          for (i=0;i<nBytesToAppend;i++)
            data[currentIndexInData+i] = (byte) 0;
        /*end of for-loop*/

          currentIndexInData += nBytesToAppend;

        }
      else
        ;
    /*end of if*/

    }
/*end of putString*/


  public
  int

  lengthXDRString( String stringToPut )
/*****************************************************************************/
/* Function name: lengthXDRString                                            */
/* File name: Message.java                                                   */
/* Purpose: to get the length of the string i.e. number of bytes             */
/*          it will take in the RPC message, including the length prefis     */
/*          in RPC a string datum is defined by XDR as an unsigned integer   */
/*          containing number of bytes in the string, followed               */
/*          by corresponding number of bytes of the string itself.           */
/*          If the number of bytes is not multiple of four, then the string  */
/*          is padded by additional null bytes on the right to make it       */
/*          multiple of four.                                                */
/* Parameters: stringToPut                                                   */
/* Returns: the length                                                       */
/* Last modified: 22.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int nBytesToAppend;
      byte[] intermediaryByteArray;
      int length;
      int remainder;
                                                       /* lengthXDRString */
/*---------------------------------------------------------------------------*/

      intermediaryByteArray = stringToPut.getBytes();

      length = intermediaryByteArray.length;

      remainder = ((int) length) %
        Constants.XDR_UNSIGNED_INT_LENGTH;

      if (remainder != 0)
        {
          nBytesToAppend =
            Constants.XDR_UNSIGNED_INT_LENGTH -
            remainder;

          length += nBytesToAppend;
        }
      else
        ;
    /*end of if*/

      length += Constants.XDR_UNSIGNED_INT_LENGTH;

      return length;

    }
/*end of lengthXDRString*/


  public
  void

  putEmptyVariableLengthOpaque()
/*****************************************************************************/
/* Function name: putEmptyVariableLengthOpaque                               */
/* File name: Message.java                                                   */
/* Purpose: to put an empty opaque datum of variable length into the byte    */
/*          array of the message                                             */
/*          in RPC an opaque datum of variable length is defined by XDR      */
/*          as an unsigned integer containing number of bytes in the datum,  */
/*          followed by corresponding number of bytes of the datum itself    */
/* Parameters:                                                               */
/* Returns:                                                                  */
/* Last modified: 02.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                            /* putEmptyVariableLengthOpaque */
/*---------------------------------------------------------------------------*/

      putUnsignedInteger( (long) 0 );                  /* length = 0 */

    }
/*end of putEmptyVariableLengthOpaque*/


  public
  void

  putEmptyOpaqueAuthentication()
/*****************************************************************************/
/* Function name: putEmptyOpaqueAuthentication                               */
/* File name: Message.java                                                   */
/* Purpose: to put an empty opaque authentication field into the byte        */
/*          array of the message                                             */
/*          in RPC an opaque authentication field is defined                 */
/*          as an 32-bit enumeration containing authentication flavor        */
/*          followed by VariableLengthOpaque                                 */
/* Parameters:                                                               */
/* Returns:                                                                  */
/* Last modified: 02.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      long flavor;
      OpaqueAuthentication opaqueAuthentication;
      VariableLengthOpaque variableLengthOpaque;

                                         /* putEmptyOpaqueAuthentication */
/*---------------------------------------------------------------------------*/

      putUnsignedInteger( Constants.AUTH_NULL );

      putEmptyVariableLengthOpaque();

    }
/*end of putEmptyOpaqueAuthentication*/


  public
  void

  putFixedLengthOpaque( int length,
                        byte[] byteArray )

                                        throws ArrayIndexOutOfBoundsException,
                                         ArrayStoreException
/*****************************************************************************/
/* Function name: putFixedLengthOpaque                                       */
/* File name: Message.java                                                   */
/* Purpose: to put an opaque datum repesented in a byte array into the byte  */
/*          array of the message                                             */
/*          in RPC a fixed length opaque datum is defined by XDR             */
/*          as a sequence of n bytes, where n is the length of the datum     */
/*          if it is a multiple of four; if it is not then the datum is      */
/*          padded on the right with from 1 to 3 null bytes to make          */
/*          total length to be multiple of four                              */
/* Parameters: length                                                        */
/*             byteArray                                                     */
/* Throws: ArrayIndexOutOfBoundsException                                    */
/*         ArrayStoreException                                               */
/* Returns:                                                                  */
/* Last modified: 16.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      int nBytesToAppend;
      int remainder;
                                                    /* putFixedLengthOpaque */
/*---------------------------------------------------------------------------*/

      System.arraycopy( byteArray, 0,
                        data, currentIndexInData,
                        length                     );

      remainder = length %
        Constants.XDR_UNSIGNED_INT_LENGTH;

      currentIndexInData += length;

      if (remainder != 0)
        {
          nBytesToAppend =
            Constants.XDR_UNSIGNED_INT_LENGTH -
            remainder;

          for (i=0;i<nBytesToAppend;i++)
            data[currentIndexInData+i] = (byte) 0;
        /*end of for-loop*/

          currentIndexInData += nBytesToAppend;

        }
      else
        ;
    /*end of if*/

    }
/*end of putFixedLengthOpaque*/


  public
  void

  putByteArray( int length,
                byte[] byteArray )
                                        throws ArrayIndexOutOfBoundsException,
                                         ArrayStoreException
/*****************************************************************************/
/* Function name: putByteArray                                               */
/* File name: Message.java                                                   */
/* Purpose: to put (just copy) a byte array into the data into the byte      */
/*          array of the message                                             */
/* Parameters: length                                                        */
/*             byteArray                                                     */
/* Throws: ArrayIndexOutOfBoundsException                                    */
/*         ArrayStoreException                                               */
/* Returns:                                                                  */
/* Last modified: 27.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      int nBytesToAppend;
                                                    /* putByteArray */
/*---------------------------------------------------------------------------*/

      System.arraycopy( byteArray, 0,
                        data, currentIndexInData,
                        length                     );
      currentIndexInData += length;

    }
/*end of putByteArray*/


  public
  void

  putUnsignedInteger( long integerToPut )
/*****************************************************************************/
/* Function name: putUnsignedInteger                                         */
/* File name: Message.java                                                   */
/* Purpose: to put an unsigned integer repesented in a long into the byte    */
/*          array of the message                                             */
/*          in RPC an unsigned integer is defined by XDR as a 32 bit datum   */
/* Parameters: integerToPut                                                  */
/* Returns:                                                                  */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i,j,k;
      int intIntegerToPut;
      int intermediateInteger;
      int mask;
                                                    /* putUnsignedInteger */
/*---------------------------------------------------------------------------*/

      intIntegerToPut = (int) integerToPut;

      for (i=0,j=Constants.XDR_UNSIGNED_INT_LENGTH;
           i<Constants.XDR_UNSIGNED_INT_LENGTH;
           i++,j--                                  )
        {
          mask = 0xFF;
          for (k=1;k<j;k++)
            mask *= 0x100;
        /*end of for-loop on k*/

          intermediateInteger = intIntegerToPut & mask;
          intermediateInteger =
            intermediateInteger >>> ((j-1)*010);

          data[currentIndexInData+i] =
            (byte) intermediateInteger;
        }
    /*end of for-loop*/

      currentIndexInData += Constants.XDR_UNSIGNED_INT_LENGTH;
    }
/*end of putUnsignedInteger*/


  public
  int

  getCurrentDataLength()
/*****************************************************************************/
/* Function name: getCurrentDataLength                                       */
/* File name: Message.java                                                   */
/* Purpose: to current number of bytes put into the data byte array so far   */
/* Parameters:                                                               */
/* Returns: the data length                                                  */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                    /* getCurrentDataLength */
/*---------------------------------------------------------------------------*/

      return currentIndexInData;

    }
/*end of getCurrentDataLength*/


  public
  String

  toString()
/*****************************************************************************/
/* Function name: toString                                                   */
/* File name: Message.java                                                   */
/* Purpose: to represent this RPC message UDP packet as a string             */
/* Parameters:                                                               */
/* Returns: the string representation                                        */
/* Last modified: 04.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      long   byteToConvert;
      String hexString = null;
      String result = "";
                                                    /* toString */
/*---------------------------------------------------------------------------*/


      result = result +
                    "rpcMessageUDPPacket:\n";
      if (inetAddress != null)
        result = result +
                    "IP address: " +
                    inetAddress.toString();
      else
        ;
    /*end of if*/
      result = result +
                    "\nfrom port: " + port;
      if (data == null)
        {
          result = result +
            "data is null here!";
          return result;                               /* return ! */
        }
      else
        ;
    /*end of if on null*/

      result = result +
                    "\nlength of the data: " +
                    data.length + "\ndata:\n";
      for (i=0;i<data.length;i++)
        {
          byteToConvert = (long) data[i];
          if (byteToConvert < 0)
            {
              byteToConvert = byteToConvert + 0x100;
            }
          else
            ;
        /*end of if*/

          hexString = Integer.toHexString(
                        (int) byteToConvert );
          if ( (hexString.length() % 2) == 1 )
            hexString = "0" + hexString;
          else
            ;
        /*end of if*/

          result = result +
                "0x" + hexString + " ";
        }
    /*end of for-loop*/

      result = result + "\n";

      return result;

    }
/*end of toString*/


  public
  String

  unparsedDataToString()
/*****************************************************************************/
/* Function name: unparsedDataToString                                       */
/* File name: Message.java                                                   */
/* Purpose: to represent this RPC message UDP packet data, that is not yet   */
/*          parsed in as a string                                            */
/* Parameters:                                                               */
/* Returns: the string representation                                        */
/* Last modified: 04.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      long   byteToConvert;
      int lengthUnparsedData;
      String hexString = null;
      String result = "";
                                                    /* unparsedDataToString */
/*---------------------------------------------------------------------------*/

      lengthUnparsedData =
        data.length -
        currentIndexInData;
      result = result +
                    "rpcMessageUDPPacket:\n";
      if (inetAddress != null)
        result = result +
                    "IP address: " +
                    inetAddress.toString();
      else
        ;
    /*end of if*/
      result = result +
                    "\nfrom port: " + port +
                    "\nlength of the yet unparsed data: " +
                    lengthUnparsedData +
                    "\nyet unparsed data:\n";

      if (data == null)
        {
          result = result +
            "data is null here!";
          return result;                               /* return ! */
        }
      else
        ;
    /*end of if on null*/

      for (i=currentIndexInData;i<data.length;i++)
        {
          byteToConvert = (long) data[i];
          if (byteToConvert < 0)
            {
              byteToConvert = byteToConvert + 0x100;
            }
          else
            ;
        /*end of if*/

          hexString = Integer.toHexString(
                        (int) byteToConvert );
          if ( (hexString.length() % 2) == 1 )
            hexString = "0" + hexString;
          else
            ;
        /*end of if*/

          result = result +
                "0x" + hexString + " ";
        }
    /*end of for-loop*/

      result = result + "\n";

      return result;

    }
/*end of unparsedDataToString*/


  public
  DatagramPacket

  getUDPPacket()
/*****************************************************************************/
/* Function name: getUDPPacket                                               */
/* File name: Message.java                                                   */
/* Purpose: to get the UDP packet from which this message data was extracted */
/* Parameters:                                                               */
/* Returns: the DatagramPacket                                               */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                    /* getUDPPacket */
/*---------------------------------------------------------------------------*/

      return rpcMessageUDPPacket;

    }
/*end of getUDPPacket*/


  public
  byte[]

  getData()
/*****************************************************************************/
/* Function name: getData                                                    */
/* File name: Message.java                                                   */
/* Purpose: to get the data byte array                                       */
/* Parameters:                                                               */
/* Returns: the byte array                                                   */
/* Last modified: 18.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                             /* getData */
/*---------------------------------------------------------------------------*/

      return data;

    }
/*end of getData*/


  public
  InetAddress

  getInetAddress()
/*****************************************************************************/
/* Function name: getInetAddress                                             */
/* File name: Message.java                                                   */
/* Purpose: to get the IP address from which this message was sent           */
/* Parameters:                                                               */
/* Returns: the InetAddress                                                  */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                    /* getInetAddress */
/*---------------------------------------------------------------------------*/

      return inetAddress;

    }
/*end of getInetAddress*/


  public
  int

  getPort()
/*****************************************************************************/
/* Function name: getPort                                                    */
/* File name: Message.java                                                   */
/* Purpose: to get the port number from which this message was sent          */
/* Parameters:                                                               */
/* Returns: the port number                                                  */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                    /* getPort */
/*---------------------------------------------------------------------------*/

      return port;

    }
/*end of getPort*/


  public
  static
  void

  main( String[] args )
/*****************************************************************************/
/* Function name: main                                                       */
/* File name: Message.java                                                   */
/* Purpose: main method for the Message class                                */
/* Parameters: agrument strings array                                        */
/* Returns:                                                                  */
/* Last modified: 01.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      Message rpcMessage;

      long result;
      byte[] ibuf;
      int ilength;
      InetAddress iaddr = null;
      int iport;
      DatagramPacket rpcMessageUDPPacket;
                                                          /* main */
/*---------------------------------------------------------------------------*/

      ilength = 56;
      ibuf = new byte[ ilength ];
      ibuf[0] = (byte) 0x38;
      ibuf[1] = (byte) 0x4d;
      ibuf[2] = (byte) 0x1b;
      ibuf[3] = (byte) 0x22;
      ibuf[4] = (byte) 0x00;
      ibuf[5] = (byte) 0x00;
      ibuf[6] = (byte) 0x00;
      ibuf[7] = (byte) 0x00;
      ibuf[8] = (byte) 0x00;
      ibuf[9] = (byte) 0x00;
      ibuf[10] = (byte) 0x00;
      ibuf[11] = (byte) 0x02;
      ibuf[12] = (byte) 0x00;
      ibuf[13] = (byte) 0x01;
      ibuf[14] = (byte) 0x86;
      ibuf[15] = (byte) 0xa0;
      ibuf[16] = (byte) 0x00;
      ibuf[17] = (byte) 0x00;
      ibuf[18] = (byte) 0x00;
      ibuf[19] = (byte) 0x02;
      ibuf[20] = (byte) 0x00;
      ibuf[21] = (byte) 0x00;
      ibuf[22] = (byte) 0x00;
      ibuf[23] = (byte) 0x03;
      ibuf[24] = (byte) 0x00;
      ibuf[25] = (byte) 0x00;
      ibuf[26] = (byte) 0x00;
      ibuf[27] = (byte) 0x00;
      ibuf[28] = (byte) 0x00;
      ibuf[29] = (byte) 0x00;
      ibuf[30] = (byte) 0x00;
      ibuf[31] = (byte) 0x00;
      ibuf[32] = (byte) 0x00;
      ibuf[33] = (byte) 0x00;
      ibuf[34] = (byte) 0x00;
      ibuf[35] = (byte) 0x00;
      ibuf[36] = (byte) 0x00;
      ibuf[37] = (byte) 0x00;
      ibuf[38] = (byte) 0x00;
      ibuf[39] = (byte) 0x00;
      ibuf[40] = (byte) 0x00;
      ibuf[41] = (byte) 0x01;
      ibuf[42] = (byte) 0x86;
      ibuf[43] = (byte) 0xa5;
      ibuf[44] = (byte) 0x00;
      ibuf[45] = (byte) 0x00;
      ibuf[46] = (byte) 0x00;
      ibuf[47] = (byte) 0x01;
      ibuf[48] = (byte) 0x00;
      ibuf[49] = (byte) 0x00;
      ibuf[50] = (byte) 0x00;
      ibuf[51] = (byte) 0x06;
      ibuf[52] = (byte) 0x00;
      ibuf[53] = (byte) 0x00;
      ibuf[54] = (byte) 0x00;
      ibuf[55] = (byte) 0x00;

      try
        {
          iaddr =
            InetAddress.getByName(
              Constants.LOCAL_LOOP_IP_ADDRESS );
        }
      catch( UnknownHostException e )
        {
          System.out.println( e.getMessage() );
        }
    /*end of try*/

      iport = 759;

      rpcMessageUDPPacket = new
        DatagramPacket( ibuf, ilength,
                        iaddr, iport   );

      rpcMessage = new
        Message( rpcMessageUDPPacket );

      System.out.print( rpcMessage.toString() );

      result = rpcMessage.getUnsignedInteger();

      System.out.println( "first uint=" + result );

      System.out.print( "\nyet unparsed: " +
                        rpcMessage.unparsedDataToString() );

      System.exit( 0 );

    }
/*end of main*/


} /* end of Message class */

/*****************************************************************************/
/* End of file: Message.java                                                 */
/*****************************************************************************/
